e498c162f11d3114823e5ba17cafaca8dde175aa
[metze/samba/wip.git] / source3 / torture / torture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-1998
5    Copyright (C) Jeremy Allison 2009
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/shmem.h"
23 #include "libsmb/namequery.h"
24 #include "wbc_async.h"
25 #include "torture/proto.h"
26 #include "libcli/security/security.h"
27 #include "tldap.h"
28 #include "tldap_util.h"
29 #include "tldap_gensec_bind.h"
30 #include "../librpc/gen_ndr/svcctl.h"
31 #include "../lib/util/memcache.h"
32 #include "nsswitch/winbind_client.h"
33 #include "dbwrap/dbwrap.h"
34 #include "dbwrap/dbwrap_open.h"
35 #include "dbwrap/dbwrap_rbt.h"
36 #include "async_smb.h"
37 #include "libsmb/libsmb.h"
38 #include "libsmb/clirap.h"
39 #include "trans2.h"
40 #include "libsmb/nmblib.h"
41 #include "../lib/util/tevent_ntstatus.h"
42 #include "util_tdb.h"
43 #include "../libcli/smb/read_smb.h"
44 #include "../libcli/smb/smbXcli_base.h"
45 #include "lib/util/sys_rw_data.h"
46 #include "lib/util/base64.h"
47 #include "lib/util/time.h"
48 #include "lib/gencache.h"
49 #include "lib/util/sys_rw.h"
50 #include "lib/util/asn1.h"
51 #include "lib/param/param.h"
52 #include "auth/gensec/gensec.h"
53
54 #include <gnutls/gnutls.h>
55 #include <gnutls/crypto.h>
56
57 extern char *optarg;
58 extern int optind;
59
60 fstring host, workgroup, share, password, username, myname;
61 struct cli_credentials *torture_creds;
62 static const char *sockops="TCP_NODELAY";
63 int torture_nprocs=1;
64 static int port_to_use=0;
65 int torture_numops=100;
66 int torture_blocksize=1024*1024;
67 static int procnum; /* records process count number when forking */
68 static struct cli_state *current_cli;
69 static fstring randomfname;
70 static bool use_oplocks;
71 static bool use_level_II_oplocks;
72 static const char *client_txt = "client_oplocks.txt";
73 static bool disable_spnego;
74 static bool use_kerberos;
75 static bool force_dos_errors;
76 static fstring multishare_conn_fname;
77 static bool use_multishare_conn = False;
78 static bool do_encrypt;
79 static const char *local_path = NULL;
80 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
81 char *test_filename;
82
83 bool torture_showall = False;
84
85 static double create_procs(bool (*fn)(int), bool *result);
86
87 /********************************************************************
88  Ensure a connection is encrypted.
89 ********************************************************************/
90
91 static bool force_cli_encryption(struct cli_state *c,
92                         const char *sharename)
93 {
94         uint16_t major, minor;
95         uint32_t caplow, caphigh;
96         NTSTATUS status;
97
98         if (!SERVER_HAS_UNIX_CIFS(c)) {
99                 d_printf("Encryption required and "
100                         "server that doesn't support "
101                         "UNIX extensions - failing connect\n");
102                         return false;
103         }
104
105         status = cli_unix_extensions_version(c, &major, &minor, &caplow,
106                                              &caphigh);
107         if (!NT_STATUS_IS_OK(status)) {
108                 d_printf("Encryption required and "
109                         "can't get UNIX CIFS extensions "
110                         "version from server: %s\n", nt_errstr(status));
111                 return false;
112         }
113
114         if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
115                 d_printf("Encryption required and "
116                         "share %s doesn't support "
117                         "encryption.\n", sharename);
118                 return false;
119         }
120
121         status = cli_smb1_setup_encryption(c, torture_creds);
122         if (!NT_STATUS_IS_OK(status)) {
123                 d_printf("Encryption required and "
124                         "setup failed with error %s.\n",
125                         nt_errstr(status));
126                 return false;
127         }
128
129         return true;
130 }
131
132
133 static struct cli_state *open_nbt_connection(void)
134 {
135         struct cli_state *c;
136         NTSTATUS status;
137         int flags = 0;
138
139         if (disable_spnego) {
140                 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
141         }
142
143         if (use_oplocks) {
144                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
145         }
146
147         if (use_level_II_oplocks) {
148                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
149         }
150
151         if (use_kerberos) {
152                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
153         }
154
155         if (force_dos_errors) {
156                 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
157         }
158
159         status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
160                                 signing_state, flags, &c);
161         if (!NT_STATUS_IS_OK(status)) {
162                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
163                 return NULL;
164         }
165
166         cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
167
168         return c;
169 }
170
171 /****************************************************************************
172  Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
173 ****************************************************************************/
174
175 static bool cli_bad_session_request(int fd,
176                          struct nmb_name *calling, struct nmb_name *called)
177 {
178         TALLOC_CTX *frame;
179         uint8_t len_buf[4];
180         struct iovec iov[3];
181         ssize_t len;
182         uint8_t *inbuf;
183         int err;
184         bool ret = false;
185         uint8_t message_type;
186         uint8_t error;
187         struct tevent_context *ev;
188         struct tevent_req *req;
189
190         frame = talloc_stackframe();
191
192         iov[0].iov_base = len_buf;
193         iov[0].iov_len  = sizeof(len_buf);
194
195         /* put in the destination name */
196
197         iov[1].iov_base = name_mangle(talloc_tos(), called->name,
198                                       called->name_type);
199         if (iov[1].iov_base == NULL) {
200                 goto fail;
201         }
202         iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
203                                   talloc_get_size(iov[1].iov_base));
204
205         /* and my name */
206
207         iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
208                                       calling->name_type);
209         if (iov[2].iov_base == NULL) {
210                 goto fail;
211         }
212         iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
213                                   talloc_get_size(iov[2].iov_base));
214
215         /* Deliberately corrupt the name len (first byte) */
216         *((uint8_t *)iov[2].iov_base) = 100;
217
218         /* send a session request (RFC 1002) */
219         /* setup the packet length
220          * Remove four bytes from the length count, since the length
221          * field in the NBT Session Service header counts the number
222          * of bytes which follow.  The cli_send_smb() function knows
223          * about this and accounts for those four bytes.
224          * CRH.
225          */
226
227         _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
228         SCVAL(len_buf,0,0x81);
229
230         len = write_data_iov(fd, iov, 3);
231         if (len == -1) {
232                 goto fail;
233         }
234
235         ev = samba_tevent_context_init(frame);
236         if (ev == NULL) {
237                 goto fail;
238         }
239         req = read_smb_send(frame, ev, fd);
240         if (req == NULL) {
241                 goto fail;
242         }
243         if (!tevent_req_poll(req, ev)) {
244                 goto fail;
245         }
246         len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
247         if (len == -1) {
248                 errno = err;
249                 goto fail;
250         }
251         TALLOC_FREE(ev);
252
253         message_type = CVAL(inbuf, 0);
254         if (message_type != 0x83) {
255                 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
256                           message_type);
257                 goto fail;
258         }
259
260         if (smb_len(inbuf) != 1) {
261                 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
262                           (int)smb_len(inbuf));
263                 goto fail;
264         }
265
266         error = CVAL(inbuf, 4);
267         if (error !=  0x82) {
268                 d_fprintf(stderr, "Expected error 0x82, got %d\n",
269                           (int)error);
270                 goto fail;
271         }
272
273         ret = true;
274 fail:
275         TALLOC_FREE(frame);
276         return ret;
277 }
278
279 /* Insert a NULL at the first separator of the given path and return a pointer
280  * to the remainder of the string.
281  */
282 static char *
283 terminate_path_at_separator(char * path)
284 {
285         char * p;
286
287         if (!path) {
288                 return NULL;
289         }
290
291         if ((p = strchr_m(path, '/'))) {
292                 *p = '\0';
293                 return p + 1;
294         }
295
296         if ((p = strchr_m(path, '\\'))) {
297                 *p = '\0';
298                 return p + 1;
299         }
300
301         /* No separator. */
302         return NULL;
303 }
304
305 /*
306   parse a //server/share type UNC name
307 */
308 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
309                       char **hostname, char **sharename)
310 {
311         char *p;
312
313         *hostname = *sharename = NULL;
314
315         if (strncmp(unc_name, "\\\\", 2) &&
316             strncmp(unc_name, "//", 2)) {
317                 return False;
318         }
319
320         *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
321         p = terminate_path_at_separator(*hostname);
322
323         if (p && *p) {
324                 *sharename = talloc_strdup(mem_ctx, p);
325                 terminate_path_at_separator(*sharename);
326         }
327
328         if (*hostname && *sharename) {
329                 return True;
330         }
331
332         TALLOC_FREE(*hostname);
333         TALLOC_FREE(*sharename);
334         return False;
335 }
336
337 static bool torture_open_connection_share(struct cli_state **c,
338                                    const char *hostname, 
339                                    const char *sharename,
340                                    int flags)
341 {
342         NTSTATUS status;
343
344         status = cli_full_connection_creds(c,
345                                            myname,
346                                            hostname,
347                                            NULL, /* dest_ss */
348                                            port_to_use,
349                                            sharename,
350                                            "?????",
351                                            torture_creds,
352                                            flags,
353                                            signing_state);
354         if (!NT_STATUS_IS_OK(status)) {
355                 printf("failed to open share connection: //%s/%s port:%d - %s\n",
356                         hostname, sharename, port_to_use, nt_errstr(status));
357                 return False;
358         }
359
360         cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
361
362         if (do_encrypt) {
363                 return force_cli_encryption(*c,
364                                         sharename);
365         }
366         return True;
367 }
368
369 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
370 {
371         char **unc_list = NULL;
372         int num_unc_names = 0;
373         bool result;
374
375         if (use_multishare_conn==True) {
376                 char *h, *s;
377                 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
378                 if (!unc_list || num_unc_names <= 0) {
379                         printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
380                         exit(1);
381                 }
382
383                 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
384                                       NULL, &h, &s)) {
385                         printf("Failed to parse UNC name %s\n",
386                                unc_list[conn_index % num_unc_names]);
387                         TALLOC_FREE(unc_list);
388                         exit(1);
389                 }
390
391                 result = torture_open_connection_share(c, h, s, flags);
392
393                 /* h, s were copied earlier */
394                 TALLOC_FREE(unc_list);
395                 return result;
396         }
397
398         return torture_open_connection_share(c, host, share, flags);
399 }
400
401 bool torture_open_connection(struct cli_state **c, int conn_index)
402 {
403         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
404
405         if (use_oplocks) {
406                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
407         }
408         if (use_level_II_oplocks) {
409                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
410         }
411
412         return torture_open_connection_flags(c, conn_index, flags);
413 }
414
415 bool torture_init_connection(struct cli_state **pcli)
416 {
417         struct cli_state *cli;
418
419         cli = open_nbt_connection();
420         if (cli == NULL) {
421                 return false;
422         }
423
424         *pcli = cli;
425         return true;
426 }
427
428 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
429 {
430         uint16_t old_vuid = cli_state_get_uid(cli);
431         NTSTATUS status;
432         bool ret;
433
434         cli_state_set_uid(cli, 0);
435         status = cli_session_setup_creds(cli, torture_creds);
436         ret = NT_STATUS_IS_OK(status);
437         *new_vuid = cli_state_get_uid(cli);
438         cli_state_set_uid(cli, old_vuid);
439         return ret;
440 }
441
442
443 bool torture_close_connection(struct cli_state *c)
444 {
445         bool ret = True;
446         NTSTATUS status;
447
448         status = cli_tdis(c);
449         if (!NT_STATUS_IS_OK(status)) {
450                 printf("tdis failed (%s)\n", nt_errstr(status));
451                 ret = False;
452         }
453
454         cli_shutdown(c);
455
456         return ret;
457 }
458
459
460 /* check if the server produced the expected dos or nt error code */
461 static bool check_both_error(int line, NTSTATUS status,
462                              uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
463 {
464         if (NT_STATUS_IS_DOS(status)) {
465                 uint8_t cclass;
466                 uint32_t num;
467
468                 /* Check DOS error */
469                 cclass = NT_STATUS_DOS_CLASS(status);
470                 num = NT_STATUS_DOS_CODE(status);
471
472                 if (eclass != cclass || ecode != num) {
473                         printf("unexpected error code class=%d code=%d\n",
474                                (int)cclass, (int)num);
475                         printf(" expected %d/%d %s (line=%d)\n",
476                                (int)eclass, (int)ecode, nt_errstr(nterr), line);
477                         return false;
478                 }
479         } else {
480                 /* Check NT error */
481                 if (!NT_STATUS_EQUAL(nterr, status)) {
482                         printf("unexpected error code %s\n",
483                                 nt_errstr(status));
484                         printf(" expected %s (line=%d)\n",
485                                 nt_errstr(nterr), line);
486                         return false;
487                 }
488         }
489
490         return true;
491 }
492
493
494 /* check if the server produced the expected error code */
495 static bool check_error(int line, NTSTATUS status,
496                         uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
497 {
498         if (NT_STATUS_IS_DOS(status)) {
499                 uint8_t cclass;
500                 uint32_t num;
501
502                 /* Check DOS error */
503
504                 cclass = NT_STATUS_DOS_CLASS(status);
505                 num = NT_STATUS_DOS_CODE(status);
506
507                 if (eclass != cclass || ecode != num) {
508                         printf("unexpected error code class=%d code=%d\n", 
509                                (int)cclass, (int)num);
510                         printf(" expected %d/%d %s (line=%d)\n", 
511                                (int)eclass, (int)ecode, nt_errstr(nterr),
512                                line);
513                         return False;
514                 }
515
516         } else {
517                 /* Check NT error */
518
519                 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
520                         printf("unexpected error code %s\n",
521                                nt_errstr(status));
522                         printf(" expected %s (line=%d)\n", nt_errstr(nterr),
523                                line);
524                         return False;
525                 }
526         }
527
528         return True;
529 }
530
531
532 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
533 {
534         NTSTATUS status;
535
536         status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
537
538         while (!NT_STATUS_IS_OK(status)) {
539                 if (!check_both_error(__LINE__, status, ERRDOS,
540                                       ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
541                         return false;
542                 }
543
544                 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
545         }
546
547         return true;
548 }
549
550
551 static bool rw_torture(struct cli_state *c)
552 {
553         const char *lockfname = "\\torture.lck";
554         fstring fname;
555         uint16_t fnum;
556         uint16_t fnum2;
557         pid_t pid2, pid = getpid();
558         int i, j;
559         char buf[1024];
560         bool correct = True;
561         size_t nread = 0;
562         NTSTATUS status;
563
564         memset(buf, '\0', sizeof(buf));
565
566         status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
567                          DENY_NONE, &fnum2);
568         if (!NT_STATUS_IS_OK(status)) {
569                 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
570         }
571         if (!NT_STATUS_IS_OK(status)) {
572                 printf("open of %s failed (%s)\n",
573                        lockfname, nt_errstr(status));
574                 return False;
575         }
576
577         for (i=0;i<torture_numops;i++) {
578                 unsigned n = (unsigned)sys_random()%10;
579
580                 if (i % 10 == 0) {
581                         printf("%d\r", i); fflush(stdout);
582                 }
583                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
584
585                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
586                         return False;
587                 }
588
589                 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
590                                   DENY_ALL, &fnum);
591                 if (!NT_STATUS_IS_OK(status)) {
592                         printf("open failed (%s)\n", nt_errstr(status));
593                         correct = False;
594                         break;
595                 }
596
597                 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
598                                       sizeof(pid), NULL);
599                 if (!NT_STATUS_IS_OK(status)) {
600                         printf("write failed (%s)\n", nt_errstr(status));
601                         correct = False;
602                 }
603
604                 for (j=0;j<50;j++) {
605                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
606                                               sizeof(pid)+(j*sizeof(buf)),
607                                               sizeof(buf), NULL);
608                         if (!NT_STATUS_IS_OK(status)) {
609                                 printf("write failed (%s)\n",
610                                        nt_errstr(status));
611                                 correct = False;
612                         }
613                 }
614
615                 pid2 = 0;
616
617                 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
618                                   &nread);
619                 if (!NT_STATUS_IS_OK(status)) {
620                         printf("read failed (%s)\n", nt_errstr(status));
621                         correct = false;
622                 } else if (nread != sizeof(pid)) {
623                         printf("read/write compare failed: "
624                                "recv %ld req %ld\n", (unsigned long)nread,
625                                (unsigned long)sizeof(pid));
626                         correct = false;
627                 }
628
629                 if (pid2 != pid) {
630                         printf("data corruption!\n");
631                         correct = False;
632                 }
633
634                 status = cli_close(c, fnum);
635                 if (!NT_STATUS_IS_OK(status)) {
636                         printf("close failed (%s)\n", nt_errstr(status));
637                         correct = False;
638                 }
639
640                 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
641                 if (!NT_STATUS_IS_OK(status)) {
642                         printf("unlink failed (%s)\n", nt_errstr(status));
643                         correct = False;
644                 }
645
646                 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
647                 if (!NT_STATUS_IS_OK(status)) {
648                         printf("unlock failed (%s)\n", nt_errstr(status));
649                         correct = False;
650                 }
651         }
652
653         cli_close(c, fnum2);
654         cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
655
656         printf("%d\n", i);
657
658         return correct;
659 }
660
661 static bool run_torture(int dummy)
662 {
663         struct cli_state *cli;
664         bool ret;
665
666         cli = current_cli;
667
668         smbXcli_conn_set_sockopt(cli->conn, sockops);
669
670         ret = rw_torture(cli);
671
672         if (!torture_close_connection(cli)) {
673                 ret = False;
674         }
675
676         return ret;
677 }
678
679 static bool rw_torture3(struct cli_state *c, char *lockfname)
680 {
681         uint16_t fnum = (uint16_t)-1;
682         unsigned int i = 0;
683         char buf[131072];
684         char buf_rd[131072];
685         unsigned count;
686         unsigned countprev = 0;
687         size_t sent = 0;
688         bool correct = True;
689         NTSTATUS status = NT_STATUS_OK;
690
691         srandom(1);
692         for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
693         {
694                 SIVAL(buf, i, sys_random());
695         }
696
697         if (procnum == 0)
698         {
699                 status = cli_unlink(
700                         c, lockfname,
701                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
702                 if (!NT_STATUS_IS_OK(status)) {
703                         printf("unlink failed (%s) (normal, this file should "
704                                "not exist)\n", nt_errstr(status));
705                 }
706
707                 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
708                                   DENY_NONE, &fnum);
709                 if (!NT_STATUS_IS_OK(status)) {
710                         printf("first open read/write of %s failed (%s)\n",
711                                         lockfname, nt_errstr(status));
712                         return False;
713                 }
714         }
715         else
716         {
717                 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
718                 {
719                         status = cli_openx(c, lockfname, O_RDONLY, 
720                                          DENY_NONE, &fnum);
721                         if (NT_STATUS_IS_OK(status)) {
722                                 break;
723                         }
724                         smb_msleep(10);
725                 }
726                 if (!NT_STATUS_IS_OK(status)) {
727                         printf("second open read-only of %s failed (%s)\n",
728                                         lockfname, nt_errstr(status));
729                         return False;
730                 }
731         }
732
733         i = 0;
734         for (count = 0; count < sizeof(buf); count += sent)
735         {
736                 if (count >= countprev) {
737                         printf("%d %8d\r", i, count);
738                         fflush(stdout);
739                         i++;
740                         countprev += (sizeof(buf) / 20);
741                 }
742
743                 if (procnum == 0)
744                 {
745                         sent = ((unsigned)sys_random()%(20))+ 1;
746                         if (sent > sizeof(buf) - count)
747                         {
748                                 sent = sizeof(buf) - count;
749                         }
750
751                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
752                                               count, sent, NULL);
753                         if (!NT_STATUS_IS_OK(status)) {
754                                 printf("write failed (%s)\n",
755                                        nt_errstr(status));
756                                 correct = False;
757                         }
758                 }
759                 else
760                 {
761                         status = cli_read(c, fnum, buf_rd+count, count,
762                                           sizeof(buf)-count, &sent);
763                         if(!NT_STATUS_IS_OK(status)) {
764                                 printf("read failed offset:%d size:%ld (%s)\n",
765                                        count, (unsigned long)sizeof(buf)-count,
766                                        nt_errstr(status));
767                                 correct = False;
768                                 sent = 0;
769                         } else if (sent > 0) {
770                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
771                                 {
772                                         printf("read/write compare failed\n");
773                                         printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
774                                         correct = False;
775                                         break;
776                                 }
777                         }
778                 }
779
780         }
781
782         status = cli_close(c, fnum);
783         if (!NT_STATUS_IS_OK(status)) {
784                 printf("close failed (%s)\n", nt_errstr(status));
785                 correct = False;
786         }
787
788         return correct;
789 }
790
791 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
792 {
793         const char *lockfname = "\\torture2.lck";
794         uint16_t fnum1;
795         uint16_t fnum2;
796         int i;
797         char buf[131072];
798         char buf_rd[131072];
799         bool correct = True;
800         size_t bytes_read;
801         NTSTATUS status;
802
803         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
804         if (!NT_STATUS_IS_OK(status)) {
805                 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
806         }
807
808         status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
809                           DENY_NONE, &fnum1);
810         if (!NT_STATUS_IS_OK(status)) {
811                 printf("first open read/write of %s failed (%s)\n",
812                                 lockfname, nt_errstr(status));
813                 return False;
814         }
815
816         status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
817         if (!NT_STATUS_IS_OK(status)) {
818                 printf("second open read-only of %s failed (%s)\n",
819                                 lockfname, nt_errstr(status));
820                 cli_close(c1, fnum1);
821                 return False;
822         }
823
824         for (i = 0; i < torture_numops; i++)
825         {
826                 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
827                 if (i % 10 == 0) {
828                         printf("%d\r", i); fflush(stdout);
829                 }
830
831                 generate_random_buffer((unsigned char *)buf, buf_size);
832
833                 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
834                                       buf_size, NULL);
835                 if (!NT_STATUS_IS_OK(status)) {
836                         printf("write failed (%s)\n", nt_errstr(status));
837                         correct = False;
838                         break;
839                 }
840
841                 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
842                 if(!NT_STATUS_IS_OK(status)) {
843                         printf("read failed (%s)\n", nt_errstr(status));
844                         correct = false;
845                         break;
846                 } else if (bytes_read != buf_size) {
847                         printf("read failed\n");
848                         printf("read %ld, expected %ld\n",
849                                (unsigned long)bytes_read,
850                                (unsigned long)buf_size); 
851                         correct = False;
852                         break;
853                 }
854
855                 if (memcmp(buf_rd, buf, buf_size) != 0)
856                 {
857                         printf("read/write compare failed\n");
858                         correct = False;
859                         break;
860                 }
861         }
862
863         status = cli_close(c2, fnum2);
864         if (!NT_STATUS_IS_OK(status)) {
865                 printf("close failed (%s)\n", nt_errstr(status));
866                 correct = False;
867         }
868
869         status = cli_close(c1, fnum1);
870         if (!NT_STATUS_IS_OK(status)) {
871                 printf("close failed (%s)\n", nt_errstr(status));
872                 correct = False;
873         }
874
875         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
876         if (!NT_STATUS_IS_OK(status)) {
877                 printf("unlink failed (%s)\n", nt_errstr(status));
878                 correct = False;
879         }
880
881         return correct;
882 }
883
884 static bool run_readwritetest(int dummy)
885 {
886         struct cli_state *cli1, *cli2;
887         bool test1, test2 = False;
888
889         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
890                 return False;
891         }
892         smbXcli_conn_set_sockopt(cli1->conn, sockops);
893         smbXcli_conn_set_sockopt(cli2->conn, sockops);
894
895         printf("starting readwritetest\n");
896
897         test1 = rw_torture2(cli1, cli2);
898         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
899
900         if (test1) {
901                 test2 = rw_torture2(cli1, cli1);
902                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
903         }
904
905         if (!torture_close_connection(cli1)) {
906                 test1 = False;
907         }
908
909         if (!torture_close_connection(cli2)) {
910                 test2 = False;
911         }
912
913         return (test1 && test2);
914 }
915
916 static bool run_readwritemulti(int dummy)
917 {
918         struct cli_state *cli;
919         bool test;
920
921         cli = current_cli;
922
923         smbXcli_conn_set_sockopt(cli->conn, sockops);
924
925         printf("run_readwritemulti: fname %s\n", randomfname);
926         test = rw_torture3(cli, randomfname);
927
928         if (!torture_close_connection(cli)) {
929                 test = False;
930         }
931
932         return test;
933 }
934
935 static bool run_readwritelarge_internal(void)
936 {
937         static struct cli_state *cli1;
938         uint16_t fnum1;
939         const char *lockfname = "\\large.dat";
940         off_t fsize;
941         char buf[126*1024];
942         bool correct = True;
943         NTSTATUS status;
944
945         if (!torture_open_connection(&cli1, 0)) {
946                 return False;
947         }
948         smbXcli_conn_set_sockopt(cli1->conn, sockops);
949         memset(buf,'\0',sizeof(buf));
950
951         printf("starting readwritelarge_internal\n");
952
953         cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
954
955         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
956                           DENY_NONE, &fnum1);
957         if (!NT_STATUS_IS_OK(status)) {
958                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
959                 return False;
960         }
961
962         cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
963
964         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
965                                      NULL, NULL, NULL);
966         if (!NT_STATUS_IS_OK(status)) {
967                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
968                 correct = False;
969         }
970
971         if (fsize == sizeof(buf))
972                 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
973                        (unsigned long)fsize);
974         else {
975                 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
976                        (unsigned long)fsize);
977                 correct = False;
978         }
979
980         status = cli_close(cli1, fnum1);
981         if (!NT_STATUS_IS_OK(status)) {
982                 printf("close failed (%s)\n", nt_errstr(status));
983                 correct = False;
984         }
985
986         status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
987         if (!NT_STATUS_IS_OK(status)) {
988                 printf("unlink failed (%s)\n", nt_errstr(status));
989                 correct = False;
990         }
991
992         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
993                           DENY_NONE, &fnum1);
994         if (!NT_STATUS_IS_OK(status)) {
995                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
996                 return False;
997         }
998
999         cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1000
1001         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1002                                      NULL, NULL, NULL);
1003         if (!NT_STATUS_IS_OK(status)) {
1004                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1005                 correct = False;
1006         }
1007
1008         if (fsize == sizeof(buf))
1009                 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1010                        (unsigned long)fsize);
1011         else {
1012                 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1013                        (unsigned long)fsize);
1014                 correct = False;
1015         }
1016
1017 #if 0
1018         /* ToDo - set allocation. JRA */
1019         if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1020                 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1021                 return False;
1022         }
1023         if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1024                                  NULL, NULL)) {
1025                 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1026                 correct = False;
1027         }
1028         if (fsize != 0)
1029                 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1030 #endif
1031
1032         status = cli_close(cli1, fnum1);
1033         if (!NT_STATUS_IS_OK(status)) {
1034                 printf("close failed (%s)\n", nt_errstr(status));
1035                 correct = False;
1036         }
1037
1038         if (!torture_close_connection(cli1)) {
1039                 correct = False;
1040         }
1041         return correct;
1042 }
1043
1044 static bool run_readwritelarge(int dummy)
1045 {
1046         return run_readwritelarge_internal();
1047 }
1048
1049 static bool run_readwritelarge_signtest(int dummy)
1050 {
1051         bool ret;
1052         signing_state = SMB_SIGNING_REQUIRED;
1053         ret = run_readwritelarge_internal();
1054         signing_state = SMB_SIGNING_DEFAULT;
1055         return ret;
1056 }
1057
1058 int line_count = 0;
1059 int nbio_id;
1060
1061 #define ival(s) strtol(s, NULL, 0)
1062
1063 /* run a test that simulates an approximate netbench client load */
1064 static bool run_netbench(int client)
1065 {
1066         struct cli_state *cli;
1067         int i;
1068         char line[1024];
1069         char cname[20];
1070         FILE *f;
1071         const char *params[20];
1072         bool correct = True;
1073
1074         cli = current_cli;
1075
1076         nbio_id = client;
1077
1078         smbXcli_conn_set_sockopt(cli->conn, sockops);
1079
1080         nb_setup(cli);
1081
1082         slprintf(cname,sizeof(cname)-1, "client%d", client);
1083
1084         f = fopen(client_txt, "r");
1085
1086         if (!f) {
1087                 perror(client_txt);
1088                 return False;
1089         }
1090
1091         while (fgets(line, sizeof(line)-1, f)) {
1092                 char *saveptr;
1093                 line_count++;
1094
1095                 line[strlen(line)-1] = 0;
1096
1097                 /* printf("[%d] %s\n", line_count, line); */
1098
1099                 all_string_sub(line,"client1", cname, sizeof(line));
1100
1101                 /* parse the command parameters */
1102                 params[0] = strtok_r(line, " ", &saveptr);
1103                 i = 0;
1104                 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1105
1106                 params[i] = "";
1107
1108                 if (i < 2) continue;
1109
1110                 if (!strncmp(params[0],"SMB", 3)) {
1111                         printf("ERROR: You are using a dbench 1 load file\n");
1112                         exit(1);
1113                 }
1114
1115                 if (!strcmp(params[0],"NTCreateX")) {
1116                         nb_createx(params[1], ival(params[2]), ival(params[3]), 
1117                                    ival(params[4]));
1118                 } else if (!strcmp(params[0],"Close")) {
1119                         nb_close(ival(params[1]));
1120                 } else if (!strcmp(params[0],"Rename")) {
1121                         nb_rename(params[1], params[2]);
1122                 } else if (!strcmp(params[0],"Unlink")) {
1123                         nb_unlink(params[1]);
1124                 } else if (!strcmp(params[0],"Deltree")) {
1125                         nb_deltree(params[1]);
1126                 } else if (!strcmp(params[0],"Rmdir")) {
1127                         nb_rmdir(params[1]);
1128                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1129                         nb_qpathinfo(params[1]);
1130                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1131                         nb_qfileinfo(ival(params[1]));
1132                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1133                         nb_qfsinfo(ival(params[1]));
1134                 } else if (!strcmp(params[0],"FIND_FIRST")) {
1135                         nb_findfirst(params[1]);
1136                 } else if (!strcmp(params[0],"WriteX")) {
1137                         nb_writex(ival(params[1]), 
1138                                   ival(params[2]), ival(params[3]), ival(params[4]));
1139                 } else if (!strcmp(params[0],"ReadX")) {
1140                         nb_readx(ival(params[1]), 
1141                                   ival(params[2]), ival(params[3]), ival(params[4]));
1142                 } else if (!strcmp(params[0],"Flush")) {
1143                         nb_flush(ival(params[1]));
1144                 } else {
1145                         printf("Unknown operation %s\n", params[0]);
1146                         exit(1);
1147                 }
1148         }
1149         fclose(f);
1150
1151         nb_cleanup();
1152
1153         if (!torture_close_connection(cli)) {
1154                 correct = False;
1155         }
1156
1157         return correct;
1158 }
1159
1160
1161 /* run a test that simulates an approximate netbench client load */
1162 static bool run_nbench(int dummy)
1163 {
1164         double t;
1165         bool correct = True;
1166
1167         nbio_shmem(torture_nprocs);
1168
1169         nbio_id = -1;
1170
1171         signal(SIGALRM, nb_alarm);
1172         alarm(1);
1173         t = create_procs(run_netbench, &correct);
1174         alarm(0);
1175
1176         printf("\nThroughput %g MB/sec\n", 
1177                1.0e-6 * nbio_total() / t);
1178         return correct;
1179 }
1180
1181
1182 /*
1183   This test checks for two things:
1184
1185   1) correct support for retaining locks over a close (ie. the server
1186      must not use posix semantics)
1187   2) support for lock timeouts
1188  */
1189 static bool run_locktest1(int dummy)
1190 {
1191         struct cli_state *cli1, *cli2;
1192         const char *fname = "\\lockt1.lck";
1193         uint16_t fnum1, fnum2, fnum3;
1194         time_t t1, t2;
1195         unsigned lock_timeout;
1196         NTSTATUS status;
1197
1198         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1199                 return False;
1200         }
1201         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1202         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1203
1204         printf("starting locktest1\n");
1205
1206         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1207
1208         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1209                           &fnum1);
1210         if (!NT_STATUS_IS_OK(status)) {
1211                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1212                 return False;
1213         }
1214
1215         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1216         if (!NT_STATUS_IS_OK(status)) {
1217                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1218                 return False;
1219         }
1220
1221         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1222         if (!NT_STATUS_IS_OK(status)) {
1223                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1224                 return False;
1225         }
1226
1227         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1228         if (!NT_STATUS_IS_OK(status)) {
1229                 printf("lock1 failed (%s)\n", nt_errstr(status));
1230                 return false;
1231         }
1232
1233         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1234         if (NT_STATUS_IS_OK(status)) {
1235                 printf("lock2 succeeded! This is a locking bug\n");
1236                 return false;
1237         } else {
1238                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1239                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1240                         return false;
1241                 }
1242         }
1243
1244         lock_timeout = (1 + (random() % 20));
1245         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1246         t1 = time(NULL);
1247         status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1248         if (NT_STATUS_IS_OK(status)) {
1249                 printf("lock3 succeeded! This is a locking bug\n");
1250                 return false;
1251         } else {
1252                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1253                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1254                         return false;
1255                 }
1256         }
1257         t2 = time(NULL);
1258
1259         if (ABS(t2 - t1) < lock_timeout-1) {
1260                 printf("error: This server appears not to support timed lock requests\n");
1261         }
1262
1263         printf("server slept for %u seconds for a %u second timeout\n",
1264                (unsigned int)(t2-t1), lock_timeout);
1265
1266         status = cli_close(cli1, fnum2);
1267         if (!NT_STATUS_IS_OK(status)) {
1268                 printf("close1 failed (%s)\n", nt_errstr(status));
1269                 return False;
1270         }
1271
1272         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1273         if (NT_STATUS_IS_OK(status)) {
1274                 printf("lock4 succeeded! This is a locking bug\n");
1275                 return false;
1276         } else {
1277                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1278                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1279                         return false;
1280                 }
1281         }
1282
1283         status = cli_close(cli1, fnum1);
1284         if (!NT_STATUS_IS_OK(status)) {
1285                 printf("close2 failed (%s)\n", nt_errstr(status));
1286                 return False;
1287         }
1288
1289         status = cli_close(cli2, fnum3);
1290         if (!NT_STATUS_IS_OK(status)) {
1291                 printf("close3 failed (%s)\n", nt_errstr(status));
1292                 return False;
1293         }
1294
1295         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1296         if (!NT_STATUS_IS_OK(status)) {
1297                 printf("unlink failed (%s)\n", nt_errstr(status));
1298                 return False;
1299         }
1300
1301
1302         if (!torture_close_connection(cli1)) {
1303                 return False;
1304         }
1305
1306         if (!torture_close_connection(cli2)) {
1307                 return False;
1308         }
1309
1310         printf("Passed locktest1\n");
1311         return True;
1312 }
1313
1314 /*
1315   this checks to see if a secondary tconx can use open files from an
1316   earlier tconx
1317  */
1318 static bool run_tcon_test(int dummy)
1319 {
1320         static struct cli_state *cli;
1321         const char *fname = "\\tcontest.tmp";
1322         uint16_t fnum1;
1323         uint32_t cnum1, cnum2, cnum3;
1324         struct smbXcli_tcon *orig_tcon = NULL;
1325         uint16_t vuid1, vuid2;
1326         char buf[4];
1327         bool ret = True;
1328         NTSTATUS status;
1329
1330         memset(buf, '\0', sizeof(buf));
1331
1332         if (!torture_open_connection(&cli, 0)) {
1333                 return False;
1334         }
1335         smbXcli_conn_set_sockopt(cli->conn, sockops);
1336
1337         printf("starting tcontest\n");
1338
1339         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1340
1341         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1342         if (!NT_STATUS_IS_OK(status)) {
1343                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1344                 return False;
1345         }
1346
1347         cnum1 = cli_state_get_tid(cli);
1348         vuid1 = cli_state_get_uid(cli);
1349
1350         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1351         if (!NT_STATUS_IS_OK(status)) {
1352                 printf("initial write failed (%s)", nt_errstr(status));
1353                 return False;
1354         }
1355
1356         orig_tcon = cli_state_save_tcon(cli);
1357         if (orig_tcon == NULL) {
1358                 return false;
1359         }
1360
1361         status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1362         if (!NT_STATUS_IS_OK(status)) {
1363                 printf("%s refused 2nd tree connect (%s)\n", host,
1364                        nt_errstr(status));
1365                 cli_shutdown(cli);
1366                 return False;
1367         }
1368
1369         cnum2 = cli_state_get_tid(cli);
1370         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1371         vuid2 = cli_state_get_uid(cli) + 1;
1372
1373         /* try a write with the wrong tid */
1374         cli_state_set_tid(cli, cnum2);
1375
1376         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1377         if (NT_STATUS_IS_OK(status)) {
1378                 printf("* server allows write with wrong TID\n");
1379                 ret = False;
1380         } else {
1381                 printf("server fails write with wrong TID : %s\n",
1382                        nt_errstr(status));
1383         }
1384
1385
1386         /* try a write with an invalid tid */
1387         cli_state_set_tid(cli, cnum3);
1388
1389         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1390         if (NT_STATUS_IS_OK(status)) {
1391                 printf("* server allows write with invalid TID\n");
1392                 ret = False;
1393         } else {
1394                 printf("server fails write with invalid TID : %s\n",
1395                        nt_errstr(status));
1396         }
1397
1398         /* try a write with an invalid vuid */
1399         cli_state_set_uid(cli, vuid2);
1400         cli_state_set_tid(cli, cnum1);
1401
1402         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1403         if (NT_STATUS_IS_OK(status)) {
1404                 printf("* server allows write with invalid VUID\n");
1405                 ret = False;
1406         } else {
1407                 printf("server fails write with invalid VUID : %s\n",
1408                        nt_errstr(status));
1409         }
1410
1411         cli_state_set_tid(cli, cnum1);
1412         cli_state_set_uid(cli, vuid1);
1413
1414         status = cli_close(cli, fnum1);
1415         if (!NT_STATUS_IS_OK(status)) {
1416                 printf("close failed (%s)\n", nt_errstr(status));
1417                 return False;
1418         }
1419
1420         cli_state_set_tid(cli, cnum2);
1421
1422         status = cli_tdis(cli);
1423         if (!NT_STATUS_IS_OK(status)) {
1424                 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1425                 return False;
1426         }
1427
1428         cli_state_restore_tcon(cli, orig_tcon);
1429
1430         cli_state_set_tid(cli, cnum1);
1431
1432         if (!torture_close_connection(cli)) {
1433                 return False;
1434         }
1435
1436         return ret;
1437 }
1438
1439
1440 /*
1441  checks for old style tcon support
1442  */
1443 static bool run_tcon2_test(int dummy)
1444 {
1445         static struct cli_state *cli;
1446         uint16_t cnum, max_xmit;
1447         char *service;
1448         NTSTATUS status;
1449
1450         if (!torture_open_connection(&cli, 0)) {
1451                 return False;
1452         }
1453         smbXcli_conn_set_sockopt(cli->conn, sockops);
1454
1455         printf("starting tcon2 test\n");
1456
1457         if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1458                 return false;
1459         }
1460
1461         status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1462
1463         SAFE_FREE(service);
1464
1465         if (!NT_STATUS_IS_OK(status)) {
1466                 printf("tcon2 failed : %s\n", nt_errstr(status));
1467         } else {
1468                 printf("tcon OK : max_xmit=%d cnum=%d\n",
1469                        (int)max_xmit, (int)cnum);
1470         }
1471
1472         if (!torture_close_connection(cli)) {
1473                 return False;
1474         }
1475
1476         printf("Passed tcon2 test\n");
1477         return True;
1478 }
1479
1480 static bool tcon_devtest(struct cli_state *cli,
1481                          const char *myshare, const char *devtype,
1482                          const char *return_devtype,
1483                          NTSTATUS expected_error)
1484 {
1485         NTSTATUS status;
1486         bool ret;
1487
1488         status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1489
1490         if (NT_STATUS_IS_OK(expected_error)) {
1491                 if (NT_STATUS_IS_OK(status)) {
1492                         if (return_devtype != NULL &&
1493                             strequal(cli->dev, return_devtype)) {
1494                                 ret = True;
1495                         } else { 
1496                                 printf("tconX to share %s with type %s "
1497                                        "succeeded but returned the wrong "
1498                                        "device type (got [%s] but should have got [%s])\n",
1499                                        myshare, devtype, cli->dev, return_devtype);
1500                                 ret = False;
1501                         }
1502                 } else {
1503                         printf("tconX to share %s with type %s "
1504                                "should have succeeded but failed\n",
1505                                myshare, devtype);
1506                         ret = False;
1507                 }
1508                 cli_tdis(cli);
1509         } else {
1510                 if (NT_STATUS_IS_OK(status)) {
1511                         printf("tconx to share %s with type %s "
1512                                "should have failed but succeeded\n",
1513                                myshare, devtype);
1514                         ret = False;
1515                 } else {
1516                         if (NT_STATUS_EQUAL(status, expected_error)) {
1517                                 ret = True;
1518                         } else {
1519                                 printf("Returned unexpected error\n");
1520                                 ret = False;
1521                         }
1522                 }
1523         }
1524         return ret;
1525 }
1526
1527 /*
1528  checks for correct tconX support
1529  */
1530 static bool run_tcon_devtype_test(int dummy)
1531 {
1532         static struct cli_state *cli1 = NULL;
1533         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1534         NTSTATUS status;
1535         bool ret = True;
1536
1537         status = cli_full_connection_creds(&cli1,
1538                                            myname,
1539                                            host,
1540                                            NULL, /* dest_ss */
1541                                            port_to_use,
1542                                            NULL, /* service */
1543                                            NULL, /* service_type */
1544                                            torture_creds,
1545                                            flags,
1546                                            signing_state);
1547
1548         if (!NT_STATUS_IS_OK(status)) {
1549                 printf("could not open connection\n");
1550                 return False;
1551         }
1552
1553         if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1554                 ret = False;
1555
1556         if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1557                 ret = False;
1558
1559         if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1560                 ret = False;
1561
1562         if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1563                 ret = False;
1564
1565         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1566                 ret = False;
1567
1568         if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1569                 ret = False;
1570
1571         if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1572                 ret = False;
1573
1574         if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1575                 ret = False;
1576
1577         if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1578                 ret = False;
1579
1580         if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1581                 ret = False;
1582
1583         cli_shutdown(cli1);
1584
1585         if (ret)
1586                 printf("Passed tcondevtest\n");
1587
1588         return ret;
1589 }
1590
1591
1592 /*
1593   This test checks that 
1594
1595   1) the server supports multiple locking contexts on the one SMB
1596   connection, distinguished by PID.  
1597
1598   2) the server correctly fails overlapping locks made by the same PID (this
1599      goes against POSIX behaviour, which is why it is tricky to implement)
1600
1601   3) the server denies unlock requests by an incorrect client PID
1602 */
1603 static bool run_locktest2(int dummy)
1604 {
1605         static struct cli_state *cli;
1606         const char *fname = "\\lockt2.lck";
1607         uint16_t fnum1, fnum2, fnum3;
1608         bool correct = True;
1609         NTSTATUS status;
1610
1611         if (!torture_open_connection(&cli, 0)) {
1612                 return False;
1613         }
1614
1615         smbXcli_conn_set_sockopt(cli->conn, sockops);
1616
1617         printf("starting locktest2\n");
1618
1619         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1620
1621         cli_setpid(cli, 1);
1622
1623         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1624         if (!NT_STATUS_IS_OK(status)) {
1625                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1626                 return False;
1627         }
1628
1629         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1630         if (!NT_STATUS_IS_OK(status)) {
1631                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1632                 return False;
1633         }
1634
1635         cli_setpid(cli, 2);
1636
1637         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1638         if (!NT_STATUS_IS_OK(status)) {
1639                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1640                 return False;
1641         }
1642
1643         cli_setpid(cli, 1);
1644
1645         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1646         if (!NT_STATUS_IS_OK(status)) {
1647                 printf("lock1 failed (%s)\n", nt_errstr(status));
1648                 return false;
1649         }
1650
1651         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1652         if (NT_STATUS_IS_OK(status)) {
1653                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1654                 correct = false;
1655         } else {
1656                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1657                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1658                         return false;
1659                 }
1660         }
1661
1662         status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1663         if (NT_STATUS_IS_OK(status)) {
1664                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1665                 correct = false;
1666         } else {
1667                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1668                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1669                         return false;
1670                 }
1671         }
1672
1673         status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1674         if (NT_STATUS_IS_OK(status)) {
1675                 printf("READ lock2 succeeded! This is a locking bug\n");
1676                 correct = false;
1677         } else {
1678                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1679                                  NT_STATUS_FILE_LOCK_CONFLICT)) {
1680                         return false;
1681                 }
1682         }
1683
1684         status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1685         if (!NT_STATUS_IS_OK(status)) {
1686                 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1687         }
1688         cli_setpid(cli, 2);
1689         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1690                 printf("unlock at 100 succeeded! This is a locking bug\n");
1691                 correct = False;
1692         }
1693
1694         status = cli_unlock(cli, fnum1, 0, 4);
1695         if (NT_STATUS_IS_OK(status)) {
1696                 printf("unlock1 succeeded! This is a locking bug\n");
1697                 correct = false;
1698         } else {
1699                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1700                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1701                         return false;
1702                 }
1703         }
1704
1705         status = cli_unlock(cli, fnum1, 0, 8);
1706         if (NT_STATUS_IS_OK(status)) {
1707                 printf("unlock2 succeeded! This is a locking bug\n");
1708                 correct = false;
1709         } else {
1710                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1711                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1712                         return false;
1713                 }
1714         }
1715
1716         status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1717         if (NT_STATUS_IS_OK(status)) {
1718                 printf("lock3 succeeded! This is a locking bug\n");
1719                 correct = false;
1720         } else {
1721                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1722                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1723                         return false;
1724                 }
1725         }
1726
1727         cli_setpid(cli, 1);
1728
1729         status = cli_close(cli, fnum1);
1730         if (!NT_STATUS_IS_OK(status)) {
1731                 printf("close1 failed (%s)\n", nt_errstr(status));
1732                 return False;
1733         }
1734
1735         status = cli_close(cli, fnum2);
1736         if (!NT_STATUS_IS_OK(status)) {
1737                 printf("close2 failed (%s)\n", nt_errstr(status));
1738                 return False;
1739         }
1740
1741         status = cli_close(cli, fnum3);
1742         if (!NT_STATUS_IS_OK(status)) {
1743                 printf("close3 failed (%s)\n", nt_errstr(status));
1744                 return False;
1745         }
1746
1747         if (!torture_close_connection(cli)) {
1748                 correct = False;
1749         }
1750
1751         printf("locktest2 finished\n");
1752
1753         return correct;
1754 }
1755
1756
1757 /*
1758   This test checks that 
1759
1760   1) the server supports the full offset range in lock requests
1761 */
1762 static bool run_locktest3(int dummy)
1763 {
1764         static struct cli_state *cli1, *cli2;
1765         const char *fname = "\\lockt3.lck";
1766         uint16_t fnum1, fnum2;
1767         int i;
1768         uint32_t offset;
1769         bool correct = True;
1770         NTSTATUS status;
1771
1772 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1773
1774         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1775                 return False;
1776         }
1777         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1778         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1779
1780         printf("starting locktest3\n");
1781
1782         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1783
1784         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1785                          &fnum1);
1786         if (!NT_STATUS_IS_OK(status)) {
1787                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1788                 return False;
1789         }
1790
1791         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1792         if (!NT_STATUS_IS_OK(status)) {
1793                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1794                 return False;
1795         }
1796
1797         for (offset=i=0;i<torture_numops;i++) {
1798                 NEXT_OFFSET;
1799
1800                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1801                 if (!NT_STATUS_IS_OK(status)) {
1802                         printf("lock1 %d failed (%s)\n", 
1803                                i,
1804                                nt_errstr(status));
1805                         return False;
1806                 }
1807
1808                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1809                 if (!NT_STATUS_IS_OK(status)) {
1810                         printf("lock2 %d failed (%s)\n", 
1811                                i,
1812                                nt_errstr(status));
1813                         return False;
1814                 }
1815         }
1816
1817         for (offset=i=0;i<torture_numops;i++) {
1818                 NEXT_OFFSET;
1819
1820                 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1821                 if (NT_STATUS_IS_OK(status)) {
1822                         printf("error: lock1 %d succeeded!\n", i);
1823                         return False;
1824                 }
1825
1826                 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1827                 if (NT_STATUS_IS_OK(status)) {
1828                         printf("error: lock2 %d succeeded!\n", i);
1829                         return False;
1830                 }
1831
1832                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1833                 if (NT_STATUS_IS_OK(status)) {
1834                         printf("error: lock3 %d succeeded!\n", i);
1835                         return False;
1836                 }
1837
1838                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1839                 if (NT_STATUS_IS_OK(status)) {
1840                         printf("error: lock4 %d succeeded!\n", i);
1841                         return False;
1842                 }
1843         }
1844
1845         for (offset=i=0;i<torture_numops;i++) {
1846                 NEXT_OFFSET;
1847
1848                 status = cli_unlock(cli1, fnum1, offset-1, 1);
1849                 if (!NT_STATUS_IS_OK(status)) {
1850                         printf("unlock1 %d failed (%s)\n", 
1851                                i,
1852                                nt_errstr(status));
1853                         return False;
1854                 }
1855
1856                 status = cli_unlock(cli2, fnum2, offset-2, 1);
1857                 if (!NT_STATUS_IS_OK(status)) {
1858                         printf("unlock2 %d failed (%s)\n", 
1859                                i,
1860                                nt_errstr(status));
1861                         return False;
1862                 }
1863         }
1864
1865         status = cli_close(cli1, fnum1);
1866         if (!NT_STATUS_IS_OK(status)) {
1867                 printf("close1 failed (%s)\n", nt_errstr(status));
1868                 return False;
1869         }
1870
1871         status = cli_close(cli2, fnum2);
1872         if (!NT_STATUS_IS_OK(status)) {
1873                 printf("close2 failed (%s)\n", nt_errstr(status));
1874                 return False;
1875         }
1876
1877         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1878         if (!NT_STATUS_IS_OK(status)) {
1879                 printf("unlink failed (%s)\n", nt_errstr(status));
1880                 return False;
1881         }
1882
1883         if (!torture_close_connection(cli1)) {
1884                 correct = False;
1885         }
1886
1887         if (!torture_close_connection(cli2)) {
1888                 correct = False;
1889         }
1890
1891         printf("finished locktest3\n");
1892
1893         return correct;
1894 }
1895
1896 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1897                            char *buf, off_t offset, size_t size,
1898                            size_t *nread, size_t expect)
1899 {
1900         NTSTATUS status;
1901         size_t l_nread;
1902
1903         status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1904
1905         if(!NT_STATUS_IS_OK(status)) {
1906                 return false;
1907         } else if (l_nread != expect) {
1908                 return false;
1909         }
1910
1911         if (nread) {
1912                 *nread = l_nread;
1913         }
1914
1915         return true;
1916 }
1917
1918 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1919         printf("** "); correct = False; \
1920         }
1921
1922 /*
1923   looks at overlapping locks
1924 */
1925 static bool run_locktest4(int dummy)
1926 {
1927         static struct cli_state *cli1, *cli2;
1928         const char *fname = "\\lockt4.lck";
1929         uint16_t fnum1, fnum2, f;
1930         bool ret;
1931         char buf[1000];
1932         bool correct = True;
1933         NTSTATUS status;
1934
1935         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1936                 return False;
1937         }
1938
1939         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1940         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1941
1942         printf("starting locktest4\n");
1943
1944         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1945
1946         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1947         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1948
1949         memset(buf, 0, sizeof(buf));
1950
1951         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1952                               NULL);
1953         if (!NT_STATUS_IS_OK(status)) {
1954                 printf("Failed to create file: %s\n", nt_errstr(status));
1955                 correct = False;
1956                 goto fail;
1957         }
1958
1959         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1960               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1961         EXPECTED(ret, False);
1962         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1963
1964         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1965               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1966         EXPECTED(ret, True);
1967         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1968
1969         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1970               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1971         EXPECTED(ret, False);
1972         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1973
1974         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1975               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1976         EXPECTED(ret, True);
1977         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1978
1979         ret = (cli_setpid(cli1, 1),
1980               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1981               (cli_setpid(cli1, 2),
1982               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1983         EXPECTED(ret, False);
1984         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1985
1986         ret = (cli_setpid(cli1, 1),
1987               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1988               (cli_setpid(cli1, 2),
1989               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1990         EXPECTED(ret, True);
1991         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1992
1993         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1994               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1995         EXPECTED(ret, True);
1996         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1997
1998         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1999               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2000         EXPECTED(ret, False);
2001         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2002
2003         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2004               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2005         EXPECTED(ret, False);
2006         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2007
2008         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2009               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2010         EXPECTED(ret, True);
2011         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2012
2013         ret = (cli_setpid(cli1, 1),
2014              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2015              (cli_setpid(cli1, 2),
2016              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2017         EXPECTED(ret, False);
2018         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2019
2020         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2021               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2022               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2023         EXPECTED(ret, False);
2024         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2025
2026
2027         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2028               test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2029         EXPECTED(ret, False);
2030         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2031
2032         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2033         ret = NT_STATUS_IS_OK(status);
2034         if (ret) {
2035                 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2036                                       NULL);
2037                 ret = NT_STATUS_IS_OK(status);
2038         }
2039         EXPECTED(ret, False);
2040         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2041
2042
2043         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2044               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2045               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2046               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2047         EXPECTED(ret, True);
2048         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2049
2050
2051         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2052               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2053               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2054               test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2055               !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2056                                              150, 4, NULL))) &&
2057               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2058         EXPECTED(ret, True);
2059         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2060
2061         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2062               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2063               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2064                                            160, 4, NULL)) &&
2065               test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2066         EXPECTED(ret, True);
2067         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2068
2069         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2070               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2071               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2072                                            170, 4, NULL)) &&
2073               test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2074         EXPECTED(ret, True);
2075         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2076
2077         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2078               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2079               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2080               !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2081                                             190, 4, NULL)) &&
2082               test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2083         EXPECTED(ret, True);
2084         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2085
2086         cli_close(cli1, fnum1);
2087         cli_close(cli2, fnum2);
2088         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2089         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2090         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2091               NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2092               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2093               NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2094               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2095         cli_close(cli1, f);
2096         cli_close(cli1, fnum1);
2097         EXPECTED(ret, True);
2098         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2099
2100  fail:
2101         cli_close(cli1, fnum1);
2102         cli_close(cli2, fnum2);
2103         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2104         torture_close_connection(cli1);
2105         torture_close_connection(cli2);
2106
2107         printf("finished locktest4\n");
2108         return correct;
2109 }
2110
2111 /*
2112   looks at lock upgrade/downgrade.
2113 */
2114 static bool run_locktest5(int dummy)
2115 {
2116         static struct cli_state *cli1, *cli2;
2117         const char *fname = "\\lockt5.lck";
2118         uint16_t fnum1, fnum2, fnum3;
2119         bool ret;
2120         char buf[1000];
2121         bool correct = True;
2122         NTSTATUS status;
2123
2124         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2125                 return False;
2126         }
2127
2128         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2129         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2130
2131         printf("starting locktest5\n");
2132
2133         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2134
2135         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2136         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2137         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2138
2139         memset(buf, 0, sizeof(buf));
2140
2141         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2142                               NULL);
2143         if (!NT_STATUS_IS_OK(status)) {
2144                 printf("Failed to create file: %s\n", nt_errstr(status));
2145                 correct = False;
2146                 goto fail;
2147         }
2148
2149         /* Check for NT bug... */
2150         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2151               NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2152         cli_close(cli1, fnum1);
2153         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2154         status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2155         ret = NT_STATUS_IS_OK(status);
2156         EXPECTED(ret, True);
2157         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2158         cli_close(cli1, fnum1);
2159         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2160         cli_unlock(cli1, fnum3, 0, 1);
2161
2162         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2163               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2164         EXPECTED(ret, True);
2165         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2166
2167         status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2168         ret = NT_STATUS_IS_OK(status);
2169         EXPECTED(ret, False);
2170
2171         printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2172
2173         /* Unlock the process 2 lock. */
2174         cli_unlock(cli2, fnum2, 0, 4);
2175
2176         status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2177         ret = NT_STATUS_IS_OK(status);
2178         EXPECTED(ret, False);
2179
2180         printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2181
2182         /* Unlock the process 1 fnum3 lock. */
2183         cli_unlock(cli1, fnum3, 0, 4);
2184
2185         /* Stack 2 more locks here. */
2186         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2187               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2188
2189         EXPECTED(ret, True);
2190         printf("the same process %s stack read locks\n", ret?"can":"cannot");
2191
2192         /* Unlock the first process lock, then check this was the WRITE lock that was
2193                 removed. */
2194
2195         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2196               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2197
2198         EXPECTED(ret, True);
2199         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2200
2201         /* Unlock the process 2 lock. */
2202         cli_unlock(cli2, fnum2, 0, 4);
2203
2204         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2205
2206         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2207                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2208                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2209
2210         EXPECTED(ret, True);
2211         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
2212
2213         /* Ensure the next unlock fails. */
2214         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2215         EXPECTED(ret, False);
2216         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
2217
2218         /* Ensure connection 2 can get a write lock. */
2219         status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2220         ret = NT_STATUS_IS_OK(status);
2221         EXPECTED(ret, True);
2222
2223         printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2224
2225
2226  fail:
2227         cli_close(cli1, fnum1);
2228         cli_close(cli2, fnum2);
2229         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2230         if (!torture_close_connection(cli1)) {
2231                 correct = False;
2232         }
2233         if (!torture_close_connection(cli2)) {
2234                 correct = False;
2235         }
2236
2237         printf("finished locktest5\n");
2238
2239         return correct;
2240 }
2241
2242 /*
2243   tries the unusual lockingX locktype bits
2244 */
2245 static bool run_locktest6(int dummy)
2246 {
2247         static struct cli_state *cli;
2248         const char *fname[1] = { "\\lock6.txt" };
2249         int i;
2250         uint16_t fnum;
2251         NTSTATUS status;
2252
2253         if (!torture_open_connection(&cli, 0)) {
2254                 return False;
2255         }
2256
2257         smbXcli_conn_set_sockopt(cli->conn, sockops);
2258
2259         printf("starting locktest6\n");
2260
2261         for (i=0;i<1;i++) {
2262                 printf("Testing %s\n", fname[i]);
2263
2264                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2265
2266                 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2267                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2268                 cli_close(cli, fnum);
2269                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2270
2271                 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2272                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2273                 cli_close(cli, fnum);
2274                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2275
2276                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2277         }
2278
2279         torture_close_connection(cli);
2280
2281         printf("finished locktest6\n");
2282         return True;
2283 }
2284
2285 static bool run_locktest7(int dummy)
2286 {
2287         struct cli_state *cli1;
2288         const char *fname = "\\lockt7.lck";
2289         uint16_t fnum1;
2290         char buf[200];
2291         bool correct = False;
2292         size_t nread;
2293         NTSTATUS status;
2294
2295         if (!torture_open_connection(&cli1, 0)) {
2296                 return False;
2297         }
2298
2299         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2300
2301         printf("starting locktest7\n");
2302
2303         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2304
2305         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2306
2307         memset(buf, 0, sizeof(buf));
2308
2309         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2310                               NULL);
2311         if (!NT_STATUS_IS_OK(status)) {
2312                 printf("Failed to create file: %s\n", nt_errstr(status));
2313                 goto fail;
2314         }
2315
2316         cli_setpid(cli1, 1);
2317
2318         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2319         if (!NT_STATUS_IS_OK(status)) {
2320                 printf("Unable to apply read lock on range 130:4, "
2321                        "error was %s\n", nt_errstr(status));
2322                 goto fail;
2323         } else {
2324                 printf("pid1 successfully locked range 130:4 for READ\n");
2325         }
2326
2327         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2328         if (!NT_STATUS_IS_OK(status)) {
2329                 printf("pid1 unable to read the range 130:4, error was %s\n",
2330                       nt_errstr(status));
2331                 goto fail;
2332         } else if (nread != 4) {
2333                 printf("pid1 unable to read the range 130:4, "
2334                        "recv %ld req %d\n", (unsigned long)nread, 4);
2335                 goto fail;
2336         } else {
2337                 printf("pid1 successfully read the range 130:4\n");
2338         }
2339
2340         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2341         if (!NT_STATUS_IS_OK(status)) {
2342                 printf("pid1 unable to write to the range 130:4, error was "
2343                        "%s\n", nt_errstr(status));
2344                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2345                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2346                         goto fail;
2347                 }
2348         } else {
2349                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2350                 goto fail;
2351         }
2352
2353         cli_setpid(cli1, 2);
2354
2355         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2356         if (!NT_STATUS_IS_OK(status)) {
2357                 printf("pid2 unable to read the range 130:4, error was %s\n",
2358                       nt_errstr(status));
2359                 goto fail;
2360         } else if (nread != 4) {
2361                 printf("pid2 unable to read the range 130:4, "
2362                        "recv %ld req %d\n", (unsigned long)nread, 4);
2363                 goto fail;
2364         } else {
2365                 printf("pid2 successfully read the range 130:4\n");
2366         }
2367
2368         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2369         if (!NT_STATUS_IS_OK(status)) {
2370                 printf("pid2 unable to write to the range 130:4, error was "
2371                        "%s\n", nt_errstr(status));
2372                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2373                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2374                         goto fail;
2375                 }
2376         } else {
2377                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2378                 goto fail;
2379         }
2380
2381         cli_setpid(cli1, 1);
2382         cli_unlock(cli1, fnum1, 130, 4);
2383
2384         status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2385         if (!NT_STATUS_IS_OK(status)) {
2386                 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2387                 goto fail;
2388         } else {
2389                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2390         }
2391
2392         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2393         if (!NT_STATUS_IS_OK(status)) {
2394                 printf("pid1 unable to read the range 130:4, error was %s\n",
2395                       nt_errstr(status));
2396                 goto fail;
2397         } else if (nread != 4) {
2398                 printf("pid1 unable to read the range 130:4, "
2399                        "recv %ld req %d\n", (unsigned long)nread, 4);
2400                 goto fail;
2401         } else {
2402                 printf("pid1 successfully read the range 130:4\n");
2403         }
2404
2405         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2406         if (!NT_STATUS_IS_OK(status)) {
2407                 printf("pid1 unable to write to the range 130:4, error was "
2408                        "%s\n", nt_errstr(status));
2409                 goto fail;
2410         } else {
2411                 printf("pid1 successfully wrote to the range 130:4\n");
2412         }
2413
2414         cli_setpid(cli1, 2);
2415
2416         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2417         if (!NT_STATUS_IS_OK(status)) {
2418                 printf("pid2 unable to read the range 130:4, error was "
2419                        "%s\n", nt_errstr(status));
2420                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2421                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2422                         goto fail;
2423                 }
2424         } else {
2425                 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2426                        (unsigned long)nread);
2427                 goto fail;
2428         }
2429
2430         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2431         if (!NT_STATUS_IS_OK(status)) {
2432                 printf("pid2 unable to write to the range 130:4, error was "
2433                        "%s\n", nt_errstr(status));
2434                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2435                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2436                         goto fail;
2437                 }
2438         } else {
2439                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2440                 goto fail;
2441         }
2442
2443         cli_unlock(cli1, fnum1, 130, 0);
2444         correct = True;
2445
2446 fail:
2447         cli_close(cli1, fnum1);
2448         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2449         torture_close_connection(cli1);
2450
2451         printf("finished locktest7\n");
2452         return correct;
2453 }
2454
2455 /*
2456  * This demonstrates a problem with our use of GPFS share modes: A file
2457  * descriptor sitting in the pending close queue holding a GPFS share mode
2458  * blocks opening a file another time. Happens with Word 2007 temp files.
2459  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2460  * open is denied with NT_STATUS_SHARING_VIOLATION.
2461  */
2462
2463 static bool run_locktest8(int dummy)
2464 {
2465         struct cli_state *cli1;
2466         const char *fname = "\\lockt8.lck";
2467         uint16_t fnum1, fnum2;
2468         char buf[200];
2469         bool correct = False;
2470         NTSTATUS status;
2471
2472         if (!torture_open_connection(&cli1, 0)) {
2473                 return False;
2474         }
2475
2476         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2477
2478         printf("starting locktest8\n");
2479
2480         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2481
2482         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2483                           &fnum1);
2484         if (!NT_STATUS_IS_OK(status)) {
2485                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2486                 return false;
2487         }
2488
2489         memset(buf, 0, sizeof(buf));
2490
2491         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2492         if (!NT_STATUS_IS_OK(status)) {
2493                 d_fprintf(stderr, "cli_openx second time returned %s\n",
2494                           nt_errstr(status));
2495                 goto fail;
2496         }
2497
2498         status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2499         if (!NT_STATUS_IS_OK(status)) {
2500                 printf("Unable to apply read lock on range 1:1, error was "
2501                        "%s\n", nt_errstr(status));
2502                 goto fail;
2503         }
2504
2505         status = cli_close(cli1, fnum1);
2506         if (!NT_STATUS_IS_OK(status)) {
2507                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2508                 goto fail;
2509         }
2510
2511         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2512         if (!NT_STATUS_IS_OK(status)) {
2513                 d_fprintf(stderr, "cli_openx third time returned %s\n",
2514                           nt_errstr(status));
2515                 goto fail;
2516         }
2517
2518         correct = true;
2519
2520 fail:
2521         cli_close(cli1, fnum1);
2522         cli_close(cli1, fnum2);
2523         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2524         torture_close_connection(cli1);
2525
2526         printf("finished locktest8\n");
2527         return correct;
2528 }
2529
2530 /*
2531  * This test is designed to be run in conjunction with
2532  * external NFS or POSIX locks taken in the filesystem.
2533  * It checks that the smbd server will block until the
2534  * lock is released and then acquire it. JRA.
2535  */
2536
2537 static bool got_alarm;
2538 static struct cli_state *alarm_cli;
2539
2540 static void alarm_handler(int dummy)
2541 {
2542         got_alarm = True;
2543 }
2544
2545 static void alarm_handler_parent(int dummy)
2546 {
2547         smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2548 }
2549
2550 static void do_local_lock(const char *fname, int read_fd, int write_fd)
2551 {
2552         int fd;
2553         char c = '\0';
2554         struct flock lock;
2555         const char *local_pathname = NULL;
2556         int ret;
2557
2558         local_pathname = talloc_asprintf(talloc_tos(),
2559                         "%s/%s", local_path, fname);
2560         if (!local_pathname) {
2561                 printf("child: alloc fail\n");
2562                 exit(1);
2563         }
2564
2565         unlink(local_pathname);
2566         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2567         if (fd == -1) {
2568                 printf("child: open of %s failed %s.\n",
2569                         local_pathname, strerror(errno));
2570                 exit(1);
2571         }
2572
2573         /* Now take a fcntl lock. */
2574         lock.l_type = F_WRLCK;
2575         lock.l_whence = SEEK_SET;
2576         lock.l_start = 0;
2577         lock.l_len = 4;
2578         lock.l_pid = getpid();
2579
2580         ret = fcntl(fd,F_SETLK,&lock);
2581         if (ret == -1) {
2582                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2583                         local_pathname, strerror(errno));
2584                 exit(1);
2585         } else {
2586                 printf("child: got lock 0:4 on file %s.\n",
2587                         local_pathname );
2588                 fflush(stdout);
2589         }
2590
2591         CatchSignal(SIGALRM, alarm_handler);
2592         alarm(5);
2593         /* Signal the parent. */
2594         if (write(write_fd, &c, 1) != 1) {
2595                 printf("child: start signal fail %s.\n",
2596                         strerror(errno));
2597                 exit(1);
2598         }
2599         alarm(0);
2600
2601         alarm(10);
2602         /* Wait for the parent to be ready. */
2603         if (read(read_fd, &c, 1) != 1) {
2604                 printf("child: reply signal fail %s.\n",
2605                         strerror(errno));
2606                 exit(1);
2607         }
2608         alarm(0);
2609
2610         sleep(5);
2611         close(fd);
2612         printf("child: released lock 0:4 on file %s.\n",
2613                 local_pathname );
2614         fflush(stdout);
2615         exit(0);
2616 }
2617
2618 static bool _run_locktest9X(const char *fname, int timeout)
2619 {
2620         struct cli_state *cli1;
2621         char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2622         uint16_t fnum;
2623         bool correct = False;
2624         int pipe_in[2], pipe_out[2];
2625         pid_t child_pid;
2626         char c = '\0';
2627         int ret;
2628         struct timeval start;
2629         double seconds;
2630         NTSTATUS status;
2631
2632         printf("starting locktest9X: %s\n", fname);
2633
2634         if (local_path == NULL) {
2635                 d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2636                 return false;
2637         }
2638
2639         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2640                 return false;
2641         }
2642
2643         child_pid = fork();
2644         if (child_pid == -1) {
2645                 return false;
2646         }
2647
2648         if (child_pid == 0) {
2649                 /* Child. */
2650                 do_local_lock(fname, pipe_out[0], pipe_in[1]);
2651                 exit(0);
2652         }
2653
2654         close(pipe_out[0]);
2655         close(pipe_in[1]);
2656         pipe_out[0] = -1;
2657         pipe_in[1] = -1;
2658
2659         /* Parent. */
2660         ret = read(pipe_in[0], &c, 1);
2661         if (ret != 1) {
2662                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2663                         strerror(errno));
2664                 return false;
2665         }
2666
2667         if (!torture_open_connection(&cli1, 0)) {
2668                 return false;
2669         }
2670
2671         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2672
2673         status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2674                           &fnum);
2675         if (!NT_STATUS_IS_OK(status)) {
2676                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2677                 return false;
2678         }
2679
2680         /* Ensure the child has the lock. */
2681         status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2682         if (NT_STATUS_IS_OK(status)) {
2683                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2684                 goto fail;
2685         } else {
2686                 d_printf("Child has the lock.\n");
2687         }
2688
2689         /* Tell the child to wait 5 seconds then exit. */
2690         ret = write(pipe_out[1], &c, 1);
2691         if (ret != 1) {
2692                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2693                         strerror(errno));
2694                 goto fail;
2695         }
2696
2697         /* Wait 20 seconds for the lock. */
2698         alarm_cli = cli1;
2699         CatchSignal(SIGALRM, alarm_handler_parent);
2700         alarm(20);
2701
2702         start = timeval_current();
2703
2704         status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2705         if (!NT_STATUS_IS_OK(status)) {
2706                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2707                        "%s\n", nt_errstr(status));
2708                 goto fail_nofd;
2709         }
2710         alarm(0);
2711
2712         seconds = timeval_elapsed(&start);
2713
2714         printf("Parent got the lock after %.2f seconds.\n",
2715                 seconds);
2716
2717         status = cli_close(cli1, fnum);
2718         if (!NT_STATUS_IS_OK(status)) {
2719                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2720                 goto fail;
2721         }
2722
2723         correct = true;
2724
2725 fail:
2726         cli_close(cli1, fnum);
2727         torture_close_connection(cli1);
2728
2729 fail_nofd:
2730
2731         printf("finished locktest9X: %s\n", fname);
2732         return correct;
2733 }
2734
2735 static bool run_locktest9a(int dummy)
2736 {
2737         return _run_locktest9X("lock9a.dat", -1);
2738 }
2739
2740 static bool run_locktest9b(int dummy)
2741 {
2742         return _run_locktest9X("lock9b.dat", 10000);
2743 }
2744
2745 struct locktest10_state {
2746         bool ok;
2747         bool done;
2748 };
2749
2750 static void locktest10_lockingx_done(struct tevent_req *subreq);
2751 static void locktest10_read_andx_done(struct tevent_req *subreq);
2752
2753 static bool run_locktest10(int dummy)
2754 {
2755         struct tevent_context *ev = NULL;
2756         struct cli_state *cli1 = NULL;
2757         struct cli_state *cli2 = NULL;
2758         struct smb1_lock_element lck = { 0 };
2759         struct tevent_req *reqs[2] = { NULL };
2760         struct tevent_req *smbreqs[2] = { NULL };
2761         const char fname[] = "\\lockt10.lck";
2762         uint16_t fnum1, fnum2;
2763         bool ret = false;
2764         bool ok;
2765         uint8_t data = 1;
2766         struct locktest10_state state = { .ok = true };
2767         NTSTATUS status;
2768
2769         printf("starting locktest10\n");
2770
2771         ev = samba_tevent_context_init(NULL);
2772         if (ev == NULL) {
2773                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2774                 goto done;
2775         }
2776
2777         ok = torture_open_connection(&cli1, 0);
2778         if (!ok) {
2779                 goto done;
2780         }
2781         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2782
2783         ok = torture_open_connection(&cli2, 1);
2784         if (!ok) {
2785                 goto done;
2786         }
2787         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2788
2789         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2790         if (!NT_STATUS_IS_OK(status)) {
2791                 d_fprintf(stderr,
2792                           "cli_openx failed: %s\n",
2793                           nt_errstr(status));
2794                 goto done;
2795         }
2796
2797         status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2798         if (!NT_STATUS_IS_OK(status)) {
2799                 d_fprintf(stderr,
2800                           "cli_writeall failed: %s\n",
2801                           nt_errstr(status));
2802                 goto done;
2803         }
2804
2805         status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2806         if (!NT_STATUS_IS_OK(status)) {
2807                 d_fprintf(stderr,
2808                           "cli_openx failed: %s\n",
2809                           nt_errstr(status));
2810                 goto done;
2811         }
2812
2813         status = cli_locktype(
2814                 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2815         if (!NT_STATUS_IS_OK(status)) {
2816                 d_fprintf(stderr,
2817                           "cli_locktype failed: %s\n",
2818                           nt_errstr(status));
2819                 goto done;
2820         }
2821
2822         lck = (struct smb1_lock_element) {
2823                 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2824         };
2825
2826         reqs[0] = cli_lockingx_create(
2827                 ev,                             /* mem_ctx */
2828                 ev,                             /* tevent_context */
2829                 cli1,                           /* cli */
2830                 fnum1,                          /* fnum */
2831                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
2832                 0,                              /* newoplocklevel */
2833                 1,                              /* timeout */
2834                 0,                              /* num_unlocks */
2835                 NULL,                           /* unlocks */
2836                 1,                              /* num_locks */
2837                 &lck,                           /* locks */
2838                 &smbreqs[0]);                   /* psmbreq */
2839         if (reqs[0] == NULL) {
2840                 d_fprintf(stderr, "cli_lockingx_create failed\n");
2841                 goto done;
2842         }
2843         tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
2844
2845         reqs[1] = cli_read_andx_create(
2846                 ev,             /* mem_ctx */
2847                 ev,             /* ev */
2848                 cli1,           /* cli */
2849                 fnum1,          /* fnum */
2850                 0,              /* offset */
2851                 1,              /* size */
2852                 &smbreqs[1]);   /* psmbreq */
2853         if (reqs[1] == NULL) {
2854                 d_fprintf(stderr, "cli_read_andx_create failed\n");
2855                 goto done;
2856         }
2857         tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
2858
2859         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
2860         if (!NT_STATUS_IS_OK(status)) {
2861                 d_fprintf(stderr,
2862                           "smb1cli_req_chain_submit failed: %s\n",
2863                           nt_errstr(status));
2864                 goto done;
2865         }
2866
2867         while (!state.done) {
2868                 tevent_loop_once(ev);
2869         }
2870
2871         torture_close_connection(cli1);
2872
2873         if (state.ok) {
2874                 ret = true;
2875         }
2876 done:
2877         return ret;
2878 }
2879
2880 static void locktest10_lockingx_done(struct tevent_req *subreq)
2881 {
2882         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
2883         NTSTATUS status;
2884
2885         status = cli_lockingx_recv(subreq);
2886         TALLOC_FREE(subreq);
2887
2888         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2889                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
2890                 state->ok = false;
2891         }
2892 }
2893
2894 static void locktest10_read_andx_done(struct tevent_req *subreq)
2895 {
2896         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
2897         ssize_t received = -1;
2898         uint8_t *rcvbuf = NULL;
2899         NTSTATUS status;
2900
2901         status = cli_read_andx_recv(subreq, &received, &rcvbuf);
2902
2903         if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
2904                 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
2905                 state->ok = false;
2906         }
2907
2908         state->done = true;
2909         TALLOC_FREE(subreq);
2910 }
2911
2912 static bool run_locktest11(int dummy)
2913 {
2914         struct cli_state *cli1;
2915         const char *fname = "\\lockt11.lck";
2916         NTSTATUS status;
2917         uint16_t fnum;
2918         bool ret = false;
2919
2920         if (!torture_open_connection(&cli1, 0)) {
2921                 return false;
2922         }
2923
2924         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2925
2926         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2927
2928         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
2929         if (!NT_STATUS_IS_OK(status)) {
2930                 d_fprintf(stderr,
2931                           "cli_openx returned %s\n",
2932                           nt_errstr(status));
2933                 return false;
2934         }
2935
2936         /*
2937          * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
2938          * returns NT_STATUS_OK
2939          */
2940
2941         status = cli_lockingx(
2942                 cli1,                           /* cli */
2943                 fnum,                           /* fnum */
2944                 LOCKING_ANDX_CANCEL_LOCK,       /* typeoflock */
2945                 0,                              /* newoplocklevel */
2946                 0,                              /* timeout */
2947                 0,                              /* num_unlocks */
2948                 NULL,                           /* unlocks */
2949                 0,                              /* num_locks */
2950                 NULL);                          /* locks */
2951
2952         if (!NT_STATUS_IS_OK(status)) {
2953                 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
2954                 goto fail;
2955         }
2956
2957         ret = true;
2958 fail:
2959         cli_close(cli1, fnum);
2960         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2961
2962         return ret;
2963 }
2964
2965 struct deferred_close_state {
2966         struct tevent_context *ev;
2967         struct cli_state *cli;
2968         uint16_t fnum;
2969 };
2970
2971 static void deferred_close_waited(struct tevent_req *subreq);
2972 static void deferred_close_done(struct tevent_req *subreq);
2973
2974 static struct tevent_req *deferred_close_send(
2975         TALLOC_CTX *mem_ctx,
2976         struct tevent_context *ev,
2977         int wait_secs,
2978         struct cli_state *cli,
2979         uint16_t fnum)
2980 {
2981         struct tevent_req *req = NULL, *subreq = NULL;
2982         struct deferred_close_state *state = NULL;
2983         struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
2984
2985         req = tevent_req_create(
2986                 mem_ctx, &state, struct deferred_close_state);
2987         if (req == NULL) {
2988                 return NULL;
2989         }
2990         state->ev = ev;
2991         state->cli = cli;
2992         state->fnum = fnum;
2993
2994         subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
2995         if (tevent_req_nomem(subreq, req)) {
2996                 return tevent_req_post(req, ev);
2997         }
2998         tevent_req_set_callback(subreq, deferred_close_waited, req);
2999         return req;
3000 }
3001
3002 static void deferred_close_waited(struct tevent_req *subreq)
3003 {
3004         struct tevent_req *req = tevent_req_callback_data(
3005                 subreq, struct tevent_req);
3006         struct deferred_close_state *state = tevent_req_data(
3007                 req, struct deferred_close_state);
3008         bool ok;
3009
3010         ok = tevent_wakeup_recv(subreq);
3011         TALLOC_FREE(subreq);
3012         if (!ok) {
3013                 tevent_req_oom(req);
3014                 return;
3015         }
3016
3017         subreq = cli_close_send(state, state->ev, state->cli, state->fnum);
3018         if (tevent_req_nomem(subreq, req)) {
3019                 return;
3020         }
3021         tevent_req_set_callback(subreq, deferred_close_done, req);
3022 }
3023
3024 static void deferred_close_done(struct tevent_req *subreq)
3025 {
3026         NTSTATUS status = cli_close_recv(subreq);
3027         tevent_req_simple_finish_ntstatus(subreq, status);
3028 }
3029
3030 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3031 {
3032         return tevent_req_simple_recv_ntstatus(req);
3033 }
3034
3035 struct lockread_state {
3036         struct smb1_lock_element lck;
3037         struct tevent_req *reqs[2];
3038         struct tevent_req *smbreqs[2];
3039         NTSTATUS lock_status;
3040         NTSTATUS read_status;
3041         uint8_t *readbuf;
3042 };
3043
3044 static void lockread_lockingx_done(struct tevent_req *subreq);
3045 static void lockread_read_andx_done(struct tevent_req *subreq);
3046
3047 static struct tevent_req *lockread_send(
3048         TALLOC_CTX *mem_ctx,
3049         struct tevent_context *ev,
3050         struct cli_state *cli,
3051         uint16_t fnum)
3052 {
3053         struct tevent_req *req = NULL;
3054         struct lockread_state *state = NULL;
3055         NTSTATUS status;
3056
3057         req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3058         if (req == NULL) {
3059                 return NULL;
3060         }
3061
3062         state->lck = (struct smb1_lock_element) {
3063                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3064         };
3065
3066         state->reqs[0] = cli_lockingx_create(
3067                 ev,                             /* mem_ctx */
3068                 ev,                             /* tevent_context */
3069                 cli,                            /* cli */
3070                 fnum,                           /* fnum */
3071                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3072                 0,                              /* newoplocklevel */
3073                 10000,                          /* timeout */
3074                 0,                              /* num_unlocks */
3075                 NULL,                           /* unlocks */
3076                 1,                              /* num_locks */
3077                 &state->lck,                    /* locks */
3078                 &state->smbreqs[0]);            /* psmbreq */
3079         if (tevent_req_nomem(state->reqs[0], req)) {
3080                 return tevent_req_post(req, ev);
3081         }
3082         tevent_req_set_callback(
3083                 state->reqs[0], lockread_lockingx_done, req);
3084
3085         state->reqs[1] = cli_read_andx_create(
3086                 ev,             /* mem_ctx */
3087                 ev,             /* ev */
3088                 cli,            /* cli */
3089                 fnum,           /* fnum */
3090                 0,              /* offset */
3091                 1,              /* size */
3092                 &state->smbreqs[1]);    /* psmbreq */
3093         if (tevent_req_nomem(state->reqs[1], req)) {
3094                 return tevent_req_post(req, ev);
3095         }
3096         tevent_req_set_callback(
3097                 state->reqs[1], lockread_read_andx_done, req);
3098
3099         status = smb1cli_req_chain_submit(state->smbreqs, 2);
3100         if (tevent_req_nterror(req, status)) {
3101                 return tevent_req_post(req, ev);
3102         }
3103         return req;
3104 }
3105
3106 static void lockread_lockingx_done(struct tevent_req *subreq)
3107 {
3108         struct tevent_req *req = tevent_req_callback_data(
3109                 subreq, struct tevent_req);
3110         struct lockread_state *state = tevent_req_data(
3111                 req, struct lockread_state);
3112         state->lock_status = cli_lockingx_recv(subreq);
3113         TALLOC_FREE(subreq);
3114         d_fprintf(stderr,
3115                   "lockingx returned %s\n",
3116                   nt_errstr(state->lock_status));
3117 }
3118
3119 static void lockread_read_andx_done(struct tevent_req *subreq)
3120 {
3121         struct tevent_req *req = tevent_req_callback_data(
3122                 subreq, struct tevent_req);
3123         struct lockread_state *state = tevent_req_data(
3124                 req, struct lockread_state);
3125         ssize_t received = -1;
3126         uint8_t *rcvbuf = NULL;
3127
3128         state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3129
3130         d_fprintf(stderr,
3131                   "read returned %s\n",
3132                   nt_errstr(state->read_status));
3133
3134         if (!NT_STATUS_IS_OK(state->read_status)) {
3135                 TALLOC_FREE(subreq);
3136                 tevent_req_done(req);
3137                 return;
3138         }
3139
3140         if (received > 0) {
3141                 state->readbuf = talloc_memdup(state, rcvbuf, received);
3142                 TALLOC_FREE(subreq);
3143                 if (tevent_req_nomem(state->readbuf, req)) {
3144                         return;
3145                 }
3146         }
3147         TALLOC_FREE(subreq);
3148         tevent_req_done(req);
3149 }
3150
3151 static NTSTATUS lockread_recv(
3152         struct tevent_req *req,
3153         NTSTATUS *lock_status,
3154         NTSTATUS *read_status,
3155         TALLOC_CTX *mem_ctx,
3156         uint8_t **read_buf)
3157 {
3158         struct lockread_state *state = tevent_req_data(
3159                 req, struct lockread_state);
3160         NTSTATUS status;
3161
3162         if (tevent_req_is_nterror(req, &status)) {
3163                 return status;
3164         }
3165
3166         *lock_status = state->lock_status;
3167         *read_status = state->read_status;
3168         if (state->readbuf != NULL) {
3169                 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3170         } else {
3171                 *read_buf = NULL;
3172         }
3173
3174         return NT_STATUS_OK;
3175 }
3176
3177 struct lock12_state {
3178         uint8_t dummy;
3179 };
3180
3181 static void lock12_closed(struct tevent_req *subreq);
3182 static void lock12_read(struct tevent_req *subreq);
3183
3184 static struct tevent_req *lock12_send(
3185         TALLOC_CTX *mem_ctx,
3186         struct tevent_context *ev,
3187         struct cli_state *cli,
3188         uint16_t fnum1,
3189         uint16_t fnum2)
3190 {
3191         struct tevent_req *req = NULL, *subreq = NULL;
3192         struct lock12_state *state = NULL;
3193
3194         req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3195         if (req == NULL) {
3196                 return NULL;
3197         }
3198
3199         subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3200         if (tevent_req_nomem(subreq, req)) {
3201                 return tevent_req_post(req, ev);
3202         }
3203         tevent_req_set_callback(subreq, lock12_closed, req);
3204
3205         subreq = lockread_send(state, ev, cli, fnum2);
3206         if (tevent_req_nomem(subreq, req)) {
3207                 return tevent_req_post(req, ev);
3208         }
3209         tevent_req_set_callback(subreq, lock12_read, req);
3210
3211         return req;
3212 }
3213
3214 static void lock12_closed(struct tevent_req *subreq)
3215 {
3216         struct tevent_req *req = tevent_req_callback_data(
3217                 subreq, struct tevent_req);
3218         NTSTATUS status;
3219
3220         status = deferred_close_recv(subreq);
3221         TALLOC_FREE(subreq);
3222         DBG_DEBUG("close returned %s\n", nt_errstr(status));
3223         if (tevent_req_nterror(req, status)) {
3224                 return;
3225         }
3226 }
3227
3228 static void lock12_read(struct tevent_req *subreq)
3229 {
3230         struct tevent_req *req = tevent_req_callback_data(
3231                 subreq, struct tevent_req);
3232         struct lock12_state *state = tevent_req_data(
3233                 req, struct lock12_state);
3234         NTSTATUS status, lock_status, read_status;
3235         uint8_t *buf = NULL;
3236
3237         status = lockread_recv(
3238                 subreq, &lock_status, &read_status, state, &buf);
3239         TALLOC_FREE(subreq);
3240         if (tevent_req_nterror(req, status) ||
3241             tevent_req_nterror(req, lock_status) ||
3242             tevent_req_nterror(req, read_status)) {
3243                 return;
3244         }
3245         tevent_req_done(req);
3246 }
3247
3248 static NTSTATUS lock12_recv(struct tevent_req *req)
3249
3250 {
3251         NTSTATUS status;
3252
3253         if (tevent_req_is_nterror(req, &status)) {
3254                 return status;
3255         }
3256         return NT_STATUS_OK;
3257 }
3258
3259 static bool run_locktest12(int dummy)
3260 {
3261         struct tevent_context *ev = NULL;
3262         struct tevent_req *req = NULL;
3263         struct cli_state *cli = NULL;
3264         const char fname[] = "\\lockt12.lck";
3265         uint16_t fnum1, fnum2;
3266         bool ret = false;
3267         bool ok;
3268         uint8_t data = 1;
3269         NTSTATUS status;
3270
3271         printf("starting locktest12\n");
3272
3273         ev = samba_tevent_context_init(NULL);
3274         if (ev == NULL) {
3275                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3276                 goto done;
3277         }
3278
3279         ok = torture_open_connection(&cli, 0);
3280         if (!ok) {
3281                 goto done;
3282         }
3283         smbXcli_conn_set_sockopt(cli->conn, sockops);
3284
3285         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3286         if (!NT_STATUS_IS_OK(status)) {
3287                 d_fprintf(stderr,
3288                           "cli_openx failed: %s\n",
3289                           nt_errstr(status));
3290                 goto done;
3291         }
3292
3293         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3294         if (!NT_STATUS_IS_OK(status)) {
3295                 d_fprintf(stderr,
3296                           "cli_openx failed: %s\n",
3297                           nt_errstr(status));
3298                 goto done;
3299         }
3300
3301         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3302         if (!NT_STATUS_IS_OK(status)) {
3303                 d_fprintf(stderr,
3304                           "cli_writeall failed: %s\n",
3305                           nt_errstr(status));
3306                 goto done;
3307         }
3308
3309         status = cli_locktype(
3310                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3311         if (!NT_STATUS_IS_OK(status)) {
3312                 d_fprintf(stderr,
3313                           "cli_locktype failed: %s\n",
3314                           nt_errstr(status));
3315                 goto done;
3316         }
3317
3318         req = lock12_send(ev, ev, cli, fnum1, fnum2);
3319         if (req == NULL) {
3320                 d_fprintf(stderr, "lock12_send failed\n");
3321                 goto done;
3322         }
3323
3324         ok = tevent_req_poll_ntstatus(req, ev, &status);
3325         if (!ok) {
3326                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3327                 goto done;
3328         }
3329
3330         if (!NT_STATUS_IS_OK(status)) {
3331                 d_fprintf(stderr,
3332                           "tevent_req_poll_ntstatus returned %s\n",
3333                           nt_errstr(status));
3334                 goto done;
3335         }
3336
3337         status = lock12_recv(req);
3338         if (!NT_STATUS_IS_OK(status)) {
3339                 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3340                 goto done;
3341         }
3342
3343         ret = true;
3344 done:
3345         torture_close_connection(cli);
3346         return ret;
3347 }
3348
3349 struct lock_ntcancel_state {
3350         struct timeval start;
3351         struct smb1_lock_element lck;
3352         struct tevent_req *subreq;
3353 };
3354
3355 static void lock_ntcancel_waited(struct tevent_req *subreq);
3356 static void lock_ntcancel_done(struct tevent_req *subreq);
3357
3358 static struct tevent_req *lock_ntcancel_send(
3359         TALLOC_CTX *mem_ctx,
3360         struct tevent_context *ev,
3361         struct cli_state *cli,
3362         uint16_t fnum)
3363 {
3364         struct tevent_req *req = NULL, *subreq = NULL;
3365         struct lock_ntcancel_state *state = NULL;
3366
3367         req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3368         if (req == NULL) {
3369                 return NULL;
3370         }
3371         state->lck = (struct smb1_lock_element) {
3372                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3373         };
3374         state->start = timeval_current();
3375
3376         state->subreq = cli_lockingx_send(
3377                 state,                          /* mem_ctx */
3378                 ev,                             /* tevent_context */
3379                 cli,                            /* cli */
3380                 fnum,                           /* fnum */
3381                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3382                 0,                              /* newoplocklevel */
3383                 10000,                          /* timeout */
3384                 0,                              /* num_unlocks */
3385                 NULL,                           /* unlocks */
3386                 1,                              /* num_locks */
3387                 &state->lck);                   /* locks */
3388         if (tevent_req_nomem(state->subreq, req)) {
3389                 return tevent_req_post(req, ev);
3390         }
3391         tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3392
3393         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3394         if (tevent_req_nomem(subreq, req)) {
3395                 return tevent_req_post(req, ev);
3396         }
3397         tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3398         return req;
3399 }
3400
3401 static void lock_ntcancel_waited(struct tevent_req *subreq)
3402 {
3403         struct tevent_req *req = tevent_req_callback_data(
3404                 subreq, struct tevent_req);
3405         struct lock_ntcancel_state *state = tevent_req_data(
3406                 req, struct lock_ntcancel_state);
3407         bool ok;
3408
3409         ok = tevent_wakeup_recv(subreq);
3410         TALLOC_FREE(subreq);
3411         if (!ok) {
3412                 tevent_req_oom(req);
3413                 return;
3414         }
3415
3416         ok = tevent_req_cancel(state->subreq);
3417         if (!ok) {
3418                 d_fprintf(stderr, "Could not cancel subreq\n");
3419                 tevent_req_oom(req);
3420                 return;
3421         }
3422 }
3423
3424 static void lock_ntcancel_done(struct tevent_req *subreq)
3425 {
3426         struct tevent_req *req = tevent_req_callback_data(
3427                 subreq, struct tevent_req);
3428         struct lock_ntcancel_state *state = tevent_req_data(
3429                 req, struct lock_ntcancel_state);
3430         NTSTATUS status;
3431         double elapsed;
3432
3433         status = cli_lockingx_recv(subreq);
3434         TALLOC_FREE(subreq);
3435
3436         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3437                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3438                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3439                 return;
3440         }
3441
3442         elapsed = timeval_elapsed(&state->start);
3443
3444         if (elapsed > 3) {
3445                 d_printf("cli_lockingx was too slow, cancel did not work\n");
3446                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3447                 return;
3448         }
3449
3450         tevent_req_done(req);
3451 }
3452
3453 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3454 {
3455         return tevent_req_simple_recv_ntstatus(req);
3456 }
3457
3458 static bool run_locktest13(int dummy)
3459 {
3460         struct tevent_context *ev = NULL;
3461         struct tevent_req *req = NULL;
3462         struct cli_state *cli = NULL;
3463         const char fname[] = "\\lockt13.lck";
3464         uint16_t fnum1, fnum2;
3465         bool ret = false;
3466         bool ok;
3467         uint8_t data = 1;
3468         NTSTATUS status;
3469
3470         printf("starting locktest13\n");
3471
3472         ev = samba_tevent_context_init(NULL);
3473         if (ev == NULL) {
3474                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3475                 goto done;
3476         }
3477
3478         ok = torture_open_connection(&cli, 0);
3479         if (!ok) {
3480                 goto done;
3481         }
3482         smbXcli_conn_set_sockopt(cli->conn, sockops);
3483
3484         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3485         if (!NT_STATUS_IS_OK(status)) {
3486                 d_fprintf(stderr,
3487                           "cli_openx failed: %s\n",
3488                           nt_errstr(status));
3489                 goto done;
3490         }
3491
3492         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3493         if (!NT_STATUS_IS_OK(status)) {
3494                 d_fprintf(stderr,
3495                           "cli_openx failed: %s\n",
3496                           nt_errstr(status));
3497                 goto done;
3498         }
3499
3500         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3501         if (!NT_STATUS_IS_OK(status)) {
3502                 d_fprintf(stderr,
3503                           "cli_writeall failed: %s\n",
3504                           nt_errstr(status));
3505                 goto done;
3506         }
3507
3508         status = cli_locktype(
3509                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3510         if (!NT_STATUS_IS_OK(status)) {
3511                 d_fprintf(stderr,
3512                           "cli_locktype failed: %s\n",
3513                           nt_errstr(status));
3514                 goto done;
3515         }
3516
3517         req = lock_ntcancel_send(ev, ev, cli, fnum2);
3518         if (req == NULL) {
3519                 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3520                 goto done;
3521         }
3522
3523         ok = tevent_req_poll_ntstatus(req, ev, &status);
3524         if (!ok) {
3525                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3526                 goto done;
3527         }
3528
3529         if (!NT_STATUS_IS_OK(status)) {
3530                 d_fprintf(stderr,
3531                           "tevent_req_poll_ntstatus returned %s\n",
3532                           nt_errstr(status));
3533                 goto done;
3534         }
3535
3536         status = lock_ntcancel_recv(req);
3537         if (!NT_STATUS_IS_OK(status)) {
3538                 d_fprintf(stderr,
3539                           "lock_ntcancel returned %s\n",
3540                           nt_errstr(status));
3541                 goto done;
3542         }
3543
3544         ret = true;
3545 done:
3546         torture_close_connection(cli);
3547         return ret;
3548 }
3549
3550 /*
3551 test whether fnums and tids open on one VC are available on another (a major
3552 security hole)
3553 */
3554 static bool run_fdpasstest(int dummy)
3555 {
3556         struct cli_state *cli1, *cli2;
3557         const char *fname = "\\fdpass.tst";
3558         uint16_t fnum1;
3559         char buf[1024];
3560         NTSTATUS status;
3561
3562         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3563                 return False;
3564         }
3565         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3566         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3567
3568         printf("starting fdpasstest\n");
3569
3570         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3571
3572         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3573                           &fnum1);
3574         if (!NT_STATUS_IS_OK(status)) {
3575                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3576                 return False;
3577         }
3578
3579         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3580                               13, NULL);
3581         if (!NT_STATUS_IS_OK(status)) {
3582                 printf("write failed (%s)\n", nt_errstr(status));
3583                 return False;
3584         }
3585
3586         cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3587         cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3588         cli_setpid(cli2, cli_getpid(cli1));
3589
3590         if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3591                 printf("read succeeded! nasty security hole [%s]\n", buf);
3592                 return false;
3593         }
3594
3595         cli_close(cli1, fnum1);
3596         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3597
3598         torture_close_connection(cli1);
3599         torture_close_connection(cli2);
3600
3601         printf("finished fdpasstest\n");
3602         return True;
3603 }
3604
3605 static bool run_fdsesstest(int dummy)
3606 {
3607         struct cli_state *cli;
3608         uint16_t new_vuid;
3609         uint16_t saved_vuid;
3610         uint32_t new_cnum;
3611         uint32_t saved_cnum;
3612         const char *fname = "\\fdsess.tst";
3613         const char *fname1 = "\\fdsess1.tst";
3614         uint16_t fnum1;
3615         uint16_t fnum2;
3616         char buf[1024];
3617         bool ret = True;
3618         NTSTATUS status;
3619
3620         if (!torture_open_connection(&cli, 0))
3621                 return False;
3622         smbXcli_conn_set_sockopt(cli->conn, sockops);
3623
3624         if (!torture_cli_session_setup2(cli, &new_vuid))
3625                 return False;
3626
3627         saved_cnum = cli_state_get_tid(cli);
3628         if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3629                 return False;
3630         new_cnum = cli_state_get_tid(cli);
3631         cli_state_set_tid(cli, saved_cnum);
3632
3633         printf("starting fdsesstest\n");
3634
3635         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3636         cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3637
3638         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3639         if (!NT_STATUS_IS_OK(status)) {
3640                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3641                 return False;
3642         }
3643
3644         status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3645                               NULL);
3646         if (!NT_STATUS_IS_OK(status)) {
3647                 printf("write failed (%s)\n", nt_errstr(status));
3648                 return False;
3649         }
3650
3651         saved_vuid = cli_state_get_uid(cli);
3652         cli_state_set_uid(cli, new_vuid);
3653
3654         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3655                 printf("read succeeded with different vuid! "
3656                        "nasty security hole [%s]\n", buf);
3657                 ret = false;
3658         }
3659         /* Try to open a file with different vuid, samba cnum. */
3660         if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3661                 printf("create with different vuid, same cnum succeeded.\n");
3662                 cli_close(cli, fnum2);
3663                 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3664         } else {
3665                 printf("create with different vuid, same cnum failed.\n");
3666                 printf("This will cause problems with service clients.\n");
3667                 ret = False;
3668         }
3669
3670         cli_state_set_uid(cli, saved_vuid);
3671
3672         /* Try with same vuid, different cnum. */
3673         cli_state_set_tid(cli, new_cnum);
3674
3675         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3676                 printf("read succeeded with different cnum![%s]\n", buf);
3677                 ret = false;
3678         }
3679
3680         cli_state_set_tid(cli, saved_cnum);
3681         cli_close(cli, fnum1);
3682         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3683
3684         torture_close_connection(cli);
3685
3686         printf("finished fdsesstest\n");
3687         return ret;
3688 }
3689
3690 /*
3691   This test checks that 
3692
3693   1) the server does not allow an unlink on a file that is open
3694 */
3695 static bool run_unlinktest(int dummy)
3696 {
3697         struct cli_state *cli;
3698         const char *fname = "\\unlink.tst";
3699         uint16_t fnum;
3700         bool correct = True;
3701         NTSTATUS status;
3702
3703         if (!torture_open_connection(&cli, 0)) {
3704                 return False;
3705         }
3706
3707         smbXcli_conn_set_sockopt(cli->conn, sockops);
3708
3709         printf("starting unlink test\n");
3710
3711         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3712
3713         cli_setpid(cli, 1);
3714
3715         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3716         if (!NT_STATUS_IS_OK(status)) {
3717                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3718                 return False;
3719         }
3720
3721         status = cli_unlink(cli, fname,
3722                             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3723         if (NT_STATUS_IS_OK(status)) {
3724                 printf("error: server allowed unlink on an open file\n");
3725                 correct = False;
3726         } else {
3727                 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3728                                       NT_STATUS_SHARING_VIOLATION);
3729         }
3730
3731         cli_close(cli, fnum);
3732         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3733
3734         if (!torture_close_connection(cli)) {
3735                 correct = False;
3736         }
3737
3738         printf("unlink test finished\n");
3739
3740         return correct;
3741 }
3742
3743
3744 /*
3745 test how many open files this server supports on the one socket
3746 */
3747 static bool run_maxfidtest(int dummy)
3748 {
3749         struct cli_state *cli;
3750         fstring fname;
3751         uint16_t fnums[0x11000];
3752         int i;
3753         int retries=4;
3754         bool correct = True;
3755         NTSTATUS status;
3756
3757         cli = current_cli;
3758
3759         if (retries <= 0) {
3760                 printf("failed to connect\n");
3761                 return False;
3762         }
3763
3764         smbXcli_conn_set_sockopt(cli->conn, sockops);
3765
3766         for (i=0; i<0x11000; i++) {
3767                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3768                 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3769                                   &fnums[i]);
3770                 if (!NT_STATUS_IS_OK(status)) {
3771                         printf("open of %s failed (%s)\n", 
3772                                fname, nt_errstr(status));
3773                         printf("maximum fnum is %d\n", i);
3774                         break;
3775                 }
3776                 printf("%6d\r", i);
3777         }
3778         printf("%6d\n", i);
3779         i--;
3780
3781         printf("cleaning up\n");
3782         for (;i>=0;i--) {
3783                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3784                 cli_close(cli, fnums[i]);
3785
3786                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3787                 if (!NT_STATUS_IS_OK(status)) {
3788                         printf("unlink of %s failed (%s)\n", 
3789                                fname, nt_errstr(status));
3790                         correct = False;
3791                 }
3792                 printf("%6d\r", i);
3793         }
3794         printf("%6d\n", 0);
3795
3796         printf("maxfid test finished\n");
3797         if (!torture_close_connection(cli)) {
3798                 correct = False;
3799         }
3800         return correct;
3801 }
3802
3803 /* generate a random buffer */
3804 static void rand_buf(char *buf, int len)
3805 {
3806         while (len--) {
3807                 *buf = (char)sys_random();
3808                 buf++;
3809         }
3810 }
3811
3812 /* send smb negprot commands, not reading the response */
3813 static bool run_negprot_nowait(int dummy)
3814 {
3815         struct tevent_context *ev;
3816         int i;
3817         struct cli_state *cli;
3818         bool correct = True;
3819
3820         printf("starting negprot nowait test\n");
3821
3822         ev = samba_tevent_context_init(talloc_tos());
3823         if (ev == NULL) {
3824                 return false;
3825         }
3826
3827         if (!(cli = open_nbt_connection())) {
3828                 TALLOC_FREE(ev);
3829                 return False;
3830         }
3831
3832         for (i=0;i<50000;i++) {
3833                 struct tevent_req *req;
3834
3835                 req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
3836                                            PROTOCOL_CORE, PROTOCOL_NT1, 0);
3837                 if (req == NULL) {
3838                         TALLOC_FREE(ev);
3839                         return false;
3840                 }
3841                 if (!tevent_req_poll(req, ev)) {
3842                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3843                                   strerror(errno));
3844                         TALLOC_FREE(ev);
3845                         return false;
3846                 }
3847                 TALLOC_FREE(req);
3848         }
3849
3850         if (torture_close_connection(cli)) {
3851                 correct = False;
3852         }
3853
3854         printf("finished negprot nowait test\n");
3855
3856         return correct;
3857 }
3858
3859 /* send smb negprot commands, not reading the response */
3860 static bool run_bad_nbt_session(int dummy)
3861 {
3862         struct nmb_name called, calling;
3863         struct sockaddr_storage ss;
3864         NTSTATUS status;
3865         int fd;
3866         bool ret;
3867
3868         printf("starting bad nbt session test\n");
3869
3870         make_nmb_name(&calling, myname, 0x0);
3871         make_nmb_name(&called , host, 0x20);
3872
3873         if (!resolve_name(host, &ss, 0x20, true)) {
3874                 d_fprintf(stderr, "Could not resolve name %s\n", host);
3875                 return false;
3876         }
3877
3878         status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3879         if (!NT_STATUS_IS_OK(status)) {
3880                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3881                           nt_errstr(status));
3882                 return false;
3883         }
3884
3885         ret = cli_bad_session_request(fd, &calling, &called);
3886         close(fd);
3887         if (!ret) {
3888                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3889                           nt_errstr(status));
3890                 return false;
3891         }
3892
3893         printf("finished bad nbt session test\n");
3894         return true;
3895 }
3896
3897 /* send random IPC commands */
3898 static bool run_randomipc(int dummy)
3899 {
3900         char *rparam = NULL;
3901         char *rdata = NULL;
3902         unsigned int rdrcnt,rprcnt;
3903         char param[1024];
3904         int api, param_len, i;
3905         struct cli_state *cli;
3906         bool correct = True;
3907         int count = 50000;
3908
3909         printf("starting random ipc test\n");
3910
3911         if (!torture_open_connection(&cli, 0)) {
3912                 return False;
3913         }
3914
3915         for (i=0;i<count;i++) {
3916                 api = sys_random() % 500;
3917                 param_len = (sys_random() % 64);
3918
3919                 rand_buf(param, param_len);
3920
3921                 SSVAL(param,0,api); 
3922
3923                 cli_api(cli, 
3924                         param, param_len, 8,  
3925                         NULL, 0, CLI_BUFFER_SIZE,
3926                         &rparam, &rprcnt,     
3927                         &rdata, &rdrcnt);
3928                 if (i % 100 == 0) {
3929                         printf("%d/%d\r", i,count);
3930                 }
3931         }
3932         printf("%d/%d\n", i, count);
3933
3934         if (!torture_close_connection(cli)) {
3935                 correct = False;
3936         }
3937
3938         SAFE_FREE(rparam);
3939         SAFE_FREE(rdata);
3940
3941         printf("finished random ipc test\n");
3942
3943         return correct;
3944 }
3945
3946
3947
3948 static void browse_callback(const char *sname, uint32_t stype,
3949                             const char *comment, void *state)
3950 {
3951         printf("\t%20.20s %08x %s\n", sname, stype, comment);
3952 }
3953
3954
3955
3956 /*
3957   This test checks the browse list code
3958
3959 */
3960 static bool run_browsetest(int dummy)
3961 {
3962         static struct cli_state *cli;
3963         bool correct = True;
3964
3965         printf("starting browse test\n");
3966
3967         if (!torture_open_connection(&cli, 0)) {
3968                 return False;
3969         }
3970
3971         printf("domain list:\n");
3972         cli_NetServerEnum(cli, cli->server_domain, 
3973                           SV_TYPE_DOMAIN_ENUM,
3974                           browse_callback, NULL);
3975
3976         printf("machine list:\n");
3977         cli_NetServerEnum(cli, cli->server_domain, 
3978                           SV_TYPE_ALL,
3979                           browse_callback, NULL);
3980
3981         if (!torture_close_connection(cli)) {
3982                 correct = False;
3983         }
3984
3985         printf("browse test finished\n");
3986
3987         return correct;
3988
3989 }
3990
3991 static bool check_attributes(struct cli_state *cli,
3992                                 const char *fname,
3993                                 uint16_t expected_attrs)
3994 {
3995         uint16_t attrs = 0;
3996         NTSTATUS status = cli_getatr(cli,
3997                                 fname,
3998                                 &attrs,
3999                                 NULL,
4000                                 NULL);
4001         if (!NT_STATUS_IS_OK(status)) {
4002                 printf("cli_getatr failed with %s\n",
4003                         nt_errstr(status));
4004                 return false;
4005         }
4006         if (attrs != expected_attrs) {
4007                 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4008                         (unsigned int)attrs,
4009                         (unsigned int)expected_attrs);
4010                 return false;
4011         }
4012         return true;
4013 }
4014
4015 /*
4016   This checks how the getatr calls works
4017 */
4018 static bool run_attrtest(int dummy)
4019 {
4020         struct cli_state *cli;
4021         uint16_t fnum;
4022         time_t t, t2;
4023         const char *fname = "\\attrib123456789.tst";
4024         bool correct = True;
4025         NTSTATUS status;
4026
4027         printf("starting attrib test\n");
4028
4029         if (!torture_open_connection(&cli, 0)) {
4030                 return False;
4031         }
4032
4033         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4034         cli_openx(cli, fname, 
4035                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4036         cli_close(cli, fnum);
4037
4038         status = cli_getatr(cli, fname, NULL, NULL, &t);
4039         if (!NT_STATUS_IS_OK(status)) {
4040                 printf("getatr failed (%s)\n", nt_errstr(status));
4041                 correct = False;
4042         }
4043
4044         if (labs(t - time(NULL)) > 60*60*24*10) {
4045                 printf("ERROR: SMBgetatr bug. time is %s",
4046                        ctime(&t));
4047                 t = time(NULL);
4048                 correct = True;
4049         }
4050
4051         t2 = t-60*60*24; /* 1 day ago */
4052
4053         status = cli_setatr(cli, fname, 0, t2);
4054         if (!NT_STATUS_IS_OK(status)) {
4055                 printf("setatr failed (%s)\n", nt_errstr(status));
4056                 correct = True;
4057         }
4058
4059         status = cli_getatr(cli, fname, NULL, NULL, &t);
4060         if (!NT_STATUS_IS_OK(status)) {
4061                 printf("getatr failed (%s)\n", nt_errstr(status));
4062                 correct = True;
4063         }
4064
4065         if (t != t2) {
4066                 printf("ERROR: getatr/setatr bug. times are\n%s",
4067                        ctime(&t));
4068                 printf("%s", ctime(&t2));
4069                 correct = True;
4070         }
4071
4072         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4073
4074         /* Check cli_setpathinfo_basic() */
4075         /* Re-create the file. */
4076         status = cli_openx(cli, fname,
4077                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4078         if (!NT_STATUS_IS_OK(status)) {
4079                 printf("Failed to recreate %s (%s)\n",
4080                         fname, nt_errstr(status));
4081                 correct = false;
4082         }
4083         cli_close(cli, fnum);
4084
4085         status = cli_setpathinfo_basic(cli,
4086                                         fname,
4087                                         0, /* create */
4088                                         0, /* access */
4089                                         0, /* write */
4090                                         0, /* change */
4091                                         FILE_ATTRIBUTE_SYSTEM |
4092                                         FILE_ATTRIBUTE_HIDDEN |
4093                                         FILE_ATTRIBUTE_READONLY);
4094         if (!NT_STATUS_IS_OK(status)) {
4095                 printf("cli_setpathinfo_basic failed with %s\n",
4096                         nt_errstr(status));
4097                 correct = false;
4098         }
4099
4100         /* Check attributes are correct. */
4101         correct = check_attributes(cli,
4102                         fname,
4103                         FILE_ATTRIBUTE_SYSTEM |
4104                         FILE_ATTRIBUTE_HIDDEN |
4105                         FILE_ATTRIBUTE_READONLY);
4106         if (correct == false) {
4107                 goto out;
4108         }
4109
4110         /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4111         status = cli_setpathinfo_basic(cli,
4112                                         fname,
4113                                         0, /* create */
4114                                         0, /* access */
4115                                         0, /* write */
4116                                         0, /* change */
4117                                         FILE_ATTRIBUTE_NORMAL);
4118         if (!NT_STATUS_IS_OK(status)) {
4119                 printf("cli_setpathinfo_basic failed with %s\n",
4120                         nt_errstr(status));
4121                 correct = false;
4122         }
4123
4124         /* Check attributes are correct. */
4125         correct = check_attributes(cli,
4126                         fname,
4127                         FILE_ATTRIBUTE_SYSTEM |
4128                         FILE_ATTRIBUTE_HIDDEN |
4129                         FILE_ATTRIBUTE_READONLY);
4130         if (correct == false) {
4131                 goto out;
4132         }
4133
4134         /* Setting to (uint16_t)-1 should also be ignored. */
4135         status = cli_setpathinfo_basic(cli,
4136                                         fname,
4137                                         0, /* create */
4138                                         0, /* access */
4139                                         0, /* write */
4140                                         0, /* change */
4141                                         (uint16_t)-1);
4142         if (!NT_STATUS_IS_OK(status)) {
4143                 printf("cli_setpathinfo_basic failed with %s\n",
4144                         nt_errstr(status));
4145                 correct = false;
4146         }
4147
4148         /* Check attributes are correct. */
4149         correct = check_attributes(cli,
4150                         fname,
4151                         FILE_ATTRIBUTE_SYSTEM |
4152                         FILE_ATTRIBUTE_HIDDEN |
4153                         FILE_ATTRIBUTE_READONLY);
4154         if (correct == false) {
4155                 goto out;
4156         }
4157
4158         /* Setting to 0 should clear them all. */
4159         status = cli_setpathinfo_basic(cli,
4160                                         fname,
4161                                         0, /* create */
4162                                         0, /* access */
4163                                         0, /* write */
4164                                         0, /* change */
4165                                         0);
4166         if (!NT_STATUS_IS_OK(status)) {
4167                 printf("cli_setpathinfo_basic failed with %s\n",
4168                         nt_errstr(status));
4169                 correct = false;
4170         }
4171
4172         /* Check attributes are correct. */
4173         correct = check_attributes(cli,
4174                         fname,
4175                         FILE_ATTRIBUTE_NORMAL);
4176         if (correct == false) {
4177                 goto out;
4178         }
4179
4180   out:
4181
4182         cli_unlink(cli,
4183                 fname,
4184                 FILE_ATTRIBUTE_SYSTEM |
4185                 FILE_ATTRIBUTE_HIDDEN|
4186                 FILE_ATTRIBUTE_READONLY);
4187
4188         if (!torture_close_connection(cli)) {
4189                 correct = False;
4190         }
4191
4192         printf("attrib test finished\n");
4193
4194         return correct;
4195 }
4196
4197
4198 /*
4199   This checks a couple of trans2 calls
4200 */
4201 static bool run_trans2test(int dummy)
4202 {
4203         struct cli_state *cli;
4204         uint16_t fnum;
4205         off_t size;
4206         time_t c_time, a_time, m_time;
4207         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4208         const char *fname = "\\trans2.tst";
4209         const char *dname = "\\trans2";
4210         const char *fname2 = "\\trans2\\trans2.tst";
4211         char *pname;
4212         bool correct = True;
4213         NTSTATUS status;
4214         uint32_t fs_attr;
4215         uint64_t ino;
4216
4217         printf("starting trans2 test\n");
4218
4219         if (!torture_open_connection(&cli, 0)) {
4220                 return False;
4221         }
4222
4223         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4224                 /* Ensure ino is zero, SMB2 gets a real one. */
4225                 ino = 0;
4226         } else {
4227                 /* Ensure ino is -1, SMB1 never gets a real one. */
4228                 ino = (uint64_t)-1;
4229         }
4230
4231         status = cli_get_fs_attr_info(cli, &fs_attr);
4232         if (!NT_STATUS_IS_OK(status)) {
4233                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4234                        nt_errstr(status));
4235                 correct = false;
4236         }
4237
4238         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4239         cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4240         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4241                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4242         if (!NT_STATUS_IS_OK(status)) {
4243                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4244                 correct = False;
4245         }
4246
4247         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4248         if (!NT_STATUS_IS_OK(status)) {
4249                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4250                 correct = False;
4251         }
4252         else if (strcmp(pname, fname)) {
4253                 printf("qfilename gave different name? [%s] [%s]\n",
4254                        fname, pname);
4255                 correct = False;
4256         }
4257
4258         cli_close(cli, fnum);
4259
4260         sleep(2);
4261
4262         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4263         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4264                           &fnum);
4265         if (!NT_STATUS_IS_OK(status)) {
4266                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4267                 return False;
4268         }
4269         cli_close(cli, fnum);
4270
4271         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4272                                 NULL);
4273         if (!NT_STATUS_IS_OK(status)) {
4274                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4275                 correct = False;
4276         } else {
4277                 time_t t = time(NULL);
4278
4279                 if (c_time != m_time) {
4280                         printf("create time=%s", ctime(&c_time));
4281                         printf("modify time=%s", ctime(&m_time));
4282                         printf("This system appears to have sticky create times\n");
4283                 }
4284                 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4285                         printf("access time=%s", ctime(&a_time));
4286                         printf("This system appears to set a midnight access time\n");
4287                         correct = False;
4288                 }
4289
4290                 if (labs(m_time - t) > 60*60*24*7) {
4291                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4292                         correct = False;
4293                 }
4294         }
4295
4296
4297         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4298         cli_openx(cli, fname, 
4299                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4300         cli_close(cli, fnum);
4301         status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
4302                                 &m_time_ts, &size, NULL, &ino);
4303         if (!NT_STATUS_IS_OK(status)) {
4304                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4305                 correct = False;
4306         } else {
4307                 if (w_time_ts.tv_sec < 60*60*24*2) {
4308                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
4309                         printf("This system appears to set a initial 0 write time\n");
4310                         correct = False;
4311                 }
4312                 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4313                         /* SMB2 should always return an inode. */
4314                         if (ino == 0) {
4315                                 printf("SMB2 bad inode (0)\n");
4316                                 correct = false;
4317                         }
4318                 } else {
4319                         /* SMB1 must always return zero here. */
4320                         if (ino != 0) {
4321                                 printf("SMB1 bad inode (!0)\n");
4322                                 correct = false;
4323                         }
4324                 }
4325         }
4326
4327         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4328
4329
4330         /* check if the server updates the directory modification time
4331            when creating a new file */
4332         status = cli_mkdir(cli, dname);
4333         if (!NT_STATUS_IS_OK(status)) {
4334                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4335                 correct = False;
4336         }
4337         sleep(3);
4338         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4339                                 &w_time_ts, &m_time_ts, &size, NULL, NULL);
4340         if (!NT_STATUS_IS_OK(status)) {
4341                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4342                 correct = False;
4343         }
4344
4345         cli_openx(cli, fname2, 
4346                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4347         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4348         cli_close(cli, fnum);
4349         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4350                                 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
4351         if (!NT_STATUS_IS_OK(status)) {
4352                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4353                 correct = False;
4354         } else {
4355                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4356                     == 0) {
4357                         printf("This system does not update directory modification times\n");
4358                         correct = False;
4359                 }
4360         }
4361         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4362         cli_rmdir(cli, dname);
4363
4364         if (!torture_close_connection(cli)) {
4365                 correct = False;
4366         }
4367
4368         printf("trans2 test finished\n");
4369
4370         return correct;
4371 }
4372
4373 /*
4374   This checks new W2K calls.
4375 */
4376
4377 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4378 {
4379         uint8_t *buf = NULL;
4380         uint32_t len;
4381         NTSTATUS status;
4382
4383         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4384                                CLI_BUFFER_SIZE, NULL, &buf, &len);
4385         if (!NT_STATUS_IS_OK(status)) {
4386                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4387                        nt_errstr(status));
4388         } else {
4389                 printf("qfileinfo: level %d, len = %u\n", level, len);
4390                 dump_data(0, (uint8_t *)buf, len);
4391                 printf("\n");
4392         }
4393         TALLOC_FREE(buf);
4394         return status;
4395 }
4396
4397 static bool run_w2ktest(int dummy)
4398 {
4399         struct cli_state *cli;
4400         uint16_t fnum;
4401         const char *fname = "\\w2ktest\\w2k.tst";
4402         int level;
4403         bool correct = True;
4404
4405         printf("starting w2k test\n");
4406
4407         if (!torture_open_connection(&cli, 0)) {
4408                 return False;
4409         }
4410
4411         cli_openx(cli, fname, 
4412                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
4413
4414         for (level = 1004; level < 1040; level++) {
4415                 new_trans(cli, fnum, level);
4416         }
4417
4418         cli_close(cli, fnum);
4419
4420         if (!torture_close_connection(cli)) {
4421                 correct = False;
4422         }
4423
4424         printf("w2k test finished\n");
4425
4426         return correct;
4427 }
4428
4429
4430 /*
4431   this is a harness for some oplock tests
4432  */
4433 static bool run_oplock1(int dummy)
4434 {
4435         struct cli_state *cli1;
4436         const char *fname = "\\lockt1.lck";
4437         uint16_t fnum1;
4438         bool correct = True;
4439         NTSTATUS status;
4440
4441         printf("starting oplock test 1\n");
4442
4443         if (!torture_open_connection(&cli1, 0)) {
4444                 return False;
4445         }
4446
4447         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4448
4449         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4450
4451         cli1->use_oplocks = True;
4452
4453         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4454                           &fnum1);
4455         if (!NT_STATUS_IS_OK(status)) {
4456                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4457                 return False;
4458         }
4459
4460         cli1->use_oplocks = False;
4461
4462         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4463         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4464
4465         status = cli_close(cli1, fnum1);
4466         if (!NT_STATUS_IS_OK(status)) {
4467                 printf("close2 failed (%s)\n", nt_errstr(status));
4468                 return False;
4469         }
4470
4471         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4472         if (!NT_STATUS_IS_OK(status)) {
4473                 printf("unlink failed (%s)\n", nt_errstr(status));
4474                 return False;
4475         }
4476
4477         if (!torture_close_connection(cli1)) {
4478                 correct = False;
4479         }
4480
4481         printf("finished oplock test 1\n");
4482
4483         return correct;
4484 }
4485
4486 static bool run_oplock2(int dummy)
4487 {
4488         struct cli_state *cli1, *cli2;
4489         const char *fname = "\\lockt2.lck";
4490         uint16_t fnum1, fnum2;
4491         int saved_use_oplocks = use_oplocks;
4492         char buf[4];
4493         bool correct = True;
4494         volatile bool *shared_correct;
4495         size_t nread;
4496         NTSTATUS status;
4497
4498         shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4499         *shared_correct = True;
4500
4501         use_level_II_oplocks = True;
4502         use_oplocks = True;
4503
4504         printf("starting oplock test 2\n");
4505
4506         if (!torture_open_connection(&cli1, 0)) {
4507                 use_level_II_oplocks = False;
4508                 use_oplocks = saved_use_oplocks;
4509                 return False;
4510         }
4511
4512         if (!torture_open_connection(&cli2, 1)) {
4513                 use_level_II_oplocks = False;
4514                 use_oplocks = saved_use_oplocks;
4515                 return False;
4516         }
4517
4518         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4519
4520         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4521         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4522
4523         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4524                           &fnum1);
4525         if (!NT_STATUS_IS_OK(status)) {
4526                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4527                 return False;
4528         }
4529
4530         /* Don't need the globals any more. */
4531         use_level_II_oplocks = False;
4532         use_oplocks = saved_use_oplocks;
4533
4534         if (fork() == 0) {
4535                 /* Child code */
4536                 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4537                 if (!NT_STATUS_IS_OK(status)) {
4538                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4539                         *shared_correct = False;
4540                         exit(0);
4541                 }
4542
4543                 sleep(2);
4544
4545                 status = cli_close(cli2, fnum2);
4546                 if (!NT_STATUS_IS_OK(status)) {
4547                         printf("close2 failed (%s)\n", nt_errstr(status));
4548                         *shared_correct = False;
4549                 }
4550
4551                 exit(0);
4552         }
4553
4554         sleep(2);
4555
4556         /* Ensure cli1 processes the break. Empty file should always return 0
4557          * bytes.  */
4558         status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4559         if (!NT_STATUS_IS_OK(status)) {
4560                 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4561                 correct = false;
4562         } else if (nread != 0) {
4563                 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4564                       (unsigned long)nread, 0);
4565                 correct = false;
4566         }
4567
4568         /* Should now be at level II. */
4569         /* Test if sending a write locks causes a break to none. */
4570         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4571         if (!NT_STATUS_IS_OK(status)) {
4572                 printf("lock failed (%s)\n", nt_errstr(status));
4573                 correct = False;
4574         }
4575
4576         cli_unlock(cli1, fnum1, 0, 4);
4577
4578         sleep(2);
4579
4580         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4581         if (!NT_STATUS_IS_OK(status)) {
4582                 printf("lock failed (%s)\n", nt_errstr(status));
4583                 correct = False;
4584         }
4585
4586         cli_unlock(cli1, fnum1, 0, 4);
4587
4588         sleep(2);
4589
4590         cli_read(cli1, fnum1, buf, 0, 4, NULL);
4591
4592         status = cli_close(cli1, fnum1);
4593         if (!NT_STATUS_IS_OK(status)) {
4594                 printf("close1 failed (%s)\n", nt_errstr(status));
4595                 correct = False;
4596         }
4597
4598         sleep(4);
4599
4600         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4601         if (!NT_STATUS_IS_OK(status)) {
4602                 printf("unlink failed (%s)\n", nt_errstr(status));
4603                 correct = False;
4604         }
4605
4606         if (!torture_close_connection(cli1)) {
4607                 correct = False;
4608         }
4609
4610         if (!*shared_correct) {
4611                 correct = False;
4612         }
4613
4614         printf("finished oplock test 2\n");
4615
4616         return correct;
4617 }
4618
4619 struct oplock4_state {
4620         struct tevent_context *ev;
4621         struct cli_state *cli;
4622         bool *got_break;
4623         uint16_t *fnum2;
4624 };
4625
4626 static void oplock4_got_break(struct tevent_req *req);
4627 static void oplock4_got_open(struct tevent_req *req);
4628
4629 static bool run_oplock4(int dummy)
4630 {
4631         struct tevent_context *ev;
4632         struct cli_state *cli1, *cli2;
4633         struct tevent_req *oplock_req, *open_req;
4634         const char *fname = "\\lockt4.lck";
4635         const char *fname_ln = "\\lockt4_ln.lck";
4636         uint16_t fnum1, fnum2;
4637         int saved_use_oplocks = use_oplocks;
4638         NTSTATUS status;
4639         bool correct = true;
4640
4641         bool got_break;
4642
4643         struct oplock4_state *state;
4644
4645         printf("starting oplock test 4\n");
4646
4647         if (!torture_open_connection(&cli1, 0)) {
4648                 use_level_II_oplocks = false;
4649                 use_oplocks = saved_use_oplocks;
4650                 return false;
4651         }
4652
4653         if (!torture_open_connection(&cli2, 1)) {
4654                 use_level_II_oplocks = false;
4655                 use_oplocks = saved_use_oplocks;
4656                 return false;
4657         }
4658
4659         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4660         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4661
4662         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4663         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4664
4665         /* Create the file. */
4666         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4667                           &fnum1);
4668         if (!NT_STATUS_IS_OK(status)) {
4669                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4670                 return false;
4671         }
4672
4673         status = cli_close(cli1, fnum1);
4674         if (!NT_STATUS_IS_OK(status)) {
4675                 printf("close1 failed (%s)\n", nt_errstr(status));
4676                 return false;
4677         }
4678
4679         /* Now create a hardlink. */
4680         status = cli_hardlink(cli1, fname, fname_ln);
4681         if (!NT_STATUS_IS_OK(status)) {
4682                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4683                 return false;
4684         }
4685
4686         /* Prove that opening hardlinks cause deny modes to conflict. */
4687         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4688         if (!NT_STATUS_IS_OK(status)) {
4689                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4690                 return false;
4691         }
4692
4693         status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4694         if (NT_STATUS_IS_OK(status)) {
4695                 printf("open of %s succeeded - should fail with sharing violation.\n",
4696                         fname_ln);
4697                 return false;
4698         }
4699
4700         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4701                 printf("open of %s should fail with sharing violation. Got %s\n",
4702                         fname_ln, nt_errstr(status));
4703                 return false;
4704         }
4705
4706         status = cli_close(cli1, fnum1);
4707         if (!NT_STATUS_IS_OK(status)) {
4708                 printf("close1 failed (%s)\n", nt_errstr(status));
4709                 return false;
4710         }
4711
4712         cli1->use_oplocks = true;
4713         cli2->use_oplocks = true;
4714
4715         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4716         if (!NT_STATUS_IS_OK(status)) {
4717                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4718                 return false;
4719         }
4720
4721         ev = samba_tevent_context_init(talloc_tos());
4722         if (ev == NULL) {
4723                 printf("tevent_context_init failed\n");
4724                 return false;
4725         }
4726
4727         state = talloc(ev, struct oplock4_state);
4728         if (state == NULL) {
4729                 printf("talloc failed\n");
4730                 return false;
4731         }
4732         state->ev = ev;
4733         state->cli = cli1;
4734         state->got_break = &got_break;
4735         state->fnum2 = &fnum2;
4736
4737         oplock_req = cli_smb_oplock_break_waiter_send(
4738                 talloc_tos(), ev, cli1);
4739         if (oplock_req == NULL) {
4740                 printf("cli_smb_oplock_break_waiter_send failed\n");
4741                 return false;
4742         }
4743         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
4744
4745         open_req = cli_openx_send(
4746                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
4747         if (open_req == NULL) {
4748                 printf("cli_openx_send failed\n");
4749                 return false;
4750         }
4751         tevent_req_set_callback(open_req, oplock4_got_open, state);
4752
4753         got_break = false;
4754         fnum2 = 0xffff;
4755
4756         while (!got_break || fnum2 == 0xffff) {
4757                 int ret;
4758                 ret = tevent_loop_once(ev);
4759                 if (ret == -1) {
4760                         printf("tevent_loop_once failed: %s\n",
4761                                strerror(errno));
4762                         return false;
4763                 }
4764         }
4765
4766         status = cli_close(cli2, fnum2);
4767         if (!NT_STATUS_IS_OK(status)) {
4768                 printf("close2 failed (%s)\n", nt_errstr(status));
4769                 correct = false;
4770         }
4771
4772         status = cli_close(cli1, fnum1);
4773         if (!NT_STATUS_IS_OK(status)) {
4774                 printf("close1 failed (%s)\n", nt_errstr(status));
4775                 correct = false;
4776         }
4777
4778         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4779         if (!NT_STATUS_IS_OK(status)) {
4780                 printf("unlink failed (%s)\n", nt_errstr(status));
4781                 correct = false;
4782         }
4783
4784         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4785         if (!NT_STATUS_IS_OK(status)) {
4786                 printf("unlink failed (%s)\n", nt_errstr(status));
4787                 correct = false;
4788         }
4789
4790         if (!torture_close_connection(cli1)) {
4791                 correct = false;
4792         }
4793
4794         if (!got_break) {
4795                 correct = false;
4796         }
4797
4798         printf("finished oplock test 4\n");
4799
4800         return correct;
4801 }
4802
4803 static void oplock4_got_break(struct tevent_req *req)
4804 {
4805         struct oplock4_state *state = tevent_req_callback_data(
4806                 req, struct oplock4_state);
4807         uint16_t fnum;
4808         uint8_t level;
4809         NTSTATUS status;
4810
4811         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
4812         TALLOC_FREE(req);
4813         if (!NT_STATUS_IS_OK(status)) {
4814                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
4815                        nt_errstr(status));
4816                 return;
4817         }
4818         *state->got_break = true;
4819
4820         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
4821                                   NO_OPLOCK);
4822         if (req == NULL) {
4823                 printf("cli_oplock_ack_send failed\n");
4824                 return;
4825         }
4826 }
4827
4828 static void oplock4_got_open(struct tevent_req *req)
4829 {
4830         struct oplock4_state *state = tevent_req_callback_data(
4831                 req, struct oplock4_state);
4832         NTSTATUS status;
4833
4834         status = cli_openx_recv(req, state->fnum2);
4835         if (!NT_STATUS_IS_OK(status)) {
4836                 printf("cli_openx_recv returned %s\n", nt_errstr(status));
4837                 *state->fnum2 = 0xffff;
4838         }
4839 }
4840
4841 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
4842
4843 struct oplock5_state {
4844         int pipe_down_fd;
4845 };
4846
4847 /*
4848  * Async open the file that has a kernel oplock, do an echo to get
4849  * that 100% across, close the file to signal to the child fd that the
4850  * oplock can be dropped, wait for the open reply.
4851  */
4852
4853 static void oplock5_opened(struct tevent_req *subreq);
4854 static void oplock5_pong(struct tevent_req *subreq);
4855 static void oplock5_timedout(struct tevent_req *subreq);
4856
4857 static struct tevent_req *oplock5_send(
4858         TALLOC_CTX *mem_ctx,
4859         struct tevent_context *ev,
4860         struct cli_state *cli,
4861         const char *fname,
4862         int pipe_down_fd)
4863 {
4864         struct tevent_req *req = NULL, *subreq = NULL;
4865         struct oplock5_state *state = NULL;
4866         static uint8_t data = 0;
4867
4868         req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
4869         if (req == NULL) {
4870                 return NULL;
4871         }
4872         state->pipe_down_fd = pipe_down_fd;
4873
4874         subreq = cli_ntcreate_send(
4875                 state,
4876                 ev,
4877                 cli,
4878                 fname,
4879                 0,                      /* CreatFlags */
4880                 SEC_FILE_READ_DATA,    /* DesiredAccess */
4881                 FILE_ATTRIBUTE_NORMAL,  /* FileAttributes */
4882                 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
4883                 FILE_OPEN,               /* CreateDisposition */
4884                 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
4885                 0,                       /* Impersonation */
4886                 0);                      /* SecurityFlags */
4887         if (tevent_req_nomem(subreq, req)) {
4888                 return tevent_req_post(req, ev);
4889         }
4890         tevent_req_set_callback(subreq, oplock5_opened, req);
4891
4892         subreq = cli_echo_send(
4893                 state,
4894                 ev,
4895                 cli,
4896                 1,
4897                 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
4898         if (tevent_req_nomem(subreq, req)) {
4899                 return tevent_req_post(req, ev);
4900         }
4901         tevent_req_set_callback(subreq, oplock5_pong, req);
4902
4903         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
4904         if (tevent_req_nomem(subreq, req)) {
4905                 return tevent_req_post(req, ev);
4906         }
4907         tevent_req_set_callback(subreq, oplock5_timedout, req);
4908
4909         return req;
4910 }
4911
4912 static void oplock5_opened(struct tevent_req *subreq)
4913 {
4914         struct tevent_req *req = tevent_req_callback_data(
4915                 subreq, struct tevent_req);
4916         NTSTATUS status;
4917         uint16_t fnum;
4918
4919         status = cli_ntcreate_recv(subreq, &fnum, NULL);
4920         TALLOC_FREE(subreq);
4921         if (tevent_req_nterror(req, status)) {
4922                 return;
4923         }
4924         tevent_req_done(req);
4925 }
4926
4927 static void oplock5_pong(struct tevent_req *subreq)
4928 {
4929         struct tevent_req *req = tevent_req_callback_data(
4930                 subreq, struct tevent_req);
4931         struct oplock5_state *state = tevent_req_data(
4932                 req, struct oplock5_state);
4933         NTSTATUS status;
4934
4935         status = cli_echo_recv(subreq);
4936         TALLOC_FREE(subreq);
4937         if (tevent_req_nterror(req, status)) {
4938                 return;
4939         }
4940
4941         close(state->pipe_down_fd);
4942 }
4943
4944 static void oplock5_timedout(struct tevent_req *subreq)
4945 {
4946         struct tevent_req *req = tevent_req_callback_data(
4947                 subreq, struct tevent_req);
4948         bool ok;
4949
4950         ok = tevent_wakeup_recv(subreq);
4951         TALLOC_FREE(subreq);
4952         if (!ok) {
4953                 tevent_req_oom(req);
4954                 return;
4955         }
4956         tevent_req_nterror(req, NT_STATUS_TIMEOUT);
4957 }
4958
4959 static NTSTATUS oplock5_recv(struct tevent_req *req)
4960 {
4961         return tevent_req_simple_recv_ntstatus(req);
4962 }
4963
4964 static bool run_oplock5(int dummy)
4965 {
4966         struct tevent_context *ev = NULL;
4967         struct tevent_req *req = NULL;
4968         struct cli_state *cli = NULL;
4969         const char *fname = "oplock5.txt";
4970         int pipe_down[2], pipe_up[2];
4971         pid_t child_pid;
4972         uint8_t c = '\0';
4973         NTSTATUS status;
4974         int ret;
4975         bool ok;
4976
4977         printf("starting oplock5\n");
4978
4979         if (local_path == NULL) {
4980                 d_fprintf(stderr, "oplock5 must be given a local path via "
4981                           "-l <localpath>\n");
4982                 return false;
4983         }
4984
4985         ret = pipe(pipe_down);
4986         if (ret == -1) {
4987                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
4988                 return false;
4989         }
4990         ret = pipe(pipe_up);
4991         if (ret == -1) {
4992                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
4993                 return false;
4994         }
4995
4996         child_pid = fork();
4997         if (child_pid == -1) {
4998                 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
4999                 return false;
5000         }
5001
5002         if (child_pid == 0) {
5003                 char *local_file = NULL;
5004                 int fd;
5005
5006                 close(pipe_down[1]);
5007                 close(pipe_up[0]);
5008
5009                 local_file = talloc_asprintf(
5010                         talloc_tos(), "%s/%s", local_path, fname);
5011                 if (local_file == 0) {
5012                         c = 1;
5013                         goto do_write;
5014                 }
5015                 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5016                 if (fd == -1) {
5017                         d_fprintf(stderr,
5018                                   "open(%s) in child failed: %s\n",
5019                                   local_file,
5020                                   strerror(errno));
5021                         c = 2;
5022                         goto do_write;
5023                 }
5024
5025                 signal(SIGIO, SIG_IGN);
5026
5027                 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5028                 if (ret == -1) {
5029                         d_fprintf(stderr,
5030                                   "SETLEASE in child failed: %s\n",
5031                                   strerror(errno));
5032                         c = 3;
5033                         goto do_write;
5034                 }
5035
5036         do_write:
5037                 ret = sys_write(pipe_up[1], &c, sizeof(c));
5038                 if (ret == -1) {
5039                         d_fprintf(stderr,
5040                                   "sys_write failed: %s\n",
5041                                   strerror(errno));
5042                         exit(4);
5043                 }
5044                 ret = sys_read(pipe_down[0], &c, sizeof(c));
5045                 if (ret == -1) {
5046                         d_fprintf(stderr,
5047                                   "sys_read failed: %s\n",
5048                                   strerror(errno));
5049                         exit(5);
5050                 }
5051                 exit(0);
5052         }
5053
5054         close(pipe_up[1]);
5055         close(pipe_down[0]);
5056
5057         ret = sys_read(pipe_up[0], &c, sizeof(c));
5058         if (ret != 1) {
5059                 d_fprintf(stderr,
5060                           "sys_read failed: %s\n",
5061                           strerror(errno));
5062                 return false;
5063         }
5064         if (c != 0) {
5065                 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5066                 return false;
5067         }
5068
5069         ok = torture_open_connection(&cli, 0);
5070         if (!ok) {
5071                 d_fprintf(stderr, "torture_open_connection failed\n");
5072                 return false;
5073         }
5074
5075         ev = samba_tevent_context_init(talloc_tos());
5076         if (ev == NULL) {
5077                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5078                 return false;
5079         }
5080
5081         req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5082         if (req == NULL) {
5083                 d_fprintf(stderr, "oplock5_send failed\n");
5084                 return false;
5085         }
5086
5087         ok = tevent_req_poll_ntstatus(req, ev, &status);
5088         if (!ok) {
5089                 d_fprintf(stderr,
5090                           "tevent_req_poll_ntstatus failed: %s\n",
5091                           nt_errstr(status));
5092                 return false;
5093         }
5094
5095         status = oplock5_recv(req);
5096         TALLOC_FREE(req);
5097         if (!NT_STATUS_IS_OK(status)) {
5098                 d_fprintf(stderr,
5099                           "oplock5 failed: %s\n",
5100                           nt_errstr(status));
5101                 return false;
5102         }
5103
5104         return true;
5105 }
5106
5107 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5108
5109 /*
5110   Test delete on close semantics.
5111  */
5112 static bool run_deletetest(int dummy)
5113 {
5114         struct cli_state *cli1 = NULL;
5115         struct cli_state *cli2 = NULL;
5116         const char *fname = "\\delete.file";
5117         uint16_t fnum1 = (uint16_t)-1;
5118         uint16_t fnum2 = (uint16_t)-1;
5119         bool correct = false;
5120         NTSTATUS status;
5121
5122         printf("starting delete test\n");
5123
5124         if (!torture_open_connection(&cli1, 0)) {
5125                 return False;
5126         }
5127
5128         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5129
5130         /* Test 1 - this should delete the file on close. */
5131
5132         cli_setatr(cli1, fname, 0, 0);
5133         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5134
5135         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5136                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5137                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5138         if (!NT_STATUS_IS_OK(status)) {
5139                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5140                 goto fail;
5141         }
5142
5143         status = cli_close(cli1, fnum1);
5144         if (!NT_STATUS_IS_OK(status)) {
5145                 printf("[1] close failed (%s)\n", nt_errstr(status));
5146                 goto fail;
5147         }
5148
5149         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5150         if (NT_STATUS_IS_OK(status)) {
5151                 printf("[1] open of %s succeeded (should fail)\n", fname);
5152                 goto fail;
5153         }
5154
5155         printf("first delete on close test succeeded.\n");
5156
5157         /* Test 2 - this should delete the file on close. */
5158
5159         cli_setatr(cli1, fname, 0, 0);
5160         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5161
5162         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5163                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5164                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5165         if (!NT_STATUS_IS_OK(status)) {
5166                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5167                 goto fail;
5168         }
5169
5170         status = cli_nt_delete_on_close(cli1, fnum1, true);
5171         if (!NT_STATUS_IS_OK(status)) {
5172                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5173                 goto fail;
5174         }
5175
5176         status = cli_close(cli1, fnum1);
5177         if (!NT_STATUS_IS_OK(status)) {
5178                 printf("[2] close failed (%s)\n", nt_errstr(status));
5179                 goto fail;
5180         }
5181
5182         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5183         if (NT_STATUS_IS_OK(status)) {
5184                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5185                 status = cli_close(cli1, fnum1);
5186                 if (!NT_STATUS_IS_OK(status)) {
5187                         printf("[2] close failed (%s)\n", nt_errstr(status));
5188                 }
5189                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5190                 goto fail;
5191         }
5192
5193         printf("second delete on close test succeeded.\n");
5194
5195         /* Test 3 - ... */
5196         cli_setatr(cli1, fname, 0, 0);
5197         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5198
5199         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5200                               FILE_ATTRIBUTE_NORMAL,
5201                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5202                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5203         if (!NT_STATUS_IS_OK(status)) {
5204                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5205                 goto fail;
5206         }
5207
5208         /* This should fail with a sharing violation - open for delete is only compatible
5209            with SHARE_DELETE. */
5210
5211         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5212                               FILE_ATTRIBUTE_NORMAL,
5213                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5214                               FILE_OPEN, 0, 0, &fnum2, NULL);
5215         if (NT_STATUS_IS_OK(status)) {
5216                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
5217                 goto fail;
5218         }
5219
5220         /* This should succeed. */
5221         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5222                              FILE_ATTRIBUTE_NORMAL,
5223                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5224                              FILE_OPEN, 0, 0, &fnum2, NULL);
5225         if (!NT_STATUS_IS_OK(status)) {
5226                 printf("[3] open  - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5227                 goto fail;
5228         }
5229
5230         status = cli_nt_delete_on_close(cli1, fnum1, true);
5231         if (!NT_STATUS_IS_OK(status)) {
5232                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5233                 goto fail;
5234         }
5235
5236         status = cli_close(cli1, fnum1);
5237         if (!NT_STATUS_IS_OK(status)) {
5238                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5239                 goto fail;
5240         }
5241
5242         status = cli_close(cli1, fnum2);
5243         if (!NT_STATUS_IS_OK(status)) {
5244                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5245                 goto fail;
5246         }
5247
5248         /* This should fail - file should no longer be there. */
5249
5250         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5251         if (NT_STATUS_IS_OK(status)) {
5252                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5253                 status = cli_close(cli1, fnum1);
5254                 if (!NT_STATUS_IS_OK(status)) {
5255                         printf("[3] close failed (%s)\n", nt_errstr(status));
5256                 }
5257                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5258                 goto fail;
5259         }
5260
5261         printf("third delete on close test succeeded.\n");
5262
5263         /* Test 4 ... */
5264         cli_setatr(cli1, fname, 0, 0);
5265         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5266
5267         status = cli_ntcreate(cli1, fname, 0,
5268                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5269                               FILE_ATTRIBUTE_NORMAL,
5270                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5271                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5272         if (!NT_STATUS_IS_OK(status)) {
5273                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5274                 goto fail;
5275         }
5276
5277         /* This should succeed. */
5278         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5279                              FILE_ATTRIBUTE_NORMAL,
5280                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5281                              FILE_OPEN, 0, 0, &fnum2, NULL);
5282         if (!NT_STATUS_IS_OK(status)) {
5283                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5284                 goto fail;
5285         }
5286
5287         status = cli_close(cli1, fnum2);
5288         if (!NT_STATUS_IS_OK(status)) {
5289                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5290                 goto fail;
5291         }
5292
5293         status = cli_nt_delete_on_close(cli1, fnum1, true);
5294         if (!NT_STATUS_IS_OK(status)) {
5295                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5296                 goto fail;
5297         }
5298
5299         /* This should fail - no more opens once delete on close set. */
5300         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5301                               FILE_ATTRIBUTE_NORMAL,
5302                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5303                               FILE_OPEN, 0, 0, &fnum2, NULL);
5304         if (NT_STATUS_IS_OK(status)) {
5305                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
5306                 goto fail;
5307         }
5308
5309         status = cli_close(cli1, fnum1);
5310         if (!NT_STATUS_IS_OK(status)) {
5311                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5312                 goto fail;
5313         }
5314
5315         printf("fourth delete on close test succeeded.\n");
5316
5317         /* Test 5 ... */
5318         cli_setatr(cli1, fname, 0, 0);
5319         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5320
5321         status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5322         if (!NT_STATUS_IS_OK(status)) {
5323                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5324                 goto fail;
5325         }
5326
5327         /* This should fail - only allowed on NT opens with DELETE access. */
5328
5329         status = cli_nt_delete_on_close(cli1, fnum1, true);
5330         if (NT_STATUS_IS_OK(status)) {
5331                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5332                 goto fail;
5333         }
5334
5335         status = cli_close(cli1, fnum1);
5336         if (!NT_STATUS_IS_OK(status)) {
5337                 printf("[5] close failed (%s)\n", nt_errstr(status));
5338                 goto fail;
5339         }
5340
5341         printf("fifth delete on close test succeeded.\n");
5342
5343         /* Test 6 ... */
5344         cli_setatr(cli1, fname, 0, 0);
5345         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5346
5347         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5348                              FILE_ATTRIBUTE_NORMAL,
5349                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5350                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5351         if (!NT_STATUS_IS_OK(status)) {
5352                 printf("[6] open of %s failed (%s)\n", fname,
5353                        nt_errstr(status));
5354                 goto fail;
5355         }
5356
5357         /* This should fail - only allowed on NT opens with DELETE access. */
5358
5359         status = cli_nt_delete_on_close(cli1, fnum1, true);
5360         if (NT_STATUS_IS_OK(status)) {
5361                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5362                 goto fail;
5363         }
5364
5365         status = cli_close(cli1, fnum1);
5366         if (!NT_STATUS_IS_OK(status)) {
5367                 printf("[6] close failed (%s)\n", nt_errstr(status));
5368                 goto fail;
5369         }
5370
5371         printf("sixth delete on close test succeeded.\n");
5372
5373         /* Test 7 ... */
5374         cli_setatr(cli1, fname, 0, 0);
5375         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5376
5377         status = cli_ntcreate(cli1, fname, 0,
5378                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5379                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5380                               0, 0, &fnum1, NULL);
5381         if (!NT_STATUS_IS_OK(status)) {
5382                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5383                 goto fail;
5384         }
5385
5386         status = cli_nt_delete_on_close(cli1, fnum1, true);
5387         if (!NT_STATUS_IS_OK(status)) {
5388                 printf("[7] setting delete_on_close on file failed !\n");
5389                 goto fail;
5390         }
5391
5392         status = cli_nt_delete_on_close(cli1, fnum1, false);
5393         if (!NT_STATUS_IS_OK(status)) {
5394                 printf("[7] unsetting delete_on_close on file failed !\n");
5395                 goto fail;
5396         }
5397
5398         status = cli_close(cli1, fnum1);
5399         if (!NT_STATUS_IS_OK(status)) {
5400                 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5401                 goto fail;
5402         }
5403
5404         /* This next open should succeed - we reset the flag. */
5405         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5406         if (!NT_STATUS_IS_OK(status)) {
5407                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5408                 goto fail;
5409         }
5410
5411         status = cli_close(cli1, fnum1);
5412         if (!NT_STATUS_IS_OK(status)) {
5413                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5414                 goto fail;
5415         }
5416
5417         printf("seventh delete on close test succeeded.\n");
5418
5419         /* Test 8 ... */
5420         cli_setatr(cli1, fname, 0, 0);
5421         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5422
5423         if (!torture_open_connection(&cli2, 1)) {
5424                 printf("[8] failed to open second connection.\n");
5425                 goto fail;
5426         }
5427
5428         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5429
5430         status = cli_ntcreate(cli1, fname, 0,
5431                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5432                              FILE_ATTRIBUTE_NORMAL,
5433                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5434                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5435         if (!NT_STATUS_IS_OK(status)) {
5436                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5437                 goto fail;
5438         }
5439
5440         status = cli_ntcreate(cli2, fname, 0,
5441                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5442                              FILE_ATTRIBUTE_NORMAL,
5443                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5444                              FILE_OPEN, 0, 0, &fnum2, NULL);
5445         if (!NT_STATUS_IS_OK(status)) {
5446                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5447                 goto fail;
5448         }
5449
5450         status = cli_nt_delete_on_close(cli1, fnum1, true);
5451         if (!NT_STATUS_IS_OK(status)) {
5452                 printf("[8] setting delete_on_close on file failed !\n");
5453                 goto fail;
5454         }
5455
5456         status = cli_close(cli1, fnum1);
5457         if (!NT_STATUS_IS_OK(status)) {
5458                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5459                 goto fail;
5460         }
5461
5462         status = cli_close(cli2, fnum2);
5463         if (!NT_STATUS_IS_OK(status)) {
5464                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5465                 goto fail;
5466         }
5467
5468         /* This should fail.. */
5469         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5470         if (NT_STATUS_IS_OK(status)) {
5471                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5472                 goto fail;
5473         }
5474
5475         printf("eighth delete on close test succeeded.\n");
5476
5477         /* Test 9 ... */
5478
5479         /* This should fail - we need to set DELETE_ACCESS. */
5480         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5481                               FILE_ATTRIBUTE_NORMAL,
5482                               FILE_SHARE_NONE,
5483                               FILE_OVERWRITE_IF,
5484                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5485         if (NT_STATUS_IS_OK(status)) {
5486                 printf("[9] open of %s succeeded should have failed!\n", fname);
5487                 goto fail;
5488         }
5489
5490         printf("ninth delete on close test succeeded.\n");
5491
5492         /* Test 10 ... */
5493
5494         status = cli_ntcreate(cli1, fname, 0,
5495                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5496                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5497                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5498                              0, &fnum1, NULL);
5499         if (!NT_STATUS_IS_OK(status)) {
5500                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5501                 goto fail;
5502         }
5503
5504         /* This should delete the file. */
5505         status = cli_close(cli1, fnum1);
5506         if (!NT_STATUS_IS_OK(status)) {
5507                 printf("[10] close failed (%s)\n", nt_errstr(status));
5508                 goto fail;
5509         }
5510
5511         /* This should fail.. */
5512         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5513         if (NT_STATUS_IS_OK(status)) {
5514                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5515                 goto fail;
5516         }
5517
5518         printf("tenth delete on close test succeeded.\n");
5519
5520         /* Test 11 ... */
5521
5522         cli_setatr(cli1, fname, 0, 0);
5523         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5524
5525         /* Can we open a read-only file with delete access? */
5526
5527         /* Create a readonly file. */
5528         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5529                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5530                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5531         if (!NT_STATUS_IS_OK(status)) {
5532                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5533                 goto fail;
5534         }
5535
5536         status = cli_close(cli1, fnum1);
5537         if (!NT_STATUS_IS_OK(status)) {
5538                 printf("[11] close failed (%s)\n", nt_errstr(status));
5539                 goto fail;
5540         }
5541
5542         /* Now try open for delete access. */
5543         status = cli_ntcreate(cli1, fname, 0,
5544                              FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5545                              0,
5546                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5547                              FILE_OPEN, 0, 0, &fnum1, NULL);
5548         if (!NT_STATUS_IS_OK(status)) {
5549                 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5550                 goto fail;
5551         }
5552
5553         cli_close(cli1, fnum1);
5554
5555         printf("eleventh delete on close test succeeded.\n");
5556
5557         /*
5558          * Test 12
5559          * like test 4 but with initial delete on close
5560          */
5561
5562         cli_setatr(cli1, fname, 0, 0);
5563         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5564
5565         status = cli_ntcreate(cli1, fname, 0,
5566                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5567                               FILE_ATTRIBUTE_NORMAL,
5568                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5569                               FILE_OVERWRITE_IF,
5570                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5571         if (!NT_STATUS_IS_OK(status)) {
5572                 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5573                 goto fail;
5574         }
5575
5576         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5577                               FILE_ATTRIBUTE_NORMAL,
5578                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5579                               FILE_OPEN, 0, 0, &fnum2, NULL);
5580         if (!NT_STATUS_IS_OK(status)) {
5581                 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5582                 goto fail;
5583         }
5584
5585         status = cli_close(cli1, fnum2);
5586         if (!NT_STATUS_IS_OK(status)) {
5587                 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5588                 goto fail;
5589         }
5590
5591         status = cli_nt_delete_on_close(cli1, fnum1, true);
5592         if (!NT_STATUS_IS_OK(status)) {
5593                 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5594                 goto fail;
5595         }
5596
5597         /* This should fail - no more opens once delete on close set. */
5598         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5599                               FILE_ATTRIBUTE_NORMAL,
5600                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5601                               FILE_OPEN, 0, 0, &fnum2, NULL);
5602         if (NT_STATUS_IS_OK(status)) {
5603                 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5604                 goto fail;
5605         }
5606
5607         status = cli_nt_delete_on_close(cli1, fnum1, false);
5608         if (!NT_STATUS_IS_OK(status)) {
5609                 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5610                 goto fail;
5611         }
5612
5613         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5614                               FILE_ATTRIBUTE_NORMAL,
5615                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5616                               FILE_OPEN, 0, 0, &fnum2, NULL);
5617         if (!NT_STATUS_IS_OK(status)) {
5618                 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5619                 goto fail;
5620         }
5621
5622         status = cli_close(cli1, fnum2);
5623         if (!NT_STATUS_IS_OK(status)) {
5624                 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5625                 goto fail;
5626         }
5627
5628         status = cli_close(cli1, fnum1);
5629         if (!NT_STATUS_IS_OK(status)) {
5630                 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5631                 goto fail;
5632         }
5633
5634         /*
5635          * setting delete on close on the handle does
5636          * not unset the initial delete on close...
5637          */
5638         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5639                               FILE_ATTRIBUTE_NORMAL,
5640                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5641                               FILE_OPEN, 0, 0, &fnum2, NULL);
5642         if (NT_STATUS_IS_OK(status)) {
5643                 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5644                 goto fail;
5645         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5646                 printf("ntcreate returned %s, expected "
5647                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5648                        nt_errstr(status));
5649                 goto fail;
5650         }
5651
5652         printf("twelfth delete on close test succeeded.\n");
5653
5654
5655         printf("finished delete test\n");
5656
5657         correct = true;
5658
5659   fail:
5660         /* FIXME: This will crash if we aborted before cli2 got
5661          * intialized, because these functions don't handle
5662          * uninitialized connections. */
5663
5664         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5665         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5666         cli_setatr(cli1, fname, 0, 0);
5667         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5668
5669         if (cli1 && !torture_close_connection(cli1)) {
5670                 correct = False;
5671         }
5672         if (cli2 && !torture_close_connection(cli2)) {
5673                 correct = False;
5674         }
5675         return correct;
5676 }
5677
5678 struct delete_stream_state {
5679         bool closed;
5680 };
5681
5682 static void delete_stream_unlinked(struct tevent_req *subreq);
5683 static void delete_stream_closed(struct tevent_req *subreq);
5684
5685 static struct tevent_req *delete_stream_send(
5686         TALLOC_CTX *mem_ctx,
5687         struct tevent_context *ev,
5688         struct cli_state *cli,
5689         const char *base_fname,
5690         uint16_t stream_fnum)
5691 {
5692         struct tevent_req *req = NULL, *subreq = NULL;
5693         struct delete_stream_state *state = NULL;
5694
5695         req = tevent_req_create(
5696                 mem_ctx, &state, struct delete_stream_state);
5697         if (req == NULL) {
5698                 return NULL;
5699         }
5700
5701         subreq = cli_unlink_send(
5702                 state,
5703                 ev,
5704                 cli,
5705                 base_fname,
5706                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5707         if (tevent_req_nomem(subreq, req)) {
5708                 return tevent_req_post(req, ev);
5709         }
5710         tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5711
5712         subreq = cli_close_send(state, ev, cli, stream_fnum);
5713         if (tevent_req_nomem(subreq, req)) {
5714                 return tevent_req_post(req, ev);
5715         }
5716         tevent_req_set_callback(subreq, delete_stream_closed, req);
5717
5718         return req;
5719 }
5720
5721 static void delete_stream_unlinked(struct tevent_req *subreq)
5722 {
5723         struct tevent_req *req = tevent_req_callback_data(
5724                 subreq, struct tevent_req);
5725         struct delete_stream_state *state = tevent_req_data(
5726                 req, struct delete_stream_state);
5727         NTSTATUS status;
5728
5729         status = cli_unlink_recv(subreq);
5730         TALLOC_FREE(subreq);
5731         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5732                 printf("cli_unlink returned %s\n",
5733                        nt_errstr(status));
5734                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5735                 return;
5736         }
5737         if (!state->closed) {
5738                 /* close reply should have come in first */
5739                 printf("Not closed\n");
5740                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5741                 return;
5742         }
5743         tevent_req_done(req);
5744 }
5745
5746 static void delete_stream_closed(struct tevent_req *subreq)
5747 {
5748         struct tevent_req *req = tevent_req_callback_data(
5749                 subreq, struct tevent_req);
5750         struct delete_stream_state *state = tevent_req_data(
5751                 req, struct delete_stream_state);
5752         NTSTATUS status;
5753
5754         status = cli_close_recv(subreq);
5755         TALLOC_FREE(subreq);
5756         if (tevent_req_nterror(req, status)) {
5757                 return;
5758         }
5759         /* also waiting for the unlink to come back */
5760         state->closed = true;
5761 }
5762
5763 static NTSTATUS delete_stream_recv(struct tevent_req *req)
5764 {
5765         return tevent_req_simple_recv_ntstatus(req);
5766 }
5767
5768 static bool run_delete_stream(int dummy)
5769 {
5770         struct tevent_context *ev = NULL;
5771         struct tevent_req *req = NULL;
5772         struct cli_state *cli = NULL;
5773         const char fname[] = "delete_stream";
5774         const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
5775         uint16_t fnum1, fnum2;
5776         NTSTATUS status;
5777         bool ok;
5778
5779         printf("Starting stream delete test\n");
5780
5781         ok = torture_open_connection(&cli, 0);
5782         if (!ok) {
5783                 return false;
5784         }
5785
5786         cli_setatr(cli, fname, 0, 0);
5787         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5788
5789         /* Create the file. */
5790         status = cli_ntcreate(
5791                 cli,
5792                 fname,
5793                 0,
5794                 READ_CONTROL_ACCESS,
5795                 0,
5796                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5797                 FILE_CREATE,
5798                 0x0,
5799                 0x0,
5800                 &fnum1,
5801                 NULL);
5802         if (!NT_STATUS_IS_OK(status)) {
5803                 d_fprintf(stderr,
5804                           "cli_ntcreate of %s failed (%s)\n",
5805                           fname,
5806                           nt_errstr(status));
5807                 return false;
5808         }
5809         status = cli_close(cli, fnum1);
5810         if (!NT_STATUS_IS_OK(status)) {
5811                 d_fprintf(stderr,
5812                           "cli_close of %s failed (%s)\n",
5813                           fname,
5814                           nt_errstr(status));
5815                 return false;
5816         }
5817
5818         /* Now create the stream. */
5819         status = cli_ntcreate(
5820                 cli,
5821                 fname_stream,
5822                 0,
5823                 FILE_WRITE_DATA,
5824                 0,
5825                 FILE_SHARE_READ|FILE_SHARE_WRITE,
5826                 FILE_CREATE,
5827                 0x0,
5828                 0x0,
5829                 &fnum1,
5830                 NULL);
5831
5832         if (!NT_STATUS_IS_OK(status)) {
5833                 d_fprintf(stderr,
5834                           "cli_ntcreate of %s failed (%s)\n",
5835                           fname_stream,
5836                           nt_errstr(status));
5837                 return false;
5838         }
5839
5840         /* open it a second time */
5841
5842         status = cli_ntcreate(
5843                 cli,
5844                 fname_stream,
5845                 0,
5846                 FILE_WRITE_DATA,
5847                 0,
5848                 FILE_SHARE_READ|FILE_SHARE_WRITE,
5849                 FILE_OPEN,
5850                 0x0,
5851                 0x0,
5852                 &fnum2,
5853                 NULL);
5854
5855         if (!NT_STATUS_IS_OK(status)) {
5856                 d_fprintf(stderr,
5857                           "2nd cli_ntcreate of %s failed (%s)\n",
5858                           fname_stream,
5859                           nt_errstr(status));
5860                 return false;
5861         }
5862
5863         ev = samba_tevent_context_init(talloc_tos());
5864         if (ev == NULL) {
5865                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5866                 return false;
5867         }
5868
5869         req = delete_stream_send(ev, ev, cli, fname, fnum1);
5870         if (req == NULL) {
5871                 d_fprintf(stderr, "delete_stream_send failed\n");
5872                 return false;
5873         }
5874
5875         ok = tevent_req_poll_ntstatus(req, ev, &status);
5876         if (!ok) {
5877                 d_fprintf(stderr,
5878                           "tevent_req_poll_ntstatus failed: %s\n",
5879                           nt_errstr(status));
5880                 return false;
5881         }
5882
5883         status = delete_stream_recv(req);
5884         TALLOC_FREE(req);
5885         if (!NT_STATUS_IS_OK(status)) {
5886                 d_fprintf(stderr,
5887                           "delete_stream failed: %s\n",
5888                           nt_errstr(status));
5889                 return false;
5890         }
5891
5892         status = cli_close(cli, fnum2);
5893         if (!NT_STATUS_IS_OK(status)) {
5894                 d_fprintf(stderr,
5895                           "close failed: %s\n",
5896                           nt_errstr(status));
5897                 return false;
5898         }
5899
5900         status = cli_unlink(
5901                 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5902         if (!NT_STATUS_IS_OK(status)) {
5903                 d_fprintf(stderr,
5904                           "unlink failed: %s\n",
5905                           nt_errstr(status));
5906                 return false;
5907         }
5908
5909         return true;
5910 }
5911
5912 /*
5913   Exercise delete on close semantics - use on the PRINT1 share in torture
5914   testing.
5915  */
5916 static bool run_delete_print_test(int dummy)
5917 {
5918         struct cli_state *cli1 = NULL;
5919         const char *fname = "print_delete.file";
5920         uint16_t fnum1 = (uint16_t)-1;
5921         bool correct = false;
5922         const char *buf = "print file data\n";
5923         NTSTATUS status;
5924
5925         printf("starting print delete test\n");
5926
5927         if (!torture_open_connection(&cli1, 0)) {
5928                 return false;
5929         }
5930
5931         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5932
5933         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5934                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5935                               0, 0, &fnum1, NULL);
5936         if (!NT_STATUS_IS_OK(status)) {
5937                 printf("open of %s failed (%s)\n",
5938                         fname,
5939                         nt_errstr(status));
5940                 goto fail;
5941         }
5942
5943         status = cli_writeall(cli1,
5944                         fnum1,
5945                         0,
5946                         (const uint8_t *)buf,
5947                         0, /* offset */
5948                         strlen(buf), /* size */
5949                         NULL);
5950         if (!NT_STATUS_IS_OK(status)) {
5951                 printf("writing print file data failed (%s)\n",
5952                         nt_errstr(status));
5953                 goto fail;
5954         }
5955
5956         status = cli_nt_delete_on_close(cli1, fnum1, true);
5957         if (!NT_STATUS_IS_OK(status)) {
5958                 printf("setting delete_on_close failed (%s)\n",
5959                         nt_errstr(status));
5960                 goto fail;
5961         }
5962
5963         status = cli_close(cli1, fnum1);
5964         if (!NT_STATUS_IS_OK(status)) {
5965                 printf("close failed (%s)\n", nt_errstr(status));
5966                 goto fail;
5967         }
5968
5969         printf("finished print delete test\n");
5970
5971         correct = true;
5972
5973   fail:
5974
5975         if (fnum1 != (uint16_t)-1) {
5976                 cli_close(cli1, fnum1);
5977         }
5978
5979         if (cli1 && !torture_close_connection(cli1)) {
5980                 correct = false;
5981         }
5982         return correct;
5983 }
5984
5985 /*
5986   Test wildcard delete.
5987  */
5988 static bool run_wild_deletetest(int dummy)
5989 {
5990         struct cli_state *cli = NULL;
5991         const char *dname = "\\WTEST";
5992         const char *fname = "\\WTEST\\A";
5993         const char *wunlink_name = "\\WTEST\\*";
5994         uint16_t fnum1 = (uint16_t)-1;
5995         bool correct = false;
5996         NTSTATUS status;
5997
5998         printf("starting wildcard delete test\n");
5999
6000         if (!torture_open_connection(&cli, 0)) {
6001                 return false;
6002         }
6003
6004         smbXcli_conn_set_sockopt(cli->conn, sockops);
6005
6006         cli_unlink(cli, fname, 0);
6007         cli_rmdir(cli, dname);
6008         status = cli_mkdir(cli, dname);
6009         if (!NT_STATUS_IS_OK(status)) {
6010                 printf("mkdir of %s failed %s!\n", dname, nt_errstr(status));
6011                 goto fail;
6012         }
6013         status = cli_openx(cli, fname, O_CREAT|O_RDONLY, DENY_NONE, &fnum1);
6014         if (!NT_STATUS_IS_OK(status)) {
6015                 printf("open of %s failed %s!\n", fname, nt_errstr(status));
6016                 goto fail;
6017         }
6018         status = cli_close(cli, fnum1);
6019         fnum1 = -1;
6020
6021         /*
6022          * Note the unlink attribute-type of zero. This should
6023          * map into FILE_ATTRIBUTE_NORMAL at the server even
6024          * on a wildcard delete.
6025          */
6026
6027         status = cli_unlink(cli, wunlink_name, 0);
6028         if (!NT_STATUS_IS_OK(status)) {
6029                 printf("unlink of %s failed %s!\n",
6030                         wunlink_name, nt_errstr(status));
6031                 goto fail;
6032         }
6033
6034         printf("finished wildcard delete test\n");
6035
6036         correct = true;
6037
6038   fail:
6039
6040         if (fnum1 != (uint16_t)-1) cli_close(cli, fnum1);
6041         cli_unlink(cli, fname, 0);
6042         cli_rmdir(cli, dname);
6043
6044         if (cli && !torture_close_connection(cli)) {
6045                 correct = false;
6046         }
6047         return correct;
6048 }
6049
6050 static bool run_deletetest_ln(int dummy)
6051 {
6052         struct cli_state *cli;
6053         const char *fname = "\\delete1";
6054         const char *fname_ln = "\\delete1_ln";
6055         uint16_t fnum;
6056         uint16_t fnum1;
6057         NTSTATUS status;
6058         bool correct = true;
6059         time_t t;
6060
6061         printf("starting deletetest-ln\n");
6062
6063         if (!torture_open_connection(&cli, 0)) {
6064                 return false;
6065         }
6066
6067         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6068         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6069
6070         smbXcli_conn_set_sockopt(cli->conn, sockops);
6071
6072         /* Create the file. */
6073         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6074         if (!NT_STATUS_IS_OK(status)) {
6075                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6076                 return false;
6077         }
6078
6079         status = cli_close(cli, fnum);
6080         if (!NT_STATUS_IS_OK(status)) {
6081                 printf("close1 failed (%s)\n", nt_errstr(status));
6082                 return false;
6083         }
6084
6085         /* Now create a hardlink. */
6086         status = cli_hardlink(cli, fname, fname_ln);
6087         if (!NT_STATUS_IS_OK(status)) {
6088                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6089                 return false;
6090         }
6091
6092         /* Open the original file. */
6093         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6094                         FILE_ATTRIBUTE_NORMAL,
6095                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6096                         FILE_OPEN_IF, 0, 0, &fnum, NULL);
6097         if (!NT_STATUS_IS_OK(status)) {
6098                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6099                 return false;
6100         }
6101
6102         /* Unlink the hard link path. */
6103         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6104                         FILE_ATTRIBUTE_NORMAL,
6105                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6106                         FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6107         if (!NT_STATUS_IS_OK(status)) {
6108                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6109                 return false;
6110         }
6111         status = cli_nt_delete_on_close(cli, fnum1, true);
6112         if (!NT_STATUS_IS_OK(status)) {
6113                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6114                         __location__, fname_ln, nt_errstr(status));
6115                 return false;
6116         }
6117
6118         status = cli_close(cli, fnum1);
6119         if (!NT_STATUS_IS_OK(status)) {
6120                 printf("close %s failed (%s)\n",
6121                         fname_ln, nt_errstr(status));
6122                 return false;
6123         }
6124
6125         status = cli_close(cli, fnum);
6126         if (!NT_STATUS_IS_OK(status)) {
6127                 printf("close %s failed (%s)\n",
6128                         fname, nt_errstr(status));
6129                 return false;
6130         }
6131
6132         /* Ensure the original file is still there. */
6133         status = cli_getatr(cli, fname, NULL, NULL, &t);
6134         if (!NT_STATUS_IS_OK(status)) {
6135                 printf("%s getatr on file %s failed (%s)\n",
6136                         __location__,
6137                         fname,
6138                         nt_errstr(status));
6139                 correct = False;
6140         }
6141
6142         /* Ensure the link path is gone. */
6143         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6144         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6145                 printf("%s, getatr for file %s returned wrong error code %s "
6146                         "- should have been deleted\n",
6147                         __location__,
6148                         fname_ln, nt_errstr(status));
6149                 correct = False;
6150         }
6151
6152         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6153         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6154
6155         if (!torture_close_connection(cli)) {
6156                 correct = false;
6157         }
6158
6159         printf("finished deletetest-ln\n");
6160
6161         return correct;
6162 }
6163
6164 /*
6165   print out server properties
6166  */
6167 static bool run_properties(int dummy)
6168 {
6169         struct cli_state *cli;
6170         bool correct = True;
6171
6172         printf("starting properties test\n");
6173
6174         ZERO_STRUCT(cli);
6175
6176         if (!torture_open_connection(&cli, 0)) {
6177                 return False;
6178         }
6179
6180         smbXcli_conn_set_sockopt(cli->conn, sockops);
6181
6182         d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6183
6184         if (!torture_close_connection(cli)) {
6185                 correct = False;
6186         }
6187
6188         return correct;
6189 }
6190
6191
6192
6193 /* FIRST_DESIRED_ACCESS   0xf019f */
6194 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6195                                FILE_READ_EA|                           /* 0xf */ \
6196                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
6197                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
6198                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
6199                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
6200 /* SECOND_DESIRED_ACCESS  0xe0080 */
6201 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6202                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6203                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
6204
6205 #if 0
6206 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6207                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6208                                FILE_READ_DATA|\
6209                                WRITE_OWNER_ACCESS                      /* */
6210 #endif
6211
6212 /*
6213   Test ntcreate calls made by xcopy
6214  */
6215 static bool run_xcopy(int dummy)
6216 {
6217         static struct cli_state *cli1;
6218         const char *fname = "\\test.txt";
6219         bool correct = True;
6220         uint16_t fnum1, fnum2;
6221         NTSTATUS status;
6222
6223         printf("starting xcopy test\n");
6224
6225         if (!torture_open_connection(&cli1, 0)) {
6226                 return False;
6227         }
6228
6229         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6230                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6231                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6232         if (!NT_STATUS_IS_OK(status)) {
6233                 printf("First open failed - %s\n", nt_errstr(status));
6234                 return False;
6235         }
6236
6237         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6238                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6239                              FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6240         if (!NT_STATUS_IS_OK(status)) {
6241                 printf("second open failed - %s\n", nt_errstr(status));
6242                 return False;
6243         }
6244
6245         if (!torture_close_connection(cli1)) {
6246                 correct = False;
6247         }
6248
6249         return correct;
6250 }
6251
6252 /*
6253   Test rename on files open with share delete and no share delete.
6254  */
6255 static bool run_rename(int dummy)
6256 {
6257         static struct cli_state *cli1;
6258         const char *fname = "\\test.txt";
6259         const char *fname1 = "\\test1.txt";
6260         bool correct = True;
6261         uint16_t fnum1;
6262         uint16_t attr;
6263         NTSTATUS status;
6264
6265         printf("starting rename test\n");
6266
6267         if (!torture_open_connection(&cli1, 0)) {
6268                 return False;
6269         }
6270
6271         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6272         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6273
6274         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6275                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6276                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6277         if (!NT_STATUS_IS_OK(status)) {
6278                 printf("First open failed - %s\n", nt_errstr(status));
6279                 return False;
6280         }
6281
6282         status = cli_rename(cli1, fname, fname1, false);
6283         if (!NT_STATUS_IS_OK(status)) {
6284                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6285         } else {
6286                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6287                 correct = False;
6288         }
6289
6290         status = cli_close(cli1, fnum1);
6291         if (!NT_STATUS_IS_OK(status)) {
6292                 printf("close - 1 failed (%s)\n", nt_errstr(status));
6293                 return False;
6294         }
6295
6296         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6297         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6298         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6299 #if 0
6300                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
6301 #else
6302                               FILE_SHARE_DELETE|FILE_SHARE_READ,
6303 #endif
6304                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6305         if (!NT_STATUS_IS_OK(status)) {
6306                 printf("Second open failed - %s\n", nt_errstr(status));
6307                 return False;
6308         }
6309
6310         status = cli_rename(cli1, fname, fname1, false);
6311         if (!NT_STATUS_IS_OK(status)) {
6312                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6313                 correct = False;
6314         } else {
6315                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6316         }
6317
6318         status = cli_close(cli1, fnum1);
6319         if (!NT_STATUS_IS_OK(status)) {
6320                 printf("close - 2 failed (%s)\n", nt_errstr(status));
6321                 return False;
6322         }
6323
6324         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6325         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6326
6327         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6328                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6329                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6330         if (!NT_STATUS_IS_OK(status)) {
6331                 printf("Third open failed - %s\n", nt_errstr(status));
6332                 return False;
6333         }
6334
6335
6336 #if 0
6337   {
6338         uint16_t fnum2;
6339
6340         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
6341                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
6342                 printf("Fourth open failed - %s\n", cli_errstr(cli1));
6343                 return False;
6344         }
6345         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
6346                 printf("[8] setting delete_on_close on file failed !\n");
6347                 return False;
6348         }
6349
6350         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
6351                 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
6352                 return False;
6353         }
6354   }
6355 #endif
6356
6357         status = cli_rename(cli1, fname, fname1, false);
6358         if (!NT_STATUS_IS_OK(status)) {
6359                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6360                 correct = False;
6361         } else {
6362                 printf("Third rename succeeded (SHARE_NONE)\n");
6363         }
6364
6365         status = cli_close(cli1, fnum1);
6366         if (!NT_STATUS_IS_OK(status)) {
6367                 printf("close - 3 failed (%s)\n", nt_errstr(status));
6368                 return False;
6369         }
6370
6371         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6372         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6373
6374         /*----*/
6375
6376         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6377                               FILE_ATTRIBUTE_NORMAL,
6378                               FILE_SHARE_READ | FILE_SHARE_WRITE,
6379                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6380         if (!NT_STATUS_IS_OK(status)) {
6381                 printf("Fourth open failed - %s\n", nt_errstr(status));
6382                 return False;
6383         }
6384
6385         status = cli_rename(cli1, fname, fname1, false);
6386         if (!NT_STATUS_IS_OK(status)) {
6387                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6388         } else {
6389                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6390                 correct = False;
6391         }
6392
6393         status = cli_close(cli1, fnum1);
6394         if (!NT_STATUS_IS_OK(status)) {
6395                 printf("close - 4 failed (%s)\n", nt_errstr(status));
6396                 return False;
6397         }
6398
6399         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6400         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6401
6402         /*--*/
6403
6404         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6405                          FILE_ATTRIBUTE_NORMAL,
6406                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6407                          FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6408         if (!NT_STATUS_IS_OK(status)) {
6409                 printf("Fifth open failed - %s\n", nt_errstr(status));
6410                 return False;
6411         }
6412
6413         status = cli_rename(cli1, fname, fname1, false);
6414         if (!NT_STATUS_IS_OK(status)) {
6415                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6416                 correct = False;
6417         } else {
6418                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6419         }
6420
6421         /*
6422          * Now check if the first name still exists ...
6423          */
6424
6425         /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6426                                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6427                                    FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
6428           printf("Opening original file after rename of open file fails: %s\n",
6429               cli_errstr(cli1));
6430         }
6431         else {
6432           printf("Opening original file after rename of open file works ...\n");
6433           (void)cli_close(cli1, fnum2);
6434           } */
6435
6436         /*--*/
6437         status = cli_close(cli1, fnum1);
6438         if (!NT_STATUS_IS_OK(status)) {
6439                 printf("close - 5 failed (%s)\n", nt_errstr(status));
6440                 return False;
6441         }
6442
6443         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6444         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6445         if (!NT_STATUS_IS_OK(status)) {
6446                 printf("getatr on file %s failed - %s ! \n",
6447                         fname1, nt_errstr(status));
6448                 correct = False;
6449         } else {
6450                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6451                         printf("Renamed file %s has wrong attr 0x%x "
6452                                 "(should be 0x%x)\n",
6453                                 fname1,
6454                                 attr,
6455                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6456                         correct = False;
6457                 } else {
6458                         printf("Renamed file %s has archive bit set\n", fname1);
6459                 }
6460         }
6461
6462         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6463         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6464
6465         if (!torture_close_connection(cli1)) {
6466                 correct = False;
6467         }
6468
6469         return correct;
6470 }
6471
6472 /*
6473   Test rename into a directory with an ACL denying it.
6474  */
6475 static bool run_rename_access(int dummy)
6476 {
6477         static struct cli_state *cli = NULL;
6478         static struct cli_state *posix_cli = NULL;
6479         const char *src = "test.txt";
6480         const char *dname = "dir";
6481         const char *dst = "dir\\test.txt";
6482         const char *dsrc = "test.dir";
6483         const char *ddst = "dir\\test.dir";
6484         uint16_t fnum = (uint16_t)-1;
6485         struct security_descriptor *sd = NULL;
6486         struct security_descriptor *newsd = NULL;
6487         NTSTATUS status;
6488         TALLOC_CTX *frame = NULL;
6489
6490         frame = talloc_stackframe();
6491         printf("starting rename access test\n");
6492
6493         /* Windows connection. */
6494         if (!torture_open_connection(&cli, 0)) {
6495                 goto fail;
6496         }
6497
6498         smbXcli_conn_set_sockopt(cli->conn, sockops);
6499
6500         /* Posix connection. */
6501         if (!torture_open_connection(&posix_cli, 0)) {
6502                 goto fail;
6503         }
6504
6505         smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6506
6507         status = torture_setup_unix_extensions(posix_cli);
6508         if (!NT_STATUS_IS_OK(status)) {
6509                 goto fail;
6510         }
6511
6512         /* Start with a clean slate. */
6513         cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6514         cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6515         cli_rmdir(cli, dsrc);
6516         cli_rmdir(cli, ddst);
6517         cli_rmdir(cli, dname);
6518
6519         /*
6520          * Setup the destination directory with a DENY ACE to
6521          * prevent new files within it.
6522          */
6523         status = cli_ntcreate(cli,
6524                                 dname,
6525                                 0,
6526                                 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6527                                         WRITE_DAC_ACCESS|FILE_READ_DATA|
6528                                         WRITE_OWNER_ACCESS,
6529                                 FILE_ATTRIBUTE_DIRECTORY,
6530                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6531                                 FILE_CREATE,
6532                                 FILE_DIRECTORY_FILE,
6533                                 0,
6534                                 &fnum,
6535                                 NULL);
6536         if (!NT_STATUS_IS_OK(status)) {
6537                 printf("Create of %s - %s\n", dname, nt_errstr(status));
6538                 goto fail;
6539         }
6540
6541         status = cli_query_secdesc(cli,
6542                                 fnum,
6543                                 frame,
6544                                 &sd);
6545         if (!NT_STATUS_IS_OK(status)) {
6546                 printf("cli_query_secdesc failed for %s (%s)\n",
6547                         dname, nt_errstr(status));
6548                 goto fail;
6549         }
6550
6551         newsd = security_descriptor_dacl_create(frame,
6552                                         0,
6553                                         NULL,
6554                                         NULL,
6555                                         SID_WORLD,
6556                                         SEC_ACE_TYPE_ACCESS_DENIED,
6557                                         SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6558                                         0,
6559                                         NULL);
6560         if (newsd == NULL) {
6561                 goto fail;
6562         }
6563         sd->dacl = security_acl_concatenate(frame,
6564                                         newsd->dacl,
6565                                         sd->dacl);
6566         if (sd->dacl == NULL) {
6567                 goto fail;
6568         }
6569         status = cli_set_secdesc(cli, fnum, sd);
6570         if (!NT_STATUS_IS_OK(status)) {
6571                 printf("cli_set_secdesc failed for %s (%s)\n",
6572                         dname, nt_errstr(status));
6573                 goto fail;
6574         }
6575         status = cli_close(cli, fnum);
6576         if (!NT_STATUS_IS_OK(status)) {
6577                 printf("close failed for %s (%s)\n",
6578                         dname, nt_errstr(status));
6579                 goto fail;
6580         }
6581         /* Now go around the back and chmod to 777 via POSIX. */
6582         status = cli_posix_chmod(posix_cli, dname, 0777);
6583         if (!NT_STATUS_IS_OK(status)) {
6584                 printf("cli_posix_chmod failed for %s (%s)\n",
6585                         dname, nt_errstr(status));
6586                 goto fail;
6587         }
6588
6589         /* Check we can't create a file within dname via Windows. */
6590         status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6591         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6592                 cli_close(posix_cli, fnum);
6593                 printf("Create of %s should be ACCESS denied, was %s\n",
6594                         dst, nt_errstr(status));
6595                 goto fail;
6596         }
6597
6598         /* Make the sample file/directory. */
6599         status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6600         if (!NT_STATUS_IS_OK(status)) {
6601                 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6602                 goto fail;
6603         }
6604         status = cli_close(cli, fnum);
6605         if (!NT_STATUS_IS_OK(status)) {
6606                 printf("cli_close failed (%s)\n", nt_errstr(status));
6607                 goto fail;
6608         }
6609
6610         status = cli_mkdir(cli, dsrc);
6611         if (!NT_STATUS_IS_OK(status)) {
6612                 printf("cli_mkdir of %s failed (%s)\n",
6613                         dsrc, nt_errstr(status));
6614                 goto fail;
6615         }
6616
6617         /*
6618          * OK - renames of the new file and directory into the
6619          * dst directory should fail.
6620          */
6621
6622         status = cli_rename(cli, src, dst, false);
6623         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6624                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6625                         src, dst, nt_errstr(status));
6626                 goto fail;
6627         }
6628         status = cli_rename(cli, dsrc, ddst, false);
6629         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6630                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6631                         src, dst, nt_errstr(status));
6632                 goto fail;
6633         }
6634
6635         TALLOC_FREE(frame);
6636         return true;
6637
6638   fail:
6639
6640         if (posix_cli) {
6641                 torture_close_connection(posix_cli);
6642         }
6643
6644         if (cli) {
6645                 if (fnum != (uint16_t)-1) {
6646                         cli_close(cli, fnum);
6647                 }
6648                 cli_unlink(cli, src,
6649                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6650                 cli_unlink(cli, dst,
6651                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6652                 cli_rmdir(cli, dsrc);
6653                 cli_rmdir(cli, ddst);
6654                 cli_rmdir(cli, dname);
6655
6656                 torture_close_connection(cli);
6657         }
6658
6659         TALLOC_FREE(frame);
6660         return false;
6661 }
6662
6663 /*
6664   Test owner rights ACE.
6665  */
6666 static bool run_owner_rights(int dummy)
6667 {
6668         static struct cli_state *cli = NULL;
6669         const char *fname = "owner_rights.txt";
6670         uint16_t fnum = (uint16_t)-1;
6671         struct security_descriptor *sd = NULL;
6672         struct security_descriptor *newsd = NULL;
6673         NTSTATUS status;
6674         TALLOC_CTX *frame = NULL;
6675
6676         frame = talloc_stackframe();
6677         printf("starting owner rights test\n");
6678
6679         /* Windows connection. */
6680         if (!torture_open_connection(&cli, 0)) {
6681                 goto fail;
6682         }
6683
6684         smbXcli_conn_set_sockopt(cli->conn, sockops);
6685
6686         /* Start with a clean slate. */
6687         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6688
6689         /* Create the test file. */
6690         /* Now try and open for read and write-dac. */
6691         status = cli_ntcreate(cli,
6692                                 fname,
6693                                 0,
6694                                 GENERIC_ALL_ACCESS,
6695                                 FILE_ATTRIBUTE_NORMAL,
6696                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6697                                         FILE_SHARE_DELETE,
6698                                 FILE_CREATE,
6699                                 0,
6700                                 0,
6701                                 &fnum,
6702                                 NULL);
6703         if (!NT_STATUS_IS_OK(status)) {
6704                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6705                 goto fail;
6706         }
6707
6708         /* Get the original SD. */
6709         status = cli_query_secdesc(cli,
6710                                 fnum,
6711                                 frame,
6712                                 &sd);
6713         if (!NT_STATUS_IS_OK(status)) {
6714                 printf("cli_query_secdesc failed for %s (%s)\n",
6715                         fname, nt_errstr(status));
6716                 goto fail;
6717         }
6718
6719         /*
6720          * Add an "owner-rights" ACE denying WRITE_DATA,
6721          * and an "owner-rights" ACE allowing READ_DATA.
6722          */
6723
6724         newsd = security_descriptor_dacl_create(frame,
6725                                         0,
6726                                         NULL,
6727                                         NULL,
6728                                         SID_OWNER_RIGHTS,
6729                                         SEC_ACE_TYPE_ACCESS_DENIED,
6730                                         FILE_WRITE_DATA,
6731                                         0,
6732                                         SID_OWNER_RIGHTS,
6733                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6734                                         FILE_READ_DATA,
6735                                         0,
6736                                         NULL);
6737         if (newsd == NULL) {
6738                 goto fail;
6739         }
6740         sd->dacl = security_acl_concatenate(frame,
6741                                         newsd->dacl,
6742                                         sd->dacl);
6743         if (sd->dacl == NULL) {
6744                 goto fail;
6745         }
6746         status = cli_set_secdesc(cli, fnum, sd);
6747         if (!NT_STATUS_IS_OK(status)) {
6748                 printf("cli_set_secdesc failed for %s (%s)\n",
6749                         fname, nt_errstr(status));
6750                 goto fail;
6751         }
6752         status = cli_close(cli, fnum);
6753         if (!NT_STATUS_IS_OK(status)) {
6754                 printf("close failed for %s (%s)\n",
6755                         fname, nt_errstr(status));
6756                 goto fail;
6757         }
6758         fnum = (uint16_t)-1;
6759
6760         /* Try and open for FILE_WRITE_DATA */
6761         status = cli_ntcreate(cli,
6762                                 fname,
6763                                 0,
6764                                 FILE_WRITE_DATA,
6765                                 FILE_ATTRIBUTE_NORMAL,
6766                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6767                                         FILE_SHARE_DELETE,
6768                                 FILE_OPEN,
6769                                 0,
6770                                 0,
6771                                 &fnum,
6772                                 NULL);
6773         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6774                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6775                 goto fail;
6776         }
6777
6778         /* Now try and open for FILE_READ_DATA */
6779         status = cli_ntcreate(cli,
6780                                 fname,
6781                                 0,
6782                                 FILE_READ_DATA,
6783                                 FILE_ATTRIBUTE_NORMAL,
6784                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6785                                         FILE_SHARE_DELETE,
6786                                 FILE_OPEN,
6787                                 0,
6788                                 0,
6789                                 &fnum,
6790                                 NULL);
6791         if (!NT_STATUS_IS_OK(status)) {
6792                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6793                 goto fail;
6794         }
6795
6796         status = cli_close(cli, fnum);
6797         if (!NT_STATUS_IS_OK(status)) {
6798                 printf("close failed for %s (%s)\n",
6799                         fname, nt_errstr(status));
6800                 goto fail;
6801         }
6802
6803         /* Restore clean slate. */
6804         TALLOC_FREE(sd);
6805         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6806
6807         /* Create the test file. */
6808         status = cli_ntcreate(cli,
6809                                 fname,
6810                                 0,
6811                                 GENERIC_ALL_ACCESS,
6812                                 FILE_ATTRIBUTE_NORMAL,
6813                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6814                                         FILE_SHARE_DELETE,
6815                                 FILE_CREATE,
6816                                 0,
6817                                 0,
6818                                 &fnum,
6819                                 NULL);
6820         if (!NT_STATUS_IS_OK(status)) {
6821                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6822                 goto fail;
6823         }
6824
6825         /* Get the original SD. */
6826         status = cli_query_secdesc(cli,
6827                                 fnum,
6828                                 frame,
6829                                 &sd);
6830         if (!NT_STATUS_IS_OK(status)) {
6831                 printf("cli_query_secdesc failed for %s (%s)\n",
6832                         fname, nt_errstr(status));
6833                 goto fail;
6834         }
6835
6836         /*
6837          * Add an "owner-rights ACE denying WRITE_DATA,
6838          * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6839          */
6840
6841         newsd = security_descriptor_dacl_create(frame,
6842                                         0,
6843                                         NULL,
6844                                         NULL,
6845                                         SID_OWNER_RIGHTS,
6846                                         SEC_ACE_TYPE_ACCESS_DENIED,
6847                                         FILE_WRITE_DATA,
6848                                         0,
6849                                         SID_OWNER_RIGHTS,
6850                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6851                                         FILE_READ_DATA|FILE_WRITE_DATA,
6852                                         0,
6853                                         NULL);
6854         if (newsd == NULL) {
6855                 goto fail;
6856         }
6857         sd->dacl = security_acl_concatenate(frame,
6858                                         newsd->dacl,
6859                                         sd->dacl);
6860         if (sd->dacl == NULL) {
6861                 goto fail;
6862         }
6863         status = cli_set_secdesc(cli, fnum, sd);
6864         if (!NT_STATUS_IS_OK(status)) {
6865                 printf("cli_set_secdesc failed for %s (%s)\n",
6866                         fname, nt_errstr(status));
6867                 goto fail;
6868         }
6869         status = cli_close(cli, fnum);
6870         if (!NT_STATUS_IS_OK(status)) {
6871                 printf("close failed for %s (%s)\n",
6872                         fname, nt_errstr(status));
6873                 goto fail;
6874         }
6875         fnum = (uint16_t)-1;
6876
6877         /* Try and open for FILE_WRITE_DATA */
6878         status = cli_ntcreate(cli,
6879                                 fname,
6880                                 0,
6881                                 FILE_WRITE_DATA,
6882                                 FILE_ATTRIBUTE_NORMAL,
6883                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6884                                         FILE_SHARE_DELETE,
6885                                 FILE_OPEN,
6886                                 0,
6887                                 0,
6888                                 &fnum,
6889                                 NULL);
6890         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6891                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6892                 goto fail;
6893         }
6894
6895         /* Now try and open for FILE_READ_DATA */
6896         status = cli_ntcreate(cli,
6897                                 fname,
6898                                 0,
6899                                 FILE_READ_DATA,
6900                                 FILE_ATTRIBUTE_NORMAL,
6901                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6902                                         FILE_SHARE_DELETE,
6903                                 FILE_OPEN,
6904                                 0,
6905                                 0,
6906                                 &fnum,
6907                                 NULL);
6908         if (!NT_STATUS_IS_OK(status)) {
6909                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6910                 goto fail;
6911         }
6912
6913         status = cli_close(cli, fnum);
6914         if (!NT_STATUS_IS_OK(status)) {
6915                 printf("close failed for %s (%s)\n",
6916                         fname, nt_errstr(status));
6917                 goto fail;
6918         }
6919
6920         /* Restore clean slate. */
6921         TALLOC_FREE(sd);
6922         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6923
6924
6925         /* Create the test file. */
6926         status = cli_ntcreate(cli,
6927                                 fname,
6928                                 0,
6929                                 GENERIC_ALL_ACCESS,
6930                                 FILE_ATTRIBUTE_NORMAL,
6931                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6932                                         FILE_SHARE_DELETE,
6933                                 FILE_CREATE,
6934                                 0,
6935                                 0,
6936                                 &fnum,
6937                                 NULL);
6938         if (!NT_STATUS_IS_OK(status)) {
6939                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6940                 goto fail;
6941         }
6942
6943         /* Get the original SD. */
6944         status = cli_query_secdesc(cli,
6945                                 fnum,
6946                                 frame,
6947                                 &sd);
6948         if (!NT_STATUS_IS_OK(status)) {
6949                 printf("cli_query_secdesc failed for %s (%s)\n",
6950                         fname, nt_errstr(status));
6951                 goto fail;
6952         }
6953
6954         /*
6955          * Add an "authenticated users" ACE allowing READ_DATA,
6956          * add an "owner-rights" denying READ_DATA,
6957          * and an "authenticated users" ACE allowing WRITE_DATA.
6958          */
6959
6960         newsd = security_descriptor_dacl_create(frame,
6961                                         0,
6962                                         NULL,
6963                                         NULL,
6964                                         SID_NT_AUTHENTICATED_USERS,
6965                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6966                                         FILE_READ_DATA,
6967                                         0,
6968                                         SID_OWNER_RIGHTS,
6969                                         SEC_ACE_TYPE_ACCESS_DENIED,
6970                                         FILE_READ_DATA,
6971                                         0,
6972                                         SID_NT_AUTHENTICATED_USERS,
6973                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6974                                         FILE_WRITE_DATA,
6975                                         0,
6976                                         NULL);
6977         if (newsd == NULL) {
6978                 printf("newsd == NULL\n");
6979                 goto fail;
6980         }
6981         sd->dacl = security_acl_concatenate(frame,
6982                                         newsd->dacl,
6983                                         sd->dacl);
6984         if (sd->dacl == NULL) {
6985                 printf("sd->dacl == NULL\n");
6986                 goto fail;
6987         }
6988         status = cli_set_secdesc(cli, fnum, sd);
6989         if (!NT_STATUS_IS_OK(status)) {
6990                 printf("cli_set_secdesc failed for %s (%s)\n",
6991                         fname, nt_errstr(status));
6992                 goto fail;
6993         }
6994         status = cli_close(cli, fnum);
6995         if (!NT_STATUS_IS_OK(status)) {
6996                 printf("close failed for %s (%s)\n",
6997                         fname, nt_errstr(status));
6998                 goto fail;
6999         }
7000         fnum = (uint16_t)-1;
7001
7002         /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7003         status = cli_ntcreate(cli,
7004                                 fname,
7005                                 0,
7006                                 FILE_READ_DATA|FILE_WRITE_DATA,
7007                                 FILE_ATTRIBUTE_NORMAL,
7008                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7009                                         FILE_SHARE_DELETE,
7010                                 FILE_OPEN,
7011                                 0,
7012                                 0,
7013                                 &fnum,
7014                                 NULL);
7015         if (!NT_STATUS_IS_OK(status)) {
7016                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7017                 goto fail;
7018         }
7019
7020         status = cli_close(cli, fnum);
7021         if (!NT_STATUS_IS_OK(status)) {
7022                 printf("close failed for %s (%s)\n",
7023                         fname, nt_errstr(status));
7024                 goto fail;
7025         }
7026
7027         cli_unlink(cli, fname,
7028                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7029
7030         TALLOC_FREE(frame);
7031         return true;
7032
7033   fail:
7034
7035         if (cli) {
7036                 if (fnum != (uint16_t)-1) {
7037                         cli_close(cli, fnum);
7038                 }
7039                 cli_unlink(cli, fname,
7040                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7041                 torture_close_connection(cli);
7042         }
7043
7044         TALLOC_FREE(frame);
7045         return false;
7046 }
7047
7048 static bool run_pipe_number(int dummy)
7049 {
7050         struct cli_state *cli1;
7051         const char *pipe_name = "\\SPOOLSS";
7052         uint16_t fnum;
7053         int num_pipes = 0;
7054         NTSTATUS status;
7055
7056         printf("starting pipenumber test\n");
7057         if (!torture_open_connection(&cli1, 0)) {
7058                 return False;
7059         }
7060
7061         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7062         while(1) {
7063                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7064                                       FILE_ATTRIBUTE_NORMAL,
7065                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
7066                                       FILE_OPEN_IF, 0, 0, &fnum, NULL);
7067                 if (!NT_STATUS_IS_OK(status)) {
7068                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7069                         break;
7070                 }
7071                 num_pipes++;
7072                 printf("\r%6d", num_pipes);
7073         }
7074
7075         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7076         torture_close_connection(cli1);
7077         return True;
7078 }
7079
7080 /*
7081   Test open mode returns on read-only files.
7082  */
7083 static bool run_opentest(int dummy)
7084 {
7085         static struct cli_state *cli1;
7086         static struct cli_state *cli2;
7087         const char *fname = "\\readonly.file";
7088         uint16_t fnum1, fnum2;
7089         char buf[20];
7090         off_t fsize;
7091         bool correct = True;
7092         char *tmp_path;
7093         NTSTATUS status;
7094
7095         printf("starting open test\n");
7096
7097         if (!torture_open_connection(&cli1, 0)) {
7098                 return False;
7099         }
7100
7101         cli_setatr(cli1, fname, 0, 0);
7102         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7103
7104         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7105
7106         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7107         if (!NT_STATUS_IS_OK(status)) {
7108                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7109                 return False;
7110         }
7111
7112         status = cli_close(cli1, fnum1);
7113         if (!NT_STATUS_IS_OK(status)) {
7114                 printf("close2 failed (%s)\n", nt_errstr(status));
7115                 return False;
7116         }
7117
7118         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7119         if (!NT_STATUS_IS_OK(status)) {
7120                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7121                 return False;
7122         }
7123
7124         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7125         if (!NT_STATUS_IS_OK(status)) {
7126                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7127                 return False;
7128         }
7129
7130         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7131         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7132
7133         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7134                         NT_STATUS_ACCESS_DENIED)) {
7135                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7136         }
7137
7138         printf("finished open test 1\n");
7139
7140         cli_close(cli1, fnum1);
7141
7142         /* Now try not readonly and ensure ERRbadshare is returned. */
7143
7144         cli_setatr(cli1, fname, 0, 0);
7145
7146         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7147         if (!NT_STATUS_IS_OK(status)) {
7148                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7149                 return False;
7150         }
7151
7152         /* This will fail - but the error should be ERRshare. */
7153         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7154
7155         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7156                         NT_STATUS_SHARING_VIOLATION)) {
7157                 printf("correct error code ERRDOS/ERRbadshare returned\n");
7158         }
7159
7160         status = cli_close(cli1, fnum1);
7161         if (!NT_STATUS_IS_OK(status)) {
7162                 printf("close2 failed (%s)\n", nt_errstr(status));
7163                 return False;
7164         }
7165
7166         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7167
7168         printf("finished open test 2\n");
7169
7170         /* Test truncate open disposition on file opened for read. */
7171         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7172         if (!NT_STATUS_IS_OK(status)) {
7173                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7174                 return False;
7175         }
7176
7177         /* write 20 bytes. */
7178
7179         memset(buf, '\0', 20);
7180
7181         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7182         if (!NT_STATUS_IS_OK(status)) {
7183                 printf("write failed (%s)\n", nt_errstr(status));
7184                 correct = False;
7185         }
7186
7187         status = cli_close(cli1, fnum1);
7188         if (!NT_STATUS_IS_OK(status)) {
7189                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7190                 return False;
7191         }
7192
7193         /* Ensure size == 20. */
7194         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7195         if (!NT_STATUS_IS_OK(status)) {
7196                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7197                 return False;
7198         }
7199
7200         if (fsize != 20) {
7201                 printf("(3) file size != 20\n");
7202                 return False;
7203         }
7204
7205         /* Now test if we can truncate a file opened for readonly. */
7206         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7207         if (!NT_STATUS_IS_OK(status)) {
7208                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7209                 return False;
7210         }
7211
7212         status = cli_close(cli1, fnum1);
7213         if (!NT_STATUS_IS_OK(status)) {
7214                 printf("close2 failed (%s)\n", nt_errstr(status));
7215                 return False;
7216         }
7217
7218         /* Ensure size == 0. */
7219         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7220         if (!NT_STATUS_IS_OK(status)) {
7221                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7222                 return False;
7223         }
7224
7225         if (fsize != 0) {
7226                 printf("(3) file size != 0\n");
7227                 return False;
7228         }
7229         printf("finished open test 3\n");
7230
7231         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7232
7233         printf("Do ctemp tests\n");
7234         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7235         if (!NT_STATUS_IS_OK(status)) {
7236                 printf("ctemp failed (%s)\n", nt_errstr(status));
7237                 return False;
7238         }
7239
7240         printf("ctemp gave path %s\n", tmp_path);
7241         status = cli_close(cli1, fnum1);
7242         if (!NT_STATUS_IS_OK(status)) {
7243                 printf("close of temp failed (%s)\n", nt_errstr(status));
7244         }
7245
7246         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7247         if (!NT_STATUS_IS_OK(status)) {
7248                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7249         }
7250
7251         /* Test the non-io opens... */
7252
7253         if (!torture_open_connection(&cli2, 1)) {
7254                 return False;
7255         }
7256
7257         cli_setatr(cli2, fname, 0, 0);
7258         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7259
7260         smbXcli_conn_set_sockopt(cli2->conn, sockops);
7261
7262         printf("TEST #1 testing 2 non-io opens (no delete)\n");
7263         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7264                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7265                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7266         if (!NT_STATUS_IS_OK(status)) {
7267                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7268                 return False;
7269         }
7270
7271         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7272                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7273                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7274         if (!NT_STATUS_IS_OK(status)) {
7275                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7276                 return False;
7277         }
7278
7279         status = cli_close(cli1, fnum1);
7280         if (!NT_STATUS_IS_OK(status)) {
7281                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7282                 return False;
7283         }
7284
7285         status = cli_close(cli2, fnum2);
7286         if (!NT_STATUS_IS_OK(status)) {
7287                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7288                 return False;
7289         }
7290
7291         printf("non-io open test #1 passed.\n");
7292
7293         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7294
7295         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7296
7297         status = cli_ntcreate(cli1, fname, 0,
7298                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7299                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7300                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7301         if (!NT_STATUS_IS_OK(status)) {
7302                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7303                 return False;
7304         }
7305
7306         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7307                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7308                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7309         if (!NT_STATUS_IS_OK(status)) {
7310                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7311                 return False;
7312         }
7313
7314         status = cli_close(cli1, fnum1);
7315         if (!NT_STATUS_IS_OK(status)) {
7316                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7317                 return False;
7318         }
7319
7320         status = cli_close(cli2, fnum2);
7321         if (!NT_STATUS_IS_OK(status)) {
7322                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7323                 return False;
7324         }
7325
7326         printf("non-io open test #2 passed.\n");
7327
7328         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7329
7330         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7331
7332         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7333                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7334                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7335         if (!NT_STATUS_IS_OK(status)) {
7336                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7337                 return False;
7338         }
7339
7340         status = cli_ntcreate(cli2, fname, 0,
7341                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7342                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7343                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7344         if (!NT_STATUS_IS_OK(status)) {
7345                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7346                 return False;
7347         }
7348
7349         status = cli_close(cli1, fnum1);
7350         if (!NT_STATUS_IS_OK(status)) {
7351                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7352                 return False;
7353         }
7354
7355         status = cli_close(cli2, fnum2);
7356         if (!NT_STATUS_IS_OK(status)) {
7357                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7358                 return False;
7359         }
7360
7361         printf("non-io open test #3 passed.\n");
7362
7363         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7364
7365         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7366
7367         status = cli_ntcreate(cli1, fname, 0,
7368                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7369                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7370                                FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7371         if (!NT_STATUS_IS_OK(status)) {
7372                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7373                 return False;
7374         }
7375
7376         status = cli_ntcreate(cli2, fname, 0,
7377                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7378                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7379                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7380         if (NT_STATUS_IS_OK(status)) {
7381                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7382                 return False;
7383         }
7384
7385         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7386
7387         status = cli_close(cli1, fnum1);
7388         if (!NT_STATUS_IS_OK(status)) {
7389                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7390                 return False;
7391         }
7392
7393         printf("non-io open test #4 passed.\n");
7394
7395         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7396
7397         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7398
7399         status = cli_ntcreate(cli1, fname, 0,
7400                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7401                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7402                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7403         if (!NT_STATUS_IS_OK(status)) {
7404                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7405                 return False;
7406         }
7407
7408         status = cli_ntcreate(cli2, fname, 0,
7409                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7410                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7411                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7412         if (!NT_STATUS_IS_OK(status)) {
7413                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7414                 return False;
7415         }
7416
7417         status = cli_close(cli1, fnum1);
7418         if (!NT_STATUS_IS_OK(status)) {
7419                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7420                 return False;
7421         }
7422
7423         status = cli_close(cli2, fnum2);
7424         if (!NT_STATUS_IS_OK(status)) {
7425                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7426                 return False;
7427         }
7428
7429         printf("non-io open test #5 passed.\n");
7430
7431         printf("TEST #6 testing 1 non-io open, one io open\n");
7432
7433         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7434
7435         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7436                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7437                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7438         if (!NT_STATUS_IS_OK(status)) {
7439                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7440                 return False;
7441         }
7442
7443         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7444                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7445                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7446         if (!NT_STATUS_IS_OK(status)) {
7447                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7448                 return False;
7449         }
7450
7451         status = cli_close(cli1, fnum1);
7452         if (!NT_STATUS_IS_OK(status)) {
7453                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7454                 return False;
7455         }
7456
7457         status = cli_close(cli2, fnum2);
7458         if (!NT_STATUS_IS_OK(status)) {
7459                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7460                 return False;
7461         }
7462
7463         printf("non-io open test #6 passed.\n");
7464
7465         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7466
7467         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7468
7469         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7470                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7471                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7472         if (!NT_STATUS_IS_OK(status)) {
7473                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7474                 return False;
7475         }
7476
7477         status = cli_ntcreate(cli2, fname, 0,
7478                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7479                               FILE_ATTRIBUTE_NORMAL,
7480                               FILE_SHARE_READ|FILE_SHARE_DELETE,
7481                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7482         if (NT_STATUS_IS_OK(status)) {
7483                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7484                 return False;
7485         }
7486
7487         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7488
7489         status = cli_close(cli1, fnum1);
7490         if (!NT_STATUS_IS_OK(status)) {
7491                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7492                 return False;
7493         }
7494
7495         printf("non-io open test #7 passed.\n");
7496
7497         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7498
7499         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7500         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7501                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7502                                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7503         if (!NT_STATUS_IS_OK(status)) {
7504                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7505                 correct = false;
7506                 goto out;
7507         }
7508
7509         /* Write to ensure we have to update the file time. */
7510         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7511                               NULL);
7512         if (!NT_STATUS_IS_OK(status)) {
7513                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7514                 correct = false;
7515                 goto out;
7516         }
7517
7518         status = cli_close(cli1, fnum1);
7519         if (!NT_STATUS_IS_OK(status)) {
7520                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7521                 correct = false;
7522         }
7523
7524   out:
7525
7526         if (!torture_close_connection(cli1)) {
7527                 correct = False;
7528         }
7529         if (!torture_close_connection(cli2)) {
7530                 correct = False;
7531         }
7532
7533         return correct;
7534 }
7535
7536 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7537 {
7538         uint16_t major, minor;
7539         uint32_t caplow, caphigh;
7540         NTSTATUS status;
7541
7542         if (!SERVER_HAS_UNIX_CIFS(cli)) {
7543                 printf("Server doesn't support UNIX CIFS extensions.\n");
7544                 return NT_STATUS_NOT_SUPPORTED;
7545         }
7546
7547         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7548                                              &caphigh);
7549         if (!NT_STATUS_IS_OK(status)) {
7550                 printf("Server didn't return UNIX CIFS extensions: %s\n",
7551                        nt_errstr(status));
7552                 return status;
7553         }
7554
7555         status = cli_set_unix_extensions_capabilities(cli, major, minor,
7556                                                       caplow, caphigh);
7557         if (!NT_STATUS_IS_OK(status)) {
7558                 printf("Server doesn't support setting UNIX CIFS extensions: "
7559                        "%s.\n", nt_errstr(status));
7560                 return status;
7561         }
7562
7563         return NT_STATUS_OK;
7564 }
7565
7566 /*
7567   Test POSIX open /mkdir calls.
7568  */
7569 static bool run_simple_posix_open_test(int dummy)
7570 {
7571         static struct cli_state *cli1;
7572         const char *fname = "posix:file";
7573         const char *hname = "posix:hlink";
7574         const char *sname = "posix:symlink";
7575         const char *dname = "posix:dir";
7576         char buf[10];
7577         char *target = NULL;
7578         uint16_t fnum1 = (uint16_t)-1;
7579         SMB_STRUCT_STAT sbuf;
7580         bool correct = false;
7581         NTSTATUS status;
7582         size_t nread;
7583         const char *fname_windows = "windows_file";
7584         uint16_t fnum2 = (uint16_t)-1;
7585
7586         printf("Starting simple POSIX open test\n");
7587
7588         if (!torture_open_connection(&cli1, 0)) {
7589                 return false;
7590         }
7591
7592         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7593
7594         status = torture_setup_unix_extensions(cli1);
7595         if (!NT_STATUS_IS_OK(status)) {
7596                 return false;
7597         }
7598
7599         cli_setatr(cli1, fname, 0, 0);
7600         cli_posix_unlink(cli1, fname);
7601         cli_setatr(cli1, dname, 0, 0);
7602         cli_posix_rmdir(cli1, dname);
7603         cli_setatr(cli1, hname, 0, 0);
7604         cli_posix_unlink(cli1, hname);
7605         cli_setatr(cli1, sname, 0, 0);
7606         cli_posix_unlink(cli1, sname);
7607         cli_setatr(cli1, fname_windows, 0, 0);
7608         cli_posix_unlink(cli1, fname_windows);
7609
7610         /* Create a directory. */
7611         status = cli_posix_mkdir(cli1, dname, 0777);
7612         if (!NT_STATUS_IS_OK(status)) {
7613                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7614                 goto out;
7615         }
7616
7617         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7618                                 0600, &fnum1);
7619         if (!NT_STATUS_IS_OK(status)) {
7620                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7621                 goto out;
7622         }
7623
7624         /* Test ftruncate - set file size. */
7625         status = cli_ftruncate(cli1, fnum1, 1000);
7626         if (!NT_STATUS_IS_OK(status)) {
7627                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7628                 goto out;
7629         }
7630
7631         /* Ensure st_size == 1000 */
7632         status = cli_posix_stat(cli1, fname, &sbuf);
7633         if (!NT_STATUS_IS_OK(status)) {
7634                 printf("stat failed (%s)\n", nt_errstr(status));
7635                 goto out;
7636         }
7637
7638         if (sbuf.st_ex_size != 1000) {
7639                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7640                 goto out;
7641         }
7642
7643         /* Ensure st_mode == 0600 */
7644         if ((sbuf.st_ex_mode & 07777) != 0600) {
7645                 printf("posix_open - bad permissions 0%o != 0600\n",
7646                                 (unsigned int)(sbuf.st_ex_mode & 07777));
7647                 goto out;
7648         }
7649
7650         /* Test ftruncate - set file size back to zero. */
7651         status = cli_ftruncate(cli1, fnum1, 0);
7652         if (!NT_STATUS_IS_OK(status)) {
7653                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7654                 goto out;
7655         }
7656
7657         status = cli_close(cli1, fnum1);
7658         if (!NT_STATUS_IS_OK(status)) {
7659                 printf("close failed (%s)\n", nt_errstr(status));
7660                 goto out;
7661         }
7662
7663         /* Now open the file again for read only. */
7664         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7665         if (!NT_STATUS_IS_OK(status)) {
7666                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7667                 goto out;
7668         }
7669
7670         /* Now unlink while open. */
7671         status = cli_posix_unlink(cli1, fname);
7672         if (!NT_STATUS_IS_OK(status)) {
7673                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7674                 goto out;
7675         }
7676
7677         status = cli_close(cli1, fnum1);
7678         if (!NT_STATUS_IS_OK(status)) {
7679                 printf("close(2) failed (%s)\n", nt_errstr(status));
7680                 goto out;
7681         }
7682
7683         /* Ensure the file has gone. */
7684         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7685         if (NT_STATUS_IS_OK(status)) {
7686                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7687                 goto out;
7688         }
7689
7690         /* Create again to test open with O_TRUNC. */
7691         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7692         if (!NT_STATUS_IS_OK(status)) {
7693                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7694                 goto out;
7695         }
7696
7697         /* Test ftruncate - set file size. */
7698         status = cli_ftruncate(cli1, fnum1, 1000);
7699         if (!NT_STATUS_IS_OK(status)) {
7700                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7701                 goto out;
7702         }
7703
7704         /* Ensure st_size == 1000 */
7705         status = cli_posix_stat(cli1, fname, &sbuf);
7706         if (!NT_STATUS_IS_OK(status)) {
7707                 printf("stat failed (%s)\n", nt_errstr(status));
7708                 goto out;
7709         }
7710
7711         if (sbuf.st_ex_size != 1000) {
7712                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7713                 goto out;
7714         }
7715
7716         status = cli_close(cli1, fnum1);
7717         if (!NT_STATUS_IS_OK(status)) {
7718                 printf("close(2) failed (%s)\n", nt_errstr(status));
7719                 goto out;
7720         }
7721
7722         /* Re-open with O_TRUNC. */
7723         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7724         if (!NT_STATUS_IS_OK(status)) {
7725                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7726                 goto out;
7727         }
7728
7729         /* Ensure st_size == 0 */
7730         status = cli_posix_stat(cli1, fname, &sbuf);
7731         if (!NT_STATUS_IS_OK(status)) {
7732                 printf("stat failed (%s)\n", nt_errstr(status));
7733                 goto out;
7734         }
7735
7736         if (sbuf.st_ex_size != 0) {
7737                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7738                 goto out;
7739         }
7740
7741         status = cli_close(cli1, fnum1);
7742         if (!NT_STATUS_IS_OK(status)) {
7743                 printf("close failed (%s)\n", nt_errstr(status));
7744                 goto out;
7745         }
7746
7747         status = cli_posix_unlink(cli1, fname);
7748         if (!NT_STATUS_IS_OK(status)) {
7749                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7750                 goto out;
7751         }
7752
7753         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
7754         if (!NT_STATUS_IS_OK(status)) {
7755                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
7756                         dname, nt_errstr(status));
7757                 goto out;
7758         }
7759
7760         cli_close(cli1, fnum1);
7761
7762         /* What happens when we try and POSIX open a directory for write ? */
7763         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
7764         if (NT_STATUS_IS_OK(status)) {
7765                 printf("POSIX open of directory %s succeeded, "
7766                        "should have failed.\n",
7767                        dname);
7768                 goto out;
7769         } else {
7770                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
7771                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
7772                         goto out;
7773                 }
7774         }
7775
7776         /* Create the file. */
7777         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7778                                 0600, &fnum1);
7779         if (!NT_STATUS_IS_OK(status)) {
7780                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7781                 goto out;
7782         }
7783
7784         /* Write some data into it. */
7785         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7786                               NULL);
7787         if (!NT_STATUS_IS_OK(status)) {
7788                 printf("cli_write failed: %s\n", nt_errstr(status));
7789                 goto out;
7790         }
7791
7792         cli_close(cli1, fnum1);
7793
7794         /* Now create a hardlink. */
7795         status = cli_posix_hardlink(cli1, fname, hname);
7796         if (!NT_STATUS_IS_OK(status)) {
7797                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
7798                 goto out;
7799         }
7800
7801         /* Now create a symlink. */
7802         status = cli_posix_symlink(cli1, fname, sname);
7803         if (!NT_STATUS_IS_OK(status)) {
7804                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
7805                 goto out;
7806         }
7807
7808         /* Open the hardlink for read. */
7809         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
7810         if (!NT_STATUS_IS_OK(status)) {
7811                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
7812                 goto out;
7813         }
7814
7815         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
7816         if (!NT_STATUS_IS_OK(status)) {
7817                 printf("POSIX read of %s failed (%s)\n", hname,
7818                        nt_errstr(status));
7819                 goto out;
7820         } else if (nread != 10) {
7821                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
7822                        hname, (unsigned long)nread, 10);
7823                 goto out;
7824         }
7825
7826         if (memcmp(buf, "TEST DATA\n", 10)) {
7827                 printf("invalid data read from hardlink\n");
7828                 goto out;
7829         }
7830
7831         /* Do a POSIX lock/unlock. */
7832         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
7833         if (!NT_STATUS_IS_OK(status)) {
7834                 printf("POSIX lock failed %s\n", nt_errstr(status));
7835                 goto out;
7836         }
7837
7838         /* Punch a hole in the locked area. */
7839         status = cli_posix_unlock(cli1, fnum1, 10, 80);
7840         if (!NT_STATUS_IS_OK(status)) {
7841                 printf("POSIX unlock failed %s\n", nt_errstr(status));
7842                 goto out;
7843         }
7844
7845         cli_close(cli1, fnum1);
7846
7847         /* Open the symlink for read - this should fail. A POSIX
7848            client should not be doing opens on a symlink. */
7849         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
7850         if (NT_STATUS_IS_OK(status)) {
7851                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
7852                 goto out;
7853         } else {
7854                 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
7855                                 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
7856                         printf("POSIX open of %s should have failed "
7857                                 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
7858                                 "failed with %s instead.\n",
7859                                 sname, nt_errstr(status));
7860                         goto out;
7861                 }
7862         }
7863
7864         status = cli_posix_readlink(cli1, sname, talloc_tos(), &target);
7865         if (!NT_STATUS_IS_OK(status)) {
7866                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
7867                 goto out;
7868         }
7869
7870         if (strcmp(target, fname) != 0) {
7871                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
7872                         sname, fname, target);
7873                 goto out;
7874         }
7875
7876         status = cli_posix_rmdir(cli1, dname);
7877         if (!NT_STATUS_IS_OK(status)) {
7878                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
7879                 goto out;
7880         }
7881
7882         /* Check directory opens with a specific permission. */
7883         status = cli_posix_mkdir(cli1, dname, 0700);
7884         if (!NT_STATUS_IS_OK(status)) {
7885                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7886                 goto out;
7887         }
7888
7889         /* Ensure st_mode == 0700 */
7890         status = cli_posix_stat(cli1, dname, &sbuf);
7891         if (!NT_STATUS_IS_OK(status)) {
7892                 printf("stat failed (%s)\n", nt_errstr(status));
7893                 goto out;
7894         }
7895
7896         if ((sbuf.st_ex_mode & 07777) != 0700) {
7897                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
7898                                 (unsigned int)(sbuf.st_ex_mode & 07777));
7899                 goto out;
7900         }
7901
7902         /*
7903          * Now create a Windows file, and attempt a POSIX unlink.
7904          * This should fail with a sharing violation but due to:
7905          *
7906          * [Bug 9571] Unlink after open causes smbd to panic
7907          *
7908          * ensure we've fixed the lock ordering violation.
7909          */
7910
7911         status = cli_ntcreate(cli1, fname_windows, 0,
7912                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
7913                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7914                         FILE_CREATE,
7915                         0x0, 0x0, &fnum2, NULL);
7916         if (!NT_STATUS_IS_OK(status)) {
7917                 printf("Windows create of %s failed (%s)\n", fname_windows,
7918                         nt_errstr(status));
7919                 goto out;
7920         }
7921
7922         /* Now try posix_unlink. */
7923         status = cli_posix_unlink(cli1, fname_windows);
7924         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7925                 printf("POSIX unlink of %s should fail "
7926                         "with NT_STATUS_SHARING_VIOLATION "
7927                         "got %s instead !\n",
7928                         fname_windows,
7929                         nt_errstr(status));
7930                 goto out;
7931         }
7932
7933         cli_close(cli1, fnum2);
7934
7935         printf("Simple POSIX open test passed\n");
7936         correct = true;
7937
7938   out:
7939
7940         if (fnum1 != (uint16_t)-1) {
7941                 cli_close(cli1, fnum1);
7942                 fnum1 = (uint16_t)-1;
7943         }
7944
7945         if (fnum2 != (uint16_t)-1) {
7946                 cli_close(cli1, fnum2);
7947                 fnum2 = (uint16_t)-1;
7948         }
7949
7950         cli_setatr(cli1, sname, 0, 0);
7951         cli_posix_unlink(cli1, sname);
7952         cli_setatr(cli1, hname, 0, 0);
7953         cli_posix_unlink(cli1, hname);
7954         cli_setatr(cli1, fname, 0, 0);
7955         cli_posix_unlink(cli1, fname);
7956         cli_setatr(cli1, dname, 0, 0);
7957         cli_posix_rmdir(cli1, dname);
7958         cli_setatr(cli1, fname_windows, 0, 0);
7959         cli_posix_unlink(cli1, fname_windows);
7960
7961         if (!torture_close_connection(cli1)) {
7962                 correct = false;
7963         }
7964
7965         return correct;
7966 }
7967
7968 /*
7969   Test POSIX and Windows ACLs are rejected on symlinks.
7970  */
7971 static bool run_acl_symlink_test(int dummy)
7972 {
7973         static struct cli_state *cli;
7974         const char *fname = "posix_file";
7975         const char *sname = "posix_symlink";
7976         uint16_t fnum = (uint16_t)-1;
7977         bool correct = false;
7978         NTSTATUS status;
7979         char *posix_acl = NULL;
7980         size_t posix_acl_len = 0;
7981         char *posix_acl_sym = NULL;
7982         size_t posix_acl_len_sym = 0;
7983         struct security_descriptor *sd = NULL;
7984         struct security_descriptor *sd_sym = NULL;
7985         TALLOC_CTX *frame = NULL;
7986
7987         frame = talloc_stackframe();
7988
7989         printf("Starting acl symlink test\n");
7990
7991         if (!torture_open_connection(&cli, 0)) {
7992                 TALLOC_FREE(frame);
7993                 return false;
7994         }
7995
7996         smbXcli_conn_set_sockopt(cli->conn, sockops);
7997
7998         status = torture_setup_unix_extensions(cli);
7999         if (!NT_STATUS_IS_OK(status)) {
8000                 TALLOC_FREE(frame);
8001                 return false;
8002         }
8003
8004         cli_setatr(cli, fname, 0, 0);
8005         cli_posix_unlink(cli, fname);
8006         cli_setatr(cli, sname, 0, 0);
8007         cli_posix_unlink(cli, sname);
8008
8009         status = cli_ntcreate(cli,
8010                         fname,
8011                         0,
8012                         READ_CONTROL_ACCESS,
8013                         0,
8014                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8015                         FILE_CREATE,
8016                         0x0,
8017                         0x0,
8018                         &fnum,
8019                         NULL);
8020
8021         if (!NT_STATUS_IS_OK(status)) {
8022                 printf("cli_ntcreate of %s failed (%s)\n",
8023                         fname,
8024                         nt_errstr(status));
8025                 goto out;
8026         }
8027
8028         /* Get the Windows ACL on the file. */
8029         status = cli_query_secdesc(cli,
8030                                 fnum,
8031                                 frame,
8032                                 &sd);
8033         if (!NT_STATUS_IS_OK(status)) {
8034                 printf("cli_query_secdesc failed (%s)\n",
8035                         nt_errstr(status));
8036                 goto out;
8037         }
8038
8039         /* Get the POSIX ACL on the file. */
8040         status = cli_posix_getacl(cli,
8041                                 fname,
8042                                 frame,
8043                                 &posix_acl_len,
8044                                 &posix_acl);
8045
8046         if (!NT_STATUS_IS_OK(status)) {
8047                 printf("cli_posix_getacl failed (%s)\n",
8048                         nt_errstr(status));
8049                 goto out;
8050         }
8051
8052         status = cli_close(cli, fnum);
8053         if (!NT_STATUS_IS_OK(status)) {
8054                 printf("close failed (%s)\n", nt_errstr(status));
8055                 goto out;
8056         }
8057         fnum = (uint16_t)-1;
8058
8059         /* Now create a symlink. */
8060         status = cli_posix_symlink(cli, fname, sname);
8061         if (!NT_STATUS_IS_OK(status)) {
8062                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8063                         sname,
8064                         fname,
8065                         nt_errstr(status));
8066                 goto out;
8067         }
8068
8069         /* Open a handle on the symlink for SD set/get should fail. */
8070         status = cli_ntcreate(cli,
8071                         sname,
8072                         0,
8073                         READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8074                         0,
8075                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8076                         FILE_OPEN,
8077                         0x0,
8078                         0x0,
8079                         &fnum,
8080                         NULL);
8081
8082         if (NT_STATUS_IS_OK(status)) {
8083                 printf("Symlink open for getsd/setsd of %s "
8084                         "succeeded (should fail)\n",
8085                         sname);
8086                 goto out;
8087         }
8088
8089         /* Open a handle on the symlink. */
8090         status = cli_ntcreate(cli,
8091                         sname,
8092                         0,
8093                         FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8094                         0,
8095                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8096                         FILE_OPEN,
8097                         0x0,
8098                         0x0,
8099                         &fnum,
8100                         NULL);
8101
8102         if (!NT_STATUS_IS_OK(status)) {
8103                 printf("cli_posix_open of %s failed (%s)\n",
8104                         sname,
8105                         nt_errstr(status));
8106                 goto out;
8107         }
8108
8109         /* Get the Windows ACL on the symlink handle. Should fail */
8110         status = cli_query_secdesc(cli,
8111                                 fnum,
8112                                 frame,
8113                                 &sd_sym);
8114
8115         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8116                 printf("cli_query_secdesc on a symlink gave %s. "
8117                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8118                         nt_errstr(status));
8119                 goto out;
8120         }
8121
8122         /* Get the POSIX ACL on the symlink pathname. Should fail. */
8123         status = cli_posix_getacl(cli,
8124                                 sname,
8125                                 frame,
8126                                 &posix_acl_len_sym,
8127                                 &posix_acl_sym);
8128
8129         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8130                 printf("cli_posix_getacl on a symlink gave %s. "
8131                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8132                         nt_errstr(status));
8133                 goto out;
8134         }
8135
8136         /* Set the Windows ACL on the symlink handle. Should fail */
8137         status = cli_set_security_descriptor(cli,
8138                                 fnum,
8139                                 SECINFO_DACL,
8140                                 sd);
8141
8142         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8143                 printf("cli_query_secdesc on a symlink gave %s. "
8144                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8145                         nt_errstr(status));
8146                 goto out;
8147         }
8148
8149         /* Set the POSIX ACL on the symlink pathname. Should fail. */
8150         status = cli_posix_setacl(cli,
8151                                 sname,
8152                                 posix_acl,
8153                                 posix_acl_len);
8154
8155         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8156                 printf("cli_posix_setacl on a symlink gave %s. "
8157                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8158                         nt_errstr(status));
8159                 goto out;
8160         }
8161
8162         printf("ACL symlink test passed\n");
8163         correct = true;
8164
8165   out:
8166
8167         if (fnum != (uint16_t)-1) {
8168                 cli_close(cli, fnum);
8169                 fnum = (uint16_t)-1;
8170         }
8171
8172         cli_setatr(cli, sname, 0, 0);
8173         cli_posix_unlink(cli, sname);
8174         cli_setatr(cli, fname, 0, 0);
8175         cli_posix_unlink(cli, fname);
8176
8177         if (!torture_close_connection(cli)) {
8178                 correct = false;
8179         }
8180
8181         TALLOC_FREE(frame);
8182         return correct;
8183 }
8184
8185 /*
8186   Test POSIX can delete a file containing streams.
8187  */
8188 static bool run_posix_stream_delete(int dummy)
8189 {
8190         struct cli_state *cli1 = NULL;
8191         struct cli_state *cli2 = NULL;
8192         const char *fname = "streamfile";
8193         const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8194         uint16_t fnum1 = (uint16_t)-1;
8195         bool correct = false;
8196         NTSTATUS status;
8197         TALLOC_CTX *frame = NULL;
8198
8199         frame = talloc_stackframe();
8200
8201         printf("Starting POSIX stream delete test\n");
8202
8203         if (!torture_open_connection(&cli1, 0) ||
8204                         !torture_open_connection(&cli2, 1)) {
8205                 TALLOC_FREE(frame);
8206                 return false;
8207         }
8208
8209         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8210         smbXcli_conn_set_sockopt(cli2->conn, sockops);
8211
8212         status = torture_setup_unix_extensions(cli2);
8213         if (!NT_STATUS_IS_OK(status)) {
8214                 goto out;
8215         }
8216
8217         cli_setatr(cli1, fname, 0, 0);
8218         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8219
8220         /* Create the file. */
8221         status = cli_ntcreate(cli1,
8222                         fname,
8223                         0,
8224                         READ_CONTROL_ACCESS,
8225                         0,
8226                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8227                         FILE_CREATE,
8228                         0x0,
8229                         0x0,
8230                         &fnum1,
8231                         NULL);
8232
8233         if (!NT_STATUS_IS_OK(status)) {
8234                 printf("cli_ntcreate of %s failed (%s)\n",
8235                         fname,
8236                         nt_errstr(status));
8237                 goto out;
8238         }
8239
8240         status = cli_close(cli1, fnum1);
8241         if (!NT_STATUS_IS_OK(status)) {
8242                 printf("cli_close of %s failed (%s)\n",
8243                         fname,
8244                         nt_errstr(status));
8245                 goto out;
8246         }
8247         fnum1 = (uint16_t)-1;
8248
8249         /* Now create the stream. */
8250         status = cli_ntcreate(cli1,
8251                         stream_fname,
8252                         0,
8253                         FILE_WRITE_DATA,
8254                         0,
8255                         FILE_SHARE_READ|FILE_SHARE_WRITE,
8256                         FILE_CREATE,
8257                         0x0,
8258                         0x0,
8259                         &fnum1,
8260                         NULL);
8261
8262         if (!NT_STATUS_IS_OK(status)) {
8263                 printf("cli_ntcreate of %s failed (%s)\n",
8264                         stream_fname,
8265                         nt_errstr(status));
8266                 goto out;
8267         }
8268
8269         /* Leave the stream handle open... */
8270
8271         /* POSIX unlink should fail. */
8272         status = cli_posix_unlink(cli2, fname);
8273         if (NT_STATUS_IS_OK(status)) {
8274                 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8275                         fname);
8276                 goto out;
8277         }
8278
8279         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8280                 printf("cli_posix_unlink of %s failed with (%s) "
8281                         "should have been NT_STATUS_SHARING_VIOLATION\n",
8282                         fname,
8283                         nt_errstr(status));
8284                 goto out;
8285         }
8286
8287         /* Close the stream handle. */
8288         status = cli_close(cli1, fnum1);
8289         if (!NT_STATUS_IS_OK(status)) {
8290                 printf("cli_close of %s failed (%s)\n",
8291                         stream_fname,
8292                         nt_errstr(status));
8293                 goto out;
8294         }
8295         fnum1 = (uint16_t)-1;
8296
8297         /* POSIX unlink after stream handle closed should succeed. */
8298         status = cli_posix_unlink(cli2, fname);
8299         if (!NT_STATUS_IS_OK(status)) {
8300                 printf("cli_posix_unlink of %s failed (%s)\n",
8301                         fname,
8302                         nt_errstr(status));
8303                 goto out;
8304         }
8305
8306         printf("POSIX stream delete test passed\n");
8307         correct = true;
8308
8309   out:
8310
8311         if (fnum1 != (uint16_t)-1) {
8312                 cli_close(cli1, fnum1);
8313                 fnum1 = (uint16_t)-1;
8314         }
8315
8316         cli_setatr(cli1, fname, 0, 0);
8317         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8318
8319         if (!torture_close_connection(cli1)) {
8320                 correct = false;
8321         }
8322         if (!torture_close_connection(cli2)) {
8323                 correct = false;
8324         }
8325
8326         TALLOC_FREE(frame);
8327         return correct;
8328 }
8329
8330 /*
8331   Test setting EA's are rejected on symlinks.
8332  */
8333 static bool run_ea_symlink_test(int dummy)
8334 {
8335         static struct cli_state *cli;
8336         const char *fname = "posix_file_ea";
8337         const char *sname = "posix_symlink_ea";
8338         const char *ea_name = "testea_name";
8339         const char *ea_value = "testea_value";
8340         uint16_t fnum = (uint16_t)-1;
8341         bool correct = false;
8342         NTSTATUS status;
8343         size_t i, num_eas;
8344         struct ea_struct *eas = NULL;
8345         TALLOC_CTX *frame = NULL;
8346
8347         frame = talloc_stackframe();
8348
8349         printf("Starting EA symlink test\n");
8350
8351         if (!torture_open_connection(&cli, 0)) {
8352                 TALLOC_FREE(frame);
8353                 return false;
8354         }
8355
8356         smbXcli_conn_set_sockopt(cli->conn, sockops);
8357
8358         status = torture_setup_unix_extensions(cli);
8359         if (!NT_STATUS_IS_OK(status)) {
8360                 TALLOC_FREE(frame);
8361                 return false;
8362         }
8363
8364         cli_setatr(cli, fname, 0, 0);
8365         cli_posix_unlink(cli, fname);
8366         cli_setatr(cli, sname, 0, 0);
8367         cli_posix_unlink(cli, sname);
8368
8369         status = cli_ntcreate(cli,
8370                         fname,
8371                         0,
8372                         READ_CONTROL_ACCESS,
8373                         0,
8374                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8375                         FILE_CREATE,
8376                         0x0,
8377                         0x0,
8378                         &fnum,
8379                         NULL);
8380
8381         if (!NT_STATUS_IS_OK(status)) {
8382                 printf("cli_ntcreate of %s failed (%s)\n",
8383                         fname,
8384                         nt_errstr(status));
8385                 goto out;
8386         }
8387
8388         status = cli_close(cli, fnum);
8389         if (!NT_STATUS_IS_OK(status)) {
8390                 printf("close failed (%s)\n",
8391                         nt_errstr(status));
8392                 goto out;
8393         }
8394         fnum = (uint16_t)-1;
8395
8396         /* Set an EA on the path. */
8397         status = cli_set_ea_path(cli,
8398                                 fname,
8399                                 ea_name,
8400                                 ea_value,
8401                                 strlen(ea_value)+1);
8402
8403         if (!NT_STATUS_IS_OK(status)) {
8404                 printf("cli_set_ea_path failed (%s)\n",
8405                         nt_errstr(status));
8406                 goto out;
8407         }
8408
8409         /* Now create a symlink. */
8410         status = cli_posix_symlink(cli, fname, sname);
8411         if (!NT_STATUS_IS_OK(status)) {
8412                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8413                         sname,
8414                         fname,
8415                         nt_errstr(status));
8416                 goto out;
8417         }
8418
8419         /* Get the EA list on the path. Should return value set. */
8420         status = cli_get_ea_list_path(cli,
8421                                 fname,
8422                                 frame,
8423                                 &num_eas,
8424                                 &eas);
8425
8426         if (!NT_STATUS_IS_OK(status)) {
8427                 printf("cli_get_ea_list_path failed (%s)\n",
8428                         nt_errstr(status));
8429                 goto out;
8430         }
8431
8432         /* Ensure the EA we set is there. */
8433         for (i=0; i<num_eas; i++) {
8434                 if (strcmp(eas[i].name, ea_name) == 0 &&
8435                                 eas[i].value.length == strlen(ea_value)+1 &&
8436                                 memcmp(eas[i].value.data,
8437                                         ea_value,
8438                                         eas[i].value.length) == 0) {
8439                         break;
8440                 }
8441         }
8442
8443         if (i == num_eas) {
8444                 printf("Didn't find EA on pathname %s\n",
8445                         fname);
8446                 goto out;
8447         }
8448
8449         num_eas = 0;
8450         TALLOC_FREE(eas);
8451
8452         /* Get the EA list on the symlink. Should return empty list. */
8453         status = cli_get_ea_list_path(cli,
8454                                 sname,
8455                                 frame,
8456                                 &num_eas,
8457                                 &eas);
8458
8459         if (!NT_STATUS_IS_OK(status)) {
8460                 printf("cli_get_ea_list_path failed (%s)\n",
8461                         nt_errstr(status));
8462                 goto out;
8463         }
8464
8465         if (num_eas != 0) {
8466                 printf("cli_get_ea_list_path failed (%s)\n",
8467                         nt_errstr(status));
8468                 goto out;
8469         }
8470
8471         /* Set an EA on the symlink. Should fail. */
8472         status = cli_set_ea_path(cli,
8473                                 sname,
8474                                 ea_name,
8475                                 ea_value,
8476                                 strlen(ea_value)+1);
8477
8478         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8479                 printf("cli_set_ea_path on a symlink gave %s. "
8480                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8481                         nt_errstr(status));
8482                 goto out;
8483         }
8484
8485         printf("EA symlink test passed\n");
8486         correct = true;
8487
8488   out:
8489
8490         if (fnum != (uint16_t)-1) {
8491                 cli_close(cli, fnum);
8492                 fnum = (uint16_t)-1;
8493         }
8494
8495         cli_setatr(cli, sname, 0, 0);
8496         cli_posix_unlink(cli, sname);
8497         cli_setatr(cli, fname, 0, 0);
8498         cli_posix_unlink(cli, fname);
8499
8500         if (!torture_close_connection(cli)) {
8501                 correct = false;
8502         }
8503
8504         TALLOC_FREE(frame);
8505         return correct;
8506 }
8507
8508 /*
8509   Test POSIX locks are OFD-locks.
8510  */
8511 static bool run_posix_ofd_lock_test(int dummy)
8512 {
8513         static struct cli_state *cli;
8514         const char *fname = "posix_file";
8515         uint16_t fnum1 = (uint16_t)-1;
8516         uint16_t fnum2 = (uint16_t)-1;
8517         bool correct = false;
8518         NTSTATUS status;
8519         TALLOC_CTX *frame = NULL;
8520
8521         frame = talloc_stackframe();
8522
8523         printf("Starting POSIX ofd-lock test\n");
8524
8525         if (!torture_open_connection(&cli, 0)) {
8526                 TALLOC_FREE(frame);
8527                 return false;
8528         }
8529
8530         smbXcli_conn_set_sockopt(cli->conn, sockops);
8531
8532         status = torture_setup_unix_extensions(cli);
8533         if (!NT_STATUS_IS_OK(status)) {
8534                 TALLOC_FREE(frame);
8535                 return false;
8536         }
8537
8538         cli_setatr(cli, fname, 0, 0);
8539         cli_posix_unlink(cli, fname);
8540
8541         /* Open the file twice. */
8542         status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8543                                 0600, &fnum1);
8544         if (!NT_STATUS_IS_OK(status)) {
8545                 printf("First POSIX open of %s failed\n", fname);
8546                 goto out;
8547         }
8548
8549         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8550         if (!NT_STATUS_IS_OK(status)) {
8551                 printf("First POSIX open of %s failed\n", fname);
8552                 goto out;
8553         }
8554
8555         /* Set a 0-50 lock on fnum1. */
8556         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8557         if (!NT_STATUS_IS_OK(status)) {
8558                 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8559                 goto out;
8560         }
8561
8562         /* Set a 60-100 lock on fnum2. */
8563         status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8564         if (!NT_STATUS_IS_OK(status)) {
8565                 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8566                 goto out;
8567         }
8568
8569         /* close fnum1 - 0-50 lock should go away. */
8570         status = cli_close(cli, fnum1);
8571         if (!NT_STATUS_IS_OK(status)) {
8572                 printf("close failed (%s)\n",
8573                         nt_errstr(status));
8574                 goto out;
8575         }
8576         fnum1 = (uint16_t)-1;
8577
8578         /* Change the lock context. */
8579         cli_setpid(cli, cli_getpid(cli) + 1);
8580
8581         /* Re-open fnum1. */
8582         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8583         if (!NT_STATUS_IS_OK(status)) {
8584                 printf("Third POSIX open of %s failed\n", fname);
8585                 goto out;
8586         }
8587
8588         /* 60-100 lock should still be there. */
8589         status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8590         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8591                 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8592                 goto out;
8593         }
8594
8595         /* 0-50 lock should be gone. */
8596         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8597         if (!NT_STATUS_IS_OK(status)) {
8598                 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8599                 goto out;
8600         }
8601
8602         printf("POSIX OFD lock test passed\n");
8603         correct = true;
8604
8605   out:
8606
8607         if (fnum1 != (uint16_t)-1) {
8608                 cli_close(cli, fnum1);
8609                 fnum1 = (uint16_t)-1;
8610         }
8611         if (fnum2 != (uint16_t)-1) {
8612                 cli_close(cli, fnum2);
8613                 fnum2 = (uint16_t)-1;
8614         }
8615
8616         cli_setatr(cli, fname, 0, 0);
8617         cli_posix_unlink(cli, fname);
8618
8619         if (!torture_close_connection(cli)) {
8620                 correct = false;
8621         }
8622
8623         TALLOC_FREE(frame);
8624         return correct;
8625 }
8626
8627 struct posix_blocking_state {
8628         struct tevent_context *ev;
8629         struct cli_state *cli1;
8630         uint16_t fnum1;
8631         struct cli_state *cli2;
8632         uint16_t fnum2;
8633         bool gotblocked;
8634         bool gotecho;
8635 };
8636
8637 static void posix_blocking_locked(struct tevent_req *subreq);
8638 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8639 static void posix_blocking_gotecho(struct tevent_req *subreq);
8640 static void posix_blocking_unlocked(struct tevent_req *subreq);
8641
8642 static struct tevent_req *posix_blocking_send(
8643         TALLOC_CTX *mem_ctx,
8644         struct tevent_context *ev,
8645         struct cli_state *cli1,
8646         uint16_t fnum1,
8647         struct cli_state *cli2,
8648         uint16_t fnum2)
8649 {
8650         struct tevent_req *req = NULL, *subreq = NULL;
8651         struct posix_blocking_state *state = NULL;
8652
8653         req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8654         if (req == NULL) {
8655                 return NULL;
8656         }
8657         state->ev = ev;
8658         state->cli1 = cli1;
8659         state->fnum1 = fnum1;
8660         state->cli2 = cli2;
8661         state->fnum2 = fnum2;
8662
8663         subreq = cli_posix_lock_send(
8664                 state,
8665                 state->ev,
8666                 state->cli1,
8667                 state->fnum1,
8668                 0,
8669                 1,
8670                 false,
8671                 WRITE_LOCK);
8672         if (tevent_req_nomem(subreq, req)) {
8673                 return tevent_req_post(req, ev);
8674         }
8675         tevent_req_set_callback(subreq, posix_blocking_locked, req);
8676         return req;
8677 }
8678
8679 static void posix_blocking_locked(struct tevent_req *subreq)
8680 {
8681         struct tevent_req *req = tevent_req_callback_data(
8682                 subreq, struct tevent_req);
8683         struct posix_blocking_state *state = tevent_req_data(
8684                 req, struct posix_blocking_state);
8685         NTSTATUS status;
8686
8687         status = cli_posix_lock_recv(subreq);
8688         TALLOC_FREE(subreq);
8689         if (tevent_req_nterror(req, status)) {
8690                 return;
8691         }
8692
8693         subreq = cli_posix_lock_send(
8694                 state,
8695                 state->ev,
8696                 state->cli2,
8697                 state->fnum2,
8698                 0,
8699                 1,
8700                 true,
8701                 WRITE_LOCK);
8702         if (tevent_req_nomem(subreq, req)) {
8703                 return;
8704         }
8705         tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8706
8707         /* Make sure the blocking request is delivered */
8708         subreq = cli_echo_send(
8709                 state,
8710                 state->ev,
8711                 state->cli2,
8712                 1,
8713                 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8714         if (tevent_req_nomem(subreq, req)) {
8715                 return;
8716         }
8717         tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8718 }
8719
8720 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8721 {
8722         struct tevent_req *req = tevent_req_callback_data(
8723                 subreq, struct tevent_req);
8724         struct posix_blocking_state *state = tevent_req_data(
8725                 req, struct posix_blocking_state);
8726         NTSTATUS status;
8727
8728         status = cli_posix_lock_recv(subreq);
8729         TALLOC_FREE(subreq);
8730         if (tevent_req_nterror(req, status)) {
8731                 return;
8732         }
8733         if (!state->gotecho) {
8734                 printf("blocked req got through before echo\n");
8735                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8736                 return;
8737         }
8738         tevent_req_done(req);
8739 }
8740
8741 static void posix_blocking_gotecho(struct tevent_req *subreq)
8742 {
8743         struct tevent_req *req = tevent_req_callback_data(
8744                 subreq, struct tevent_req);
8745         struct posix_blocking_state *state = tevent_req_data(
8746                 req, struct posix_blocking_state);
8747         NTSTATUS status;
8748
8749         status = cli_echo_recv(subreq);
8750         TALLOC_FREE(subreq);
8751         if (tevent_req_nterror(req, status)) {
8752                 return;
8753         }
8754         if (state->gotblocked) {
8755                 printf("blocked req got through before echo\n");
8756                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8757                 return;
8758         }
8759         state->gotecho = true;
8760
8761         subreq = cli_posix_lock_send(
8762                 state,
8763                 state->ev,
8764                 state->cli1,
8765                 state->fnum1,
8766                 0,
8767                 1,
8768                 false,
8769                 UNLOCK_LOCK);
8770         if (tevent_req_nomem(subreq, req)) {
8771                 return;
8772         }
8773         tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
8774 }
8775
8776 static void posix_blocking_unlocked(struct tevent_req *subreq)
8777 {
8778         struct tevent_req *req = tevent_req_callback_data(
8779                 subreq, struct tevent_req);
8780         NTSTATUS status;
8781
8782         status = cli_posix_lock_recv(subreq);
8783         TALLOC_FREE(subreq);
8784         if (tevent_req_nterror(req, status)) {
8785                 return;
8786         }
8787         /* tevent_req_done in posix_blocking_gotlocked */
8788 }
8789
8790 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
8791 {
8792         return tevent_req_simple_recv_ntstatus(req);
8793 }
8794
8795 static bool run_posix_blocking_lock(int dummy)
8796 {
8797         struct tevent_context *ev = NULL;
8798         struct cli_state *cli1 = NULL, *cli2 = NULL;
8799         const char *fname = "posix_blocking";
8800         uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
8801         struct tevent_req *req = NULL;
8802         NTSTATUS status;
8803         bool ret = false;
8804         bool ok;
8805
8806         printf("Starting posix blocking lock test\n");
8807
8808         ev = samba_tevent_context_init(NULL);
8809         if (ev == NULL) {
8810                 return false;
8811         }
8812
8813         ok = torture_open_connection(&cli1, 0);
8814         if (!ok) {
8815                 goto fail;
8816         }
8817         ok = torture_open_connection(&cli2, 0);
8818         if (!ok) {
8819                 goto fail;
8820         }
8821
8822         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8823
8824         status = torture_setup_unix_extensions(cli1);
8825         if (!NT_STATUS_IS_OK(status)) {
8826                 return false;
8827         }
8828
8829         cli_setatr(cli1, fname, 0, 0);
8830         cli_posix_unlink(cli1, fname);
8831
8832         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8833                                 0600, &fnum1);
8834         if (!NT_STATUS_IS_OK(status)) {
8835                 printf("First POSIX open of %s failed: %s\n",
8836                        fname,
8837                        nt_errstr(status));
8838                 goto fail;
8839         }
8840
8841         status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
8842         if (!NT_STATUS_IS_OK(status)) {
8843                 printf("Second POSIX open of %s failed: %s\n",
8844                        fname,
8845                        nt_errstr(status));
8846                 goto fail;
8847         }
8848
8849         req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
8850         if (req == NULL) {
8851                 printf("cli_posix_blocking failed\n");
8852                 goto fail;
8853         }
8854
8855         ok = tevent_req_poll_ntstatus(req, ev, &status);
8856         if (!ok) {
8857                 printf("tevent_req_poll_ntstatus failed: %s\n",
8858                        nt_errstr(status));
8859                 goto fail;
8860         }
8861         status = posix_blocking_recv(req);
8862         TALLOC_FREE(req);
8863         if (!NT_STATUS_IS_OK(status)) {
8864                 printf("posix_blocking_recv returned %s\n",
8865                        nt_errstr(status));
8866                 goto fail;
8867         }
8868
8869         ret = true;
8870 fail:
8871
8872         if (fnum1 != UINT16_MAX) {
8873                 cli_close(cli1, fnum1);
8874                 fnum1 = UINT16_MAX;
8875         }
8876         if (fnum2 != UINT16_MAX) {
8877                 cli_close(cli2, fnum2);
8878                 fnum2 = UINT16_MAX;
8879         }
8880
8881         if (cli1 != NULL) {
8882                 cli_setatr(cli1, fname, 0, 0);
8883                 cli_posix_unlink(cli1, fname);
8884         }
8885
8886         ok = true;
8887
8888         if (cli1 != NULL) {
8889                 ok &= torture_close_connection(cli1);
8890                 cli1 = NULL;
8891         }
8892         if (cli2 != NULL) {
8893                 ok &= torture_close_connection(cli2);
8894                 cli2 = NULL;
8895         }
8896
8897         if (!ok) {
8898                 ret = false;
8899         }
8900         TALLOC_FREE(ev);
8901         return ret;
8902 }
8903
8904 /*
8905   Test POSIX mkdir is case-sensitive.
8906  */
8907 static bool run_posix_mkdir_test(int dummy)
8908 {
8909         static struct cli_state *cli;
8910         const char *fname_foo = "POSIX_foo";
8911         const char *fname_foo_Foo = "POSIX_foo/Foo";
8912         const char *fname_foo_foo = "POSIX_foo/foo";
8913         const char *fname_Foo = "POSIX_Foo";
8914         const char *fname_Foo_Foo = "POSIX_Foo/Foo";
8915         const char *fname_Foo_foo = "POSIX_Foo/foo";
8916         bool correct = false;
8917         NTSTATUS status;
8918         TALLOC_CTX *frame = NULL;
8919         uint16_t fnum = (uint16_t)-1;
8920
8921         frame = talloc_stackframe();
8922
8923         printf("Starting POSIX mkdir test\n");
8924
8925         if (!torture_open_connection(&cli, 0)) {
8926                 TALLOC_FREE(frame);
8927                 return false;
8928         }
8929
8930         smbXcli_conn_set_sockopt(cli->conn, sockops);
8931
8932         status = torture_setup_unix_extensions(cli);
8933         if (!NT_STATUS_IS_OK(status)) {
8934                 TALLOC_FREE(frame);
8935                 return false;
8936         }
8937
8938         cli_posix_rmdir(cli, fname_foo_foo);
8939         cli_posix_rmdir(cli, fname_foo_Foo);
8940         cli_posix_rmdir(cli, fname_foo);
8941
8942         cli_posix_rmdir(cli, fname_Foo_foo);
8943         cli_posix_rmdir(cli, fname_Foo_Foo);
8944         cli_posix_rmdir(cli, fname_Foo);
8945
8946         /*
8947          * Create a file POSIX_foo then try
8948          * and use it in a directory path by
8949          * doing mkdir POSIX_foo/bar.
8950          * The mkdir should fail with
8951          * NT_STATUS_OBJECT_PATH_NOT_FOUND
8952          */
8953
8954         status = cli_posix_open(cli,
8955                         fname_foo,
8956                         O_RDWR|O_CREAT,
8957                         0666,
8958                         &fnum);
8959         if (!NT_STATUS_IS_OK(status)) {
8960                 printf("cli_posix_open of %s failed error %s\n",
8961                         fname_foo,
8962                         nt_errstr(status));
8963                 goto out;
8964         }
8965
8966         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
8967         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
8968                 printf("cli_posix_mkdir of %s should fail with "
8969                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
8970                         "%s instead\n",
8971                         fname_foo_foo,
8972                         nt_errstr(status));
8973                 goto out;
8974         }
8975
8976         status = cli_close(cli, fnum);
8977         if (!NT_STATUS_IS_OK(status)) {
8978                 printf("cli_close failed %s\n", nt_errstr(status));
8979                 goto out;
8980         }
8981         fnum = (uint16_t)-1;
8982
8983         status = cli_posix_unlink(cli, fname_foo);
8984         if (!NT_STATUS_IS_OK(status)) {
8985                 printf("cli_posix_unlink of %s failed error %s\n",
8986                         fname_foo,
8987                         nt_errstr(status));
8988                 goto out;
8989         }
8990
8991         /*
8992          * Now we've deleted everything, posix_mkdir, posix_rmdir,
8993          * posix_open, posix_unlink, on
8994          * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
8995          * not silently create POSIX_foo/foo.
8996          */
8997
8998         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
8999         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9000                 printf("cli_posix_mkdir of %s should fail with "
9001                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9002                         "%s instead\n",
9003                         fname_foo_foo,
9004                         nt_errstr(status));
9005                 goto out;
9006         }
9007
9008         status = cli_posix_rmdir(cli, fname_foo_foo);
9009         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9010                 printf("cli_posix_rmdir of %s should fail with "
9011                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9012                         "%s instead\n",
9013                         fname_foo_foo,
9014                         nt_errstr(status));
9015                 goto out;
9016         }
9017
9018         status = cli_posix_open(cli,
9019                         fname_foo_foo,
9020                         O_RDWR|O_CREAT,
9021                         0666,
9022                         &fnum);
9023         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9024                 printf("cli_posix_open of %s should fail with "
9025                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9026                         "%s instead\n",
9027                         fname_foo_foo,
9028                         nt_errstr(status));
9029                 goto out;
9030         }
9031
9032         status = cli_posix_unlink(cli, fname_foo_foo);
9033         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9034                 printf("cli_posix_unlink of %s should fail with "
9035                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9036                         "%s instead\n",
9037                         fname_foo_foo,
9038                         nt_errstr(status));
9039                 goto out;
9040         }
9041
9042         status = cli_posix_mkdir(cli, fname_foo, 0777);
9043         if (!NT_STATUS_IS_OK(status)) {
9044                 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9045                 goto out;
9046         }
9047
9048         status = cli_posix_mkdir(cli, fname_Foo, 0777);
9049         if (!NT_STATUS_IS_OK(status)) {
9050                 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9051                 goto out;
9052         }
9053
9054         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9055         if (!NT_STATUS_IS_OK(status)) {
9056                 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9057                 goto out;
9058         }
9059
9060         status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9061         if (!NT_STATUS_IS_OK(status)) {
9062                 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9063                 goto out;
9064         }
9065
9066         status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9067         if (!NT_STATUS_IS_OK(status)) {
9068                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9069                 goto out;
9070         }
9071
9072         status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9073         if (!NT_STATUS_IS_OK(status)) {
9074                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9075                 goto out;
9076         }
9077
9078         printf("POSIX mkdir test passed\n");
9079         correct = true;
9080
9081   out:
9082
9083         if (fnum != (uint16_t)-1) {
9084                 cli_close(cli, fnum);
9085                 fnum = (uint16_t)-1;
9086         }
9087
9088         cli_posix_rmdir(cli, fname_foo_foo);
9089         cli_posix_rmdir(cli, fname_foo_Foo);
9090         cli_posix_rmdir(cli, fname_foo);
9091
9092         cli_posix_rmdir(cli, fname_Foo_foo);
9093         cli_posix_rmdir(cli, fname_Foo_Foo);
9094         cli_posix_rmdir(cli, fname_Foo);
9095
9096         if (!torture_close_connection(cli)) {
9097                 correct = false;
9098         }
9099
9100         TALLOC_FREE(frame);
9101         return correct;
9102 }
9103
9104 struct posix_acl_oplock_state {
9105         struct tevent_context *ev;
9106         struct cli_state *cli;
9107         bool *got_break;
9108         bool *acl_ret;
9109         NTSTATUS status;
9110 };
9111
9112 static void posix_acl_oplock_got_break(struct tevent_req *req)
9113 {
9114         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9115                 req, struct posix_acl_oplock_state);
9116         uint16_t fnum;
9117         uint8_t level;
9118         NTSTATUS status;
9119
9120         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9121         TALLOC_FREE(req);
9122         if (!NT_STATUS_IS_OK(status)) {
9123                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9124                        nt_errstr(status));
9125                 return;
9126         }
9127         *state->got_break = true;
9128
9129         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9130                                   NO_OPLOCK);
9131         if (req == NULL) {
9132                 printf("cli_oplock_ack_send failed\n");
9133                 return;
9134         }
9135 }
9136
9137 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9138 {
9139         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9140                 req, struct posix_acl_oplock_state);
9141         size_t ret_size = 0;
9142         char *ret_data = NULL;
9143
9144         state->status = cli_posix_getacl_recv(req,
9145                         state,
9146                         &ret_size,
9147                         &ret_data);
9148
9149         if (!NT_STATUS_IS_OK(state->status)) {
9150                 printf("cli_posix_getacl_recv returned %s\n",
9151                         nt_errstr(state->status));
9152         }
9153         *state->acl_ret = true;
9154 }
9155
9156 static bool run_posix_acl_oplock_test(int dummy)
9157 {
9158         struct tevent_context *ev;
9159         struct cli_state *cli1, *cli2;
9160         struct tevent_req *oplock_req, *getacl_req;
9161         const char *fname = "posix_acl_oplock";
9162         uint16_t fnum;
9163         int saved_use_oplocks = use_oplocks;
9164         NTSTATUS status;
9165         bool correct = true;
9166         bool got_break = false;
9167         bool acl_ret = false;
9168
9169         struct posix_acl_oplock_state *state;
9170
9171         printf("starting posix_acl_oplock test\n");
9172
9173         if (!torture_open_connection(&cli1, 0)) {
9174                 use_level_II_oplocks = false;
9175                 use_oplocks = saved_use_oplocks;
9176                 return false;
9177         }
9178
9179         if (!torture_open_connection(&cli2, 1)) {
9180                 use_level_II_oplocks = false;
9181                 use_oplocks = saved_use_oplocks;
9182                 return false;
9183         }
9184
9185         /* Setup posix on cli2 only. */
9186         status = torture_setup_unix_extensions(cli2);
9187         if (!NT_STATUS_IS_OK(status)) {
9188                 return false;
9189         }
9190
9191         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9192         smbXcli_conn_set_sockopt(cli2->conn, sockops);
9193
9194         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9195
9196         /* Create the file on the Windows connection. */
9197         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9198                           &fnum);
9199         if (!NT_STATUS_IS_OK(status)) {
9200                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9201                 return false;
9202         }
9203
9204         status = cli_close(cli1, fnum);
9205         if (!NT_STATUS_IS_OK(status)) {
9206                 printf("close1 failed (%s)\n", nt_errstr(status));
9207                 return false;
9208         }
9209
9210         cli1->use_oplocks = true;
9211
9212         /* Open with oplock. */
9213         status = cli_ntcreate(cli1,
9214                         fname,
9215                         0,
9216                         FILE_READ_DATA,
9217                         FILE_ATTRIBUTE_NORMAL,
9218                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9219                         FILE_OPEN,
9220                         0,
9221                         0,
9222                         &fnum,
9223                         NULL);
9224
9225         if (!NT_STATUS_IS_OK(status)) {
9226                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9227                 return false;
9228         }
9229
9230         ev = samba_tevent_context_init(talloc_tos());
9231         if (ev == NULL) {
9232                 printf("tevent_context_init failed\n");
9233                 return false;
9234         }
9235
9236         state = talloc_zero(ev, struct posix_acl_oplock_state);
9237         if (state == NULL) {
9238                 printf("talloc failed\n");
9239                 return false;
9240         }
9241         state->ev = ev;
9242         state->cli = cli1;
9243         state->got_break = &got_break;
9244         state->acl_ret = &acl_ret;
9245
9246         oplock_req = cli_smb_oplock_break_waiter_send(
9247                 talloc_tos(), ev, cli1);
9248         if (oplock_req == NULL) {
9249                 printf("cli_smb_oplock_break_waiter_send failed\n");
9250                 return false;
9251         }
9252         tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9253
9254         /* Get ACL on POSIX connection - should break oplock. */
9255         getacl_req = cli_posix_getacl_send(talloc_tos(),
9256                                 ev,
9257                                 cli2,
9258                                 fname);
9259         if (getacl_req == NULL) {
9260                 printf("cli_posix_getacl_send failed\n");
9261                 return false;
9262         }
9263         tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9264
9265         while (!got_break || !acl_ret) {
9266                 int ret;
9267                 ret = tevent_loop_once(ev);
9268                 if (ret == -1) {
9269                         printf("tevent_loop_once failed: %s\n",
9270                                strerror(errno));
9271                         return false;
9272                 }
9273         }
9274
9275         if (!NT_STATUS_IS_OK(state->status)) {
9276                 printf("getacl failed (%s)\n", nt_errstr(state->status));
9277                 correct = false;
9278         }
9279
9280         status = cli_close(cli1, fnum);
9281         if (!NT_STATUS_IS_OK(status)) {
9282                 printf("close2 failed (%s)\n", nt_errstr(status));
9283                 correct = false;
9284         }
9285
9286         status = cli_unlink(cli1,
9287                         fname,
9288                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9289         if (!NT_STATUS_IS_OK(status)) {
9290                 printf("unlink failed (%s)\n", nt_errstr(status));
9291                 correct = false;
9292         }
9293
9294         if (!torture_close_connection(cli1)) {
9295                 correct = false;
9296         }
9297         if (!torture_close_connection(cli2)) {
9298                 correct = false;
9299         }
9300
9301         if (!got_break) {
9302                 correct = false;
9303         }
9304
9305         printf("finished posix acl oplock test\n");
9306
9307         return correct;
9308 }
9309
9310 static bool run_posix_acl_shareroot_test(int dummy)
9311 {
9312         struct cli_state *cli;
9313         NTSTATUS status;
9314         bool correct = false;
9315         char *posix_acl = NULL;
9316         size_t posix_acl_len = 0;
9317         uint16_t num_file_acls = 0;
9318         uint16_t num_dir_acls = 0;
9319         uint16_t i;
9320         uint32_t expected_size = 0;
9321         bool got_user = false;
9322         bool got_group = false;
9323         bool got_other = false;
9324         TALLOC_CTX *frame = NULL;
9325
9326         frame = talloc_stackframe();
9327
9328         printf("starting posix_acl_shareroot test\n");
9329
9330         if (!torture_open_connection(&cli, 0)) {
9331                 TALLOC_FREE(frame);
9332                 return false;
9333         }
9334
9335         smbXcli_conn_set_sockopt(cli->conn, sockops);
9336
9337         status = torture_setup_unix_extensions(cli);
9338         if (!NT_STATUS_IS_OK(status)) {
9339                 printf("Failed to setup unix extensions\n");
9340                 goto out;
9341         }
9342
9343         /* Get the POSIX ACL on the root of the share. */
9344         status = cli_posix_getacl(cli,
9345                                 ".",
9346                                 frame,
9347                                 &posix_acl_len,
9348                                 &posix_acl);
9349
9350         if (!NT_STATUS_IS_OK(status)) {
9351                 printf("cli_posix_getacl of '.' failed (%s)\n",
9352                         nt_errstr(status));
9353                 goto out;
9354         }
9355
9356         if (posix_acl_len < 6 ||
9357                         SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9358                 printf("getfacl ., unknown POSIX acl version %u.\n",
9359                         (unsigned int)CVAL(posix_acl,0) );
9360                 goto out;
9361         }
9362
9363         num_file_acls = SVAL(posix_acl,2);
9364         num_dir_acls = SVAL(posix_acl,4);
9365         expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9366                                 SMB_POSIX_ACL_ENTRY_SIZE*
9367                                 (num_file_acls+num_dir_acls);
9368
9369         if (posix_acl_len != expected_size) {
9370                 printf("incorrect POSIX acl buffer size "
9371                         "(should be %u, was %u).\n",
9372                         (unsigned int)expected_size,
9373                         (unsigned int)posix_acl_len);
9374                 goto out;
9375         }
9376
9377         /*
9378          * We don't need to know what the ACL's are
9379          * we just need to know we have at least 3
9380          * file entries (u,g,o).
9381          */
9382
9383         for (i = 0; i < num_file_acls; i++) {
9384                 unsigned char tagtype =
9385                         CVAL(posix_acl,
9386                                 SMB_POSIX_ACL_HEADER_SIZE+
9387                                 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9388
9389                 switch(tagtype) {
9390                         case SMB_POSIX_ACL_USER_OBJ:
9391                                 got_user = true;
9392                                 break;
9393                         case SMB_POSIX_ACL_GROUP_OBJ:
9394                                 got_group = true;
9395                                 break;
9396                         case SMB_POSIX_ACL_OTHER:
9397                                 got_other = true;
9398                                 break;
9399                         default:
9400                                 break;
9401                 }
9402         }
9403
9404         if (!got_user) {
9405                 printf("Missing user entry\n");
9406                 goto out;
9407         }
9408
9409         if (!got_group) {
9410                 printf("Missing group entry\n");
9411                 goto out;
9412         }
9413
9414         if (!got_other) {
9415                 printf("Missing other entry\n");
9416                 goto out;
9417         }
9418
9419         correct = true;
9420
9421   out:
9422
9423         if (!torture_close_connection(cli)) {
9424                 correct = false;
9425         }
9426
9427         printf("finished posix acl shareroot test\n");
9428         TALLOC_FREE(frame);
9429
9430         return correct;
9431 }
9432
9433 static uint32_t open_attrs_table[] = {
9434                 FILE_ATTRIBUTE_NORMAL,
9435                 FILE_ATTRIBUTE_ARCHIVE,
9436                 FILE_ATTRIBUTE_READONLY,
9437                 FILE_ATTRIBUTE_HIDDEN,
9438                 FILE_ATTRIBUTE_SYSTEM,
9439
9440                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9441                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9442                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9443                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9444                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9445                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9446
9447                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9448                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9449                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9450                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9451 };
9452
9453 struct trunc_open_results {
9454         unsigned int num;
9455         uint32_t init_attr;
9456         uint32_t trunc_attr;
9457         uint32_t result_attr;
9458 };
9459
9460 static struct trunc_open_results attr_results[] = {
9461         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9462         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9463         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9464         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9465         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9466         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9467         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9468         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9469         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9470         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9471         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9472         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9473         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9474         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9475         { 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 },
9476         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9477         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9478         { 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 },
9479         { 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 },
9480         { 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 },
9481         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9482         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9483         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9484         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9485         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9486         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9487 };
9488
9489 static bool run_openattrtest(int dummy)
9490 {
9491         static struct cli_state *cli1;
9492         const char *fname = "\\openattr.file";
9493         uint16_t fnum1;
9494         bool correct = True;
9495         uint16_t attr;
9496         unsigned int i, j, k, l;
9497         NTSTATUS status;
9498
9499         printf("starting open attr test\n");
9500
9501         if (!torture_open_connection(&cli1, 0)) {
9502                 return False;
9503         }
9504
9505         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9506
9507         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9508                 cli_setatr(cli1, fname, 0, 0);
9509                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9510
9511                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9512                                        open_attrs_table[i], FILE_SHARE_NONE,
9513                                        FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9514                 if (!NT_STATUS_IS_OK(status)) {
9515                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9516                         return False;
9517                 }
9518
9519                 status = cli_close(cli1, fnum1);
9520                 if (!NT_STATUS_IS_OK(status)) {
9521                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9522                         return False;
9523                 }
9524
9525                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9526                         status = cli_ntcreate(cli1, fname, 0,
9527                                               FILE_READ_DATA|FILE_WRITE_DATA,
9528                                               open_attrs_table[j],
9529                                               FILE_SHARE_NONE, FILE_OVERWRITE,
9530                                               0, 0, &fnum1, NULL);
9531                         if (!NT_STATUS_IS_OK(status)) {
9532                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9533                                         if (attr_results[l].num == k) {
9534                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9535                                                                 k, open_attrs_table[i],
9536                                                                 open_attrs_table[j],
9537                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
9538                                                 correct = False;
9539                                         }
9540                                 }
9541
9542                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9543                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9544                                                         k, open_attrs_table[i], open_attrs_table[j],
9545                                                         nt_errstr(status));
9546                                         correct = False;
9547                                 }
9548 #if 0
9549                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9550 #endif
9551                                 k++;
9552                                 continue;
9553                         }
9554
9555                         status = cli_close(cli1, fnum1);
9556                         if (!NT_STATUS_IS_OK(status)) {
9557                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9558                                 return False;
9559                         }
9560
9561                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9562                         if (!NT_STATUS_IS_OK(status)) {
9563                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9564                                 return False;
9565                         }
9566
9567 #if 0
9568                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9569                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
9570 #endif
9571
9572                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9573                                 if (attr_results[l].num == k) {
9574                                         if (attr != attr_results[l].result_attr ||
9575                                                         open_attrs_table[i] != attr_results[l].init_attr ||
9576                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
9577                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9578                                                 open_attrs_table[i],
9579                                                 open_attrs_table[j],
9580                                                 (unsigned int)attr,
9581                                                 attr_results[l].result_attr);
9582                                                 correct = False;
9583                                         }
9584                                         break;
9585                                 }
9586                         }
9587                         k++;
9588                 }
9589         }
9590
9591         cli_setatr(cli1, fname, 0, 0);
9592         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9593
9594         printf("open attr test %s.\n", correct ? "passed" : "failed");
9595
9596         if (!torture_close_connection(cli1)) {
9597                 correct = False;
9598         }
9599         return correct;
9600 }
9601
9602 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
9603                     const char *name, void *state)
9604 {
9605         int *matched = (int *)state;
9606         if (matched != NULL) {
9607                 *matched += 1;
9608         }
9609         return NT_STATUS_OK;
9610 }
9611
9612 /*
9613   test directory listing speed
9614  */
9615 static bool run_dirtest(int dummy)
9616 {
9617         int i;
9618         static struct cli_state *cli;
9619         uint16_t fnum;
9620         struct timeval core_start;
9621         bool correct = True;
9622         int matched;
9623
9624         printf("starting directory test\n");
9625
9626         if (!torture_open_connection(&cli, 0)) {
9627                 return False;
9628         }
9629
9630         smbXcli_conn_set_sockopt(cli->conn, sockops);
9631
9632         srandom(0);
9633         for (i=0;i<torture_numops;i++) {
9634                 fstring fname;
9635                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9636                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9637                         fprintf(stderr,"Failed to open %s\n", fname);
9638                         return False;
9639                 }
9640                 cli_close(cli, fnum);
9641         }
9642
9643         core_start = timeval_current();
9644
9645         matched = 0;
9646         cli_list(cli, "a*.*", 0, list_fn, &matched);
9647         printf("Matched %d\n", matched);
9648
9649         matched = 0;
9650         cli_list(cli, "b*.*", 0, list_fn, &matched);
9651         printf("Matched %d\n", matched);
9652
9653         matched = 0;
9654         cli_list(cli, "xyzabc", 0, list_fn, &matched);
9655         printf("Matched %d\n", matched);
9656
9657         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9658
9659         srandom(0);
9660         for (i=0;i<torture_numops;i++) {
9661                 fstring fname;
9662                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9663                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9664         }
9665
9666         if (!torture_close_connection(cli)) {
9667                 correct = False;
9668         }
9669
9670         printf("finished dirtest\n");
9671
9672         return correct;
9673 }
9674
9675 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
9676                    void *state)
9677 {
9678         struct cli_state *pcli = (struct cli_state *)state;
9679         fstring fname;
9680         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9681
9682         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9683                 return NT_STATUS_OK;
9684
9685         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
9686                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9687                         printf("del_fn: failed to rmdir %s\n,", fname );
9688         } else {
9689                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9690                         printf("del_fn: failed to unlink %s\n,", fname );
9691         }
9692         return NT_STATUS_OK;
9693 }
9694
9695
9696 /*
9697   sees what IOCTLs are supported
9698  */
9699 bool torture_ioctl_test(int dummy)
9700 {
9701         static struct cli_state *cli;
9702         uint16_t device, function;
9703         uint16_t fnum;
9704         const char *fname = "\\ioctl.dat";
9705         DATA_BLOB blob;
9706         NTSTATUS status;
9707
9708         if (!torture_open_connection(&cli, 0)) {
9709                 return False;
9710         }
9711
9712         printf("starting ioctl test\n");
9713
9714         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9715
9716         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9717         if (!NT_STATUS_IS_OK(status)) {
9718                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9719                 return False;
9720         }
9721
9722         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9723         printf("ioctl device info: %s\n", nt_errstr(status));
9724
9725         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9726         printf("ioctl job info: %s\n", nt_errstr(status));
9727
9728         for (device=0;device<0x100;device++) {
9729                 printf("ioctl test with device = 0x%x\n", device);
9730                 for (function=0;function<0x100;function++) {
9731                         uint32_t code = (device<<16) | function;
9732
9733                         status = cli_raw_ioctl(cli, fnum, code, &blob);
9734
9735                         if (NT_STATUS_IS_OK(status)) {
9736                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
9737                                        (int)blob.length);
9738                                 data_blob_free(&blob);
9739                         }
9740                 }
9741         }
9742
9743         if (!torture_close_connection(cli)) {
9744                 return False;
9745         }
9746
9747         return True;
9748 }
9749
9750
9751 /*
9752   tries varients of chkpath
9753  */
9754 bool torture_chkpath_test(int dummy)
9755 {
9756         static struct cli_state *cli;
9757         uint16_t fnum;
9758         bool ret;
9759         NTSTATUS status;
9760
9761         if (!torture_open_connection(&cli, 0)) {
9762                 return False;
9763         }
9764
9765         printf("starting chkpath test\n");
9766
9767         /* cleanup from an old run */
9768         cli_rmdir(cli, "\\chkpath.dir\\dir2");
9769         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9770         cli_rmdir(cli, "\\chkpath.dir");
9771
9772         status = cli_mkdir(cli, "\\chkpath.dir");
9773         if (!NT_STATUS_IS_OK(status)) {
9774                 printf("mkdir1 failed : %s\n", nt_errstr(status));
9775                 return False;
9776         }
9777
9778         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
9779         if (!NT_STATUS_IS_OK(status)) {
9780                 printf("mkdir2 failed : %s\n", nt_errstr(status));
9781                 return False;
9782         }
9783
9784         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
9785                           DENY_NONE, &fnum);
9786         if (!NT_STATUS_IS_OK(status)) {
9787                 printf("open1 failed (%s)\n", nt_errstr(status));
9788                 return False;
9789         }
9790         cli_close(cli, fnum);
9791
9792         status = cli_chkpath(cli, "\\chkpath.dir");
9793         if (!NT_STATUS_IS_OK(status)) {
9794                 printf("chkpath1 failed: %s\n", nt_errstr(status));
9795                 ret = False;
9796         }
9797
9798         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
9799         if (!NT_STATUS_IS_OK(status)) {
9800                 printf("chkpath2 failed: %s\n", nt_errstr(status));
9801                 ret = False;
9802         }
9803
9804         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
9805         if (!NT_STATUS_IS_OK(status)) {
9806                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9807                                   NT_STATUS_NOT_A_DIRECTORY);
9808         } else {
9809                 printf("* chkpath on a file should fail\n");
9810                 ret = False;
9811         }
9812
9813         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
9814         if (!NT_STATUS_IS_OK(status)) {
9815                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
9816                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
9817         } else {
9818                 printf("* chkpath on a non existent file should fail\n");
9819                 ret = False;
9820         }
9821
9822         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
9823         if (!NT_STATUS_IS_OK(status)) {
9824                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9825                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
9826         } else {
9827                 printf("* chkpath on a non existent component should fail\n");
9828                 ret = False;
9829         }
9830
9831         cli_rmdir(cli, "\\chkpath.dir\\dir2");
9832         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9833         cli_rmdir(cli, "\\chkpath.dir");
9834
9835         if (!torture_close_connection(cli)) {
9836                 return False;
9837         }
9838
9839         return ret;
9840 }
9841
9842 static bool run_eatest(int dummy)
9843 {
9844         static struct cli_state *cli;
9845         const char *fname = "\\eatest.txt";
9846         bool correct = True;
9847         uint16_t fnum;
9848         int i;
9849         size_t num_eas;
9850         struct ea_struct *ea_list = NULL;
9851         TALLOC_CTX *mem_ctx = talloc_init("eatest");
9852         NTSTATUS status;
9853
9854         printf("starting eatest\n");
9855
9856         if (!torture_open_connection(&cli, 0)) {
9857                 talloc_destroy(mem_ctx);
9858                 return False;
9859         }
9860
9861         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9862
9863         status = cli_ntcreate(cli, fname, 0,
9864                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
9865                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
9866                               0x4044, 0, &fnum, NULL);
9867         if (!NT_STATUS_IS_OK(status)) {
9868                 printf("open failed - %s\n", nt_errstr(status));
9869                 talloc_destroy(mem_ctx);
9870                 return False;
9871         }
9872
9873         for (i = 0; i < 10; i++) {
9874                 fstring ea_name, ea_val;
9875
9876                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
9877                 memset(ea_val, (char)i+1, i+1);
9878                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
9879                 if (!NT_STATUS_IS_OK(status)) {
9880                         printf("ea_set of name %s failed - %s\n", ea_name,
9881                                nt_errstr(status));
9882                         talloc_destroy(mem_ctx);
9883                         return False;
9884                 }
9885         }
9886
9887         cli_close(cli, fnum);
9888         for (i = 0; i < 10; i++) {
9889                 fstring ea_name, ea_val;
9890
9891                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
9892                 memset(ea_val, (char)i+1, i+1);
9893                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
9894                 if (!NT_STATUS_IS_OK(status)) {
9895                         printf("ea_set of name %s failed - %s\n", ea_name,
9896                                nt_errstr(status));
9897                         talloc_destroy(mem_ctx);
9898                         return False;
9899                 }
9900         }
9901
9902         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
9903         if (!NT_STATUS_IS_OK(status)) {
9904                 printf("ea_get list failed - %s\n", nt_errstr(status));
9905                 correct = False;
9906         }
9907
9908         printf("num_eas = %d\n", (int)num_eas);
9909
9910         if (num_eas != 20) {
9911                 printf("Should be 20 EA's stored... failing.\n");
9912                 correct = False;
9913         }
9914
9915         for (i = 0; i < num_eas; i++) {
9916                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
9917                 dump_data(0, ea_list[i].value.data,
9918                           ea_list[i].value.length);
9919         }
9920
9921         /* Setting EA's to zero length deletes them. Test this */
9922         printf("Now deleting all EA's - case indepenent....\n");
9923
9924 #if 1
9925         cli_set_ea_path(cli, fname, "", "", 0);
9926 #else
9927         for (i = 0; i < 20; i++) {
9928                 fstring ea_name;
9929                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
9930                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
9931                 if (!NT_STATUS_IS_OK(status)) {
9932                         printf("ea_set of name %s failed - %s\n", ea_name,
9933                                nt_errstr(status));
9934                         talloc_destroy(mem_ctx);
9935                         return False;
9936                 }
9937         }
9938 #endif
9939
9940         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
9941         if (!NT_STATUS_IS_OK(status)) {
9942                 printf("ea_get list failed - %s\n", nt_errstr(status));
9943                 correct = False;
9944         }
9945
9946         printf("num_eas = %d\n", (int)num_eas);
9947         for (i = 0; i < num_eas; i++) {
9948                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
9949                 dump_data(0, ea_list[i].value.data,
9950                           ea_list[i].value.length);
9951         }
9952
9953         if (num_eas != 0) {
9954                 printf("deleting EA's failed.\n");
9955                 correct = False;
9956         }
9957
9958         /* Try and delete a non existent EA. */
9959         status = cli_set_ea_path(cli, fname, "foo", "", 0);
9960         if (!NT_STATUS_IS_OK(status)) {
9961                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
9962                        nt_errstr(status));
9963                 correct = False;
9964         }
9965
9966         talloc_destroy(mem_ctx);
9967         if (!torture_close_connection(cli)) {
9968                 correct = False;
9969         }
9970
9971         return correct;
9972 }
9973
9974 static bool run_dirtest1(int dummy)
9975 {
9976         int i;
9977         static struct cli_state *cli;
9978         uint16_t fnum;
9979         int num_seen;
9980         bool correct = True;
9981
9982         printf("starting directory test\n");
9983
9984         if (!torture_open_connection(&cli, 0)) {
9985                 return False;
9986         }
9987
9988         smbXcli_conn_set_sockopt(cli->conn, sockops);
9989
9990         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
9991         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
9992         cli_rmdir(cli, "\\LISTDIR");
9993         cli_mkdir(cli, "\\LISTDIR");
9994
9995         /* Create 1000 files and 1000 directories. */
9996         for (i=0;i<1000;i++) {
9997                 fstring fname;
9998                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
9999                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10000                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10001                                    0, 0, &fnum, NULL))) {
10002                         fprintf(stderr,"Failed to open %s\n", fname);
10003                         return False;
10004                 }
10005                 cli_close(cli, fnum);
10006         }
10007         for (i=0;i<1000;i++) {
10008                 fstring fname;
10009                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10010                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10011                         fprintf(stderr,"Failed to open %s\n", fname);
10012                         return False;
10013                 }
10014         }
10015
10016         /* Now ensure that doing an old list sees both files and directories. */
10017         num_seen = 0;
10018         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10019         printf("num_seen = %d\n", num_seen );
10020         /* We should see 100 files + 1000 directories + . and .. */
10021         if (num_seen != 2002)
10022                 correct = False;
10023
10024         /* Ensure if we have the "must have" bits we only see the
10025          * relevent entries.
10026          */
10027         num_seen = 0;
10028         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10029         printf("num_seen = %d\n", num_seen );
10030         if (num_seen != 1002)
10031                 correct = False;
10032
10033         num_seen = 0;
10034         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10035         printf("num_seen = %d\n", num_seen );
10036         if (num_seen != 1000)
10037                 correct = False;
10038
10039         /* Delete everything. */
10040         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10041         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10042         cli_rmdir(cli, "\\LISTDIR");
10043
10044 #if 0
10045         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10046         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10047         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10048 #endif
10049
10050         if (!torture_close_connection(cli)) {
10051                 correct = False;
10052         }
10053
10054         printf("finished dirtest1\n");
10055
10056         return correct;
10057 }
10058
10059 static bool run_error_map_extract(int dummy) {
10060
10061         static struct cli_state *c_dos;
10062         static struct cli_state *c_nt;
10063         NTSTATUS status;
10064
10065         uint32_t error;
10066
10067         uint32_t errnum;
10068         uint8_t errclass;
10069
10070         NTSTATUS nt_status;
10071
10072         fstring user;
10073
10074         /* NT-Error connection */
10075
10076         disable_spnego = true;
10077         if (!(c_nt = open_nbt_connection())) {
10078                 disable_spnego = false;
10079                 return False;
10080         }
10081         disable_spnego = false;
10082
10083         status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
10084                                  PROTOCOL_NT1);
10085
10086         if (!NT_STATUS_IS_OK(status)) {
10087                 printf("%s rejected the NT-error negprot (%s)\n", host,
10088                        nt_errstr(status));
10089                 cli_shutdown(c_nt);
10090                 return False;
10091         }
10092
10093         status = cli_session_setup_anon(c_nt);
10094         if (!NT_STATUS_IS_OK(status)) {
10095                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10096                 return False;
10097         }
10098
10099         /* DOS-Error connection */
10100
10101         disable_spnego = true;
10102         force_dos_errors = true;
10103         if (!(c_dos = open_nbt_connection())) {
10104                 disable_spnego = false;
10105                 force_dos_errors = false;
10106                 return False;
10107         }
10108         disable_spnego = false;
10109         force_dos_errors = false;
10110
10111         status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
10112                                  PROTOCOL_NT1);
10113         if (!NT_STATUS_IS_OK(status)) {
10114                 printf("%s rejected the DOS-error negprot (%s)\n", host,
10115                        nt_errstr(status));
10116                 cli_shutdown(c_dos);
10117                 return False;
10118         }
10119
10120         status = cli_session_setup_anon(c_dos);
10121         if (!NT_STATUS_IS_OK(status)) {
10122                 printf("%s rejected the DOS-error initial session setup (%s)\n",
10123                         host, nt_errstr(status));
10124                 return False;
10125         }
10126
10127         c_nt->map_dos_errors = false;
10128         c_dos->map_dos_errors = false;
10129
10130         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10131                 struct cli_credentials *user_creds = NULL;
10132
10133                 fstr_sprintf(user, "%X", error);
10134
10135                 user_creds = cli_session_creds_init(talloc_tos(),
10136                                                     user,
10137                                                     workgroup,
10138                                                     NULL, /* realm */
10139                                                     password,
10140                                                     false, /* use_kerberos */
10141                                                     false, /* fallback_after_kerberos */
10142                                                     false, /* use_ccache */
10143                                                     false); /* password_is_nt_hash */
10144                 if (user_creds == NULL) {
10145                         printf("cli_session_creds_init(%s) failed\n", user);
10146                         return false;
10147                 }
10148
10149                 status = cli_session_setup_creds(c_nt, user_creds);
10150                 if (NT_STATUS_IS_OK(status)) {
10151                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10152                 }
10153
10154                 /* Case #1: 32-bit NT errors */
10155                 if (!NT_STATUS_IS_DOS(status)) {
10156                         nt_status = status;
10157                 } else {
10158                         printf("/** Dos error on NT connection! (%s) */\n", 
10159                                nt_errstr(status));
10160                         nt_status = NT_STATUS(0xc0000000);
10161                 }
10162
10163                 status = cli_session_setup_creds(c_dos, user_creds);
10164                 if (NT_STATUS_IS_OK(status)) {
10165                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10166                 }
10167
10168                 /* Case #1: 32-bit NT errors */
10169                 if (NT_STATUS_IS_DOS(status)) {
10170                         printf("/** NT error on DOS connection! (%s) */\n", 
10171                                nt_errstr(status));
10172                         errnum = errclass = 0;
10173                 } else {
10174                         errclass = NT_STATUS_DOS_CLASS(status);
10175                         errnum = NT_STATUS_DOS_CODE(status);
10176                 }
10177
10178                 if (NT_STATUS_V(nt_status) != error) { 
10179                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
10180                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
10181                                get_nt_error_c_code(talloc_tos(), nt_status));
10182                 }
10183
10184                 printf("\t{%s,\t%s,\t%s},\n", 
10185                        smb_dos_err_class(errclass), 
10186                        smb_dos_err_name(errclass, errnum), 
10187                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10188
10189                 TALLOC_FREE(user_creds);
10190         }
10191         return True;
10192 }
10193
10194 static bool run_sesssetup_bench(int dummy)
10195 {
10196         static struct cli_state *c;
10197         const char *fname = "\\file.dat";
10198         uint16_t fnum;
10199         NTSTATUS status;
10200         int i;
10201
10202         if (!torture_open_connection(&c, 0)) {
10203                 return false;
10204         }
10205
10206         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10207                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10208                               FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10209         if (!NT_STATUS_IS_OK(status)) {
10210                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10211                 return false;
10212         }
10213
10214         for (i=0; i<torture_numops; i++) {
10215                 status = cli_session_setup_creds(c, torture_creds);
10216                 if (!NT_STATUS_IS_OK(status)) {
10217                         d_printf("(%s) cli_session_setup_creds failed: %s\n",
10218                                  __location__, nt_errstr(status));
10219                         return false;
10220                 }
10221
10222                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
10223
10224                 status = cli_ulogoff(c);
10225                 if (!NT_STATUS_IS_OK(status)) {
10226                         d_printf("(%s) cli_ulogoff failed: %s\n",
10227                                  __location__, nt_errstr(status));
10228                         return false;
10229                 }
10230         }
10231
10232         return true;
10233 }
10234
10235 static bool subst_test(const char *str, const char *user, const char *domain,
10236                        uid_t uid, gid_t gid, const char *expected)
10237 {
10238         char *subst;
10239         bool result = true;
10240
10241         subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10242
10243         if (strcmp(subst, expected) != 0) {
10244                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10245                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10246                        expected);
10247                 result = false;
10248         }
10249
10250         TALLOC_FREE(subst);
10251         return result;
10252 }
10253
10254 static void chain1_open_completion(struct tevent_req *req)
10255 {
10256         uint16_t fnum;
10257         NTSTATUS status;
10258         status = cli_openx_recv(req, &fnum);
10259         TALLOC_FREE(req);
10260
10261         d_printf("cli_openx_recv returned %s: %d\n",
10262                  nt_errstr(status),
10263                  NT_STATUS_IS_OK(status) ? fnum : -1);
10264 }
10265
10266 static void chain1_write_completion(struct tevent_req *req)
10267 {
10268         size_t written;
10269         NTSTATUS status;
10270         status = cli_write_andx_recv(req, &written);
10271         TALLOC_FREE(req);
10272
10273         d_printf("cli_write_andx_recv returned %s: %d\n",
10274                  nt_errstr(status),
10275                  NT_STATUS_IS_OK(status) ? (int)written : -1);
10276 }
10277
10278 static void chain1_close_completion(struct tevent_req *req)
10279 {
10280         NTSTATUS status;
10281         bool *done = (bool *)tevent_req_callback_data_void(req);
10282
10283         status = cli_close_recv(req);
10284         *done = true;
10285
10286         TALLOC_FREE(req);
10287
10288         d_printf("cli_close returned %s\n", nt_errstr(status));
10289 }
10290
10291 static bool run_chain1(int dummy)
10292 {
10293         struct cli_state *cli1;
10294         struct tevent_context *evt = samba_tevent_context_init(NULL);
10295         struct tevent_req *reqs[3], *smbreqs[3];
10296         bool done = false;
10297         const char *str = "foobar";
10298         const char *fname = "\\test_chain";
10299         NTSTATUS status;
10300
10301         printf("starting chain1 test\n");
10302         if (!torture_open_connection(&cli1, 0)) {
10303                 return False;
10304         }
10305
10306         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10307
10308         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10309
10310         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10311                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
10312         if (reqs[0] == NULL) return false;
10313         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10314
10315
10316         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10317                                         (const uint8_t *)str, 0, strlen(str)+1,
10318                                         smbreqs, 1, &smbreqs[1]);
10319         if (reqs[1] == NULL) return false;
10320         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10321
10322         reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10323         if (reqs[2] == NULL) return false;
10324         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10325
10326         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10327         if (!NT_STATUS_IS_OK(status)) {
10328                 return false;
10329         }
10330
10331         while (!done) {
10332                 tevent_loop_once(evt);
10333         }
10334
10335         torture_close_connection(cli1);
10336         return True;
10337 }
10338
10339 static void chain2_sesssetup_completion(struct tevent_req *req)
10340 {
10341         NTSTATUS status;
10342         status = cli_session_setup_guest_recv(req);
10343         d_printf("sesssetup returned %s\n", nt_errstr(status));
10344 }
10345
10346 static void chain2_tcon_completion(struct tevent_req *req)
10347 {
10348         bool *done = (bool *)tevent_req_callback_data_void(req);
10349         NTSTATUS status;
10350         status = cli_tcon_andx_recv(req);
10351         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10352         *done = true;
10353 }
10354
10355 static bool run_chain2(int dummy)
10356 {
10357         struct cli_state *cli1;
10358         struct tevent_context *evt = samba_tevent_context_init(NULL);
10359         struct tevent_req *reqs[2], *smbreqs[2];
10360         bool done = false;
10361         NTSTATUS status;
10362         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10363
10364         printf("starting chain2 test\n");
10365         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10366                                       port_to_use, SMB_SIGNING_DEFAULT, flags);
10367         if (!NT_STATUS_IS_OK(status)) {
10368                 return False;
10369         }
10370
10371         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10372
10373         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10374                                                  &smbreqs[0]);
10375         if (reqs[0] == NULL) return false;
10376         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10377
10378         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10379                                        "?????", NULL, 0, &smbreqs[1]);
10380         if (reqs[1] == NULL) return false;
10381         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10382
10383         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10384         if (!NT_STATUS_IS_OK(status)) {
10385                 return false;
10386         }
10387
10388         while (!done) {
10389                 tevent_loop_once(evt);
10390         }
10391
10392         torture_close_connection(cli1);
10393         return True;
10394 }
10395
10396
10397 struct torture_createdel_state {
10398         struct tevent_context *ev;
10399         struct cli_state *cli;
10400 };
10401
10402 static void torture_createdel_created(struct tevent_req *subreq);
10403 static void torture_createdel_closed(struct tevent_req *subreq);
10404
10405 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10406                                                  struct tevent_context *ev,
10407                                                  struct cli_state *cli,
10408                                                  const char *name)
10409 {
10410         struct tevent_req *req, *subreq;
10411         struct torture_createdel_state *state;
10412
10413         req = tevent_req_create(mem_ctx, &state,
10414                                 struct torture_createdel_state);
10415         if (req == NULL) {
10416                 return NULL;
10417         }
10418         state->ev = ev;
10419         state->cli = cli;
10420
10421         subreq = cli_ntcreate_send(
10422                 state, ev, cli, name, 0,
10423                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10424                 FILE_ATTRIBUTE_NORMAL,
10425                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10426                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10427                 SMB2_IMPERSONATION_IMPERSONATION, 0);
10428
10429         if (tevent_req_nomem(subreq, req)) {
10430                 return tevent_req_post(req, ev);
10431         }
10432         tevent_req_set_callback(subreq, torture_createdel_created, req);
10433         return req;
10434 }
10435
10436 static void torture_createdel_created(struct tevent_req *subreq)
10437 {
10438         struct tevent_req *req = tevent_req_callback_data(
10439                 subreq, struct tevent_req);
10440         struct torture_createdel_state *state = tevent_req_data(
10441                 req, struct torture_createdel_state);
10442         NTSTATUS status;
10443         uint16_t fnum;
10444
10445         status = cli_ntcreate_recv(subreq, &fnum, NULL);
10446         TALLOC_FREE(subreq);
10447         if (tevent_req_nterror(req, status)) {
10448                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10449                            nt_errstr(status)));
10450                 return;
10451         }
10452
10453         subreq = cli_close_send(state, state->ev, state->cli, fnum);
10454         if (tevent_req_nomem(subreq, req)) {
10455                 return;
10456         }
10457         tevent_req_set_callback(subreq, torture_createdel_closed, req);
10458 }
10459
10460 static void torture_createdel_closed(struct tevent_req *subreq)
10461 {
10462         struct tevent_req *req = tevent_req_callback_data(
10463                 subreq, struct tevent_req);
10464         NTSTATUS status;
10465
10466         status = cli_close_recv(subreq);
10467         if (tevent_req_nterror(req, status)) {
10468                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10469                 return;
10470         }
10471         tevent_req_done(req);
10472 }
10473
10474 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10475 {
10476         return tevent_req_simple_recv_ntstatus(req);
10477 }
10478
10479 struct torture_createdels_state {
10480         struct tevent_context *ev;
10481         struct cli_state *cli;
10482         const char *base_name;
10483         int sent;
10484         int received;
10485         int num_files;
10486         struct tevent_req **reqs;
10487 };
10488
10489 static void torture_createdels_done(struct tevent_req *subreq);
10490
10491 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10492                                                   struct tevent_context *ev,
10493                                                   struct cli_state *cli,
10494                                                   const char *base_name,
10495                                                   int num_parallel,
10496                                                   int num_files)
10497 {
10498         struct tevent_req *req;
10499         struct torture_createdels_state *state;
10500         int i;
10501
10502         req = tevent_req_create(mem_ctx, &state,
10503                                 struct torture_createdels_state);
10504         if (req == NULL) {
10505                 return NULL;
10506         }
10507         state->ev = ev;
10508         state->cli = cli;
10509         state->base_name = talloc_strdup(state, base_name);
10510         if (tevent_req_nomem(state->base_name, req)) {
10511                 return tevent_req_post(req, ev);
10512         }
10513         state->num_files = MAX(num_parallel, num_files);
10514         state->sent = 0;
10515         state->received = 0;
10516
10517         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10518         if (tevent_req_nomem(state->reqs, req)) {
10519                 return tevent_req_post(req, ev);
10520         }
10521
10522         for (i=0; i<num_parallel; i++) {
10523                 char *name;
10524
10525                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10526                                        state->sent);
10527                 if (tevent_req_nomem(name, req)) {
10528                         return tevent_req_post(req, ev);
10529                 }
10530                 state->reqs[i] = torture_createdel_send(
10531                         state->reqs, state->ev, state->cli, name);
10532                 if (tevent_req_nomem(state->reqs[i], req)) {
10533                         return tevent_req_post(req, ev);
10534                 }
10535                 name = talloc_move(state->reqs[i], &name);
10536                 tevent_req_set_callback(state->reqs[i],
10537                                         torture_createdels_done, req);
10538                 state->sent += 1;
10539         }
10540         return req;
10541 }
10542
10543 static void torture_createdels_done(struct tevent_req *subreq)
10544 {
10545         struct tevent_req *req = tevent_req_callback_data(
10546                 subreq, struct tevent_req);
10547         struct torture_createdels_state *state = tevent_req_data(
10548                 req, struct torture_createdels_state);
10549         size_t num_parallel = talloc_array_length(state->reqs);
10550         NTSTATUS status;
10551         char *name;
10552         int i;
10553
10554         status = torture_createdel_recv(subreq);
10555         if (!NT_STATUS_IS_OK(status)){
10556                 DEBUG(10, ("torture_createdel_recv returned %s\n",
10557                            nt_errstr(status)));
10558                 TALLOC_FREE(subreq);
10559                 tevent_req_nterror(req, status);
10560                 return;
10561         }
10562
10563         for (i=0; i<num_parallel; i++) {
10564                 if (subreq == state->reqs[i]) {
10565                         break;
10566                 }
10567         }
10568         if (i == num_parallel) {
10569                 DEBUG(10, ("received something we did not send\n"));
10570                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10571                 return;
10572         }
10573         TALLOC_FREE(state->reqs[i]);
10574
10575         if (state->sent >= state->num_files) {
10576                 tevent_req_done(req);
10577                 return;
10578         }
10579
10580         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10581                                state->sent);
10582         if (tevent_req_nomem(name, req)) {
10583                 return;
10584         }
10585         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10586                                                 state->cli, name);
10587         if (tevent_req_nomem(state->reqs[i], req)) {
10588                 return;
10589         }
10590         name = talloc_move(state->reqs[i], &name);
10591         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10592         state->sent += 1;
10593 }
10594
10595 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10596 {
10597         return tevent_req_simple_recv_ntstatus(req);
10598 }
10599
10600 struct swallow_notify_state {
10601         struct tevent_context *ev;
10602         struct cli_state *cli;
10603         uint16_t fnum;
10604         uint32_t completion_filter;
10605         bool recursive;
10606         bool (*fn)(uint32_t action, const char *name, void *priv);
10607         void *priv;
10608 };
10609
10610 static void swallow_notify_done(struct tevent_req *subreq);
10611
10612 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10613                                               struct tevent_context *ev,
10614                                               struct cli_state *cli,
10615                                               uint16_t fnum,
10616                                               uint32_t completion_filter,
10617                                               bool recursive,
10618                                               bool (*fn)(uint32_t action,
10619                                                          const char *name,
10620                                                          void *priv),
10621                                               void *priv)
10622 {
10623         struct tevent_req *req, *subreq;
10624         struct swallow_notify_state *state;
10625
10626         req = tevent_req_create(mem_ctx, &state,
10627                                 struct swallow_notify_state);
10628         if (req == NULL) {
10629                 return NULL;
10630         }
10631         state->ev = ev;
10632         state->cli = cli;
10633         state->fnum = fnum;
10634         state->completion_filter = completion_filter;
10635         state->recursive = recursive;
10636         state->fn = fn;
10637         state->priv = priv;
10638
10639         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10640                                  0xffff, state->completion_filter,
10641                                  state->recursive);
10642         if (tevent_req_nomem(subreq, req)) {
10643                 return tevent_req_post(req, ev);
10644         }
10645         tevent_req_set_callback(subreq, swallow_notify_done, req);
10646         return req;
10647 }
10648
10649 static void swallow_notify_done(struct tevent_req *subreq)
10650 {
10651         struct tevent_req *req = tevent_req_callback_data(
10652                 subreq, struct tevent_req);
10653         struct swallow_notify_state *state = tevent_req_data(
10654                 req, struct swallow_notify_state);
10655         NTSTATUS status;
10656         uint32_t i, num_changes;
10657         struct notify_change *changes;
10658
10659         status = cli_notify_recv(subreq, state, &num_changes, &changes);
10660         TALLOC_FREE(subreq);
10661         if (!NT_STATUS_IS_OK(status)) {
10662                 DEBUG(10, ("cli_notify_recv returned %s\n",
10663                            nt_errstr(status)));
10664                 tevent_req_nterror(req, status);
10665                 return;
10666         }
10667
10668         for (i=0; i<num_changes; i++) {
10669                 state->fn(changes[i].action, changes[i].name, state->priv);
10670         }
10671         TALLOC_FREE(changes);
10672
10673         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10674                                  0xffff, state->completion_filter,
10675                                  state->recursive);
10676         if (tevent_req_nomem(subreq, req)) {
10677                 return;
10678         }
10679         tevent_req_set_callback(subreq, swallow_notify_done, req);
10680 }
10681
10682 static bool print_notifies(uint32_t action, const char *name, void *priv)
10683 {
10684         if (DEBUGLEVEL > 5) {
10685                 d_printf("%d %s\n", (int)action, name);
10686         }
10687         return true;
10688 }
10689
10690 static void notify_bench_done(struct tevent_req *req)
10691 {
10692         int *num_finished = (int *)tevent_req_callback_data_void(req);
10693         *num_finished += 1;
10694 }
10695
10696 static bool run_notify_bench(int dummy)
10697 {
10698         const char *dname = "\\notify-bench";
10699         struct tevent_context *ev;
10700         NTSTATUS status;
10701         uint16_t dnum;
10702         struct tevent_req *req1;
10703         struct tevent_req *req2 = NULL;
10704         int i, num_unc_names;
10705         int num_finished = 0;
10706
10707         printf("starting notify-bench test\n");
10708
10709         if (use_multishare_conn) {
10710                 char **unc_list;
10711                 unc_list = file_lines_load(multishare_conn_fname,
10712                                            &num_unc_names, 0, NULL);
10713                 if (!unc_list || num_unc_names <= 0) {
10714                         d_printf("Failed to load unc names list from '%s'\n",
10715                                  multishare_conn_fname);
10716                         return false;
10717                 }
10718                 TALLOC_FREE(unc_list);
10719         } else {
10720                 num_unc_names = 1;
10721         }
10722
10723         ev = samba_tevent_context_init(talloc_tos());
10724         if (ev == NULL) {
10725                 d_printf("tevent_context_init failed\n");
10726                 return false;
10727         }
10728
10729         for (i=0; i<num_unc_names; i++) {
10730                 struct cli_state *cli;
10731                 char *base_fname;
10732
10733                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
10734                                              dname, i);
10735                 if (base_fname == NULL) {
10736                         return false;
10737                 }
10738
10739                 if (!torture_open_connection(&cli, i)) {
10740                         return false;
10741                 }
10742
10743                 status = cli_ntcreate(cli, dname, 0,
10744                                       MAXIMUM_ALLOWED_ACCESS,
10745                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
10746                                       FILE_SHARE_DELETE,
10747                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
10748                                       &dnum, NULL);
10749
10750                 if (!NT_STATUS_IS_OK(status)) {
10751                         d_printf("Could not create %s: %s\n", dname,
10752                                  nt_errstr(status));
10753                         return false;
10754                 }
10755
10756                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
10757                                            FILE_NOTIFY_CHANGE_FILE_NAME |
10758                                            FILE_NOTIFY_CHANGE_DIR_NAME |
10759                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
10760                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
10761                                            false, print_notifies, NULL);
10762                 if (req1 == NULL) {
10763                         d_printf("Could not create notify request\n");
10764                         return false;
10765                 }
10766
10767                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
10768                                                base_fname, 10, torture_numops);
10769                 if (req2 == NULL) {
10770                         d_printf("Could not create createdels request\n");
10771                         return false;
10772                 }
10773                 TALLOC_FREE(base_fname);
10774
10775                 tevent_req_set_callback(req2, notify_bench_done,
10776                                         &num_finished);
10777         }
10778
10779         while (num_finished < num_unc_names) {
10780                 int ret;
10781                 ret = tevent_loop_once(ev);
10782                 if (ret != 0) {
10783                         d_printf("tevent_loop_once failed\n");
10784                         return false;
10785                 }
10786         }
10787
10788         if (!tevent_req_poll(req2, ev)) {
10789                 d_printf("tevent_req_poll failed\n");
10790         }
10791
10792         status = torture_createdels_recv(req2);
10793         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
10794
10795         return true;
10796 }
10797
10798 static bool run_mangle1(int dummy)
10799 {
10800         struct cli_state *cli;
10801         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
10802         uint16_t fnum;
10803         fstring alt_name;
10804         NTSTATUS status;
10805         time_t change_time, access_time, write_time;
10806         off_t size;
10807         uint16_t mode;
10808
10809         printf("starting mangle1 test\n");
10810         if (!torture_open_connection(&cli, 0)) {
10811                 return False;
10812         }
10813
10814         smbXcli_conn_set_sockopt(cli->conn, sockops);
10815
10816         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10817                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10818                               0, 0, &fnum, NULL);
10819         if (!NT_STATUS_IS_OK(status)) {
10820                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10821                 return false;
10822         }
10823         cli_close(cli, fnum);
10824
10825         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
10826         if (!NT_STATUS_IS_OK(status)) {
10827                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
10828                          nt_errstr(status));
10829                 return false;
10830         }
10831         d_printf("alt_name: %s\n", alt_name);
10832
10833         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
10834         if (!NT_STATUS_IS_OK(status)) {
10835                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
10836                          nt_errstr(status));
10837                 return false;
10838         }
10839         cli_close(cli, fnum);
10840
10841         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
10842                                 &write_time, &size, &mode);
10843         if (!NT_STATUS_IS_OK(status)) {
10844                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
10845                          nt_errstr(status));
10846                 return false;
10847         }
10848
10849         return true;
10850 }
10851
10852 static NTSTATUS mangle_illegal_list_shortname_fn(const char *mntpoint,
10853                                                  struct file_info *f,
10854                                                  const char *mask,
10855                                                  void *state)
10856 {
10857         if (f->short_name == NULL) {
10858                 return NT_STATUS_OK;
10859         }
10860
10861         if (strlen(f->short_name) == 0) {
10862                 return NT_STATUS_OK;
10863         }
10864
10865         printf("unexpected shortname: %s\n", f->short_name);
10866
10867         return NT_STATUS_OBJECT_NAME_INVALID;
10868 }
10869
10870 static NTSTATUS mangle_illegal_list_name_fn(const char *mntpoint,
10871                                             struct file_info *f,
10872                                             const char *mask,
10873                                             void *state)
10874 {
10875         char *name = state;
10876
10877         printf("name: %s\n", f->name);
10878         fstrcpy(name, f->name);
10879         return NT_STATUS_OK;
10880 }
10881
10882 static bool run_mangle_illegal(int dummy)
10883 {
10884         struct cli_state *cli = NULL;
10885         struct cli_state *cli_posix = NULL;
10886         const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
10887         const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
10888         char *mangled_path = NULL;
10889         uint16_t fnum;
10890         fstring name;
10891         fstring alt_name;
10892         NTSTATUS status;
10893
10894         printf("starting mangle-illegal test\n");
10895
10896         if (!torture_open_connection(&cli, 0)) {
10897                 return False;
10898         }
10899
10900         smbXcli_conn_set_sockopt(cli->conn, sockops);
10901
10902         if (!torture_open_connection(&cli_posix, 0)) {
10903                 return false;
10904         }
10905
10906         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
10907
10908         status = torture_setup_unix_extensions(cli_posix);
10909         if (!NT_STATUS_IS_OK(status)) {
10910                 return false;
10911         }
10912
10913         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
10914         status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
10915         if (!NT_STATUS_IS_OK(status)) {
10916                 printf("mkdir1 failed : %s\n", nt_errstr(status));
10917                 return False;
10918         }
10919
10920         /*
10921          * Create a file with illegal NTFS characters and test that we
10922          * get a usable mangled name
10923          */
10924
10925         cli_setatr(cli_posix, illegal_fname, 0, 0);
10926         cli_posix_unlink(cli_posix, illegal_fname);
10927
10928         status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
10929                                 0600, &fnum);
10930         if (!NT_STATUS_IS_OK(status)) {
10931                 printf("POSIX create of %s failed (%s)\n",
10932                        illegal_fname, nt_errstr(status));
10933                 return false;
10934         }
10935
10936         status = cli_close(cli_posix, fnum);
10937         if (!NT_STATUS_IS_OK(status)) {
10938                 printf("close failed (%s)\n", nt_errstr(status));
10939                 return false;
10940         }
10941
10942         status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
10943         if (!NT_STATUS_IS_OK(status)) {
10944                 d_printf("cli_list failed: %s\n", nt_errstr(status));
10945                 return false;
10946         }
10947
10948         mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
10949         if (mangled_path == NULL) {
10950                 return false;
10951         }
10952
10953         status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
10954         if (!NT_STATUS_IS_OK(status)) {
10955                 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
10956                 TALLOC_FREE(mangled_path);
10957                 return false;
10958         }
10959         TALLOC_FREE(mangled_path);
10960         cli_close(cli, fnum);
10961
10962         cli_setatr(cli_posix, illegal_fname, 0, 0);
10963         cli_posix_unlink(cli_posix, illegal_fname);
10964
10965         /*
10966          * Create a file with a long name and check that we got *no* short name.
10967          */
10968
10969         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10970                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10971                               0, 0, &fnum, NULL);
10972         if (!NT_STATUS_IS_OK(status)) {
10973                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10974                 return false;
10975         }
10976         cli_close(cli, fnum);
10977
10978         status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
10979         if (!NT_STATUS_IS_OK(status)) {
10980                 d_printf("cli_list failed\n");
10981                 return false;
10982         }
10983
10984         cli_unlink(cli, fname, 0);
10985         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
10986
10987         if (!torture_close_connection(cli_posix)) {
10988                 return false;
10989         }
10990
10991         if (!torture_close_connection(cli)) {
10992                 return false;
10993         }
10994
10995         return true;
10996 }
10997
10998 static size_t null_source(uint8_t *buf, size_t n, void *priv)
10999 {
11000         size_t *to_pull = (size_t *)priv;
11001         size_t thistime = *to_pull;
11002
11003         thistime = MIN(thistime, n);
11004         if (thistime == 0) {
11005                 return 0;
11006         }
11007
11008         memset(buf, 0, thistime);
11009         *to_pull -= thistime;
11010         return thistime;
11011 }
11012
11013 static bool run_windows_write(int dummy)
11014 {
11015         struct cli_state *cli1;
11016         uint16_t fnum;
11017         int i;
11018         bool ret = false;
11019         const char *fname = "\\writetest.txt";
11020         struct timeval start_time;
11021         double seconds;
11022         double kbytes;
11023         NTSTATUS status;
11024
11025         printf("starting windows_write test\n");
11026         if (!torture_open_connection(&cli1, 0)) {
11027                 return False;
11028         }
11029
11030         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11031         if (!NT_STATUS_IS_OK(status)) {
11032                 printf("open failed (%s)\n", nt_errstr(status));
11033                 return False;
11034         }
11035
11036         smbXcli_conn_set_sockopt(cli1->conn, sockops);
11037
11038         start_time = timeval_current();
11039
11040         for (i=0; i<torture_numops; i++) {
11041                 uint8_t c = 0;
11042                 off_t start = i * torture_blocksize;
11043                 size_t to_pull = torture_blocksize - 1;
11044
11045                 status = cli_writeall(cli1, fnum, 0, &c,
11046                                       start + torture_blocksize - 1, 1, NULL);
11047                 if (!NT_STATUS_IS_OK(status)) {
11048                         printf("cli_write failed: %s\n", nt_errstr(status));
11049                         goto fail;
11050                 }
11051
11052                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11053                                   null_source, &to_pull);
11054                 if (!NT_STATUS_IS_OK(status)) {
11055                         printf("cli_push returned: %s\n", nt_errstr(status));
11056                         goto fail;
11057                 }
11058         }
11059
11060         seconds = timeval_elapsed(&start_time);
11061         kbytes = (double)torture_blocksize * torture_numops;
11062         kbytes /= 1024;
11063
11064         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11065                (double)seconds, (int)(kbytes/seconds));
11066
11067         ret = true;
11068  fail:
11069         cli_close(cli1, fnum);
11070         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11071         torture_close_connection(cli1);
11072         return ret;
11073 }
11074
11075 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11076 {
11077         size_t max_pdu = 0x1FFFF;
11078
11079         if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11080                 max_pdu = 0xFFFFFF;
11081         }
11082
11083         if (smb1cli_conn_signing_is_active(cli->conn)) {
11084                 max_pdu = 0x1FFFF;
11085         }
11086
11087         if (smb1cli_conn_encryption_on(cli->conn)) {
11088                 max_pdu = CLI_BUFFER_SIZE;
11089         }
11090
11091         if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11092                 len_requested &= 0xFFFF;
11093         }
11094
11095         return MIN(len_requested,
11096                    max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11097 }
11098
11099 static bool check_read_call(struct cli_state *cli,
11100                             uint16_t fnum,
11101                             uint8_t *buf,
11102                             size_t len_requested)
11103 {
11104         NTSTATUS status;
11105         struct tevent_req *subreq = NULL;
11106         ssize_t len_read = 0;
11107         size_t len_expected = 0;
11108         struct tevent_context *ev = NULL;
11109
11110         ev = samba_tevent_context_init(talloc_tos());
11111         if (ev == NULL) {
11112                 return false;
11113         }
11114
11115         subreq = cli_read_andx_send(talloc_tos(),
11116                                     ev,
11117                                     cli,
11118                                     fnum,
11119                                     0,
11120                                     len_requested);
11121
11122         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11123                 return false;
11124         }
11125
11126         status = cli_read_andx_recv(subreq, &len_read, &buf);
11127         if (!NT_STATUS_IS_OK(status)) {
11128                 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11129                 return false;
11130         }
11131
11132         TALLOC_FREE(subreq);
11133         TALLOC_FREE(ev);
11134
11135         len_expected = calc_expected_return(cli, len_requested);
11136
11137         if (len_expected > 0x10000 && len_read == 0x10000) {
11138                 /* Windows servers only return a max of 0x10000,
11139                    doesn't matter if you set CAP_LARGE_READX in
11140                    the client sessionsetupX call or not. */
11141                 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11142                         (unsigned int)len_requested);
11143         } else if (len_read != len_expected) {
11144                 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11145                         (unsigned int)len_requested,
11146                         (unsigned int)len_read,
11147                         (unsigned int)len_expected);
11148                 return false;
11149         } else {
11150                 d_printf("Correct read reply.\n");
11151         }
11152
11153         return true;
11154 }
11155
11156 /* Test large readX variants. */
11157 static bool large_readx_tests(struct cli_state *cli,
11158                                 uint16_t fnum,
11159                                 uint8_t *buf)
11160 {
11161         /* A read of 0xFFFF0001 should *always* return 1 byte. */
11162         if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11163                 return false;
11164         }
11165         /* A read of 0x10000 should return 0x10000 bytes. */
11166         if (check_read_call(cli, fnum, buf,    0x10000) == false) {
11167                 return false;
11168         }
11169         /* A read of 0x10000 should return 0x10001 bytes. */
11170         if (check_read_call(cli, fnum, buf,    0x10001) == false) {
11171                 return false;
11172         }
11173         /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11174            the requested number of bytes. */
11175         if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11176                 return false;
11177         }
11178         /* A read of 1MB should return 1MB bytes (on Samba). */
11179         if (check_read_call(cli, fnum, buf,   0x100000) == false) {
11180                 return false;
11181         }
11182
11183         if (check_read_call(cli, fnum, buf,    0x20001) == false) {
11184                 return false;
11185         }
11186         if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11187                 return false;
11188         }
11189         if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11190                 return false;
11191         }
11192         return true;
11193 }
11194
11195 static bool run_large_readx(int dummy)
11196 {
11197         uint8_t *buf = NULL;
11198         struct cli_state *cli1 = NULL;
11199         struct cli_state *cli2 = NULL;
11200         bool correct = false;
11201         const char *fname = "\\large_readx.dat";
11202         NTSTATUS status;
11203         uint16_t fnum1 = UINT16_MAX;
11204         uint32_t normal_caps = 0;
11205         size_t file_size = 20*1024*1024;
11206         TALLOC_CTX *frame = talloc_stackframe();
11207         size_t i;
11208         struct {
11209                 const char *name;
11210                 enum smb_signing_setting signing_setting;
11211                 enum protocol_types protocol;
11212         } runs[] = {
11213                 {
11214                         .name = "NT1",
11215                         .signing_setting = SMB_SIGNING_IF_REQUIRED,
11216                         .protocol = PROTOCOL_NT1,
11217                 },{
11218                         .name = "NT1 - SIGNING_REQUIRED",
11219                         .signing_setting = SMB_SIGNING_REQUIRED,
11220                         .protocol = PROTOCOL_NT1,
11221                 },
11222         };
11223
11224         printf("starting large_readx test\n");
11225
11226         if (!torture_open_connection(&cli1, 0)) {
11227                 goto out;
11228         }
11229
11230         normal_caps = smb1cli_conn_capabilities(cli1->conn);
11231
11232         if (!(normal_caps & CAP_LARGE_READX)) {
11233                 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11234                         (unsigned int)normal_caps);
11235                 goto out;
11236         }
11237
11238         /* Create a file of size 4MB. */
11239         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11240                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11241                         0, 0, &fnum1, NULL);
11242
11243         if (!NT_STATUS_IS_OK(status)) {
11244                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11245                 goto out;
11246         }
11247
11248         /* Write file_size bytes. */
11249         buf = talloc_zero_array(frame, uint8_t, file_size);
11250         if (buf == NULL) {
11251                 goto out;
11252         }
11253
11254         status = cli_writeall(cli1,
11255                               fnum1,
11256                               0,
11257                               buf,
11258                               0,
11259                               file_size,
11260                               NULL);
11261         if (!NT_STATUS_IS_OK(status)) {
11262                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11263                 goto out;
11264         }
11265
11266         status = cli_close(cli1, fnum1);
11267         if (!NT_STATUS_IS_OK(status)) {
11268                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11269                 goto out;
11270         }
11271
11272         fnum1 = UINT16_MAX;
11273
11274         for (i=0; i < ARRAY_SIZE(runs); i++) {
11275                 enum smb_signing_setting saved_signing_setting = signing_state;
11276                 uint16_t fnum2 = -1;
11277
11278                 if (do_encrypt &&
11279                     (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11280                 {
11281                         d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11282                         continue;
11283                 }
11284
11285                 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11286
11287                 signing_state = runs[i].signing_setting;
11288                 cli2 = open_nbt_connection();
11289                 signing_state = saved_signing_setting;
11290                 if (cli2 == NULL) {
11291                         goto out;
11292                 }
11293
11294                 status = smbXcli_negprot(cli2->conn,
11295                                          cli2->timeout,
11296                                          runs[i].protocol,
11297                                          runs[i].protocol);
11298                 if (!NT_STATUS_IS_OK(status)) {
11299                         goto out;
11300                 }
11301
11302                 status = cli_session_setup_creds(cli2, torture_creds);
11303                 if (!NT_STATUS_IS_OK(status)) {
11304                         goto out;
11305                 }
11306
11307                 status = cli_tree_connect(cli2,
11308                                         share,
11309                                         "?????",
11310                                         password);
11311                 if (!NT_STATUS_IS_OK(status)) {
11312                         goto out;
11313                 }
11314
11315                 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11316
11317                 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11318
11319                 if (!(normal_caps & CAP_LARGE_READX)) {
11320                         d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11321                                 (unsigned int)normal_caps);
11322                         goto out;
11323                 }
11324
11325                 if (do_encrypt) {
11326                         if (force_cli_encryption(cli2, share) == false) {
11327                                 goto out;
11328                         }
11329                 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11330                         uint16_t major, minor;
11331                         uint32_t caplow, caphigh;
11332
11333                         status = cli_unix_extensions_version(cli2,
11334                                                              &major, &minor,
11335                                                              &caplow, &caphigh);
11336                         if (!NT_STATUS_IS_OK(status)) {
11337                                 goto out;
11338                         }
11339                 }
11340
11341                 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11342                                 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11343                                 0, 0, &fnum2, NULL);
11344                 if (!NT_STATUS_IS_OK(status)) {
11345                         d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11346                         goto out;
11347                 }
11348
11349                 /* All reads must return less than file_size bytes. */
11350                 if (!large_readx_tests(cli2, fnum2, buf)) {
11351                         goto out;
11352                 }
11353
11354                 status = cli_close(cli2, fnum2);
11355                 if (!NT_STATUS_IS_OK(status)) {
11356                         d_printf("cli_close failed: %s\n", nt_errstr(status));
11357                         goto out;
11358                 }
11359                 fnum2 = -1;
11360
11361                 if (!torture_close_connection(cli2)) {
11362                         goto out;
11363                 }
11364                 cli2 = NULL;
11365         }
11366
11367         correct = true;
11368         printf("Success on large_readx test\n");
11369
11370   out:
11371
11372         if (cli2) {
11373                 if (!torture_close_connection(cli2)) {
11374                         correct = false;
11375                 }
11376         }
11377
11378         if (cli1) {
11379                 if (fnum1 != UINT16_MAX) {
11380                         status = cli_close(cli1, fnum1);
11381                         if (!NT_STATUS_IS_OK(status)) {
11382                                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11383                         }
11384                         fnum1 = UINT16_MAX;
11385                 }
11386
11387                 status = cli_unlink(cli1, fname,
11388                                     FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11389                 if (!NT_STATUS_IS_OK(status)) {
11390                         printf("unlink failed (%s)\n", nt_errstr(status));
11391                 }
11392
11393                 if (!torture_close_connection(cli1)) {
11394                         correct = false;
11395                 }
11396         }
11397
11398         TALLOC_FREE(frame);
11399
11400         printf("finished large_readx test\n");
11401         return correct;
11402 }
11403
11404 static bool run_cli_echo(int dummy)
11405 {
11406         struct cli_state *cli;
11407         NTSTATUS status;
11408
11409         printf("starting cli_echo test\n");
11410         if (!torture_open_connection(&cli, 0)) {
11411                 return false;
11412         }
11413         smbXcli_conn_set_sockopt(cli->conn, sockops);
11414
11415         status = cli_echo(cli, 5, data_blob_const("hello", 5));
11416
11417         d_printf("cli_echo returned %s\n", nt_errstr(status));
11418
11419         torture_close_connection(cli);
11420         return NT_STATUS_IS_OK(status);
11421 }
11422
11423 static int splice_status(off_t written, void *priv)
11424 {
11425         return true;
11426 }
11427
11428 static bool run_cli_splice(int dummy)
11429 {
11430         uint8_t *buf = NULL;
11431         struct cli_state *cli1 = NULL;
11432         bool correct = false;
11433         const char *fname_src = "\\splice_src.dat";
11434         const char *fname_dst = "\\splice_dst.dat";
11435         NTSTATUS status;
11436         uint16_t fnum1 = UINT16_MAX;
11437         uint16_t fnum2 = UINT16_MAX;
11438         size_t file_size = 2*1024*1024;
11439         size_t splice_size = 1*1024*1024 + 713;
11440         uint8_t digest1[16], digest2[16];
11441         off_t written = 0;
11442         size_t nread = 0;
11443         TALLOC_CTX *frame = talloc_stackframe();
11444
11445         printf("starting cli_splice test\n");
11446
11447         if (!torture_open_connection(&cli1, 0)) {
11448                 goto out;
11449         }
11450
11451         cli_unlink(cli1, fname_src,
11452                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11453         cli_unlink(cli1, fname_dst,
11454                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11455
11456         /* Create a file */
11457         status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11458                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11459                         0, 0, &fnum1, NULL);
11460
11461         if (!NT_STATUS_IS_OK(status)) {
11462                 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11463                 goto out;
11464         }
11465
11466         /* Write file_size bytes - must be bigger than splice_size. */
11467         buf = talloc_zero_array(frame, uint8_t, file_size);
11468         if (buf == NULL) {
11469                 d_printf("talloc_fail\n");
11470                 goto out;
11471         }
11472
11473         /* Fill it with random numbers. */
11474         generate_random_buffer(buf, file_size);
11475
11476         /* MD5 the first 1MB + 713 bytes. */
11477         gnutls_hash_fast(GNUTLS_DIG_MD5,
11478                          buf,
11479                          splice_size,
11480                          digest1);
11481
11482         status = cli_writeall(cli1,
11483                               fnum1,
11484                               0,
11485                               buf,
11486                               0,
11487                               file_size,
11488                               NULL);
11489         if (!NT_STATUS_IS_OK(status)) {
11490                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11491                 goto out;
11492         }
11493
11494         status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11495                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11496                         0, 0, &fnum2, NULL);
11497
11498         if (!NT_STATUS_IS_OK(status)) {
11499                 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11500                 goto out;
11501         }
11502
11503         /* Now splice 1MB + 713 bytes. */
11504         status = cli_splice(cli1,
11505                                 cli1,
11506                                 fnum1,
11507                                 fnum2,
11508                                 splice_size,
11509                                 0,
11510                                 0,
11511                                 &written,
11512                                 splice_status,
11513                                 NULL);
11514
11515         if (!NT_STATUS_IS_OK(status)) {
11516                 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11517                 goto out;
11518         }
11519
11520         /* Clear the old buffer. */
11521         memset(buf, '\0', file_size);
11522
11523         /* Read the new file. */
11524         status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11525         if (!NT_STATUS_IS_OK(status)) {
11526                 d_printf("cli_read failed: %s\n", nt_errstr(status));
11527                 goto out;
11528         }
11529         if (nread != splice_size) {
11530                 d_printf("bad read of 0x%x, should be 0x%x\n",
11531                         (unsigned int)nread,
11532                         (unsigned int)splice_size);
11533                 goto out;
11534         }
11535
11536         /* MD5 the first 1MB + 713 bytes. */
11537         gnutls_hash_fast(GNUTLS_DIG_MD5,
11538                          buf,
11539                          splice_size,
11540                          digest2);
11541
11542         /* Must be the same. */
11543         if (memcmp(digest1, digest2, 16) != 0) {
11544                 d_printf("bad MD5 compare\n");
11545                 goto out;
11546         }
11547
11548         correct = true;
11549         printf("Success on cli_splice test\n");
11550
11551   out:
11552
11553         if (cli1) {
11554                 if (fnum1 != UINT16_MAX) {
11555                         cli_close(cli1, fnum1);
11556                 }
11557                 if (fnum2 != UINT16_MAX) {
11558                         cli_close(cli1, fnum2);
11559                 }
11560
11561                 cli_unlink(cli1, fname_src,
11562                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11563                 cli_unlink(cli1, fname_dst,
11564                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11565
11566                 if (!torture_close_connection(cli1)) {
11567                         correct = false;
11568                 }
11569         }
11570
11571         TALLOC_FREE(frame);
11572         return correct;
11573 }
11574
11575 static bool run_uid_regression_test(int dummy)
11576 {
11577         static struct cli_state *cli;
11578         int16_t old_vuid;
11579         int32_t old_cnum;
11580         bool correct = True;
11581         struct smbXcli_tcon *orig_tcon = NULL;
11582         NTSTATUS status;
11583
11584         printf("starting uid regression test\n");
11585
11586         if (!torture_open_connection(&cli, 0)) {
11587                 return False;
11588         }
11589
11590         smbXcli_conn_set_sockopt(cli->conn, sockops);
11591
11592         /* Ok - now save then logoff our current user. */
11593         old_vuid = cli_state_get_uid(cli);
11594
11595         status = cli_ulogoff(cli);
11596         if (!NT_STATUS_IS_OK(status)) {
11597                 d_printf("(%s) cli_ulogoff failed: %s\n",
11598                          __location__, nt_errstr(status));
11599                 correct = false;
11600                 goto out;
11601         }
11602
11603         cli_state_set_uid(cli, old_vuid);
11604
11605         /* Try an operation. */
11606         status = cli_mkdir(cli, "\\uid_reg_test");
11607         if (NT_STATUS_IS_OK(status)) {
11608                 d_printf("(%s) cli_mkdir succeeded\n",
11609                          __location__);
11610                 correct = false;
11611                 goto out;
11612         } else {
11613                 /* Should be bad uid. */
11614                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11615                                  NT_STATUS_USER_SESSION_DELETED)) {
11616                         correct = false;
11617                         goto out;
11618                 }
11619         }
11620
11621         old_cnum = cli_state_get_tid(cli);
11622         orig_tcon = cli_state_save_tcon(cli);
11623         if (orig_tcon == NULL) {
11624                 correct = false;
11625                 goto out;
11626         }
11627
11628         /* Now try a SMBtdis with the invalid vuid set to zero. */
11629         cli_state_set_uid(cli, 0);
11630
11631         /* This should succeed. */
11632         status = cli_tdis(cli);
11633
11634         if (NT_STATUS_IS_OK(status)) {
11635                 d_printf("First tdis with invalid vuid should succeed.\n");
11636         } else {
11637                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
11638                 correct = false;
11639                 cli_state_restore_tcon(cli, orig_tcon);
11640                 goto out;
11641         }
11642
11643         cli_state_restore_tcon(cli, orig_tcon);
11644         cli_state_set_uid(cli, old_vuid);
11645         cli_state_set_tid(cli, old_cnum);
11646
11647         /* This should fail. */
11648         status = cli_tdis(cli);
11649         if (NT_STATUS_IS_OK(status)) {
11650                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
11651                 correct = false;
11652                 goto out;
11653         } else {
11654                 /* Should be bad tid. */
11655                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
11656                                 NT_STATUS_NETWORK_NAME_DELETED)) {
11657                         correct = false;
11658                         goto out;
11659                 }
11660         }
11661
11662         cli_rmdir(cli, "\\uid_reg_test");
11663
11664   out:
11665
11666         cli_shutdown(cli);
11667         return correct;
11668 }
11669
11670
11671 static const char *illegal_chars = "*\\/?<>|\":";
11672 static char force_shortname_chars[] = " +,.[];=\177";
11673
11674 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
11675                              const char *mask, void *state)
11676 {
11677         struct cli_state *pcli = (struct cli_state *)state;
11678         fstring fname;
11679         NTSTATUS status = NT_STATUS_OK;
11680
11681         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
11682
11683         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
11684                 return NT_STATUS_OK;
11685
11686         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
11687                 status = cli_rmdir(pcli, fname);
11688                 if (!NT_STATUS_IS_OK(status)) {
11689                         printf("del_fn: failed to rmdir %s\n,", fname );
11690                 }
11691         } else {
11692                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11693                 if (!NT_STATUS_IS_OK(status)) {
11694                         printf("del_fn: failed to unlink %s\n,", fname );
11695                 }
11696         }
11697         return status;
11698 }
11699
11700 struct sn_state {
11701         int matched;
11702         int i;
11703         bool val;
11704 };
11705
11706 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
11707                               const char *name, void *state)
11708 {
11709         struct sn_state *s = (struct sn_state  *)state;
11710         int i = s->i;
11711
11712 #if 0
11713         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
11714                 i, finfo->name, finfo->short_name);
11715 #endif
11716
11717         if (strchr(force_shortname_chars, i)) {
11718                 if (!finfo->short_name) {
11719                         /* Shortname not created when it should be. */
11720                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
11721                                 __location__, finfo->name, i);
11722                         s->val = true;
11723                 }
11724         } else if (finfo->short_name){
11725                 /* Shortname created when it should not be. */
11726                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
11727                         __location__, finfo->short_name, finfo->name);
11728                 s->val = true;
11729         }
11730         s->matched += 1;
11731         return NT_STATUS_OK;
11732 }
11733
11734 static bool run_shortname_test(int dummy)
11735 {
11736         static struct cli_state *cli;
11737         bool correct = True;
11738         int i;
11739         struct sn_state s;
11740         char fname[40];
11741         NTSTATUS status;
11742
11743         printf("starting shortname test\n");
11744
11745         if (!torture_open_connection(&cli, 0)) {
11746                 return False;
11747         }
11748
11749         smbXcli_conn_set_sockopt(cli->conn, sockops);
11750
11751         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11752         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11753         cli_rmdir(cli, "\\shortname");
11754
11755         status = cli_mkdir(cli, "\\shortname");
11756         if (!NT_STATUS_IS_OK(status)) {
11757                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
11758                         __location__, nt_errstr(status));
11759                 correct = false;
11760                 goto out;
11761         }
11762
11763         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
11764                 correct = false;
11765                 goto out;
11766         }
11767         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
11768                 correct = false;
11769                 goto out;
11770         }
11771
11772         s.val = false;
11773
11774         for (i = 32; i < 128; i++) {
11775                 uint16_t fnum = (uint16_t)-1;
11776
11777                 s.i = i;
11778
11779                 if (strchr(illegal_chars, i)) {
11780                         continue;
11781                 }
11782                 fname[15] = i;
11783
11784                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
11785                                    FILE_SHARE_READ|FILE_SHARE_WRITE,
11786                                    FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
11787                 if (!NT_STATUS_IS_OK(status)) {
11788                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
11789                                 __location__, fname, nt_errstr(status));
11790                         correct = false;
11791                         goto out;
11792                 }
11793                 cli_close(cli, fnum);
11794
11795                 s.matched = 0;
11796                 status = cli_list(cli, "\\shortname\\test*.*", 0,
11797                                   shortname_list_fn, &s);
11798                 if (s.matched != 1) {
11799                         d_printf("(%s) failed to list %s: %s\n",
11800                                 __location__, fname, nt_errstr(status));
11801                         correct = false;
11802                         goto out;
11803                 }
11804
11805                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11806                 if (!NT_STATUS_IS_OK(status)) {
11807                         d_printf("(%s) failed to delete %s: %s\n",
11808                                 __location__, fname, nt_errstr(status));
11809                         correct = false;
11810                         goto out;
11811                 }
11812
11813                 if (s.val) {
11814                         correct = false;
11815                         goto out;
11816                 }
11817         }
11818
11819   out:
11820
11821         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11822         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11823         cli_rmdir(cli, "\\shortname");
11824         torture_close_connection(cli);
11825         return correct;
11826 }
11827
11828 TLDAPRC callback_code;
11829
11830 static void pagedsearch_cb(struct tevent_req *req)
11831 {
11832         TLDAPRC rc;
11833         struct tldap_message *msg;
11834         char *dn;
11835
11836         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
11837         if (!TLDAP_RC_IS_SUCCESS(rc)) {
11838                 d_printf("tldap_search_paged_recv failed: %s\n",
11839                          tldap_rc2string(rc));
11840                 callback_code = rc;
11841                 return;
11842         }
11843         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
11844                 TALLOC_FREE(msg);
11845                 return;
11846         }
11847         if (!tldap_entry_dn(msg, &dn)) {
11848                 d_printf("tldap_entry_dn failed\n");
11849                 return;
11850         }
11851         d_printf("%s\n", dn);
11852         TALLOC_FREE(msg);
11853 }
11854
11855 enum tldap_extended_val {
11856         EXTENDED_ZERO = 0,
11857         EXTENDED_ONE = 1,
11858         EXTENDED_NONE = 2,
11859 };
11860
11861 /*
11862  * Construct an extended dn control with either no value, 0 or 1
11863  *
11864  * No value and 0 are equivalent (non-hyphenated GUID)
11865  * 1 has the hyphenated GUID
11866  */
11867 static struct tldap_control *
11868 tldap_build_extended_control(enum tldap_extended_val val)
11869 {
11870         struct tldap_control empty_control;
11871         struct asn1_data *data;
11872
11873         ZERO_STRUCT(empty_control);
11874
11875         if (val != EXTENDED_NONE) {
11876                 data = asn1_init(talloc_tos());
11877
11878                 if (!data) {
11879                         return NULL;
11880                 }
11881
11882                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
11883                         return NULL;
11884                 }
11885
11886                 if (!asn1_write_Integer(data, (int)val)) {
11887                         return NULL;
11888                 }
11889
11890                 if (!asn1_pop_tag(data)) {
11891                         return NULL;
11892                 }
11893
11894                 if (!asn1_blob(data, &empty_control.value)) {
11895                         return NULL;
11896                 }
11897         }
11898
11899         empty_control.oid = "1.2.840.113556.1.4.529";
11900         empty_control.critical = true;
11901
11902         return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
11903
11904 }
11905
11906 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
11907                                       enum tldap_extended_val control_val)
11908 {
11909         struct tldap_control *control = tldap_build_extended_control(control_val);
11910         char *dn = NULL;
11911         struct tldap_message **msg;
11912         TLDAPRC rc;
11913
11914         rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
11915                           "(objectClass=*)", NULL, 0, 0,
11916                           control, 1, NULL,
11917                           0, 0, 0, 0, talloc_tos(), &msg);
11918         if (!TLDAP_RC_IS_SUCCESS(rc)) {
11919                 d_printf("tldap_search for domain DN failed: %s\n",
11920                          tldap_errstr(talloc_tos(), ld, rc));
11921                 return false;
11922         }
11923
11924         if (!tldap_entry_dn(msg[0], &dn)) {
11925                 d_printf("tldap_search domain DN fetch failed: %s\n",
11926                          tldap_errstr(talloc_tos(), ld, rc));
11927                 return false;
11928         }
11929
11930         d_printf("%s\n", dn);
11931         {
11932                 uint32_t time_low;
11933                 uint32_t time_mid, time_hi_and_version;
11934                 uint32_t clock_seq[2];
11935                 uint32_t node[6];
11936                 char next;
11937
11938                 switch (control_val) {
11939                 case EXTENDED_NONE:
11940                 case EXTENDED_ZERO:
11941                         /*
11942                          * When reading GUIDs with hyphens, scanf will treat
11943                          * hyphen as a hex character (and counts as part of the
11944                          * width). This creates leftover GUID string which we
11945                          * check will for with 'next' and closing '>'.
11946                          */
11947                         if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
11948                                          &time_low, &time_mid,
11949                                          &time_hi_and_version, &clock_seq[0],
11950                                          &clock_seq[1], &node[0], &node[1],
11951                                          &node[2], &node[3], &node[4],
11952                                          &node[5], &next)) {
11953                                 /* This GUID is good */
11954                         } else {
11955                                 d_printf("GUID format in control (no hyphens) doesn't match output\n");
11956                                 return false;
11957                         }
11958
11959                         break;
11960                 case EXTENDED_ONE:
11961                         if (12 == sscanf(dn,
11962                                          "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
11963                                          &time_low, &time_mid,
11964                                          &time_hi_and_version, &clock_seq[0],
11965                                          &clock_seq[1], &node[0], &node[1],
11966                                          &node[2], &node[3], &node[4],
11967                                          &node[5], &next)) {
11968                                 /* This GUID is good */
11969                         } else {
11970                                 d_printf("GUID format in control (with hyphens) doesn't match output\n");
11971                                 return false;
11972                         }
11973
11974                         break;
11975                 default:
11976                         return false;
11977                 }
11978         }
11979
11980         return true;
11981 }
11982
11983 static bool run_tldap(int dummy)
11984 {
11985         struct tldap_context *ld;
11986         int fd;
11987         TLDAPRC rc;
11988         NTSTATUS status;
11989         struct sockaddr_storage addr;
11990         struct tevent_context *ev;
11991         struct tevent_req *req;
11992         char *basedn;
11993         const char *filter;
11994
11995         if (!resolve_name(host, &addr, 0, false)) {
11996                 d_printf("could not find host %s\n", host);
11997                 return false;
11998         }
11999         status = open_socket_out(&addr, 389, 9999, &fd);
12000         if (!NT_STATUS_IS_OK(status)) {
12001                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12002                 return false;
12003         }
12004
12005         ld = tldap_context_create(talloc_tos(), fd);
12006         if (ld == NULL) {
12007                 close(fd);
12008                 d_printf("tldap_context_create failed\n");
12009                 return false;
12010         }
12011
12012         rc = tldap_fetch_rootdse(ld);
12013         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12014                 d_printf("tldap_fetch_rootdse failed: %s\n",
12015                          tldap_errstr(talloc_tos(), ld, rc));
12016                 return false;
12017         }
12018
12019         basedn = tldap_talloc_single_attribute(
12020                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12021         if (basedn == NULL) {
12022                 d_printf("no defaultNamingContext\n");
12023                 return false;
12024         }
12025         d_printf("defaultNamingContext: %s\n", basedn);
12026
12027         ev = samba_tevent_context_init(talloc_tos());
12028         if (ev == NULL) {
12029                 d_printf("tevent_context_init failed\n");
12030                 return false;
12031         }
12032
12033         rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12034                                loadparm_init_s3(talloc_tos(),
12035                                                 loadparm_s3_helpers()),
12036                                GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12037
12038         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12039                 d_printf("tldap_gensec_bind failed\n");
12040                 return false;
12041         }
12042
12043         callback_code = TLDAP_SUCCESS;
12044
12045         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12046                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
12047                                       NULL, 0, 0,
12048                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
12049         if (req == NULL) {
12050                 d_printf("tldap_search_paged_send failed\n");
12051                 return false;
12052         }
12053         tevent_req_set_callback(req, pagedsearch_cb, NULL);
12054
12055         tevent_req_poll(req, ev);
12056
12057         TALLOC_FREE(req);
12058
12059         rc = callback_code;
12060
12061         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12062                 d_printf("tldap_search with paging failed: %s\n",
12063                          tldap_errstr(talloc_tos(), ld, rc));
12064                 return false;
12065         }
12066
12067         /* test search filters against rootDSE */
12068         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12069                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12070
12071         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12072                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12073                           talloc_tos(), NULL);
12074         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12075                 d_printf("tldap_search with complex filter failed: %s\n",
12076                          tldap_errstr(talloc_tos(), ld, rc));
12077                 return false;
12078         }
12079
12080         /*
12081          * Tests to check for regression of:
12082          *
12083          * https://bugzilla.samba.org/show_bug.cgi?id=14029
12084          *
12085          * TLDAP used here to pick apart the original string DN (with GUID)
12086          */
12087         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12088                 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12089                          tldap_errstr(talloc_tos(), ld, rc));
12090                 return false;
12091         }
12092         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12093                 d_printf("tldap_search with extended dn (0) failed: %s\n",
12094                          tldap_errstr(talloc_tos(), ld, rc));
12095                 return false;
12096         }
12097         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12098                 d_printf("tldap_search with extended dn (1) failed: %s\n",
12099                          tldap_errstr(talloc_tos(), ld, rc));
12100                 return false;
12101         }
12102
12103         TALLOC_FREE(ld);
12104         return true;
12105 }
12106
12107 /* Torture test to ensure no regression of :
12108 https://bugzilla.samba.org/show_bug.cgi?id=7084
12109 */
12110
12111 static bool run_dir_createtime(int dummy)
12112 {
12113         struct cli_state *cli;
12114         const char *dname = "\\testdir_createtime";
12115         const char *fname = "\\testdir_createtime\\testfile";
12116         NTSTATUS status;
12117         struct timespec create_time;
12118         struct timespec create_time1;
12119         uint16_t fnum;
12120         bool ret = false;
12121         uint64_t ino;
12122
12123         if (!torture_open_connection(&cli, 0)) {
12124                 return false;
12125         }
12126
12127         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12128                 /* Ensure ino is zero, SMB2 gets a real one. */
12129                 ino = 0;
12130         } else {
12131                 /* Ensure ino is -1, SMB1 never gets a real one. */
12132                 ino = (uint64_t)-1;
12133         }
12134
12135         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12136         cli_rmdir(cli, dname);
12137
12138         status = cli_mkdir(cli, dname);
12139         if (!NT_STATUS_IS_OK(status)) {
12140                 printf("mkdir failed: %s\n", nt_errstr(status));
12141                 goto out;
12142         }
12143
12144         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
12145                                 NULL, NULL, &ino);
12146         if (!NT_STATUS_IS_OK(status)) {
12147                 printf("cli_qpathinfo2 returned %s\n",
12148                        nt_errstr(status));
12149                 goto out;
12150         }
12151
12152         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12153                 /* SMB2 should always return an inode. */
12154                 if (ino == 0) {
12155                         printf("SMB2 bad inode (0)\n");
12156                         goto out;
12157                 }
12158         } else {
12159                 /* SMB1 must always return zero here. */
12160                 if (ino != 0) {
12161                         printf("SMB1 bad inode (!0)\n");
12162                         goto out;
12163                 }
12164         }
12165
12166         /* Sleep 3 seconds, then create a file. */
12167         sleep(3);
12168
12169         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12170                          DENY_NONE, &fnum);
12171         if (!NT_STATUS_IS_OK(status)) {
12172                 printf("cli_openx failed: %s\n", nt_errstr(status));
12173                 goto out;
12174         }
12175
12176         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
12177                                 NULL, NULL, NULL);
12178         if (!NT_STATUS_IS_OK(status)) {
12179                 printf("cli_qpathinfo2 (2) returned %s\n",
12180                        nt_errstr(status));
12181                 goto out;
12182         }
12183
12184         if (timespec_compare(&create_time1, &create_time)) {
12185                 printf("run_dir_createtime: create time was updated (error)\n");
12186         } else {
12187                 printf("run_dir_createtime: create time was not updated (correct)\n");
12188                 ret = true;
12189         }
12190
12191   out:
12192
12193         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12194         cli_rmdir(cli, dname);
12195         if (!torture_close_connection(cli)) {
12196                 ret = false;
12197         }
12198         return ret;
12199 }
12200
12201
12202 static bool run_streamerror(int dummy)
12203 {
12204         struct cli_state *cli;
12205         const char *dname = "\\testdir_streamerror";
12206         const char *streamname =
12207                 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12208         NTSTATUS status;
12209         time_t change_time, access_time, write_time;
12210         off_t size;
12211         uint16_t mode, fnum;
12212         bool ret = true;
12213
12214         if (!torture_open_connection(&cli, 0)) {
12215                 return false;
12216         }
12217
12218         cli_unlink(cli, "\\testdir_streamerror\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12219         cli_rmdir(cli, dname);
12220
12221         status = cli_mkdir(cli, dname);
12222         if (!NT_STATUS_IS_OK(status)) {
12223                 printf("mkdir failed: %s\n", nt_errstr(status));
12224                 return false;
12225         }
12226
12227         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12228                                 &write_time, &size, &mode);
12229         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12230                 printf("pathinfo returned %s, expected "
12231                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12232                        nt_errstr(status));
12233                 ret = false;
12234         }
12235
12236         status = cli_ntcreate(cli, streamname, 0x16,
12237                               FILE_READ_DATA|FILE_READ_EA|
12238                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12239                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12240                               FILE_OPEN, 0, 0, &fnum, NULL);
12241
12242         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12243                 printf("ntcreate returned %s, expected "
12244                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12245                        nt_errstr(status));
12246                 ret = false;
12247         }
12248
12249
12250         cli_rmdir(cli, dname);
12251         return ret;
12252 }
12253
12254 struct pidtest_state {
12255         bool success;
12256         uint16_t vwv[1];
12257         DATA_BLOB data;
12258 };
12259
12260 static void pid_echo_done(struct tevent_req *subreq);
12261
12262 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12263                         struct tevent_context *ev,
12264                         struct cli_state *cli)
12265 {
12266         struct tevent_req *req, *subreq;
12267         struct pidtest_state *state;
12268
12269         req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12270         if (req == NULL) {
12271                 return NULL;
12272         }
12273
12274         SSVAL(state->vwv, 0, 1);
12275         state->data = data_blob_const("hello", 5);
12276
12277         subreq = smb1cli_req_send(state,
12278                                 ev,
12279                                 cli->conn,
12280                                 SMBecho,
12281                                 0, 0, /* *_flags */
12282                                 0, 0, /* *_flags2 */
12283                                 cli->timeout,
12284                                 0xDEADBEEF, /* pid */
12285                                 NULL, /* tcon */
12286                                 NULL, /* session */
12287                                 ARRAY_SIZE(state->vwv), state->vwv,
12288                                 state->data.length, state->data.data);
12289
12290         if (tevent_req_nomem(subreq, req)) {
12291                 return tevent_req_post(req, ev);
12292         }
12293         tevent_req_set_callback(subreq, pid_echo_done, req);
12294         return req;
12295 }
12296
12297 static void pid_echo_done(struct tevent_req *subreq)
12298 {
12299         struct tevent_req *req = tevent_req_callback_data(
12300                 subreq, struct tevent_req);
12301         struct pidtest_state *state = tevent_req_data(
12302                 req, struct pidtest_state);
12303         NTSTATUS status;
12304         uint32_t num_bytes;
12305         uint8_t *bytes = NULL;
12306         struct iovec *recv_iov = NULL;
12307         uint8_t *phdr = NULL;
12308         uint16_t pidlow = 0;
12309         uint16_t pidhigh = 0;
12310         struct smb1cli_req_expected_response expected[] = {
12311         {
12312                 .status = NT_STATUS_OK,
12313                 .wct    = 1,
12314         },
12315         };
12316
12317         status = smb1cli_req_recv(subreq, state,
12318                                 &recv_iov,
12319                                 &phdr,
12320                                 NULL, /* pwct */
12321                                 NULL, /* pvwv */
12322                                 NULL, /* pvwv_offset */
12323                                 &num_bytes,
12324                                 &bytes,
12325                                 NULL, /* pbytes_offset */
12326                                 NULL, /* pinbuf */
12327                                 expected, ARRAY_SIZE(expected));
12328
12329         TALLOC_FREE(subreq);
12330
12331         if (!NT_STATUS_IS_OK(status)) {
12332                 tevent_req_nterror(req, status);
12333                 return;
12334         }
12335
12336         if (num_bytes != state->data.length) {
12337                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12338                 return;
12339         }
12340
12341         if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12342                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12343                 return;
12344         }
12345
12346         /* Check pid low/high == DEADBEEF */
12347         pidlow = SVAL(phdr, HDR_PID);
12348         if (pidlow != 0xBEEF){
12349                 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12350                         (unsigned int)pidlow);
12351                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12352                 return;
12353         }
12354         pidhigh = SVAL(phdr, HDR_PIDHIGH);
12355         if (pidhigh != 0xDEAD){
12356                 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12357                         (unsigned int)pidhigh);
12358                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12359                 return;
12360         }
12361
12362         tevent_req_done(req);
12363 }
12364
12365 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12366 {
12367         return tevent_req_simple_recv_ntstatus(req);
12368 }
12369
12370 static bool run_pidhigh(int dummy)
12371 {
12372         bool success = false;
12373         struct cli_state *cli = NULL;
12374         NTSTATUS status;
12375         struct tevent_context *ev = NULL;
12376         struct tevent_req *req = NULL;
12377         TALLOC_CTX *frame = talloc_stackframe();
12378
12379         printf("starting pid high test\n");
12380         if (!torture_open_connection(&cli, 0)) {
12381                 return false;
12382         }
12383         smbXcli_conn_set_sockopt(cli->conn, sockops);
12384
12385         ev = samba_tevent_context_init(frame);
12386         if (ev == NULL) {
12387                 goto fail;
12388         }
12389
12390         req = pid_echo_send(frame, ev, cli);
12391         if (req == NULL) {
12392                 goto fail;
12393         }
12394
12395         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12396                 goto fail;
12397         }
12398
12399         status = pid_echo_recv(req);
12400         if (NT_STATUS_IS_OK(status)) {
12401                 printf("pid high test ok\n");
12402                 success = true;
12403         }
12404
12405  fail:
12406
12407         TALLOC_FREE(frame);
12408         torture_close_connection(cli);
12409         return success;
12410 }
12411
12412 /*
12413   Test Windows open on a bad POSIX symlink.
12414  */
12415 static bool run_symlink_open_test(int dummy)
12416 {
12417         static struct cli_state *cli;
12418         const char *fname = "non_existant_file";
12419         const char *sname = "dangling_symlink";
12420         uint16_t fnum = (uint16_t)-1;
12421         bool correct = false;
12422         NTSTATUS status;
12423         TALLOC_CTX *frame = NULL;
12424
12425         frame = talloc_stackframe();
12426
12427         printf("Starting Windows bad symlink open test\n");
12428
12429         if (!torture_open_connection(&cli, 0)) {
12430                 TALLOC_FREE(frame);
12431                 return false;
12432         }
12433
12434         smbXcli_conn_set_sockopt(cli->conn, sockops);
12435
12436         status = torture_setup_unix_extensions(cli);
12437         if (!NT_STATUS_IS_OK(status)) {
12438                 TALLOC_FREE(frame);
12439                 return false;
12440         }
12441
12442         /* Ensure nothing exists. */
12443         cli_setatr(cli, fname, 0, 0);
12444         cli_posix_unlink(cli, fname);
12445         cli_setatr(cli, sname, 0, 0);
12446         cli_posix_unlink(cli, sname);
12447
12448         /* Create a symlink pointing nowhere. */
12449         status = cli_posix_symlink(cli, fname, sname);
12450         if (!NT_STATUS_IS_OK(status)) {
12451                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12452                         sname,
12453                         fname,
12454                         nt_errstr(status));
12455                 goto out;
12456         }
12457
12458         /* Now ensure that a Windows open doesn't hang. */
12459         status = cli_ntcreate(cli,
12460                         sname,
12461                         0,
12462                         FILE_READ_DATA|FILE_WRITE_DATA,
12463                         0,
12464                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12465                         FILE_OPEN_IF,
12466                         0x0,
12467                         0x0,
12468                         &fnum,
12469                         NULL);
12470
12471         /*
12472          * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12473          * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12474          * we use O_NOFOLLOW on the server or not.
12475          */
12476         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12477             NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12478         {
12479                 correct = true;
12480         } else {
12481                 printf("cli_ntcreate of %s returned %s - should return"
12482                                 " either (%s) or (%s)\n",
12483                         sname,
12484                         nt_errstr(status),
12485                         nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12486                         nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12487                 goto out;
12488         }
12489
12490         correct = true;
12491
12492   out:
12493
12494         if (fnum != (uint16_t)-1) {
12495                 cli_close(cli, fnum);
12496                 fnum = (uint16_t)-1;
12497         }
12498
12499         cli_setatr(cli, sname, 0, 0);
12500         cli_posix_unlink(cli, sname);
12501         cli_setatr(cli, fname, 0, 0);
12502         cli_posix_unlink(cli, fname);
12503
12504         if (!torture_close_connection(cli)) {
12505                 correct = false;
12506         }
12507
12508         TALLOC_FREE(frame);
12509         return correct;
12510 }
12511
12512 /*
12513  * Only testing minimal time strings, as the others
12514  * need (locale-dependent) guessing at what strftime does and
12515  * even may differ in builds.
12516  */
12517 static bool timesubst_test(void)
12518 {
12519         TALLOC_CTX *ctx = NULL;
12520         /* Sa 23. Dez 04:33:20 CET 2017 */
12521         const struct timeval tv = { 1514000000, 123 };
12522         const char* expect_minimal = "20171223_033320";
12523         const char* expect_minus   = "20171223_033320_000123";
12524         char *s;
12525         char *env_tz, *orig_tz = NULL;
12526         bool result = true;
12527
12528         ctx = talloc_new(NULL);
12529
12530         env_tz = getenv("TZ");
12531         if(env_tz) {
12532                 orig_tz = talloc_strdup(ctx, env_tz);
12533         }
12534         setenv("TZ", "UTC", 1);
12535
12536         s = minimal_timeval_string(ctx, &tv, false);
12537
12538         if(!s || strcmp(s, expect_minimal)) {
12539                 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
12540                        "[%s]\n", s ? s : "<nil>", expect_minimal);
12541                 result = false;
12542         }
12543         TALLOC_FREE(s);
12544         s = minimal_timeval_string(ctx, &tv, true);
12545         if(!s || strcmp(s, expect_minus)) {
12546                 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
12547                        "[%s]\n", s ? s : "<nil>", expect_minus);
12548                 result = false;
12549         }
12550         TALLOC_FREE(s);
12551
12552         if(orig_tz) {
12553                 setenv("TZ", orig_tz, 1);
12554         }
12555
12556         TALLOC_FREE(ctx);
12557         return result;
12558 }
12559
12560 static bool run_local_substitute(int dummy)
12561 {
12562         bool ok = true;
12563
12564         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
12565         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
12566         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
12567         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
12568         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
12569         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
12570         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
12571         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
12572         ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
12573         /* Substitution depends on current time, so better test the underlying
12574            formatting function. At least covers %t. */
12575         ok &= timesubst_test();
12576
12577         /* Different captialization rules in sub_basic... */
12578
12579         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
12580                        "blaDOM") == 0);
12581
12582         return ok;
12583 }
12584
12585 static bool run_local_base64(int dummy)
12586 {
12587         int i;
12588         bool ret = true;
12589
12590         for (i=1; i<2000; i++) {
12591                 DATA_BLOB blob1, blob2;
12592                 char *b64;
12593
12594                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
12595                 blob1.length = i;
12596                 generate_random_buffer(blob1.data, blob1.length);
12597
12598                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
12599                 if (b64 == NULL) {
12600                         d_fprintf(stderr, "base64_encode_data_blob failed "
12601                                   "for %d bytes\n", i);
12602                         ret = false;
12603                 }
12604                 blob2 = base64_decode_data_blob(b64);
12605                 TALLOC_FREE(b64);
12606
12607                 if (data_blob_cmp(&blob1, &blob2)) {
12608                         d_fprintf(stderr, "data_blob_cmp failed for %d "
12609                                   "bytes\n", i);
12610                         ret = false;
12611                 }
12612                 TALLOC_FREE(blob1.data);
12613                 data_blob_free(&blob2);
12614         }
12615         return ret;
12616 }
12617
12618 static void parse_fn(const struct gencache_timeout *t,
12619                      DATA_BLOB blob,
12620                      void *private_data)
12621 {
12622         return;
12623 }
12624
12625 static bool run_local_gencache(int dummy)
12626 {
12627         char *val;
12628         time_t tm;
12629         DATA_BLOB blob;
12630         char v;
12631         struct memcache *mem;
12632         int i;
12633
12634         mem = memcache_init(NULL, 0);
12635         if (mem == NULL) {
12636                 d_printf("%s: memcache_init failed\n", __location__);
12637                 return false;
12638         }
12639         memcache_set_global(mem);
12640
12641         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
12642                 d_printf("%s: gencache_set() failed\n", __location__);
12643                 return False;
12644         }
12645
12646         if (!gencache_get("foo", NULL, NULL, NULL)) {
12647                 d_printf("%s: gencache_get() failed\n", __location__);
12648                 return False;
12649         }
12650
12651         for (i=0; i<1000000; i++) {
12652                 gencache_parse("foo", parse_fn, NULL);
12653         }
12654
12655         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
12656                 d_printf("%s: gencache_get() failed\n", __location__);
12657                 return False;
12658         }
12659         TALLOC_FREE(val);
12660
12661         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
12662                 d_printf("%s: gencache_get() failed\n", __location__);
12663                 return False;
12664         }
12665
12666         if (strcmp(val, "bar") != 0) {
12667                 d_printf("%s: gencache_get() returned %s, expected %s\n",
12668                          __location__, val, "bar");
12669                 TALLOC_FREE(val);
12670                 return False;
12671         }
12672
12673         TALLOC_FREE(val);
12674
12675         if (!gencache_del("foo")) {
12676                 d_printf("%s: gencache_del() failed\n", __location__);
12677                 return False;
12678         }
12679         if (gencache_del("foo")) {
12680                 d_printf("%s: second gencache_del() succeeded\n",
12681                          __location__);
12682                 return False;
12683         }
12684
12685         if (gencache_get("foo", talloc_tos(), &val, &tm)) {
12686                 d_printf("%s: gencache_get() on deleted entry "
12687                          "succeeded\n", __location__);
12688                 return False;
12689         }
12690
12691         blob = data_blob_string_const_null("bar");
12692         tm = time(NULL) + 60;
12693
12694         if (!gencache_set_data_blob("foo", blob, tm)) {
12695                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
12696                 return False;
12697         }
12698
12699         if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
12700                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
12701                 return False;
12702         }
12703
12704         if (strcmp((const char *)blob.data, "bar") != 0) {
12705                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
12706                          __location__, (const char *)blob.data, "bar");
12707                 data_blob_free(&blob);
12708                 return False;
12709         }
12710
12711         data_blob_free(&blob);
12712
12713         if (!gencache_del("foo")) {
12714                 d_printf("%s: gencache_del() failed\n", __location__);
12715                 return False;
12716         }
12717         if (gencache_del("foo")) {
12718                 d_printf("%s: second gencache_del() succeeded\n",
12719                          __location__);
12720                 return False;
12721         }
12722
12723         if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
12724                 d_printf("%s: gencache_get_data_blob() on deleted entry "
12725                          "succeeded\n", __location__);
12726                 return False;
12727         }
12728
12729         v = 1;
12730         blob.data = (uint8_t *)&v;
12731         blob.length = sizeof(v);
12732
12733         if (!gencache_set_data_blob("blob", blob, tm)) {
12734                 d_printf("%s: gencache_set_data_blob() failed\n",
12735                          __location__);
12736                 return false;
12737         }
12738         if (gencache_get("blob", talloc_tos(), &val, &tm)) {
12739                 d_printf("%s: gencache_get succeeded\n", __location__);
12740                 return false;
12741         }
12742
12743         return True;
12744 }
12745
12746 static bool rbt_testval(struct db_context *db, const char *key,
12747                         const char *value)
12748 {
12749         struct db_record *rec;
12750         TDB_DATA data = string_tdb_data(value);
12751         bool ret = false;
12752         NTSTATUS status;
12753         TDB_DATA dbvalue;
12754
12755         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
12756         if (rec == NULL) {
12757                 d_fprintf(stderr, "fetch_locked failed\n");
12758                 goto done;
12759         }
12760         status = dbwrap_record_store(rec, data, 0);
12761         if (!NT_STATUS_IS_OK(status)) {
12762                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
12763                 goto done;
12764         }
12765         TALLOC_FREE(rec);
12766
12767         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
12768         if (rec == NULL) {
12769                 d_fprintf(stderr, "second fetch_locked failed\n");
12770                 goto done;
12771         }
12772
12773         dbvalue = dbwrap_record_get_value(rec);
12774         if ((dbvalue.dsize != data.dsize)
12775             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
12776                 d_fprintf(stderr, "Got wrong data back\n");
12777                 goto done;
12778         }
12779
12780         ret = true;
12781  done:
12782         TALLOC_FREE(rec);
12783         return ret;
12784 }
12785
12786 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
12787 {
12788         int *count2 = (int *)private_data;
12789         (*count2)++;
12790         return 0;
12791 }
12792
12793 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
12794 {
12795         int *count2 = (int *)private_data;
12796         (*count2)++;
12797         dbwrap_record_delete(rec);
12798         return 0;
12799 }
12800
12801 static bool run_local_rbtree(int dummy)
12802 {
12803         struct db_context *db;
12804         bool ret = false;
12805         int i;
12806         NTSTATUS status;
12807         int count = 0;
12808         int count2 = 0;
12809
12810         db = db_open_rbt(NULL);
12811
12812         if (db == NULL) {
12813                 d_fprintf(stderr, "db_open_rbt failed\n");
12814                 return false;
12815         }
12816
12817         for (i=0; i<1000; i++) {
12818                 char *key, *value;
12819
12820                 if (asprintf(&key, "key%ld", random()) == -1) {
12821                         goto done;
12822                 }
12823                 if (asprintf(&value, "value%ld", random()) == -1) {
12824                         SAFE_FREE(key);
12825                         goto done;
12826                 }
12827
12828                 if (!rbt_testval(db, key, value)) {
12829                         SAFE_FREE(key);
12830                         SAFE_FREE(value);
12831                         goto done;
12832                 }
12833
12834                 SAFE_FREE(value);
12835                 if (asprintf(&value, "value%ld", random()) == -1) {
12836                         SAFE_FREE(key);
12837                         goto done;
12838                 }
12839
12840                 if (!rbt_testval(db, key, value)) {
12841                         SAFE_FREE(key);
12842                         SAFE_FREE(value);
12843                         goto done;
12844                 }
12845
12846                 SAFE_FREE(key);
12847                 SAFE_FREE(value);
12848         }
12849
12850         ret = true;
12851         count = 0; count2 = 0;
12852         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
12853                                       &count2, &count);
12854         printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
12855         if ((count != count2) || (count != 1000)) {
12856                 ret = false;
12857         }
12858         count = 0; count2 = 0;
12859         status = dbwrap_traverse(db, local_rbtree_traverse_delete,
12860                                  &count2, &count);
12861         printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
12862         if ((count != count2) || (count != 1000)) {
12863                 ret = false;
12864         }
12865         count = 0; count2 = 0;
12866         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
12867                                       &count2, &count);
12868         printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
12869         if ((count != count2) || (count != 0)) {
12870                 ret = false;
12871         }
12872
12873  done:
12874         TALLOC_FREE(db);
12875         return ret;
12876 }
12877
12878
12879 /*
12880   local test for character set functions
12881
12882   This is a very simple test for the functionality in convert_string_error()
12883  */
12884 static bool run_local_convert_string(int dummy)
12885 {
12886         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
12887         const char *test_strings[2] = { "March", "M\303\244rz" };
12888         char dst[7];
12889         int i;
12890
12891         for (i=0; i<2; i++) {
12892                 const char *str = test_strings[i];
12893                 int len = strlen(str);
12894                 size_t converted_size;
12895                 bool ret;
12896
12897                 memset(dst, 'X', sizeof(dst));
12898
12899                 /* first try with real source length */
12900                 ret = convert_string_error(CH_UNIX, CH_UTF8,
12901                                            str, len,
12902                                            dst, sizeof(dst),
12903                                            &converted_size);
12904                 if (ret != true) {
12905                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
12906                         goto failed;
12907                 }
12908
12909                 if (converted_size != len) {
12910                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
12911                                   str, len, (int)converted_size);
12912                         goto failed;
12913                 }
12914
12915                 if (strncmp(str, dst, converted_size) != 0) {
12916                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
12917                         goto failed;
12918                 }
12919
12920                 if (strlen(str) != converted_size) {
12921                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
12922                                   (int)strlen(str), (int)converted_size);
12923                         goto failed;
12924                 }
12925
12926                 if (dst[converted_size] != 'X') {
12927                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
12928                         goto failed;
12929                 }
12930
12931                 /* now with srclen==-1, this causes the nul to be
12932                  * converted too */
12933                 ret = convert_string_error(CH_UNIX, CH_UTF8,
12934                                            str, -1,
12935                                            dst, sizeof(dst),
12936                                            &converted_size);
12937                 if (ret != true) {
12938                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
12939                         goto failed;
12940                 }
12941
12942                 if (converted_size != len+1) {
12943                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
12944                                   str, len, (int)converted_size);
12945                         goto failed;
12946                 }
12947
12948                 if (strncmp(str, dst, converted_size) != 0) {
12949                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
12950                         goto failed;
12951                 }
12952
12953                 if (len+1 != converted_size) {
12954                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
12955                                   len+1, (int)converted_size);
12956                         goto failed;
12957                 }
12958
12959                 if (dst[converted_size] != 'X') {
12960                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
12961                         goto failed;
12962                 }
12963
12964         }
12965
12966
12967         TALLOC_FREE(tmp_ctx);
12968         return true;
12969 failed:
12970         TALLOC_FREE(tmp_ctx);
12971         return false;
12972 }
12973
12974 static bool run_local_string_to_sid(int dummy) {
12975         struct dom_sid sid;
12976
12977         if (string_to_sid(&sid, "S--1-5-32-545")) {
12978                 printf("allowing S--1-5-32-545\n");
12979                 return false;
12980         }
12981         if (string_to_sid(&sid, "S-1-5-32-+545")) {
12982                 printf("allowing S-1-5-32-+545\n");
12983                 return false;
12984         }
12985         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")) {
12986                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
12987                 return false;
12988         }
12989         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
12990                 printf("allowing S-1-5-32-545-abc\n");
12991                 return false;
12992         }
12993         if (string_to_sid(&sid, "S-300-5-32-545")) {
12994                 printf("allowing S-300-5-32-545\n");
12995                 return false;
12996         }
12997         if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
12998                 printf("allowing S-1-0xfffffffffffffe-32-545\n");
12999                 return false;
13000         }
13001         if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13002                 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13003                 return false;
13004         }
13005         if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13006                 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13007                 return false;
13008         }
13009         if (!string_to_sid(&sid, "S-1-5-32-545")) {
13010                 printf("could not parse S-1-5-32-545\n");
13011                 return false;
13012         }
13013         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13014                 struct dom_sid_buf buf;
13015                 printf("mis-parsed S-1-5-32-545 as %s\n",
13016                        dom_sid_str_buf(&sid, &buf));
13017                 return false;
13018         }
13019         return true;
13020 }
13021
13022 static bool sid_to_string_test(const char *expected) {
13023         char *str;
13024         bool res = true;
13025         struct dom_sid sid;
13026
13027         if (!string_to_sid(&sid, expected)) {
13028                 printf("could not parse %s\n", expected);
13029                 return false;
13030         }
13031
13032         str = dom_sid_string(NULL, &sid);
13033         if (strcmp(str, expected)) {
13034                 printf("Comparison failed (%s != %s)\n", str, expected);
13035                 res = false;
13036         }
13037         TALLOC_FREE(str);
13038         return res;
13039 }
13040
13041 static bool run_local_sid_to_string(int dummy) {
13042         if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13043                 return false;
13044         if (!sid_to_string_test("S-1-545"))
13045                 return false;
13046         if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13047                 return false;
13048         return true;
13049 }
13050
13051 static bool run_local_binary_to_sid(int dummy) {
13052         ssize_t ret;
13053         struct dom_sid *sid = talloc(NULL, struct dom_sid);
13054         static const uint8_t good_binary_sid[] = {
13055                 0x1, /* revision number */
13056                 15, /* num auths */
13057                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13058                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13059                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13060                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13061                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13062                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13063                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13064                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13065                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13066                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13067                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13068                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13069                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13070                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13071                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13072                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13073         };
13074
13075         static const uint8_t long_binary_sid[] = {
13076                 0x1, /* revision number */
13077                 15, /* num auths */
13078                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13079                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13080                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13081                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13082                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13083                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13084                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13085                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13086                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13087                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13088                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13089                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13090                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13091                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13092                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13093                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13094                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13095                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13096                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13097         };
13098
13099         static const uint8_t long_binary_sid2[] = {
13100                 0x1, /* revision number */
13101                 32, /* num auths */
13102                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13103                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13104                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13105                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13106                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13107                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13108                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13109                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13110                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13111                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13112                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13113                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13114                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13115                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13116                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13117                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13118                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13119                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13120                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13121                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13122                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13123                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13124                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13125                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13126                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13127                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13128                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13129                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13130                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13131                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13132                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13133                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13134                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13135         };
13136
13137         ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13138         if (ret == -1) {
13139                 return false;
13140         }
13141         ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13142         if (ret != -1) {
13143                 return false;
13144         }
13145         ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13146         if (ret != -1) {
13147                 return false;
13148         }
13149         return true;
13150 }
13151
13152 /* Split a path name into filename and stream name components. Canonicalise
13153  * such that an implicit $DATA token is always explicit.
13154  *
13155  * The "specification" of this function can be found in the
13156  * run_local_stream_name() function in torture.c, I've tried those
13157  * combinations against a W2k3 server.
13158  */
13159
13160 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13161                                        char **pbase, char **pstream)
13162 {
13163         char *base = NULL;
13164         char *stream = NULL;
13165         char *sname; /* stream name */
13166         const char *stype; /* stream type */
13167
13168         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13169
13170         sname = strchr_m(fname, ':');
13171
13172         if (sname == NULL) {
13173                 if (pbase != NULL) {
13174                         base = talloc_strdup(mem_ctx, fname);
13175                         NT_STATUS_HAVE_NO_MEMORY(base);
13176                 }
13177                 goto done;
13178         }
13179
13180         if (pbase != NULL) {
13181                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13182                 NT_STATUS_HAVE_NO_MEMORY(base);
13183         }
13184
13185         sname += 1;
13186
13187         stype = strchr_m(sname, ':');
13188
13189         if (stype == NULL) {
13190                 sname = talloc_strdup(mem_ctx, sname);
13191                 stype = "$DATA";
13192         }
13193         else {
13194                 if (strcasecmp_m(stype, ":$DATA") != 0) {
13195                         /*
13196                          * If there is an explicit stream type, so far we only
13197                          * allow $DATA. Is there anything else allowed? -- vl
13198                          */
13199                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13200                         TALLOC_FREE(base);
13201                         return NT_STATUS_OBJECT_NAME_INVALID;
13202                 }
13203                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13204                 stype += 1;
13205         }
13206
13207         if (sname == NULL) {
13208                 TALLOC_FREE(base);
13209                 return NT_STATUS_NO_MEMORY;
13210         }
13211
13212         if (sname[0] == '\0') {
13213                 /*
13214                  * no stream name, so no stream
13215                  */
13216                 goto done;
13217         }
13218
13219         if (pstream != NULL) {
13220                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13221                 if (stream == NULL) {
13222                         TALLOC_FREE(sname);
13223                         TALLOC_FREE(base);
13224                         return NT_STATUS_NO_MEMORY;
13225                 }
13226                 /*
13227                  * upper-case the type field
13228                  */
13229                 (void)strupper_m(strchr_m(stream, ':')+1);
13230         }
13231
13232  done:
13233         if (pbase != NULL) {
13234                 *pbase = base;
13235         }
13236         if (pstream != NULL) {
13237                 *pstream = stream;
13238         }
13239         return NT_STATUS_OK;
13240 }
13241
13242 static bool test_stream_name(const char *fname, const char *expected_base,
13243                              const char *expected_stream,
13244                              NTSTATUS expected_status)
13245 {
13246         NTSTATUS status;
13247         char *base = NULL;
13248         char *stream = NULL;
13249
13250         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13251         if (!NT_STATUS_EQUAL(status, expected_status)) {
13252                 goto error;
13253         }
13254
13255         if (!NT_STATUS_IS_OK(status)) {
13256                 return true;
13257         }
13258
13259         if (base == NULL) goto error;
13260
13261         if (strcmp(expected_base, base) != 0) goto error;
13262
13263         if ((expected_stream != NULL) && (stream == NULL)) goto error;
13264         if ((expected_stream == NULL) && (stream != NULL)) goto error;
13265
13266         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
13267                 goto error;
13268
13269         TALLOC_FREE(base);
13270         TALLOC_FREE(stream);
13271         return true;
13272
13273  error:
13274         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
13275                   fname, expected_base ? expected_base : "<NULL>",
13276                   expected_stream ? expected_stream : "<NULL>",
13277                   nt_errstr(expected_status));
13278         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
13279                   base ? base : "<NULL>", stream ? stream : "<NULL>",
13280                   nt_errstr(status));
13281         TALLOC_FREE(base);
13282         TALLOC_FREE(stream);
13283         return false;
13284 }
13285
13286 static bool run_local_stream_name(int dummy)
13287 {
13288         bool ret = true;
13289
13290         ret &= test_stream_name(
13291                 "bla", "bla", NULL, NT_STATUS_OK);
13292         ret &= test_stream_name(
13293                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
13294         ret &= test_stream_name(
13295                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13296         ret &= test_stream_name(
13297                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
13298         ret &= test_stream_name(
13299                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13300         ret &= test_stream_name(
13301                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
13302         ret &= test_stream_name(
13303                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
13304         ret &= test_stream_name(
13305                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
13306
13307         return ret;
13308 }
13309
13310 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
13311 {
13312         if (a.length != b.length) {
13313                 printf("a.length=%d != b.length=%d\n",
13314                        (int)a.length, (int)b.length);
13315                 return false;
13316         }
13317         if (memcmp(a.data, b.data, a.length) != 0) {
13318                 printf("a.data and b.data differ\n");
13319                 return false;
13320         }
13321         return true;
13322 }
13323
13324 static bool run_local_memcache(int dummy)
13325 {
13326         struct memcache *cache;
13327         DATA_BLOB k1, k2, k3, k4, k5;
13328         DATA_BLOB d1, d3;
13329         DATA_BLOB v1, v3;
13330
13331         TALLOC_CTX *mem_ctx;
13332         char *ptr1 = NULL;
13333         char *ptr2 = NULL;
13334         char *ptr3 = NULL;
13335
13336         char *str1, *str2;
13337         size_t size1, size2;
13338         bool ret = false;
13339
13340         mem_ctx = talloc_init("foo");
13341         if (mem_ctx == NULL) {
13342                 return false;
13343         }
13344
13345         /* STAT_CACHE TESTS */
13346
13347         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13348
13349         if (cache == NULL) {
13350                 printf("memcache_init failed\n");
13351                 return false;
13352         }
13353
13354         d1 = data_blob_const("d1", 2);
13355         d3 = data_blob_const("d3", 2);
13356
13357         k1 = data_blob_const("d1", 2);
13358         k2 = data_blob_const("d2", 2);
13359         k3 = data_blob_const("d3", 2);
13360         k4 = data_blob_const("d4", 2);
13361         k5 = data_blob_const("d5", 2);
13362
13363         memcache_add(cache, STAT_CACHE, k1, d1);
13364
13365         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
13366                 printf("could not find k1\n");
13367                 return false;
13368         }
13369         if (!data_blob_equal(d1, v1)) {
13370                 return false;
13371         }
13372
13373         memcache_add(cache, STAT_CACHE, k1, d3);
13374
13375         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
13376                 printf("could not find replaced k1\n");
13377                 return false;
13378         }
13379         if (!data_blob_equal(d3, v3)) {
13380                 return false;
13381         }
13382
13383         TALLOC_FREE(cache);
13384
13385         /* GETWD_CACHE TESTS */
13386         str1 = talloc_strdup(mem_ctx, "string1");
13387         if (str1 == NULL) {
13388                 return false;
13389         }
13390         ptr2 = str1; /* Keep an alias for comparison. */
13391
13392         str2 = talloc_strdup(mem_ctx, "string2");
13393         if (str2 == NULL) {
13394                 return false;
13395         }
13396
13397         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13398         if (cache == NULL) {
13399                 printf("memcache_init failed\n");
13400                 return false;
13401         }
13402
13403         memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
13404         /* str1 == NULL now. */
13405         ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
13406         if (ptr1 == NULL) {
13407                 printf("could not find k2\n");
13408                 return false;
13409         }
13410         if (ptr1 != ptr2) {
13411                 printf("fetch of k2 got wrong string\n");
13412                 return false;
13413         }
13414
13415         /* Add a blob to ensure k2 gets purged. */
13416         d3 = data_blob_talloc_zero(mem_ctx, 180);
13417         memcache_add(cache, STAT_CACHE, k3, d3);
13418
13419         ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
13420         if (ptr2 != NULL) {
13421                 printf("Did find k2, should have been purged\n");
13422                 return false;
13423         }
13424
13425         /*
13426          * Test that talloc size also is accounted in memcache and
13427          * causes purge of other object.
13428          */
13429
13430         str1 = talloc_zero_size(mem_ctx, 100);
13431         str2 = talloc_zero_size(mem_ctx, 100);
13432
13433         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13434         memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
13435
13436         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
13437         if (ptr3 != NULL) {
13438                 printf("Did find k4, should have been purged\n");
13439                 return false;
13440         }
13441
13442         /*
13443          * Test that adding a duplicate non-talloced
13444          * key/value on top of a talloced key/value takes account
13445          * of the talloc_freed value size.
13446          */
13447         TALLOC_FREE(cache);
13448         TALLOC_FREE(mem_ctx);
13449
13450         mem_ctx = talloc_init("key_replace");
13451         if (mem_ctx == NULL) {
13452                 return false;
13453         }
13454
13455         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13456         if (cache == NULL) {
13457                 return false;
13458         }
13459
13460         /*
13461          * Add a 100 byte talloced string. This will
13462          * store a (4 or 8 byte) pointer and record the
13463          * total talloced size.
13464          */
13465         str1 = talloc_zero_size(mem_ctx, 100);
13466         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13467         /*
13468          * Now overwrite with a small talloced
13469          * value. This should fit in the existing size
13470          * and the total talloced size should be removed
13471          * from the cache size.
13472          */
13473         str1 = talloc_zero_size(mem_ctx, 2);
13474         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13475         /*
13476          * Now store a 20 byte string. If the
13477          * total talloced size wasn't accounted for
13478          * and removed in the overwrite, then this
13479          * will evict k4.
13480          */
13481         str2 = talloc_zero_size(mem_ctx, 20);
13482         memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
13483
13484         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
13485         if (ptr3 == NULL) {
13486                 printf("Did not find k4, should not have been purged\n");
13487                 return false;
13488         }
13489
13490         TALLOC_FREE(cache);
13491         TALLOC_FREE(mem_ctx);
13492
13493         mem_ctx = talloc_init("foo");
13494         if (mem_ctx == NULL) {
13495                 return false;
13496         }
13497
13498         cache = memcache_init(NULL, 0);
13499         if (cache == NULL) {
13500                 return false;
13501         }
13502
13503         str1 = talloc_strdup(mem_ctx, "string1");
13504         if (str1 == NULL) {
13505                 return false;
13506         }
13507         str2 = talloc_strdup(mem_ctx, "string2");
13508         if (str2 == NULL) {
13509                 return false;
13510         }
13511         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
13512                             data_blob_string_const("torture"), &str1);
13513         size1 = talloc_total_size(cache);
13514
13515         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
13516                             data_blob_string_const("torture"), &str2);
13517         size2 = talloc_total_size(cache);
13518
13519         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
13520
13521         if (size2 > size1) {
13522                 printf("memcache leaks memory!\n");
13523                 goto fail;
13524         }
13525
13526         ret = true;
13527  fail:
13528         TALLOC_FREE(cache);
13529         return ret;
13530 }
13531
13532 static void wbclient_done(struct tevent_req *req)
13533 {
13534         wbcErr wbc_err;
13535         struct winbindd_response *wb_resp;
13536         int *i = (int *)tevent_req_callback_data_void(req);
13537
13538         wbc_err = wb_trans_recv(req, req, &wb_resp);
13539         TALLOC_FREE(req);
13540         *i += 1;
13541         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
13542 }
13543
13544 static bool run_wbclient_multi_ping(int dummy)
13545 {
13546         struct tevent_context *ev;
13547         struct wb_context **wb_ctx;
13548         struct winbindd_request wb_req;
13549         bool result = false;
13550         int i, j;
13551
13552         BlockSignals(True, SIGPIPE);
13553
13554         ev = tevent_context_init(talloc_tos());
13555         if (ev == NULL) {
13556                 goto fail;
13557         }
13558
13559         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
13560         if (wb_ctx == NULL) {
13561                 goto fail;
13562         }
13563
13564         ZERO_STRUCT(wb_req);
13565         wb_req.cmd = WINBINDD_PING;
13566
13567         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
13568
13569         for (i=0; i<torture_nprocs; i++) {
13570                 wb_ctx[i] = wb_context_init(ev, NULL);
13571                 if (wb_ctx[i] == NULL) {
13572                         goto fail;
13573                 }
13574                 for (j=0; j<torture_numops; j++) {
13575                         struct tevent_req *req;
13576                         req = wb_trans_send(ev, ev, wb_ctx[i],
13577                                             (j % 2) == 0, &wb_req);
13578                         if (req == NULL) {
13579                                 goto fail;
13580                         }
13581                         tevent_req_set_callback(req, wbclient_done, &i);
13582                 }
13583         }
13584
13585         i = 0;
13586
13587         while (i < torture_nprocs * torture_numops) {
13588                 tevent_loop_once(ev);
13589         }
13590
13591         result = true;
13592  fail:
13593         TALLOC_FREE(ev);
13594         return result;
13595 }
13596
13597 static bool dbtrans_inc(struct db_context *db)
13598 {
13599         struct db_record *rec;
13600         uint32_t val;
13601         bool ret = false;
13602         NTSTATUS status;
13603         TDB_DATA value;
13604
13605         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
13606         if (rec == NULL) {
13607                 printf(__location__ "fetch_lock failed\n");
13608                 return false;
13609         }
13610
13611         value = dbwrap_record_get_value(rec);
13612
13613         if (value.dsize != sizeof(uint32_t)) {
13614                 printf(__location__ "value.dsize = %d\n",
13615                        (int)value.dsize);
13616                 goto fail;
13617         }
13618
13619         memcpy(&val, value.dptr, sizeof(val));
13620         val += 1;
13621
13622         status = dbwrap_record_store(
13623                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
13624         if (!NT_STATUS_IS_OK(status)) {
13625                 printf(__location__ "store failed: %s\n",
13626                        nt_errstr(status));
13627                 goto fail;
13628         }
13629
13630         ret = true;
13631 fail:
13632         TALLOC_FREE(rec);
13633         return ret;
13634 }
13635
13636 static bool run_local_dbtrans(int dummy)
13637 {
13638         struct db_context *db;
13639         struct db_record *rec;
13640         NTSTATUS status;
13641         uint32_t initial;
13642         int res;
13643         TDB_DATA value;
13644
13645         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
13646                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
13647                      DBWRAP_FLAG_NONE);
13648         if (db == NULL) {
13649                 printf("Could not open transtest.db\n");
13650                 return false;
13651         }
13652
13653         res = dbwrap_transaction_start(db);
13654         if (res != 0) {
13655                 printf(__location__ "transaction_start failed\n");
13656                 return false;
13657         }
13658
13659         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
13660         if (rec == NULL) {
13661                 printf(__location__ "fetch_lock failed\n");
13662                 return false;
13663         }
13664
13665         value = dbwrap_record_get_value(rec);
13666
13667         if (value.dptr == NULL) {
13668                 initial = 0;
13669                 status = dbwrap_record_store(
13670                         rec, make_tdb_data((uint8_t *)&initial,
13671                                            sizeof(initial)),
13672                         0);
13673                 if (!NT_STATUS_IS_OK(status)) {
13674                         printf(__location__ "store returned %s\n",
13675                                nt_errstr(status));
13676                         return false;
13677                 }
13678         }
13679
13680         TALLOC_FREE(rec);
13681
13682         res = dbwrap_transaction_commit(db);
13683         if (res != 0) {
13684                 printf(__location__ "transaction_commit failed\n");
13685                 return false;
13686         }
13687
13688         while (true) {
13689                 uint32_t val, val2;
13690                 int i;
13691
13692                 res = dbwrap_transaction_start(db);
13693                 if (res != 0) {
13694                         printf(__location__ "transaction_start failed\n");
13695                         break;
13696                 }
13697
13698                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
13699                 if (!NT_STATUS_IS_OK(status)) {
13700                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
13701                                nt_errstr(status));
13702                         break;
13703                 }
13704
13705                 for (i=0; i<10; i++) {
13706                         if (!dbtrans_inc(db)) {
13707                                 return false;
13708                         }
13709                 }
13710
13711                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
13712                 if (!NT_STATUS_IS_OK(status)) {
13713                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
13714                                nt_errstr(status));
13715                         break;
13716                 }
13717
13718                 if (val2 != val + 10) {
13719                         printf(__location__ "val=%d, val2=%d\n",
13720                                (int)val, (int)val2);
13721                         break;
13722                 }
13723
13724                 printf("val2=%d\r", val2);
13725
13726                 res = dbwrap_transaction_commit(db);
13727                 if (res != 0) {
13728                         printf(__location__ "transaction_commit failed\n");
13729                         break;
13730                 }
13731         }
13732
13733         TALLOC_FREE(db);
13734         return true;
13735 }
13736
13737 /*
13738  * Just a dummy test to be run under a debugger. There's no real way
13739  * to inspect the tevent_poll specific function from outside of
13740  * tevent_poll.c.
13741  */
13742
13743 static bool run_local_tevent_poll(int dummy)
13744 {
13745         struct tevent_context *ev;
13746         struct tevent_fd *fd1, *fd2;
13747         bool result = false;
13748
13749         ev = tevent_context_init_byname(NULL, "poll");
13750         if (ev == NULL) {
13751                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
13752                 goto fail;
13753         }
13754
13755         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
13756         if (fd1 == NULL) {
13757                 d_fprintf(stderr, "tevent_add_fd failed\n");
13758                 goto fail;
13759         }
13760         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
13761         if (fd2 == NULL) {
13762                 d_fprintf(stderr, "tevent_add_fd failed\n");
13763                 goto fail;
13764         }
13765         TALLOC_FREE(fd2);
13766
13767         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
13768         if (fd2 == NULL) {
13769                 d_fprintf(stderr, "tevent_add_fd failed\n");
13770                 goto fail;
13771         }
13772
13773         result = true;
13774 fail:
13775         TALLOC_FREE(ev);
13776         return result;
13777 }
13778
13779 static bool run_local_hex_encode_buf(int dummy)
13780 {
13781         char buf[17];
13782         uint8_t src[8];
13783         int i;
13784
13785         for (i=0; i<sizeof(src); i++) {
13786                 src[i] = i;
13787         }
13788         hex_encode_buf(buf, src, sizeof(src));
13789         if (strcmp(buf, "0001020304050607") != 0) {
13790                 return false;
13791         }
13792         hex_encode_buf(buf, NULL, 0);
13793         if (buf[0] != '\0') {
13794                 return false;
13795         }
13796         return true;
13797 }
13798
13799 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
13800         "0.0.0.0",
13801         "::0",
13802         "1.2.3.1",
13803         "0.0.0.0",
13804         "0.0.0.0",
13805         "1.2.3.2",
13806         "1.2.3.3",
13807         "1.2.3.4",
13808         "1.2.3.5",
13809         "::0",
13810         "1.2.3.6",
13811         "1.2.3.7",
13812         "::0",
13813         "::0",
13814         "::0",
13815         "1.2.3.8",
13816         "1.2.3.9",
13817         "1.2.3.10",
13818         "1.2.3.11",
13819         "1.2.3.12",
13820         "1.2.3.13",
13821         "1001:1111:1111:1000:0:1111:1111:1111",
13822         "1.2.3.1",
13823         "1.2.3.2",
13824         "1.2.3.3",
13825         "1.2.3.12",
13826         "::0",
13827         "::0"
13828 };
13829
13830 static const char *remove_duplicate_addrs2_test_strings_result[] = {
13831         "1.2.3.1",
13832         "1.2.3.2",
13833         "1.2.3.3",
13834         "1.2.3.4",
13835         "1.2.3.5",
13836         "1.2.3.6",
13837         "1.2.3.7",
13838         "1.2.3.8",
13839         "1.2.3.9",
13840         "1.2.3.10",
13841         "1.2.3.11",
13842         "1.2.3.12",
13843         "1.2.3.13",
13844         "1001:1111:1111:1000:0:1111:1111:1111"
13845 };
13846
13847 static bool run_local_remove_duplicate_addrs2(int dummy)
13848 {
13849         struct ip_service test_vector[28];
13850         int count, i;
13851
13852         /* Construct the sockaddr_storage test vector. */
13853         for (i = 0; i < 28; i++) {
13854                 struct addrinfo hints;
13855                 struct addrinfo *res = NULL;
13856                 int ret;
13857
13858                 memset(&hints, '\0', sizeof(hints));
13859                 hints.ai_flags = AI_NUMERICHOST;
13860                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
13861                                 NULL,
13862                                 &hints,
13863                                 &res);
13864                 if (ret) {
13865                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
13866                                 remove_duplicate_addrs2_test_strings_vector[i]);
13867                         return false;
13868                 }
13869                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
13870                 memcpy(&test_vector[i].ss,
13871                         res->ai_addr,
13872                         res->ai_addrlen);
13873                 freeaddrinfo(res);
13874         }
13875
13876         count = remove_duplicate_addrs2(test_vector, i);
13877
13878         if (count != 14) {
13879                 fprintf(stderr, "count wrong (%d) should be 14\n",
13880                         count);
13881                 return false;
13882         }
13883
13884         for (i = 0; i < count; i++) {
13885                 char addr[INET6_ADDRSTRLEN];
13886
13887                 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
13888
13889                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
13890                         fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
13891                                 i,
13892                                 addr,
13893                                 remove_duplicate_addrs2_test_strings_result[i]);
13894                         return false;
13895                 }
13896         }
13897
13898         printf("run_local_remove_duplicate_addrs2: success\n");
13899         return true;
13900 }
13901
13902 static bool run_local_tdb_opener(int dummy)
13903 {
13904         TDB_CONTEXT *t;
13905         unsigned v = 0;
13906
13907         while (1) {
13908                 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
13909                              O_RDWR|O_CREAT, 0755);
13910                 if (t == NULL) {
13911                         perror("tdb_open failed");
13912                         return false;
13913                 }
13914                 tdb_close(t);
13915
13916                 v += 1;
13917                 printf("\r%u", v);
13918         }
13919         return true;
13920 }
13921
13922 static bool run_local_tdb_writer(int dummy)
13923 {
13924         TDB_CONTEXT *t;
13925         unsigned v = 0;
13926         TDB_DATA val;
13927
13928         t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
13929         if (t == 0) {
13930                 perror("tdb_open failed");
13931                 return 1;
13932         }
13933
13934         val.dptr = (uint8_t *)&v;
13935         val.dsize = sizeof(v);
13936
13937         while (1) {
13938                 TDB_DATA data;
13939                 int ret;
13940
13941                 ret = tdb_store(t, val, val, 0);
13942                 if (ret != 0) {
13943                         printf("%s\n", tdb_errorstr(t));
13944                 }
13945                 v += 1;
13946                 printf("\r%u", v);
13947
13948                 data = tdb_fetch(t, val);
13949                 if (data.dptr != NULL) {
13950                         SAFE_FREE(data.dptr);
13951                 }
13952         }
13953         return true;
13954 }
13955
13956 static bool run_local_canonicalize_path(int dummy)
13957 {
13958         const char *src[] = {
13959                         "/foo/..",
13960                         "/..",
13961                         "/foo/bar/../baz",
13962                         "/foo/././",
13963                         "/../foo",
13964                         ".././././",
13965                         ".././././../../../boo",
13966                         "./..",
13967                         NULL
13968                         };
13969         const char *dst[] = {
13970                         "/",
13971                         "/",
13972                         "/foo/baz",
13973                         "/foo",
13974                         "/foo",
13975                         "/",
13976                         "/boo",
13977                         "/",
13978                         NULL
13979                         };
13980         unsigned int i;
13981
13982         for (i = 0; src[i] != NULL; i++) {
13983                 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
13984                 if (d == NULL) {
13985                         perror("talloc fail\n");
13986                         return false;
13987                 }
13988                 if (strcmp(d, dst[i]) != 0) {
13989                         d_fprintf(stderr,
13990                                 "canonicalize mismatch %s -> %s != %s",
13991                                 src[i], d, dst[i]);
13992                         return false;
13993                 }
13994                 talloc_free(d);
13995         }
13996         return true;
13997 }
13998
13999 static bool run_ign_bad_negprot(int dummy)
14000 {
14001         struct tevent_context *ev;
14002         struct tevent_req *req;
14003         struct smbXcli_conn *conn;
14004         struct sockaddr_storage ss;
14005         NTSTATUS status;
14006         int fd;
14007         bool ok;
14008
14009         printf("starting ignore bad negprot\n");
14010
14011         ok = resolve_name(host, &ss, 0x20, true);
14012         if (!ok) {
14013                 d_fprintf(stderr, "Could not resolve name %s\n", host);
14014                 return false;
14015         }
14016
14017         status = open_socket_out(&ss, 445, 10000, &fd);
14018         if (!NT_STATUS_IS_OK(status)) {
14019                 d_fprintf(stderr, "open_socket_out failed: %s\n",
14020                           nt_errstr(status));
14021                 return false;
14022         }
14023
14024         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14025                                    NULL, 0);
14026         if (conn == NULL) {
14027                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14028                 return false;
14029         }
14030
14031         status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
14032         if (NT_STATUS_IS_OK(status)) {
14033                 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
14034                 return false;
14035         }
14036
14037         ev = samba_tevent_context_init(talloc_tos());
14038         if (ev == NULL) {
14039                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14040                 return false;
14041         }
14042
14043         req = smb1cli_session_setup_nt1_send(
14044                 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
14045                 data_blob_null, data_blob_null, 0x40,
14046                 "Windows 2000 2195", "Windows 2000 5.0");
14047         if (req == NULL) {
14048                 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
14049                 return false;
14050         }
14051
14052         ok = tevent_req_poll_ntstatus(req, ev, &status);
14053         if (!ok) {
14054                 d_fprintf(stderr, "tevent_req_poll failed\n");
14055                 return false;
14056         }
14057
14058         status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
14059                                                 NULL, NULL);
14060         if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
14061                 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
14062                           "%s, expected NT_STATUS_CONNECTION_RESET\n",
14063                           nt_errstr(status));
14064                 return false;
14065         }
14066
14067         TALLOC_FREE(conn);
14068
14069         printf("starting ignore bad negprot\n");
14070
14071         return true;
14072 }
14073
14074 static double create_procs(bool (*fn)(int), bool *result)
14075 {
14076         int i, status;
14077         volatile pid_t *child_status;
14078         volatile bool *child_status_out;
14079         int synccount;
14080         int tries = 8;
14081         struct timeval start;
14082
14083         synccount = 0;
14084
14085         child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
14086         if (!child_status) {
14087                 printf("Failed to setup shared memory\n");
14088                 return -1;
14089         }
14090
14091         child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
14092         if (!child_status_out) {
14093                 printf("Failed to setup result status shared memory\n");
14094                 return -1;
14095         }
14096
14097         for (i = 0; i < torture_nprocs; i++) {
14098                 child_status[i] = 0;
14099                 child_status_out[i] = True;
14100         }
14101
14102         start = timeval_current();
14103
14104         for (i=0;i<torture_nprocs;i++) {
14105                 procnum = i;
14106                 if (fork() == 0) {
14107                         pid_t mypid = getpid();
14108                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
14109
14110                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
14111
14112                         while (1) {
14113                                 if (torture_open_connection(&current_cli, i)) break;
14114                                 if (tries-- == 0) {
14115                                         printf("pid %d failed to start\n", (int)getpid());
14116                                         _exit(1);
14117                                 }
14118                                 smb_msleep(10); 
14119                         }
14120
14121                         child_status[i] = getpid();
14122
14123                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
14124
14125                         child_status_out[i] = fn(i);
14126                         _exit(0);
14127                 }
14128         }
14129
14130         do {
14131                 synccount = 0;
14132                 for (i=0;i<torture_nprocs;i++) {
14133                         if (child_status[i]) synccount++;
14134                 }
14135                 if (synccount == torture_nprocs) break;
14136                 smb_msleep(10);
14137         } while (timeval_elapsed(&start) < 30);
14138
14139         if (synccount != torture_nprocs) {
14140                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
14141                 *result = False;
14142                 return timeval_elapsed(&start);
14143         }
14144
14145         /* start the client load */
14146         start = timeval_current();
14147
14148         for (i=0;i<torture_nprocs;i++) {
14149                 child_status[i] = 0;
14150         }
14151
14152         printf("%d clients started\n", torture_nprocs);
14153
14154         for (i=0;i<torture_nprocs;i++) {
14155                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
14156         }
14157
14158         printf("\n");
14159
14160         for (i=0;i<torture_nprocs;i++) {
14161                 if (!child_status_out[i]) {
14162                         *result = False;
14163                 }
14164         }
14165         return timeval_elapsed(&start);
14166 }
14167
14168 #define FLAG_MULTIPROC 1
14169
14170 static struct {
14171         const char *name;
14172         bool (*fn)(int);
14173         unsigned flags;
14174 } torture_ops[] = {
14175         {
14176                 .name = "FDPASS",
14177                 .fn   = run_fdpasstest,
14178         },
14179         {
14180                 .name = "LOCK1",
14181                 .fn   = run_locktest1,
14182         },
14183         {
14184                 .name = "LOCK2",
14185                 .fn   =  run_locktest2,
14186         },
14187         {
14188                 .name = "LOCK3",
14189                 .fn   =  run_locktest3,
14190         },
14191         {
14192                 .name = "LOCK4",
14193                 .fn   =  run_locktest4,
14194         },
14195         {
14196                 .name = "LOCK5",
14197                 .fn   =  run_locktest5,
14198         },
14199         {
14200                 .name = "LOCK6",
14201                 .fn   =  run_locktest6,
14202         },
14203         {
14204                 .name = "LOCK7",
14205                 .fn   =  run_locktest7,
14206         },
14207         {
14208                 .name = "LOCK8",
14209                 .fn   =  run_locktest8,
14210         },
14211         {
14212                 .name = "LOCK9A",
14213                 .fn   =  run_locktest9a,
14214         },
14215         {
14216                 .name = "LOCK9B",
14217                 .fn   =  run_locktest9b,
14218         },
14219         {
14220                 .name = "LOCK10",
14221                 .fn   =  run_locktest10,
14222         },
14223         {
14224                 .name = "LOCK11",
14225                 .fn   =  run_locktest11,
14226         },
14227         {
14228                 .name = "LOCK12",
14229                 .fn   =  run_locktest12,
14230         },
14231         {
14232                 .name = "LOCK13",
14233                 .fn   =  run_locktest13,
14234         },
14235         {
14236                 .name = "UNLINK",
14237                 .fn   = run_unlinktest,
14238         },
14239         {
14240                 .name = "BROWSE",
14241                 .fn   = run_browsetest,
14242         },
14243         {
14244                 .name = "ATTR",
14245                 .fn   =   run_attrtest,
14246         },
14247         {
14248                 .name = "TRANS2",
14249                 .fn   = run_trans2test,
14250         },
14251         {
14252                 .name  = "MAXFID",
14253                 .fn    = run_maxfidtest,
14254                 .flags = FLAG_MULTIPROC,
14255         },
14256         {
14257                 .name  = "TORTURE",
14258                 .fn    = run_torture,
14259                 .flags = FLAG_MULTIPROC,
14260         },
14261         {
14262                 .name  = "RANDOMIPC",
14263                 .fn    = run_randomipc,
14264         },
14265         {
14266                 .name  = "NEGNOWAIT",
14267                 .fn    = run_negprot_nowait,
14268         },
14269         {
14270                 .name  = "NBENCH",
14271                 .fn    =  run_nbench,
14272         },
14273         {
14274                 .name  = "NBENCH2",
14275                 .fn    = run_nbench2,
14276         },
14277         {
14278                 .name  = "OPLOCK1",
14279                 .fn    =  run_oplock1,
14280         },
14281         {
14282                 .name  = "OPLOCK2",
14283                 .fn    =  run_oplock2,
14284         },
14285         {
14286                 .name  = "OPLOCK4",
14287                 .fn    =  run_oplock4,
14288         },
14289 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
14290         {
14291                 .name  = "OPLOCK5",
14292                 .fn    =  run_oplock5,
14293         },
14294 #endif
14295         {
14296                 .name  = "DIR",
14297                 .fn    =  run_dirtest,
14298         },
14299         {
14300                 .name  = "DIR1",
14301                 .fn    =  run_dirtest1,
14302         },
14303         {
14304                 .name  = "DIR-CREATETIME",
14305                 .fn    =  run_dir_createtime,
14306         },
14307         {
14308                 .name  = "DENY1",
14309                 .fn    =  torture_denytest1,
14310         },
14311         {
14312                 .name  = "DENY2",
14313                 .fn    =  torture_denytest2,
14314         },
14315         {
14316                 .name  = "TCON",
14317                 .fn    =  run_tcon_test,
14318         },
14319         {
14320                 .name  = "TCONDEV",
14321                 .fn    =  run_tcon_devtype_test,
14322         },
14323         {
14324                 .name  = "RW1",
14325                 .fn    =  run_readwritetest,
14326         },
14327         {
14328                 .name  = "RW2",
14329                 .fn    =  run_readwritemulti,
14330                 .flags = FLAG_MULTIPROC
14331         },
14332         {
14333                 .name  = "RW3",
14334                 .fn    =  run_readwritelarge,
14335         },
14336         {
14337                 .name  = "RW-SIGNING",
14338                 .fn    =  run_readwritelarge_signtest,
14339         },
14340         {
14341                 .name  = "OPEN",
14342                 .fn    = run_opentest,
14343         },
14344         {
14345                 .name  = "POSIX",
14346                 .fn    = run_simple_posix_open_test,
14347         },
14348         {
14349                 .name  = "POSIX-APPEND",
14350                 .fn    = run_posix_append,
14351         },
14352         {
14353                 .name  = "POSIX-SYMLINK-ACL",
14354                 .fn    = run_acl_symlink_test,
14355         },
14356         {
14357                 .name  = "POSIX-SYMLINK-EA",
14358                 .fn    = run_ea_symlink_test,
14359         },
14360         {
14361                 .name  = "POSIX-STREAM-DELETE",
14362                 .fn    = run_posix_stream_delete,
14363         },
14364         {
14365                 .name  = "POSIX-OFD-LOCK",
14366                 .fn    = run_posix_ofd_lock_test,
14367         },
14368         {
14369                 .name  = "POSIX-BLOCKING-LOCK",
14370                 .fn    = run_posix_blocking_lock,
14371         },
14372         {
14373                 .name  = "POSIX-MKDIR",
14374                 .fn    = run_posix_mkdir_test,
14375         },
14376         {
14377                 .name  = "POSIX-ACL-OPLOCK",
14378                 .fn    = run_posix_acl_oplock_test,
14379         },
14380         {
14381                 .name  = "POSIX-ACL-SHAREROOT",
14382                 .fn    = run_posix_acl_shareroot_test,
14383         },
14384         {
14385                 .name  = "WINDOWS-BAD-SYMLINK",
14386                 .fn    = run_symlink_open_test,
14387         },
14388         {
14389                 .name  = "CASE-INSENSITIVE-CREATE",
14390                 .fn    = run_case_insensitive_create,
14391         },
14392         {
14393                 .name  = "ASYNC-ECHO",
14394                 .fn    = run_async_echo,
14395         },
14396         {
14397                 .name  = "UID-REGRESSION-TEST",
14398                 .fn    = run_uid_regression_test,
14399         },
14400         {
14401                 .name  = "SHORTNAME-TEST",
14402                 .fn    = run_shortname_test,
14403         },
14404         {
14405                 .name  = "ADDRCHANGE",
14406                 .fn    = run_addrchange,
14407         },
14408 #if 1
14409         {
14410                 .name  = "OPENATTR",
14411                 .fn    = run_openattrtest,
14412         },
14413 #endif
14414         {
14415                 .name  = "XCOPY",
14416                 .fn    = run_xcopy,
14417         },
14418         {
14419                 .name  = "RENAME",
14420                 .fn    = run_rename,
14421         },
14422         {
14423                 .name  = "RENAME-ACCESS",
14424                 .fn    = run_rename_access,
14425         },
14426         {
14427                 .name  = "OWNER-RIGHTS",
14428                 .fn    = run_owner_rights,
14429         },
14430         {
14431                 .name  = "DELETE",
14432                 .fn    = run_deletetest,
14433         },
14434         {
14435                 .name  = "DELETE-STREAM",
14436                 .fn    = run_delete_stream,
14437         },
14438         {
14439                 .name  = "DELETE-PRINT",
14440                 .fn    = run_delete_print_test,
14441         },
14442         {
14443                 .name  = "WILDDELETE",
14444                 .fn    = run_wild_deletetest,
14445         },
14446         {
14447                 .name  = "DELETE-LN",
14448                 .fn    = run_deletetest_ln,
14449         },
14450         {
14451                 .name  = "PROPERTIES",
14452                 .fn    = run_properties,
14453         },
14454         {
14455                 .name  = "MANGLE",
14456                 .fn    = torture_mangle,
14457         },
14458         {
14459                 .name  = "MANGLE1",
14460                 .fn    = run_mangle1,
14461         },
14462         {
14463                 .name  = "MANGLE-ILLEGAL",
14464                 .fn    = run_mangle_illegal,
14465         },
14466         {
14467                 .name  = "W2K",
14468                 .fn    = run_w2ktest,
14469         },
14470         {
14471                 .name  = "TRANS2SCAN",
14472                 .fn    = torture_trans2_scan,
14473         },
14474         {
14475                 .name  = "NTTRANSSCAN",
14476                 .fn    = torture_nttrans_scan,
14477         },
14478         {
14479                 .name  = "UTABLE",
14480                 .fn    = torture_utable,
14481         },
14482         {
14483                 .name  = "CASETABLE",
14484                 .fn    = torture_casetable,
14485         },
14486         {
14487                 .name  = "ERRMAPEXTRACT",
14488                 .fn    = run_error_map_extract,
14489         },
14490         {
14491                 .name  = "PIPE_NUMBER",
14492                 .fn    = run_pipe_number,
14493         },
14494         {
14495                 .name  = "TCON2",
14496                 .fn    =  run_tcon2_test,
14497         },
14498         {
14499                 .name  = "IOCTL",
14500                 .fn    =  torture_ioctl_test,
14501         },
14502         {
14503                 .name  = "CHKPATH",
14504                 .fn    =  torture_chkpath_test,
14505         },
14506         {
14507                 .name  = "FDSESS",
14508                 .fn    = run_fdsesstest,
14509         },
14510         {
14511                 .name  = "EATEST",
14512                 .fn    = run_eatest,
14513         },
14514         {
14515                 .name  = "SESSSETUP_BENCH",
14516                 .fn    = run_sesssetup_bench,
14517         },
14518         {
14519                 .name  = "CHAIN1",
14520                 .fn    = run_chain1,
14521         },
14522         {
14523                 .name  = "CHAIN2",
14524                 .fn    = run_chain2,
14525         },
14526         {
14527                 .name  = "CHAIN3",
14528                 .fn    = run_chain3,
14529         },
14530         {
14531                 .name  = "WINDOWS-WRITE",
14532                 .fn    = run_windows_write,
14533         },
14534         {
14535                 .name  = "LARGE_READX",
14536                 .fn    = run_large_readx,
14537         },
14538         {
14539                 .name  = "NTTRANS-CREATE",
14540                 .fn    = run_nttrans_create,
14541         },
14542         {
14543                 .name  = "NTTRANS-FSCTL",
14544                 .fn    = run_nttrans_fsctl,
14545         },
14546         {
14547                 .name  = "CLI_ECHO",
14548                 .fn    = run_cli_echo,
14549         },
14550         {
14551                 .name  = "CLI_SPLICE",
14552                 .fn    = run_cli_splice,
14553         },
14554         {
14555                 .name  = "TLDAP",
14556                 .fn    = run_tldap,
14557         },
14558         {
14559                 .name  = "STREAMERROR",
14560                 .fn    = run_streamerror,
14561         },
14562         {
14563                 .name  = "NOTIFY-BENCH",
14564                 .fn    = run_notify_bench,
14565         },
14566         {
14567                 .name  = "NOTIFY-BENCH2",
14568                 .fn    = run_notify_bench2,
14569         },
14570         {
14571                 .name  = "NOTIFY-BENCH3",
14572                 .fn    = run_notify_bench3,
14573         },
14574         {
14575                 .name  = "BAD-NBT-SESSION",
14576                 .fn    = run_bad_nbt_session,
14577         },
14578         {
14579                 .name  = "IGN-BAD-NEGPROT",
14580                 .fn    = run_ign_bad_negprot,
14581         },
14582         {
14583                 .name  = "SMB-ANY-CONNECT",
14584                 .fn    = run_smb_any_connect,
14585         },
14586         {
14587                 .name  = "NOTIFY-ONLINE",
14588                 .fn    = run_notify_online,
14589         },
14590         {
14591                 .name  = "SMB2-BASIC",
14592                 .fn    = run_smb2_basic,
14593         },
14594         {
14595                 .name  = "SMB2-NEGPROT",
14596                 .fn    = run_smb2_negprot,
14597         },
14598         {
14599                 .name  = "SMB2-ANONYMOUS",
14600                 .fn    = run_smb2_anonymous,
14601         },
14602         {
14603                 .name  = "SMB2-SESSION-RECONNECT",
14604                 .fn    = run_smb2_session_reconnect,
14605         },
14606         {
14607                 .name  = "SMB2-TCON-DEPENDENCE",
14608                 .fn    = run_smb2_tcon_dependence,
14609         },
14610         {
14611                 .name  = "SMB2-MULTI-CHANNEL",
14612                 .fn    = run_smb2_multi_channel,
14613         },
14614         {
14615                 .name  = "SMB2-SESSION-REAUTH",
14616                 .fn    = run_smb2_session_reauth,
14617         },
14618         {
14619                 .name  = "SMB2-FTRUNCATE",
14620                 .fn    = run_smb2_ftruncate,
14621         },
14622         {
14623                 .name  = "SMB2-DIR-FSYNC",
14624                 .fn    = run_smb2_dir_fsync,
14625         },
14626         {
14627                 .name  = "SMB2-PATH-SLASH",
14628                 .fn    = run_smb2_path_slash,
14629         },
14630         {
14631                 .name  = "CLEANUP1",
14632                 .fn    = run_cleanup1,
14633         },
14634         {
14635                 .name  = "CLEANUP2",
14636                 .fn    = run_cleanup2,
14637         },
14638         {
14639                 .name  = "CLEANUP4",
14640                 .fn    = run_cleanup4,
14641         },
14642         {
14643                 .name  = "OPLOCK-CANCEL",
14644                 .fn    = run_oplock_cancel,
14645         },
14646         {
14647                 .name  = "PIDHIGH",
14648                 .fn    = run_pidhigh,
14649         },
14650         {
14651                 .name  = "LOCAL-SUBSTITUTE",
14652                 .fn    = run_local_substitute,
14653         },
14654         {
14655                 .name  = "LOCAL-GENCACHE",
14656                 .fn    = run_local_gencache,
14657         },
14658         {
14659                 .name  = "LOCAL-DBWRAP-WATCH1",
14660                 .fn    = run_dbwrap_watch1,
14661         },
14662         {
14663                 .name  = "LOCAL-DBWRAP-WATCH2",
14664                 .fn    = run_dbwrap_watch2,
14665         },
14666         {
14667                 .name  = "LOCAL-DBWRAP-DO-LOCKED1",
14668                 .fn    = run_dbwrap_do_locked1,
14669         },
14670         {
14671                 .name  = "LOCAL-MESSAGING-READ1",
14672                 .fn    = run_messaging_read1,
14673         },
14674         {
14675                 .name  = "LOCAL-MESSAGING-READ2",
14676                 .fn    = run_messaging_read2,
14677         },
14678         {
14679                 .name  = "LOCAL-MESSAGING-READ3",
14680                 .fn    = run_messaging_read3,
14681         },
14682         {
14683                 .name  = "LOCAL-MESSAGING-READ4",
14684                 .fn    = run_messaging_read4,
14685         },
14686         {
14687                 .name  = "LOCAL-MESSAGING-FDPASS1",
14688                 .fn    = run_messaging_fdpass1,
14689         },
14690         {
14691                 .name  = "LOCAL-MESSAGING-FDPASS2",
14692                 .fn    = run_messaging_fdpass2,
14693         },
14694         {
14695                 .name  = "LOCAL-MESSAGING-FDPASS2a",
14696                 .fn    = run_messaging_fdpass2a,
14697         },
14698         {
14699                 .name  = "LOCAL-MESSAGING-FDPASS2b",
14700                 .fn    = run_messaging_fdpass2b,
14701         },
14702         {
14703                 .name  = "LOCAL-MESSAGING-SEND-ALL",
14704                 .fn    = run_messaging_send_all,
14705         },
14706         {
14707                 .name  = "LOCAL-BASE64",
14708                 .fn    = run_local_base64,
14709         },
14710         {
14711                 .name  = "LOCAL-RBTREE",
14712                 .fn    = run_local_rbtree,
14713         },
14714         {
14715                 .name  = "LOCAL-MEMCACHE",
14716                 .fn    = run_local_memcache,
14717         },
14718         {
14719                 .name  = "LOCAL-STREAM-NAME",
14720                 .fn    = run_local_stream_name,
14721         },
14722         {
14723                 .name  = "WBCLIENT-MULTI-PING",
14724                 .fn    = run_wbclient_multi_ping,
14725         },
14726         {
14727                 .name  = "LOCAL-string_to_sid",
14728                 .fn    = run_local_string_to_sid,
14729         },
14730         {
14731                 .name  = "LOCAL-sid_to_string",
14732                 .fn    = run_local_sid_to_string,
14733         },
14734         {
14735                 .name  = "LOCAL-binary_to_sid",
14736                 .fn    = run_local_binary_to_sid,
14737         },
14738         {
14739                 .name  = "LOCAL-DBTRANS",
14740                 .fn    = run_local_dbtrans,
14741         },
14742         {
14743                 .name  = "LOCAL-TEVENT-POLL",
14744                 .fn    = run_local_tevent_poll,
14745         },
14746         {
14747                 .name  = "LOCAL-CONVERT-STRING",
14748                 .fn    = run_local_convert_string,
14749         },
14750         {
14751                 .name  = "LOCAL-CONV-AUTH-INFO",
14752                 .fn    = run_local_conv_auth_info,
14753         },
14754         {
14755                 .name  = "LOCAL-hex_encode_buf",
14756                 .fn    = run_local_hex_encode_buf,
14757         },
14758         {
14759                 .name  = "LOCAL-IDMAP-TDB-COMMON",
14760                 .fn    = run_idmap_tdb_common_test,
14761         },
14762         {
14763                 .name  = "LOCAL-remove_duplicate_addrs2",
14764                 .fn    = run_local_remove_duplicate_addrs2,
14765         },
14766         {
14767                 .name  = "local-tdb-opener",
14768                 .fn    = run_local_tdb_opener,
14769         },
14770         {
14771                 .name  = "local-tdb-writer",
14772                 .fn    = run_local_tdb_writer,
14773         },
14774         {
14775                 .name  = "LOCAL-DBWRAP-CTDB",
14776                 .fn    = run_local_dbwrap_ctdb,
14777         },
14778         {
14779                 .name  = "LOCAL-BENCH-PTHREADPOOL",
14780                 .fn    = run_bench_pthreadpool,
14781         },
14782         {
14783                 .name  = "LOCAL-PTHREADPOOL-TEVENT",
14784                 .fn    = run_pthreadpool_tevent,
14785         },
14786         {
14787                 .name  = "LOCAL-G-LOCK1",
14788                 .fn    = run_g_lock1,
14789         },
14790         {
14791                 .name  = "LOCAL-G-LOCK2",
14792                 .fn    = run_g_lock2,
14793         },
14794         {
14795                 .name  = "LOCAL-G-LOCK3",
14796                 .fn    = run_g_lock3,
14797         },
14798         {
14799                 .name  = "LOCAL-G-LOCK4",
14800                 .fn    = run_g_lock4,
14801         },
14802         {
14803                 .name  = "LOCAL-G-LOCK5",
14804                 .fn    = run_g_lock5,
14805         },
14806         {
14807                 .name  = "LOCAL-G-LOCK6",
14808                 .fn    = run_g_lock6,
14809         },
14810         {
14811                 .name  = "LOCAL-G-LOCK-PING-PONG",
14812                 .fn    = run_g_lock_ping_pong,
14813         },
14814         {
14815                 .name  = "LOCAL-CANONICALIZE-PATH",
14816                 .fn    = run_local_canonicalize_path,
14817         },
14818         {
14819                 .name  = "LOCAL-NAMEMAP-CACHE1",
14820                 .fn    = run_local_namemap_cache1,
14821         },
14822         {
14823                 .name  = "LOCAL-IDMAP-CACHE1",
14824                 .fn    = run_local_idmap_cache1,
14825         },
14826         {
14827                 .name  = "qpathinfo-bufsize",
14828                 .fn    = run_qpathinfo_bufsize,
14829         },
14830         {
14831                 .name  = "hide-new-files-timeout",
14832                 .fn    = run_hidenewfiles,
14833         },
14834         {
14835                 .name = NULL,
14836         },
14837 };
14838
14839 /****************************************************************************
14840 run a specified test or "ALL"
14841 ****************************************************************************/
14842 static bool run_test(const char *name)
14843 {
14844         bool ret = True;
14845         bool result = True;
14846         bool found = False;
14847         int i;
14848         double t;
14849         if (strequal(name,"ALL")) {
14850                 for (i=0;torture_ops[i].name;i++) {
14851                         run_test(torture_ops[i].name);
14852                 }
14853                 found = True;
14854         }
14855
14856         for (i=0;torture_ops[i].name;i++) {
14857                 fstr_sprintf(randomfname, "\\XX%x", 
14858                          (unsigned)random());
14859
14860                 if (strequal(name, torture_ops[i].name)) {
14861                         found = True;
14862                         printf("Running %s\n", name);
14863                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
14864                                 t = create_procs(torture_ops[i].fn, &result);
14865                                 if (!result) { 
14866                                         ret = False;
14867                                         printf("TEST %s FAILED!\n", name);
14868                                 }
14869                         } else {
14870                                 struct timeval start;
14871                                 start = timeval_current();
14872                                 if (!torture_ops[i].fn(0)) {
14873                                         ret = False;
14874                                         printf("TEST %s FAILED!\n", name);
14875                                 }
14876                                 t = timeval_elapsed(&start);
14877                         }
14878                         printf("%s took %g secs\n\n", name, t);
14879                 }
14880         }
14881
14882         if (!found) {
14883                 printf("Did not find a test named %s\n", name);
14884                 ret = False;
14885         }
14886
14887         return ret;
14888 }
14889
14890
14891 static void usage(void)
14892 {
14893         int i;
14894
14895         printf("WARNING samba4 test suite is much more complete nowadays.\n");
14896         printf("Please use samba4 torture.\n\n");
14897
14898         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
14899
14900         printf("\t-d debuglevel\n");
14901         printf("\t-U user%%pass\n");
14902         printf("\t-k                    use kerberos\n");
14903         printf("\t-N numprocs\n");
14904         printf("\t-n my_netbios_name\n");
14905         printf("\t-W workgroup\n");
14906         printf("\t-o num_operations\n");
14907         printf("\t-O socket_options\n");
14908         printf("\t-m maximum protocol\n");
14909         printf("\t-L use oplocks\n");
14910         printf("\t-c CLIENT.TXT         specify client load file for NBENCH\n");
14911         printf("\t-A showall\n");
14912         printf("\t-p port\n");
14913         printf("\t-s seed\n");
14914         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
14915         printf("\t-f filename           filename to test\n");
14916         printf("\t-e                    encrypt\n");
14917         printf("\n\n");
14918
14919         printf("tests are:");
14920         for (i=0;torture_ops[i].name;i++) {
14921                 printf(" %s", torture_ops[i].name);
14922         }
14923         printf("\n");
14924
14925         printf("default test is ALL\n");
14926
14927         exit(1);
14928 }
14929
14930 /****************************************************************************
14931   main program
14932 ****************************************************************************/
14933  int main(int argc,char *argv[])
14934 {
14935         int opt, i;
14936         char *p;
14937         int gotuser = 0;
14938         int gotpass = 0;
14939         bool correct = True;
14940         TALLOC_CTX *frame = talloc_stackframe();
14941         int seed = time(NULL);
14942
14943 #ifdef HAVE_SETBUFFER
14944         setbuffer(stdout, NULL, 0);
14945 #endif
14946
14947         setup_logging("smbtorture", DEBUG_STDOUT);
14948
14949         smb_init_locale();
14950         fault_setup();
14951
14952         if (is_default_dyn_CONFIGFILE()) {
14953                 if(getenv("SMB_CONF_PATH")) {
14954                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
14955                 }
14956         }
14957         lp_load_global(get_dyn_CONFIGFILE());
14958         load_interfaces();
14959
14960         if (argc < 2) {
14961                 usage();
14962         }
14963
14964         for(p = argv[1]; *p; p++)
14965           if(*p == '\\')
14966             *p = '/';
14967
14968         if (strncmp(argv[1], "//", 2)) {
14969                 usage();
14970         }
14971
14972         fstrcpy(host, &argv[1][2]);
14973         p = strchr_m(&host[2],'/');
14974         if (!p) {
14975                 usage();
14976         }
14977         *p = 0;
14978         fstrcpy(share, p+1);
14979
14980         fstrcpy(myname, get_myname(talloc_tos()));
14981         if (!*myname) {
14982                 fprintf(stderr, "Failed to get my hostname.\n");
14983                 return 1;
14984         }
14985
14986         if (*username == 0 && getenv("LOGNAME")) {
14987           fstrcpy(username,getenv("LOGNAME"));
14988         }
14989
14990         argc--;
14991         argv++;
14992
14993         fstrcpy(workgroup, lp_workgroup());
14994
14995         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
14996                != EOF) {
14997                 switch (opt) {
14998                 case 'p':
14999                         port_to_use = atoi(optarg);
15000                         break;
15001                 case 's':
15002                         seed = atoi(optarg);
15003                         break;
15004                 case 'W':
15005                         fstrcpy(workgroup,optarg);
15006                         break;
15007                 case 'm':
15008                         lp_set_cmdline("client max protocol", optarg);
15009                         break;
15010                 case 'N':
15011                         torture_nprocs = atoi(optarg);
15012                         break;
15013                 case 'o':
15014                         torture_numops = atoi(optarg);
15015                         break;
15016                 case 'd':
15017                         lp_set_cmdline("log level", optarg);
15018                         break;
15019                 case 'O':
15020                         sockops = optarg;
15021                         break;
15022                 case 'L':
15023                         use_oplocks = True;
15024                         break;
15025                 case 'l':
15026                         local_path = optarg;
15027                         break;
15028                 case 'A':
15029                         torture_showall = True;
15030                         break;
15031                 case 'n':
15032                         fstrcpy(myname, optarg);
15033                         break;
15034                 case 'c':
15035                         client_txt = optarg;
15036                         break;
15037                 case 'e':
15038                         do_encrypt = true;
15039                         break;
15040                 case 'k':
15041 #ifdef HAVE_KRB5
15042                         use_kerberos = True;
15043 #else
15044                         d_printf("No kerberos support compiled in\n");
15045                         exit(1);
15046 #endif
15047                         break;
15048                 case 'U':
15049                         gotuser = 1;
15050                         fstrcpy(username,optarg);
15051                         p = strchr_m(username,'%');
15052                         if (p) {
15053                                 *p = 0;
15054                                 fstrcpy(password, p+1);
15055                                 gotpass = 1;
15056                         }
15057                         break;
15058                 case 'b':
15059                         fstrcpy(multishare_conn_fname, optarg);
15060                         use_multishare_conn = True;
15061                         break;
15062                 case 'B':
15063                         torture_blocksize = atoi(optarg);
15064                         break;
15065                 case 'f':
15066                         test_filename = SMB_STRDUP(optarg);
15067                         break;
15068                 default:
15069                         printf("Unknown option %c (%d)\n", (char)opt, opt);
15070                         usage();
15071                 }
15072         }
15073
15074         d_printf("using seed %d\n", seed);
15075
15076         srandom(seed);
15077
15078         if(use_kerberos && !gotuser) gotpass = True;
15079
15080         while (!gotpass) {
15081                 char pwd[256] = {0};
15082                 int rc;
15083
15084                 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
15085                 if (rc == 0) {
15086                         fstrcpy(password, pwd);
15087                         gotpass = 1;
15088                 }
15089         }
15090
15091         printf("host=%s share=%s user=%s myname=%s\n", 
15092                host, share, username, myname);
15093
15094         torture_creds = cli_session_creds_init(frame,
15095                                                username,
15096                                                workgroup,
15097                                                NULL, /* realm */
15098                                                password,
15099                                                use_kerberos,
15100                                                false, /* fallback_after_kerberos */
15101                                                false, /* use_ccache */
15102                                                false); /* password_is_nt_hash */
15103         if (torture_creds == NULL) {
15104                 d_printf("cli_session_creds_init() failed.\n");
15105                 exit(1);
15106         }
15107
15108         if (argc == optind) {
15109                 correct = run_test("ALL");
15110         } else {
15111                 for (i=optind;i<argc;i++) {
15112                         if (!run_test(argv[i])) {
15113                                 correct = False;
15114                         }
15115                 }
15116         }
15117
15118         TALLOC_FREE(frame);
15119
15120         if (correct) {
15121                 return(0);
15122         } else {
15123                 return(1);
15124         }
15125 }