ce9c56056f510cdd7d3b4bedfb0f15e137e2d1b3
[samba.git] / source3 / torture / torture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-1998
5    Copyright (C) Jeremy Allison 2009
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/shmem.h"
23 #include "libsmb/namequery.h"
24 #include "wbc_async.h"
25 #include "torture/proto.h"
26 #include "libcli/security/security.h"
27 #include "tldap.h"
28 #include "tldap_util.h"
29 #include "tldap_gensec_bind.h"
30 #include "../librpc/gen_ndr/svcctl.h"
31 #include "../lib/util/memcache.h"
32 #include "nsswitch/winbind_client.h"
33 #include "dbwrap/dbwrap.h"
34 #include "dbwrap/dbwrap_open.h"
35 #include "dbwrap/dbwrap_rbt.h"
36 #include "async_smb.h"
37 #include "libsmb/libsmb.h"
38 #include "libsmb/clirap.h"
39 #include "trans2.h"
40 #include "libsmb/nmblib.h"
41 #include "../lib/util/tevent_ntstatus.h"
42 #include "util_tdb.h"
43 #include "../libcli/smb/read_smb.h"
44 #include "../libcli/smb/smbXcli_base.h"
45 #include "lib/util/sys_rw_data.h"
46 #include "lib/util/base64.h"
47 #include "lib/util/time.h"
48 #include "lib/gencache.h"
49 #include "lib/util/sys_rw.h"
50 #include "lib/util/asn1.h"
51 #include "lib/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 (force_dos_errors) {
152                 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
153         }
154
155         status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
156                                 signing_state, flags, &c);
157         if (!NT_STATUS_IS_OK(status)) {
158                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
159                 return NULL;
160         }
161
162         cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
163
164         return c;
165 }
166
167 /****************************************************************************
168  Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
169 ****************************************************************************/
170
171 static bool cli_bad_session_request(int fd,
172                          struct nmb_name *calling, struct nmb_name *called)
173 {
174         TALLOC_CTX *frame;
175         uint8_t len_buf[4];
176         struct iovec iov[3];
177         ssize_t len;
178         uint8_t *inbuf;
179         int err;
180         bool ret = false;
181         uint8_t message_type;
182         uint8_t error;
183         struct tevent_context *ev;
184         struct tevent_req *req;
185
186         frame = talloc_stackframe();
187
188         iov[0].iov_base = len_buf;
189         iov[0].iov_len  = sizeof(len_buf);
190
191         /* put in the destination name */
192
193         iov[1].iov_base = name_mangle(talloc_tos(), called->name,
194                                       called->name_type);
195         if (iov[1].iov_base == NULL) {
196                 goto fail;
197         }
198         iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
199                                   talloc_get_size(iov[1].iov_base));
200
201         /* and my name */
202
203         iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
204                                       calling->name_type);
205         if (iov[2].iov_base == NULL) {
206                 goto fail;
207         }
208         iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
209                                   talloc_get_size(iov[2].iov_base));
210
211         /* Deliberately corrupt the name len (first byte) */
212         *((uint8_t *)iov[2].iov_base) = 100;
213
214         /* send a session request (RFC 1002) */
215         /* setup the packet length
216          * Remove four bytes from the length count, since the length
217          * field in the NBT Session Service header counts the number
218          * of bytes which follow.  The cli_send_smb() function knows
219          * about this and accounts for those four bytes.
220          * CRH.
221          */
222
223         _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
224         SCVAL(len_buf,0,0x81);
225
226         len = write_data_iov(fd, iov, 3);
227         if (len == -1) {
228                 goto fail;
229         }
230
231         ev = samba_tevent_context_init(frame);
232         if (ev == NULL) {
233                 goto fail;
234         }
235         req = read_smb_send(frame, ev, fd);
236         if (req == NULL) {
237                 goto fail;
238         }
239         if (!tevent_req_poll(req, ev)) {
240                 goto fail;
241         }
242         len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
243         if (len == -1) {
244                 errno = err;
245                 goto fail;
246         }
247         TALLOC_FREE(ev);
248
249         message_type = CVAL(inbuf, 0);
250         if (message_type != 0x83) {
251                 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
252                           message_type);
253                 goto fail;
254         }
255
256         if (smb_len(inbuf) != 1) {
257                 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
258                           (int)smb_len(inbuf));
259                 goto fail;
260         }
261
262         error = CVAL(inbuf, 4);
263         if (error !=  0x82) {
264                 d_fprintf(stderr, "Expected error 0x82, got %d\n",
265                           (int)error);
266                 goto fail;
267         }
268
269         ret = true;
270 fail:
271         TALLOC_FREE(frame);
272         return ret;
273 }
274
275 /* Insert a NULL at the first separator of the given path and return a pointer
276  * to the remainder of the string.
277  */
278 static char *
279 terminate_path_at_separator(char * path)
280 {
281         char * p;
282
283         if (!path) {
284                 return NULL;
285         }
286
287         if ((p = strchr_m(path, '/'))) {
288                 *p = '\0';
289                 return p + 1;
290         }
291
292         if ((p = strchr_m(path, '\\'))) {
293                 *p = '\0';
294                 return p + 1;
295         }
296
297         /* No separator. */
298         return NULL;
299 }
300
301 /*
302   parse a //server/share type UNC name
303 */
304 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
305                       char **hostname, char **sharename)
306 {
307         char *p;
308
309         *hostname = *sharename = NULL;
310
311         if (strncmp(unc_name, "\\\\", 2) &&
312             strncmp(unc_name, "//", 2)) {
313                 return False;
314         }
315
316         *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
317         p = terminate_path_at_separator(*hostname);
318
319         if (p && *p) {
320                 *sharename = talloc_strdup(mem_ctx, p);
321                 terminate_path_at_separator(*sharename);
322         }
323
324         if (*hostname && *sharename) {
325                 return True;
326         }
327
328         TALLOC_FREE(*hostname);
329         TALLOC_FREE(*sharename);
330         return False;
331 }
332
333 static bool torture_open_connection_share(struct cli_state **c,
334                                    const char *hostname, 
335                                    const char *sharename,
336                                    int flags)
337 {
338         NTSTATUS status;
339
340         status = cli_full_connection_creds(c,
341                                            myname,
342                                            hostname,
343                                            NULL, /* dest_ss */
344                                            port_to_use,
345                                            sharename,
346                                            "?????",
347                                            torture_creds,
348                                            flags,
349                                            signing_state);
350         if (!NT_STATUS_IS_OK(status)) {
351                 printf("failed to open share connection: //%s/%s port:%d - %s\n",
352                         hostname, sharename, port_to_use, nt_errstr(status));
353                 return False;
354         }
355
356         cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
357
358         if (do_encrypt) {
359                 return force_cli_encryption(*c,
360                                         sharename);
361         }
362         return True;
363 }
364
365 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
366 {
367         char **unc_list = NULL;
368         int num_unc_names = 0;
369         bool result;
370
371         if (use_multishare_conn==True) {
372                 char *h, *s;
373                 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
374                 if (!unc_list || num_unc_names <= 0) {
375                         printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
376                         exit(1);
377                 }
378
379                 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
380                                       NULL, &h, &s)) {
381                         printf("Failed to parse UNC name %s\n",
382                                unc_list[conn_index % num_unc_names]);
383                         TALLOC_FREE(unc_list);
384                         exit(1);
385                 }
386
387                 result = torture_open_connection_share(c, h, s, flags);
388
389                 /* h, s were copied earlier */
390                 TALLOC_FREE(unc_list);
391                 return result;
392         }
393
394         return torture_open_connection_share(c, host, share, flags);
395 }
396
397 bool torture_open_connection(struct cli_state **c, int conn_index)
398 {
399         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
400
401         if (use_oplocks) {
402                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
403         }
404         if (use_level_II_oplocks) {
405                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
406         }
407
408         return torture_open_connection_flags(c, conn_index, flags);
409 }
410
411 bool torture_init_connection(struct cli_state **pcli)
412 {
413         struct cli_state *cli;
414
415         cli = open_nbt_connection();
416         if (cli == NULL) {
417                 return false;
418         }
419
420         *pcli = cli;
421         return true;
422 }
423
424 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
425 {
426         uint16_t old_vuid = cli_state_get_uid(cli);
427         NTSTATUS status;
428         bool ret;
429
430         cli_state_set_uid(cli, 0);
431         status = cli_session_setup_creds(cli, torture_creds);
432         ret = NT_STATUS_IS_OK(status);
433         *new_vuid = cli_state_get_uid(cli);
434         cli_state_set_uid(cli, old_vuid);
435         return ret;
436 }
437
438
439 bool torture_close_connection(struct cli_state *c)
440 {
441         bool ret = True;
442         NTSTATUS status;
443
444         status = cli_tdis(c);
445         if (!NT_STATUS_IS_OK(status)) {
446                 printf("tdis failed (%s)\n", nt_errstr(status));
447                 ret = False;
448         }
449
450         cli_shutdown(c);
451
452         return ret;
453 }
454
455
456 /* check if the server produced the expected dos or nt error code */
457 static bool check_both_error(int line, NTSTATUS status,
458                              uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
459 {
460         if (NT_STATUS_IS_DOS(status)) {
461                 uint8_t cclass;
462                 uint32_t num;
463
464                 /* Check DOS error */
465                 cclass = NT_STATUS_DOS_CLASS(status);
466                 num = NT_STATUS_DOS_CODE(status);
467
468                 if (eclass != cclass || ecode != num) {
469                         printf("unexpected error code class=%d code=%d\n",
470                                (int)cclass, (int)num);
471                         printf(" expected %d/%d %s (line=%d)\n",
472                                (int)eclass, (int)ecode, nt_errstr(nterr), line);
473                         return false;
474                 }
475         } else {
476                 /* Check NT error */
477                 if (!NT_STATUS_EQUAL(nterr, status)) {
478                         printf("unexpected error code %s\n",
479                                 nt_errstr(status));
480                         printf(" expected %s (line=%d)\n",
481                                 nt_errstr(nterr), line);
482                         return false;
483                 }
484         }
485
486         return true;
487 }
488
489
490 /* check if the server produced the expected error code */
491 static bool check_error(int line, NTSTATUS status,
492                         uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
493 {
494         if (NT_STATUS_IS_DOS(status)) {
495                 uint8_t cclass;
496                 uint32_t num;
497
498                 /* Check DOS error */
499
500                 cclass = NT_STATUS_DOS_CLASS(status);
501                 num = NT_STATUS_DOS_CODE(status);
502
503                 if (eclass != cclass || ecode != num) {
504                         printf("unexpected error code class=%d code=%d\n", 
505                                (int)cclass, (int)num);
506                         printf(" expected %d/%d %s (line=%d)\n", 
507                                (int)eclass, (int)ecode, nt_errstr(nterr),
508                                line);
509                         return False;
510                 }
511
512         } else {
513                 /* Check NT error */
514
515                 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
516                         printf("unexpected error code %s\n",
517                                nt_errstr(status));
518                         printf(" expected %s (line=%d)\n", nt_errstr(nterr),
519                                line);
520                         return False;
521                 }
522         }
523
524         return True;
525 }
526
527
528 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
529 {
530         NTSTATUS status;
531
532         status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
533
534         while (!NT_STATUS_IS_OK(status)) {
535                 if (!check_both_error(__LINE__, status, ERRDOS,
536                                       ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
537                         return false;
538                 }
539
540                 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
541         }
542
543         return true;
544 }
545
546
547 static bool rw_torture(struct cli_state *c)
548 {
549         const char *lockfname = "\\torture.lck";
550         fstring fname;
551         uint16_t fnum;
552         uint16_t fnum2;
553         pid_t pid2, pid = getpid();
554         int i, j;
555         char buf[1024];
556         bool correct = True;
557         size_t nread = 0;
558         NTSTATUS status;
559
560         memset(buf, '\0', sizeof(buf));
561
562         status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
563                          DENY_NONE, &fnum2);
564         if (!NT_STATUS_IS_OK(status)) {
565                 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
566         }
567         if (!NT_STATUS_IS_OK(status)) {
568                 printf("open of %s failed (%s)\n",
569                        lockfname, nt_errstr(status));
570                 return False;
571         }
572
573         for (i=0;i<torture_numops;i++) {
574                 unsigned n = (unsigned)sys_random()%10;
575
576                 if (i % 10 == 0) {
577                         printf("%d\r", i); fflush(stdout);
578                 }
579                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
580
581                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
582                         return False;
583                 }
584
585                 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
586                                   DENY_ALL, &fnum);
587                 if (!NT_STATUS_IS_OK(status)) {
588                         printf("open failed (%s)\n", nt_errstr(status));
589                         correct = False;
590                         break;
591                 }
592
593                 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
594                                       sizeof(pid), NULL);
595                 if (!NT_STATUS_IS_OK(status)) {
596                         printf("write failed (%s)\n", nt_errstr(status));
597                         correct = False;
598                 }
599
600                 for (j=0;j<50;j++) {
601                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
602                                               sizeof(pid)+(j*sizeof(buf)),
603                                               sizeof(buf), NULL);
604                         if (!NT_STATUS_IS_OK(status)) {
605                                 printf("write failed (%s)\n",
606                                        nt_errstr(status));
607                                 correct = False;
608                         }
609                 }
610
611                 pid2 = 0;
612
613                 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
614                                   &nread);
615                 if (!NT_STATUS_IS_OK(status)) {
616                         printf("read failed (%s)\n", nt_errstr(status));
617                         correct = false;
618                 } else if (nread != sizeof(pid)) {
619                         printf("read/write compare failed: "
620                                "recv %ld req %ld\n", (unsigned long)nread,
621                                (unsigned long)sizeof(pid));
622                         correct = false;
623                 }
624
625                 if (pid2 != pid) {
626                         printf("data corruption!\n");
627                         correct = False;
628                 }
629
630                 status = cli_close(c, fnum);
631                 if (!NT_STATUS_IS_OK(status)) {
632                         printf("close failed (%s)\n", nt_errstr(status));
633                         correct = False;
634                 }
635
636                 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
637                 if (!NT_STATUS_IS_OK(status)) {
638                         printf("unlink failed (%s)\n", nt_errstr(status));
639                         correct = False;
640                 }
641
642                 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
643                 if (!NT_STATUS_IS_OK(status)) {
644                         printf("unlock failed (%s)\n", nt_errstr(status));
645                         correct = False;
646                 }
647         }
648
649         cli_close(c, fnum2);
650         cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
651
652         printf("%d\n", i);
653
654         return correct;
655 }
656
657 static bool run_torture(int dummy)
658 {
659         struct cli_state *cli;
660         bool ret;
661
662         cli = current_cli;
663
664         smbXcli_conn_set_sockopt(cli->conn, sockops);
665
666         ret = rw_torture(cli);
667
668         if (!torture_close_connection(cli)) {
669                 ret = False;
670         }
671
672         return ret;
673 }
674
675 static bool rw_torture3(struct cli_state *c, char *lockfname)
676 {
677         uint16_t fnum = (uint16_t)-1;
678         unsigned int i = 0;
679         char buf[131072];
680         char buf_rd[131072];
681         unsigned count;
682         unsigned countprev = 0;
683         size_t sent = 0;
684         bool correct = True;
685         NTSTATUS status = NT_STATUS_OK;
686
687         srandom(1);
688         for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
689         {
690                 SIVAL(buf, i, sys_random());
691         }
692
693         if (procnum == 0)
694         {
695                 status = cli_unlink(
696                         c, lockfname,
697                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
698                 if (!NT_STATUS_IS_OK(status)) {
699                         printf("unlink failed (%s) (normal, this file should "
700                                "not exist)\n", nt_errstr(status));
701                 }
702
703                 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
704                                   DENY_NONE, &fnum);
705                 if (!NT_STATUS_IS_OK(status)) {
706                         printf("first open read/write of %s failed (%s)\n",
707                                         lockfname, nt_errstr(status));
708                         return False;
709                 }
710         }
711         else
712         {
713                 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
714                 {
715                         status = cli_openx(c, lockfname, O_RDONLY, 
716                                          DENY_NONE, &fnum);
717                         if (NT_STATUS_IS_OK(status)) {
718                                 break;
719                         }
720                         smb_msleep(10);
721                 }
722                 if (!NT_STATUS_IS_OK(status)) {
723                         printf("second open read-only of %s failed (%s)\n",
724                                         lockfname, nt_errstr(status));
725                         return False;
726                 }
727         }
728
729         i = 0;
730         for (count = 0; count < sizeof(buf); count += sent)
731         {
732                 if (count >= countprev) {
733                         printf("%d %8d\r", i, count);
734                         fflush(stdout);
735                         i++;
736                         countprev += (sizeof(buf) / 20);
737                 }
738
739                 if (procnum == 0)
740                 {
741                         sent = ((unsigned)sys_random()%(20))+ 1;
742                         if (sent > sizeof(buf) - count)
743                         {
744                                 sent = sizeof(buf) - count;
745                         }
746
747                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
748                                               count, sent, NULL);
749                         if (!NT_STATUS_IS_OK(status)) {
750                                 printf("write failed (%s)\n",
751                                        nt_errstr(status));
752                                 correct = False;
753                         }
754                 }
755                 else
756                 {
757                         status = cli_read(c, fnum, buf_rd+count, count,
758                                           sizeof(buf)-count, &sent);
759                         if(!NT_STATUS_IS_OK(status)) {
760                                 printf("read failed offset:%d size:%ld (%s)\n",
761                                        count, (unsigned long)sizeof(buf)-count,
762                                        nt_errstr(status));
763                                 correct = False;
764                                 sent = 0;
765                         } else if (sent > 0) {
766                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
767                                 {
768                                         printf("read/write compare failed\n");
769                                         printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
770                                         correct = False;
771                                         break;
772                                 }
773                         }
774                 }
775
776         }
777
778         status = cli_close(c, fnum);
779         if (!NT_STATUS_IS_OK(status)) {
780                 printf("close failed (%s)\n", nt_errstr(status));
781                 correct = False;
782         }
783
784         return correct;
785 }
786
787 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
788 {
789         const char *lockfname = "\\torture2.lck";
790         uint16_t fnum1;
791         uint16_t fnum2;
792         int i;
793         char buf[131072];
794         char buf_rd[131072];
795         bool correct = True;
796         size_t bytes_read;
797         NTSTATUS status;
798
799         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
800         if (!NT_STATUS_IS_OK(status)) {
801                 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
802         }
803
804         status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
805                           DENY_NONE, &fnum1);
806         if (!NT_STATUS_IS_OK(status)) {
807                 printf("first open read/write of %s failed (%s)\n",
808                                 lockfname, nt_errstr(status));
809                 return False;
810         }
811
812         status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
813         if (!NT_STATUS_IS_OK(status)) {
814                 printf("second open read-only of %s failed (%s)\n",
815                                 lockfname, nt_errstr(status));
816                 cli_close(c1, fnum1);
817                 return False;
818         }
819
820         for (i = 0; i < torture_numops; i++)
821         {
822                 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
823                 if (i % 10 == 0) {
824                         printf("%d\r", i); fflush(stdout);
825                 }
826
827                 generate_random_buffer((unsigned char *)buf, buf_size);
828
829                 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
830                                       buf_size, NULL);
831                 if (!NT_STATUS_IS_OK(status)) {
832                         printf("write failed (%s)\n", nt_errstr(status));
833                         correct = False;
834                         break;
835                 }
836
837                 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
838                 if(!NT_STATUS_IS_OK(status)) {
839                         printf("read failed (%s)\n", nt_errstr(status));
840                         correct = false;
841                         break;
842                 } else if (bytes_read != buf_size) {
843                         printf("read failed\n");
844                         printf("read %ld, expected %ld\n",
845                                (unsigned long)bytes_read,
846                                (unsigned long)buf_size); 
847                         correct = False;
848                         break;
849                 }
850
851                 if (memcmp(buf_rd, buf, buf_size) != 0)
852                 {
853                         printf("read/write compare failed\n");
854                         correct = False;
855                         break;
856                 }
857         }
858
859         status = cli_close(c2, fnum2);
860         if (!NT_STATUS_IS_OK(status)) {
861                 printf("close failed (%s)\n", nt_errstr(status));
862                 correct = False;
863         }
864
865         status = cli_close(c1, fnum1);
866         if (!NT_STATUS_IS_OK(status)) {
867                 printf("close failed (%s)\n", nt_errstr(status));
868                 correct = False;
869         }
870
871         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
872         if (!NT_STATUS_IS_OK(status)) {
873                 printf("unlink failed (%s)\n", nt_errstr(status));
874                 correct = False;
875         }
876
877         return correct;
878 }
879
880 static bool run_readwritetest(int dummy)
881 {
882         struct cli_state *cli1, *cli2;
883         bool test1, test2 = False;
884
885         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
886                 return False;
887         }
888         smbXcli_conn_set_sockopt(cli1->conn, sockops);
889         smbXcli_conn_set_sockopt(cli2->conn, sockops);
890
891         printf("starting readwritetest\n");
892
893         test1 = rw_torture2(cli1, cli2);
894         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
895
896         if (test1) {
897                 test2 = rw_torture2(cli1, cli1);
898                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
899         }
900
901         if (!torture_close_connection(cli1)) {
902                 test1 = False;
903         }
904
905         if (!torture_close_connection(cli2)) {
906                 test2 = False;
907         }
908
909         return (test1 && test2);
910 }
911
912 static bool run_readwritemulti(int dummy)
913 {
914         struct cli_state *cli;
915         bool test;
916
917         cli = current_cli;
918
919         smbXcli_conn_set_sockopt(cli->conn, sockops);
920
921         printf("run_readwritemulti: fname %s\n", randomfname);
922         test = rw_torture3(cli, randomfname);
923
924         if (!torture_close_connection(cli)) {
925                 test = False;
926         }
927
928         return test;
929 }
930
931 static bool run_readwritelarge_internal(void)
932 {
933         static struct cli_state *cli1;
934         uint16_t fnum1;
935         const char *lockfname = "\\large.dat";
936         off_t fsize;
937         char buf[126*1024];
938         bool correct = True;
939         NTSTATUS status;
940
941         if (!torture_open_connection(&cli1, 0)) {
942                 return False;
943         }
944         smbXcli_conn_set_sockopt(cli1->conn, sockops);
945         memset(buf,'\0',sizeof(buf));
946
947         printf("starting readwritelarge_internal\n");
948
949         cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
950
951         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
952                           DENY_NONE, &fnum1);
953         if (!NT_STATUS_IS_OK(status)) {
954                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
955                 return False;
956         }
957
958         cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
959
960         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
961                                      NULL, NULL, NULL);
962         if (!NT_STATUS_IS_OK(status)) {
963                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
964                 correct = False;
965         }
966
967         if (fsize == sizeof(buf))
968                 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
969                        (unsigned long)fsize);
970         else {
971                 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
972                        (unsigned long)fsize);
973                 correct = False;
974         }
975
976         status = cli_close(cli1, fnum1);
977         if (!NT_STATUS_IS_OK(status)) {
978                 printf("close failed (%s)\n", nt_errstr(status));
979                 correct = False;
980         }
981
982         status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
983         if (!NT_STATUS_IS_OK(status)) {
984                 printf("unlink failed (%s)\n", nt_errstr(status));
985                 correct = False;
986         }
987
988         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
989                           DENY_NONE, &fnum1);
990         if (!NT_STATUS_IS_OK(status)) {
991                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
992                 return False;
993         }
994
995         cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
996
997         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
998                                      NULL, NULL, NULL);
999         if (!NT_STATUS_IS_OK(status)) {
1000                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1001                 correct = False;
1002         }
1003
1004         if (fsize == sizeof(buf))
1005                 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1006                        (unsigned long)fsize);
1007         else {
1008                 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1009                        (unsigned long)fsize);
1010                 correct = False;
1011         }
1012
1013         status = cli_close(cli1, fnum1);
1014         if (!NT_STATUS_IS_OK(status)) {
1015                 printf("close failed (%s)\n", nt_errstr(status));
1016                 correct = False;
1017         }
1018
1019         if (!torture_close_connection(cli1)) {
1020                 correct = False;
1021         }
1022         return correct;
1023 }
1024
1025 static bool run_readwritelarge(int dummy)
1026 {
1027         return run_readwritelarge_internal();
1028 }
1029
1030 static bool run_readwritelarge_signtest(int dummy)
1031 {
1032         bool ret;
1033         signing_state = SMB_SIGNING_REQUIRED;
1034         ret = run_readwritelarge_internal();
1035         signing_state = SMB_SIGNING_DEFAULT;
1036         return ret;
1037 }
1038
1039 int line_count = 0;
1040 int nbio_id;
1041
1042 #define ival(s) strtol(s, NULL, 0)
1043
1044 /* run a test that simulates an approximate netbench client load */
1045 static bool run_netbench(int client)
1046 {
1047         struct cli_state *cli;
1048         int i;
1049         char line[1024];
1050         char cname[20];
1051         FILE *f;
1052         const char *params[20];
1053         bool correct = True;
1054
1055         cli = current_cli;
1056
1057         nbio_id = client;
1058
1059         smbXcli_conn_set_sockopt(cli->conn, sockops);
1060
1061         nb_setup(cli);
1062
1063         slprintf(cname,sizeof(cname)-1, "client%d", client);
1064
1065         f = fopen(client_txt, "r");
1066
1067         if (!f) {
1068                 perror(client_txt);
1069                 return False;
1070         }
1071
1072         while (fgets(line, sizeof(line)-1, f)) {
1073                 char *saveptr;
1074                 line_count++;
1075
1076                 line[strlen(line)-1] = 0;
1077
1078                 /* printf("[%d] %s\n", line_count, line); */
1079
1080                 all_string_sub(line,"client1", cname, sizeof(line));
1081
1082                 /* parse the command parameters */
1083                 params[0] = strtok_r(line, " ", &saveptr);
1084                 i = 0;
1085                 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1086
1087                 params[i] = "";
1088
1089                 if (i < 2) continue;
1090
1091                 if (!strncmp(params[0],"SMB", 3)) {
1092                         printf("ERROR: You are using a dbench 1 load file\n");
1093                         exit(1);
1094                 }
1095
1096                 if (!strcmp(params[0],"NTCreateX")) {
1097                         nb_createx(params[1], ival(params[2]), ival(params[3]), 
1098                                    ival(params[4]));
1099                 } else if (!strcmp(params[0],"Close")) {
1100                         nb_close(ival(params[1]));
1101                 } else if (!strcmp(params[0],"Rename")) {
1102                         nb_rename(params[1], params[2]);
1103                 } else if (!strcmp(params[0],"Unlink")) {
1104                         nb_unlink(params[1]);
1105                 } else if (!strcmp(params[0],"Deltree")) {
1106                         nb_deltree(params[1]);
1107                 } else if (!strcmp(params[0],"Rmdir")) {
1108                         nb_rmdir(params[1]);
1109                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1110                         nb_qpathinfo(params[1]);
1111                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1112                         nb_qfileinfo(ival(params[1]));
1113                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1114                         nb_qfsinfo(ival(params[1]));
1115                 } else if (!strcmp(params[0],"FIND_FIRST")) {
1116                         nb_findfirst(params[1]);
1117                 } else if (!strcmp(params[0],"WriteX")) {
1118                         nb_writex(ival(params[1]), 
1119                                   ival(params[2]), ival(params[3]), ival(params[4]));
1120                 } else if (!strcmp(params[0],"ReadX")) {
1121                         nb_readx(ival(params[1]), 
1122                                   ival(params[2]), ival(params[3]), ival(params[4]));
1123                 } else if (!strcmp(params[0],"Flush")) {
1124                         nb_flush(ival(params[1]));
1125                 } else {
1126                         printf("Unknown operation %s\n", params[0]);
1127                         exit(1);
1128                 }
1129         }
1130         fclose(f);
1131
1132         nb_cleanup();
1133
1134         if (!torture_close_connection(cli)) {
1135                 correct = False;
1136         }
1137
1138         return correct;
1139 }
1140
1141
1142 /* run a test that simulates an approximate netbench client load */
1143 static bool run_nbench(int dummy)
1144 {
1145         double t;
1146         bool correct = True;
1147
1148         nbio_shmem(torture_nprocs);
1149
1150         nbio_id = -1;
1151
1152         signal(SIGALRM, nb_alarm);
1153         alarm(1);
1154         t = create_procs(run_netbench, &correct);
1155         alarm(0);
1156
1157         printf("\nThroughput %g MB/sec\n", 
1158                1.0e-6 * nbio_total() / t);
1159         return correct;
1160 }
1161
1162
1163 /*
1164   This test checks for two things:
1165
1166   1) correct support for retaining locks over a close (ie. the server
1167      must not use posix semantics)
1168   2) support for lock timeouts
1169  */
1170 static bool run_locktest1(int dummy)
1171 {
1172         struct cli_state *cli1, *cli2;
1173         const char *fname = "\\lockt1.lck";
1174         uint16_t fnum1, fnum2, fnum3;
1175         time_t t1, t2;
1176         unsigned lock_timeout;
1177         NTSTATUS status;
1178
1179         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1180                 return False;
1181         }
1182         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1183         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1184
1185         printf("starting locktest1\n");
1186
1187         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1188
1189         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1190                           &fnum1);
1191         if (!NT_STATUS_IS_OK(status)) {
1192                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1193                 return False;
1194         }
1195
1196         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1197         if (!NT_STATUS_IS_OK(status)) {
1198                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1199                 return False;
1200         }
1201
1202         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1203         if (!NT_STATUS_IS_OK(status)) {
1204                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1205                 return False;
1206         }
1207
1208         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1209         if (!NT_STATUS_IS_OK(status)) {
1210                 printf("lock1 failed (%s)\n", nt_errstr(status));
1211                 return false;
1212         }
1213
1214         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1215         if (NT_STATUS_IS_OK(status)) {
1216                 printf("lock2 succeeded! This is a locking bug\n");
1217                 return false;
1218         } else {
1219                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1220                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1221                         return false;
1222                 }
1223         }
1224
1225         lock_timeout = (1 + (random() % 20));
1226         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1227         t1 = time(NULL);
1228         status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1229         if (NT_STATUS_IS_OK(status)) {
1230                 printf("lock3 succeeded! This is a locking bug\n");
1231                 return false;
1232         } else {
1233                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1234                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1235                         return false;
1236                 }
1237         }
1238         t2 = time(NULL);
1239
1240         if (ABS(t2 - t1) < lock_timeout-1) {
1241                 printf("error: This server appears not to support timed lock requests\n");
1242         }
1243
1244         printf("server slept for %u seconds for a %u second timeout\n",
1245                (unsigned int)(t2-t1), lock_timeout);
1246
1247         status = cli_close(cli1, fnum2);
1248         if (!NT_STATUS_IS_OK(status)) {
1249                 printf("close1 failed (%s)\n", nt_errstr(status));
1250                 return False;
1251         }
1252
1253         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1254         if (NT_STATUS_IS_OK(status)) {
1255                 printf("lock4 succeeded! This is a locking bug\n");
1256                 return false;
1257         } else {
1258                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1259                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1260                         return false;
1261                 }
1262         }
1263
1264         status = cli_close(cli1, fnum1);
1265         if (!NT_STATUS_IS_OK(status)) {
1266                 printf("close2 failed (%s)\n", nt_errstr(status));
1267                 return False;
1268         }
1269
1270         status = cli_close(cli2, fnum3);
1271         if (!NT_STATUS_IS_OK(status)) {
1272                 printf("close3 failed (%s)\n", nt_errstr(status));
1273                 return False;
1274         }
1275
1276         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1277         if (!NT_STATUS_IS_OK(status)) {
1278                 printf("unlink failed (%s)\n", nt_errstr(status));
1279                 return False;
1280         }
1281
1282
1283         if (!torture_close_connection(cli1)) {
1284                 return False;
1285         }
1286
1287         if (!torture_close_connection(cli2)) {
1288                 return False;
1289         }
1290
1291         printf("Passed locktest1\n");
1292         return True;
1293 }
1294
1295 /*
1296   this checks to see if a secondary tconx can use open files from an
1297   earlier tconx
1298  */
1299 static bool run_tcon_test(int dummy)
1300 {
1301         static struct cli_state *cli;
1302         const char *fname = "\\tcontest.tmp";
1303         uint16_t fnum1;
1304         uint32_t cnum1, cnum2, cnum3;
1305         struct smbXcli_tcon *orig_tcon = NULL;
1306         uint16_t vuid1, vuid2;
1307         char buf[4];
1308         bool ret = True;
1309         NTSTATUS status;
1310
1311         memset(buf, '\0', sizeof(buf));
1312
1313         if (!torture_open_connection(&cli, 0)) {
1314                 return False;
1315         }
1316         smbXcli_conn_set_sockopt(cli->conn, sockops);
1317
1318         printf("starting tcontest\n");
1319
1320         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1321
1322         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1323         if (!NT_STATUS_IS_OK(status)) {
1324                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1325                 return False;
1326         }
1327
1328         cnum1 = cli_state_get_tid(cli);
1329         vuid1 = cli_state_get_uid(cli);
1330
1331         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1332         if (!NT_STATUS_IS_OK(status)) {
1333                 printf("initial write failed (%s)", nt_errstr(status));
1334                 return False;
1335         }
1336
1337         orig_tcon = cli_state_save_tcon(cli);
1338         if (orig_tcon == NULL) {
1339                 return false;
1340         }
1341
1342         status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1343         if (!NT_STATUS_IS_OK(status)) {
1344                 printf("%s refused 2nd tree connect (%s)\n", host,
1345                        nt_errstr(status));
1346                 cli_shutdown(cli);
1347                 return False;
1348         }
1349
1350         cnum2 = cli_state_get_tid(cli);
1351         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1352         vuid2 = cli_state_get_uid(cli) + 1;
1353
1354         /* try a write with the wrong tid */
1355         cli_state_set_tid(cli, cnum2);
1356
1357         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1358         if (NT_STATUS_IS_OK(status)) {
1359                 printf("* server allows write with wrong TID\n");
1360                 ret = False;
1361         } else {
1362                 printf("server fails write with wrong TID : %s\n",
1363                        nt_errstr(status));
1364         }
1365
1366
1367         /* try a write with an invalid tid */
1368         cli_state_set_tid(cli, cnum3);
1369
1370         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1371         if (NT_STATUS_IS_OK(status)) {
1372                 printf("* server allows write with invalid TID\n");
1373                 ret = False;
1374         } else {
1375                 printf("server fails write with invalid TID : %s\n",
1376                        nt_errstr(status));
1377         }
1378
1379         /* try a write with an invalid vuid */
1380         cli_state_set_uid(cli, vuid2);
1381         cli_state_set_tid(cli, cnum1);
1382
1383         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1384         if (NT_STATUS_IS_OK(status)) {
1385                 printf("* server allows write with invalid VUID\n");
1386                 ret = False;
1387         } else {
1388                 printf("server fails write with invalid VUID : %s\n",
1389                        nt_errstr(status));
1390         }
1391
1392         cli_state_set_tid(cli, cnum1);
1393         cli_state_set_uid(cli, vuid1);
1394
1395         status = cli_close(cli, fnum1);
1396         if (!NT_STATUS_IS_OK(status)) {
1397                 printf("close failed (%s)\n", nt_errstr(status));
1398                 return False;
1399         }
1400
1401         cli_state_set_tid(cli, cnum2);
1402
1403         status = cli_tdis(cli);
1404         if (!NT_STATUS_IS_OK(status)) {
1405                 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1406                 return False;
1407         }
1408
1409         cli_state_restore_tcon(cli, orig_tcon);
1410
1411         cli_state_set_tid(cli, cnum1);
1412
1413         if (!torture_close_connection(cli)) {
1414                 return False;
1415         }
1416
1417         return ret;
1418 }
1419
1420
1421 /*
1422  checks for old style tcon support
1423  */
1424 static bool run_tcon2_test(int dummy)
1425 {
1426         static struct cli_state *cli;
1427         uint16_t cnum, max_xmit;
1428         char *service;
1429         NTSTATUS status;
1430
1431         if (!torture_open_connection(&cli, 0)) {
1432                 return False;
1433         }
1434         smbXcli_conn_set_sockopt(cli->conn, sockops);
1435
1436         printf("starting tcon2 test\n");
1437
1438         if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1439                 return false;
1440         }
1441
1442         status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1443
1444         SAFE_FREE(service);
1445
1446         if (!NT_STATUS_IS_OK(status)) {
1447                 printf("tcon2 failed : %s\n", nt_errstr(status));
1448         } else {
1449                 printf("tcon OK : max_xmit=%d cnum=%d\n",
1450                        (int)max_xmit, (int)cnum);
1451         }
1452
1453         if (!torture_close_connection(cli)) {
1454                 return False;
1455         }
1456
1457         printf("Passed tcon2 test\n");
1458         return True;
1459 }
1460
1461 static bool tcon_devtest(struct cli_state *cli,
1462                          const char *myshare, const char *devtype,
1463                          const char *return_devtype,
1464                          NTSTATUS expected_error)
1465 {
1466         NTSTATUS status;
1467         bool ret;
1468
1469         status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1470
1471         if (NT_STATUS_IS_OK(expected_error)) {
1472                 if (NT_STATUS_IS_OK(status)) {
1473                         if (return_devtype != NULL &&
1474                             strequal(cli->dev, return_devtype)) {
1475                                 ret = True;
1476                         } else { 
1477                                 printf("tconX to share %s with type %s "
1478                                        "succeeded but returned the wrong "
1479                                        "device type (got [%s] but should have got [%s])\n",
1480                                        myshare, devtype, cli->dev, return_devtype);
1481                                 ret = False;
1482                         }
1483                 } else {
1484                         printf("tconX to share %s with type %s "
1485                                "should have succeeded but failed\n",
1486                                myshare, devtype);
1487                         ret = False;
1488                 }
1489                 cli_tdis(cli);
1490         } else {
1491                 if (NT_STATUS_IS_OK(status)) {
1492                         printf("tconx to share %s with type %s "
1493                                "should have failed but succeeded\n",
1494                                myshare, devtype);
1495                         ret = False;
1496                 } else {
1497                         if (NT_STATUS_EQUAL(status, expected_error)) {
1498                                 ret = True;
1499                         } else {
1500                                 printf("Returned unexpected error\n");
1501                                 ret = False;
1502                         }
1503                 }
1504         }
1505         return ret;
1506 }
1507
1508 /*
1509  checks for correct tconX support
1510  */
1511 static bool run_tcon_devtype_test(int dummy)
1512 {
1513         static struct cli_state *cli1 = NULL;
1514         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1515         NTSTATUS status;
1516         bool ret = True;
1517
1518         status = cli_full_connection_creds(&cli1,
1519                                            myname,
1520                                            host,
1521                                            NULL, /* dest_ss */
1522                                            port_to_use,
1523                                            NULL, /* service */
1524                                            NULL, /* service_type */
1525                                            torture_creds,
1526                                            flags,
1527                                            signing_state);
1528
1529         if (!NT_STATUS_IS_OK(status)) {
1530                 printf("could not open connection\n");
1531                 return False;
1532         }
1533
1534         if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1535                 ret = False;
1536
1537         if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1538                 ret = False;
1539
1540         if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1541                 ret = False;
1542
1543         if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1544                 ret = False;
1545
1546         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1547                 ret = False;
1548
1549         if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1550                 ret = False;
1551
1552         if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1553                 ret = False;
1554
1555         if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1556                 ret = False;
1557
1558         if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1559                 ret = False;
1560
1561         if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1562                 ret = False;
1563
1564         cli_shutdown(cli1);
1565
1566         if (ret)
1567                 printf("Passed tcondevtest\n");
1568
1569         return ret;
1570 }
1571
1572
1573 /*
1574   This test checks that 
1575
1576   1) the server supports multiple locking contexts on the one SMB
1577   connection, distinguished by PID.  
1578
1579   2) the server correctly fails overlapping locks made by the same PID (this
1580      goes against POSIX behaviour, which is why it is tricky to implement)
1581
1582   3) the server denies unlock requests by an incorrect client PID
1583 */
1584 static bool run_locktest2(int dummy)
1585 {
1586         static struct cli_state *cli;
1587         const char *fname = "\\lockt2.lck";
1588         uint16_t fnum1, fnum2, fnum3;
1589         bool correct = True;
1590         NTSTATUS status;
1591
1592         if (!torture_open_connection(&cli, 0)) {
1593                 return False;
1594         }
1595
1596         smbXcli_conn_set_sockopt(cli->conn, sockops);
1597
1598         printf("starting locktest2\n");
1599
1600         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1601
1602         cli_setpid(cli, 1);
1603
1604         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1605         if (!NT_STATUS_IS_OK(status)) {
1606                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1607                 return False;
1608         }
1609
1610         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1611         if (!NT_STATUS_IS_OK(status)) {
1612                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1613                 return False;
1614         }
1615
1616         cli_setpid(cli, 2);
1617
1618         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1619         if (!NT_STATUS_IS_OK(status)) {
1620                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1621                 return False;
1622         }
1623
1624         cli_setpid(cli, 1);
1625
1626         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1627         if (!NT_STATUS_IS_OK(status)) {
1628                 printf("lock1 failed (%s)\n", nt_errstr(status));
1629                 return false;
1630         }
1631
1632         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1633         if (NT_STATUS_IS_OK(status)) {
1634                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1635                 correct = false;
1636         } else {
1637                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1638                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1639                         return false;
1640                 }
1641         }
1642
1643         status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1644         if (NT_STATUS_IS_OK(status)) {
1645                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1646                 correct = false;
1647         } else {
1648                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1649                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1650                         return false;
1651                 }
1652         }
1653
1654         status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1655         if (NT_STATUS_IS_OK(status)) {
1656                 printf("READ lock2 succeeded! This is a locking bug\n");
1657                 correct = false;
1658         } else {
1659                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1660                                  NT_STATUS_FILE_LOCK_CONFLICT)) {
1661                         return false;
1662                 }
1663         }
1664
1665         status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1666         if (!NT_STATUS_IS_OK(status)) {
1667                 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1668         }
1669         cli_setpid(cli, 2);
1670         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1671                 printf("unlock at 100 succeeded! This is a locking bug\n");
1672                 correct = False;
1673         }
1674
1675         status = cli_unlock(cli, fnum1, 0, 4);
1676         if (NT_STATUS_IS_OK(status)) {
1677                 printf("unlock1 succeeded! This is a locking bug\n");
1678                 correct = false;
1679         } else {
1680                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1681                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1682                         return false;
1683                 }
1684         }
1685
1686         status = cli_unlock(cli, fnum1, 0, 8);
1687         if (NT_STATUS_IS_OK(status)) {
1688                 printf("unlock2 succeeded! This is a locking bug\n");
1689                 correct = false;
1690         } else {
1691                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1692                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1693                         return false;
1694                 }
1695         }
1696
1697         status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1698         if (NT_STATUS_IS_OK(status)) {
1699                 printf("lock3 succeeded! This is a locking bug\n");
1700                 correct = false;
1701         } else {
1702                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1703                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1704                         return false;
1705                 }
1706         }
1707
1708         cli_setpid(cli, 1);
1709
1710         status = cli_close(cli, fnum1);
1711         if (!NT_STATUS_IS_OK(status)) {
1712                 printf("close1 failed (%s)\n", nt_errstr(status));
1713                 return False;
1714         }
1715
1716         status = cli_close(cli, fnum2);
1717         if (!NT_STATUS_IS_OK(status)) {
1718                 printf("close2 failed (%s)\n", nt_errstr(status));
1719                 return False;
1720         }
1721
1722         status = cli_close(cli, fnum3);
1723         if (!NT_STATUS_IS_OK(status)) {
1724                 printf("close3 failed (%s)\n", nt_errstr(status));
1725                 return False;
1726         }
1727
1728         if (!torture_close_connection(cli)) {
1729                 correct = False;
1730         }
1731
1732         printf("locktest2 finished\n");
1733
1734         return correct;
1735 }
1736
1737
1738 /*
1739   This test checks that 
1740
1741   1) the server supports the full offset range in lock requests
1742 */
1743 static bool run_locktest3(int dummy)
1744 {
1745         static struct cli_state *cli1, *cli2;
1746         const char *fname = "\\lockt3.lck";
1747         uint16_t fnum1, fnum2;
1748         int i;
1749         uint32_t offset;
1750         bool correct = True;
1751         NTSTATUS status;
1752
1753 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1754
1755         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1756                 return False;
1757         }
1758         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1759         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1760
1761         printf("starting locktest3\n");
1762
1763         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1764
1765         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1766                          &fnum1);
1767         if (!NT_STATUS_IS_OK(status)) {
1768                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1769                 return False;
1770         }
1771
1772         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1773         if (!NT_STATUS_IS_OK(status)) {
1774                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1775                 return False;
1776         }
1777
1778         for (offset=i=0;i<torture_numops;i++) {
1779                 NEXT_OFFSET;
1780
1781                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1782                 if (!NT_STATUS_IS_OK(status)) {
1783                         printf("lock1 %d failed (%s)\n", 
1784                                i,
1785                                nt_errstr(status));
1786                         return False;
1787                 }
1788
1789                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1790                 if (!NT_STATUS_IS_OK(status)) {
1791                         printf("lock2 %d failed (%s)\n", 
1792                                i,
1793                                nt_errstr(status));
1794                         return False;
1795                 }
1796         }
1797
1798         for (offset=i=0;i<torture_numops;i++) {
1799                 NEXT_OFFSET;
1800
1801                 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1802                 if (NT_STATUS_IS_OK(status)) {
1803                         printf("error: lock1 %d succeeded!\n", i);
1804                         return False;
1805                 }
1806
1807                 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1808                 if (NT_STATUS_IS_OK(status)) {
1809                         printf("error: lock2 %d succeeded!\n", i);
1810                         return False;
1811                 }
1812
1813                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1814                 if (NT_STATUS_IS_OK(status)) {
1815                         printf("error: lock3 %d succeeded!\n", i);
1816                         return False;
1817                 }
1818
1819                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1820                 if (NT_STATUS_IS_OK(status)) {
1821                         printf("error: lock4 %d succeeded!\n", i);
1822                         return False;
1823                 }
1824         }
1825
1826         for (offset=i=0;i<torture_numops;i++) {
1827                 NEXT_OFFSET;
1828
1829                 status = cli_unlock(cli1, fnum1, offset-1, 1);
1830                 if (!NT_STATUS_IS_OK(status)) {
1831                         printf("unlock1 %d failed (%s)\n", 
1832                                i,
1833                                nt_errstr(status));
1834                         return False;
1835                 }
1836
1837                 status = cli_unlock(cli2, fnum2, offset-2, 1);
1838                 if (!NT_STATUS_IS_OK(status)) {
1839                         printf("unlock2 %d failed (%s)\n", 
1840                                i,
1841                                nt_errstr(status));
1842                         return False;
1843                 }
1844         }
1845
1846         status = cli_close(cli1, fnum1);
1847         if (!NT_STATUS_IS_OK(status)) {
1848                 printf("close1 failed (%s)\n", nt_errstr(status));
1849                 return False;
1850         }
1851
1852         status = cli_close(cli2, fnum2);
1853         if (!NT_STATUS_IS_OK(status)) {
1854                 printf("close2 failed (%s)\n", nt_errstr(status));
1855                 return False;
1856         }
1857
1858         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1859         if (!NT_STATUS_IS_OK(status)) {
1860                 printf("unlink failed (%s)\n", nt_errstr(status));
1861                 return False;
1862         }
1863
1864         if (!torture_close_connection(cli1)) {
1865                 correct = False;
1866         }
1867
1868         if (!torture_close_connection(cli2)) {
1869                 correct = False;
1870         }
1871
1872         printf("finished locktest3\n");
1873
1874         return correct;
1875 }
1876
1877 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1878                            char *buf, off_t offset, size_t size,
1879                            size_t *nread, size_t expect)
1880 {
1881         NTSTATUS status;
1882         size_t l_nread;
1883
1884         status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1885
1886         if(!NT_STATUS_IS_OK(status)) {
1887                 return false;
1888         } else if (l_nread != expect) {
1889                 return false;
1890         }
1891
1892         if (nread) {
1893                 *nread = l_nread;
1894         }
1895
1896         return true;
1897 }
1898
1899 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1900         printf("** "); correct = False; \
1901         }
1902
1903 /*
1904   looks at overlapping locks
1905 */
1906 static bool run_locktest4(int dummy)
1907 {
1908         static struct cli_state *cli1, *cli2;
1909         const char *fname = "\\lockt4.lck";
1910         uint16_t fnum1, fnum2, f;
1911         bool ret;
1912         char buf[1000];
1913         bool correct = True;
1914         NTSTATUS status;
1915
1916         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1917                 return False;
1918         }
1919
1920         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1921         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1922
1923         printf("starting locktest4\n");
1924
1925         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1926
1927         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1928         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1929
1930         memset(buf, 0, sizeof(buf));
1931
1932         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1933                               NULL);
1934         if (!NT_STATUS_IS_OK(status)) {
1935                 printf("Failed to create file: %s\n", nt_errstr(status));
1936                 correct = False;
1937                 goto fail;
1938         }
1939
1940         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1941               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1942         EXPECTED(ret, False);
1943         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1944
1945         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1946               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1947         EXPECTED(ret, True);
1948         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1949
1950         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1951               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1952         EXPECTED(ret, False);
1953         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1954
1955         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1956               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1957         EXPECTED(ret, True);
1958         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1959
1960         ret = (cli_setpid(cli1, 1),
1961               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1962               (cli_setpid(cli1, 2),
1963               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1964         EXPECTED(ret, False);
1965         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1966
1967         ret = (cli_setpid(cli1, 1),
1968               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1969               (cli_setpid(cli1, 2),
1970               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1971         EXPECTED(ret, True);
1972         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1973
1974         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1975               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1976         EXPECTED(ret, True);
1977         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1978
1979         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1980               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1981         EXPECTED(ret, False);
1982         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1983
1984         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1985               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1986         EXPECTED(ret, False);
1987         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1988
1989         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1990               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
1991         EXPECTED(ret, True);
1992         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1993
1994         ret = (cli_setpid(cli1, 1),
1995              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
1996              (cli_setpid(cli1, 2),
1997              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
1998         EXPECTED(ret, False);
1999         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2000
2001         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2002               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2003               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2004         EXPECTED(ret, False);
2005         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2006
2007
2008         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2009               test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2010         EXPECTED(ret, False);
2011         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2012
2013         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2014         ret = NT_STATUS_IS_OK(status);
2015         if (ret) {
2016                 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2017                                       NULL);
2018                 ret = NT_STATUS_IS_OK(status);
2019         }
2020         EXPECTED(ret, False);
2021         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2022
2023
2024         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2025               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2026               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2027               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2028         EXPECTED(ret, True);
2029         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2030
2031
2032         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2033               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2034               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2035               test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2036               !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2037                                              150, 4, NULL))) &&
2038               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2039         EXPECTED(ret, True);
2040         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2041
2042         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2043               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2044               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2045                                            160, 4, NULL)) &&
2046               test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2047         EXPECTED(ret, True);
2048         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2049
2050         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2051               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2052               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2053                                            170, 4, NULL)) &&
2054               test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2055         EXPECTED(ret, True);
2056         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2057
2058         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2059               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2060               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2061               !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2062                                             190, 4, NULL)) &&
2063               test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2064         EXPECTED(ret, True);
2065         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2066
2067         cli_close(cli1, fnum1);
2068         cli_close(cli2, fnum2);
2069         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2070         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2071         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2072               NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2073               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2074               NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2075               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2076         cli_close(cli1, f);
2077         cli_close(cli1, fnum1);
2078         EXPECTED(ret, True);
2079         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2080
2081  fail:
2082         cli_close(cli1, fnum1);
2083         cli_close(cli2, fnum2);
2084         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2085         torture_close_connection(cli1);
2086         torture_close_connection(cli2);
2087
2088         printf("finished locktest4\n");
2089         return correct;
2090 }
2091
2092 /*
2093   looks at lock upgrade/downgrade.
2094 */
2095 static bool run_locktest5(int dummy)
2096 {
2097         static struct cli_state *cli1, *cli2;
2098         const char *fname = "\\lockt5.lck";
2099         uint16_t fnum1, fnum2, fnum3;
2100         bool ret;
2101         char buf[1000];
2102         bool correct = True;
2103         NTSTATUS status;
2104
2105         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2106                 return False;
2107         }
2108
2109         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2110         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2111
2112         printf("starting locktest5\n");
2113
2114         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2115
2116         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2117         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2118         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2119
2120         memset(buf, 0, sizeof(buf));
2121
2122         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2123                               NULL);
2124         if (!NT_STATUS_IS_OK(status)) {
2125                 printf("Failed to create file: %s\n", nt_errstr(status));
2126                 correct = False;
2127                 goto fail;
2128         }
2129
2130         /* Check for NT bug... */
2131         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2132               NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2133         cli_close(cli1, fnum1);
2134         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2135         status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2136         ret = NT_STATUS_IS_OK(status);
2137         EXPECTED(ret, True);
2138         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2139         cli_close(cli1, fnum1);
2140         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2141         cli_unlock(cli1, fnum3, 0, 1);
2142
2143         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2144               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2145         EXPECTED(ret, True);
2146         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2147
2148         status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2149         ret = NT_STATUS_IS_OK(status);
2150         EXPECTED(ret, False);
2151
2152         printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2153
2154         /* Unlock the process 2 lock. */
2155         cli_unlock(cli2, fnum2, 0, 4);
2156
2157         status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2158         ret = NT_STATUS_IS_OK(status);
2159         EXPECTED(ret, False);
2160
2161         printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2162
2163         /* Unlock the process 1 fnum3 lock. */
2164         cli_unlock(cli1, fnum3, 0, 4);
2165
2166         /* Stack 2 more locks here. */
2167         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2168               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2169
2170         EXPECTED(ret, True);
2171         printf("the same process %s stack read locks\n", ret?"can":"cannot");
2172
2173         /* Unlock the first process lock, then check this was the WRITE lock that was
2174                 removed. */
2175
2176         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2177               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2178
2179         EXPECTED(ret, True);
2180         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2181
2182         /* Unlock the process 2 lock. */
2183         cli_unlock(cli2, fnum2, 0, 4);
2184
2185         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2186
2187         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2188                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2189                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2190
2191         EXPECTED(ret, True);
2192         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
2193
2194         /* Ensure the next unlock fails. */
2195         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2196         EXPECTED(ret, False);
2197         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
2198
2199         /* Ensure connection 2 can get a write lock. */
2200         status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2201         ret = NT_STATUS_IS_OK(status);
2202         EXPECTED(ret, True);
2203
2204         printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2205
2206
2207  fail:
2208         cli_close(cli1, fnum1);
2209         cli_close(cli2, fnum2);
2210         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2211         if (!torture_close_connection(cli1)) {
2212                 correct = False;
2213         }
2214         if (!torture_close_connection(cli2)) {
2215                 correct = False;
2216         }
2217
2218         printf("finished locktest5\n");
2219
2220         return correct;
2221 }
2222
2223 /*
2224   tries the unusual lockingX locktype bits
2225 */
2226 static bool run_locktest6(int dummy)
2227 {
2228         static struct cli_state *cli;
2229         const char *fname[1] = { "\\lock6.txt" };
2230         int i;
2231         uint16_t fnum;
2232         NTSTATUS status;
2233
2234         if (!torture_open_connection(&cli, 0)) {
2235                 return False;
2236         }
2237
2238         smbXcli_conn_set_sockopt(cli->conn, sockops);
2239
2240         printf("starting locktest6\n");
2241
2242         for (i=0;i<1;i++) {
2243                 printf("Testing %s\n", fname[i]);
2244
2245                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2246
2247                 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2248                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2249                 cli_close(cli, fnum);
2250                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2251
2252                 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2253                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2254                 cli_close(cli, fnum);
2255                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2256
2257                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2258         }
2259
2260         torture_close_connection(cli);
2261
2262         printf("finished locktest6\n");
2263         return True;
2264 }
2265
2266 static bool run_locktest7(int dummy)
2267 {
2268         struct cli_state *cli1;
2269         const char *fname = "\\lockt7.lck";
2270         uint16_t fnum1;
2271         char buf[200];
2272         bool correct = False;
2273         size_t nread;
2274         NTSTATUS status;
2275
2276         if (!torture_open_connection(&cli1, 0)) {
2277                 return False;
2278         }
2279
2280         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2281
2282         printf("starting locktest7\n");
2283
2284         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2285
2286         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2287
2288         memset(buf, 0, sizeof(buf));
2289
2290         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2291                               NULL);
2292         if (!NT_STATUS_IS_OK(status)) {
2293                 printf("Failed to create file: %s\n", nt_errstr(status));
2294                 goto fail;
2295         }
2296
2297         cli_setpid(cli1, 1);
2298
2299         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2300         if (!NT_STATUS_IS_OK(status)) {
2301                 printf("Unable to apply read lock on range 130:4, "
2302                        "error was %s\n", nt_errstr(status));
2303                 goto fail;
2304         } else {
2305                 printf("pid1 successfully locked range 130:4 for READ\n");
2306         }
2307
2308         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2309         if (!NT_STATUS_IS_OK(status)) {
2310                 printf("pid1 unable to read the range 130:4, error was %s\n",
2311                       nt_errstr(status));
2312                 goto fail;
2313         } else if (nread != 4) {
2314                 printf("pid1 unable to read the range 130:4, "
2315                        "recv %ld req %d\n", (unsigned long)nread, 4);
2316                 goto fail;
2317         } else {
2318                 printf("pid1 successfully read the range 130:4\n");
2319         }
2320
2321         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2322         if (!NT_STATUS_IS_OK(status)) {
2323                 printf("pid1 unable to write to the range 130:4, error was "
2324                        "%s\n", nt_errstr(status));
2325                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2326                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2327                         goto fail;
2328                 }
2329         } else {
2330                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2331                 goto fail;
2332         }
2333
2334         cli_setpid(cli1, 2);
2335
2336         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2337         if (!NT_STATUS_IS_OK(status)) {
2338                 printf("pid2 unable to read the range 130:4, error was %s\n",
2339                       nt_errstr(status));
2340                 goto fail;
2341         } else if (nread != 4) {
2342                 printf("pid2 unable to read the range 130:4, "
2343                        "recv %ld req %d\n", (unsigned long)nread, 4);
2344                 goto fail;
2345         } else {
2346                 printf("pid2 successfully read the range 130:4\n");
2347         }
2348
2349         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2350         if (!NT_STATUS_IS_OK(status)) {
2351                 printf("pid2 unable to write to the range 130:4, error was "
2352                        "%s\n", nt_errstr(status));
2353                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2354                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2355                         goto fail;
2356                 }
2357         } else {
2358                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2359                 goto fail;
2360         }
2361
2362         cli_setpid(cli1, 1);
2363         cli_unlock(cli1, fnum1, 130, 4);
2364
2365         status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2366         if (!NT_STATUS_IS_OK(status)) {
2367                 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2368                 goto fail;
2369         } else {
2370                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2371         }
2372
2373         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2374         if (!NT_STATUS_IS_OK(status)) {
2375                 printf("pid1 unable to read the range 130:4, error was %s\n",
2376                       nt_errstr(status));
2377                 goto fail;
2378         } else if (nread != 4) {
2379                 printf("pid1 unable to read the range 130:4, "
2380                        "recv %ld req %d\n", (unsigned long)nread, 4);
2381                 goto fail;
2382         } else {
2383                 printf("pid1 successfully read the range 130:4\n");
2384         }
2385
2386         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2387         if (!NT_STATUS_IS_OK(status)) {
2388                 printf("pid1 unable to write to the range 130:4, error was "
2389                        "%s\n", nt_errstr(status));
2390                 goto fail;
2391         } else {
2392                 printf("pid1 successfully wrote to the range 130:4\n");
2393         }
2394
2395         cli_setpid(cli1, 2);
2396
2397         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2398         if (!NT_STATUS_IS_OK(status)) {
2399                 printf("pid2 unable to read the range 130:4, error was "
2400                        "%s\n", nt_errstr(status));
2401                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2402                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2403                         goto fail;
2404                 }
2405         } else {
2406                 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2407                        (unsigned long)nread);
2408                 goto fail;
2409         }
2410
2411         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2412         if (!NT_STATUS_IS_OK(status)) {
2413                 printf("pid2 unable to write to the range 130:4, error was "
2414                        "%s\n", nt_errstr(status));
2415                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2416                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2417                         goto fail;
2418                 }
2419         } else {
2420                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2421                 goto fail;
2422         }
2423
2424         cli_unlock(cli1, fnum1, 130, 0);
2425         correct = True;
2426
2427 fail:
2428         cli_close(cli1, fnum1);
2429         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2430         torture_close_connection(cli1);
2431
2432         printf("finished locktest7\n");
2433         return correct;
2434 }
2435
2436 /*
2437  * This demonstrates a problem with our use of GPFS share modes: A file
2438  * descriptor sitting in the pending close queue holding a GPFS share mode
2439  * blocks opening a file another time. Happens with Word 2007 temp files.
2440  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2441  * open is denied with NT_STATUS_SHARING_VIOLATION.
2442  */
2443
2444 static bool run_locktest8(int dummy)
2445 {
2446         struct cli_state *cli1;
2447         const char *fname = "\\lockt8.lck";
2448         uint16_t fnum1, fnum2;
2449         char buf[200];
2450         bool correct = False;
2451         NTSTATUS status;
2452
2453         if (!torture_open_connection(&cli1, 0)) {
2454                 return False;
2455         }
2456
2457         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2458
2459         printf("starting locktest8\n");
2460
2461         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2462
2463         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2464                           &fnum1);
2465         if (!NT_STATUS_IS_OK(status)) {
2466                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2467                 return false;
2468         }
2469
2470         memset(buf, 0, sizeof(buf));
2471
2472         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2473         if (!NT_STATUS_IS_OK(status)) {
2474                 d_fprintf(stderr, "cli_openx second time returned %s\n",
2475                           nt_errstr(status));
2476                 goto fail;
2477         }
2478
2479         status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2480         if (!NT_STATUS_IS_OK(status)) {
2481                 printf("Unable to apply read lock on range 1:1, error was "
2482                        "%s\n", nt_errstr(status));
2483                 goto fail;
2484         }
2485
2486         status = cli_close(cli1, fnum1);
2487         if (!NT_STATUS_IS_OK(status)) {
2488                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2489                 goto fail;
2490         }
2491
2492         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2493         if (!NT_STATUS_IS_OK(status)) {
2494                 d_fprintf(stderr, "cli_openx third time returned %s\n",
2495                           nt_errstr(status));
2496                 goto fail;
2497         }
2498
2499         correct = true;
2500
2501 fail:
2502         cli_close(cli1, fnum1);
2503         cli_close(cli1, fnum2);
2504         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2505         torture_close_connection(cli1);
2506
2507         printf("finished locktest8\n");
2508         return correct;
2509 }
2510
2511 /*
2512  * This test is designed to be run in conjunction with
2513  * external NFS or POSIX locks taken in the filesystem.
2514  * It checks that the smbd server will block until the
2515  * lock is released and then acquire it. JRA.
2516  */
2517
2518 static bool got_alarm;
2519 static struct cli_state *alarm_cli;
2520
2521 static void alarm_handler(int dummy)
2522 {
2523         got_alarm = True;
2524 }
2525
2526 static void alarm_handler_parent(int dummy)
2527 {
2528         smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2529 }
2530
2531 static void do_local_lock(const char *fname, int read_fd, int write_fd)
2532 {
2533         int fd;
2534         char c = '\0';
2535         struct flock lock;
2536         const char *local_pathname = NULL;
2537         int ret;
2538
2539         local_pathname = talloc_asprintf(talloc_tos(),
2540                         "%s/%s", local_path, fname);
2541         if (!local_pathname) {
2542                 printf("child: alloc fail\n");
2543                 exit(1);
2544         }
2545
2546         unlink(local_pathname);
2547         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2548         if (fd == -1) {
2549                 printf("child: open of %s failed %s.\n",
2550                         local_pathname, strerror(errno));
2551                 exit(1);
2552         }
2553
2554         /* Now take a fcntl lock. */
2555         lock.l_type = F_WRLCK;
2556         lock.l_whence = SEEK_SET;
2557         lock.l_start = 0;
2558         lock.l_len = 4;
2559         lock.l_pid = getpid();
2560
2561         ret = fcntl(fd,F_SETLK,&lock);
2562         if (ret == -1) {
2563                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2564                         local_pathname, strerror(errno));
2565                 exit(1);
2566         } else {
2567                 printf("child: got lock 0:4 on file %s.\n",
2568                         local_pathname );
2569                 fflush(stdout);
2570         }
2571
2572         CatchSignal(SIGALRM, alarm_handler);
2573         alarm(5);
2574         /* Signal the parent. */
2575         if (write(write_fd, &c, 1) != 1) {
2576                 printf("child: start signal fail %s.\n",
2577                         strerror(errno));
2578                 exit(1);
2579         }
2580         alarm(0);
2581
2582         alarm(10);
2583         /* Wait for the parent to be ready. */
2584         if (read(read_fd, &c, 1) != 1) {
2585                 printf("child: reply signal fail %s.\n",
2586                         strerror(errno));
2587                 exit(1);
2588         }
2589         alarm(0);
2590
2591         sleep(5);
2592         close(fd);
2593         printf("child: released lock 0:4 on file %s.\n",
2594                 local_pathname );
2595         fflush(stdout);
2596         exit(0);
2597 }
2598
2599 static bool _run_locktest9X(const char *fname, int timeout)
2600 {
2601         struct cli_state *cli1;
2602         char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2603         uint16_t fnum;
2604         bool correct = False;
2605         int pipe_in[2], pipe_out[2];
2606         pid_t child_pid;
2607         char c = '\0';
2608         int ret;
2609         struct timeval start;
2610         double seconds;
2611         NTSTATUS status;
2612
2613         printf("starting locktest9X: %s\n", fname);
2614
2615         if (local_path == NULL) {
2616                 d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2617                 return false;
2618         }
2619
2620         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2621                 return false;
2622         }
2623
2624         child_pid = fork();
2625         if (child_pid == -1) {
2626                 return false;
2627         }
2628
2629         if (child_pid == 0) {
2630                 /* Child. */
2631                 do_local_lock(fname, pipe_out[0], pipe_in[1]);
2632                 exit(0);
2633         }
2634
2635         close(pipe_out[0]);
2636         close(pipe_in[1]);
2637         pipe_out[0] = -1;
2638         pipe_in[1] = -1;
2639
2640         /* Parent. */
2641         ret = read(pipe_in[0], &c, 1);
2642         if (ret != 1) {
2643                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2644                         strerror(errno));
2645                 return false;
2646         }
2647
2648         if (!torture_open_connection(&cli1, 0)) {
2649                 return false;
2650         }
2651
2652         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2653
2654         status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2655                           &fnum);
2656         if (!NT_STATUS_IS_OK(status)) {
2657                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2658                 return false;
2659         }
2660
2661         /* Ensure the child has the lock. */
2662         status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2663         if (NT_STATUS_IS_OK(status)) {
2664                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2665                 goto fail;
2666         } else {
2667                 d_printf("Child has the lock.\n");
2668         }
2669
2670         /* Tell the child to wait 5 seconds then exit. */
2671         ret = write(pipe_out[1], &c, 1);
2672         if (ret != 1) {
2673                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2674                         strerror(errno));
2675                 goto fail;
2676         }
2677
2678         /* Wait 20 seconds for the lock. */
2679         alarm_cli = cli1;
2680         CatchSignal(SIGALRM, alarm_handler_parent);
2681         alarm(20);
2682
2683         start = timeval_current();
2684
2685         status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2686         if (!NT_STATUS_IS_OK(status)) {
2687                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2688                        "%s\n", nt_errstr(status));
2689                 goto fail_nofd;
2690         }
2691         alarm(0);
2692
2693         seconds = timeval_elapsed(&start);
2694
2695         printf("Parent got the lock after %.2f seconds.\n",
2696                 seconds);
2697
2698         status = cli_close(cli1, fnum);
2699         if (!NT_STATUS_IS_OK(status)) {
2700                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2701                 goto fail;
2702         }
2703
2704         correct = true;
2705
2706 fail:
2707         cli_close(cli1, fnum);
2708         torture_close_connection(cli1);
2709
2710 fail_nofd:
2711
2712         printf("finished locktest9X: %s\n", fname);
2713         return correct;
2714 }
2715
2716 static bool run_locktest9a(int dummy)
2717 {
2718         return _run_locktest9X("lock9a.dat", -1);
2719 }
2720
2721 static bool run_locktest9b(int dummy)
2722 {
2723         return _run_locktest9X("lock9b.dat", 10000);
2724 }
2725
2726 struct locktest10_state {
2727         bool ok;
2728         bool done;
2729 };
2730
2731 static void locktest10_lockingx_done(struct tevent_req *subreq);
2732 static void locktest10_read_andx_done(struct tevent_req *subreq);
2733
2734 static bool run_locktest10(int dummy)
2735 {
2736         struct tevent_context *ev = NULL;
2737         struct cli_state *cli1 = NULL;
2738         struct cli_state *cli2 = NULL;
2739         struct smb1_lock_element lck = { 0 };
2740         struct tevent_req *reqs[2] = { NULL };
2741         struct tevent_req *smbreqs[2] = { NULL };
2742         const char fname[] = "\\lockt10.lck";
2743         uint16_t fnum1, fnum2;
2744         bool ret = false;
2745         bool ok;
2746         uint8_t data = 1;
2747         struct locktest10_state state = { .ok = true };
2748         NTSTATUS status;
2749
2750         printf("starting locktest10\n");
2751
2752         ev = samba_tevent_context_init(NULL);
2753         if (ev == NULL) {
2754                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2755                 goto done;
2756         }
2757
2758         ok = torture_open_connection(&cli1, 0);
2759         if (!ok) {
2760                 goto done;
2761         }
2762         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2763
2764         ok = torture_open_connection(&cli2, 1);
2765         if (!ok) {
2766                 goto done;
2767         }
2768         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2769
2770         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2771         if (!NT_STATUS_IS_OK(status)) {
2772                 d_fprintf(stderr,
2773                           "cli_openx failed: %s\n",
2774                           nt_errstr(status));
2775                 goto done;
2776         }
2777
2778         status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2779         if (!NT_STATUS_IS_OK(status)) {
2780                 d_fprintf(stderr,
2781                           "cli_writeall failed: %s\n",
2782                           nt_errstr(status));
2783                 goto done;
2784         }
2785
2786         status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2787         if (!NT_STATUS_IS_OK(status)) {
2788                 d_fprintf(stderr,
2789                           "cli_openx failed: %s\n",
2790                           nt_errstr(status));
2791                 goto done;
2792         }
2793
2794         status = cli_locktype(
2795                 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2796         if (!NT_STATUS_IS_OK(status)) {
2797                 d_fprintf(stderr,
2798                           "cli_locktype failed: %s\n",
2799                           nt_errstr(status));
2800                 goto done;
2801         }
2802
2803         lck = (struct smb1_lock_element) {
2804                 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2805         };
2806
2807         reqs[0] = cli_lockingx_create(
2808                 ev,                             /* mem_ctx */
2809                 ev,                             /* tevent_context */
2810                 cli1,                           /* cli */
2811                 fnum1,                          /* fnum */
2812                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
2813                 0,                              /* newoplocklevel */
2814                 1,                              /* timeout */
2815                 0,                              /* num_unlocks */
2816                 NULL,                           /* unlocks */
2817                 1,                              /* num_locks */
2818                 &lck,                           /* locks */
2819                 &smbreqs[0]);                   /* psmbreq */
2820         if (reqs[0] == NULL) {
2821                 d_fprintf(stderr, "cli_lockingx_create failed\n");
2822                 goto done;
2823         }
2824         tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
2825
2826         reqs[1] = cli_read_andx_create(
2827                 ev,             /* mem_ctx */
2828                 ev,             /* ev */
2829                 cli1,           /* cli */
2830                 fnum1,          /* fnum */
2831                 0,              /* offset */
2832                 1,              /* size */
2833                 &smbreqs[1]);   /* psmbreq */
2834         if (reqs[1] == NULL) {
2835                 d_fprintf(stderr, "cli_read_andx_create failed\n");
2836                 goto done;
2837         }
2838         tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
2839
2840         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
2841         if (!NT_STATUS_IS_OK(status)) {
2842                 d_fprintf(stderr,
2843                           "smb1cli_req_chain_submit failed: %s\n",
2844                           nt_errstr(status));
2845                 goto done;
2846         }
2847
2848         while (!state.done) {
2849                 tevent_loop_once(ev);
2850         }
2851
2852         torture_close_connection(cli1);
2853
2854         if (state.ok) {
2855                 ret = true;
2856         }
2857 done:
2858         return ret;
2859 }
2860
2861 static void locktest10_lockingx_done(struct tevent_req *subreq)
2862 {
2863         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
2864         NTSTATUS status;
2865
2866         status = cli_lockingx_recv(subreq);
2867         TALLOC_FREE(subreq);
2868
2869         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2870                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
2871                 state->ok = false;
2872         }
2873 }
2874
2875 static void locktest10_read_andx_done(struct tevent_req *subreq)
2876 {
2877         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
2878         ssize_t received = -1;
2879         uint8_t *rcvbuf = NULL;
2880         NTSTATUS status;
2881
2882         status = cli_read_andx_recv(subreq, &received, &rcvbuf);
2883
2884         if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
2885                 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
2886                 state->ok = false;
2887         }
2888
2889         state->done = true;
2890         TALLOC_FREE(subreq);
2891 }
2892
2893 static bool run_locktest11(int dummy)
2894 {
2895         struct cli_state *cli1;
2896         const char *fname = "\\lockt11.lck";
2897         NTSTATUS status;
2898         uint16_t fnum;
2899         bool ret = false;
2900
2901         if (!torture_open_connection(&cli1, 0)) {
2902                 return false;
2903         }
2904
2905         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2906
2907         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2908
2909         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
2910         if (!NT_STATUS_IS_OK(status)) {
2911                 d_fprintf(stderr,
2912                           "cli_openx returned %s\n",
2913                           nt_errstr(status));
2914                 return false;
2915         }
2916
2917         /*
2918          * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
2919          * returns NT_STATUS_OK
2920          */
2921
2922         status = cli_lockingx(
2923                 cli1,                           /* cli */
2924                 fnum,                           /* fnum */
2925                 LOCKING_ANDX_CANCEL_LOCK,       /* typeoflock */
2926                 0,                              /* newoplocklevel */
2927                 0,                              /* timeout */
2928                 0,                              /* num_unlocks */
2929                 NULL,                           /* unlocks */
2930                 0,                              /* num_locks */
2931                 NULL);                          /* locks */
2932
2933         if (!NT_STATUS_IS_OK(status)) {
2934                 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
2935                 goto fail;
2936         }
2937
2938         ret = true;
2939 fail:
2940         cli_close(cli1, fnum);
2941         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2942
2943         return ret;
2944 }
2945
2946 struct deferred_close_state {
2947         struct tevent_context *ev;
2948         struct cli_state *cli;
2949         uint16_t fnum;
2950 };
2951
2952 static void deferred_close_waited(struct tevent_req *subreq);
2953 static void deferred_close_done(struct tevent_req *subreq);
2954
2955 static struct tevent_req *deferred_close_send(
2956         TALLOC_CTX *mem_ctx,
2957         struct tevent_context *ev,
2958         int wait_secs,
2959         struct cli_state *cli,
2960         uint16_t fnum)
2961 {
2962         struct tevent_req *req = NULL, *subreq = NULL;
2963         struct deferred_close_state *state = NULL;
2964         struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
2965
2966         req = tevent_req_create(
2967                 mem_ctx, &state, struct deferred_close_state);
2968         if (req == NULL) {
2969                 return NULL;
2970         }
2971         state->ev = ev;
2972         state->cli = cli;
2973         state->fnum = fnum;
2974
2975         subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
2976         if (tevent_req_nomem(subreq, req)) {
2977                 return tevent_req_post(req, ev);
2978         }
2979         tevent_req_set_callback(subreq, deferred_close_waited, req);
2980         return req;
2981 }
2982
2983 static void deferred_close_waited(struct tevent_req *subreq)
2984 {
2985         struct tevent_req *req = tevent_req_callback_data(
2986                 subreq, struct tevent_req);
2987         struct deferred_close_state *state = tevent_req_data(
2988                 req, struct deferred_close_state);
2989         bool ok;
2990
2991         ok = tevent_wakeup_recv(subreq);
2992         TALLOC_FREE(subreq);
2993         if (!ok) {
2994                 tevent_req_oom(req);
2995                 return;
2996         }
2997
2998         subreq = cli_close_send(state, state->ev, state->cli, state->fnum);
2999         if (tevent_req_nomem(subreq, req)) {
3000                 return;
3001         }
3002         tevent_req_set_callback(subreq, deferred_close_done, req);
3003 }
3004
3005 static void deferred_close_done(struct tevent_req *subreq)
3006 {
3007         NTSTATUS status = cli_close_recv(subreq);
3008         tevent_req_simple_finish_ntstatus(subreq, status);
3009 }
3010
3011 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3012 {
3013         return tevent_req_simple_recv_ntstatus(req);
3014 }
3015
3016 struct lockread_state {
3017         struct smb1_lock_element lck;
3018         struct tevent_req *reqs[2];
3019         struct tevent_req *smbreqs[2];
3020         NTSTATUS lock_status;
3021         NTSTATUS read_status;
3022         uint8_t *readbuf;
3023 };
3024
3025 static void lockread_lockingx_done(struct tevent_req *subreq);
3026 static void lockread_read_andx_done(struct tevent_req *subreq);
3027
3028 static struct tevent_req *lockread_send(
3029         TALLOC_CTX *mem_ctx,
3030         struct tevent_context *ev,
3031         struct cli_state *cli,
3032         uint16_t fnum)
3033 {
3034         struct tevent_req *req = NULL;
3035         struct lockread_state *state = NULL;
3036         NTSTATUS status;
3037
3038         req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3039         if (req == NULL) {
3040                 return NULL;
3041         }
3042
3043         state->lck = (struct smb1_lock_element) {
3044                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3045         };
3046
3047         state->reqs[0] = cli_lockingx_create(
3048                 ev,                             /* mem_ctx */
3049                 ev,                             /* tevent_context */
3050                 cli,                            /* cli */
3051                 fnum,                           /* fnum */
3052                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3053                 0,                              /* newoplocklevel */
3054                 10000,                          /* timeout */
3055                 0,                              /* num_unlocks */
3056                 NULL,                           /* unlocks */
3057                 1,                              /* num_locks */
3058                 &state->lck,                    /* locks */
3059                 &state->smbreqs[0]);            /* psmbreq */
3060         if (tevent_req_nomem(state->reqs[0], req)) {
3061                 return tevent_req_post(req, ev);
3062         }
3063         tevent_req_set_callback(
3064                 state->reqs[0], lockread_lockingx_done, req);
3065
3066         state->reqs[1] = cli_read_andx_create(
3067                 ev,             /* mem_ctx */
3068                 ev,             /* ev */
3069                 cli,            /* cli */
3070                 fnum,           /* fnum */
3071                 0,              /* offset */
3072                 1,              /* size */
3073                 &state->smbreqs[1]);    /* psmbreq */
3074         if (tevent_req_nomem(state->reqs[1], req)) {
3075                 return tevent_req_post(req, ev);
3076         }
3077         tevent_req_set_callback(
3078                 state->reqs[1], lockread_read_andx_done, req);
3079
3080         status = smb1cli_req_chain_submit(state->smbreqs, 2);
3081         if (tevent_req_nterror(req, status)) {
3082                 return tevent_req_post(req, ev);
3083         }
3084         return req;
3085 }
3086
3087 static void lockread_lockingx_done(struct tevent_req *subreq)
3088 {
3089         struct tevent_req *req = tevent_req_callback_data(
3090                 subreq, struct tevent_req);
3091         struct lockread_state *state = tevent_req_data(
3092                 req, struct lockread_state);
3093         state->lock_status = cli_lockingx_recv(subreq);
3094         TALLOC_FREE(subreq);
3095         d_fprintf(stderr,
3096                   "lockingx returned %s\n",
3097                   nt_errstr(state->lock_status));
3098 }
3099
3100 static void lockread_read_andx_done(struct tevent_req *subreq)
3101 {
3102         struct tevent_req *req = tevent_req_callback_data(
3103                 subreq, struct tevent_req);
3104         struct lockread_state *state = tevent_req_data(
3105                 req, struct lockread_state);
3106         ssize_t received = -1;
3107         uint8_t *rcvbuf = NULL;
3108
3109         state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3110
3111         d_fprintf(stderr,
3112                   "read returned %s\n",
3113                   nt_errstr(state->read_status));
3114
3115         if (!NT_STATUS_IS_OK(state->read_status)) {
3116                 TALLOC_FREE(subreq);
3117                 tevent_req_done(req);
3118                 return;
3119         }
3120
3121         if (received > 0) {
3122                 state->readbuf = talloc_memdup(state, rcvbuf, received);
3123                 TALLOC_FREE(subreq);
3124                 if (tevent_req_nomem(state->readbuf, req)) {
3125                         return;
3126                 }
3127         }
3128         TALLOC_FREE(subreq);
3129         tevent_req_done(req);
3130 }
3131
3132 static NTSTATUS lockread_recv(
3133         struct tevent_req *req,
3134         NTSTATUS *lock_status,
3135         NTSTATUS *read_status,
3136         TALLOC_CTX *mem_ctx,
3137         uint8_t **read_buf)
3138 {
3139         struct lockread_state *state = tevent_req_data(
3140                 req, struct lockread_state);
3141         NTSTATUS status;
3142
3143         if (tevent_req_is_nterror(req, &status)) {
3144                 return status;
3145         }
3146
3147         *lock_status = state->lock_status;
3148         *read_status = state->read_status;
3149         if (state->readbuf != NULL) {
3150                 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3151         } else {
3152                 *read_buf = NULL;
3153         }
3154
3155         return NT_STATUS_OK;
3156 }
3157
3158 struct lock12_state {
3159         uint8_t dummy;
3160 };
3161
3162 static void lock12_closed(struct tevent_req *subreq);
3163 static void lock12_read(struct tevent_req *subreq);
3164
3165 static struct tevent_req *lock12_send(
3166         TALLOC_CTX *mem_ctx,
3167         struct tevent_context *ev,
3168         struct cli_state *cli,
3169         uint16_t fnum1,
3170         uint16_t fnum2)
3171 {
3172         struct tevent_req *req = NULL, *subreq = NULL;
3173         struct lock12_state *state = NULL;
3174
3175         req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3176         if (req == NULL) {
3177                 return NULL;
3178         }
3179
3180         subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3181         if (tevent_req_nomem(subreq, req)) {
3182                 return tevent_req_post(req, ev);
3183         }
3184         tevent_req_set_callback(subreq, lock12_closed, req);
3185
3186         subreq = lockread_send(state, ev, cli, fnum2);
3187         if (tevent_req_nomem(subreq, req)) {
3188                 return tevent_req_post(req, ev);
3189         }
3190         tevent_req_set_callback(subreq, lock12_read, req);
3191
3192         return req;
3193 }
3194
3195 static void lock12_closed(struct tevent_req *subreq)
3196 {
3197         struct tevent_req *req = tevent_req_callback_data(
3198                 subreq, struct tevent_req);
3199         NTSTATUS status;
3200
3201         status = deferred_close_recv(subreq);
3202         TALLOC_FREE(subreq);
3203         DBG_DEBUG("close returned %s\n", nt_errstr(status));
3204         if (tevent_req_nterror(req, status)) {
3205                 return;
3206         }
3207 }
3208
3209 static void lock12_read(struct tevent_req *subreq)
3210 {
3211         struct tevent_req *req = tevent_req_callback_data(
3212                 subreq, struct tevent_req);
3213         struct lock12_state *state = tevent_req_data(
3214                 req, struct lock12_state);
3215         NTSTATUS status, lock_status, read_status;
3216         uint8_t *buf = NULL;
3217
3218         status = lockread_recv(
3219                 subreq, &lock_status, &read_status, state, &buf);
3220         TALLOC_FREE(subreq);
3221         if (tevent_req_nterror(req, status) ||
3222             tevent_req_nterror(req, lock_status) ||
3223             tevent_req_nterror(req, read_status)) {
3224                 return;
3225         }
3226         tevent_req_done(req);
3227 }
3228
3229 static NTSTATUS lock12_recv(struct tevent_req *req)
3230
3231 {
3232         NTSTATUS status;
3233
3234         if (tevent_req_is_nterror(req, &status)) {
3235                 return status;
3236         }
3237         return NT_STATUS_OK;
3238 }
3239
3240 static bool run_locktest12(int dummy)
3241 {
3242         struct tevent_context *ev = NULL;
3243         struct tevent_req *req = NULL;
3244         struct cli_state *cli = NULL;
3245         const char fname[] = "\\lockt12.lck";
3246         uint16_t fnum1, fnum2;
3247         bool ret = false;
3248         bool ok;
3249         uint8_t data = 1;
3250         NTSTATUS status;
3251
3252         printf("starting locktest12\n");
3253
3254         ev = samba_tevent_context_init(NULL);
3255         if (ev == NULL) {
3256                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3257                 goto done;
3258         }
3259
3260         ok = torture_open_connection(&cli, 0);
3261         if (!ok) {
3262                 goto done;
3263         }
3264         smbXcli_conn_set_sockopt(cli->conn, sockops);
3265
3266         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3267         if (!NT_STATUS_IS_OK(status)) {
3268                 d_fprintf(stderr,
3269                           "cli_openx failed: %s\n",
3270                           nt_errstr(status));
3271                 goto done;
3272         }
3273
3274         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3275         if (!NT_STATUS_IS_OK(status)) {
3276                 d_fprintf(stderr,
3277                           "cli_openx failed: %s\n",
3278                           nt_errstr(status));
3279                 goto done;
3280         }
3281
3282         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3283         if (!NT_STATUS_IS_OK(status)) {
3284                 d_fprintf(stderr,
3285                           "cli_writeall failed: %s\n",
3286                           nt_errstr(status));
3287                 goto done;
3288         }
3289
3290         status = cli_locktype(
3291                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3292         if (!NT_STATUS_IS_OK(status)) {
3293                 d_fprintf(stderr,
3294                           "cli_locktype failed: %s\n",
3295                           nt_errstr(status));
3296                 goto done;
3297         }
3298
3299         req = lock12_send(ev, ev, cli, fnum1, fnum2);
3300         if (req == NULL) {
3301                 d_fprintf(stderr, "lock12_send failed\n");
3302                 goto done;
3303         }
3304
3305         ok = tevent_req_poll_ntstatus(req, ev, &status);
3306         if (!ok) {
3307                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3308                 goto done;
3309         }
3310
3311         if (!NT_STATUS_IS_OK(status)) {
3312                 d_fprintf(stderr,
3313                           "tevent_req_poll_ntstatus returned %s\n",
3314                           nt_errstr(status));
3315                 goto done;
3316         }
3317
3318         status = lock12_recv(req);
3319         if (!NT_STATUS_IS_OK(status)) {
3320                 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3321                 goto done;
3322         }
3323
3324         ret = true;
3325 done:
3326         if (cli != NULL) {
3327                 torture_close_connection(cli);
3328         }
3329         return ret;
3330 }
3331
3332 struct lock_ntcancel_state {
3333         struct timeval start;
3334         struct smb1_lock_element lck;
3335         struct tevent_req *subreq;
3336 };
3337
3338 static void lock_ntcancel_waited(struct tevent_req *subreq);
3339 static void lock_ntcancel_done(struct tevent_req *subreq);
3340
3341 static struct tevent_req *lock_ntcancel_send(
3342         TALLOC_CTX *mem_ctx,
3343         struct tevent_context *ev,
3344         struct cli_state *cli,
3345         uint16_t fnum)
3346 {
3347         struct tevent_req *req = NULL, *subreq = NULL;
3348         struct lock_ntcancel_state *state = NULL;
3349
3350         req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3351         if (req == NULL) {
3352                 return NULL;
3353         }
3354         state->lck = (struct smb1_lock_element) {
3355                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3356         };
3357         state->start = timeval_current();
3358
3359         state->subreq = cli_lockingx_send(
3360                 state,                          /* mem_ctx */
3361                 ev,                             /* tevent_context */
3362                 cli,                            /* cli */
3363                 fnum,                           /* fnum */
3364                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3365                 0,                              /* newoplocklevel */
3366                 10000,                          /* timeout */
3367                 0,                              /* num_unlocks */
3368                 NULL,                           /* unlocks */
3369                 1,                              /* num_locks */
3370                 &state->lck);                   /* locks */
3371         if (tevent_req_nomem(state->subreq, req)) {
3372                 return tevent_req_post(req, ev);
3373         }
3374         tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3375
3376         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3377         if (tevent_req_nomem(subreq, req)) {
3378                 return tevent_req_post(req, ev);
3379         }
3380         tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3381         return req;
3382 }
3383
3384 static void lock_ntcancel_waited(struct tevent_req *subreq)
3385 {
3386         struct tevent_req *req = tevent_req_callback_data(
3387                 subreq, struct tevent_req);
3388         struct lock_ntcancel_state *state = tevent_req_data(
3389                 req, struct lock_ntcancel_state);
3390         bool ok;
3391
3392         ok = tevent_wakeup_recv(subreq);
3393         TALLOC_FREE(subreq);
3394         if (!ok) {
3395                 tevent_req_oom(req);
3396                 return;
3397         }
3398
3399         ok = tevent_req_cancel(state->subreq);
3400         if (!ok) {
3401                 d_fprintf(stderr, "Could not cancel subreq\n");
3402                 tevent_req_oom(req);
3403                 return;
3404         }
3405 }
3406
3407 static void lock_ntcancel_done(struct tevent_req *subreq)
3408 {
3409         struct tevent_req *req = tevent_req_callback_data(
3410                 subreq, struct tevent_req);
3411         struct lock_ntcancel_state *state = tevent_req_data(
3412                 req, struct lock_ntcancel_state);
3413         NTSTATUS status;
3414         double elapsed;
3415
3416         status = cli_lockingx_recv(subreq);
3417         TALLOC_FREE(subreq);
3418
3419         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3420                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3421                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3422                 return;
3423         }
3424
3425         elapsed = timeval_elapsed(&state->start);
3426
3427         if (elapsed > 3) {
3428                 d_printf("cli_lockingx was too slow, cancel did not work\n");
3429                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3430                 return;
3431         }
3432
3433         tevent_req_done(req);
3434 }
3435
3436 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3437 {
3438         return tevent_req_simple_recv_ntstatus(req);
3439 }
3440
3441 static bool run_locktest13(int dummy)
3442 {
3443         struct tevent_context *ev = NULL;
3444         struct tevent_req *req = NULL;
3445         struct cli_state *cli = NULL;
3446         const char fname[] = "\\lockt13.lck";
3447         uint16_t fnum1, fnum2;
3448         bool ret = false;
3449         bool ok;
3450         uint8_t data = 1;
3451         NTSTATUS status;
3452
3453         printf("starting locktest13\n");
3454
3455         ev = samba_tevent_context_init(NULL);
3456         if (ev == NULL) {
3457                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3458                 goto done;
3459         }
3460
3461         ok = torture_open_connection(&cli, 0);
3462         if (!ok) {
3463                 goto done;
3464         }
3465         smbXcli_conn_set_sockopt(cli->conn, sockops);
3466
3467         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3468         if (!NT_STATUS_IS_OK(status)) {
3469                 d_fprintf(stderr,
3470                           "cli_openx failed: %s\n",
3471                           nt_errstr(status));
3472                 goto done;
3473         }
3474
3475         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3476         if (!NT_STATUS_IS_OK(status)) {
3477                 d_fprintf(stderr,
3478                           "cli_openx failed: %s\n",
3479                           nt_errstr(status));
3480                 goto done;
3481         }
3482
3483         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3484         if (!NT_STATUS_IS_OK(status)) {
3485                 d_fprintf(stderr,
3486                           "cli_writeall failed: %s\n",
3487                           nt_errstr(status));
3488                 goto done;
3489         }
3490
3491         status = cli_locktype(
3492                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3493         if (!NT_STATUS_IS_OK(status)) {
3494                 d_fprintf(stderr,
3495                           "cli_locktype failed: %s\n",
3496                           nt_errstr(status));
3497                 goto done;
3498         }
3499
3500         req = lock_ntcancel_send(ev, ev, cli, fnum2);
3501         if (req == NULL) {
3502                 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3503                 goto done;
3504         }
3505
3506         ok = tevent_req_poll_ntstatus(req, ev, &status);
3507         if (!ok) {
3508                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3509                 goto done;
3510         }
3511
3512         if (!NT_STATUS_IS_OK(status)) {
3513                 d_fprintf(stderr,
3514                           "tevent_req_poll_ntstatus returned %s\n",
3515                           nt_errstr(status));
3516                 goto done;
3517         }
3518
3519         status = lock_ntcancel_recv(req);
3520         if (!NT_STATUS_IS_OK(status)) {
3521                 d_fprintf(stderr,
3522                           "lock_ntcancel returned %s\n",
3523                           nt_errstr(status));
3524                 goto done;
3525         }
3526
3527         ret = true;
3528 done:
3529         if (cli != NULL) {
3530                 torture_close_connection(cli);
3531         }
3532         return ret;
3533 }
3534
3535 /*
3536 test whether fnums and tids open on one VC are available on another (a major
3537 security hole)
3538 */
3539 static bool run_fdpasstest(int dummy)
3540 {
3541         struct cli_state *cli1, *cli2;
3542         const char *fname = "\\fdpass.tst";
3543         uint16_t fnum1;
3544         char buf[1024];
3545         NTSTATUS status;
3546
3547         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3548                 return False;
3549         }
3550         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3551         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3552
3553         printf("starting fdpasstest\n");
3554
3555         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3556
3557         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3558                           &fnum1);
3559         if (!NT_STATUS_IS_OK(status)) {
3560                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3561                 return False;
3562         }
3563
3564         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3565                               13, NULL);
3566         if (!NT_STATUS_IS_OK(status)) {
3567                 printf("write failed (%s)\n", nt_errstr(status));
3568                 return False;
3569         }
3570
3571         cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3572         cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3573         cli_setpid(cli2, cli_getpid(cli1));
3574
3575         if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3576                 printf("read succeeded! nasty security hole [%s]\n", buf);
3577                 return false;
3578         }
3579
3580         cli_close(cli1, fnum1);
3581         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3582
3583         torture_close_connection(cli1);
3584         torture_close_connection(cli2);
3585
3586         printf("finished fdpasstest\n");
3587         return True;
3588 }
3589
3590 static bool run_fdsesstest(int dummy)
3591 {
3592         struct cli_state *cli;
3593         uint16_t new_vuid;
3594         uint16_t saved_vuid;
3595         uint32_t new_cnum;
3596         uint32_t saved_cnum;
3597         const char *fname = "\\fdsess.tst";
3598         const char *fname1 = "\\fdsess1.tst";
3599         uint16_t fnum1;
3600         uint16_t fnum2;
3601         char buf[1024];
3602         bool ret = True;
3603         NTSTATUS status;
3604
3605         if (!torture_open_connection(&cli, 0))
3606                 return False;
3607         smbXcli_conn_set_sockopt(cli->conn, sockops);
3608
3609         if (!torture_cli_session_setup2(cli, &new_vuid))
3610                 return False;
3611
3612         saved_cnum = cli_state_get_tid(cli);
3613         if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3614                 return False;
3615         new_cnum = cli_state_get_tid(cli);
3616         cli_state_set_tid(cli, saved_cnum);
3617
3618         printf("starting fdsesstest\n");
3619
3620         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3621         cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3622
3623         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3624         if (!NT_STATUS_IS_OK(status)) {
3625                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3626                 return False;
3627         }
3628
3629         status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3630                               NULL);
3631         if (!NT_STATUS_IS_OK(status)) {
3632                 printf("write failed (%s)\n", nt_errstr(status));
3633                 return False;
3634         }
3635
3636         saved_vuid = cli_state_get_uid(cli);
3637         cli_state_set_uid(cli, new_vuid);
3638
3639         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3640                 printf("read succeeded with different vuid! "
3641                        "nasty security hole [%s]\n", buf);
3642                 ret = false;
3643         }
3644         /* Try to open a file with different vuid, samba cnum. */
3645         if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3646                 printf("create with different vuid, same cnum succeeded.\n");
3647                 cli_close(cli, fnum2);
3648                 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3649         } else {
3650                 printf("create with different vuid, same cnum failed.\n");
3651                 printf("This will cause problems with service clients.\n");
3652                 ret = False;
3653         }
3654
3655         cli_state_set_uid(cli, saved_vuid);
3656
3657         /* Try with same vuid, different cnum. */
3658         cli_state_set_tid(cli, new_cnum);
3659
3660         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3661                 printf("read succeeded with different cnum![%s]\n", buf);
3662                 ret = false;
3663         }
3664
3665         cli_state_set_tid(cli, saved_cnum);
3666         cli_close(cli, fnum1);
3667         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3668
3669         torture_close_connection(cli);
3670
3671         printf("finished fdsesstest\n");
3672         return ret;
3673 }
3674
3675 /*
3676   This test checks that 
3677
3678   1) the server does not allow an unlink on a file that is open
3679 */
3680 static bool run_unlinktest(int dummy)
3681 {
3682         struct cli_state *cli;
3683         const char *fname = "\\unlink.tst";
3684         uint16_t fnum;
3685         bool correct = True;
3686         NTSTATUS status;
3687
3688         if (!torture_open_connection(&cli, 0)) {
3689                 return False;
3690         }
3691
3692         smbXcli_conn_set_sockopt(cli->conn, sockops);
3693
3694         printf("starting unlink test\n");
3695
3696         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3697
3698         cli_setpid(cli, 1);
3699
3700         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3701         if (!NT_STATUS_IS_OK(status)) {
3702                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3703                 return False;
3704         }
3705
3706         status = cli_unlink(cli, fname,
3707                             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3708         if (NT_STATUS_IS_OK(status)) {
3709                 printf("error: server allowed unlink on an open file\n");
3710                 correct = False;
3711         } else {
3712                 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3713                                       NT_STATUS_SHARING_VIOLATION);
3714         }
3715
3716         cli_close(cli, fnum);
3717         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3718
3719         if (!torture_close_connection(cli)) {
3720                 correct = False;
3721         }
3722
3723         printf("unlink test finished\n");
3724
3725         return correct;
3726 }
3727
3728
3729 /*
3730 test how many open files this server supports on the one socket
3731 */
3732 static bool run_maxfidtest(int dummy)
3733 {
3734         struct cli_state *cli;
3735         fstring fname;
3736         uint16_t fnums[0x11000];
3737         int i;
3738         int retries=4;
3739         bool correct = True;
3740         NTSTATUS status;
3741
3742         cli = current_cli;
3743
3744         if (retries <= 0) {
3745                 printf("failed to connect\n");
3746                 return False;
3747         }
3748
3749         smbXcli_conn_set_sockopt(cli->conn, sockops);
3750
3751         for (i=0; i<0x11000; i++) {
3752                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3753                 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3754                                   &fnums[i]);
3755                 if (!NT_STATUS_IS_OK(status)) {
3756                         printf("open of %s failed (%s)\n", 
3757                                fname, nt_errstr(status));
3758                         printf("maximum fnum is %d\n", i);
3759                         break;
3760                 }
3761                 printf("%6d\r", i);
3762         }
3763         printf("%6d\n", i);
3764         i--;
3765
3766         printf("cleaning up\n");
3767         for (;i>=0;i--) {
3768                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3769                 cli_close(cli, fnums[i]);
3770
3771                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3772                 if (!NT_STATUS_IS_OK(status)) {
3773                         printf("unlink of %s failed (%s)\n", 
3774                                fname, nt_errstr(status));
3775                         correct = False;
3776                 }
3777                 printf("%6d\r", i);
3778         }
3779         printf("%6d\n", 0);
3780
3781         printf("maxfid test finished\n");
3782         if (!torture_close_connection(cli)) {
3783                 correct = False;
3784         }
3785         return correct;
3786 }
3787
3788 /* generate a random buffer */
3789 static void rand_buf(char *buf, int len)
3790 {
3791         while (len--) {
3792                 *buf = (char)sys_random();
3793                 buf++;
3794         }
3795 }
3796
3797 /* send smb negprot commands, not reading the response */
3798 static bool run_negprot_nowait(int dummy)
3799 {
3800         struct tevent_context *ev;
3801         int i;
3802         struct cli_state *cli;
3803         bool correct = True;
3804
3805         printf("starting negprot nowait test\n");
3806
3807         ev = samba_tevent_context_init(talloc_tos());
3808         if (ev == NULL) {
3809                 return false;
3810         }
3811
3812         if (!(cli = open_nbt_connection())) {
3813                 TALLOC_FREE(ev);
3814                 return False;
3815         }
3816
3817         for (i=0;i<50000;i++) {
3818                 struct tevent_req *req;
3819
3820                 req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
3821                                            PROTOCOL_CORE, PROTOCOL_NT1, 0);
3822                 if (req == NULL) {
3823                         TALLOC_FREE(ev);
3824                         return false;
3825                 }
3826                 if (!tevent_req_poll(req, ev)) {
3827                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3828                                   strerror(errno));
3829                         TALLOC_FREE(ev);
3830                         return false;
3831                 }
3832                 TALLOC_FREE(req);
3833         }
3834
3835         if (torture_close_connection(cli)) {
3836                 correct = False;
3837         }
3838
3839         printf("finished negprot nowait test\n");
3840
3841         return correct;
3842 }
3843
3844 /* send smb negprot commands, not reading the response */
3845 static bool run_bad_nbt_session(int dummy)
3846 {
3847         struct nmb_name called, calling;
3848         struct sockaddr_storage ss;
3849         NTSTATUS status;
3850         int fd;
3851         bool ret;
3852
3853         printf("starting bad nbt session test\n");
3854
3855         make_nmb_name(&calling, myname, 0x0);
3856         make_nmb_name(&called , host, 0x20);
3857
3858         if (!resolve_name(host, &ss, 0x20, true)) {
3859                 d_fprintf(stderr, "Could not resolve name %s\n", host);
3860                 return false;
3861         }
3862
3863         status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3864         if (!NT_STATUS_IS_OK(status)) {
3865                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3866                           nt_errstr(status));
3867                 return false;
3868         }
3869
3870         ret = cli_bad_session_request(fd, &calling, &called);
3871         close(fd);
3872         if (!ret) {
3873                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3874                           nt_errstr(status));
3875                 return false;
3876         }
3877
3878         printf("finished bad nbt session test\n");
3879         return true;
3880 }
3881
3882 /* send random IPC commands */
3883 static bool run_randomipc(int dummy)
3884 {
3885         char *rparam = NULL;
3886         char *rdata = NULL;
3887         unsigned int rdrcnt,rprcnt;
3888         char param[1024];
3889         int api, param_len, i;
3890         struct cli_state *cli;
3891         bool correct = True;
3892         int count = 50000;
3893
3894         printf("starting random ipc test\n");
3895
3896         if (!torture_open_connection(&cli, 0)) {
3897                 return False;
3898         }
3899
3900         for (i=0;i<count;i++) {
3901                 api = sys_random() % 500;
3902                 param_len = (sys_random() % 64);
3903
3904                 rand_buf(param, param_len);
3905
3906                 SSVAL(param,0,api); 
3907
3908                 cli_api(cli, 
3909                         param, param_len, 8,  
3910                         NULL, 0, CLI_BUFFER_SIZE,
3911                         &rparam, &rprcnt,     
3912                         &rdata, &rdrcnt);
3913                 if (i % 100 == 0) {
3914                         printf("%d/%d\r", i,count);
3915                 }
3916         }
3917         printf("%d/%d\n", i, count);
3918
3919         if (!torture_close_connection(cli)) {
3920                 correct = False;
3921         }
3922
3923         SAFE_FREE(rparam);
3924         SAFE_FREE(rdata);
3925
3926         printf("finished random ipc test\n");
3927
3928         return correct;
3929 }
3930
3931
3932
3933 static void browse_callback(const char *sname, uint32_t stype,
3934                             const char *comment, void *state)
3935 {
3936         printf("\t%20.20s %08x %s\n", sname, stype, comment);
3937 }
3938
3939
3940
3941 /*
3942   This test checks the browse list code
3943
3944 */
3945 static bool run_browsetest(int dummy)
3946 {
3947         static struct cli_state *cli;
3948         bool correct = True;
3949
3950         printf("starting browse test\n");
3951
3952         if (!torture_open_connection(&cli, 0)) {
3953                 return False;
3954         }
3955
3956         printf("domain list:\n");
3957         cli_NetServerEnum(cli, cli->server_domain, 
3958                           SV_TYPE_DOMAIN_ENUM,
3959                           browse_callback, NULL);
3960
3961         printf("machine list:\n");
3962         cli_NetServerEnum(cli, cli->server_domain, 
3963                           SV_TYPE_ALL,
3964                           browse_callback, NULL);
3965
3966         if (!torture_close_connection(cli)) {
3967                 correct = False;
3968         }
3969
3970         printf("browse test finished\n");
3971
3972         return correct;
3973
3974 }
3975
3976 static bool check_attributes(struct cli_state *cli,
3977                                 const char *fname,
3978                                 uint32_t expected_attrs)
3979 {
3980         uint32_t attrs = 0;
3981         NTSTATUS status = cli_getatr(cli,
3982                                 fname,
3983                                 &attrs,
3984                                 NULL,
3985                                 NULL);
3986         if (!NT_STATUS_IS_OK(status)) {
3987                 printf("cli_getatr failed with %s\n",
3988                         nt_errstr(status));
3989                 return false;
3990         }
3991         if (attrs != expected_attrs) {
3992                 printf("Attributes incorrect 0x%x, should be 0x%x\n",
3993                         (unsigned int)attrs,
3994                         (unsigned int)expected_attrs);
3995                 return false;
3996         }
3997         return true;
3998 }
3999
4000 /*
4001   This checks how the getatr calls works
4002 */
4003 static bool run_attrtest(int dummy)
4004 {
4005         struct cli_state *cli;
4006         uint16_t fnum;
4007         time_t t, t2;
4008         const char *fname = "\\attrib123456789.tst";
4009         bool correct = True;
4010         NTSTATUS status;
4011
4012         printf("starting attrib test\n");
4013
4014         if (!torture_open_connection(&cli, 0)) {
4015                 return False;
4016         }
4017
4018         /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4019         status = cli_unlink(cli, fname, 0x20000);
4020         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4021                 correct = false;
4022                 goto out;
4023         }
4024
4025         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4026         cli_openx(cli, fname, 
4027                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4028         cli_close(cli, fnum);
4029
4030         status = cli_getatr(cli, fname, NULL, NULL, &t);
4031         if (!NT_STATUS_IS_OK(status)) {
4032                 printf("getatr failed (%s)\n", nt_errstr(status));
4033                 correct = False;
4034         }
4035
4036         if (labs(t - time(NULL)) > 60*60*24*10) {
4037                 printf("ERROR: SMBgetatr bug. time is %s",
4038                        ctime(&t));
4039                 t = time(NULL);
4040                 correct = True;
4041         }
4042
4043         t2 = t-60*60*24; /* 1 day ago */
4044
4045         /* Ensure we can't set with out-of-range (unknown) attribute. */
4046         status = cli_setatr(cli, fname, 0x20000, t2);
4047         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4048                 correct = false;
4049                 goto out;
4050         }
4051
4052         status = cli_setatr(cli, fname, 0, t2);
4053         if (!NT_STATUS_IS_OK(status)) {
4054                 printf("setatr failed (%s)\n", nt_errstr(status));
4055                 correct = True;
4056         }
4057
4058         status = cli_getatr(cli, fname, NULL, NULL, &t);
4059         if (!NT_STATUS_IS_OK(status)) {
4060                 printf("getatr failed (%s)\n", nt_errstr(status));
4061                 correct = True;
4062         }
4063
4064         if (t != t2) {
4065                 printf("ERROR: getatr/setatr bug. times are\n%s",
4066                        ctime(&t));
4067                 printf("%s", ctime(&t2));
4068                 correct = True;
4069         }
4070
4071         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4072
4073         /* Check cli_setpathinfo_ext() */
4074         /* Re-create the file. */
4075         status = cli_openx(cli, fname,
4076                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4077         if (!NT_STATUS_IS_OK(status)) {
4078                 printf("Failed to recreate %s (%s)\n",
4079                         fname, nt_errstr(status));
4080                 correct = false;
4081         }
4082         cli_close(cli, fnum);
4083
4084         status = cli_setpathinfo_ext(
4085                 cli,
4086                 fname,
4087                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4088                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4089                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4090                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4091                 FILE_ATTRIBUTE_SYSTEM |
4092                 FILE_ATTRIBUTE_HIDDEN |
4093                 FILE_ATTRIBUTE_READONLY);
4094         if (!NT_STATUS_IS_OK(status)) {
4095                 printf("cli_setpathinfo_ext 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_ext(
4112                 cli,
4113                 fname,
4114                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4115                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4116                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4117                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4118                 FILE_ATTRIBUTE_NORMAL);
4119         if (!NT_STATUS_IS_OK(status)) {
4120                 printf("cli_setpathinfo_ext failed with %s\n",
4121                         nt_errstr(status));
4122                 correct = false;
4123         }
4124
4125         /* Check attributes are correct. */
4126         correct = check_attributes(cli,
4127                         fname,
4128                         FILE_ATTRIBUTE_SYSTEM |
4129                         FILE_ATTRIBUTE_HIDDEN |
4130                         FILE_ATTRIBUTE_READONLY);
4131         if (correct == false) {
4132                 goto out;
4133         }
4134
4135         /* Setting to (uint16_t)-1 should also be ignored. */
4136         status = cli_setpathinfo_ext(
4137                 cli,
4138                 fname,
4139                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4140                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4141                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4142                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4143                 (uint32_t)-1);
4144         if (!NT_STATUS_IS_OK(status)) {
4145                 printf("cli_setpathinfo_ext failed with %s\n",
4146                         nt_errstr(status));
4147                 correct = false;
4148         }
4149
4150         /* Check attributes are correct. */
4151         correct = check_attributes(cli,
4152                         fname,
4153                         FILE_ATTRIBUTE_SYSTEM |
4154                         FILE_ATTRIBUTE_HIDDEN |
4155                         FILE_ATTRIBUTE_READONLY);
4156         if (correct == false) {
4157                 goto out;
4158         }
4159
4160         /* Setting to 0 should clear them all. */
4161         status = cli_setpathinfo_ext(
4162                 cli,
4163                 fname,
4164                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4165                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4166                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4167                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4168                 0);
4169         if (!NT_STATUS_IS_OK(status)) {
4170                 printf("cli_setpathinfo_ext failed with %s\n",
4171                         nt_errstr(status));
4172                 correct = false;
4173         }
4174
4175         /* Check attributes are correct. */
4176         correct = check_attributes(cli,
4177                         fname,
4178                         FILE_ATTRIBUTE_NORMAL);
4179         if (correct == false) {
4180                 goto out;
4181         }
4182
4183   out:
4184
4185         cli_unlink(cli,
4186                 fname,
4187                 FILE_ATTRIBUTE_SYSTEM |
4188                 FILE_ATTRIBUTE_HIDDEN|
4189                 FILE_ATTRIBUTE_READONLY);
4190
4191         if (!torture_close_connection(cli)) {
4192                 correct = False;
4193         }
4194
4195         printf("attrib test finished\n");
4196
4197         return correct;
4198 }
4199
4200
4201 /*
4202   This checks a couple of trans2 calls
4203 */
4204 static bool run_trans2test(int dummy)
4205 {
4206         struct cli_state *cli;
4207         uint16_t fnum;
4208         off_t size;
4209         time_t c_time, a_time, m_time;
4210         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4211         const char *fname = "\\trans2.tst";
4212         const char *dname = "\\trans2";
4213         const char *fname2 = "\\trans2\\trans2.tst";
4214         char *pname;
4215         bool correct = True;
4216         NTSTATUS status;
4217         uint32_t fs_attr;
4218         uint64_t ino;
4219
4220         printf("starting trans2 test\n");
4221
4222         if (!torture_open_connection(&cli, 0)) {
4223                 return False;
4224         }
4225
4226         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4227                 /* Ensure ino is zero, SMB2 gets a real one. */
4228                 ino = 0;
4229         } else {
4230                 /* Ensure ino is -1, SMB1 never gets a real one. */
4231                 ino = (uint64_t)-1;
4232         }
4233
4234         status = cli_get_fs_attr_info(cli, &fs_attr);
4235         if (!NT_STATUS_IS_OK(status)) {
4236                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4237                        nt_errstr(status));
4238                 correct = false;
4239         }
4240
4241         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4242         cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4243         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4244                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4245         if (!NT_STATUS_IS_OK(status)) {
4246                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4247                 correct = False;
4248         }
4249
4250         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4251         if (!NT_STATUS_IS_OK(status)) {
4252                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4253                 correct = False;
4254         }
4255         else if (strcmp(pname, fname)) {
4256                 printf("qfilename gave different name? [%s] [%s]\n",
4257                        fname, pname);
4258                 correct = False;
4259         }
4260
4261         cli_close(cli, fnum);
4262
4263         sleep(2);
4264
4265         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4266         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4267                           &fnum);
4268         if (!NT_STATUS_IS_OK(status)) {
4269                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4270                 return False;
4271         }
4272         cli_close(cli, fnum);
4273
4274         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4275                                 NULL);
4276         if (!NT_STATUS_IS_OK(status)) {
4277                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4278                 correct = False;
4279         } else {
4280                 time_t t = time(NULL);
4281
4282                 if (c_time != m_time) {
4283                         printf("create time=%s", ctime(&c_time));
4284                         printf("modify time=%s", ctime(&m_time));
4285                         printf("This system appears to have sticky create times\n");
4286                 }
4287                 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4288                         printf("access time=%s", ctime(&a_time));
4289                         printf("This system appears to set a midnight access time\n");
4290                         correct = False;
4291                 }
4292
4293                 if (labs(m_time - t) > 60*60*24*7) {
4294                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4295                         correct = False;
4296                 }
4297         }
4298
4299
4300         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4301         cli_openx(cli, fname, 
4302                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4303         cli_close(cli, fnum);
4304         status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
4305                                 &m_time_ts, &size, NULL, &ino);
4306         if (!NT_STATUS_IS_OK(status)) {
4307                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4308                 correct = False;
4309         } else {
4310                 if (w_time_ts.tv_sec < 60*60*24*2) {
4311                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
4312                         printf("This system appears to set a initial 0 write time\n");
4313                         correct = False;
4314                 }
4315                 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4316                         /* SMB2 should always return an inode. */
4317                         if (ino == 0) {
4318                                 printf("SMB2 bad inode (0)\n");
4319                                 correct = false;
4320                         }
4321                 } else {
4322                         /* SMB1 must always return zero here. */
4323                         if (ino != 0) {
4324                                 printf("SMB1 bad inode (!0)\n");
4325                                 correct = false;
4326                         }
4327                 }
4328         }
4329
4330         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4331
4332
4333         /* check if the server updates the directory modification time
4334            when creating a new file */
4335         status = cli_mkdir(cli, dname);
4336         if (!NT_STATUS_IS_OK(status)) {
4337                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4338                 correct = False;
4339         }
4340         sleep(3);
4341         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4342                                 &w_time_ts, &m_time_ts, &size, NULL, NULL);
4343         if (!NT_STATUS_IS_OK(status)) {
4344                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4345                 correct = False;
4346         }
4347
4348         cli_openx(cli, fname2, 
4349                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4350         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4351         cli_close(cli, fnum);
4352         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4353                                 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
4354         if (!NT_STATUS_IS_OK(status)) {
4355                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4356                 correct = False;
4357         } else {
4358                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4359                     == 0) {
4360                         printf("This system does not update directory modification times\n");
4361                         correct = False;
4362                 }
4363         }
4364         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4365         cli_rmdir(cli, dname);
4366
4367         if (!torture_close_connection(cli)) {
4368                 correct = False;
4369         }
4370
4371         printf("trans2 test finished\n");
4372
4373         return correct;
4374 }
4375
4376 /*
4377   This checks new W2K calls.
4378 */
4379
4380 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4381 {
4382         uint8_t *buf = NULL;
4383         uint32_t len;
4384         NTSTATUS status;
4385
4386         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4387                                CLI_BUFFER_SIZE, NULL, &buf, &len);
4388         if (!NT_STATUS_IS_OK(status)) {
4389                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4390                        nt_errstr(status));
4391         } else {
4392                 printf("qfileinfo: level %d, len = %u\n", level, len);
4393                 dump_data(0, (uint8_t *)buf, len);
4394                 printf("\n");
4395         }
4396         TALLOC_FREE(buf);
4397         return status;
4398 }
4399
4400 static bool run_w2ktest(int dummy)
4401 {
4402         struct cli_state *cli;
4403         uint16_t fnum;
4404         const char *fname = "\\w2ktest\\w2k.tst";
4405         int level;
4406         bool correct = True;
4407
4408         printf("starting w2k test\n");
4409
4410         if (!torture_open_connection(&cli, 0)) {
4411                 return False;
4412         }
4413
4414         cli_openx(cli, fname, 
4415                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
4416
4417         for (level = 1004; level < 1040; level++) {
4418                 new_trans(cli, fnum, level);
4419         }
4420
4421         cli_close(cli, fnum);
4422
4423         if (!torture_close_connection(cli)) {
4424                 correct = False;
4425         }
4426
4427         printf("w2k test finished\n");
4428
4429         return correct;
4430 }
4431
4432
4433 /*
4434   this is a harness for some oplock tests
4435  */
4436 static bool run_oplock1(int dummy)
4437 {
4438         struct cli_state *cli1;
4439         const char *fname = "\\lockt1.lck";
4440         uint16_t fnum1;
4441         bool correct = True;
4442         NTSTATUS status;
4443
4444         printf("starting oplock test 1\n");
4445
4446         if (!torture_open_connection(&cli1, 0)) {
4447                 return False;
4448         }
4449
4450         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4451
4452         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4453
4454         cli1->use_oplocks = True;
4455
4456         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4457                           &fnum1);
4458         if (!NT_STATUS_IS_OK(status)) {
4459                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4460                 return False;
4461         }
4462
4463         cli1->use_oplocks = False;
4464
4465         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4466         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4467
4468         status = cli_close(cli1, fnum1);
4469         if (!NT_STATUS_IS_OK(status)) {
4470                 printf("close2 failed (%s)\n", nt_errstr(status));
4471                 return False;
4472         }
4473
4474         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4475         if (!NT_STATUS_IS_OK(status)) {
4476                 printf("unlink failed (%s)\n", nt_errstr(status));
4477                 return False;
4478         }
4479
4480         if (!torture_close_connection(cli1)) {
4481                 correct = False;
4482         }
4483
4484         printf("finished oplock test 1\n");
4485
4486         return correct;
4487 }
4488
4489 static bool run_oplock2(int dummy)
4490 {
4491         struct cli_state *cli1, *cli2;
4492         const char *fname = "\\lockt2.lck";
4493         uint16_t fnum1, fnum2;
4494         int saved_use_oplocks = use_oplocks;
4495         char buf[4];
4496         bool correct = True;
4497         volatile bool *shared_correct;
4498         size_t nread;
4499         NTSTATUS status;
4500
4501         shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4502         *shared_correct = True;
4503
4504         use_level_II_oplocks = True;
4505         use_oplocks = True;
4506
4507         printf("starting oplock test 2\n");
4508
4509         if (!torture_open_connection(&cli1, 0)) {
4510                 use_level_II_oplocks = False;
4511                 use_oplocks = saved_use_oplocks;
4512                 return False;
4513         }
4514
4515         if (!torture_open_connection(&cli2, 1)) {
4516                 use_level_II_oplocks = False;
4517                 use_oplocks = saved_use_oplocks;
4518                 return False;
4519         }
4520
4521         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4522
4523         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4524         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4525
4526         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4527                           &fnum1);
4528         if (!NT_STATUS_IS_OK(status)) {
4529                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4530                 return False;
4531         }
4532
4533         /* Don't need the globals any more. */
4534         use_level_II_oplocks = False;
4535         use_oplocks = saved_use_oplocks;
4536
4537         if (fork() == 0) {
4538                 /* Child code */
4539                 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4540                 if (!NT_STATUS_IS_OK(status)) {
4541                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4542                         *shared_correct = False;
4543                         exit(0);
4544                 }
4545
4546                 sleep(2);
4547
4548                 status = cli_close(cli2, fnum2);
4549                 if (!NT_STATUS_IS_OK(status)) {
4550                         printf("close2 failed (%s)\n", nt_errstr(status));
4551                         *shared_correct = False;
4552                 }
4553
4554                 exit(0);
4555         }
4556
4557         sleep(2);
4558
4559         /* Ensure cli1 processes the break. Empty file should always return 0
4560          * bytes.  */
4561         status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4562         if (!NT_STATUS_IS_OK(status)) {
4563                 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4564                 correct = false;
4565         } else if (nread != 0) {
4566                 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4567                       (unsigned long)nread, 0);
4568                 correct = false;
4569         }
4570
4571         /* Should now be at level II. */
4572         /* Test if sending a write locks causes a break to none. */
4573         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4574         if (!NT_STATUS_IS_OK(status)) {
4575                 printf("lock failed (%s)\n", nt_errstr(status));
4576                 correct = False;
4577         }
4578
4579         cli_unlock(cli1, fnum1, 0, 4);
4580
4581         sleep(2);
4582
4583         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4584         if (!NT_STATUS_IS_OK(status)) {
4585                 printf("lock failed (%s)\n", nt_errstr(status));
4586                 correct = False;
4587         }
4588
4589         cli_unlock(cli1, fnum1, 0, 4);
4590
4591         sleep(2);
4592
4593         cli_read(cli1, fnum1, buf, 0, 4, NULL);
4594
4595         status = cli_close(cli1, fnum1);
4596         if (!NT_STATUS_IS_OK(status)) {
4597                 printf("close1 failed (%s)\n", nt_errstr(status));
4598                 correct = False;
4599         }
4600
4601         sleep(4);
4602
4603         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4604         if (!NT_STATUS_IS_OK(status)) {
4605                 printf("unlink failed (%s)\n", nt_errstr(status));
4606                 correct = False;
4607         }
4608
4609         if (!torture_close_connection(cli1)) {
4610                 correct = False;
4611         }
4612
4613         if (!*shared_correct) {
4614                 correct = False;
4615         }
4616
4617         printf("finished oplock test 2\n");
4618
4619         return correct;
4620 }
4621
4622 struct oplock4_state {
4623         struct tevent_context *ev;
4624         struct cli_state *cli;
4625         bool *got_break;
4626         uint16_t *fnum2;
4627 };
4628
4629 static void oplock4_got_break(struct tevent_req *req);
4630 static void oplock4_got_open(struct tevent_req *req);
4631
4632 static bool run_oplock4(int dummy)
4633 {
4634         struct tevent_context *ev;
4635         struct cli_state *cli1, *cli2;
4636         struct tevent_req *oplock_req, *open_req;
4637         const char *fname = "\\lockt4.lck";
4638         const char *fname_ln = "\\lockt4_ln.lck";
4639         uint16_t fnum1, fnum2;
4640         int saved_use_oplocks = use_oplocks;
4641         NTSTATUS status;
4642         bool correct = true;
4643
4644         bool got_break;
4645
4646         struct oplock4_state *state;
4647
4648         printf("starting oplock test 4\n");
4649
4650         if (!torture_open_connection(&cli1, 0)) {
4651                 use_level_II_oplocks = false;
4652                 use_oplocks = saved_use_oplocks;
4653                 return false;
4654         }
4655
4656         if (!torture_open_connection(&cli2, 1)) {
4657                 use_level_II_oplocks = false;
4658                 use_oplocks = saved_use_oplocks;
4659                 return false;
4660         }
4661
4662         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4663         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4664
4665         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4666         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4667
4668         /* Create the file. */
4669         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4670                           &fnum1);
4671         if (!NT_STATUS_IS_OK(status)) {
4672                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4673                 return false;
4674         }
4675
4676         status = cli_close(cli1, fnum1);
4677         if (!NT_STATUS_IS_OK(status)) {
4678                 printf("close1 failed (%s)\n", nt_errstr(status));
4679                 return false;
4680         }
4681
4682         /* Now create a hardlink. */
4683         status = cli_hardlink(cli1, fname, fname_ln);
4684         if (!NT_STATUS_IS_OK(status)) {
4685                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4686                 return false;
4687         }
4688
4689         /* Prove that opening hardlinks cause deny modes to conflict. */
4690         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4691         if (!NT_STATUS_IS_OK(status)) {
4692                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4693                 return false;
4694         }
4695
4696         status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4697         if (NT_STATUS_IS_OK(status)) {
4698                 printf("open of %s succeeded - should fail with sharing violation.\n",
4699                         fname_ln);
4700                 return false;
4701         }
4702
4703         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4704                 printf("open of %s should fail with sharing violation. Got %s\n",
4705                         fname_ln, nt_errstr(status));
4706                 return false;
4707         }
4708
4709         status = cli_close(cli1, fnum1);
4710         if (!NT_STATUS_IS_OK(status)) {
4711                 printf("close1 failed (%s)\n", nt_errstr(status));
4712                 return false;
4713         }
4714
4715         cli1->use_oplocks = true;
4716         cli2->use_oplocks = true;
4717
4718         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4719         if (!NT_STATUS_IS_OK(status)) {
4720                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4721                 return false;
4722         }
4723
4724         ev = samba_tevent_context_init(talloc_tos());
4725         if (ev == NULL) {
4726                 printf("tevent_context_init failed\n");
4727                 return false;
4728         }
4729
4730         state = talloc(ev, struct oplock4_state);
4731         if (state == NULL) {
4732                 printf("talloc failed\n");
4733                 return false;
4734         }
4735         state->ev = ev;
4736         state->cli = cli1;
4737         state->got_break = &got_break;
4738         state->fnum2 = &fnum2;
4739
4740         oplock_req = cli_smb_oplock_break_waiter_send(
4741                 talloc_tos(), ev, cli1);
4742         if (oplock_req == NULL) {
4743                 printf("cli_smb_oplock_break_waiter_send failed\n");
4744                 return false;
4745         }
4746         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
4747
4748         open_req = cli_openx_send(
4749                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
4750         if (open_req == NULL) {
4751                 printf("cli_openx_send failed\n");
4752                 return false;
4753         }
4754         tevent_req_set_callback(open_req, oplock4_got_open, state);
4755
4756         got_break = false;
4757         fnum2 = 0xffff;
4758
4759         while (!got_break || fnum2 == 0xffff) {
4760                 int ret;
4761                 ret = tevent_loop_once(ev);
4762                 if (ret == -1) {
4763                         printf("tevent_loop_once failed: %s\n",
4764                                strerror(errno));
4765                         return false;
4766                 }
4767         }
4768
4769         status = cli_close(cli2, fnum2);
4770         if (!NT_STATUS_IS_OK(status)) {
4771                 printf("close2 failed (%s)\n", nt_errstr(status));
4772                 correct = false;
4773         }
4774
4775         status = cli_close(cli1, fnum1);
4776         if (!NT_STATUS_IS_OK(status)) {
4777                 printf("close1 failed (%s)\n", nt_errstr(status));
4778                 correct = false;
4779         }
4780
4781         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4782         if (!NT_STATUS_IS_OK(status)) {
4783                 printf("unlink failed (%s)\n", nt_errstr(status));
4784                 correct = false;
4785         }
4786
4787         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4788         if (!NT_STATUS_IS_OK(status)) {
4789                 printf("unlink failed (%s)\n", nt_errstr(status));
4790                 correct = false;
4791         }
4792
4793         if (!torture_close_connection(cli1)) {
4794                 correct = false;
4795         }
4796
4797         if (!got_break) {
4798                 correct = false;
4799         }
4800
4801         printf("finished oplock test 4\n");
4802
4803         return correct;
4804 }
4805
4806 static void oplock4_got_break(struct tevent_req *req)
4807 {
4808         struct oplock4_state *state = tevent_req_callback_data(
4809                 req, struct oplock4_state);
4810         uint16_t fnum;
4811         uint8_t level;
4812         NTSTATUS status;
4813
4814         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
4815         TALLOC_FREE(req);
4816         if (!NT_STATUS_IS_OK(status)) {
4817                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
4818                        nt_errstr(status));
4819                 return;
4820         }
4821         *state->got_break = true;
4822
4823         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
4824                                   NO_OPLOCK);
4825         if (req == NULL) {
4826                 printf("cli_oplock_ack_send failed\n");
4827                 return;
4828         }
4829 }
4830
4831 static void oplock4_got_open(struct tevent_req *req)
4832 {
4833         struct oplock4_state *state = tevent_req_callback_data(
4834                 req, struct oplock4_state);
4835         NTSTATUS status;
4836
4837         status = cli_openx_recv(req, state->fnum2);
4838         if (!NT_STATUS_IS_OK(status)) {
4839                 printf("cli_openx_recv returned %s\n", nt_errstr(status));
4840                 *state->fnum2 = 0xffff;
4841         }
4842 }
4843
4844 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
4845
4846 struct oplock5_state {
4847         int pipe_down_fd;
4848 };
4849
4850 /*
4851  * Async open the file that has a kernel oplock, do an echo to get
4852  * that 100% across, close the file to signal to the child fd that the
4853  * oplock can be dropped, wait for the open reply.
4854  */
4855
4856 static void oplock5_opened(struct tevent_req *subreq);
4857 static void oplock5_pong(struct tevent_req *subreq);
4858 static void oplock5_timedout(struct tevent_req *subreq);
4859
4860 static struct tevent_req *oplock5_send(
4861         TALLOC_CTX *mem_ctx,
4862         struct tevent_context *ev,
4863         struct cli_state *cli,
4864         const char *fname,
4865         int pipe_down_fd)
4866 {
4867         struct tevent_req *req = NULL, *subreq = NULL;
4868         struct oplock5_state *state = NULL;
4869         static uint8_t data = 0;
4870
4871         req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
4872         if (req == NULL) {
4873                 return NULL;
4874         }
4875         state->pipe_down_fd = pipe_down_fd;
4876
4877         subreq = cli_ntcreate_send(
4878                 state,
4879                 ev,
4880                 cli,
4881                 fname,
4882                 0,                      /* CreatFlags */
4883                 SEC_FILE_READ_DATA,    /* DesiredAccess */
4884                 FILE_ATTRIBUTE_NORMAL,  /* FileAttributes */
4885                 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
4886                 FILE_OPEN,               /* CreateDisposition */
4887                 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
4888                 0,                       /* Impersonation */
4889                 0);                      /* SecurityFlags */
4890         if (tevent_req_nomem(subreq, req)) {
4891                 return tevent_req_post(req, ev);
4892         }
4893         tevent_req_set_callback(subreq, oplock5_opened, req);
4894
4895         subreq = cli_echo_send(
4896                 state,
4897                 ev,
4898                 cli,
4899                 1,
4900                 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
4901         if (tevent_req_nomem(subreq, req)) {
4902                 return tevent_req_post(req, ev);
4903         }
4904         tevent_req_set_callback(subreq, oplock5_pong, req);
4905
4906         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
4907         if (tevent_req_nomem(subreq, req)) {
4908                 return tevent_req_post(req, ev);
4909         }
4910         tevent_req_set_callback(subreq, oplock5_timedout, req);
4911
4912         return req;
4913 }
4914
4915 static void oplock5_opened(struct tevent_req *subreq)
4916 {
4917         struct tevent_req *req = tevent_req_callback_data(
4918                 subreq, struct tevent_req);
4919         NTSTATUS status;
4920         uint16_t fnum;
4921
4922         status = cli_ntcreate_recv(subreq, &fnum, NULL);
4923         TALLOC_FREE(subreq);
4924         if (tevent_req_nterror(req, status)) {
4925                 return;
4926         }
4927         tevent_req_done(req);
4928 }
4929
4930 static void oplock5_pong(struct tevent_req *subreq)
4931 {
4932         struct tevent_req *req = tevent_req_callback_data(
4933                 subreq, struct tevent_req);
4934         struct oplock5_state *state = tevent_req_data(
4935                 req, struct oplock5_state);
4936         NTSTATUS status;
4937
4938         status = cli_echo_recv(subreq);
4939         TALLOC_FREE(subreq);
4940         if (tevent_req_nterror(req, status)) {
4941                 return;
4942         }
4943
4944         close(state->pipe_down_fd);
4945 }
4946
4947 static void oplock5_timedout(struct tevent_req *subreq)
4948 {
4949         struct tevent_req *req = tevent_req_callback_data(
4950                 subreq, struct tevent_req);
4951         bool ok;
4952
4953         ok = tevent_wakeup_recv(subreq);
4954         TALLOC_FREE(subreq);
4955         if (!ok) {
4956                 tevent_req_oom(req);
4957                 return;
4958         }
4959         tevent_req_nterror(req, NT_STATUS_TIMEOUT);
4960 }
4961
4962 static NTSTATUS oplock5_recv(struct tevent_req *req)
4963 {
4964         return tevent_req_simple_recv_ntstatus(req);
4965 }
4966
4967 static bool run_oplock5(int dummy)
4968 {
4969         struct tevent_context *ev = NULL;
4970         struct tevent_req *req = NULL;
4971         struct cli_state *cli = NULL;
4972         const char *fname = "oplock5.txt";
4973         int pipe_down[2], pipe_up[2];
4974         pid_t child_pid;
4975         uint8_t c = '\0';
4976         NTSTATUS status;
4977         int ret;
4978         bool ok;
4979
4980         printf("starting oplock5\n");
4981
4982         if (local_path == NULL) {
4983                 d_fprintf(stderr, "oplock5 must be given a local path via "
4984                           "-l <localpath>\n");
4985                 return false;
4986         }
4987
4988         ret = pipe(pipe_down);
4989         if (ret == -1) {
4990                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
4991                 return false;
4992         }
4993         ret = pipe(pipe_up);
4994         if (ret == -1) {
4995                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
4996                 return false;
4997         }
4998
4999         child_pid = fork();
5000         if (child_pid == -1) {
5001                 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5002                 return false;
5003         }
5004
5005         if (child_pid == 0) {
5006                 char *local_file = NULL;
5007                 int fd;
5008
5009                 close(pipe_down[1]);
5010                 close(pipe_up[0]);
5011
5012                 local_file = talloc_asprintf(
5013                         talloc_tos(), "%s/%s", local_path, fname);
5014                 if (local_file == 0) {
5015                         c = 1;
5016                         goto do_write;
5017                 }
5018                 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5019                 if (fd == -1) {
5020                         d_fprintf(stderr,
5021                                   "open(%s) in child failed: %s\n",
5022                                   local_file,
5023                                   strerror(errno));
5024                         c = 2;
5025                         goto do_write;
5026                 }
5027
5028                 signal(SIGIO, SIG_IGN);
5029
5030                 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5031                 if (ret == -1) {
5032                         d_fprintf(stderr,
5033                                   "SETLEASE in child failed: %s\n",
5034                                   strerror(errno));
5035                         c = 3;
5036                         goto do_write;
5037                 }
5038
5039         do_write:
5040                 ret = sys_write(pipe_up[1], &c, sizeof(c));
5041                 if (ret == -1) {
5042                         d_fprintf(stderr,
5043                                   "sys_write failed: %s\n",
5044                                   strerror(errno));
5045                         exit(4);
5046                 }
5047                 ret = sys_read(pipe_down[0], &c, sizeof(c));
5048                 if (ret == -1) {
5049                         d_fprintf(stderr,
5050                                   "sys_read failed: %s\n",
5051                                   strerror(errno));
5052                         exit(5);
5053                 }
5054                 exit(0);
5055         }
5056
5057         close(pipe_up[1]);
5058         close(pipe_down[0]);
5059
5060         ret = sys_read(pipe_up[0], &c, sizeof(c));
5061         if (ret != 1) {
5062                 d_fprintf(stderr,
5063                           "sys_read failed: %s\n",
5064                           strerror(errno));
5065                 return false;
5066         }
5067         if (c != 0) {
5068                 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5069                 return false;
5070         }
5071
5072         ok = torture_open_connection(&cli, 0);
5073         if (!ok) {
5074                 d_fprintf(stderr, "torture_open_connection failed\n");
5075                 return false;
5076         }
5077
5078         ev = samba_tevent_context_init(talloc_tos());
5079         if (ev == NULL) {
5080                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5081                 return false;
5082         }
5083
5084         req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5085         if (req == NULL) {
5086                 d_fprintf(stderr, "oplock5_send failed\n");
5087                 return false;
5088         }
5089
5090         ok = tevent_req_poll_ntstatus(req, ev, &status);
5091         if (!ok) {
5092                 d_fprintf(stderr,
5093                           "tevent_req_poll_ntstatus failed: %s\n",
5094                           nt_errstr(status));
5095                 return false;
5096         }
5097
5098         status = oplock5_recv(req);
5099         TALLOC_FREE(req);
5100         if (!NT_STATUS_IS_OK(status)) {
5101                 d_fprintf(stderr,
5102                           "oplock5 failed: %s\n",
5103                           nt_errstr(status));
5104                 return false;
5105         }
5106
5107         return true;
5108 }
5109
5110 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5111
5112 /*
5113   Test delete on close semantics.
5114  */
5115 static bool run_deletetest(int dummy)
5116 {
5117         struct cli_state *cli1 = NULL;
5118         struct cli_state *cli2 = NULL;
5119         const char *fname = "\\delete.file";
5120         uint16_t fnum1 = (uint16_t)-1;
5121         uint16_t fnum2 = (uint16_t)-1;
5122         bool correct = false;
5123         NTSTATUS status;
5124
5125         printf("starting delete test\n");
5126
5127         if (!torture_open_connection(&cli1, 0)) {
5128                 return False;
5129         }
5130
5131         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5132
5133         /* Test 1 - this should delete the file on close. */
5134
5135         cli_setatr(cli1, fname, 0, 0);
5136         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5137
5138         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5139                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5140                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5141         if (!NT_STATUS_IS_OK(status)) {
5142                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5143                 goto fail;
5144         }
5145
5146         status = cli_close(cli1, fnum1);
5147         if (!NT_STATUS_IS_OK(status)) {
5148                 printf("[1] close failed (%s)\n", nt_errstr(status));
5149                 goto fail;
5150         }
5151
5152         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5153         if (NT_STATUS_IS_OK(status)) {
5154                 printf("[1] open of %s succeeded (should fail)\n", fname);
5155                 goto fail;
5156         }
5157
5158         printf("first delete on close test succeeded.\n");
5159
5160         /* Test 2 - this should delete the file on close. */
5161
5162         cli_setatr(cli1, fname, 0, 0);
5163         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5164
5165         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5166                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5167                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5168         if (!NT_STATUS_IS_OK(status)) {
5169                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5170                 goto fail;
5171         }
5172
5173         status = cli_nt_delete_on_close(cli1, fnum1, true);
5174         if (!NT_STATUS_IS_OK(status)) {
5175                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5176                 goto fail;
5177         }
5178
5179         status = cli_close(cli1, fnum1);
5180         if (!NT_STATUS_IS_OK(status)) {
5181                 printf("[2] close failed (%s)\n", nt_errstr(status));
5182                 goto fail;
5183         }
5184
5185         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5186         if (NT_STATUS_IS_OK(status)) {
5187                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5188                 status = cli_close(cli1, fnum1);
5189                 if (!NT_STATUS_IS_OK(status)) {
5190                         printf("[2] close failed (%s)\n", nt_errstr(status));
5191                 }
5192                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5193                 goto fail;
5194         }
5195
5196         printf("second delete on close test succeeded.\n");
5197
5198         /* Test 3 - ... */
5199         cli_setatr(cli1, fname, 0, 0);
5200         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5201
5202         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5203                               FILE_ATTRIBUTE_NORMAL,
5204                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5205                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5206         if (!NT_STATUS_IS_OK(status)) {
5207                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5208                 goto fail;
5209         }
5210
5211         /* This should fail with a sharing violation - open for delete is only compatible
5212            with SHARE_DELETE. */
5213
5214         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5215                               FILE_ATTRIBUTE_NORMAL,
5216                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5217                               FILE_OPEN, 0, 0, &fnum2, NULL);
5218         if (NT_STATUS_IS_OK(status)) {
5219                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
5220                 goto fail;
5221         }
5222
5223         /* This should succeed. */
5224         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5225                              FILE_ATTRIBUTE_NORMAL,
5226                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5227                              FILE_OPEN, 0, 0, &fnum2, NULL);
5228         if (!NT_STATUS_IS_OK(status)) {
5229                 printf("[3] open  - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5230                 goto fail;
5231         }
5232
5233         status = cli_nt_delete_on_close(cli1, fnum1, true);
5234         if (!NT_STATUS_IS_OK(status)) {
5235                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5236                 goto fail;
5237         }
5238
5239         status = cli_close(cli1, fnum1);
5240         if (!NT_STATUS_IS_OK(status)) {
5241                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5242                 goto fail;
5243         }
5244
5245         status = cli_close(cli1, fnum2);
5246         if (!NT_STATUS_IS_OK(status)) {
5247                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5248                 goto fail;
5249         }
5250
5251         /* This should fail - file should no longer be there. */
5252
5253         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5254         if (NT_STATUS_IS_OK(status)) {
5255                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5256                 status = cli_close(cli1, fnum1);
5257                 if (!NT_STATUS_IS_OK(status)) {
5258                         printf("[3] close failed (%s)\n", nt_errstr(status));
5259                 }
5260                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5261                 goto fail;
5262         }
5263
5264         printf("third delete on close test succeeded.\n");
5265
5266         /* Test 4 ... */
5267         cli_setatr(cli1, fname, 0, 0);
5268         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5269
5270         status = cli_ntcreate(cli1, fname, 0,
5271                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5272                               FILE_ATTRIBUTE_NORMAL,
5273                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5274                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5275         if (!NT_STATUS_IS_OK(status)) {
5276                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5277                 goto fail;
5278         }
5279
5280         /* This should succeed. */
5281         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5282                              FILE_ATTRIBUTE_NORMAL,
5283                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5284                              FILE_OPEN, 0, 0, &fnum2, NULL);
5285         if (!NT_STATUS_IS_OK(status)) {
5286                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5287                 goto fail;
5288         }
5289
5290         status = cli_close(cli1, fnum2);
5291         if (!NT_STATUS_IS_OK(status)) {
5292                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5293                 goto fail;
5294         }
5295
5296         status = cli_nt_delete_on_close(cli1, fnum1, true);
5297         if (!NT_STATUS_IS_OK(status)) {
5298                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5299                 goto fail;
5300         }
5301
5302         /* This should fail - no more opens once delete on close set. */
5303         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5304                               FILE_ATTRIBUTE_NORMAL,
5305                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5306                               FILE_OPEN, 0, 0, &fnum2, NULL);
5307         if (NT_STATUS_IS_OK(status)) {
5308                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
5309                 goto fail;
5310         }
5311
5312         status = cli_close(cli1, fnum1);
5313         if (!NT_STATUS_IS_OK(status)) {
5314                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5315                 goto fail;
5316         }
5317
5318         printf("fourth delete on close test succeeded.\n");
5319
5320         /* Test 5 ... */
5321         cli_setatr(cli1, fname, 0, 0);
5322         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5323
5324         status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5325         if (!NT_STATUS_IS_OK(status)) {
5326                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5327                 goto fail;
5328         }
5329
5330         /* This should fail - only allowed on NT opens with DELETE access. */
5331
5332         status = cli_nt_delete_on_close(cli1, fnum1, true);
5333         if (NT_STATUS_IS_OK(status)) {
5334                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5335                 goto fail;
5336         }
5337
5338         status = cli_close(cli1, fnum1);
5339         if (!NT_STATUS_IS_OK(status)) {
5340                 printf("[5] close failed (%s)\n", nt_errstr(status));
5341                 goto fail;
5342         }
5343
5344         printf("fifth delete on close test succeeded.\n");
5345
5346         /* Test 6 ... */
5347         cli_setatr(cli1, fname, 0, 0);
5348         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5349
5350         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5351                              FILE_ATTRIBUTE_NORMAL,
5352                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5353                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5354         if (!NT_STATUS_IS_OK(status)) {
5355                 printf("[6] open of %s failed (%s)\n", fname,
5356                        nt_errstr(status));
5357                 goto fail;
5358         }
5359
5360         /* This should fail - only allowed on NT opens with DELETE access. */
5361
5362         status = cli_nt_delete_on_close(cli1, fnum1, true);
5363         if (NT_STATUS_IS_OK(status)) {
5364                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5365                 goto fail;
5366         }
5367
5368         status = cli_close(cli1, fnum1);
5369         if (!NT_STATUS_IS_OK(status)) {
5370                 printf("[6] close failed (%s)\n", nt_errstr(status));
5371                 goto fail;
5372         }
5373
5374         printf("sixth delete on close test succeeded.\n");
5375
5376         /* Test 7 ... */
5377         cli_setatr(cli1, fname, 0, 0);
5378         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5379
5380         status = cli_ntcreate(cli1, fname, 0,
5381                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5382                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5383                               0, 0, &fnum1, NULL);
5384         if (!NT_STATUS_IS_OK(status)) {
5385                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5386                 goto fail;
5387         }
5388
5389         status = cli_nt_delete_on_close(cli1, fnum1, true);
5390         if (!NT_STATUS_IS_OK(status)) {
5391                 printf("[7] setting delete_on_close on file failed !\n");
5392                 goto fail;
5393         }
5394
5395         status = cli_nt_delete_on_close(cli1, fnum1, false);
5396         if (!NT_STATUS_IS_OK(status)) {
5397                 printf("[7] unsetting delete_on_close on file failed !\n");
5398                 goto fail;
5399         }
5400
5401         status = cli_close(cli1, fnum1);
5402         if (!NT_STATUS_IS_OK(status)) {
5403                 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5404                 goto fail;
5405         }
5406
5407         /* This next open should succeed - we reset the flag. */
5408         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5409         if (!NT_STATUS_IS_OK(status)) {
5410                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5411                 goto fail;
5412         }
5413
5414         status = cli_close(cli1, fnum1);
5415         if (!NT_STATUS_IS_OK(status)) {
5416                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5417                 goto fail;
5418         }
5419
5420         printf("seventh delete on close test succeeded.\n");
5421
5422         /* Test 8 ... */
5423         cli_setatr(cli1, fname, 0, 0);
5424         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5425
5426         if (!torture_open_connection(&cli2, 1)) {
5427                 printf("[8] failed to open second connection.\n");
5428                 goto fail;
5429         }
5430
5431         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5432
5433         status = cli_ntcreate(cli1, fname, 0,
5434                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5435                              FILE_ATTRIBUTE_NORMAL,
5436                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5437                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5438         if (!NT_STATUS_IS_OK(status)) {
5439                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5440                 goto fail;
5441         }
5442
5443         status = cli_ntcreate(cli2, fname, 0,
5444                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5445                              FILE_ATTRIBUTE_NORMAL,
5446                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5447                              FILE_OPEN, 0, 0, &fnum2, NULL);
5448         if (!NT_STATUS_IS_OK(status)) {
5449                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5450                 goto fail;
5451         }
5452
5453         status = cli_nt_delete_on_close(cli1, fnum1, true);
5454         if (!NT_STATUS_IS_OK(status)) {
5455                 printf("[8] setting delete_on_close on file failed !\n");
5456                 goto fail;
5457         }
5458
5459         status = cli_close(cli1, fnum1);
5460         if (!NT_STATUS_IS_OK(status)) {
5461                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5462                 goto fail;
5463         }
5464
5465         status = cli_close(cli2, fnum2);
5466         if (!NT_STATUS_IS_OK(status)) {
5467                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5468                 goto fail;
5469         }
5470
5471         /* This should fail.. */
5472         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5473         if (NT_STATUS_IS_OK(status)) {
5474                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5475                 goto fail;
5476         }
5477
5478         printf("eighth delete on close test succeeded.\n");
5479
5480         /* Test 9 ... */
5481
5482         /* This should fail - we need to set DELETE_ACCESS. */
5483         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5484                               FILE_ATTRIBUTE_NORMAL,
5485                               FILE_SHARE_NONE,
5486                               FILE_OVERWRITE_IF,
5487                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5488         if (NT_STATUS_IS_OK(status)) {
5489                 printf("[9] open of %s succeeded should have failed!\n", fname);
5490                 goto fail;
5491         }
5492
5493         printf("ninth delete on close test succeeded.\n");
5494
5495         /* Test 10 ... */
5496
5497         status = cli_ntcreate(cli1, fname, 0,
5498                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5499                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5500                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5501                              0, &fnum1, NULL);
5502         if (!NT_STATUS_IS_OK(status)) {
5503                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5504                 goto fail;
5505         }
5506
5507         /* This should delete the file. */
5508         status = cli_close(cli1, fnum1);
5509         if (!NT_STATUS_IS_OK(status)) {
5510                 printf("[10] close failed (%s)\n", nt_errstr(status));
5511                 goto fail;
5512         }
5513
5514         /* This should fail.. */
5515         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5516         if (NT_STATUS_IS_OK(status)) {
5517                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5518                 goto fail;
5519         }
5520
5521         printf("tenth delete on close test succeeded.\n");
5522
5523         /* Test 11 ... */
5524
5525         cli_setatr(cli1, fname, 0, 0);
5526         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5527
5528         /* Can we open a read-only file with delete access? */
5529
5530         /* Create a readonly file. */
5531         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5532                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5533                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5534         if (!NT_STATUS_IS_OK(status)) {
5535                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5536                 goto fail;
5537         }
5538
5539         status = cli_close(cli1, fnum1);
5540         if (!NT_STATUS_IS_OK(status)) {
5541                 printf("[11] close failed (%s)\n", nt_errstr(status));
5542                 goto fail;
5543         }
5544
5545         /* Now try open for delete access. */
5546         status = cli_ntcreate(cli1, fname, 0,
5547                              FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5548                              0,
5549                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5550                              FILE_OPEN, 0, 0, &fnum1, NULL);
5551         if (!NT_STATUS_IS_OK(status)) {
5552                 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5553                 goto fail;
5554         }
5555
5556         cli_close(cli1, fnum1);
5557
5558         printf("eleventh delete on close test succeeded.\n");
5559
5560         /*
5561          * Test 12
5562          * like test 4 but with initial delete on close
5563          */
5564
5565         cli_setatr(cli1, fname, 0, 0);
5566         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5567
5568         status = cli_ntcreate(cli1, fname, 0,
5569                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5570                               FILE_ATTRIBUTE_NORMAL,
5571                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5572                               FILE_OVERWRITE_IF,
5573                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5574         if (!NT_STATUS_IS_OK(status)) {
5575                 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5576                 goto fail;
5577         }
5578
5579         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5580                               FILE_ATTRIBUTE_NORMAL,
5581                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5582                               FILE_OPEN, 0, 0, &fnum2, NULL);
5583         if (!NT_STATUS_IS_OK(status)) {
5584                 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5585                 goto fail;
5586         }
5587
5588         status = cli_close(cli1, fnum2);
5589         if (!NT_STATUS_IS_OK(status)) {
5590                 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5591                 goto fail;
5592         }
5593
5594         status = cli_nt_delete_on_close(cli1, fnum1, true);
5595         if (!NT_STATUS_IS_OK(status)) {
5596                 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5597                 goto fail;
5598         }
5599
5600         /* This should fail - no more opens once delete on close set. */
5601         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5602                               FILE_ATTRIBUTE_NORMAL,
5603                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5604                               FILE_OPEN, 0, 0, &fnum2, NULL);
5605         if (NT_STATUS_IS_OK(status)) {
5606                 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5607                 goto fail;
5608         }
5609
5610         status = cli_nt_delete_on_close(cli1, fnum1, false);
5611         if (!NT_STATUS_IS_OK(status)) {
5612                 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5613                 goto fail;
5614         }
5615
5616         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5617                               FILE_ATTRIBUTE_NORMAL,
5618                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5619                               FILE_OPEN, 0, 0, &fnum2, NULL);
5620         if (!NT_STATUS_IS_OK(status)) {
5621                 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5622                 goto fail;
5623         }
5624
5625         status = cli_close(cli1, fnum2);
5626         if (!NT_STATUS_IS_OK(status)) {
5627                 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5628                 goto fail;
5629         }
5630
5631         status = cli_close(cli1, fnum1);
5632         if (!NT_STATUS_IS_OK(status)) {
5633                 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5634                 goto fail;
5635         }
5636
5637         /*
5638          * setting delete on close on the handle does
5639          * not unset the initial delete on close...
5640          */
5641         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5642                               FILE_ATTRIBUTE_NORMAL,
5643                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5644                               FILE_OPEN, 0, 0, &fnum2, NULL);
5645         if (NT_STATUS_IS_OK(status)) {
5646                 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5647                 goto fail;
5648         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5649                 printf("ntcreate returned %s, expected "
5650                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5651                        nt_errstr(status));
5652                 goto fail;
5653         }
5654
5655         printf("twelfth delete on close test succeeded.\n");
5656
5657
5658         printf("finished delete test\n");
5659
5660         correct = true;
5661
5662   fail:
5663         /* FIXME: This will crash if we aborted before cli2 got
5664          * intialized, because these functions don't handle
5665          * uninitialized connections. */
5666
5667         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5668         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5669         cli_setatr(cli1, fname, 0, 0);
5670         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5671
5672         if (cli1 && !torture_close_connection(cli1)) {
5673                 correct = False;
5674         }
5675         if (cli2 && !torture_close_connection(cli2)) {
5676                 correct = False;
5677         }
5678         return correct;
5679 }
5680
5681 struct delete_stream_state {
5682         bool closed;
5683 };
5684
5685 static void delete_stream_unlinked(struct tevent_req *subreq);
5686 static void delete_stream_closed(struct tevent_req *subreq);
5687
5688 static struct tevent_req *delete_stream_send(
5689         TALLOC_CTX *mem_ctx,
5690         struct tevent_context *ev,
5691         struct cli_state *cli,
5692         const char *base_fname,
5693         uint16_t stream_fnum)
5694 {
5695         struct tevent_req *req = NULL, *subreq = NULL;
5696         struct delete_stream_state *state = NULL;
5697
5698         req = tevent_req_create(
5699                 mem_ctx, &state, struct delete_stream_state);
5700         if (req == NULL) {
5701                 return NULL;
5702         }
5703
5704         subreq = cli_unlink_send(
5705                 state,
5706                 ev,
5707                 cli,
5708                 base_fname,
5709                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5710         if (tevent_req_nomem(subreq, req)) {
5711                 return tevent_req_post(req, ev);
5712         }
5713         tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5714
5715         subreq = cli_close_send(state, ev, cli, stream_fnum);
5716         if (tevent_req_nomem(subreq, req)) {
5717                 return tevent_req_post(req, ev);
5718         }
5719         tevent_req_set_callback(subreq, delete_stream_closed, req);
5720
5721         return req;
5722 }
5723
5724 static void delete_stream_unlinked(struct tevent_req *subreq)
5725 {
5726         struct tevent_req *req = tevent_req_callback_data(
5727                 subreq, struct tevent_req);
5728         struct delete_stream_state *state = tevent_req_data(
5729                 req, struct delete_stream_state);
5730         NTSTATUS status;
5731
5732         status = cli_unlink_recv(subreq);
5733         TALLOC_FREE(subreq);
5734         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5735                 printf("cli_unlink returned %s\n",
5736                        nt_errstr(status));
5737                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5738                 return;
5739         }
5740         if (!state->closed) {
5741                 /* close reply should have come in first */
5742                 printf("Not closed\n");
5743                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5744                 return;
5745         }
5746         tevent_req_done(req);
5747 }
5748
5749 static void delete_stream_closed(struct tevent_req *subreq)
5750 {
5751         struct tevent_req *req = tevent_req_callback_data(
5752                 subreq, struct tevent_req);
5753         struct delete_stream_state *state = tevent_req_data(
5754                 req, struct delete_stream_state);
5755         NTSTATUS status;
5756
5757         status = cli_close_recv(subreq);
5758         TALLOC_FREE(subreq);
5759         if (tevent_req_nterror(req, status)) {
5760                 return;
5761         }
5762         /* also waiting for the unlink to come back */
5763         state->closed = true;
5764 }
5765
5766 static NTSTATUS delete_stream_recv(struct tevent_req *req)
5767 {
5768         return tevent_req_simple_recv_ntstatus(req);
5769 }
5770
5771 static bool run_delete_stream(int dummy)
5772 {
5773         struct tevent_context *ev = NULL;
5774         struct tevent_req *req = NULL;
5775         struct cli_state *cli = NULL;
5776         const char fname[] = "delete_stream";
5777         const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
5778         uint16_t fnum1, fnum2;
5779         NTSTATUS status;
5780         bool ok;
5781
5782         printf("Starting stream delete test\n");
5783
5784         ok = torture_open_connection(&cli, 0);
5785         if (!ok) {
5786                 return false;
5787         }
5788
5789         cli_setatr(cli, fname, 0, 0);
5790         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5791
5792         /* Create the file. */
5793         status = cli_ntcreate(
5794                 cli,
5795                 fname,
5796                 0,
5797                 READ_CONTROL_ACCESS,
5798                 0,
5799                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5800                 FILE_CREATE,
5801                 0x0,
5802                 0x0,
5803                 &fnum1,
5804                 NULL);
5805         if (!NT_STATUS_IS_OK(status)) {
5806                 d_fprintf(stderr,
5807                           "cli_ntcreate of %s failed (%s)\n",
5808                           fname,
5809                           nt_errstr(status));
5810                 return false;
5811         }
5812         status = cli_close(cli, fnum1);
5813         if (!NT_STATUS_IS_OK(status)) {
5814                 d_fprintf(stderr,
5815                           "cli_close of %s failed (%s)\n",
5816                           fname,
5817                           nt_errstr(status));
5818                 return false;
5819         }
5820
5821         /* Now create the stream. */
5822         status = cli_ntcreate(
5823                 cli,
5824                 fname_stream,
5825                 0,
5826                 FILE_WRITE_DATA,
5827                 0,
5828                 FILE_SHARE_READ|FILE_SHARE_WRITE,
5829                 FILE_CREATE,
5830                 0x0,
5831                 0x0,
5832                 &fnum1,
5833                 NULL);
5834
5835         if (!NT_STATUS_IS_OK(status)) {
5836                 d_fprintf(stderr,
5837                           "cli_ntcreate of %s failed (%s)\n",
5838                           fname_stream,
5839                           nt_errstr(status));
5840                 return false;
5841         }
5842
5843         /* open it a second time */
5844
5845         status = cli_ntcreate(
5846                 cli,
5847                 fname_stream,
5848                 0,
5849                 FILE_WRITE_DATA,
5850                 0,
5851                 FILE_SHARE_READ|FILE_SHARE_WRITE,
5852                 FILE_OPEN,
5853                 0x0,
5854                 0x0,
5855                 &fnum2,
5856                 NULL);
5857
5858         if (!NT_STATUS_IS_OK(status)) {
5859                 d_fprintf(stderr,
5860                           "2nd cli_ntcreate of %s failed (%s)\n",
5861                           fname_stream,
5862                           nt_errstr(status));
5863                 return false;
5864         }
5865
5866         ev = samba_tevent_context_init(talloc_tos());
5867         if (ev == NULL) {
5868                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5869                 return false;
5870         }
5871
5872         req = delete_stream_send(ev, ev, cli, fname, fnum1);
5873         if (req == NULL) {
5874                 d_fprintf(stderr, "delete_stream_send failed\n");
5875                 return false;
5876         }
5877
5878         ok = tevent_req_poll_ntstatus(req, ev, &status);
5879         if (!ok) {
5880                 d_fprintf(stderr,
5881                           "tevent_req_poll_ntstatus failed: %s\n",
5882                           nt_errstr(status));
5883                 return false;
5884         }
5885
5886         status = delete_stream_recv(req);
5887         TALLOC_FREE(req);
5888         if (!NT_STATUS_IS_OK(status)) {
5889                 d_fprintf(stderr,
5890                           "delete_stream failed: %s\n",
5891                           nt_errstr(status));
5892                 return false;
5893         }
5894
5895         status = cli_close(cli, fnum2);
5896         if (!NT_STATUS_IS_OK(status)) {
5897                 d_fprintf(stderr,
5898                           "close failed: %s\n",
5899                           nt_errstr(status));
5900                 return false;
5901         }
5902
5903         status = cli_unlink(
5904                 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5905         if (!NT_STATUS_IS_OK(status)) {
5906                 d_fprintf(stderr,
5907                           "unlink failed: %s\n",
5908                           nt_errstr(status));
5909                 return false;
5910         }
5911
5912         return true;
5913 }
5914
5915 /*
5916   Exercise delete on close semantics - use on the PRINT1 share in torture
5917   testing.
5918  */
5919 static bool run_delete_print_test(int dummy)
5920 {
5921         struct cli_state *cli1 = NULL;
5922         const char *fname = "print_delete.file";
5923         uint16_t fnum1 = (uint16_t)-1;
5924         bool correct = false;
5925         const char *buf = "print file data\n";
5926         NTSTATUS status;
5927
5928         printf("starting print delete test\n");
5929
5930         if (!torture_open_connection(&cli1, 0)) {
5931                 return false;
5932         }
5933
5934         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5935
5936         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5937                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5938                               0, 0, &fnum1, NULL);
5939         if (!NT_STATUS_IS_OK(status)) {
5940                 printf("open of %s failed (%s)\n",
5941                         fname,
5942                         nt_errstr(status));
5943                 goto fail;
5944         }
5945
5946         status = cli_writeall(cli1,
5947                         fnum1,
5948                         0,
5949                         (const uint8_t *)buf,
5950                         0, /* offset */
5951                         strlen(buf), /* size */
5952                         NULL);
5953         if (!NT_STATUS_IS_OK(status)) {
5954                 printf("writing print file data failed (%s)\n",
5955                         nt_errstr(status));
5956                 goto fail;
5957         }
5958
5959         status = cli_nt_delete_on_close(cli1, fnum1, true);
5960         if (!NT_STATUS_IS_OK(status)) {
5961                 printf("setting delete_on_close failed (%s)\n",
5962                         nt_errstr(status));
5963                 goto fail;
5964         }
5965
5966         status = cli_close(cli1, fnum1);
5967         if (!NT_STATUS_IS_OK(status)) {
5968                 printf("close failed (%s)\n", nt_errstr(status));
5969                 goto fail;
5970         }
5971
5972         printf("finished print delete test\n");
5973
5974         correct = true;
5975
5976   fail:
5977
5978         if (fnum1 != (uint16_t)-1) {
5979                 cli_close(cli1, fnum1);
5980         }
5981
5982         if (cli1 && !torture_close_connection(cli1)) {
5983                 correct = false;
5984         }
5985         return correct;
5986 }
5987
5988 /*
5989   Test wildcard delete.
5990  */
5991 static bool run_wild_deletetest(int dummy)
5992 {
5993         struct cli_state *cli = NULL;
5994         const char *dname = "\\WTEST";
5995         const char *fname = "\\WTEST\\A";
5996         const char *wunlink_name = "\\WTEST\\*";
5997         uint16_t fnum1 = (uint16_t)-1;
5998         bool correct = false;
5999         NTSTATUS status;
6000
6001         printf("starting wildcard delete test\n");
6002
6003         if (!torture_open_connection(&cli, 0)) {
6004                 return false;
6005         }
6006
6007         smbXcli_conn_set_sockopt(cli->conn, sockops);
6008
6009         cli_unlink(cli, fname, 0);
6010         cli_rmdir(cli, dname);
6011         status = cli_mkdir(cli, dname);
6012         if (!NT_STATUS_IS_OK(status)) {
6013                 printf("mkdir of %s failed %s!\n", dname, nt_errstr(status));
6014                 goto fail;
6015         }
6016         status = cli_openx(cli, fname, O_CREAT|O_RDONLY, DENY_NONE, &fnum1);
6017         if (!NT_STATUS_IS_OK(status)) {
6018                 printf("open of %s failed %s!\n", fname, nt_errstr(status));
6019                 goto fail;
6020         }
6021         status = cli_close(cli, fnum1);
6022         fnum1 = -1;
6023
6024         /*
6025          * Note the unlink attribute-type of zero. This should
6026          * map into FILE_ATTRIBUTE_NORMAL at the server even
6027          * on a wildcard delete.
6028          */
6029
6030         status = cli_unlink(cli, wunlink_name, 0);
6031         if (!NT_STATUS_IS_OK(status)) {
6032                 printf("unlink of %s failed %s!\n",
6033                         wunlink_name, nt_errstr(status));
6034                 goto fail;
6035         }
6036
6037         printf("finished wildcard delete test\n");
6038
6039         correct = true;
6040
6041   fail:
6042
6043         if (fnum1 != (uint16_t)-1) cli_close(cli, fnum1);
6044         cli_unlink(cli, fname, 0);
6045         cli_rmdir(cli, dname);
6046
6047         if (cli && !torture_close_connection(cli)) {
6048                 correct = false;
6049         }
6050         return correct;
6051 }
6052
6053 static bool run_deletetest_ln(int dummy)
6054 {
6055         struct cli_state *cli;
6056         const char *fname = "\\delete1";
6057         const char *fname_ln = "\\delete1_ln";
6058         uint16_t fnum;
6059         uint16_t fnum1;
6060         NTSTATUS status;
6061         bool correct = true;
6062         time_t t;
6063
6064         printf("starting deletetest-ln\n");
6065
6066         if (!torture_open_connection(&cli, 0)) {
6067                 return false;
6068         }
6069
6070         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6071         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6072
6073         smbXcli_conn_set_sockopt(cli->conn, sockops);
6074
6075         /* Create the file. */
6076         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6077         if (!NT_STATUS_IS_OK(status)) {
6078                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6079                 return false;
6080         }
6081
6082         status = cli_close(cli, fnum);
6083         if (!NT_STATUS_IS_OK(status)) {
6084                 printf("close1 failed (%s)\n", nt_errstr(status));
6085                 return false;
6086         }
6087
6088         /* Now create a hardlink. */
6089         status = cli_hardlink(cli, fname, fname_ln);
6090         if (!NT_STATUS_IS_OK(status)) {
6091                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6092                 return false;
6093         }
6094
6095         /* Open the original file. */
6096         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6097                         FILE_ATTRIBUTE_NORMAL,
6098                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6099                         FILE_OPEN_IF, 0, 0, &fnum, NULL);
6100         if (!NT_STATUS_IS_OK(status)) {
6101                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6102                 return false;
6103         }
6104
6105         /* Unlink the hard link path. */
6106         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6107                         FILE_ATTRIBUTE_NORMAL,
6108                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6109                         FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6110         if (!NT_STATUS_IS_OK(status)) {
6111                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6112                 return false;
6113         }
6114         status = cli_nt_delete_on_close(cli, fnum1, true);
6115         if (!NT_STATUS_IS_OK(status)) {
6116                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6117                         __location__, fname_ln, nt_errstr(status));
6118                 return false;
6119         }
6120
6121         status = cli_close(cli, fnum1);
6122         if (!NT_STATUS_IS_OK(status)) {
6123                 printf("close %s failed (%s)\n",
6124                         fname_ln, nt_errstr(status));
6125                 return false;
6126         }
6127
6128         status = cli_close(cli, fnum);
6129         if (!NT_STATUS_IS_OK(status)) {
6130                 printf("close %s failed (%s)\n",
6131                         fname, nt_errstr(status));
6132                 return false;
6133         }
6134
6135         /* Ensure the original file is still there. */
6136         status = cli_getatr(cli, fname, NULL, NULL, &t);
6137         if (!NT_STATUS_IS_OK(status)) {
6138                 printf("%s getatr on file %s failed (%s)\n",
6139                         __location__,
6140                         fname,
6141                         nt_errstr(status));
6142                 correct = False;
6143         }
6144
6145         /* Ensure the link path is gone. */
6146         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6147         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6148                 printf("%s, getatr for file %s returned wrong error code %s "
6149                         "- should have been deleted\n",
6150                         __location__,
6151                         fname_ln, nt_errstr(status));
6152                 correct = False;
6153         }
6154
6155         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6156         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6157
6158         if (!torture_close_connection(cli)) {
6159                 correct = false;
6160         }
6161
6162         printf("finished deletetest-ln\n");
6163
6164         return correct;
6165 }
6166
6167 /*
6168   print out server properties
6169  */
6170 static bool run_properties(int dummy)
6171 {
6172         struct cli_state *cli;
6173         bool correct = True;
6174
6175         printf("starting properties test\n");
6176
6177         ZERO_STRUCT(cli);
6178
6179         if (!torture_open_connection(&cli, 0)) {
6180                 return False;
6181         }
6182
6183         smbXcli_conn_set_sockopt(cli->conn, sockops);
6184
6185         d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6186
6187         if (!torture_close_connection(cli)) {
6188                 correct = False;
6189         }
6190
6191         return correct;
6192 }
6193
6194
6195
6196 /* FIRST_DESIRED_ACCESS   0xf019f */
6197 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6198                                FILE_READ_EA|                           /* 0xf */ \
6199                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
6200                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
6201                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
6202                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
6203 /* SECOND_DESIRED_ACCESS  0xe0080 */
6204 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6205                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6206                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
6207
6208 #if 0
6209 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6210                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6211                                FILE_READ_DATA|\
6212                                WRITE_OWNER_ACCESS                      /* */
6213 #endif
6214
6215 /*
6216   Test ntcreate calls made by xcopy
6217  */
6218 static bool run_xcopy(int dummy)
6219 {
6220         static struct cli_state *cli1;
6221         const char *fname = "\\test.txt";
6222         bool correct = True;
6223         uint16_t fnum1, fnum2;
6224         NTSTATUS status;
6225
6226         printf("starting xcopy test\n");
6227
6228         if (!torture_open_connection(&cli1, 0)) {
6229                 return False;
6230         }
6231
6232         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6233                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6234                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6235         if (!NT_STATUS_IS_OK(status)) {
6236                 printf("First open failed - %s\n", nt_errstr(status));
6237                 return False;
6238         }
6239
6240         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6241                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6242                              FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6243         if (!NT_STATUS_IS_OK(status)) {
6244                 printf("second open failed - %s\n", nt_errstr(status));
6245                 return False;
6246         }
6247
6248         if (!torture_close_connection(cli1)) {
6249                 correct = False;
6250         }
6251
6252         return correct;
6253 }
6254
6255 /*
6256   Test rename on files open with share delete and no share delete.
6257  */
6258 static bool run_rename(int dummy)
6259 {
6260         static struct cli_state *cli1;
6261         const char *fname = "\\test.txt";
6262         const char *fname1 = "\\test1.txt";
6263         bool correct = True;
6264         uint16_t fnum1;
6265         uint32_t attr;
6266         NTSTATUS status;
6267
6268         printf("starting rename test\n");
6269
6270         if (!torture_open_connection(&cli1, 0)) {
6271                 return False;
6272         }
6273
6274         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6275         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6276
6277         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6278                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6279                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6280         if (!NT_STATUS_IS_OK(status)) {
6281                 printf("First open failed - %s\n", nt_errstr(status));
6282                 return False;
6283         }
6284
6285         status = cli_rename(cli1, fname, fname1, false);
6286         if (!NT_STATUS_IS_OK(status)) {
6287                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6288         } else {
6289                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6290                 correct = False;
6291         }
6292
6293         status = cli_close(cli1, fnum1);
6294         if (!NT_STATUS_IS_OK(status)) {
6295                 printf("close - 1 failed (%s)\n", nt_errstr(status));
6296                 return False;
6297         }
6298
6299         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6300         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6301         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6302 #if 0
6303                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
6304 #else
6305                               FILE_SHARE_DELETE|FILE_SHARE_READ,
6306 #endif
6307                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6308         if (!NT_STATUS_IS_OK(status)) {
6309                 printf("Second open failed - %s\n", nt_errstr(status));
6310                 return False;
6311         }
6312
6313         status = cli_rename(cli1, fname, fname1, false);
6314         if (!NT_STATUS_IS_OK(status)) {
6315                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6316                 correct = False;
6317         } else {
6318                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6319         }
6320
6321         status = cli_close(cli1, fnum1);
6322         if (!NT_STATUS_IS_OK(status)) {
6323                 printf("close - 2 failed (%s)\n", nt_errstr(status));
6324                 return False;
6325         }
6326
6327         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6328         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6329
6330         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6331                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6332                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6333         if (!NT_STATUS_IS_OK(status)) {
6334                 printf("Third open failed - %s\n", nt_errstr(status));
6335                 return False;
6336         }
6337
6338
6339         status = cli_rename(cli1, fname, fname1, false);
6340         if (!NT_STATUS_IS_OK(status)) {
6341                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6342                 correct = False;
6343         } else {
6344                 printf("Third rename succeeded (SHARE_NONE)\n");
6345         }
6346
6347         status = cli_close(cli1, fnum1);
6348         if (!NT_STATUS_IS_OK(status)) {
6349                 printf("close - 3 failed (%s)\n", nt_errstr(status));
6350                 return False;
6351         }
6352
6353         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6354         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6355
6356         /*----*/
6357
6358         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6359                               FILE_ATTRIBUTE_NORMAL,
6360                               FILE_SHARE_READ | FILE_SHARE_WRITE,
6361                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6362         if (!NT_STATUS_IS_OK(status)) {
6363                 printf("Fourth open failed - %s\n", nt_errstr(status));
6364                 return False;
6365         }
6366
6367         status = cli_rename(cli1, fname, fname1, false);
6368         if (!NT_STATUS_IS_OK(status)) {
6369                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6370         } else {
6371                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6372                 correct = False;
6373         }
6374
6375         status = cli_close(cli1, fnum1);
6376         if (!NT_STATUS_IS_OK(status)) {
6377                 printf("close - 4 failed (%s)\n", nt_errstr(status));
6378                 return False;
6379         }
6380
6381         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6382         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6383
6384         /*--*/
6385
6386         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6387                          FILE_ATTRIBUTE_NORMAL,
6388                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6389                          FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6390         if (!NT_STATUS_IS_OK(status)) {
6391                 printf("Fifth open failed - %s\n", nt_errstr(status));
6392                 return False;
6393         }
6394
6395         status = cli_rename(cli1, fname, fname1, false);
6396         if (!NT_STATUS_IS_OK(status)) {
6397                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6398                 correct = False;
6399         } else {
6400                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6401         }
6402
6403         /*--*/
6404         status = cli_close(cli1, fnum1);
6405         if (!NT_STATUS_IS_OK(status)) {
6406                 printf("close - 5 failed (%s)\n", nt_errstr(status));
6407                 return False;
6408         }
6409
6410         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6411         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6412         if (!NT_STATUS_IS_OK(status)) {
6413                 printf("getatr on file %s failed - %s ! \n",
6414                         fname1, nt_errstr(status));
6415                 correct = False;
6416         } else {
6417                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6418                         printf("Renamed file %s has wrong attr 0x%x "
6419                                 "(should be 0x%x)\n",
6420                                 fname1,
6421                                 attr,
6422                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6423                         correct = False;
6424                 } else {
6425                         printf("Renamed file %s has archive bit set\n", fname1);
6426                 }
6427         }
6428
6429         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6430         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6431
6432         if (!torture_close_connection(cli1)) {
6433                 correct = False;
6434         }
6435
6436         return correct;
6437 }
6438
6439 /*
6440   Test rename into a directory with an ACL denying it.
6441  */
6442 static bool run_rename_access(int dummy)
6443 {
6444         static struct cli_state *cli = NULL;
6445         static struct cli_state *posix_cli = NULL;
6446         const char *src = "test.txt";
6447         const char *dname = "dir";
6448         const char *dst = "dir\\test.txt";
6449         const char *dsrc = "test.dir";
6450         const char *ddst = "dir\\test.dir";
6451         uint16_t fnum = (uint16_t)-1;
6452         struct security_descriptor *sd = NULL;
6453         struct security_descriptor *newsd = NULL;
6454         NTSTATUS status;
6455         TALLOC_CTX *frame = NULL;
6456
6457         frame = talloc_stackframe();
6458         printf("starting rename access test\n");
6459
6460         /* Windows connection. */
6461         if (!torture_open_connection(&cli, 0)) {
6462                 goto fail;
6463         }
6464
6465         smbXcli_conn_set_sockopt(cli->conn, sockops);
6466
6467         /* Posix connection. */
6468         if (!torture_open_connection(&posix_cli, 0)) {
6469                 goto fail;
6470         }
6471
6472         smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6473
6474         status = torture_setup_unix_extensions(posix_cli);
6475         if (!NT_STATUS_IS_OK(status)) {
6476                 goto fail;
6477         }
6478
6479         /* Start with a clean slate. */
6480         cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6481         cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6482         cli_rmdir(cli, dsrc);
6483         cli_rmdir(cli, ddst);
6484         cli_rmdir(cli, dname);
6485
6486         /*
6487          * Setup the destination directory with a DENY ACE to
6488          * prevent new files within it.
6489          */
6490         status = cli_ntcreate(cli,
6491                                 dname,
6492                                 0,
6493                                 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6494                                         WRITE_DAC_ACCESS|FILE_READ_DATA|
6495                                         WRITE_OWNER_ACCESS,
6496                                 FILE_ATTRIBUTE_DIRECTORY,
6497                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6498                                 FILE_CREATE,
6499                                 FILE_DIRECTORY_FILE,
6500                                 0,
6501                                 &fnum,
6502                                 NULL);
6503         if (!NT_STATUS_IS_OK(status)) {
6504                 printf("Create of %s - %s\n", dname, nt_errstr(status));
6505                 goto fail;
6506         }
6507
6508         status = cli_query_secdesc(cli,
6509                                 fnum,
6510                                 frame,
6511                                 &sd);
6512         if (!NT_STATUS_IS_OK(status)) {
6513                 printf("cli_query_secdesc failed for %s (%s)\n",
6514                         dname, nt_errstr(status));
6515                 goto fail;
6516         }
6517
6518         newsd = security_descriptor_dacl_create(frame,
6519                                         0,
6520                                         NULL,
6521                                         NULL,
6522                                         SID_WORLD,
6523                                         SEC_ACE_TYPE_ACCESS_DENIED,
6524                                         SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6525                                         0,
6526                                         NULL);
6527         if (newsd == NULL) {
6528                 goto fail;
6529         }
6530         sd->dacl = security_acl_concatenate(frame,
6531                                         newsd->dacl,
6532                                         sd->dacl);
6533         if (sd->dacl == NULL) {
6534                 goto fail;
6535         }
6536         status = cli_set_secdesc(cli, fnum, sd);
6537         if (!NT_STATUS_IS_OK(status)) {
6538                 printf("cli_set_secdesc failed for %s (%s)\n",
6539                         dname, nt_errstr(status));
6540                 goto fail;
6541         }
6542         status = cli_close(cli, fnum);
6543         if (!NT_STATUS_IS_OK(status)) {
6544                 printf("close failed for %s (%s)\n",
6545                         dname, nt_errstr(status));
6546                 goto fail;
6547         }
6548         /* Now go around the back and chmod to 777 via POSIX. */
6549         status = cli_posix_chmod(posix_cli, dname, 0777);
6550         if (!NT_STATUS_IS_OK(status)) {
6551                 printf("cli_posix_chmod failed for %s (%s)\n",
6552                         dname, nt_errstr(status));
6553                 goto fail;
6554         }
6555
6556         /* Check we can't create a file within dname via Windows. */
6557         status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6558         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6559                 cli_close(posix_cli, fnum);
6560                 printf("Create of %s should be ACCESS denied, was %s\n",
6561                         dst, nt_errstr(status));
6562                 goto fail;
6563         }
6564
6565         /* Make the sample file/directory. */
6566         status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6567         if (!NT_STATUS_IS_OK(status)) {
6568                 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6569                 goto fail;
6570         }
6571         status = cli_close(cli, fnum);
6572         if (!NT_STATUS_IS_OK(status)) {
6573                 printf("cli_close failed (%s)\n", nt_errstr(status));
6574                 goto fail;
6575         }
6576
6577         status = cli_mkdir(cli, dsrc);
6578         if (!NT_STATUS_IS_OK(status)) {
6579                 printf("cli_mkdir of %s failed (%s)\n",
6580                         dsrc, nt_errstr(status));
6581                 goto fail;
6582         }
6583
6584         /*
6585          * OK - renames of the new file and directory into the
6586          * dst directory should fail.
6587          */
6588
6589         status = cli_rename(cli, src, dst, false);
6590         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6591                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6592                         src, dst, nt_errstr(status));
6593                 goto fail;
6594         }
6595         status = cli_rename(cli, dsrc, ddst, false);
6596         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6597                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6598                         src, dst, nt_errstr(status));
6599                 goto fail;
6600         }
6601
6602         TALLOC_FREE(frame);
6603         return true;
6604
6605   fail:
6606
6607         if (posix_cli) {
6608                 torture_close_connection(posix_cli);
6609         }
6610
6611         if (cli) {
6612                 if (fnum != (uint16_t)-1) {
6613                         cli_close(cli, fnum);
6614                 }
6615                 cli_unlink(cli, src,
6616                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6617                 cli_unlink(cli, dst,
6618                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6619                 cli_rmdir(cli, dsrc);
6620                 cli_rmdir(cli, ddst);
6621                 cli_rmdir(cli, dname);
6622
6623                 torture_close_connection(cli);
6624         }
6625
6626         TALLOC_FREE(frame);
6627         return false;
6628 }
6629
6630 /*
6631   Test owner rights ACE.
6632  */
6633 static bool run_owner_rights(int dummy)
6634 {
6635         static struct cli_state *cli = NULL;
6636         const char *fname = "owner_rights.txt";
6637         uint16_t fnum = (uint16_t)-1;
6638         struct security_descriptor *sd = NULL;
6639         struct security_descriptor *newsd = NULL;
6640         NTSTATUS status;
6641         TALLOC_CTX *frame = NULL;
6642
6643         frame = talloc_stackframe();
6644         printf("starting owner rights test\n");
6645
6646         /* Windows connection. */
6647         if (!torture_open_connection(&cli, 0)) {
6648                 goto fail;
6649         }
6650
6651         smbXcli_conn_set_sockopt(cli->conn, sockops);
6652
6653         /* Start with a clean slate. */
6654         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6655
6656         /* Create the test file. */
6657         /* Now try and open for read and write-dac. */
6658         status = cli_ntcreate(cli,
6659                                 fname,
6660                                 0,
6661                                 GENERIC_ALL_ACCESS,
6662                                 FILE_ATTRIBUTE_NORMAL,
6663                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6664                                         FILE_SHARE_DELETE,
6665                                 FILE_CREATE,
6666                                 0,
6667                                 0,
6668                                 &fnum,
6669                                 NULL);
6670         if (!NT_STATUS_IS_OK(status)) {
6671                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6672                 goto fail;
6673         }
6674
6675         /* Get the original SD. */
6676         status = cli_query_secdesc(cli,
6677                                 fnum,
6678                                 frame,
6679                                 &sd);
6680         if (!NT_STATUS_IS_OK(status)) {
6681                 printf("cli_query_secdesc failed for %s (%s)\n",
6682                         fname, nt_errstr(status));
6683                 goto fail;
6684         }
6685
6686         /*
6687          * Add an "owner-rights" ACE denying WRITE_DATA,
6688          * and an "owner-rights" ACE allowing READ_DATA.
6689          */
6690
6691         newsd = security_descriptor_dacl_create(frame,
6692                                         0,
6693                                         NULL,
6694                                         NULL,
6695                                         SID_OWNER_RIGHTS,
6696                                         SEC_ACE_TYPE_ACCESS_DENIED,
6697                                         FILE_WRITE_DATA,
6698                                         0,
6699                                         SID_OWNER_RIGHTS,
6700                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6701                                         FILE_READ_DATA,
6702                                         0,
6703                                         NULL);
6704         if (newsd == NULL) {
6705                 goto fail;
6706         }
6707         sd->dacl = security_acl_concatenate(frame,
6708                                         newsd->dacl,
6709                                         sd->dacl);
6710         if (sd->dacl == NULL) {
6711                 goto fail;
6712         }
6713         status = cli_set_secdesc(cli, fnum, sd);
6714         if (!NT_STATUS_IS_OK(status)) {
6715                 printf("cli_set_secdesc failed for %s (%s)\n",
6716                         fname, nt_errstr(status));
6717                 goto fail;
6718         }
6719         status = cli_close(cli, fnum);
6720         if (!NT_STATUS_IS_OK(status)) {
6721                 printf("close failed for %s (%s)\n",
6722                         fname, nt_errstr(status));
6723                 goto fail;
6724         }
6725         fnum = (uint16_t)-1;
6726
6727         /* Try and open for FILE_WRITE_DATA */
6728         status = cli_ntcreate(cli,
6729                                 fname,
6730                                 0,
6731                                 FILE_WRITE_DATA,
6732                                 FILE_ATTRIBUTE_NORMAL,
6733                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6734                                         FILE_SHARE_DELETE,
6735                                 FILE_OPEN,
6736                                 0,
6737                                 0,
6738                                 &fnum,
6739                                 NULL);
6740         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6741                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6742                 goto fail;
6743         }
6744
6745         /* Now try and open for FILE_READ_DATA */
6746         status = cli_ntcreate(cli,
6747                                 fname,
6748                                 0,
6749                                 FILE_READ_DATA,
6750                                 FILE_ATTRIBUTE_NORMAL,
6751                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6752                                         FILE_SHARE_DELETE,
6753                                 FILE_OPEN,
6754                                 0,
6755                                 0,
6756                                 &fnum,
6757                                 NULL);
6758         if (!NT_STATUS_IS_OK(status)) {
6759                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6760                 goto fail;
6761         }
6762
6763         status = cli_close(cli, fnum);
6764         if (!NT_STATUS_IS_OK(status)) {
6765                 printf("close failed for %s (%s)\n",
6766                         fname, nt_errstr(status));
6767                 goto fail;
6768         }
6769
6770         /* Restore clean slate. */
6771         TALLOC_FREE(sd);
6772         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6773
6774         /* Create the test file. */
6775         status = cli_ntcreate(cli,
6776                                 fname,
6777                                 0,
6778                                 GENERIC_ALL_ACCESS,
6779                                 FILE_ATTRIBUTE_NORMAL,
6780                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6781                                         FILE_SHARE_DELETE,
6782                                 FILE_CREATE,
6783                                 0,
6784                                 0,
6785                                 &fnum,
6786                                 NULL);
6787         if (!NT_STATUS_IS_OK(status)) {
6788                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6789                 goto fail;
6790         }
6791
6792         /* Get the original SD. */
6793         status = cli_query_secdesc(cli,
6794                                 fnum,
6795                                 frame,
6796                                 &sd);
6797         if (!NT_STATUS_IS_OK(status)) {
6798                 printf("cli_query_secdesc failed for %s (%s)\n",
6799                         fname, nt_errstr(status));
6800                 goto fail;
6801         }
6802
6803         /*
6804          * Add an "owner-rights ACE denying WRITE_DATA,
6805          * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6806          */
6807
6808         newsd = security_descriptor_dacl_create(frame,
6809                                         0,
6810                                         NULL,
6811                                         NULL,
6812                                         SID_OWNER_RIGHTS,
6813                                         SEC_ACE_TYPE_ACCESS_DENIED,
6814                                         FILE_WRITE_DATA,
6815                                         0,
6816                                         SID_OWNER_RIGHTS,
6817                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6818                                         FILE_READ_DATA|FILE_WRITE_DATA,
6819                                         0,
6820                                         NULL);
6821         if (newsd == NULL) {
6822                 goto fail;
6823         }
6824         sd->dacl = security_acl_concatenate(frame,
6825                                         newsd->dacl,
6826                                         sd->dacl);
6827         if (sd->dacl == NULL) {
6828                 goto fail;
6829         }
6830         status = cli_set_secdesc(cli, fnum, sd);
6831         if (!NT_STATUS_IS_OK(status)) {
6832                 printf("cli_set_secdesc failed for %s (%s)\n",
6833                         fname, nt_errstr(status));
6834                 goto fail;
6835         }
6836         status = cli_close(cli, fnum);
6837         if (!NT_STATUS_IS_OK(status)) {
6838                 printf("close failed for %s (%s)\n",
6839                         fname, nt_errstr(status));
6840                 goto fail;
6841         }
6842         fnum = (uint16_t)-1;
6843
6844         /* Try and open for FILE_WRITE_DATA */
6845         status = cli_ntcreate(cli,
6846                                 fname,
6847                                 0,
6848                                 FILE_WRITE_DATA,
6849                                 FILE_ATTRIBUTE_NORMAL,
6850                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6851                                         FILE_SHARE_DELETE,
6852                                 FILE_OPEN,
6853                                 0,
6854                                 0,
6855                                 &fnum,
6856                                 NULL);
6857         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6858                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6859                 goto fail;
6860         }
6861
6862         /* Now try and open for FILE_READ_DATA */
6863         status = cli_ntcreate(cli,
6864                                 fname,
6865                                 0,
6866                                 FILE_READ_DATA,
6867                                 FILE_ATTRIBUTE_NORMAL,
6868                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6869                                         FILE_SHARE_DELETE,
6870                                 FILE_OPEN,
6871                                 0,
6872                                 0,
6873                                 &fnum,
6874                                 NULL);
6875         if (!NT_STATUS_IS_OK(status)) {
6876                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6877                 goto fail;
6878         }
6879
6880         status = cli_close(cli, fnum);
6881         if (!NT_STATUS_IS_OK(status)) {
6882                 printf("close failed for %s (%s)\n",
6883                         fname, nt_errstr(status));
6884                 goto fail;
6885         }
6886
6887         /* Restore clean slate. */
6888         TALLOC_FREE(sd);
6889         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6890
6891
6892         /* Create the test file. */
6893         status = cli_ntcreate(cli,
6894                                 fname,
6895                                 0,
6896                                 GENERIC_ALL_ACCESS,
6897                                 FILE_ATTRIBUTE_NORMAL,
6898                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6899                                         FILE_SHARE_DELETE,
6900                                 FILE_CREATE,
6901                                 0,
6902                                 0,
6903                                 &fnum,
6904                                 NULL);
6905         if (!NT_STATUS_IS_OK(status)) {
6906                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6907                 goto fail;
6908         }
6909
6910         /* Get the original SD. */
6911         status = cli_query_secdesc(cli,
6912                                 fnum,
6913                                 frame,
6914                                 &sd);
6915         if (!NT_STATUS_IS_OK(status)) {
6916                 printf("cli_query_secdesc failed for %s (%s)\n",
6917                         fname, nt_errstr(status));
6918                 goto fail;
6919         }
6920
6921         /*
6922          * Add an "authenticated users" ACE allowing READ_DATA,
6923          * add an "owner-rights" denying READ_DATA,
6924          * and an "authenticated users" ACE allowing WRITE_DATA.
6925          */
6926
6927         newsd = security_descriptor_dacl_create(frame,
6928                                         0,
6929                                         NULL,
6930                                         NULL,
6931                                         SID_NT_AUTHENTICATED_USERS,
6932                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6933                                         FILE_READ_DATA,
6934                                         0,
6935                                         SID_OWNER_RIGHTS,
6936                                         SEC_ACE_TYPE_ACCESS_DENIED,
6937                                         FILE_READ_DATA,
6938                                         0,
6939                                         SID_NT_AUTHENTICATED_USERS,
6940                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6941                                         FILE_WRITE_DATA,
6942                                         0,
6943                                         NULL);
6944         if (newsd == NULL) {
6945                 printf("newsd == NULL\n");
6946                 goto fail;
6947         }
6948         sd->dacl = security_acl_concatenate(frame,
6949                                         newsd->dacl,
6950                                         sd->dacl);
6951         if (sd->dacl == NULL) {
6952                 printf("sd->dacl == NULL\n");
6953                 goto fail;
6954         }
6955         status = cli_set_secdesc(cli, fnum, sd);
6956         if (!NT_STATUS_IS_OK(status)) {
6957                 printf("cli_set_secdesc failed for %s (%s)\n",
6958                         fname, nt_errstr(status));
6959                 goto fail;
6960         }
6961         status = cli_close(cli, fnum);
6962         if (!NT_STATUS_IS_OK(status)) {
6963                 printf("close failed for %s (%s)\n",
6964                         fname, nt_errstr(status));
6965                 goto fail;
6966         }
6967         fnum = (uint16_t)-1;
6968
6969         /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
6970         status = cli_ntcreate(cli,
6971                                 fname,
6972                                 0,
6973                                 FILE_READ_DATA|FILE_WRITE_DATA,
6974                                 FILE_ATTRIBUTE_NORMAL,
6975                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6976                                         FILE_SHARE_DELETE,
6977                                 FILE_OPEN,
6978                                 0,
6979                                 0,
6980                                 &fnum,
6981                                 NULL);
6982         if (!NT_STATUS_IS_OK(status)) {
6983                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6984                 goto fail;
6985         }
6986
6987         status = cli_close(cli, fnum);
6988         if (!NT_STATUS_IS_OK(status)) {
6989                 printf("close failed for %s (%s)\n",
6990                         fname, nt_errstr(status));
6991                 goto fail;
6992         }
6993
6994         cli_unlink(cli, fname,
6995                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6996
6997         TALLOC_FREE(frame);
6998         return true;
6999
7000   fail:
7001
7002         if (cli) {
7003                 if (fnum != (uint16_t)-1) {
7004                         cli_close(cli, fnum);
7005                 }
7006                 cli_unlink(cli, fname,
7007                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7008                 torture_close_connection(cli);
7009         }
7010
7011         TALLOC_FREE(frame);
7012         return false;
7013 }
7014
7015 /*
7016  * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7017  * Note this test only works with a user with SeSecurityPrivilege set.
7018  *
7019  * NB. This is also tested in samba3.base.createx_access
7020  * but this makes it very explicit what we're looking for.
7021  */
7022 static bool run_smb1_system_security(int dummy)
7023 {
7024         static struct cli_state *cli = NULL;
7025         const char *fname = "system_security.txt";
7026         uint16_t fnum = (uint16_t)-1;
7027         NTSTATUS status;
7028         TALLOC_CTX *frame = NULL;
7029
7030         frame = talloc_stackframe();
7031         printf("starting smb1 system security test\n");
7032
7033         /* SMB1 connection - torture_open_connection() forces this. */
7034         if (!torture_open_connection(&cli, 0)) {
7035                 goto fail;
7036         }
7037
7038         smbXcli_conn_set_sockopt(cli->conn, sockops);
7039
7040         /* Start with a clean slate. */
7041         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7042
7043         /* Create the test file. */
7044         status = cli_ntcreate(cli,
7045                                 fname,
7046                                 0,
7047                                 GENERIC_ALL_ACCESS,
7048                                 FILE_ATTRIBUTE_NORMAL,
7049                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7050                                         FILE_SHARE_DELETE,
7051                                 FILE_CREATE,
7052                                 0,
7053                                 0,
7054                                 &fnum,
7055                                 NULL);
7056         if (!NT_STATUS_IS_OK(status)) {
7057                 printf("Create of %s - %s\n", fname, nt_errstr(status));
7058                 goto fail;
7059         }
7060
7061         status = cli_close(cli, fnum);
7062
7063         /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7064         /*
7065          * On SMB1 this succeeds - SMB2 it fails,
7066          * see the SMB2-SACL test.
7067          */
7068         status = cli_ntcreate(cli,
7069                                 fname,
7070                                 0,
7071                                 SEC_FLAG_SYSTEM_SECURITY,
7072                                 FILE_ATTRIBUTE_NORMAL,
7073                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7074                                         FILE_SHARE_DELETE,
7075                                 FILE_OPEN,
7076                                 0,
7077                                 0,
7078                                 &fnum,
7079                                 NULL);
7080         if (!NT_STATUS_IS_OK(status)) {
7081                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7082                 goto fail;
7083         }
7084
7085         status = cli_close(cli, fnum);
7086
7087         cli_unlink(cli, fname,
7088                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7089
7090         torture_close_connection(cli);
7091         TALLOC_FREE(frame);
7092         return true;
7093
7094   fail:
7095
7096         if (cli) {
7097                 if (fnum != (uint16_t)-1) {
7098                         cli_close(cli, fnum);
7099                 }
7100                 cli_unlink(cli, fname,
7101                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7102                 torture_close_connection(cli);
7103         }
7104
7105         TALLOC_FREE(frame);
7106         return false;
7107 }
7108
7109 static bool run_pipe_number(int dummy)
7110 {
7111         struct cli_state *cli1;
7112         const char *pipe_name = "\\SPOOLSS";
7113         uint16_t fnum;
7114         int num_pipes = 0;
7115         NTSTATUS status;
7116
7117         printf("starting pipenumber test\n");
7118         if (!torture_open_connection(&cli1, 0)) {
7119                 return False;
7120         }
7121
7122         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7123         while(1) {
7124                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7125                                       FILE_ATTRIBUTE_NORMAL,
7126                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
7127                                       FILE_OPEN_IF, 0, 0, &fnum, NULL);
7128                 if (!NT_STATUS_IS_OK(status)) {
7129                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7130                         break;
7131                 }
7132                 num_pipes++;
7133                 printf("\r%6d", num_pipes);
7134         }
7135
7136         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7137         torture_close_connection(cli1);
7138         return True;
7139 }
7140
7141 /*
7142   Test open mode returns on read-only files.
7143  */
7144 static bool run_opentest(int dummy)
7145 {
7146         static struct cli_state *cli1;
7147         static struct cli_state *cli2;
7148         const char *fname = "\\readonly.file";
7149         uint16_t fnum1, fnum2;
7150         char buf[20];
7151         off_t fsize;
7152         bool correct = True;
7153         char *tmp_path;
7154         NTSTATUS status;
7155
7156         printf("starting open test\n");
7157
7158         if (!torture_open_connection(&cli1, 0)) {
7159                 return False;
7160         }
7161
7162         cli_setatr(cli1, fname, 0, 0);
7163         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7164
7165         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7166
7167         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7168         if (!NT_STATUS_IS_OK(status)) {
7169                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7170                 return False;
7171         }
7172
7173         status = cli_close(cli1, fnum1);
7174         if (!NT_STATUS_IS_OK(status)) {
7175                 printf("close2 failed (%s)\n", nt_errstr(status));
7176                 return False;
7177         }
7178
7179         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7180         if (!NT_STATUS_IS_OK(status)) {
7181                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7182                 return False;
7183         }
7184
7185         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7186         if (!NT_STATUS_IS_OK(status)) {
7187                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7188                 return False;
7189         }
7190
7191         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7192         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7193
7194         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7195                         NT_STATUS_ACCESS_DENIED)) {
7196                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7197         }
7198
7199         printf("finished open test 1\n");
7200
7201         cli_close(cli1, fnum1);
7202
7203         /* Now try not readonly and ensure ERRbadshare is returned. */
7204
7205         cli_setatr(cli1, fname, 0, 0);
7206
7207         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7208         if (!NT_STATUS_IS_OK(status)) {
7209                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7210                 return False;
7211         }
7212
7213         /* This will fail - but the error should be ERRshare. */
7214         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7215
7216         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7217                         NT_STATUS_SHARING_VIOLATION)) {
7218                 printf("correct error code ERRDOS/ERRbadshare returned\n");
7219         }
7220
7221         status = cli_close(cli1, fnum1);
7222         if (!NT_STATUS_IS_OK(status)) {
7223                 printf("close2 failed (%s)\n", nt_errstr(status));
7224                 return False;
7225         }
7226
7227         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7228
7229         printf("finished open test 2\n");
7230
7231         /* Test truncate open disposition on file opened for read. */
7232         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7233         if (!NT_STATUS_IS_OK(status)) {
7234                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7235                 return False;
7236         }
7237
7238         /* write 20 bytes. */
7239
7240         memset(buf, '\0', 20);
7241
7242         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7243         if (!NT_STATUS_IS_OK(status)) {
7244                 printf("write failed (%s)\n", nt_errstr(status));
7245                 correct = False;
7246         }
7247
7248         status = cli_close(cli1, fnum1);
7249         if (!NT_STATUS_IS_OK(status)) {
7250                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7251                 return False;
7252         }
7253
7254         /* Ensure size == 20. */
7255         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7256         if (!NT_STATUS_IS_OK(status)) {
7257                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7258                 return False;
7259         }
7260
7261         if (fsize != 20) {
7262                 printf("(3) file size != 20\n");
7263                 return False;
7264         }
7265
7266         /* Now test if we can truncate a file opened for readonly. */
7267         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7268         if (!NT_STATUS_IS_OK(status)) {
7269                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7270                 return False;
7271         }
7272
7273         status = cli_close(cli1, fnum1);
7274         if (!NT_STATUS_IS_OK(status)) {
7275                 printf("close2 failed (%s)\n", nt_errstr(status));
7276                 return False;
7277         }
7278
7279         /* Ensure size == 0. */
7280         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7281         if (!NT_STATUS_IS_OK(status)) {
7282                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7283                 return False;
7284         }
7285
7286         if (fsize != 0) {
7287                 printf("(3) file size != 0\n");
7288                 return False;
7289         }
7290         printf("finished open test 3\n");
7291
7292         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7293
7294         printf("Do ctemp tests\n");
7295         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7296         if (!NT_STATUS_IS_OK(status)) {
7297                 printf("ctemp failed (%s)\n", nt_errstr(status));
7298                 return False;
7299         }
7300
7301         printf("ctemp gave path %s\n", tmp_path);
7302         status = cli_close(cli1, fnum1);
7303         if (!NT_STATUS_IS_OK(status)) {
7304                 printf("close of temp failed (%s)\n", nt_errstr(status));
7305         }
7306
7307         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7308         if (!NT_STATUS_IS_OK(status)) {
7309                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7310         }
7311
7312         /* Test the non-io opens... */
7313
7314         if (!torture_open_connection(&cli2, 1)) {
7315                 return False;
7316         }
7317
7318         cli_setatr(cli2, fname, 0, 0);
7319         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7320
7321         smbXcli_conn_set_sockopt(cli2->conn, sockops);
7322
7323         printf("TEST #1 testing 2 non-io opens (no delete)\n");
7324         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7325                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7326                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7327         if (!NT_STATUS_IS_OK(status)) {
7328                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7329                 return False;
7330         }
7331
7332         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7333                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7334                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7335         if (!NT_STATUS_IS_OK(status)) {
7336                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7337                 return False;
7338         }
7339
7340         status = cli_close(cli1, fnum1);
7341         if (!NT_STATUS_IS_OK(status)) {
7342                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7343                 return False;
7344         }
7345
7346         status = cli_close(cli2, fnum2);
7347         if (!NT_STATUS_IS_OK(status)) {
7348                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7349                 return False;
7350         }
7351
7352         printf("non-io open test #1 passed.\n");
7353
7354         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7355
7356         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7357
7358         status = cli_ntcreate(cli1, fname, 0,
7359                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7360                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7361                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7362         if (!NT_STATUS_IS_OK(status)) {
7363                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7364                 return False;
7365         }
7366
7367         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7368                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7369                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7370         if (!NT_STATUS_IS_OK(status)) {
7371                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7372                 return False;
7373         }
7374
7375         status = cli_close(cli1, fnum1);
7376         if (!NT_STATUS_IS_OK(status)) {
7377                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7378                 return False;
7379         }
7380
7381         status = cli_close(cli2, fnum2);
7382         if (!NT_STATUS_IS_OK(status)) {
7383                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7384                 return False;
7385         }
7386
7387         printf("non-io open test #2 passed.\n");
7388
7389         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7390
7391         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7392
7393         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7394                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7395                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7396         if (!NT_STATUS_IS_OK(status)) {
7397                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7398                 return False;
7399         }
7400
7401         status = cli_ntcreate(cli2, fname, 0,
7402                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7403                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7404                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7405         if (!NT_STATUS_IS_OK(status)) {
7406                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7407                 return False;
7408         }
7409
7410         status = cli_close(cli1, fnum1);
7411         if (!NT_STATUS_IS_OK(status)) {
7412                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7413                 return False;
7414         }
7415
7416         status = cli_close(cli2, fnum2);
7417         if (!NT_STATUS_IS_OK(status)) {
7418                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7419                 return False;
7420         }
7421
7422         printf("non-io open test #3 passed.\n");
7423
7424         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7425
7426         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7427
7428         status = cli_ntcreate(cli1, fname, 0,
7429                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7430                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7431                                FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7432         if (!NT_STATUS_IS_OK(status)) {
7433                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7434                 return False;
7435         }
7436
7437         status = cli_ntcreate(cli2, fname, 0,
7438                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7439                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7440                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7441         if (NT_STATUS_IS_OK(status)) {
7442                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7443                 return False;
7444         }
7445
7446         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7447
7448         status = cli_close(cli1, fnum1);
7449         if (!NT_STATUS_IS_OK(status)) {
7450                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7451                 return False;
7452         }
7453
7454         printf("non-io open test #4 passed.\n");
7455
7456         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7457
7458         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7459
7460         status = cli_ntcreate(cli1, fname, 0,
7461                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7462                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7463                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7464         if (!NT_STATUS_IS_OK(status)) {
7465                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7466                 return False;
7467         }
7468
7469         status = cli_ntcreate(cli2, fname, 0,
7470                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7471                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7472                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7473         if (!NT_STATUS_IS_OK(status)) {
7474                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7475                 return False;
7476         }
7477
7478         status = cli_close(cli1, fnum1);
7479         if (!NT_STATUS_IS_OK(status)) {
7480                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7481                 return False;
7482         }
7483
7484         status = cli_close(cli2, fnum2);
7485         if (!NT_STATUS_IS_OK(status)) {
7486                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7487                 return False;
7488         }
7489
7490         printf("non-io open test #5 passed.\n");
7491
7492         printf("TEST #6 testing 1 non-io open, one io open\n");
7493
7494         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7495
7496         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7497                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7498                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7499         if (!NT_STATUS_IS_OK(status)) {
7500                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7501                 return False;
7502         }
7503
7504         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7505                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7506                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7507         if (!NT_STATUS_IS_OK(status)) {
7508                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7509                 return False;
7510         }
7511
7512         status = cli_close(cli1, fnum1);
7513         if (!NT_STATUS_IS_OK(status)) {
7514                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7515                 return False;
7516         }
7517
7518         status = cli_close(cli2, fnum2);
7519         if (!NT_STATUS_IS_OK(status)) {
7520                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7521                 return False;
7522         }
7523
7524         printf("non-io open test #6 passed.\n");
7525
7526         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7527
7528         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7529
7530         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7531                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7532                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7533         if (!NT_STATUS_IS_OK(status)) {
7534                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7535                 return False;
7536         }
7537
7538         status = cli_ntcreate(cli2, fname, 0,
7539                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7540                               FILE_ATTRIBUTE_NORMAL,
7541                               FILE_SHARE_READ|FILE_SHARE_DELETE,
7542                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7543         if (NT_STATUS_IS_OK(status)) {
7544                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7545                 return False;
7546         }
7547
7548         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7549
7550         status = cli_close(cli1, fnum1);
7551         if (!NT_STATUS_IS_OK(status)) {
7552                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7553                 return False;
7554         }
7555
7556         printf("non-io open test #7 passed.\n");
7557
7558         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7559
7560         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7561         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7562                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7563                                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7564         if (!NT_STATUS_IS_OK(status)) {
7565                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7566                 correct = false;
7567                 goto out;
7568         }
7569
7570         /* Write to ensure we have to update the file time. */
7571         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7572                               NULL);
7573         if (!NT_STATUS_IS_OK(status)) {
7574                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7575                 correct = false;
7576                 goto out;
7577         }
7578
7579         status = cli_close(cli1, fnum1);
7580         if (!NT_STATUS_IS_OK(status)) {
7581                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7582                 correct = false;
7583         }
7584
7585   out:
7586
7587         if (!torture_close_connection(cli1)) {
7588                 correct = False;
7589         }
7590         if (!torture_close_connection(cli2)) {
7591                 correct = False;
7592         }
7593
7594         return correct;
7595 }
7596
7597 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7598 {
7599         uint16_t major, minor;
7600         uint32_t caplow, caphigh;
7601         NTSTATUS status;
7602
7603         if (!SERVER_HAS_UNIX_CIFS(cli)) {
7604                 printf("Server doesn't support UNIX CIFS extensions.\n");
7605                 return NT_STATUS_NOT_SUPPORTED;
7606         }
7607
7608         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7609                                              &caphigh);
7610         if (!NT_STATUS_IS_OK(status)) {
7611                 printf("Server didn't return UNIX CIFS extensions: %s\n",
7612                        nt_errstr(status));
7613                 return status;
7614         }
7615
7616         status = cli_set_unix_extensions_capabilities(cli, major, minor,
7617                                                       caplow, caphigh);
7618         if (!NT_STATUS_IS_OK(status)) {
7619                 printf("Server doesn't support setting UNIX CIFS extensions: "
7620                        "%s.\n", nt_errstr(status));
7621                 return status;
7622         }
7623
7624         return NT_STATUS_OK;
7625 }
7626
7627 /*
7628   Test POSIX open /mkdir calls.
7629  */
7630 static bool run_simple_posix_open_test(int dummy)
7631 {
7632         static struct cli_state *cli1;
7633         const char *fname = "posix:file";
7634         const char *hname = "posix:hlink";
7635         const char *sname = "posix:symlink";
7636         const char *dname = "posix:dir";
7637         char buf[10];
7638         char *target = NULL;
7639         uint16_t fnum1 = (uint16_t)-1;
7640         SMB_STRUCT_STAT sbuf;
7641         bool correct = false;
7642         NTSTATUS status;
7643         size_t nread;
7644         const char *fname_windows = "windows_file";
7645         uint16_t fnum2 = (uint16_t)-1;
7646
7647         printf("Starting simple POSIX open test\n");
7648
7649         if (!torture_open_connection(&cli1, 0)) {
7650                 return false;
7651         }
7652
7653         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7654
7655         status = torture_setup_unix_extensions(cli1);
7656         if (!NT_STATUS_IS_OK(status)) {
7657                 return false;
7658         }
7659
7660         cli_setatr(cli1, fname, 0, 0);
7661         cli_posix_unlink(cli1, fname);
7662         cli_setatr(cli1, dname, 0, 0);
7663         cli_posix_rmdir(cli1, dname);
7664         cli_setatr(cli1, hname, 0, 0);
7665         cli_posix_unlink(cli1, hname);
7666         cli_setatr(cli1, sname, 0, 0);
7667         cli_posix_unlink(cli1, sname);
7668         cli_setatr(cli1, fname_windows, 0, 0);
7669         cli_posix_unlink(cli1, fname_windows);
7670
7671         /* Create a directory. */
7672         status = cli_posix_mkdir(cli1, dname, 0777);
7673         if (!NT_STATUS_IS_OK(status)) {
7674                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7675                 goto out;
7676         }
7677
7678         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7679                                 0600, &fnum1);
7680         if (!NT_STATUS_IS_OK(status)) {
7681                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7682                 goto out;
7683         }
7684
7685         /* Test ftruncate - set file size. */
7686         status = cli_ftruncate(cli1, fnum1, 1000);
7687         if (!NT_STATUS_IS_OK(status)) {
7688                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7689                 goto out;
7690         }
7691
7692         /* Ensure st_size == 1000 */
7693         status = cli_posix_stat(cli1, fname, &sbuf);
7694         if (!NT_STATUS_IS_OK(status)) {
7695                 printf("stat failed (%s)\n", nt_errstr(status));
7696                 goto out;
7697         }
7698
7699         if (sbuf.st_ex_size != 1000) {
7700                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7701                 goto out;
7702         }
7703
7704         /* Ensure st_mode == 0600 */
7705         if ((sbuf.st_ex_mode & 07777) != 0600) {
7706                 printf("posix_open - bad permissions 0%o != 0600\n",
7707                                 (unsigned int)(sbuf.st_ex_mode & 07777));
7708                 goto out;
7709         }
7710
7711         /* Test ftruncate - set file size back to zero. */
7712         status = cli_ftruncate(cli1, fnum1, 0);
7713         if (!NT_STATUS_IS_OK(status)) {
7714                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7715                 goto out;
7716         }
7717
7718         status = cli_close(cli1, fnum1);
7719         if (!NT_STATUS_IS_OK(status)) {
7720                 printf("close failed (%s)\n", nt_errstr(status));
7721                 goto out;
7722         }
7723
7724         /* Now open the file again for read only. */
7725         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7726         if (!NT_STATUS_IS_OK(status)) {
7727                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7728                 goto out;
7729         }
7730
7731         /* Now unlink while open. */
7732         status = cli_posix_unlink(cli1, fname);
7733         if (!NT_STATUS_IS_OK(status)) {
7734                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7735                 goto out;
7736         }
7737
7738         status = cli_close(cli1, fnum1);
7739         if (!NT_STATUS_IS_OK(status)) {
7740                 printf("close(2) failed (%s)\n", nt_errstr(status));
7741                 goto out;
7742         }
7743
7744         /* Ensure the file has gone. */
7745         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7746         if (NT_STATUS_IS_OK(status)) {
7747                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7748                 goto out;
7749         }
7750
7751         /* Create again to test open with O_TRUNC. */
7752         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7753         if (!NT_STATUS_IS_OK(status)) {
7754                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7755                 goto out;
7756         }
7757
7758         /* Test ftruncate - set file size. */
7759         status = cli_ftruncate(cli1, fnum1, 1000);
7760         if (!NT_STATUS_IS_OK(status)) {
7761                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7762                 goto out;
7763         }
7764
7765         /* Ensure st_size == 1000 */
7766         status = cli_posix_stat(cli1, fname, &sbuf);
7767         if (!NT_STATUS_IS_OK(status)) {
7768                 printf("stat failed (%s)\n", nt_errstr(status));
7769                 goto out;
7770         }
7771
7772         if (sbuf.st_ex_size != 1000) {
7773                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7774                 goto out;
7775         }
7776
7777         status = cli_close(cli1, fnum1);
7778         if (!NT_STATUS_IS_OK(status)) {
7779                 printf("close(2) failed (%s)\n", nt_errstr(status));
7780                 goto out;
7781         }
7782
7783         /* Re-open with O_TRUNC. */
7784         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7785         if (!NT_STATUS_IS_OK(status)) {
7786                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7787                 goto out;
7788         }
7789
7790         /* Ensure st_size == 0 */
7791         status = cli_posix_stat(cli1, fname, &sbuf);
7792         if (!NT_STATUS_IS_OK(status)) {
7793                 printf("stat failed (%s)\n", nt_errstr(status));
7794                 goto out;
7795         }
7796
7797         if (sbuf.st_ex_size != 0) {
7798                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7799                 goto out;
7800         }
7801
7802         status = cli_close(cli1, fnum1);
7803         if (!NT_STATUS_IS_OK(status)) {
7804                 printf("close failed (%s)\n", nt_errstr(status));
7805                 goto out;
7806         }
7807
7808         status = cli_posix_unlink(cli1, fname);
7809         if (!NT_STATUS_IS_OK(status)) {
7810                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7811                 goto out;
7812         }
7813
7814         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
7815         if (!NT_STATUS_IS_OK(status)) {
7816                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
7817                         dname, nt_errstr(status));
7818                 goto out;
7819         }
7820
7821         cli_close(cli1, fnum1);
7822
7823         /* What happens when we try and POSIX open a directory for write ? */
7824         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
7825         if (NT_STATUS_IS_OK(status)) {
7826                 printf("POSIX open of directory %s succeeded, "
7827                        "should have failed.\n",
7828                        dname);
7829                 goto out;
7830         } else {
7831                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
7832                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
7833                         goto out;
7834                 }
7835         }
7836
7837         /* Create the file. */
7838         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7839                                 0600, &fnum1);
7840         if (!NT_STATUS_IS_OK(status)) {
7841                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7842                 goto out;
7843         }
7844
7845         /* Write some data into it. */
7846         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7847                               NULL);
7848         if (!NT_STATUS_IS_OK(status)) {
7849                 printf("cli_write failed: %s\n", nt_errstr(status));
7850                 goto out;
7851         }
7852
7853         cli_close(cli1, fnum1);
7854
7855         /* Now create a hardlink. */
7856         status = cli_posix_hardlink(cli1, fname, hname);
7857         if (!NT_STATUS_IS_OK(status)) {
7858                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
7859                 goto out;
7860         }
7861
7862         /* Now create a symlink. */
7863         status = cli_posix_symlink(cli1, fname, sname);
7864         if (!NT_STATUS_IS_OK(status)) {
7865                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
7866                 goto out;
7867         }
7868
7869         /* Open the hardlink for read. */
7870         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
7871         if (!NT_STATUS_IS_OK(status)) {
7872                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
7873                 goto out;
7874         }
7875
7876         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
7877         if (!NT_STATUS_IS_OK(status)) {
7878                 printf("POSIX read of %s failed (%s)\n", hname,
7879                        nt_errstr(status));
7880                 goto out;
7881         } else if (nread != 10) {
7882                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
7883                        hname, (unsigned long)nread, 10);
7884                 goto out;
7885         }
7886
7887         if (memcmp(buf, "TEST DATA\n", 10)) {
7888                 printf("invalid data read from hardlink\n");
7889                 goto out;
7890         }
7891
7892         /* Do a POSIX lock/unlock. */
7893         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
7894         if (!NT_STATUS_IS_OK(status)) {
7895                 printf("POSIX lock failed %s\n", nt_errstr(status));
7896                 goto out;
7897         }
7898
7899         /* Punch a hole in the locked area. */
7900         status = cli_posix_unlock(cli1, fnum1, 10, 80);
7901         if (!NT_STATUS_IS_OK(status)) {
7902                 printf("POSIX unlock failed %s\n", nt_errstr(status));
7903                 goto out;
7904         }
7905
7906         cli_close(cli1, fnum1);
7907
7908         /* Open the symlink for read - this should fail. A POSIX
7909            client should not be doing opens on a symlink. */
7910         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
7911         if (NT_STATUS_IS_OK(status)) {
7912                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
7913                 goto out;
7914         } else {
7915                 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
7916                                 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
7917                         printf("POSIX open of %s should have failed "
7918                                 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
7919                                 "failed with %s instead.\n",
7920                                 sname, nt_errstr(status));
7921                         goto out;
7922                 }
7923         }
7924
7925         status = cli_posix_readlink(cli1, sname, talloc_tos(), &target);
7926         if (!NT_STATUS_IS_OK(status)) {
7927                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
7928                 goto out;
7929         }
7930
7931         if (strcmp(target, fname) != 0) {
7932                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
7933                         sname, fname, target);
7934                 goto out;
7935         }
7936
7937         status = cli_posix_rmdir(cli1, dname);
7938         if (!NT_STATUS_IS_OK(status)) {
7939                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
7940                 goto out;
7941         }
7942
7943         /* Check directory opens with a specific permission. */
7944         status = cli_posix_mkdir(cli1, dname, 0700);
7945         if (!NT_STATUS_IS_OK(status)) {
7946                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7947                 goto out;
7948         }
7949
7950         /* Ensure st_mode == 0700 */
7951         status = cli_posix_stat(cli1, dname, &sbuf);
7952         if (!NT_STATUS_IS_OK(status)) {
7953                 printf("stat failed (%s)\n", nt_errstr(status));
7954                 goto out;
7955         }
7956
7957         if ((sbuf.st_ex_mode & 07777) != 0700) {
7958                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
7959                                 (unsigned int)(sbuf.st_ex_mode & 07777));
7960                 goto out;
7961         }
7962
7963         /*
7964          * Now create a Windows file, and attempt a POSIX unlink.
7965          * This should fail with a sharing violation but due to:
7966          *
7967          * [Bug 9571] Unlink after open causes smbd to panic
7968          *
7969          * ensure we've fixed the lock ordering violation.
7970          */
7971
7972         status = cli_ntcreate(cli1, fname_windows, 0,
7973                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
7974                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7975                         FILE_CREATE,
7976                         0x0, 0x0, &fnum2, NULL);
7977         if (!NT_STATUS_IS_OK(status)) {
7978                 printf("Windows create of %s failed (%s)\n", fname_windows,
7979                         nt_errstr(status));
7980                 goto out;
7981         }
7982
7983         /* Now try posix_unlink. */
7984         status = cli_posix_unlink(cli1, fname_windows);
7985         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7986                 printf("POSIX unlink of %s should fail "
7987                         "with NT_STATUS_SHARING_VIOLATION "
7988                         "got %s instead !\n",
7989                         fname_windows,
7990                         nt_errstr(status));
7991                 goto out;
7992         }
7993
7994         cli_close(cli1, fnum2);
7995
7996         printf("Simple POSIX open test passed\n");
7997         correct = true;
7998
7999   out:
8000
8001         if (fnum1 != (uint16_t)-1) {
8002                 cli_close(cli1, fnum1);
8003                 fnum1 = (uint16_t)-1;
8004         }
8005
8006         if (fnum2 != (uint16_t)-1) {
8007                 cli_close(cli1, fnum2);
8008                 fnum2 = (uint16_t)-1;
8009         }
8010
8011         cli_setatr(cli1, sname, 0, 0);
8012         cli_posix_unlink(cli1, sname);
8013         cli_setatr(cli1, hname, 0, 0);
8014         cli_posix_unlink(cli1, hname);
8015         cli_setatr(cli1, fname, 0, 0);
8016         cli_posix_unlink(cli1, fname);
8017         cli_setatr(cli1, dname, 0, 0);
8018         cli_posix_rmdir(cli1, dname);
8019         cli_setatr(cli1, fname_windows, 0, 0);
8020         cli_posix_unlink(cli1, fname_windows);
8021
8022         if (!torture_close_connection(cli1)) {
8023                 correct = false;
8024         }
8025
8026         return correct;
8027 }
8028
8029 /*
8030   Test POSIX and Windows ACLs are rejected on symlinks.
8031  */
8032 static bool run_acl_symlink_test(int dummy)
8033 {
8034         static struct cli_state *cli;
8035         const char *fname = "posix_file";
8036         const char *sname = "posix_symlink";
8037         uint16_t fnum = (uint16_t)-1;
8038         bool correct = false;
8039         NTSTATUS status;
8040         char *posix_acl = NULL;
8041         size_t posix_acl_len = 0;
8042         char *posix_acl_sym = NULL;
8043         size_t posix_acl_len_sym = 0;
8044         struct security_descriptor *sd = NULL;
8045         struct security_descriptor *sd_sym = NULL;
8046         TALLOC_CTX *frame = NULL;
8047
8048         frame = talloc_stackframe();
8049
8050         printf("Starting acl symlink test\n");
8051
8052         if (!torture_open_connection(&cli, 0)) {
8053                 TALLOC_FREE(frame);
8054                 return false;
8055         }
8056
8057         smbXcli_conn_set_sockopt(cli->conn, sockops);
8058
8059         status = torture_setup_unix_extensions(cli);
8060         if (!NT_STATUS_IS_OK(status)) {
8061                 TALLOC_FREE(frame);
8062                 return false;
8063         }
8064
8065         cli_setatr(cli, fname, 0, 0);
8066         cli_posix_unlink(cli, fname);
8067         cli_setatr(cli, sname, 0, 0);
8068         cli_posix_unlink(cli, sname);
8069
8070         status = cli_ntcreate(cli,
8071                         fname,
8072                         0,
8073                         READ_CONTROL_ACCESS,
8074                         0,
8075                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8076                         FILE_CREATE,
8077                         0x0,
8078                         0x0,
8079                         &fnum,
8080                         NULL);
8081
8082         if (!NT_STATUS_IS_OK(status)) {
8083                 printf("cli_ntcreate of %s failed (%s)\n",
8084                         fname,
8085                         nt_errstr(status));
8086                 goto out;
8087         }
8088
8089         /* Get the Windows ACL on the file. */
8090         status = cli_query_secdesc(cli,
8091                                 fnum,
8092                                 frame,
8093                                 &sd);
8094         if (!NT_STATUS_IS_OK(status)) {
8095                 printf("cli_query_secdesc failed (%s)\n",
8096                         nt_errstr(status));
8097                 goto out;
8098         }
8099
8100         /* Get the POSIX ACL on the file. */
8101         status = cli_posix_getacl(cli,
8102                                 fname,
8103                                 frame,
8104                                 &posix_acl_len,
8105                                 &posix_acl);
8106
8107         if (!NT_STATUS_IS_OK(status)) {
8108                 printf("cli_posix_getacl failed (%s)\n",
8109                         nt_errstr(status));
8110                 goto out;
8111         }
8112
8113         status = cli_close(cli, fnum);
8114         if (!NT_STATUS_IS_OK(status)) {
8115                 printf("close failed (%s)\n", nt_errstr(status));
8116                 goto out;
8117         }
8118         fnum = (uint16_t)-1;
8119
8120         /* Now create a symlink. */
8121         status = cli_posix_symlink(cli, fname, sname);
8122         if (!NT_STATUS_IS_OK(status)) {
8123                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8124                         sname,
8125                         fname,
8126                         nt_errstr(status));
8127                 goto out;
8128         }
8129
8130         /* Open a handle on the symlink for SD set/get should fail. */
8131         status = cli_ntcreate(cli,
8132                         sname,
8133                         0,
8134                         READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8135                         0,
8136                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8137                         FILE_OPEN,
8138                         0x0,
8139                         0x0,
8140                         &fnum,
8141                         NULL);
8142
8143         if (NT_STATUS_IS_OK(status)) {
8144                 printf("Symlink open for getsd/setsd of %s "
8145                         "succeeded (should fail)\n",
8146                         sname);
8147                 goto out;
8148         }
8149
8150         /* Open a handle on the symlink. */
8151         status = cli_ntcreate(cli,
8152                         sname,
8153                         0,
8154                         FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8155                         0,
8156                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8157                         FILE_OPEN,
8158                         0x0,
8159                         0x0,
8160                         &fnum,
8161                         NULL);
8162
8163         if (!NT_STATUS_IS_OK(status)) {
8164                 printf("cli_posix_open of %s failed (%s)\n",
8165                         sname,
8166                         nt_errstr(status));
8167                 goto out;
8168         }
8169
8170         /* Get the Windows ACL on the symlink handle. Should fail */
8171         status = cli_query_secdesc(cli,
8172                                 fnum,
8173                                 frame,
8174                                 &sd_sym);
8175
8176         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8177                 printf("cli_query_secdesc on a symlink gave %s. "
8178                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8179                         nt_errstr(status));
8180                 goto out;
8181         }
8182
8183         /* Get the POSIX ACL on the symlink pathname. Should fail. */
8184         status = cli_posix_getacl(cli,
8185                                 sname,
8186                                 frame,
8187                                 &posix_acl_len_sym,
8188                                 &posix_acl_sym);
8189
8190         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8191                 printf("cli_posix_getacl on a symlink gave %s. "
8192                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8193                         nt_errstr(status));
8194                 goto out;
8195         }
8196
8197         /* Set the Windows ACL on the symlink handle. Should fail */
8198         status = cli_set_security_descriptor(cli,
8199                                 fnum,
8200                                 SECINFO_DACL,
8201                                 sd);
8202
8203         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8204                 printf("cli_query_secdesc on a symlink gave %s. "
8205                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8206                         nt_errstr(status));
8207                 goto out;
8208         }
8209
8210         /* Set the POSIX ACL on the symlink pathname. Should fail. */
8211         status = cli_posix_setacl(cli,
8212                                 sname,
8213                                 posix_acl,
8214                                 posix_acl_len);
8215
8216         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8217                 printf("cli_posix_setacl on a symlink gave %s. "
8218                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8219                         nt_errstr(status));
8220                 goto out;
8221         }
8222
8223         printf("ACL symlink test passed\n");
8224         correct = true;
8225
8226   out:
8227
8228         if (fnum != (uint16_t)-1) {
8229                 cli_close(cli, fnum);
8230                 fnum = (uint16_t)-1;
8231         }
8232
8233         cli_setatr(cli, sname, 0, 0);
8234         cli_posix_unlink(cli, sname);
8235         cli_setatr(cli, fname, 0, 0);
8236         cli_posix_unlink(cli, fname);
8237
8238         if (!torture_close_connection(cli)) {
8239                 correct = false;
8240         }
8241
8242         TALLOC_FREE(frame);
8243         return correct;
8244 }
8245
8246 /*
8247   Test POSIX can delete a file containing streams.
8248  */
8249 static bool run_posix_stream_delete(int dummy)
8250 {
8251         struct cli_state *cli1 = NULL;
8252         struct cli_state *cli2 = NULL;
8253         const char *fname = "streamfile";
8254         const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8255         uint16_t fnum1 = (uint16_t)-1;
8256         bool correct = false;
8257         NTSTATUS status;
8258         TALLOC_CTX *frame = NULL;
8259
8260         frame = talloc_stackframe();
8261
8262         printf("Starting POSIX stream delete test\n");
8263
8264         if (!torture_open_connection(&cli1, 0) ||
8265                         !torture_open_connection(&cli2, 1)) {
8266                 TALLOC_FREE(frame);
8267                 return false;
8268         }
8269
8270         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8271         smbXcli_conn_set_sockopt(cli2->conn, sockops);
8272
8273         status = torture_setup_unix_extensions(cli2);
8274         if (!NT_STATUS_IS_OK(status)) {
8275                 goto out;
8276         }
8277
8278         cli_setatr(cli1, fname, 0, 0);
8279         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8280
8281         /* Create the file. */
8282         status = cli_ntcreate(cli1,
8283                         fname,
8284                         0,
8285                         READ_CONTROL_ACCESS,
8286                         0,
8287                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8288                         FILE_CREATE,
8289                         0x0,
8290                         0x0,
8291                         &fnum1,
8292                         NULL);
8293
8294         if (!NT_STATUS_IS_OK(status)) {
8295                 printf("cli_ntcreate of %s failed (%s)\n",
8296                         fname,
8297                         nt_errstr(status));
8298                 goto out;
8299         }
8300
8301         status = cli_close(cli1, fnum1);
8302         if (!NT_STATUS_IS_OK(status)) {
8303                 printf("cli_close of %s failed (%s)\n",
8304                         fname,
8305                         nt_errstr(status));
8306                 goto out;
8307         }
8308         fnum1 = (uint16_t)-1;
8309
8310         /* Now create the stream. */
8311         status = cli_ntcreate(cli1,
8312                         stream_fname,
8313                         0,
8314                         FILE_WRITE_DATA,
8315                         0,
8316                         FILE_SHARE_READ|FILE_SHARE_WRITE,
8317                         FILE_CREATE,
8318                         0x0,
8319                         0x0,
8320                         &fnum1,
8321                         NULL);
8322
8323         if (!NT_STATUS_IS_OK(status)) {
8324                 printf("cli_ntcreate of %s failed (%s)\n",
8325                         stream_fname,
8326                         nt_errstr(status));
8327                 goto out;
8328         }
8329
8330         /* Leave the stream handle open... */
8331
8332         /* POSIX unlink should fail. */
8333         status = cli_posix_unlink(cli2, fname);
8334         if (NT_STATUS_IS_OK(status)) {
8335                 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8336                         fname);
8337                 goto out;
8338         }
8339
8340         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8341                 printf("cli_posix_unlink of %s failed with (%s) "
8342                         "should have been NT_STATUS_SHARING_VIOLATION\n",
8343                         fname,
8344                         nt_errstr(status));
8345                 goto out;
8346         }
8347
8348         /* Close the stream handle. */
8349         status = cli_close(cli1, fnum1);
8350         if (!NT_STATUS_IS_OK(status)) {
8351                 printf("cli_close of %s failed (%s)\n",
8352                         stream_fname,
8353                         nt_errstr(status));
8354                 goto out;
8355         }
8356         fnum1 = (uint16_t)-1;
8357
8358         /* POSIX unlink after stream handle closed should succeed. */
8359         status = cli_posix_unlink(cli2, fname);
8360         if (!NT_STATUS_IS_OK(status)) {
8361                 printf("cli_posix_unlink of %s failed (%s)\n",
8362                         fname,
8363                         nt_errstr(status));
8364                 goto out;
8365         }
8366
8367         printf("POSIX stream delete test passed\n");
8368         correct = true;
8369
8370   out:
8371
8372         if (fnum1 != (uint16_t)-1) {
8373                 cli_close(cli1, fnum1);
8374                 fnum1 = (uint16_t)-1;
8375         }
8376
8377         cli_setatr(cli1, fname, 0, 0);
8378         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8379
8380         if (!torture_close_connection(cli1)) {
8381                 correct = false;
8382         }
8383         if (!torture_close_connection(cli2)) {
8384                 correct = false;
8385         }
8386
8387         TALLOC_FREE(frame);
8388         return correct;
8389 }
8390
8391 /*
8392   Test setting EA's are rejected on symlinks.
8393  */
8394 static bool run_ea_symlink_test(int dummy)
8395 {
8396         static struct cli_state *cli;
8397         const char *fname = "posix_file_ea";
8398         const char *sname = "posix_symlink_ea";
8399         const char *ea_name = "testea_name";
8400         const char *ea_value = "testea_value";
8401         uint16_t fnum = (uint16_t)-1;
8402         bool correct = false;
8403         NTSTATUS status;
8404         size_t i, num_eas;
8405         struct ea_struct *eas = NULL;
8406         TALLOC_CTX *frame = NULL;
8407
8408         frame = talloc_stackframe();
8409
8410         printf("Starting EA symlink test\n");
8411
8412         if (!torture_open_connection(&cli, 0)) {
8413                 TALLOC_FREE(frame);
8414                 return false;
8415         }
8416
8417         smbXcli_conn_set_sockopt(cli->conn, sockops);
8418
8419         status = torture_setup_unix_extensions(cli);
8420         if (!NT_STATUS_IS_OK(status)) {
8421                 TALLOC_FREE(frame);
8422                 return false;
8423         }
8424
8425         cli_setatr(cli, fname, 0, 0);
8426         cli_posix_unlink(cli, fname);
8427         cli_setatr(cli, sname, 0, 0);
8428         cli_posix_unlink(cli, sname);
8429
8430         status = cli_ntcreate(cli,
8431                         fname,
8432                         0,
8433                         READ_CONTROL_ACCESS,
8434                         0,
8435                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8436                         FILE_CREATE,
8437                         0x0,
8438                         0x0,
8439                         &fnum,
8440                         NULL);
8441
8442         if (!NT_STATUS_IS_OK(status)) {
8443                 printf("cli_ntcreate of %s failed (%s)\n",
8444                         fname,
8445                         nt_errstr(status));
8446                 goto out;
8447         }
8448
8449         status = cli_close(cli, fnum);
8450         if (!NT_STATUS_IS_OK(status)) {
8451                 printf("close failed (%s)\n",
8452                         nt_errstr(status));
8453                 goto out;
8454         }
8455         fnum = (uint16_t)-1;
8456
8457         /* Set an EA on the path. */
8458         status = cli_set_ea_path(cli,
8459                                 fname,
8460                                 ea_name,
8461                                 ea_value,
8462                                 strlen(ea_value)+1);
8463
8464         if (!NT_STATUS_IS_OK(status)) {
8465                 printf("cli_set_ea_path failed (%s)\n",
8466                         nt_errstr(status));
8467                 goto out;
8468         }
8469
8470         /* Now create a symlink. */
8471         status = cli_posix_symlink(cli, fname, sname);
8472         if (!NT_STATUS_IS_OK(status)) {
8473                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8474                         sname,
8475                         fname,
8476                         nt_errstr(status));
8477                 goto out;
8478         }
8479
8480         /* Get the EA list on the path. Should return value set. */
8481         status = cli_get_ea_list_path(cli,
8482                                 fname,
8483                                 frame,
8484                                 &num_eas,
8485                                 &eas);
8486
8487         if (!NT_STATUS_IS_OK(status)) {
8488                 printf("cli_get_ea_list_path failed (%s)\n",
8489                         nt_errstr(status));
8490                 goto out;
8491         }
8492
8493         /* Ensure the EA we set is there. */
8494         for (i=0; i<num_eas; i++) {
8495                 if (strcmp(eas[i].name, ea_name) == 0 &&
8496                                 eas[i].value.length == strlen(ea_value)+1 &&
8497                                 memcmp(eas[i].value.data,
8498                                         ea_value,
8499                                         eas[i].value.length) == 0) {
8500                         break;
8501                 }
8502         }
8503
8504         if (i == num_eas) {
8505                 printf("Didn't find EA on pathname %s\n",
8506                         fname);
8507                 goto out;
8508         }
8509
8510         num_eas = 0;
8511         TALLOC_FREE(eas);
8512
8513         /* Get the EA list on the symlink. Should return empty list. */
8514         status = cli_get_ea_list_path(cli,
8515                                 sname,
8516                                 frame,
8517                                 &num_eas,
8518                                 &eas);
8519
8520         if (!NT_STATUS_IS_OK(status)) {
8521                 printf("cli_get_ea_list_path failed (%s)\n",
8522                         nt_errstr(status));
8523                 goto out;
8524         }
8525
8526         if (num_eas != 0) {
8527                 printf("cli_get_ea_list_path failed (%s)\n",
8528                         nt_errstr(status));
8529                 goto out;
8530         }
8531
8532         /* Set an EA on the symlink. Should fail. */
8533         status = cli_set_ea_path(cli,
8534                                 sname,
8535                                 ea_name,
8536                                 ea_value,
8537                                 strlen(ea_value)+1);
8538
8539         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8540                 printf("cli_set_ea_path on a symlink gave %s. "
8541                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8542                         nt_errstr(status));
8543                 goto out;
8544         }
8545
8546         printf("EA symlink test passed\n");
8547         correct = true;
8548
8549   out:
8550
8551         if (fnum != (uint16_t)-1) {
8552                 cli_close(cli, fnum);
8553                 fnum = (uint16_t)-1;
8554         }
8555
8556         cli_setatr(cli, sname, 0, 0);
8557         cli_posix_unlink(cli, sname);
8558         cli_setatr(cli, fname, 0, 0);
8559         cli_posix_unlink(cli, fname);
8560
8561         if (!torture_close_connection(cli)) {
8562                 correct = false;
8563         }
8564
8565         TALLOC_FREE(frame);
8566         return correct;
8567 }
8568
8569 /*
8570   Test POSIX locks are OFD-locks.
8571  */
8572 static bool run_posix_ofd_lock_test(int dummy)
8573 {
8574         static struct cli_state *cli;
8575         const char *fname = "posix_file";
8576         uint16_t fnum1 = (uint16_t)-1;
8577         uint16_t fnum2 = (uint16_t)-1;
8578         bool correct = false;
8579         NTSTATUS status;
8580         TALLOC_CTX *frame = NULL;
8581
8582         frame = talloc_stackframe();
8583
8584         printf("Starting POSIX ofd-lock test\n");
8585
8586         if (!torture_open_connection(&cli, 0)) {
8587                 TALLOC_FREE(frame);
8588                 return false;
8589         }
8590
8591         smbXcli_conn_set_sockopt(cli->conn, sockops);
8592
8593         status = torture_setup_unix_extensions(cli);
8594         if (!NT_STATUS_IS_OK(status)) {
8595                 TALLOC_FREE(frame);
8596                 return false;
8597         }
8598
8599         cli_setatr(cli, fname, 0, 0);
8600         cli_posix_unlink(cli, fname);
8601
8602         /* Open the file twice. */
8603         status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8604                                 0600, &fnum1);
8605         if (!NT_STATUS_IS_OK(status)) {
8606                 printf("First POSIX open of %s failed\n", fname);
8607                 goto out;
8608         }
8609
8610         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8611         if (!NT_STATUS_IS_OK(status)) {
8612                 printf("First POSIX open of %s failed\n", fname);
8613                 goto out;
8614         }
8615
8616         /* Set a 0-50 lock on fnum1. */
8617         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8618         if (!NT_STATUS_IS_OK(status)) {
8619                 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8620                 goto out;
8621         }
8622
8623         /* Set a 60-100 lock on fnum2. */
8624         status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8625         if (!NT_STATUS_IS_OK(status)) {
8626                 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8627                 goto out;
8628         }
8629
8630         /* close fnum1 - 0-50 lock should go away. */
8631         status = cli_close(cli, fnum1);
8632         if (!NT_STATUS_IS_OK(status)) {
8633                 printf("close failed (%s)\n",
8634                         nt_errstr(status));
8635                 goto out;
8636         }
8637         fnum1 = (uint16_t)-1;
8638
8639         /* Change the lock context. */
8640         cli_setpid(cli, cli_getpid(cli) + 1);
8641
8642         /* Re-open fnum1. */
8643         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8644         if (!NT_STATUS_IS_OK(status)) {
8645                 printf("Third POSIX open of %s failed\n", fname);
8646                 goto out;
8647         }
8648
8649         /* 60-100 lock should still be there. */
8650         status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8651         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8652                 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8653                 goto out;
8654         }
8655
8656         /* 0-50 lock should be gone. */
8657         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8658         if (!NT_STATUS_IS_OK(status)) {
8659                 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8660                 goto out;
8661         }
8662
8663         printf("POSIX OFD lock test passed\n");
8664         correct = true;
8665
8666   out:
8667
8668         if (fnum1 != (uint16_t)-1) {
8669                 cli_close(cli, fnum1);
8670                 fnum1 = (uint16_t)-1;
8671         }
8672         if (fnum2 != (uint16_t)-1) {
8673                 cli_close(cli, fnum2);
8674                 fnum2 = (uint16_t)-1;
8675         }
8676
8677         cli_setatr(cli, fname, 0, 0);
8678         cli_posix_unlink(cli, fname);
8679
8680         if (!torture_close_connection(cli)) {
8681                 correct = false;
8682         }
8683
8684         TALLOC_FREE(frame);
8685         return correct;
8686 }
8687
8688 struct posix_blocking_state {
8689         struct tevent_context *ev;
8690         struct cli_state *cli1;
8691         uint16_t fnum1;
8692         struct cli_state *cli2;
8693         uint16_t fnum2;
8694         bool gotblocked;
8695         bool gotecho;
8696 };
8697
8698 static void posix_blocking_locked(struct tevent_req *subreq);
8699 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8700 static void posix_blocking_gotecho(struct tevent_req *subreq);
8701 static void posix_blocking_unlocked(struct tevent_req *subreq);
8702
8703 static struct tevent_req *posix_blocking_send(
8704         TALLOC_CTX *mem_ctx,
8705         struct tevent_context *ev,
8706         struct cli_state *cli1,
8707         uint16_t fnum1,
8708         struct cli_state *cli2,
8709         uint16_t fnum2)
8710 {
8711         struct tevent_req *req = NULL, *subreq = NULL;
8712         struct posix_blocking_state *state = NULL;
8713
8714         req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8715         if (req == NULL) {
8716                 return NULL;
8717         }
8718         state->ev = ev;
8719         state->cli1 = cli1;
8720         state->fnum1 = fnum1;
8721         state->cli2 = cli2;
8722         state->fnum2 = fnum2;
8723
8724         subreq = cli_posix_lock_send(
8725                 state,
8726                 state->ev,
8727                 state->cli1,
8728                 state->fnum1,
8729                 0,
8730                 1,
8731                 false,
8732                 WRITE_LOCK);
8733         if (tevent_req_nomem(subreq, req)) {
8734                 return tevent_req_post(req, ev);
8735         }
8736         tevent_req_set_callback(subreq, posix_blocking_locked, req);
8737         return req;
8738 }
8739
8740 static void posix_blocking_locked(struct tevent_req *subreq)
8741 {
8742         struct tevent_req *req = tevent_req_callback_data(
8743                 subreq, struct tevent_req);
8744         struct posix_blocking_state *state = tevent_req_data(
8745                 req, struct posix_blocking_state);
8746         NTSTATUS status;
8747
8748         status = cli_posix_lock_recv(subreq);
8749         TALLOC_FREE(subreq);
8750         if (tevent_req_nterror(req, status)) {
8751                 return;
8752         }
8753
8754         subreq = cli_posix_lock_send(
8755                 state,
8756                 state->ev,
8757                 state->cli2,
8758                 state->fnum2,
8759                 0,
8760                 1,
8761                 true,
8762                 WRITE_LOCK);
8763         if (tevent_req_nomem(subreq, req)) {
8764                 return;
8765         }
8766         tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8767
8768         /* Make sure the blocking request is delivered */
8769         subreq = cli_echo_send(
8770                 state,
8771                 state->ev,
8772                 state->cli2,
8773                 1,
8774                 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8775         if (tevent_req_nomem(subreq, req)) {
8776                 return;
8777         }
8778         tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8779 }
8780
8781 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8782 {
8783         struct tevent_req *req = tevent_req_callback_data(
8784                 subreq, struct tevent_req);
8785         struct posix_blocking_state *state = tevent_req_data(
8786                 req, struct posix_blocking_state);
8787         NTSTATUS status;
8788
8789         status = cli_posix_lock_recv(subreq);
8790         TALLOC_FREE(subreq);
8791         if (tevent_req_nterror(req, status)) {
8792                 return;
8793         }
8794         if (!state->gotecho) {
8795                 printf("blocked req got through before echo\n");
8796                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8797                 return;
8798         }
8799         tevent_req_done(req);
8800 }
8801
8802 static void posix_blocking_gotecho(struct tevent_req *subreq)
8803 {
8804         struct tevent_req *req = tevent_req_callback_data(
8805                 subreq, struct tevent_req);
8806         struct posix_blocking_state *state = tevent_req_data(
8807                 req, struct posix_blocking_state);
8808         NTSTATUS status;
8809
8810         status = cli_echo_recv(subreq);
8811         TALLOC_FREE(subreq);
8812         if (tevent_req_nterror(req, status)) {
8813                 return;
8814         }
8815         if (state->gotblocked) {
8816                 printf("blocked req got through before echo\n");
8817                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8818                 return;
8819         }
8820         state->gotecho = true;
8821
8822         subreq = cli_posix_lock_send(
8823                 state,
8824                 state->ev,
8825                 state->cli1,
8826                 state->fnum1,
8827                 0,
8828                 1,
8829                 false,
8830                 UNLOCK_LOCK);
8831         if (tevent_req_nomem(subreq, req)) {
8832                 return;
8833         }
8834         tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
8835 }
8836
8837 static void posix_blocking_unlocked(struct tevent_req *subreq)
8838 {
8839         struct tevent_req *req = tevent_req_callback_data(
8840                 subreq, struct tevent_req);
8841         NTSTATUS status;
8842
8843         status = cli_posix_lock_recv(subreq);
8844         TALLOC_FREE(subreq);
8845         if (tevent_req_nterror(req, status)) {
8846                 return;
8847         }
8848         /* tevent_req_done in posix_blocking_gotlocked */
8849 }
8850
8851 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
8852 {
8853         return tevent_req_simple_recv_ntstatus(req);
8854 }
8855
8856 static bool run_posix_blocking_lock(int dummy)
8857 {
8858         struct tevent_context *ev = NULL;
8859         struct cli_state *cli1 = NULL, *cli2 = NULL;
8860         const char *fname = "posix_blocking";
8861         uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
8862         struct tevent_req *req = NULL;
8863         NTSTATUS status;
8864         bool ret = false;
8865         bool ok;
8866
8867         printf("Starting posix blocking lock test\n");
8868
8869         ev = samba_tevent_context_init(NULL);
8870         if (ev == NULL) {
8871                 return false;
8872         }
8873
8874         ok = torture_open_connection(&cli1, 0);
8875         if (!ok) {
8876                 goto fail;
8877         }
8878         ok = torture_open_connection(&cli2, 0);
8879         if (!ok) {
8880                 goto fail;
8881         }
8882
8883         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8884
8885         status = torture_setup_unix_extensions(cli1);
8886         if (!NT_STATUS_IS_OK(status)) {
8887                 return false;
8888         }
8889
8890         cli_setatr(cli1, fname, 0, 0);
8891         cli_posix_unlink(cli1, fname);
8892
8893         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8894                                 0600, &fnum1);
8895         if (!NT_STATUS_IS_OK(status)) {
8896                 printf("First POSIX open of %s failed: %s\n",
8897                        fname,
8898                        nt_errstr(status));
8899                 goto fail;
8900         }
8901
8902         status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
8903         if (!NT_STATUS_IS_OK(status)) {
8904                 printf("Second POSIX open of %s failed: %s\n",
8905                        fname,
8906                        nt_errstr(status));
8907                 goto fail;
8908         }
8909
8910         req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
8911         if (req == NULL) {
8912                 printf("cli_posix_blocking failed\n");
8913                 goto fail;
8914         }
8915
8916         ok = tevent_req_poll_ntstatus(req, ev, &status);
8917         if (!ok) {
8918                 printf("tevent_req_poll_ntstatus failed: %s\n",
8919                        nt_errstr(status));
8920                 goto fail;
8921         }
8922         status = posix_blocking_recv(req);
8923         TALLOC_FREE(req);
8924         if (!NT_STATUS_IS_OK(status)) {
8925                 printf("posix_blocking_recv returned %s\n",
8926                        nt_errstr(status));
8927                 goto fail;
8928         }
8929
8930         ret = true;
8931 fail:
8932
8933         if (fnum1 != UINT16_MAX) {
8934                 cli_close(cli1, fnum1);
8935                 fnum1 = UINT16_MAX;
8936         }
8937         if (fnum2 != UINT16_MAX) {
8938                 cli_close(cli2, fnum2);
8939                 fnum2 = UINT16_MAX;
8940         }
8941
8942         if (cli1 != NULL) {
8943                 cli_setatr(cli1, fname, 0, 0);
8944                 cli_posix_unlink(cli1, fname);
8945         }
8946
8947         ok = true;
8948
8949         if (cli1 != NULL) {
8950                 ok &= torture_close_connection(cli1);
8951                 cli1 = NULL;
8952         }
8953         if (cli2 != NULL) {
8954                 ok &= torture_close_connection(cli2);
8955                 cli2 = NULL;
8956         }
8957
8958         if (!ok) {
8959                 ret = false;
8960         }
8961         TALLOC_FREE(ev);
8962         return ret;
8963 }
8964
8965 /*
8966   Test POSIX mkdir is case-sensitive.
8967  */
8968 static bool run_posix_mkdir_test(int dummy)
8969 {
8970         static struct cli_state *cli;
8971         const char *fname_foo = "POSIX_foo";
8972         const char *fname_foo_Foo = "POSIX_foo/Foo";
8973         const char *fname_foo_foo = "POSIX_foo/foo";
8974         const char *fname_Foo = "POSIX_Foo";
8975         const char *fname_Foo_Foo = "POSIX_Foo/Foo";
8976         const char *fname_Foo_foo = "POSIX_Foo/foo";
8977         bool correct = false;
8978         NTSTATUS status;
8979         TALLOC_CTX *frame = NULL;
8980         uint16_t fnum = (uint16_t)-1;
8981
8982         frame = talloc_stackframe();
8983
8984         printf("Starting POSIX mkdir test\n");
8985
8986         if (!torture_open_connection(&cli, 0)) {
8987                 TALLOC_FREE(frame);
8988                 return false;
8989         }
8990
8991         smbXcli_conn_set_sockopt(cli->conn, sockops);
8992
8993         status = torture_setup_unix_extensions(cli);
8994         if (!NT_STATUS_IS_OK(status)) {
8995                 TALLOC_FREE(frame);
8996                 return false;
8997         }
8998
8999         cli_posix_rmdir(cli, fname_foo_foo);
9000         cli_posix_rmdir(cli, fname_foo_Foo);
9001         cli_posix_rmdir(cli, fname_foo);
9002
9003         cli_posix_rmdir(cli, fname_Foo_foo);
9004         cli_posix_rmdir(cli, fname_Foo_Foo);
9005         cli_posix_rmdir(cli, fname_Foo);
9006
9007         /*
9008          * Create a file POSIX_foo then try
9009          * and use it in a directory path by
9010          * doing mkdir POSIX_foo/bar.
9011          * The mkdir should fail with
9012          * NT_STATUS_OBJECT_PATH_NOT_FOUND
9013          */
9014
9015         status = cli_posix_open(cli,
9016                         fname_foo,
9017                         O_RDWR|O_CREAT,
9018                         0666,
9019                         &fnum);
9020         if (!NT_STATUS_IS_OK(status)) {
9021                 printf("cli_posix_open of %s failed error %s\n",
9022                         fname_foo,
9023                         nt_errstr(status));
9024                 goto out;
9025         }
9026
9027         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9028         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9029                 printf("cli_posix_mkdir of %s should fail with "
9030                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9031                         "%s instead\n",
9032                         fname_foo_foo,
9033                         nt_errstr(status));
9034                 goto out;
9035         }
9036
9037         status = cli_close(cli, fnum);
9038         if (!NT_STATUS_IS_OK(status)) {
9039                 printf("cli_close failed %s\n", nt_errstr(status));
9040                 goto out;
9041         }
9042         fnum = (uint16_t)-1;
9043
9044         status = cli_posix_unlink(cli, fname_foo);
9045         if (!NT_STATUS_IS_OK(status)) {
9046                 printf("cli_posix_unlink of %s failed error %s\n",
9047                         fname_foo,
9048                         nt_errstr(status));
9049                 goto out;
9050         }
9051
9052         /*
9053          * Now we've deleted everything, posix_mkdir, posix_rmdir,
9054          * posix_open, posix_unlink, on
9055          * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9056          * not silently create POSIX_foo/foo.
9057          */
9058
9059         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9060         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9061                 printf("cli_posix_mkdir of %s should fail with "
9062                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9063                         "%s instead\n",
9064                         fname_foo_foo,
9065                         nt_errstr(status));
9066                 goto out;
9067         }
9068
9069         status = cli_posix_rmdir(cli, fname_foo_foo);
9070         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9071                 printf("cli_posix_rmdir of %s should fail with "
9072                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9073                         "%s instead\n",
9074                         fname_foo_foo,
9075                         nt_errstr(status));
9076                 goto out;
9077         }
9078
9079         status = cli_posix_open(cli,
9080                         fname_foo_foo,
9081                         O_RDWR|O_CREAT,
9082                         0666,
9083                         &fnum);
9084         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9085                 printf("cli_posix_open of %s should fail with "
9086                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9087                         "%s instead\n",
9088                         fname_foo_foo,
9089                         nt_errstr(status));
9090                 goto out;
9091         }
9092
9093         status = cli_posix_unlink(cli, fname_foo_foo);
9094         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9095                 printf("cli_posix_unlink of %s should fail with "
9096                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9097                         "%s instead\n",
9098                         fname_foo_foo,
9099                         nt_errstr(status));
9100                 goto out;
9101         }
9102
9103         status = cli_posix_mkdir(cli, fname_foo, 0777);
9104         if (!NT_STATUS_IS_OK(status)) {
9105                 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9106                 goto out;
9107         }
9108
9109         status = cli_posix_mkdir(cli, fname_Foo, 0777);
9110         if (!NT_STATUS_IS_OK(status)) {
9111                 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9112                 goto out;
9113         }
9114
9115         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9116         if (!NT_STATUS_IS_OK(status)) {
9117                 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9118                 goto out;
9119         }
9120
9121         status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9122         if (!NT_STATUS_IS_OK(status)) {
9123                 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9124                 goto out;
9125         }
9126
9127         status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9128         if (!NT_STATUS_IS_OK(status)) {
9129                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9130                 goto out;
9131         }
9132
9133         status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9134         if (!NT_STATUS_IS_OK(status)) {
9135                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9136                 goto out;
9137         }
9138
9139         printf("POSIX mkdir test passed\n");
9140         correct = true;
9141
9142   out:
9143
9144         if (fnum != (uint16_t)-1) {
9145                 cli_close(cli, fnum);
9146                 fnum = (uint16_t)-1;
9147         }
9148
9149         cli_posix_rmdir(cli, fname_foo_foo);
9150         cli_posix_rmdir(cli, fname_foo_Foo);
9151         cli_posix_rmdir(cli, fname_foo);
9152
9153         cli_posix_rmdir(cli, fname_Foo_foo);
9154         cli_posix_rmdir(cli, fname_Foo_Foo);
9155         cli_posix_rmdir(cli, fname_Foo);
9156
9157         if (!torture_close_connection(cli)) {
9158                 correct = false;
9159         }
9160
9161         TALLOC_FREE(frame);
9162         return correct;
9163 }
9164
9165 struct posix_acl_oplock_state {
9166         struct tevent_context *ev;
9167         struct cli_state *cli;
9168         bool *got_break;
9169         bool *acl_ret;
9170         NTSTATUS status;
9171 };
9172
9173 static void posix_acl_oplock_got_break(struct tevent_req *req)
9174 {
9175         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9176                 req, struct posix_acl_oplock_state);
9177         uint16_t fnum;
9178         uint8_t level;
9179         NTSTATUS status;
9180
9181         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9182         TALLOC_FREE(req);
9183         if (!NT_STATUS_IS_OK(status)) {
9184                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9185                        nt_errstr(status));
9186                 return;
9187         }
9188         *state->got_break = true;
9189
9190         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9191                                   NO_OPLOCK);
9192         if (req == NULL) {
9193                 printf("cli_oplock_ack_send failed\n");
9194                 return;
9195         }
9196 }
9197
9198 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9199 {
9200         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9201                 req, struct posix_acl_oplock_state);
9202         size_t ret_size = 0;
9203         char *ret_data = NULL;
9204
9205         state->status = cli_posix_getacl_recv(req,
9206                         state,
9207                         &ret_size,
9208                         &ret_data);
9209
9210         if (!NT_STATUS_IS_OK(state->status)) {
9211                 printf("cli_posix_getacl_recv returned %s\n",
9212                         nt_errstr(state->status));
9213         }
9214         *state->acl_ret = true;
9215 }
9216
9217 static bool run_posix_acl_oplock_test(int dummy)
9218 {
9219         struct tevent_context *ev;
9220         struct cli_state *cli1, *cli2;
9221         struct tevent_req *oplock_req, *getacl_req;
9222         const char *fname = "posix_acl_oplock";
9223         uint16_t fnum;
9224         int saved_use_oplocks = use_oplocks;
9225         NTSTATUS status;
9226         bool correct = true;
9227         bool got_break = false;
9228         bool acl_ret = false;
9229
9230         struct posix_acl_oplock_state *state;
9231
9232         printf("starting posix_acl_oplock test\n");
9233
9234         if (!torture_open_connection(&cli1, 0)) {
9235                 use_level_II_oplocks = false;
9236                 use_oplocks = saved_use_oplocks;
9237                 return false;
9238         }
9239
9240         if (!torture_open_connection(&cli2, 1)) {
9241                 use_level_II_oplocks = false;
9242                 use_oplocks = saved_use_oplocks;
9243                 return false;
9244         }
9245
9246         /* Setup posix on cli2 only. */
9247         status = torture_setup_unix_extensions(cli2);
9248         if (!NT_STATUS_IS_OK(status)) {
9249                 return false;
9250         }
9251
9252         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9253         smbXcli_conn_set_sockopt(cli2->conn, sockops);
9254
9255         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9256
9257         /* Create the file on the Windows connection. */
9258         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9259                           &fnum);
9260         if (!NT_STATUS_IS_OK(status)) {
9261                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9262                 return false;
9263         }
9264
9265         status = cli_close(cli1, fnum);
9266         if (!NT_STATUS_IS_OK(status)) {
9267                 printf("close1 failed (%s)\n", nt_errstr(status));
9268                 return false;
9269         }
9270
9271         cli1->use_oplocks = true;
9272
9273         /* Open with oplock. */
9274         status = cli_ntcreate(cli1,
9275                         fname,
9276                         0,
9277                         FILE_READ_DATA,
9278                         FILE_ATTRIBUTE_NORMAL,
9279                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9280                         FILE_OPEN,
9281                         0,
9282                         0,
9283                         &fnum,
9284                         NULL);
9285
9286         if (!NT_STATUS_IS_OK(status)) {
9287                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9288                 return false;
9289         }
9290
9291         ev = samba_tevent_context_init(talloc_tos());
9292         if (ev == NULL) {
9293                 printf("tevent_context_init failed\n");
9294                 return false;
9295         }
9296
9297         state = talloc_zero(ev, struct posix_acl_oplock_state);
9298         if (state == NULL) {
9299                 printf("talloc failed\n");
9300                 return false;
9301         }
9302         state->ev = ev;
9303         state->cli = cli1;
9304         state->got_break = &got_break;
9305         state->acl_ret = &acl_ret;
9306
9307         oplock_req = cli_smb_oplock_break_waiter_send(
9308                 talloc_tos(), ev, cli1);
9309         if (oplock_req == NULL) {
9310                 printf("cli_smb_oplock_break_waiter_send failed\n");
9311                 return false;
9312         }
9313         tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9314
9315         /* Get ACL on POSIX connection - should break oplock. */
9316         getacl_req = cli_posix_getacl_send(talloc_tos(),
9317                                 ev,
9318                                 cli2,
9319                                 fname);
9320         if (getacl_req == NULL) {
9321                 printf("cli_posix_getacl_send failed\n");
9322                 return false;
9323         }
9324         tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9325
9326         while (!got_break || !acl_ret) {
9327                 int ret;
9328                 ret = tevent_loop_once(ev);
9329                 if (ret == -1) {
9330                         printf("tevent_loop_once failed: %s\n",
9331                                strerror(errno));
9332                         return false;
9333                 }
9334         }
9335
9336         if (!NT_STATUS_IS_OK(state->status)) {
9337                 printf("getacl failed (%s)\n", nt_errstr(state->status));
9338                 correct = false;
9339         }
9340
9341         status = cli_close(cli1, fnum);
9342         if (!NT_STATUS_IS_OK(status)) {
9343                 printf("close2 failed (%s)\n", nt_errstr(status));
9344                 correct = false;
9345         }
9346
9347         status = cli_unlink(cli1,
9348                         fname,
9349                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9350         if (!NT_STATUS_IS_OK(status)) {
9351                 printf("unlink failed (%s)\n", nt_errstr(status));
9352                 correct = false;
9353         }
9354
9355         if (!torture_close_connection(cli1)) {
9356                 correct = false;
9357         }
9358         if (!torture_close_connection(cli2)) {
9359                 correct = false;
9360         }
9361
9362         if (!got_break) {
9363                 correct = false;
9364         }
9365
9366         printf("finished posix acl oplock test\n");
9367
9368         return correct;
9369 }
9370
9371 static bool run_posix_acl_shareroot_test(int dummy)
9372 {
9373         struct cli_state *cli;
9374         NTSTATUS status;
9375         bool correct = false;
9376         char *posix_acl = NULL;
9377         size_t posix_acl_len = 0;
9378         uint16_t num_file_acls = 0;
9379         uint16_t num_dir_acls = 0;
9380         uint16_t i;
9381         uint32_t expected_size = 0;
9382         bool got_user = false;
9383         bool got_group = false;
9384         bool got_other = false;
9385         TALLOC_CTX *frame = NULL;
9386
9387         frame = talloc_stackframe();
9388
9389         printf("starting posix_acl_shareroot test\n");
9390
9391         if (!torture_open_connection(&cli, 0)) {
9392                 TALLOC_FREE(frame);
9393                 return false;
9394         }
9395
9396         smbXcli_conn_set_sockopt(cli->conn, sockops);
9397
9398         status = torture_setup_unix_extensions(cli);
9399         if (!NT_STATUS_IS_OK(status)) {
9400                 printf("Failed to setup unix extensions\n");
9401                 goto out;
9402         }
9403
9404         /* Get the POSIX ACL on the root of the share. */
9405         status = cli_posix_getacl(cli,
9406                                 ".",
9407                                 frame,
9408                                 &posix_acl_len,
9409                                 &posix_acl);
9410
9411         if (!NT_STATUS_IS_OK(status)) {
9412                 printf("cli_posix_getacl of '.' failed (%s)\n",
9413                         nt_errstr(status));
9414                 goto out;
9415         }
9416
9417         if (posix_acl_len < 6 ||
9418                         SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9419                 printf("getfacl ., unknown POSIX acl version %u.\n",
9420                         (unsigned int)CVAL(posix_acl,0) );
9421                 goto out;
9422         }
9423
9424         num_file_acls = SVAL(posix_acl,2);
9425         num_dir_acls = SVAL(posix_acl,4);
9426         expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9427                                 SMB_POSIX_ACL_ENTRY_SIZE*
9428                                 (num_file_acls+num_dir_acls);
9429
9430         if (posix_acl_len != expected_size) {
9431                 printf("incorrect POSIX acl buffer size "
9432                         "(should be %u, was %u).\n",
9433                         (unsigned int)expected_size,
9434                         (unsigned int)posix_acl_len);
9435                 goto out;
9436         }
9437
9438         /*
9439          * We don't need to know what the ACL's are
9440          * we just need to know we have at least 3
9441          * file entries (u,g,o).
9442          */
9443
9444         for (i = 0; i < num_file_acls; i++) {
9445                 unsigned char tagtype =
9446                         CVAL(posix_acl,
9447                                 SMB_POSIX_ACL_HEADER_SIZE+
9448                                 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9449
9450                 switch(tagtype) {
9451                         case SMB_POSIX_ACL_USER_OBJ:
9452                                 got_user = true;
9453                                 break;
9454                         case SMB_POSIX_ACL_GROUP_OBJ:
9455                                 got_group = true;
9456                                 break;
9457                         case SMB_POSIX_ACL_OTHER:
9458                                 got_other = true;
9459                                 break;
9460                         default:
9461                                 break;
9462                 }
9463         }
9464
9465         if (!got_user) {
9466                 printf("Missing user entry\n");
9467                 goto out;
9468         }
9469
9470         if (!got_group) {
9471                 printf("Missing group entry\n");
9472                 goto out;
9473         }
9474
9475         if (!got_other) {
9476                 printf("Missing other entry\n");
9477                 goto out;
9478         }
9479
9480         correct = true;
9481
9482   out:
9483
9484         if (!torture_close_connection(cli)) {
9485                 correct = false;
9486         }
9487
9488         printf("finished posix acl shareroot test\n");
9489         TALLOC_FREE(frame);
9490
9491         return correct;
9492 }
9493
9494 static uint32_t open_attrs_table[] = {
9495                 FILE_ATTRIBUTE_NORMAL,
9496                 FILE_ATTRIBUTE_ARCHIVE,
9497                 FILE_ATTRIBUTE_READONLY,
9498                 FILE_ATTRIBUTE_HIDDEN,
9499                 FILE_ATTRIBUTE_SYSTEM,
9500
9501                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9502                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9503                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9504                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9505                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9506                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9507
9508                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9509                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9510                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9511                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9512 };
9513
9514 struct trunc_open_results {
9515         unsigned int num;
9516         uint32_t init_attr;
9517         uint32_t trunc_attr;
9518         uint32_t result_attr;
9519 };
9520
9521 static struct trunc_open_results attr_results[] = {
9522         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9523         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9524         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9525         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9526         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9527         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9528         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9529         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9530         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9531         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9532         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9533         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9534         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9535         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9536         { 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 },
9537         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9538         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9539         { 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 },
9540         { 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 },
9541         { 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 },
9542         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9543         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9544         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9545         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9546         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9547         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9548 };
9549
9550 static bool run_openattrtest(int dummy)
9551 {
9552         static struct cli_state *cli1;
9553         const char *fname = "\\openattr.file";
9554         uint16_t fnum1;
9555         bool correct = True;
9556         uint32_t attr;
9557         unsigned int i, j, k, l;
9558         NTSTATUS status;
9559
9560         printf("starting open attr test\n");
9561
9562         if (!torture_open_connection(&cli1, 0)) {
9563                 return False;
9564         }
9565
9566         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9567
9568         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9569                 cli_setatr(cli1, fname, 0, 0);
9570                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9571
9572                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9573                                        open_attrs_table[i], FILE_SHARE_NONE,
9574                                        FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9575                 if (!NT_STATUS_IS_OK(status)) {
9576                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9577                         return False;
9578                 }
9579
9580                 status = cli_close(cli1, fnum1);
9581                 if (!NT_STATUS_IS_OK(status)) {
9582                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9583                         return False;
9584                 }
9585
9586                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9587                         status = cli_ntcreate(cli1, fname, 0,
9588                                               FILE_READ_DATA|FILE_WRITE_DATA,
9589                                               open_attrs_table[j],
9590                                               FILE_SHARE_NONE, FILE_OVERWRITE,
9591                                               0, 0, &fnum1, NULL);
9592                         if (!NT_STATUS_IS_OK(status)) {
9593                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9594                                         if (attr_results[l].num == k) {
9595                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9596                                                                 k, open_attrs_table[i],
9597                                                                 open_attrs_table[j],
9598                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
9599                                                 correct = False;
9600                                         }
9601                                 }
9602
9603                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9604                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9605                                                         k, open_attrs_table[i], open_attrs_table[j],
9606                                                         nt_errstr(status));
9607                                         correct = False;
9608                                 }
9609 #if 0
9610                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9611 #endif
9612                                 k++;
9613                                 continue;
9614                         }
9615
9616                         status = cli_close(cli1, fnum1);
9617                         if (!NT_STATUS_IS_OK(status)) {
9618                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9619                                 return False;
9620                         }
9621
9622                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9623                         if (!NT_STATUS_IS_OK(status)) {
9624                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9625                                 return False;
9626                         }
9627
9628 #if 0
9629                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9630                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
9631 #endif
9632
9633                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9634                                 if (attr_results[l].num == k) {
9635                                         if (attr != attr_results[l].result_attr ||
9636                                                         open_attrs_table[i] != attr_results[l].init_attr ||
9637                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
9638                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9639                                                 open_attrs_table[i],
9640                                                 open_attrs_table[j],
9641                                                 (unsigned int)attr,
9642                                                 attr_results[l].result_attr);
9643                                                 correct = False;
9644                                         }
9645                                         break;
9646                                 }
9647                         }
9648                         k++;
9649                 }
9650         }
9651
9652         cli_setatr(cli1, fname, 0, 0);
9653         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9654
9655         printf("open attr test %s.\n", correct ? "passed" : "failed");
9656
9657         if (!torture_close_connection(cli1)) {
9658                 correct = False;
9659         }
9660         return correct;
9661 }
9662
9663 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
9664                     const char *name, void *state)
9665 {
9666         int *matched = (int *)state;
9667         if (matched != NULL) {
9668                 *matched += 1;
9669         }
9670         return NT_STATUS_OK;
9671 }
9672
9673 /*
9674   test directory listing speed
9675  */
9676 static bool run_dirtest(int dummy)
9677 {
9678         int i;
9679         static struct cli_state *cli;
9680         uint16_t fnum;
9681         struct timeval core_start;
9682         bool correct = True;
9683         int matched;
9684
9685         printf("starting directory test\n");
9686
9687         if (!torture_open_connection(&cli, 0)) {
9688                 return False;
9689         }
9690
9691         smbXcli_conn_set_sockopt(cli->conn, sockops);
9692
9693         srandom(0);
9694         for (i=0;i<torture_numops;i++) {
9695                 fstring fname;
9696                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9697                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9698                         fprintf(stderr,"Failed to open %s\n", fname);
9699                         return False;
9700                 }
9701                 cli_close(cli, fnum);
9702         }
9703
9704         core_start = timeval_current();
9705
9706         matched = 0;
9707         cli_list(cli, "a*.*", 0, list_fn, &matched);
9708         printf("Matched %d\n", matched);
9709
9710         matched = 0;
9711         cli_list(cli, "b*.*", 0, list_fn, &matched);
9712         printf("Matched %d\n", matched);
9713
9714         matched = 0;
9715         cli_list(cli, "xyzabc", 0, list_fn, &matched);
9716         printf("Matched %d\n", matched);
9717
9718         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9719
9720         srandom(0);
9721         for (i=0;i<torture_numops;i++) {
9722                 fstring fname;
9723                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9724                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9725         }
9726
9727         if (!torture_close_connection(cli)) {
9728                 correct = False;
9729         }
9730
9731         printf("finished dirtest\n");
9732
9733         return correct;
9734 }
9735
9736 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
9737                    void *state)
9738 {
9739         struct cli_state *pcli = (struct cli_state *)state;
9740         fstring fname;
9741         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9742
9743         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9744                 return NT_STATUS_OK;
9745
9746         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9747                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9748                         printf("del_fn: failed to rmdir %s\n,", fname );
9749         } else {
9750                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9751                         printf("del_fn: failed to unlink %s\n,", fname );
9752         }
9753         return NT_STATUS_OK;
9754 }
9755
9756
9757 /*
9758   sees what IOCTLs are supported
9759  */
9760 bool torture_ioctl_test(int dummy)
9761 {
9762         static struct cli_state *cli;
9763         uint16_t device, function;
9764         uint16_t fnum;
9765         const char *fname = "\\ioctl.dat";
9766         DATA_BLOB blob;
9767         NTSTATUS status;
9768
9769         if (!torture_open_connection(&cli, 0)) {
9770                 return False;
9771         }
9772
9773         printf("starting ioctl test\n");
9774
9775         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9776
9777         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9778         if (!NT_STATUS_IS_OK(status)) {
9779                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9780                 return False;
9781         }
9782
9783         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9784         printf("ioctl device info: %s\n", nt_errstr(status));
9785
9786         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9787         printf("ioctl job info: %s\n", nt_errstr(status));
9788
9789         for (device=0;device<0x100;device++) {
9790                 printf("ioctl test with device = 0x%x\n", device);
9791                 for (function=0;function<0x100;function++) {
9792                         uint32_t code = (device<<16) | function;
9793
9794                         status = cli_raw_ioctl(cli, fnum, code, &blob);
9795
9796                         if (NT_STATUS_IS_OK(status)) {
9797                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
9798                                        (int)blob.length);
9799                                 data_blob_free(&blob);
9800                         }
9801                 }
9802         }
9803
9804         if (!torture_close_connection(cli)) {
9805                 return False;
9806         }
9807
9808         return True;
9809 }
9810
9811
9812 /*
9813   tries varients of chkpath
9814  */
9815 bool torture_chkpath_test(int dummy)
9816 {
9817         static struct cli_state *cli;
9818         uint16_t fnum;
9819         bool ret;
9820         NTSTATUS status;
9821
9822         if (!torture_open_connection(&cli, 0)) {
9823                 return False;
9824         }
9825
9826         printf("starting chkpath test\n");
9827
9828         /* cleanup from an old run */
9829         cli_rmdir(cli, "\\chkpath.dir\\dir2");
9830         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9831         cli_rmdir(cli, "\\chkpath.dir");
9832
9833         status = cli_mkdir(cli, "\\chkpath.dir");
9834         if (!NT_STATUS_IS_OK(status)) {
9835                 printf("mkdir1 failed : %s\n", nt_errstr(status));
9836                 return False;
9837         }
9838
9839         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
9840         if (!NT_STATUS_IS_OK(status)) {
9841                 printf("mkdir2 failed : %s\n", nt_errstr(status));
9842                 return False;
9843         }
9844
9845         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
9846                           DENY_NONE, &fnum);
9847         if (!NT_STATUS_IS_OK(status)) {
9848                 printf("open1 failed (%s)\n", nt_errstr(status));
9849                 return False;
9850         }
9851         cli_close(cli, fnum);
9852
9853         status = cli_chkpath(cli, "\\chkpath.dir");
9854         if (!NT_STATUS_IS_OK(status)) {
9855                 printf("chkpath1 failed: %s\n", nt_errstr(status));
9856                 ret = False;
9857         }
9858
9859         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
9860         if (!NT_STATUS_IS_OK(status)) {
9861                 printf("chkpath2 failed: %s\n", nt_errstr(status));
9862                 ret = False;
9863         }
9864
9865         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
9866         if (!NT_STATUS_IS_OK(status)) {
9867                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9868                                   NT_STATUS_NOT_A_DIRECTORY);
9869         } else {
9870                 printf("* chkpath on a file should fail\n");
9871                 ret = False;
9872         }
9873
9874         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
9875         if (!NT_STATUS_IS_OK(status)) {
9876                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
9877                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
9878         } else {
9879                 printf("* chkpath on a non existent file should fail\n");
9880                 ret = False;
9881         }
9882
9883         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
9884         if (!NT_STATUS_IS_OK(status)) {
9885                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9886                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
9887         } else {
9888                 printf("* chkpath on a non existent component should fail\n");
9889                 ret = False;
9890         }
9891
9892         cli_rmdir(cli, "\\chkpath.dir\\dir2");
9893         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9894         cli_rmdir(cli, "\\chkpath.dir");
9895
9896         if (!torture_close_connection(cli)) {
9897                 return False;
9898         }
9899
9900         return ret;
9901 }
9902
9903 static bool run_eatest(int dummy)
9904 {
9905         static struct cli_state *cli;
9906         const char *fname = "\\eatest.txt";
9907         bool correct = True;
9908         uint16_t fnum;
9909         int i;
9910         size_t num_eas;
9911         struct ea_struct *ea_list = NULL;
9912         TALLOC_CTX *mem_ctx = talloc_init("eatest");
9913         NTSTATUS status;
9914
9915         printf("starting eatest\n");
9916
9917         if (!torture_open_connection(&cli, 0)) {
9918                 talloc_destroy(mem_ctx);
9919                 return False;
9920         }
9921
9922         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9923
9924         status = cli_ntcreate(cli, fname, 0,
9925                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
9926                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
9927                               0x4044, 0, &fnum, NULL);
9928         if (!NT_STATUS_IS_OK(status)) {
9929                 printf("open failed - %s\n", nt_errstr(status));
9930                 talloc_destroy(mem_ctx);
9931                 return False;
9932         }
9933
9934         for (i = 0; i < 10; i++) {
9935                 fstring ea_name, ea_val;
9936
9937                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
9938                 memset(ea_val, (char)i+1, i+1);
9939                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
9940                 if (!NT_STATUS_IS_OK(status)) {
9941                         printf("ea_set of name %s failed - %s\n", ea_name,
9942                                nt_errstr(status));
9943                         talloc_destroy(mem_ctx);
9944                         return False;
9945                 }
9946         }
9947
9948         cli_close(cli, fnum);
9949         for (i = 0; i < 10; i++) {
9950                 fstring ea_name, ea_val;
9951
9952                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
9953                 memset(ea_val, (char)i+1, i+1);
9954                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
9955                 if (!NT_STATUS_IS_OK(status)) {
9956                         printf("ea_set of name %s failed - %s\n", ea_name,
9957                                nt_errstr(status));
9958                         talloc_destroy(mem_ctx);
9959                         return False;
9960                 }
9961         }
9962
9963         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
9964         if (!NT_STATUS_IS_OK(status)) {
9965                 printf("ea_get list failed - %s\n", nt_errstr(status));
9966                 correct = False;
9967         }
9968
9969         printf("num_eas = %d\n", (int)num_eas);
9970
9971         if (num_eas != 20) {
9972                 printf("Should be 20 EA's stored... failing.\n");
9973                 correct = False;
9974         }
9975
9976         for (i = 0; i < num_eas; i++) {
9977                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
9978                 dump_data(0, ea_list[i].value.data,
9979                           ea_list[i].value.length);
9980         }
9981
9982         /* Setting EA's to zero length deletes them. Test this */
9983         printf("Now deleting all EA's - case indepenent....\n");
9984
9985 #if 1
9986         cli_set_ea_path(cli, fname, "", "", 0);
9987 #else
9988         for (i = 0; i < 20; i++) {
9989                 fstring ea_name;
9990                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
9991                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
9992                 if (!NT_STATUS_IS_OK(status)) {
9993                         printf("ea_set of name %s failed - %s\n", ea_name,
9994                                nt_errstr(status));
9995                         talloc_destroy(mem_ctx);
9996                         return False;
9997                 }
9998         }
9999 #endif
10000
10001         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10002         if (!NT_STATUS_IS_OK(status)) {
10003                 printf("ea_get list failed - %s\n", nt_errstr(status));
10004                 correct = False;
10005         }
10006
10007         printf("num_eas = %d\n", (int)num_eas);
10008         for (i = 0; i < num_eas; i++) {
10009                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
10010                 dump_data(0, ea_list[i].value.data,
10011                           ea_list[i].value.length);
10012         }
10013
10014         if (num_eas != 0) {
10015                 printf("deleting EA's failed.\n");
10016                 correct = False;
10017         }
10018
10019         /* Try and delete a non existent EA. */
10020         status = cli_set_ea_path(cli, fname, "foo", "", 0);
10021         if (!NT_STATUS_IS_OK(status)) {
10022                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10023                        nt_errstr(status));
10024                 correct = False;
10025         }
10026
10027         talloc_destroy(mem_ctx);
10028         if (!torture_close_connection(cli)) {
10029                 correct = False;
10030         }
10031
10032         return correct;
10033 }
10034
10035 static bool run_dirtest1(int dummy)
10036 {
10037         int i;
10038         static struct cli_state *cli;
10039         uint16_t fnum;
10040         int num_seen;
10041         bool correct = True;
10042
10043         printf("starting directory test\n");
10044
10045         if (!torture_open_connection(&cli, 0)) {
10046                 return False;
10047         }
10048
10049         smbXcli_conn_set_sockopt(cli->conn, sockops);
10050
10051         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10052         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10053         cli_rmdir(cli, "\\LISTDIR");
10054         cli_mkdir(cli, "\\LISTDIR");
10055
10056         /* Create 1000 files and 1000 directories. */
10057         for (i=0;i<1000;i++) {
10058                 fstring fname;
10059                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10060                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10061                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10062                                    0, 0, &fnum, NULL))) {
10063                         fprintf(stderr,"Failed to open %s\n", fname);
10064                         return False;
10065                 }
10066                 cli_close(cli, fnum);
10067         }
10068         for (i=0;i<1000;i++) {
10069                 fstring fname;
10070                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10071                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10072                         fprintf(stderr,"Failed to open %s\n", fname);
10073                         return False;
10074                 }
10075         }
10076
10077         /* Now ensure that doing an old list sees both files and directories. */
10078         num_seen = 0;
10079         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10080         printf("num_seen = %d\n", num_seen );
10081         /* We should see 100 files + 1000 directories + . and .. */
10082         if (num_seen != 2002)
10083                 correct = False;
10084
10085         /* Ensure if we have the "must have" bits we only see the
10086          * relevent entries.
10087          */
10088         num_seen = 0;
10089         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10090         printf("num_seen = %d\n", num_seen );
10091         if (num_seen != 1002)
10092                 correct = False;
10093
10094         num_seen = 0;
10095         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10096         printf("num_seen = %d\n", num_seen );
10097         if (num_seen != 1000)
10098                 correct = False;
10099
10100         /* Delete everything. */
10101         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10102         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10103         cli_rmdir(cli, "\\LISTDIR");
10104
10105 #if 0
10106         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10107         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10108         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10109 #endif
10110
10111         if (!torture_close_connection(cli)) {
10112                 correct = False;
10113         }
10114
10115         printf("finished dirtest1\n");
10116
10117         return correct;
10118 }
10119
10120 static bool run_error_map_extract(int dummy) {
10121
10122         static struct cli_state *c_dos;
10123         static struct cli_state *c_nt;
10124         NTSTATUS status;
10125
10126         uint32_t error;
10127
10128         uint32_t errnum;
10129         uint8_t errclass;
10130
10131         NTSTATUS nt_status;
10132
10133         fstring user;
10134
10135         /* NT-Error connection */
10136
10137         disable_spnego = true;
10138         if (!(c_nt = open_nbt_connection())) {
10139                 disable_spnego = false;
10140                 return False;
10141         }
10142         disable_spnego = false;
10143
10144         status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
10145                                  PROTOCOL_NT1);
10146
10147         if (!NT_STATUS_IS_OK(status)) {
10148                 printf("%s rejected the NT-error negprot (%s)\n", host,
10149                        nt_errstr(status));
10150                 cli_shutdown(c_nt);
10151                 return False;
10152         }
10153
10154         status = cli_session_setup_anon(c_nt);
10155         if (!NT_STATUS_IS_OK(status)) {
10156                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10157                 return False;
10158         }
10159
10160         /* DOS-Error connection */
10161
10162         disable_spnego = true;
10163         force_dos_errors = true;
10164         if (!(c_dos = open_nbt_connection())) {
10165                 disable_spnego = false;
10166                 force_dos_errors = false;
10167                 return False;
10168         }
10169         disable_spnego = false;
10170         force_dos_errors = false;
10171
10172         status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
10173                                  PROTOCOL_NT1);
10174         if (!NT_STATUS_IS_OK(status)) {
10175                 printf("%s rejected the DOS-error negprot (%s)\n", host,
10176                        nt_errstr(status));
10177                 cli_shutdown(c_dos);
10178                 return False;
10179         }
10180
10181         status = cli_session_setup_anon(c_dos);
10182         if (!NT_STATUS_IS_OK(status)) {
10183                 printf("%s rejected the DOS-error initial session setup (%s)\n",
10184                         host, nt_errstr(status));
10185                 return False;
10186         }
10187
10188         c_nt->map_dos_errors = false;
10189         c_dos->map_dos_errors = false;
10190
10191         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10192                 struct cli_credentials *user_creds = NULL;
10193
10194                 fstr_sprintf(user, "%X", error);
10195
10196                 user_creds = cli_session_creds_init(talloc_tos(),
10197                                                     user,
10198                                                     workgroup,
10199                                                     NULL, /* realm */
10200                                                     password,
10201                                                     false, /* use_kerberos */
10202                                                     false, /* fallback_after_kerberos */
10203                                                     false, /* use_ccache */
10204                                                     false); /* password_is_nt_hash */
10205                 if (user_creds == NULL) {
10206                         printf("cli_session_creds_init(%s) failed\n", user);
10207                         return false;
10208                 }
10209
10210                 status = cli_session_setup_creds(c_nt, user_creds);
10211                 if (NT_STATUS_IS_OK(status)) {
10212                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10213                 }
10214
10215                 /* Case #1: 32-bit NT errors */
10216                 if (!NT_STATUS_IS_DOS(status)) {
10217                         nt_status = status;
10218                 } else {
10219                         printf("/** Dos error on NT connection! (%s) */\n", 
10220                                nt_errstr(status));
10221                         nt_status = NT_STATUS(0xc0000000);
10222                 }
10223
10224                 status = cli_session_setup_creds(c_dos, user_creds);
10225                 if (NT_STATUS_IS_OK(status)) {
10226                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10227                 }
10228
10229                 /* Case #1: 32-bit NT errors */
10230                 if (NT_STATUS_IS_DOS(status)) {
10231                         printf("/** NT error on DOS connection! (%s) */\n", 
10232                                nt_errstr(status));
10233                         errnum = errclass = 0;
10234                 } else {
10235                         errclass = NT_STATUS_DOS_CLASS(status);
10236                         errnum = NT_STATUS_DOS_CODE(status);
10237                 }
10238
10239                 if (NT_STATUS_V(nt_status) != error) { 
10240                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
10241                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
10242                                get_nt_error_c_code(talloc_tos(), nt_status));
10243                 }
10244
10245                 printf("\t{%s,\t%s,\t%s},\n", 
10246                        smb_dos_err_class(errclass), 
10247                        smb_dos_err_name(errclass, errnum), 
10248                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10249
10250                 TALLOC_FREE(user_creds);
10251         }
10252         return True;
10253 }
10254
10255 static bool run_sesssetup_bench(int dummy)
10256 {
10257         static struct cli_state *c;
10258         const char *fname = "\\file.dat";
10259         uint16_t fnum;
10260         NTSTATUS status;
10261         int i;
10262
10263         if (!torture_open_connection(&c, 0)) {
10264                 return false;
10265         }
10266
10267         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10268                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10269                               FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10270         if (!NT_STATUS_IS_OK(status)) {
10271                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10272                 return false;
10273         }
10274
10275         for (i=0; i<torture_numops; i++) {
10276                 status = cli_session_setup_creds(c, torture_creds);
10277                 if (!NT_STATUS_IS_OK(status)) {
10278                         d_printf("(%s) cli_session_setup_creds failed: %s\n",
10279                                  __location__, nt_errstr(status));
10280                         return false;
10281                 }
10282
10283                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
10284
10285                 status = cli_ulogoff(c);
10286                 if (!NT_STATUS_IS_OK(status)) {
10287                         d_printf("(%s) cli_ulogoff failed: %s\n",
10288                                  __location__, nt_errstr(status));
10289                         return false;
10290                 }
10291         }
10292
10293         return true;
10294 }
10295
10296 static bool subst_test(const char *str, const char *user, const char *domain,
10297                        uid_t uid, gid_t gid, const char *expected)
10298 {
10299         char *subst;
10300         bool result = true;
10301
10302         subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10303
10304         if (strcmp(subst, expected) != 0) {
10305                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10306                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10307                        expected);
10308                 result = false;
10309         }
10310
10311         TALLOC_FREE(subst);
10312         return result;
10313 }
10314
10315 static void chain1_open_completion(struct tevent_req *req)
10316 {
10317         uint16_t fnum;
10318         NTSTATUS status;
10319         status = cli_openx_recv(req, &fnum);
10320         TALLOC_FREE(req);
10321
10322         d_printf("cli_openx_recv returned %s: %d\n",
10323                  nt_errstr(status),
10324                  NT_STATUS_IS_OK(status) ? fnum : -1);
10325 }
10326
10327 static void chain1_write_completion(struct tevent_req *req)
10328 {
10329         size_t written;
10330         NTSTATUS status;
10331         status = cli_write_andx_recv(req, &written);
10332         TALLOC_FREE(req);
10333
10334         d_printf("cli_write_andx_recv returned %s: %d\n",
10335                  nt_errstr(status),
10336                  NT_STATUS_IS_OK(status) ? (int)written : -1);
10337 }
10338
10339 static void chain1_close_completion(struct tevent_req *req)
10340 {
10341         NTSTATUS status;
10342         bool *done = (bool *)tevent_req_callback_data_void(req);
10343
10344         status = cli_close_recv(req);
10345         *done = true;
10346
10347         TALLOC_FREE(req);
10348
10349         d_printf("cli_close returned %s\n", nt_errstr(status));
10350 }
10351
10352 static bool run_chain1(int dummy)
10353 {
10354         struct cli_state *cli1;
10355         struct tevent_context *evt = samba_tevent_context_init(NULL);
10356         struct tevent_req *reqs[3], *smbreqs[3];
10357         bool done = false;
10358         const char *str = "foobar";
10359         const char *fname = "\\test_chain";
10360         NTSTATUS status;
10361
10362         printf("starting chain1 test\n");
10363         if (!torture_open_connection(&cli1, 0)) {
10364                 return False;
10365         }
10366
10367         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10368
10369         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10370
10371         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10372                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
10373         if (reqs[0] == NULL) return false;
10374         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10375
10376
10377         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10378                                         (const uint8_t *)str, 0, strlen(str)+1,
10379                                         smbreqs, 1, &smbreqs[1]);
10380         if (reqs[1] == NULL) return false;
10381         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10382
10383         reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10384         if (reqs[2] == NULL) return false;
10385         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10386
10387         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10388         if (!NT_STATUS_IS_OK(status)) {
10389                 return false;
10390         }
10391
10392         while (!done) {
10393                 tevent_loop_once(evt);
10394         }
10395
10396         torture_close_connection(cli1);
10397         return True;
10398 }
10399
10400 static void chain2_sesssetup_completion(struct tevent_req *req)
10401 {
10402         NTSTATUS status;
10403         status = cli_session_setup_guest_recv(req);
10404         d_printf("sesssetup returned %s\n", nt_errstr(status));
10405 }
10406
10407 static void chain2_tcon_completion(struct tevent_req *req)
10408 {
10409         bool *done = (bool *)tevent_req_callback_data_void(req);
10410         NTSTATUS status;
10411         status = cli_tcon_andx_recv(req);
10412         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10413         *done = true;
10414 }
10415
10416 static bool run_chain2(int dummy)
10417 {
10418         struct cli_state *cli1;
10419         struct tevent_context *evt = samba_tevent_context_init(NULL);
10420         struct tevent_req *reqs[2], *smbreqs[2];
10421         bool done = false;
10422         NTSTATUS status;
10423         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10424
10425         printf("starting chain2 test\n");
10426         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10427                                       port_to_use, SMB_SIGNING_DEFAULT, flags);
10428         if (!NT_STATUS_IS_OK(status)) {
10429                 return False;
10430         }
10431
10432         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10433
10434         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10435                                                  &smbreqs[0]);
10436         if (reqs[0] == NULL) return false;
10437         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10438
10439         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10440                                        "?????", NULL, 0, &smbreqs[1]);
10441         if (reqs[1] == NULL) return false;
10442         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10443
10444         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10445         if (!NT_STATUS_IS_OK(status)) {
10446                 return false;
10447         }
10448
10449         while (!done) {
10450                 tevent_loop_once(evt);
10451         }
10452
10453         torture_close_connection(cli1);
10454         return True;
10455 }
10456
10457
10458 struct torture_createdel_state {
10459         struct tevent_context *ev;
10460         struct cli_state *cli;
10461 };
10462
10463 static void torture_createdel_created(struct tevent_req *subreq);
10464 static void torture_createdel_closed(struct tevent_req *subreq);
10465
10466 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10467                                                  struct tevent_context *ev,
10468                                                  struct cli_state *cli,
10469                                                  const char *name)
10470 {
10471         struct tevent_req *req, *subreq;
10472         struct torture_createdel_state *state;
10473
10474         req = tevent_req_create(mem_ctx, &state,
10475                                 struct torture_createdel_state);
10476         if (req == NULL) {
10477                 return NULL;
10478         }
10479         state->ev = ev;
10480         state->cli = cli;
10481
10482         subreq = cli_ntcreate_send(
10483                 state, ev, cli, name, 0,
10484                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10485                 FILE_ATTRIBUTE_NORMAL,
10486                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10487                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10488                 SMB2_IMPERSONATION_IMPERSONATION, 0);
10489
10490         if (tevent_req_nomem(subreq, req)) {
10491                 return tevent_req_post(req, ev);
10492         }
10493         tevent_req_set_callback(subreq, torture_createdel_created, req);
10494         return req;
10495 }
10496
10497 static void torture_createdel_created(struct tevent_req *subreq)
10498 {
10499         struct tevent_req *req = tevent_req_callback_data(
10500                 subreq, struct tevent_req);
10501         struct torture_createdel_state *state = tevent_req_data(
10502                 req, struct torture_createdel_state);
10503         NTSTATUS status;
10504         uint16_t fnum;
10505
10506         status = cli_ntcreate_recv(subreq, &fnum, NULL);
10507         TALLOC_FREE(subreq);
10508         if (tevent_req_nterror(req, status)) {
10509                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10510                            nt_errstr(status)));
10511                 return;
10512         }
10513
10514         subreq = cli_close_send(state, state->ev, state->cli, fnum);
10515         if (tevent_req_nomem(subreq, req)) {
10516                 return;
10517         }
10518         tevent_req_set_callback(subreq, torture_createdel_closed, req);
10519 }
10520
10521 static void torture_createdel_closed(struct tevent_req *subreq)
10522 {
10523         struct tevent_req *req = tevent_req_callback_data(
10524                 subreq, struct tevent_req);
10525         NTSTATUS status;
10526
10527         status = cli_close_recv(subreq);
10528         if (tevent_req_nterror(req, status)) {
10529                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10530                 return;
10531         }
10532         tevent_req_done(req);
10533 }
10534
10535 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10536 {
10537         return tevent_req_simple_recv_ntstatus(req);
10538 }
10539
10540 struct torture_createdels_state {
10541         struct tevent_context *ev;
10542         struct cli_state *cli;
10543         const char *base_name;
10544         int sent;
10545         int received;
10546         int num_files;
10547         struct tevent_req **reqs;
10548 };
10549
10550 static void torture_createdels_done(struct tevent_req *subreq);
10551
10552 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10553                                                   struct tevent_context *ev,
10554                                                   struct cli_state *cli,
10555                                                   const char *base_name,
10556                                                   int num_parallel,
10557                                                   int num_files)
10558 {
10559         struct tevent_req *req;
10560         struct torture_createdels_state *state;
10561         int i;
10562
10563         req = tevent_req_create(mem_ctx, &state,
10564                                 struct torture_createdels_state);
10565         if (req == NULL) {
10566                 return NULL;
10567         }
10568         state->ev = ev;
10569         state->cli = cli;
10570         state->base_name = talloc_strdup(state, base_name);
10571         if (tevent_req_nomem(state->base_name, req)) {
10572                 return tevent_req_post(req, ev);
10573         }
10574         state->num_files = MAX(num_parallel, num_files);
10575         state->sent = 0;
10576         state->received = 0;
10577
10578         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10579         if (tevent_req_nomem(state->reqs, req)) {
10580                 return tevent_req_post(req, ev);
10581         }
10582
10583         for (i=0; i<num_parallel; i++) {
10584                 char *name;
10585
10586                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10587                                        state->sent);
10588                 if (tevent_req_nomem(name, req)) {
10589                         return tevent_req_post(req, ev);
10590                 }
10591                 state->reqs[i] = torture_createdel_send(
10592                         state->reqs, state->ev, state->cli, name);
10593                 if (tevent_req_nomem(state->reqs[i], req)) {
10594                         return tevent_req_post(req, ev);
10595                 }
10596                 name = talloc_move(state->reqs[i], &name);
10597                 tevent_req_set_callback(state->reqs[i],
10598                                         torture_createdels_done, req);
10599                 state->sent += 1;
10600         }
10601         return req;
10602 }
10603
10604 static void torture_createdels_done(struct tevent_req *subreq)
10605 {
10606         struct tevent_req *req = tevent_req_callback_data(
10607                 subreq, struct tevent_req);
10608         struct torture_createdels_state *state = tevent_req_data(
10609                 req, struct torture_createdels_state);
10610         size_t num_parallel = talloc_array_length(state->reqs);
10611         NTSTATUS status;
10612         char *name;
10613         int i;
10614
10615         status = torture_createdel_recv(subreq);
10616         if (!NT_STATUS_IS_OK(status)){
10617                 DEBUG(10, ("torture_createdel_recv returned %s\n",
10618                            nt_errstr(status)));
10619                 TALLOC_FREE(subreq);
10620                 tevent_req_nterror(req, status);
10621                 return;
10622         }
10623
10624         for (i=0; i<num_parallel; i++) {
10625                 if (subreq == state->reqs[i]) {
10626                         break;
10627                 }
10628         }
10629         if (i == num_parallel) {
10630                 DEBUG(10, ("received something we did not send\n"));
10631                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10632                 return;
10633         }
10634         TALLOC_FREE(state->reqs[i]);
10635
10636         if (state->sent >= state->num_files) {
10637                 tevent_req_done(req);
10638                 return;
10639         }
10640
10641         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10642                                state->sent);
10643         if (tevent_req_nomem(name, req)) {
10644                 return;
10645         }
10646         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10647                                                 state->cli, name);
10648         if (tevent_req_nomem(state->reqs[i], req)) {
10649                 return;
10650         }
10651         name = talloc_move(state->reqs[i], &name);
10652         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10653         state->sent += 1;
10654 }
10655
10656 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10657 {
10658         return tevent_req_simple_recv_ntstatus(req);
10659 }
10660
10661 struct swallow_notify_state {
10662         struct tevent_context *ev;
10663         struct cli_state *cli;
10664         uint16_t fnum;
10665         uint32_t completion_filter;
10666         bool recursive;
10667         bool (*fn)(uint32_t action, const char *name, void *priv);
10668         void *priv;
10669 };
10670
10671 static void swallow_notify_done(struct tevent_req *subreq);
10672
10673 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10674                                               struct tevent_context *ev,
10675                                               struct cli_state *cli,
10676                                               uint16_t fnum,
10677                                               uint32_t completion_filter,
10678                                               bool recursive,
10679                                               bool (*fn)(uint32_t action,
10680                                                          const char *name,
10681                                                          void *priv),
10682                                               void *priv)
10683 {
10684         struct tevent_req *req, *subreq;
10685         struct swallow_notify_state *state;
10686
10687         req = tevent_req_create(mem_ctx, &state,
10688                                 struct swallow_notify_state);
10689         if (req == NULL) {
10690                 return NULL;
10691         }
10692         state->ev = ev;
10693         state->cli = cli;
10694         state->fnum = fnum;
10695         state->completion_filter = completion_filter;
10696         state->recursive = recursive;
10697         state->fn = fn;
10698         state->priv = priv;
10699
10700         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10701                                  0xffff, state->completion_filter,
10702                                  state->recursive);
10703         if (tevent_req_nomem(subreq, req)) {
10704                 return tevent_req_post(req, ev);
10705         }
10706         tevent_req_set_callback(subreq, swallow_notify_done, req);
10707         return req;
10708 }
10709
10710 static void swallow_notify_done(struct tevent_req *subreq)
10711 {
10712         struct tevent_req *req = tevent_req_callback_data(
10713                 subreq, struct tevent_req);
10714         struct swallow_notify_state *state = tevent_req_data(
10715                 req, struct swallow_notify_state);
10716         NTSTATUS status;
10717         uint32_t i, num_changes;
10718         struct notify_change *changes;
10719
10720         status = cli_notify_recv(subreq, state, &num_changes, &changes);
10721         TALLOC_FREE(subreq);
10722         if (!NT_STATUS_IS_OK(status)) {
10723                 DEBUG(10, ("cli_notify_recv returned %s\n",
10724                            nt_errstr(status)));
10725                 tevent_req_nterror(req, status);
10726                 return;
10727         }
10728
10729         for (i=0; i<num_changes; i++) {
10730                 state->fn(changes[i].action, changes[i].name, state->priv);
10731         }
10732         TALLOC_FREE(changes);
10733
10734         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10735                                  0xffff, state->completion_filter,
10736                                  state->recursive);
10737         if (tevent_req_nomem(subreq, req)) {
10738                 return;
10739         }
10740         tevent_req_set_callback(subreq, swallow_notify_done, req);
10741 }
10742
10743 static bool print_notifies(uint32_t action, const char *name, void *priv)
10744 {
10745         if (DEBUGLEVEL > 5) {
10746                 d_printf("%d %s\n", (int)action, name);
10747         }
10748         return true;
10749 }
10750
10751 static void notify_bench_done(struct tevent_req *req)
10752 {
10753         int *num_finished = (int *)tevent_req_callback_data_void(req);
10754         *num_finished += 1;
10755 }
10756
10757 static bool run_notify_bench(int dummy)
10758 {
10759         const char *dname = "\\notify-bench";
10760         struct tevent_context *ev;
10761         NTSTATUS status;
10762         uint16_t dnum;
10763         struct tevent_req *req1;
10764         struct tevent_req *req2 = NULL;
10765         int i, num_unc_names;
10766         int num_finished = 0;
10767
10768         printf("starting notify-bench test\n");
10769
10770         if (use_multishare_conn) {
10771                 char **unc_list;
10772                 unc_list = file_lines_load(multishare_conn_fname,
10773                                            &num_unc_names, 0, NULL);
10774                 if (!unc_list || num_unc_names <= 0) {
10775                         d_printf("Failed to load unc names list from '%s'\n",
10776                                  multishare_conn_fname);
10777                         return false;
10778                 }
10779                 TALLOC_FREE(unc_list);
10780         } else {
10781                 num_unc_names = 1;
10782         }
10783
10784         ev = samba_tevent_context_init(talloc_tos());
10785         if (ev == NULL) {
10786                 d_printf("tevent_context_init failed\n");
10787                 return false;
10788         }
10789
10790         for (i=0; i<num_unc_names; i++) {
10791                 struct cli_state *cli;
10792                 char *base_fname;
10793
10794                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
10795                                              dname, i);
10796                 if (base_fname == NULL) {
10797                         return false;
10798                 }
10799
10800                 if (!torture_open_connection(&cli, i)) {
10801                         return false;
10802                 }
10803
10804                 status = cli_ntcreate(cli, dname, 0,
10805                                       MAXIMUM_ALLOWED_ACCESS,
10806                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
10807                                       FILE_SHARE_DELETE,
10808                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
10809                                       &dnum, NULL);
10810
10811                 if (!NT_STATUS_IS_OK(status)) {
10812                         d_printf("Could not create %s: %s\n", dname,
10813                                  nt_errstr(status));
10814                         return false;
10815                 }
10816
10817                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
10818                                            FILE_NOTIFY_CHANGE_FILE_NAME |
10819                                            FILE_NOTIFY_CHANGE_DIR_NAME |
10820                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
10821                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
10822                                            false, print_notifies, NULL);
10823                 if (req1 == NULL) {
10824                         d_printf("Could not create notify request\n");
10825                         return false;
10826                 }
10827
10828                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
10829                                                base_fname, 10, torture_numops);
10830                 if (req2 == NULL) {
10831                         d_printf("Could not create createdels request\n");
10832                         return false;
10833                 }
10834                 TALLOC_FREE(base_fname);
10835
10836                 tevent_req_set_callback(req2, notify_bench_done,
10837                                         &num_finished);
10838         }
10839
10840         while (num_finished < num_unc_names) {
10841                 int ret;
10842                 ret = tevent_loop_once(ev);
10843                 if (ret != 0) {
10844                         d_printf("tevent_loop_once failed\n");
10845                         return false;
10846                 }
10847         }
10848
10849         if (!tevent_req_poll(req2, ev)) {
10850                 d_printf("tevent_req_poll failed\n");
10851         }
10852
10853         status = torture_createdels_recv(req2);
10854         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
10855
10856         return true;
10857 }
10858
10859 static bool run_mangle1(int dummy)
10860 {
10861         struct cli_state *cli;
10862         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
10863         uint16_t fnum;
10864         fstring alt_name;
10865         NTSTATUS status;
10866         time_t change_time, access_time, write_time;
10867         off_t size;
10868         uint32_t attr;
10869
10870         printf("starting mangle1 test\n");
10871         if (!torture_open_connection(&cli, 0)) {
10872                 return False;
10873         }
10874
10875         smbXcli_conn_set_sockopt(cli->conn, sockops);
10876
10877         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10878                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10879                               0, 0, &fnum, NULL);
10880         if (!NT_STATUS_IS_OK(status)) {
10881                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10882                 return false;
10883         }
10884         cli_close(cli, fnum);
10885
10886         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
10887         if (!NT_STATUS_IS_OK(status)) {
10888                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
10889                          nt_errstr(status));
10890                 return false;
10891         }
10892         d_printf("alt_name: %s\n", alt_name);
10893
10894         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
10895         if (!NT_STATUS_IS_OK(status)) {
10896                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
10897                          nt_errstr(status));
10898                 return false;
10899         }
10900         cli_close(cli, fnum);
10901
10902         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
10903                                 &write_time, &size, &attr);
10904         if (!NT_STATUS_IS_OK(status)) {
10905                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
10906                          nt_errstr(status));
10907                 return false;
10908         }
10909
10910         return true;
10911 }
10912
10913 static NTSTATUS mangle_illegal_list_shortname_fn(const char *mntpoint,
10914                                                  struct file_info *f,
10915                                                  const char *mask,
10916                                                  void *state)
10917 {
10918         if (f->short_name == NULL) {
10919                 return NT_STATUS_OK;
10920         }
10921
10922         if (strlen(f->short_name) == 0) {
10923                 return NT_STATUS_OK;
10924         }
10925
10926         printf("unexpected shortname: %s\n", f->short_name);
10927
10928         return NT_STATUS_OBJECT_NAME_INVALID;
10929 }
10930
10931 static NTSTATUS mangle_illegal_list_name_fn(const char *mntpoint,
10932                                             struct file_info *f,
10933                                             const char *mask,
10934                                             void *state)
10935 {
10936         char *name = state;
10937
10938         printf("name: %s\n", f->name);
10939         fstrcpy(name, f->name);
10940         return NT_STATUS_OK;
10941 }
10942
10943 static bool run_mangle_illegal(int dummy)
10944 {
10945         struct cli_state *cli = NULL;
10946         struct cli_state *cli_posix = NULL;
10947         const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
10948         const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
10949         char *mangled_path = NULL;
10950         uint16_t fnum;
10951         fstring name;
10952         fstring alt_name;
10953         NTSTATUS status;
10954
10955         printf("starting mangle-illegal test\n");
10956
10957         if (!torture_open_connection(&cli, 0)) {
10958                 return False;
10959         }
10960
10961         smbXcli_conn_set_sockopt(cli->conn, sockops);
10962
10963         if (!torture_open_connection(&cli_posix, 0)) {
10964                 return false;
10965         }
10966
10967         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
10968
10969         status = torture_setup_unix_extensions(cli_posix);
10970         if (!NT_STATUS_IS_OK(status)) {
10971                 return false;
10972         }
10973
10974         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
10975         status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
10976         if (!NT_STATUS_IS_OK(status)) {
10977                 printf("mkdir1 failed : %s\n", nt_errstr(status));
10978                 return False;
10979         }
10980
10981         /*
10982          * Create a file with illegal NTFS characters and test that we
10983          * get a usable mangled name
10984          */
10985
10986         cli_setatr(cli_posix, illegal_fname, 0, 0);
10987         cli_posix_unlink(cli_posix, illegal_fname);
10988
10989         status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
10990                                 0600, &fnum);
10991         if (!NT_STATUS_IS_OK(status)) {
10992                 printf("POSIX create of %s failed (%s)\n",
10993                        illegal_fname, nt_errstr(status));
10994                 return false;
10995         }
10996
10997         status = cli_close(cli_posix, fnum);
10998         if (!NT_STATUS_IS_OK(status)) {
10999                 printf("close failed (%s)\n", nt_errstr(status));
11000                 return false;
11001         }
11002
11003         status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11004         if (!NT_STATUS_IS_OK(status)) {
11005                 d_printf("cli_list failed: %s\n", nt_errstr(status));
11006                 return false;
11007         }
11008
11009         mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11010         if (mangled_path == NULL) {
11011                 return false;
11012         }
11013
11014         status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11015         if (!NT_STATUS_IS_OK(status)) {
11016                 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11017                 TALLOC_FREE(mangled_path);
11018                 return false;
11019         }
11020         TALLOC_FREE(mangled_path);
11021         cli_close(cli, fnum);
11022
11023         cli_setatr(cli_posix, illegal_fname, 0, 0);
11024         cli_posix_unlink(cli_posix, illegal_fname);
11025
11026         /*
11027          * Create a file with a long name and check that we got *no* short name.
11028          */
11029
11030         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11031                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11032                               0, 0, &fnum, NULL);
11033         if (!NT_STATUS_IS_OK(status)) {
11034                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11035                 return false;
11036         }
11037         cli_close(cli, fnum);
11038
11039         status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11040         if (!NT_STATUS_IS_OK(status)) {
11041                 d_printf("cli_list failed\n");
11042                 return false;
11043         }
11044
11045         cli_unlink(cli, fname, 0);
11046         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11047
11048         if (!torture_close_connection(cli_posix)) {
11049                 return false;
11050         }
11051
11052         if (!torture_close_connection(cli)) {
11053                 return false;
11054         }
11055
11056         return true;
11057 }
11058
11059 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11060 {
11061         size_t *to_pull = (size_t *)priv;
11062         size_t thistime = *to_pull;
11063
11064         thistime = MIN(thistime, n);
11065         if (thistime == 0) {
11066                 return 0;
11067         }
11068
11069         memset(buf, 0, thistime);
11070         *to_pull -= thistime;
11071         return thistime;
11072 }
11073
11074 static bool run_windows_write(int dummy)
11075 {
11076         struct cli_state *cli1;
11077         uint16_t fnum;
11078         int i;
11079         bool ret = false;
11080         const char *fname = "\\writetest.txt";
11081         struct timeval start_time;
11082         double seconds;
11083         double kbytes;
11084         NTSTATUS status;
11085
11086         printf("starting windows_write test\n");
11087         if (!torture_open_connection(&cli1, 0)) {
11088                 return False;
11089         }
11090
11091         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11092         if (!NT_STATUS_IS_OK(status)) {
11093                 printf("open failed (%s)\n", nt_errstr(status));
11094                 return False;
11095         }
11096
11097         smbXcli_conn_set_sockopt(cli1->conn, sockops);
11098
11099         start_time = timeval_current();
11100
11101         for (i=0; i<torture_numops; i++) {
11102                 uint8_t c = 0;
11103                 off_t start = i * torture_blocksize;
11104                 size_t to_pull = torture_blocksize - 1;
11105
11106                 status = cli_writeall(cli1, fnum, 0, &c,
11107                                       start + torture_blocksize - 1, 1, NULL);
11108                 if (!NT_STATUS_IS_OK(status)) {
11109                         printf("cli_write failed: %s\n", nt_errstr(status));
11110                         goto fail;
11111                 }
11112
11113                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11114                                   null_source, &to_pull);
11115                 if (!NT_STATUS_IS_OK(status)) {
11116                         printf("cli_push returned: %s\n", nt_errstr(status));
11117                         goto fail;
11118                 }
11119         }
11120
11121         seconds = timeval_elapsed(&start_time);
11122         kbytes = (double)torture_blocksize * torture_numops;
11123         kbytes /= 1024;
11124
11125         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11126                (double)seconds, (int)(kbytes/seconds));
11127
11128         ret = true;
11129  fail:
11130         cli_close(cli1, fnum);
11131         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11132         torture_close_connection(cli1);
11133         return ret;
11134 }
11135
11136 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11137 {
11138         size_t max_pdu = 0x1FFFF;
11139
11140         if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11141                 max_pdu = 0xFFFFFF;
11142         }
11143
11144         if (smb1cli_conn_signing_is_active(cli->conn)) {
11145                 max_pdu = 0x1FFFF;
11146         }
11147
11148         if (smb1cli_conn_encryption_on(cli->conn)) {
11149                 max_pdu = CLI_BUFFER_SIZE;
11150         }
11151
11152         if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11153                 len_requested &= 0xFFFF;
11154         }
11155
11156         return MIN(len_requested,
11157                    max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11158 }
11159
11160 static bool check_read_call(struct cli_state *cli,
11161                             uint16_t fnum,
11162                             uint8_t *buf,
11163                             size_t len_requested)
11164 {
11165         NTSTATUS status;
11166         struct tevent_req *subreq = NULL;
11167         ssize_t len_read = 0;
11168         size_t len_expected = 0;
11169         struct tevent_context *ev = NULL;
11170
11171         ev = samba_tevent_context_init(talloc_tos());
11172         if (ev == NULL) {
11173                 return false;
11174         }
11175
11176         subreq = cli_read_andx_send(talloc_tos(),
11177                                     ev,
11178                                     cli,
11179                                     fnum,
11180                                     0,
11181                                     len_requested);
11182
11183         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11184                 return false;
11185         }
11186
11187         status = cli_read_andx_recv(subreq, &len_read, &buf);
11188         if (!NT_STATUS_IS_OK(status)) {
11189                 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11190                 return false;
11191         }
11192
11193         TALLOC_FREE(subreq);
11194         TALLOC_FREE(ev);
11195
11196         len_expected = calc_expected_return(cli, len_requested);
11197
11198         if (len_expected > 0x10000 && len_read == 0x10000) {
11199                 /* Windows servers only return a max of 0x10000,
11200                    doesn't matter if you set CAP_LARGE_READX in
11201                    the client sessionsetupX call or not. */
11202                 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11203                         (unsigned int)len_requested);
11204         } else if (len_read != len_expected) {
11205                 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11206                         (unsigned int)len_requested,
11207                         (unsigned int)len_read,
11208                         (unsigned int)len_expected);
11209                 return false;
11210         } else {
11211                 d_printf("Correct read reply.\n");
11212         }
11213
11214         return true;
11215 }
11216
11217 /* Test large readX variants. */
11218 static bool large_readx_tests(struct cli_state *cli,
11219                                 uint16_t fnum,
11220                                 uint8_t *buf)
11221 {
11222         /* A read of 0xFFFF0001 should *always* return 1 byte. */
11223         if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11224                 return false;
11225         }
11226         /* A read of 0x10000 should return 0x10000 bytes. */
11227         if (check_read_call(cli, fnum, buf,    0x10000) == false) {
11228                 return false;
11229         }
11230         /* A read of 0x10000 should return 0x10001 bytes. */
11231         if (check_read_call(cli, fnum, buf,    0x10001) == false) {
11232                 return false;
11233         }
11234         /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11235            the requested number of bytes. */
11236         if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11237                 return false;
11238         }
11239         /* A read of 1MB should return 1MB bytes (on Samba). */
11240         if (check_read_call(cli, fnum, buf,   0x100000) == false) {
11241                 return false;
11242         }
11243
11244         if (check_read_call(cli, fnum, buf,    0x20001) == false) {
11245                 return false;
11246         }
11247         if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11248                 return false;
11249         }
11250         if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11251                 return false;
11252         }
11253         return true;
11254 }
11255
11256 static bool run_large_readx(int dummy)
11257 {
11258         uint8_t *buf = NULL;
11259         struct cli_state *cli1 = NULL;
11260         struct cli_state *cli2 = NULL;
11261         bool correct = false;
11262         const char *fname = "\\large_readx.dat";
11263         NTSTATUS status;
11264         uint16_t fnum1 = UINT16_MAX;
11265         uint32_t normal_caps = 0;
11266         size_t file_size = 20*1024*1024;
11267         TALLOC_CTX *frame = talloc_stackframe();
11268         size_t i;
11269         struct {
11270                 const char *name;
11271                 enum smb_signing_setting signing_setting;
11272                 enum protocol_types protocol;
11273         } runs[] = {
11274                 {
11275                         .name = "NT1",
11276                         .signing_setting = SMB_SIGNING_IF_REQUIRED,
11277                         .protocol = PROTOCOL_NT1,
11278                 },{
11279                         .name = "NT1 - SIGNING_REQUIRED",
11280                         .signing_setting = SMB_SIGNING_REQUIRED,
11281                         .protocol = PROTOCOL_NT1,
11282                 },
11283         };
11284
11285         printf("starting large_readx test\n");
11286
11287         if (!torture_open_connection(&cli1, 0)) {
11288                 goto out;
11289         }
11290
11291         normal_caps = smb1cli_conn_capabilities(cli1->conn);
11292
11293         if (!(normal_caps & CAP_LARGE_READX)) {
11294                 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11295                         (unsigned int)normal_caps);
11296                 goto out;
11297         }
11298
11299         /* Create a file of size 4MB. */
11300         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11301                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11302                         0, 0, &fnum1, NULL);
11303
11304         if (!NT_STATUS_IS_OK(status)) {
11305                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11306                 goto out;
11307         }
11308
11309         /* Write file_size bytes. */
11310         buf = talloc_zero_array(frame, uint8_t, file_size);
11311         if (buf == NULL) {
11312                 goto out;
11313         }
11314
11315         status = cli_writeall(cli1,
11316                               fnum1,
11317                               0,
11318                               buf,
11319                               0,
11320                               file_size,
11321                               NULL);
11322         if (!NT_STATUS_IS_OK(status)) {
11323                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11324                 goto out;
11325         }
11326
11327         status = cli_close(cli1, fnum1);
11328         if (!NT_STATUS_IS_OK(status)) {
11329                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11330                 goto out;
11331         }
11332
11333         fnum1 = UINT16_MAX;
11334
11335         for (i=0; i < ARRAY_SIZE(runs); i++) {
11336                 enum smb_signing_setting saved_signing_setting = signing_state;
11337                 uint16_t fnum2 = -1;
11338
11339                 if (do_encrypt &&
11340                     (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11341                 {
11342                         d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11343                         continue;
11344                 }
11345
11346                 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11347
11348                 signing_state = runs[i].signing_setting;
11349                 cli2 = open_nbt_connection();
11350                 signing_state = saved_signing_setting;
11351                 if (cli2 == NULL) {
11352                         goto out;
11353                 }
11354
11355                 status = smbXcli_negprot(cli2->conn,
11356                                          cli2->timeout,
11357                                          runs[i].protocol,
11358                                          runs[i].protocol);
11359                 if (!NT_STATUS_IS_OK(status)) {
11360                         goto out;
11361                 }
11362
11363                 status = cli_session_setup_creds(cli2, torture_creds);
11364                 if (!NT_STATUS_IS_OK(status)) {
11365                         goto out;
11366                 }
11367
11368                 status = cli_tree_connect(cli2,
11369                                         share,
11370                                         "?????",
11371                                         password);
11372                 if (!NT_STATUS_IS_OK(status)) {
11373                         goto out;
11374                 }
11375
11376                 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11377
11378                 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11379
11380                 if (!(normal_caps & CAP_LARGE_READX)) {
11381                         d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11382                                 (unsigned int)normal_caps);
11383                         goto out;
11384                 }
11385
11386                 if (do_encrypt) {
11387                         if (force_cli_encryption(cli2, share) == false) {
11388                                 goto out;
11389                         }
11390                 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11391                         uint16_t major, minor;
11392                         uint32_t caplow, caphigh;
11393
11394                         status = cli_unix_extensions_version(cli2,
11395                                                              &major, &minor,
11396                                                              &caplow, &caphigh);
11397                         if (!NT_STATUS_IS_OK(status)) {
11398                                 goto out;
11399                         }
11400                 }
11401
11402                 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11403                                 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11404                                 0, 0, &fnum2, NULL);
11405                 if (!NT_STATUS_IS_OK(status)) {
11406                         d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11407                         goto out;
11408                 }
11409
11410                 /* All reads must return less than file_size bytes. */
11411                 if (!large_readx_tests(cli2, fnum2, buf)) {
11412                         goto out;
11413                 }
11414
11415                 status = cli_close(cli2, fnum2);
11416                 if (!NT_STATUS_IS_OK(status)) {
11417                         d_printf("cli_close failed: %s\n", nt_errstr(status));
11418                         goto out;
11419                 }
11420                 fnum2 = -1;
11421
11422                 if (!torture_close_connection(cli2)) {
11423                         goto out;
11424                 }
11425                 cli2 = NULL;
11426         }
11427
11428         correct = true;
11429         printf("Success on large_readx test\n");
11430
11431   out:
11432
11433         if (cli2) {
11434                 if (!torture_close_connection(cli2)) {
11435                         correct = false;
11436                 }
11437         }
11438
11439         if (cli1) {
11440                 if (fnum1 != UINT16_MAX) {
11441                         status = cli_close(cli1, fnum1);
11442                         if (!NT_STATUS_IS_OK(status)) {
11443                                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11444                         }
11445                         fnum1 = UINT16_MAX;
11446                 }
11447
11448                 status = cli_unlink(cli1, fname,
11449                                     FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11450                 if (!NT_STATUS_IS_OK(status)) {
11451                         printf("unlink failed (%s)\n", nt_errstr(status));
11452                 }
11453
11454                 if (!torture_close_connection(cli1)) {
11455                         correct = false;
11456                 }
11457         }
11458
11459         TALLOC_FREE(frame);
11460
11461         printf("finished large_readx test\n");
11462         return correct;
11463 }
11464
11465 static NTSTATUS msdfs_attribute_list_fn(const char *mnt,
11466                                   struct file_info *finfo,
11467                                   const char *mask,
11468                                   void *private_data)
11469 {
11470         uint32_t *p_attr = (uint32_t *)private_data;
11471
11472         if (strequal(finfo->name, test_filename)) {
11473                 *p_attr = finfo->attr;
11474         }
11475
11476         return NT_STATUS_OK;
11477 }
11478
11479 static bool run_msdfs_attribute(int dummy)
11480 {
11481         static struct cli_state *cli;
11482         bool correct = false;
11483         uint32_t attr = 0;
11484         NTSTATUS status;
11485
11486         printf("Starting MSDFS-ATTRIBUTE test\n");
11487
11488         if (test_filename == NULL || test_filename[0] == '\0') {
11489                 printf("MSDFS-ATTRIBUTE test "
11490                         "needs -f filename-of-msdfs-link\n");
11491                 return false;
11492         }
11493
11494         /*
11495          * NB. We use torture_open_connection_flags() not
11496          * torture_open_connection() as the latter forces
11497          * SMB1.
11498          */
11499         if (!torture_open_connection_flags(&cli, 0, 0)) {
11500                 return false;
11501         }
11502
11503         smbXcli_conn_set_sockopt(cli->conn, sockops);
11504
11505         status = cli_list(cli,
11506                         "*",
11507                         FILE_ATTRIBUTE_DIRECTORY,
11508                         msdfs_attribute_list_fn,
11509                         &attr);
11510
11511         if (!NT_STATUS_IS_OK(status)) {
11512                 printf("cli_list failed with %s\n",
11513                         nt_errstr(status));
11514                 goto out;
11515         }
11516         if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11517                 printf("file %s should have "
11518                         "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11519                         test_filename,
11520                         (unsigned int)attr);
11521                 goto out;
11522         }
11523
11524         if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11525                 printf("file %s should have "
11526                         "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11527                         test_filename,
11528                         (unsigned int)attr);
11529                 goto out;
11530         }
11531
11532         correct = true;
11533
11534   out:
11535
11536         torture_close_connection(cli);
11537         return correct;
11538 }
11539
11540 static bool run_cli_echo(int dummy)
11541 {
11542         struct cli_state *cli;
11543         NTSTATUS status;
11544
11545         printf("starting cli_echo test\n");
11546         if (!torture_open_connection(&cli, 0)) {
11547                 return false;
11548         }
11549         smbXcli_conn_set_sockopt(cli->conn, sockops);
11550
11551         status = cli_echo(cli, 5, data_blob_const("hello", 5));
11552
11553         d_printf("cli_echo returned %s\n", nt_errstr(status));
11554
11555         torture_close_connection(cli);
11556         return NT_STATUS_IS_OK(status);
11557 }
11558
11559 static int splice_status(off_t written, void *priv)
11560 {
11561         return true;
11562 }
11563
11564 static bool run_cli_splice(int dummy)
11565 {
11566         uint8_t *buf = NULL;
11567         struct cli_state *cli1 = NULL;
11568         bool correct = false;
11569         const char *fname_src = "\\splice_src.dat";
11570         const char *fname_dst = "\\splice_dst.dat";
11571         NTSTATUS status;
11572         uint16_t fnum1 = UINT16_MAX;
11573         uint16_t fnum2 = UINT16_MAX;
11574         size_t file_size = 2*1024*1024;
11575         size_t splice_size = 1*1024*1024 + 713;
11576         uint8_t digest1[16], digest2[16];
11577         off_t written = 0;
11578         size_t nread = 0;
11579         TALLOC_CTX *frame = talloc_stackframe();
11580
11581         printf("starting cli_splice test\n");
11582
11583         if (!torture_open_connection(&cli1, 0)) {
11584                 goto out;
11585         }
11586
11587         cli_unlink(cli1, fname_src,
11588                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11589         cli_unlink(cli1, fname_dst,
11590                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11591
11592         /* Create a file */
11593         status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11594                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11595                         0, 0, &fnum1, NULL);
11596
11597         if (!NT_STATUS_IS_OK(status)) {
11598                 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11599                 goto out;
11600         }
11601
11602         /* Write file_size bytes - must be bigger than splice_size. */
11603         buf = talloc_zero_array(frame, uint8_t, file_size);
11604         if (buf == NULL) {
11605                 d_printf("talloc_fail\n");
11606                 goto out;
11607         }
11608
11609         /* Fill it with random numbers. */
11610         generate_random_buffer(buf, file_size);
11611
11612         /* MD5 the first 1MB + 713 bytes. */
11613         gnutls_hash_fast(GNUTLS_DIG_MD5,
11614                          buf,
11615                          splice_size,
11616                          digest1);
11617
11618         status = cli_writeall(cli1,
11619                               fnum1,
11620                               0,
11621                               buf,
11622                               0,
11623                               file_size,
11624                               NULL);
11625         if (!NT_STATUS_IS_OK(status)) {
11626                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11627                 goto out;
11628         }
11629
11630         status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11631                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11632                         0, 0, &fnum2, NULL);
11633
11634         if (!NT_STATUS_IS_OK(status)) {
11635                 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11636                 goto out;
11637         }
11638
11639         /* Now splice 1MB + 713 bytes. */
11640         status = cli_splice(cli1,
11641                                 cli1,
11642                                 fnum1,
11643                                 fnum2,
11644                                 splice_size,
11645                                 0,
11646                                 0,
11647                                 &written,
11648                                 splice_status,
11649                                 NULL);
11650
11651         if (!NT_STATUS_IS_OK(status)) {
11652                 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11653                 goto out;
11654         }
11655
11656         /* Clear the old buffer. */
11657         memset(buf, '\0', file_size);
11658
11659         /* Read the new file. */
11660         status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11661         if (!NT_STATUS_IS_OK(status)) {
11662                 d_printf("cli_read failed: %s\n", nt_errstr(status));
11663                 goto out;
11664         }
11665         if (nread != splice_size) {
11666                 d_printf("bad read of 0x%x, should be 0x%x\n",
11667                         (unsigned int)nread,
11668                         (unsigned int)splice_size);
11669                 goto out;
11670         }
11671
11672         /* MD5 the first 1MB + 713 bytes. */
11673         gnutls_hash_fast(GNUTLS_DIG_MD5,
11674                          buf,
11675                          splice_size,
11676                          digest2);
11677
11678         /* Must be the same. */
11679         if (memcmp(digest1, digest2, 16) != 0) {
11680                 d_printf("bad MD5 compare\n");
11681                 goto out;
11682         }
11683
11684         correct = true;
11685         printf("Success on cli_splice test\n");
11686
11687   out:
11688
11689         if (cli1) {
11690                 if (fnum1 != UINT16_MAX) {
11691                         cli_close(cli1, fnum1);
11692                 }
11693                 if (fnum2 != UINT16_MAX) {
11694                         cli_close(cli1, fnum2);
11695                 }
11696
11697                 cli_unlink(cli1, fname_src,
11698                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11699                 cli_unlink(cli1, fname_dst,
11700                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11701
11702                 if (!torture_close_connection(cli1)) {
11703                         correct = false;
11704                 }
11705         }
11706
11707         TALLOC_FREE(frame);
11708         return correct;
11709 }
11710
11711 static bool run_uid_regression_test(int dummy)
11712 {
11713         static struct cli_state *cli;
11714         int16_t old_vuid;
11715         int32_t old_cnum;
11716         bool correct = True;
11717         struct smbXcli_tcon *orig_tcon = NULL;
11718         NTSTATUS status;
11719
11720         printf("starting uid regression test\n");
11721
11722         if (!torture_open_connection(&cli, 0)) {
11723                 return False;
11724         }
11725
11726         smbXcli_conn_set_sockopt(cli->conn, sockops);
11727
11728         /* Ok - now save then logoff our current user. */
11729         old_vuid = cli_state_get_uid(cli);
11730
11731         status = cli_ulogoff(cli);
11732         if (!NT_STATUS_IS_OK(status)) {
11733                 d_printf("(%s) cli_ulogoff failed: %s\n",
11734                          __location__, nt_errstr(status));
11735                 correct = false;
11736                 goto out;
11737         }
11738
11739         cli_state_set_uid(cli, old_vuid);
11740
11741         /* Try an operation. */
11742         status = cli_mkdir(cli, "\\uid_reg_test");
11743         if (NT_STATUS_IS_OK(status)) {
11744                 d_printf("(%s) cli_mkdir succeeded\n",
11745                          __location__);
11746                 correct = false;
11747                 goto out;
11748         } else {
11749                 /* Should be bad uid. */
11750                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11751                                  NT_STATUS_USER_SESSION_DELETED)) {
11752                         correct = false;
11753                         goto out;
11754                 }
11755         }
11756
11757         old_cnum = cli_state_get_tid(cli);
11758         orig_tcon = cli_state_save_tcon(cli);
11759         if (orig_tcon == NULL) {
11760                 correct = false;
11761                 goto out;
11762         }
11763
11764         /* Now try a SMBtdis with the invalid vuid set to zero. */
11765         cli_state_set_uid(cli, 0);
11766
11767         /* This should succeed. */
11768         status = cli_tdis(cli);
11769
11770         if (NT_STATUS_IS_OK(status)) {
11771                 d_printf("First tdis with invalid vuid should succeed.\n");
11772         } else {
11773                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
11774                 correct = false;
11775                 cli_state_restore_tcon(cli, orig_tcon);
11776                 goto out;
11777         }
11778
11779         cli_state_restore_tcon(cli, orig_tcon);
11780         cli_state_set_uid(cli, old_vuid);
11781         cli_state_set_tid(cli, old_cnum);
11782
11783         /* This should fail. */
11784         status = cli_tdis(cli);
11785         if (NT_STATUS_IS_OK(status)) {
11786                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
11787                 correct = false;
11788                 goto out;
11789         } else {
11790                 /* Should be bad tid. */
11791                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
11792                                 NT_STATUS_NETWORK_NAME_DELETED)) {
11793                         correct = false;
11794                         goto out;
11795                 }
11796         }
11797
11798         cli_rmdir(cli, "\\uid_reg_test");
11799
11800   out:
11801
11802         cli_shutdown(cli);
11803         return correct;
11804 }
11805
11806
11807 static const char *illegal_chars = "*\\/?<>|\":";
11808 static char force_shortname_chars[] = " +,.[];=\177";
11809
11810 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
11811                              const char *mask, void *state)
11812 {
11813         struct cli_state *pcli = (struct cli_state *)state;
11814         fstring fname;
11815         NTSTATUS status = NT_STATUS_OK;
11816
11817         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
11818
11819         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
11820                 return NT_STATUS_OK;
11821
11822         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
11823                 status = cli_rmdir(pcli, fname);
11824                 if (!NT_STATUS_IS_OK(status)) {
11825                         printf("del_fn: failed to rmdir %s\n,", fname );
11826                 }
11827         } else {
11828                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11829                 if (!NT_STATUS_IS_OK(status)) {
11830                         printf("del_fn: failed to unlink %s\n,", fname );
11831                 }
11832         }
11833         return status;
11834 }
11835
11836 struct sn_state {
11837         int matched;
11838         int i;
11839         bool val;
11840 };
11841
11842 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
11843                               const char *name, void *state)
11844 {
11845         struct sn_state *s = (struct sn_state  *)state;
11846         int i = s->i;
11847
11848 #if 0
11849         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
11850                 i, finfo->name, finfo->short_name);
11851 #endif
11852
11853         if (strchr(force_shortname_chars, i)) {
11854                 if (!finfo->short_name) {
11855                         /* Shortname not created when it should be. */
11856                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
11857                                 __location__, finfo->name, i);
11858                         s->val = true;
11859                 }
11860         } else if (finfo->short_name){
11861                 /* Shortname created when it should not be. */
11862                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
11863                         __location__, finfo->short_name, finfo->name);
11864                 s->val = true;
11865         }
11866         s->matched += 1;
11867         return NT_STATUS_OK;
11868 }
11869
11870 static bool run_shortname_test(int dummy)
11871 {
11872         static struct cli_state *cli;
11873         bool correct = True;
11874         int i;
11875         struct sn_state s;
11876         char fname[40];
11877         NTSTATUS status;
11878
11879         printf("starting shortname test\n");
11880
11881         if (!torture_open_connection(&cli, 0)) {
11882                 return False;
11883         }
11884
11885         smbXcli_conn_set_sockopt(cli->conn, sockops);
11886
11887         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11888         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11889         cli_rmdir(cli, "\\shortname");
11890
11891         status = cli_mkdir(cli, "\\shortname");
11892         if (!NT_STATUS_IS_OK(status)) {
11893                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
11894                         __location__, nt_errstr(status));
11895                 correct = false;
11896                 goto out;
11897         }
11898
11899         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
11900                 correct = false;
11901                 goto out;
11902         }
11903         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
11904                 correct = false;
11905                 goto out;
11906         }
11907
11908         s.val = false;
11909
11910         for (i = 32; i < 128; i++) {
11911                 uint16_t fnum = (uint16_t)-1;
11912
11913                 s.i = i;
11914
11915                 if (strchr(illegal_chars, i)) {
11916                         continue;
11917                 }
11918                 fname[15] = i;
11919
11920                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
11921                                    FILE_SHARE_READ|FILE_SHARE_WRITE,
11922                                    FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
11923                 if (!NT_STATUS_IS_OK(status)) {
11924                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
11925                                 __location__, fname, nt_errstr(status));
11926                         correct = false;
11927                         goto out;
11928                 }
11929                 cli_close(cli, fnum);
11930
11931                 s.matched = 0;
11932                 status = cli_list(cli, "\\shortname\\test*.*", 0,
11933                                   shortname_list_fn, &s);
11934                 if (s.matched != 1) {
11935                         d_printf("(%s) failed to list %s: %s\n",
11936                                 __location__, fname, nt_errstr(status));
11937                         correct = false;
11938                         goto out;
11939                 }
11940
11941                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11942                 if (!NT_STATUS_IS_OK(status)) {
11943                         d_printf("(%s) failed to delete %s: %s\n",
11944                                 __location__, fname, nt_errstr(status));
11945                         correct = false;
11946                         goto out;
11947                 }
11948
11949                 if (s.val) {
11950                         correct = false;
11951                         goto out;
11952                 }
11953         }
11954
11955   out:
11956
11957         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11958         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11959         cli_rmdir(cli, "\\shortname");
11960         torture_close_connection(cli);
11961         return correct;
11962 }
11963
11964 TLDAPRC callback_code;
11965
11966 static void pagedsearch_cb(struct tevent_req *req)
11967 {
11968         TLDAPRC rc;
11969         struct tldap_message *msg;
11970         char *dn;
11971
11972         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
11973         if (!TLDAP_RC_IS_SUCCESS(rc)) {
11974                 d_printf("tldap_search_paged_recv failed: %s\n",
11975                          tldap_rc2string(rc));
11976                 callback_code = rc;
11977                 return;
11978         }
11979         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
11980                 TALLOC_FREE(msg);
11981                 return;
11982         }
11983         if (!tldap_entry_dn(msg, &dn)) {
11984                 d_printf("tldap_entry_dn failed\n");
11985                 return;
11986         }
11987         d_printf("%s\n", dn);
11988         TALLOC_FREE(msg);
11989 }
11990
11991 enum tldap_extended_val {
11992         EXTENDED_ZERO = 0,
11993         EXTENDED_ONE = 1,
11994         EXTENDED_NONE = 2,
11995 };
11996
11997 /*
11998  * Construct an extended dn control with either no value, 0 or 1
11999  *
12000  * No value and 0 are equivalent (non-hyphenated GUID)
12001  * 1 has the hyphenated GUID
12002  */
12003 static struct tldap_control *
12004 tldap_build_extended_control(enum tldap_extended_val val)
12005 {
12006         struct tldap_control empty_control;
12007         struct asn1_data *data;
12008
12009         ZERO_STRUCT(empty_control);
12010
12011         if (val != EXTENDED_NONE) {
12012                 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12013
12014                 if (!data) {
12015                         return NULL;
12016                 }
12017
12018                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12019                         return NULL;
12020                 }
12021
12022                 if (!asn1_write_Integer(data, (int)val)) {
12023                         return NULL;
12024                 }
12025
12026                 if (!asn1_pop_tag(data)) {
12027                         return NULL;
12028                 }
12029
12030                 if (!asn1_blob(data, &empty_control.value)) {
12031                         return NULL;
12032                 }
12033         }
12034
12035         empty_control.oid = "1.2.840.113556.1.4.529";
12036         empty_control.critical = true;
12037
12038         return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12039
12040 }
12041
12042 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12043                                       enum tldap_extended_val control_val)
12044 {
12045         struct tldap_control *control = tldap_build_extended_control(control_val);
12046         char *dn = NULL;
12047         struct tldap_message **msg;
12048         TLDAPRC rc;
12049
12050         rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12051                           "(objectClass=*)", NULL, 0, 0,
12052                           control, 1, NULL,
12053                           0, 0, 0, 0, talloc_tos(), &msg);
12054         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12055                 d_printf("tldap_search for domain DN failed: %s\n",
12056                          tldap_errstr(talloc_tos(), ld, rc));
12057                 return false;
12058         }
12059
12060         if (!tldap_entry_dn(msg[0], &dn)) {
12061                 d_printf("tldap_search domain DN fetch failed: %s\n",
12062                          tldap_errstr(talloc_tos(), ld, rc));
12063                 return false;
12064         }
12065
12066         d_printf("%s\n", dn);
12067         {
12068                 uint32_t time_low;
12069                 uint32_t time_mid, time_hi_and_version;
12070                 uint32_t clock_seq[2];
12071                 uint32_t node[6];
12072                 char next;
12073
12074                 switch (control_val) {
12075                 case EXTENDED_NONE:
12076                 case EXTENDED_ZERO:
12077                         /*
12078                          * When reading GUIDs with hyphens, scanf will treat
12079                          * hyphen as a hex character (and counts as part of the
12080                          * width). This creates leftover GUID string which we
12081                          * check will for with 'next' and closing '>'.
12082                          */
12083                         if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12084                                          &time_low, &time_mid,
12085                                          &time_hi_and_version, &clock_seq[0],
12086                                          &clock_seq[1], &node[0], &node[1],
12087                                          &node[2], &node[3], &node[4],
12088                                          &node[5], &next)) {
12089                                 /* This GUID is good */
12090                         } else {
12091                                 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12092                                 return false;
12093                         }
12094
12095                         break;
12096                 case EXTENDED_ONE:
12097                         if (12 == sscanf(dn,
12098                                          "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12099                                          &time_low, &time_mid,
12100                                          &time_hi_and_version, &clock_seq[0],
12101                                          &clock_seq[1], &node[0], &node[1],
12102                                          &node[2], &node[3], &node[4],
12103                                          &node[5], &next)) {
12104                                 /* This GUID is good */
12105                         } else {
12106                                 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12107                                 return false;
12108                         }
12109
12110                         break;
12111                 default:
12112                         return false;
12113                 }
12114         }
12115
12116         return true;
12117 }
12118
12119 static bool run_tldap(int dummy)
12120 {
12121         struct tldap_context *ld;
12122         int fd;
12123         TLDAPRC rc;
12124         NTSTATUS status;
12125         struct sockaddr_storage addr;
12126         struct tevent_context *ev;
12127         struct tevent_req *req;
12128         char *basedn;
12129         const char *filter;
12130
12131         if (!resolve_name(host, &addr, 0, false)) {
12132                 d_printf("could not find host %s\n", host);
12133                 return false;
12134         }
12135         status = open_socket_out(&addr, 389, 9999, &fd);
12136         if (!NT_STATUS_IS_OK(status)) {
12137                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12138                 return false;
12139         }
12140
12141         ld = tldap_context_create(talloc_tos(), fd);
12142         if (ld == NULL) {
12143                 close(fd);
12144                 d_printf("tldap_context_create failed\n");
12145                 return false;
12146         }
12147
12148         rc = tldap_fetch_rootdse(ld);
12149         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12150                 d_printf("tldap_fetch_rootdse failed: %s\n",
12151                          tldap_errstr(talloc_tos(), ld, rc));
12152                 return false;
12153         }
12154
12155         basedn = tldap_talloc_single_attribute(
12156                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12157         if (basedn == NULL) {
12158                 d_printf("no defaultNamingContext\n");
12159                 return false;
12160         }
12161         d_printf("defaultNamingContext: %s\n", basedn);
12162
12163         ev = samba_tevent_context_init(talloc_tos());
12164         if (ev == NULL) {
12165                 d_printf("tevent_context_init failed\n");
12166                 return false;
12167         }
12168
12169         rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12170                                loadparm_init_s3(talloc_tos(),
12171                                                 loadparm_s3_helpers()),
12172                                GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12173
12174         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12175                 d_printf("tldap_gensec_bind failed\n");
12176                 return false;
12177         }
12178
12179         callback_code = TLDAP_SUCCESS;
12180
12181         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12182                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
12183                                       NULL, 0, 0,
12184                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
12185         if (req == NULL) {
12186                 d_printf("tldap_search_paged_send failed\n");
12187                 return false;
12188         }
12189         tevent_req_set_callback(req, pagedsearch_cb, NULL);
12190
12191         tevent_req_poll(req, ev);
12192
12193         TALLOC_FREE(req);
12194
12195         rc = callback_code;
12196
12197         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12198                 d_printf("tldap_search with paging failed: %s\n",
12199                          tldap_errstr(talloc_tos(), ld, rc));
12200                 return false;
12201         }
12202
12203         /* test search filters against rootDSE */
12204         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12205                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12206
12207         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12208                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12209                           talloc_tos(), NULL);
12210         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12211                 d_printf("tldap_search with complex filter failed: %s\n",
12212                          tldap_errstr(talloc_tos(), ld, rc));
12213                 return false;
12214         }
12215
12216         /*
12217          * Tests to check for regression of:
12218          *
12219          * https://bugzilla.samba.org/show_bug.cgi?id=14029
12220          *
12221          * TLDAP used here to pick apart the original string DN (with GUID)
12222          */
12223         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12224                 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12225                          tldap_errstr(talloc_tos(), ld, rc));
12226                 return false;
12227         }
12228         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12229                 d_printf("tldap_search with extended dn (0) failed: %s\n",
12230                          tldap_errstr(talloc_tos(), ld, rc));
12231                 return false;
12232         }
12233         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12234                 d_printf("tldap_search with extended dn (1) failed: %s\n",
12235                          tldap_errstr(talloc_tos(), ld, rc));
12236                 return false;
12237         }
12238
12239         TALLOC_FREE(ld);
12240         return true;
12241 }
12242
12243 /* Torture test to ensure no regression of :
12244 https://bugzilla.samba.org/show_bug.cgi?id=7084
12245 */
12246
12247 static bool run_dir_createtime(int dummy)
12248 {
12249         struct cli_state *cli;
12250         const char *dname = "\\testdir_createtime";
12251         const char *fname = "\\testdir_createtime\\testfile";
12252         NTSTATUS status;
12253         struct timespec create_time;
12254         struct timespec create_time1;
12255         uint16_t fnum;
12256         bool ret = false;
12257         uint64_t ino;
12258
12259         if (!torture_open_connection(&cli, 0)) {
12260                 return false;
12261         }
12262
12263         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12264                 /* Ensure ino is zero, SMB2 gets a real one. */
12265                 ino = 0;
12266         } else {
12267                 /* Ensure ino is -1, SMB1 never gets a real one. */
12268                 ino = (uint64_t)-1;
12269         }
12270
12271         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12272         cli_rmdir(cli, dname);
12273
12274         status = cli_mkdir(cli, dname);
12275         if (!NT_STATUS_IS_OK(status)) {
12276                 printf("mkdir failed: %s\n", nt_errstr(status));
12277                 goto out;
12278         }
12279
12280         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
12281                                 NULL, NULL, &ino);
12282         if (!NT_STATUS_IS_OK(status)) {
12283                 printf("cli_qpathinfo2 returned %s\n",
12284                        nt_errstr(status));
12285                 goto out;
12286         }
12287
12288         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12289                 /* SMB2 should always return an inode. */
12290                 if (ino == 0) {
12291                         printf("SMB2 bad inode (0)\n");
12292                         goto out;
12293                 }
12294         } else {
12295                 /* SMB1 must always return zero here. */
12296                 if (ino != 0) {
12297                         printf("SMB1 bad inode (!0)\n");
12298                         goto out;
12299                 }
12300         }
12301
12302         /* Sleep 3 seconds, then create a file. */
12303         sleep(3);
12304
12305         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12306                          DENY_NONE, &fnum);
12307         if (!NT_STATUS_IS_OK(status)) {
12308                 printf("cli_openx failed: %s\n", nt_errstr(status));
12309                 goto out;
12310         }
12311
12312         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
12313                                 NULL, NULL, NULL);
12314         if (!NT_STATUS_IS_OK(status)) {
12315                 printf("cli_qpathinfo2 (2) returned %s\n",
12316                        nt_errstr(status));
12317                 goto out;
12318         }
12319
12320         if (timespec_compare(&create_time1, &create_time)) {
12321                 printf("run_dir_createtime: create time was updated (error)\n");
12322         } else {
12323                 printf("run_dir_createtime: create time was not updated (correct)\n");
12324                 ret = true;
12325         }
12326
12327   out:
12328
12329         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12330         cli_rmdir(cli, dname);
12331         if (!torture_close_connection(cli)) {
12332                 ret = false;
12333         }
12334         return ret;
12335 }
12336
12337
12338 static bool run_streamerror(int dummy)
12339 {
12340         struct cli_state *cli;
12341         const char *dname = "\\testdir_streamerror";
12342         const char *streamname =
12343                 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12344         NTSTATUS status;
12345         time_t change_time, access_time, write_time;
12346         off_t size;
12347         uint16_t fnum;
12348         uint32_t attr;
12349         bool ret = true;
12350
12351         if (!torture_open_connection(&cli, 0)) {
12352                 return false;
12353         }
12354
12355         cli_unlink(cli, "\\testdir_streamerror\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12356         cli_rmdir(cli, dname);
12357
12358         status = cli_mkdir(cli, dname);
12359         if (!NT_STATUS_IS_OK(status)) {
12360                 printf("mkdir failed: %s\n", nt_errstr(status));
12361                 return false;
12362         }
12363
12364         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12365                                 &write_time, &size, &attr);
12366         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12367                 printf("pathinfo returned %s, expected "
12368                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12369                        nt_errstr(status));
12370                 ret = false;
12371         }
12372
12373         status = cli_ntcreate(cli, streamname, 0x16,
12374                               FILE_READ_DATA|FILE_READ_EA|
12375                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12376                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12377                               FILE_OPEN, 0, 0, &fnum, NULL);
12378
12379         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12380                 printf("ntcreate returned %s, expected "
12381                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12382                        nt_errstr(status));
12383                 ret = false;
12384         }
12385
12386
12387         cli_rmdir(cli, dname);
12388         return ret;
12389 }
12390
12391 struct pidtest_state {
12392         bool success;
12393         uint16_t vwv[1];
12394         DATA_BLOB data;
12395 };
12396
12397 static void pid_echo_done(struct tevent_req *subreq);
12398
12399 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12400                         struct tevent_context *ev,
12401                         struct cli_state *cli)
12402 {
12403         struct tevent_req *req, *subreq;
12404         struct pidtest_state *state;
12405
12406         req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12407         if (req == NULL) {
12408                 return NULL;
12409         }
12410
12411         SSVAL(state->vwv, 0, 1);
12412         state->data = data_blob_const("hello", 5);
12413
12414         subreq = smb1cli_req_send(state,
12415                                 ev,
12416                                 cli->conn,
12417                                 SMBecho,
12418                                 0, 0, /* *_flags */
12419                                 0, 0, /* *_flags2 */
12420                                 cli->timeout,
12421                                 0xDEADBEEF, /* pid */
12422                                 NULL, /* tcon */
12423                                 NULL, /* session */
12424                                 ARRAY_SIZE(state->vwv), state->vwv,
12425                                 state->data.length, state->data.data);
12426
12427         if (tevent_req_nomem(subreq, req)) {
12428                 return tevent_req_post(req, ev);
12429         }
12430         tevent_req_set_callback(subreq, pid_echo_done, req);
12431         return req;
12432 }
12433
12434 static void pid_echo_done(struct tevent_req *subreq)
12435 {
12436         struct tevent_req *req = tevent_req_callback_data(
12437                 subreq, struct tevent_req);
12438         struct pidtest_state *state = tevent_req_data(
12439                 req, struct pidtest_state);
12440         NTSTATUS status;
12441         uint32_t num_bytes;
12442         uint8_t *bytes = NULL;
12443         struct iovec *recv_iov = NULL;
12444         uint8_t *phdr = NULL;
12445         uint16_t pidlow = 0;
12446         uint16_t pidhigh = 0;
12447         struct smb1cli_req_expected_response expected[] = {
12448         {
12449                 .status = NT_STATUS_OK,
12450                 .wct    = 1,
12451         },
12452         };
12453
12454         status = smb1cli_req_recv(subreq, state,
12455                                 &recv_iov,
12456                                 &phdr,
12457                                 NULL, /* pwct */
12458                                 NULL, /* pvwv */
12459                                 NULL, /* pvwv_offset */
12460                                 &num_bytes,
12461                                 &bytes,
12462                                 NULL, /* pbytes_offset */
12463                                 NULL, /* pinbuf */
12464                                 expected, ARRAY_SIZE(expected));
12465
12466         TALLOC_FREE(subreq);
12467
12468         if (!NT_STATUS_IS_OK(status)) {
12469                 tevent_req_nterror(req, status);
12470                 return;
12471         }
12472
12473         if (num_bytes != state->data.length) {
12474                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12475                 return;
12476         }
12477
12478         if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12479                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12480                 return;
12481         }
12482
12483         /* Check pid low/high == DEADBEEF */
12484         pidlow = SVAL(phdr, HDR_PID);
12485         if (pidlow != 0xBEEF){
12486                 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12487                         (unsigned int)pidlow);
12488                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12489                 return;
12490         }
12491         pidhigh = SVAL(phdr, HDR_PIDHIGH);
12492         if (pidhigh != 0xDEAD){
12493                 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12494                         (unsigned int)pidhigh);
12495                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12496                 return;
12497         }
12498
12499         tevent_req_done(req);
12500 }
12501
12502 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12503 {
12504         return tevent_req_simple_recv_ntstatus(req);
12505 }
12506
12507 static bool run_pidhigh(int dummy)
12508 {
12509         bool success = false;
12510         struct cli_state *cli = NULL;
12511         NTSTATUS status;
12512         struct tevent_context *ev = NULL;
12513         struct tevent_req *req = NULL;
12514         TALLOC_CTX *frame = talloc_stackframe();
12515
12516         printf("starting pid high test\n");
12517         if (!torture_open_connection(&cli, 0)) {
12518                 return false;
12519         }
12520         smbXcli_conn_set_sockopt(cli->conn, sockops);
12521
12522         ev = samba_tevent_context_init(frame);
12523         if (ev == NULL) {
12524                 goto fail;
12525         }
12526
12527         req = pid_echo_send(frame, ev, cli);
12528         if (req == NULL) {
12529                 goto fail;
12530         }
12531
12532         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12533                 goto fail;
12534         }
12535
12536         status = pid_echo_recv(req);
12537         if (NT_STATUS_IS_OK(status)) {
12538                 printf("pid high test ok\n");
12539                 success = true;
12540         }
12541
12542  fail:
12543
12544         TALLOC_FREE(frame);
12545         torture_close_connection(cli);
12546         return success;
12547 }
12548
12549 /*
12550   Test Windows open on a bad POSIX symlink.
12551  */
12552 static bool run_symlink_open_test(int dummy)
12553 {
12554         static struct cli_state *cli;
12555         const char *fname = "non_existant_file";
12556         const char *sname = "dangling_symlink";
12557         uint16_t fnum = (uint16_t)-1;
12558         bool correct = false;
12559         NTSTATUS status;
12560         TALLOC_CTX *frame = NULL;
12561
12562         frame = talloc_stackframe();
12563
12564         printf("Starting Windows bad symlink open test\n");
12565
12566         if (!torture_open_connection(&cli, 0)) {
12567                 TALLOC_FREE(frame);
12568                 return false;
12569         }
12570
12571         smbXcli_conn_set_sockopt(cli->conn, sockops);
12572
12573         status = torture_setup_unix_extensions(cli);
12574         if (!NT_STATUS_IS_OK(status)) {
12575                 TALLOC_FREE(frame);
12576                 return false;
12577         }
12578
12579         /* Ensure nothing exists. */
12580         cli_setatr(cli, fname, 0, 0);
12581         cli_posix_unlink(cli, fname);
12582         cli_setatr(cli, sname, 0, 0);
12583         cli_posix_unlink(cli, sname);
12584
12585         /* Create a symlink pointing nowhere. */
12586         status = cli_posix_symlink(cli, fname, sname);
12587         if (!NT_STATUS_IS_OK(status)) {
12588                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12589                         sname,
12590                         fname,
12591                         nt_errstr(status));
12592                 goto out;
12593         }
12594
12595         /* Now ensure that a Windows open doesn't hang. */
12596         status = cli_ntcreate(cli,
12597                         sname,
12598                         0,
12599                         FILE_READ_DATA|FILE_WRITE_DATA,
12600                         0,
12601                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12602                         FILE_OPEN_IF,
12603                         0x0,
12604                         0x0,
12605                         &fnum,
12606                         NULL);
12607
12608         /*
12609          * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12610          * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12611          * we use O_NOFOLLOW on the server or not.
12612          */
12613         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12614             NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12615         {
12616                 correct = true;
12617         } else {
12618                 printf("cli_ntcreate of %s returned %s - should return"
12619                                 " either (%s) or (%s)\n",
12620                         sname,
12621                         nt_errstr(status),
12622                         nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12623                         nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12624                 goto out;
12625         }
12626
12627         correct = true;
12628
12629   out:
12630
12631         if (fnum != (uint16_t)-1) {
12632                 cli_close(cli, fnum);
12633                 fnum = (uint16_t)-1;
12634         }
12635
12636         cli_setatr(cli, sname, 0, 0);
12637         cli_posix_unlink(cli, sname);
12638         cli_setatr(cli, fname, 0, 0);
12639         cli_posix_unlink(cli, fname);
12640
12641         if (!torture_close_connection(cli)) {
12642                 correct = false;
12643         }
12644
12645         TALLOC_FREE(frame);
12646         return correct;
12647 }
12648
12649 /*
12650  * Only testing minimal time strings, as the others
12651  * need (locale-dependent) guessing at what strftime does and
12652  * even may differ in builds.
12653  */
12654 static bool timesubst_test(void)
12655 {
12656         TALLOC_CTX *ctx = NULL;
12657         /* Sa 23. Dez 04:33:20 CET 2017 */
12658         const struct timeval tv = { 1514000000, 123 };
12659         const char* expect_minimal = "20171223_033320";
12660         const char* expect_minus   = "20171223_033320_000123";
12661         char *s;
12662         char *env_tz, *orig_tz = NULL;
12663         bool result = true;
12664
12665         ctx = talloc_new(NULL);
12666
12667         env_tz = getenv("TZ");
12668         if(env_tz) {
12669                 orig_tz = talloc_strdup(ctx, env_tz);
12670         }
12671         setenv("TZ", "UTC", 1);
12672
12673         s = minimal_timeval_string(ctx, &tv, false);
12674
12675         if(!s || strcmp(s, expect_minimal)) {
12676                 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
12677                        "[%s]\n", s ? s : "<nil>", expect_minimal);
12678                 result = false;
12679         }
12680         TALLOC_FREE(s);
12681         s = minimal_timeval_string(ctx, &tv, true);
12682         if(!s || strcmp(s, expect_minus)) {
12683                 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
12684                        "[%s]\n", s ? s : "<nil>", expect_minus);
12685                 result = false;
12686         }
12687         TALLOC_FREE(s);
12688
12689         if(orig_tz) {
12690                 setenv("TZ", orig_tz, 1);
12691         }
12692
12693         TALLOC_FREE(ctx);
12694         return result;
12695 }
12696
12697 static bool run_local_substitute(int dummy)
12698 {
12699         bool ok = true;
12700
12701         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
12702         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
12703         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
12704         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
12705         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
12706         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
12707         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
12708         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
12709         ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
12710         /* Substitution depends on current time, so better test the underlying
12711            formatting function. At least covers %t. */
12712         ok &= timesubst_test();
12713
12714         /* Different captialization rules in sub_basic... */
12715
12716         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
12717                        "blaDOM") == 0);
12718
12719         return ok;
12720 }
12721
12722 static bool run_local_base64(int dummy)
12723 {
12724         int i;
12725         bool ret = true;
12726
12727         for (i=1; i<2000; i++) {
12728                 DATA_BLOB blob1, blob2;
12729                 char *b64;
12730
12731                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
12732                 blob1.length = i;
12733                 generate_random_buffer(blob1.data, blob1.length);
12734
12735                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
12736                 if (b64 == NULL) {
12737                         d_fprintf(stderr, "base64_encode_data_blob failed "
12738                                   "for %d bytes\n", i);
12739                         ret = false;
12740                 }
12741                 blob2 = base64_decode_data_blob(b64);
12742                 TALLOC_FREE(b64);
12743
12744                 if (data_blob_cmp(&blob1, &blob2)) {
12745                         d_fprintf(stderr, "data_blob_cmp failed for %d "
12746                                   "bytes\n", i);
12747                         ret = false;
12748                 }
12749                 TALLOC_FREE(blob1.data);
12750                 data_blob_free(&blob2);
12751         }
12752         return ret;
12753 }
12754
12755 static void parse_fn(const struct gencache_timeout *t,
12756                      DATA_BLOB blob,
12757                      void *private_data)
12758 {
12759         return;
12760 }
12761
12762 static bool run_local_gencache(int dummy)
12763 {
12764         char *val;
12765         time_t tm;
12766         DATA_BLOB blob;
12767         char v;
12768         struct memcache *mem;
12769         int i;
12770
12771         mem = memcache_init(NULL, 0);
12772         if (mem == NULL) {
12773                 d_printf("%s: memcache_init failed\n", __location__);
12774                 return false;
12775         }
12776         memcache_set_global(mem);
12777
12778         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
12779                 d_printf("%s: gencache_set() failed\n", __location__);
12780                 return False;
12781         }
12782
12783         if (!gencache_get("foo", NULL, NULL, NULL)) {
12784                 d_printf("%s: gencache_get() failed\n", __location__);
12785                 return False;
12786         }
12787
12788         for (i=0; i<1000000; i++) {
12789                 gencache_parse("foo", parse_fn, NULL);
12790         }
12791
12792         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
12793                 d_printf("%s: gencache_get() failed\n", __location__);
12794                 return False;
12795         }
12796         TALLOC_FREE(val);
12797
12798         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
12799                 d_printf("%s: gencache_get() failed\n", __location__);
12800                 return False;
12801         }
12802
12803         if (strcmp(val, "bar") != 0) {
12804                 d_printf("%s: gencache_get() returned %s, expected %s\n",
12805                          __location__, val, "bar");
12806                 TALLOC_FREE(val);
12807                 return False;
12808         }
12809
12810         TALLOC_FREE(val);
12811
12812         if (!gencache_del("foo")) {
12813                 d_printf("%s: gencache_del() failed\n", __location__);
12814                 return False;
12815         }
12816         if (gencache_del("foo")) {
12817                 d_printf("%s: second gencache_del() succeeded\n",
12818                          __location__);
12819                 return False;
12820         }
12821
12822         if (gencache_get("foo", talloc_tos(), &val, &tm)) {
12823                 d_printf("%s: gencache_get() on deleted entry "
12824                          "succeeded\n", __location__);
12825                 return False;
12826         }
12827
12828         blob = data_blob_string_const_null("bar");
12829         tm = time(NULL) + 60;
12830
12831         if (!gencache_set_data_blob("foo", blob, tm)) {
12832                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
12833                 return False;
12834         }
12835
12836         if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
12837                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
12838                 return False;
12839         }
12840
12841         if (strcmp((const char *)blob.data, "bar") != 0) {
12842                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
12843                          __location__, (const char *)blob.data, "bar");
12844                 data_blob_free(&blob);
12845                 return False;
12846         }
12847
12848         data_blob_free(&blob);
12849
12850         if (!gencache_del("foo")) {
12851                 d_printf("%s: gencache_del() failed\n", __location__);
12852                 return False;
12853         }
12854         if (gencache_del("foo")) {
12855                 d_printf("%s: second gencache_del() succeeded\n",
12856                          __location__);
12857                 return False;
12858         }
12859
12860         if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
12861                 d_printf("%s: gencache_get_data_blob() on deleted entry "
12862                          "succeeded\n", __location__);
12863                 return False;
12864         }
12865
12866         v = 1;
12867         blob.data = (uint8_t *)&v;
12868         blob.length = sizeof(v);
12869
12870         if (!gencache_set_data_blob("blob", blob, tm)) {
12871                 d_printf("%s: gencache_set_data_blob() failed\n",
12872                          __location__);
12873                 return false;
12874         }
12875         if (gencache_get("blob", talloc_tos(), &val, &tm)) {
12876                 d_printf("%s: gencache_get succeeded\n", __location__);
12877                 return false;
12878         }
12879
12880         return True;
12881 }
12882
12883 static bool rbt_testval(struct db_context *db, const char *key,
12884                         const char *value)
12885 {
12886         struct db_record *rec;
12887         TDB_DATA data = string_tdb_data(value);
12888         bool ret = false;
12889         NTSTATUS status;
12890         TDB_DATA dbvalue;
12891
12892         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
12893         if (rec == NULL) {
12894                 d_fprintf(stderr, "fetch_locked failed\n");
12895                 goto done;
12896         }
12897         status = dbwrap_record_store(rec, data, 0);
12898         if (!NT_STATUS_IS_OK(status)) {
12899                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
12900                 goto done;
12901         }
12902         TALLOC_FREE(rec);
12903
12904         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
12905         if (rec == NULL) {
12906                 d_fprintf(stderr, "second fetch_locked failed\n");
12907                 goto done;
12908         }
12909
12910         dbvalue = dbwrap_record_get_value(rec);
12911         if ((dbvalue.dsize != data.dsize)
12912             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
12913                 d_fprintf(stderr, "Got wrong data back\n");
12914                 goto done;
12915         }
12916
12917         ret = true;
12918  done:
12919         TALLOC_FREE(rec);
12920         return ret;
12921 }
12922
12923 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
12924 {
12925         int *count2 = (int *)private_data;
12926         (*count2)++;
12927         return 0;
12928 }
12929
12930 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
12931 {
12932         int *count2 = (int *)private_data;
12933         (*count2)++;
12934         dbwrap_record_delete(rec);
12935         return 0;
12936 }
12937
12938 static bool run_local_rbtree(int dummy)
12939 {
12940         struct db_context *db;
12941         bool ret = false;
12942         int i;
12943         NTSTATUS status;
12944         int count = 0;
12945         int count2 = 0;
12946
12947         db = db_open_rbt(NULL);
12948
12949         if (db == NULL) {
12950                 d_fprintf(stderr, "db_open_rbt failed\n");
12951                 return false;
12952         }
12953
12954         for (i=0; i<1000; i++) {
12955                 char *key, *value;
12956
12957                 if (asprintf(&key, "key%ld", random()) == -1) {
12958                         goto done;
12959                 }
12960                 if (asprintf(&value, "value%ld", random()) == -1) {
12961                         SAFE_FREE(key);
12962                         goto done;
12963                 }
12964
12965                 if (!rbt_testval(db, key, value)) {
12966                         SAFE_FREE(key);
12967                         SAFE_FREE(value);
12968                         goto done;
12969                 }
12970
12971                 SAFE_FREE(value);
12972                 if (asprintf(&value, "value%ld", random()) == -1) {
12973                         SAFE_FREE(key);
12974                         goto done;
12975                 }
12976
12977                 if (!rbt_testval(db, key, value)) {
12978                         SAFE_FREE(key);
12979                         SAFE_FREE(value);
12980                         goto done;
12981                 }
12982
12983                 SAFE_FREE(key);
12984                 SAFE_FREE(value);
12985         }
12986
12987         ret = true;
12988         count = 0; count2 = 0;
12989         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
12990                                       &count2, &count);
12991         printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
12992         if ((count != count2) || (count != 1000)) {
12993                 ret = false;
12994         }
12995         count = 0; count2 = 0;
12996         status = dbwrap_traverse(db, local_rbtree_traverse_delete,
12997                                  &count2, &count);
12998         printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
12999         if ((count != count2) || (count != 1000)) {
13000                 ret = false;
13001         }
13002         count = 0; count2 = 0;
13003         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13004                                       &count2, &count);
13005         printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13006         if ((count != count2) || (count != 0)) {
13007                 ret = false;
13008         }
13009
13010  done:
13011         TALLOC_FREE(db);
13012         return ret;
13013 }
13014
13015
13016 /*
13017   local test for character set functions
13018
13019   This is a very simple test for the functionality in convert_string_error()
13020  */
13021 static bool run_local_convert_string(int dummy)
13022 {
13023         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13024         const char *test_strings[2] = { "March", "M\303\244rz" };
13025         char dst[7];
13026         int i;
13027
13028         for (i=0; i<2; i++) {
13029                 const char *str = test_strings[i];
13030                 int len = strlen(str);
13031                 size_t converted_size;
13032                 bool ret;
13033
13034                 memset(dst, 'X', sizeof(dst));
13035
13036                 /* first try with real source length */
13037                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13038                                            str, len,
13039                                            dst, sizeof(dst),
13040                                            &converted_size);
13041                 if (ret != true) {
13042                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13043                         goto failed;
13044                 }
13045
13046                 if (converted_size != len) {
13047                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13048                                   str, len, (int)converted_size);
13049                         goto failed;
13050                 }
13051
13052                 if (strncmp(str, dst, converted_size) != 0) {
13053                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13054                         goto failed;
13055                 }
13056
13057                 if (strlen(str) != converted_size) {
13058                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13059                                   (int)strlen(str), (int)converted_size);
13060                         goto failed;
13061                 }
13062
13063                 if (dst[converted_size] != 'X') {
13064                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13065                         goto failed;
13066                 }
13067
13068                 /* now with srclen==-1, this causes the nul to be
13069                  * converted too */
13070                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13071                                            str, -1,
13072                                            dst, sizeof(dst),
13073                                            &converted_size);
13074                 if (ret != true) {
13075                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13076                         goto failed;
13077                 }
13078
13079                 if (converted_size != len+1) {
13080                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13081                                   str, len, (int)converted_size);
13082                         goto failed;
13083                 }
13084
13085                 if (strncmp(str, dst, converted_size) != 0) {
13086                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13087                         goto failed;
13088                 }
13089
13090                 if (len+1 != converted_size) {
13091                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13092                                   len+1, (int)converted_size);
13093                         goto failed;
13094                 }
13095
13096                 if (dst[converted_size] != 'X') {
13097                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13098                         goto failed;
13099                 }
13100
13101         }
13102
13103
13104         TALLOC_FREE(tmp_ctx);
13105         return true;
13106 failed:
13107         TALLOC_FREE(tmp_ctx);
13108         return false;
13109 }
13110
13111 static bool run_local_string_to_sid(int dummy) {
13112         struct dom_sid sid;
13113
13114         if (string_to_sid(&sid, "S--1-5-32-545")) {
13115                 printf("allowing S--1-5-32-545\n");
13116                 return false;
13117         }
13118         if (string_to_sid(&sid, "S-1-5-32-+545")) {
13119                 printf("allowing S-1-5-32-+545\n");
13120                 return false;
13121         }
13122         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")) {
13123                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13124                 return false;
13125         }
13126         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13127                 printf("allowing S-1-5-32-545-abc\n");
13128                 return false;
13129         }
13130         if (string_to_sid(&sid, "S-300-5-32-545")) {
13131                 printf("allowing S-300-5-32-545\n");
13132                 return false;
13133         }
13134         if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13135                 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13136                 return false;
13137         }
13138         if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13139                 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13140                 return false;
13141         }
13142         if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13143                 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13144                 return false;
13145         }
13146         if (!string_to_sid(&sid, "S-1-5-32-545")) {
13147                 printf("could not parse S-1-5-32-545\n");
13148                 return false;
13149         }
13150         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13151                 struct dom_sid_buf buf;
13152                 printf("mis-parsed S-1-5-32-545 as %s\n",
13153                        dom_sid_str_buf(&sid, &buf));
13154                 return false;
13155         }
13156         return true;
13157 }
13158
13159 static bool sid_to_string_test(const char *expected) {
13160         char *str;
13161         bool res = true;
13162         struct dom_sid sid;
13163
13164         if (!string_to_sid(&sid, expected)) {
13165                 printf("could not parse %s\n", expected);
13166                 return false;
13167         }
13168
13169         str = dom_sid_string(NULL, &sid);
13170         if (strcmp(str, expected)) {
13171                 printf("Comparison failed (%s != %s)\n", str, expected);
13172                 res = false;
13173         }
13174         TALLOC_FREE(str);
13175         return res;
13176 }
13177
13178 static bool run_local_sid_to_string(int dummy) {
13179         if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13180                 return false;
13181         if (!sid_to_string_test("S-1-545"))
13182                 return false;
13183         if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13184                 return false;
13185         return true;
13186 }
13187
13188 static bool run_local_binary_to_sid(int dummy) {
13189         ssize_t ret;
13190         struct dom_sid *sid = talloc(NULL, struct dom_sid);
13191         static const uint8_t good_binary_sid[] = {
13192                 0x1, /* revision number */
13193                 15, /* num auths */
13194                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13195                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13196                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13197                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13198                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13199                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13200                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13201                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13202                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13203                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13204                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13205                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13206                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13207                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13208                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13209                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13210         };
13211
13212         static const uint8_t long_binary_sid[] = {
13213                 0x1, /* revision number */
13214                 15, /* num auths */
13215                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13216                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13217                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13218                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13219                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13220                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13221                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13222                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13223                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13224                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13225                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13226                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13227                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13228                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13229                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13230                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13231                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13232                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13233                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13234         };
13235
13236         static const uint8_t long_binary_sid2[] = {
13237                 0x1, /* revision number */
13238                 32, /* num auths */
13239                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13240                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13241                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13242                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13243                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13244                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13245                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13246                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13247                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13248                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13249                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13250                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13251                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13252                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13253                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13254                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13255                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13256                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13257                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13258                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13259                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13260                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13261                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13262                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13263                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13264                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13265                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13266                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13267                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13268                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13269                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13270                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13271                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13272         };
13273
13274         ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13275         if (ret == -1) {
13276                 return false;
13277         }
13278         ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13279         if (ret != -1) {
13280                 return false;
13281         }
13282         ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13283         if (ret != -1) {
13284                 return false;
13285         }
13286         return true;
13287 }
13288
13289 /* Split a path name into filename and stream name components. Canonicalise
13290  * such that an implicit $DATA token is always explicit.
13291  *
13292  * The "specification" of this function can be found in the
13293  * run_local_stream_name() function in torture.c, I've tried those
13294  * combinations against a W2k3 server.
13295  */
13296
13297 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13298                                        char **pbase, char **pstream)
13299 {
13300         char *base = NULL;
13301         char *stream = NULL;
13302         char *sname; /* stream name */
13303         const char *stype; /* stream type */
13304
13305         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13306
13307         sname = strchr_m(fname, ':');
13308
13309         if (sname == NULL) {
13310                 if (pbase != NULL) {
13311                         base = talloc_strdup(mem_ctx, fname);
13312                         NT_STATUS_HAVE_NO_MEMORY(base);
13313                 }
13314                 goto done;
13315         }
13316
13317         if (pbase != NULL) {
13318                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13319                 NT_STATUS_HAVE_NO_MEMORY(base);
13320         }
13321
13322         sname += 1;
13323
13324         stype = strchr_m(sname, ':');
13325
13326         if (stype == NULL) {
13327                 sname = talloc_strdup(mem_ctx, sname);
13328                 stype = "$DATA";
13329         }
13330         else {
13331                 if (strcasecmp_m(stype, ":$DATA") != 0) {
13332                         /*
13333                          * If there is an explicit stream type, so far we only
13334                          * allow $DATA. Is there anything else allowed? -- vl
13335                          */
13336                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13337                         TALLOC_FREE(base);
13338                         return NT_STATUS_OBJECT_NAME_INVALID;
13339                 }
13340                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13341                 stype += 1;
13342         }
13343
13344         if (sname == NULL) {
13345                 TALLOC_FREE(base);
13346                 return NT_STATUS_NO_MEMORY;
13347         }
13348
13349         if (sname[0] == '\0') {
13350                 /*
13351                  * no stream name, so no stream
13352                  */
13353                 goto done;
13354         }
13355
13356         if (pstream != NULL) {
13357                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13358                 if (stream == NULL) {
13359                         TALLOC_FREE(sname);
13360                         TALLOC_FREE(base);
13361                         return NT_STATUS_NO_MEMORY;
13362                 }
13363                 /*
13364                  * upper-case the type field
13365                  */
13366                 (void)strupper_m(strchr_m(stream, ':')+1);
13367         }
13368
13369  done:
13370         if (pbase != NULL) {
13371                 *pbase = base;
13372         }
13373         if (pstream != NULL) {
13374                 *pstream = stream;
13375         }
13376         return NT_STATUS_OK;
13377 }
13378
13379 static bool test_stream_name(const char *fname, const char *expected_base,
13380                              const char *expected_stream,
13381                              NTSTATUS expected_status)
13382 {
13383         NTSTATUS status;
13384         char *base = NULL;
13385         char *stream = NULL;
13386
13387         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13388         if (!NT_STATUS_EQUAL(status, expected_status)) {
13389                 goto error;
13390         }
13391
13392         if (!NT_STATUS_IS_OK(status)) {
13393                 return true;
13394         }
13395
13396         if (base == NULL) goto error;
13397
13398         if (strcmp(expected_base, base) != 0) goto error;
13399
13400         if ((expected_stream != NULL) && (stream == NULL)) goto error;
13401         if ((expected_stream == NULL) && (stream != NULL)) goto error;
13402
13403         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
13404                 goto error;
13405
13406         TALLOC_FREE(base);
13407         TALLOC_FREE(stream);
13408         return true;
13409
13410  error:
13411         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
13412                   fname, expected_base ? expected_base : "<NULL>",
13413                   expected_stream ? expected_stream : "<NULL>",
13414                   nt_errstr(expected_status));
13415         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
13416                   base ? base : "<NULL>", stream ? stream : "<NULL>",
13417                   nt_errstr(status));
13418         TALLOC_FREE(base);
13419         TALLOC_FREE(stream);
13420         return false;
13421 }
13422
13423 static bool run_local_stream_name(int dummy)
13424 {
13425         bool ret = true;
13426
13427         ret &= test_stream_name(
13428                 "bla", "bla", NULL, NT_STATUS_OK);
13429         ret &= test_stream_name(
13430                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
13431         ret &= test_stream_name(
13432                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13433         ret &= test_stream_name(
13434                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
13435         ret &= test_stream_name(
13436                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13437         ret &= test_stream_name(
13438                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
13439         ret &= test_stream_name(
13440                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
13441         ret &= test_stream_name(
13442                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
13443
13444         return ret;
13445 }
13446
13447 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
13448 {
13449         if (a.length != b.length) {
13450                 printf("a.length=%d != b.length=%d\n",
13451                        (int)a.length, (int)b.length);
13452                 return false;
13453         }
13454         if (memcmp(a.data, b.data, a.length) != 0) {
13455                 printf("a.data and b.data differ\n");
13456                 return false;
13457         }
13458         return true;
13459 }
13460
13461 static bool run_local_memcache(int dummy)
13462 {
13463         struct memcache *cache;
13464         DATA_BLOB k1, k2, k3, k4, k5;
13465         DATA_BLOB d1, d3;
13466         DATA_BLOB v1, v3;
13467
13468         TALLOC_CTX *mem_ctx;
13469         char *ptr1 = NULL;
13470         char *ptr2 = NULL;
13471         char *ptr3 = NULL;
13472
13473         char *str1, *str2;
13474         size_t size1, size2;
13475         bool ret = false;
13476
13477         mem_ctx = talloc_init("foo");
13478         if (mem_ctx == NULL) {
13479                 return false;
13480         }
13481
13482         /* STAT_CACHE TESTS */
13483
13484         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13485
13486         if (cache == NULL) {
13487                 printf("memcache_init failed\n");
13488                 return false;
13489         }
13490
13491         d1 = data_blob_const("d1", 2);
13492         d3 = data_blob_const("d3", 2);
13493
13494         k1 = data_blob_const("d1", 2);
13495         k2 = data_blob_const("d2", 2);
13496         k3 = data_blob_const("d3", 2);
13497         k4 = data_blob_const("d4", 2);
13498         k5 = data_blob_const("d5", 2);
13499
13500         memcache_add(cache, STAT_CACHE, k1, d1);
13501
13502         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
13503                 printf("could not find k1\n");
13504                 return false;
13505         }
13506         if (!data_blob_equal(d1, v1)) {
13507                 return false;
13508         }
13509
13510         memcache_add(cache, STAT_CACHE, k1, d3);
13511
13512         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
13513                 printf("could not find replaced k1\n");
13514                 return false;
13515         }
13516         if (!data_blob_equal(d3, v3)) {
13517                 return false;
13518         }
13519
13520         TALLOC_FREE(cache);
13521
13522         /* GETWD_CACHE TESTS */
13523         str1 = talloc_strdup(mem_ctx, "string1");
13524         if (str1 == NULL) {
13525                 return false;
13526         }
13527         ptr2 = str1; /* Keep an alias for comparison. */
13528
13529         str2 = talloc_strdup(mem_ctx, "string2");
13530         if (str2 == NULL) {
13531                 return false;
13532         }
13533
13534         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13535         if (cache == NULL) {
13536                 printf("memcache_init failed\n");
13537                 return false;
13538         }
13539
13540         memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
13541         /* str1 == NULL now. */
13542         ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
13543         if (ptr1 == NULL) {
13544                 printf("could not find k2\n");
13545                 return false;
13546         }
13547         if (ptr1 != ptr2) {
13548                 printf("fetch of k2 got wrong string\n");
13549                 return false;
13550         }
13551
13552         /* Add a blob to ensure k2 gets purged. */
13553         d3 = data_blob_talloc_zero(mem_ctx, 180);
13554         memcache_add(cache, STAT_CACHE, k3, d3);
13555
13556         ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
13557         if (ptr2 != NULL) {
13558                 printf("Did find k2, should have been purged\n");
13559                 return false;
13560         }
13561
13562         /*
13563          * Test that talloc size also is accounted in memcache and
13564          * causes purge of other object.
13565          */
13566
13567         str1 = talloc_zero_size(mem_ctx, 100);
13568         str2 = talloc_zero_size(mem_ctx, 100);
13569
13570         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13571         memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
13572
13573         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
13574         if (ptr3 != NULL) {
13575                 printf("Did find k4, should have been purged\n");
13576                 return false;
13577         }
13578
13579         /*
13580          * Test that adding a duplicate non-talloced
13581          * key/value on top of a talloced key/value takes account
13582          * of the talloc_freed value size.
13583          */
13584         TALLOC_FREE(cache);
13585         TALLOC_FREE(mem_ctx);
13586
13587         mem_ctx = talloc_init("key_replace");
13588         if (mem_ctx == NULL) {
13589                 return false;
13590         }
13591
13592         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13593         if (cache == NULL) {
13594                 return false;
13595         }
13596
13597         /*
13598          * Add a 100 byte talloced string. This will
13599          * store a (4 or 8 byte) pointer and record the
13600          * total talloced size.
13601          */
13602         str1 = talloc_zero_size(mem_ctx, 100);
13603         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13604         /*
13605          * Now overwrite with a small talloced
13606          * value. This should fit in the existing size
13607          * and the total talloced size should be removed
13608          * from the cache size.
13609          */
13610         str1 = talloc_zero_size(mem_ctx, 2);
13611         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13612         /*
13613          * Now store a 20 byte string. If the
13614          * total talloced size wasn't accounted for
13615          * and removed in the overwrite, then this
13616          * will evict k4.
13617          */
13618         str2 = talloc_zero_size(mem_ctx, 20);
13619         memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
13620
13621         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
13622         if (ptr3 == NULL) {
13623                 printf("Did not find k4, should not have been purged\n");
13624                 return false;
13625         }
13626
13627         TALLOC_FREE(cache);
13628         TALLOC_FREE(mem_ctx);
13629
13630         mem_ctx = talloc_init("foo");
13631         if (mem_ctx == NULL) {
13632                 return false;
13633         }
13634
13635         cache = memcache_init(NULL, 0);
13636         if (cache == NULL) {
13637                 return false;
13638         }
13639
13640         str1 = talloc_strdup(mem_ctx, "string1");
13641         if (str1 == NULL) {
13642                 return false;
13643         }
13644         str2 = talloc_strdup(mem_ctx, "string2");
13645         if (str2 == NULL) {
13646                 return false;
13647         }
13648         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
13649                             data_blob_string_const("torture"), &str1);
13650         size1 = talloc_total_size(cache);
13651
13652         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
13653                             data_blob_string_const("torture"), &str2);
13654         size2 = talloc_total_size(cache);
13655
13656         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
13657
13658         if (size2 > size1) {
13659                 printf("memcache leaks memory!\n");
13660                 goto fail;
13661         }
13662
13663         ret = true;
13664  fail:
13665         TALLOC_FREE(cache);
13666         return ret;
13667 }
13668
13669 static void wbclient_done(struct tevent_req *req)
13670 {
13671         wbcErr wbc_err;
13672         struct winbindd_response *wb_resp;
13673         int *i = (int *)tevent_req_callback_data_void(req);
13674
13675         wbc_err = wb_trans_recv(req, req, &wb_resp);
13676         TALLOC_FREE(req);
13677         *i += 1;
13678         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
13679 }
13680
13681 static bool run_wbclient_multi_ping(int dummy)
13682 {
13683         struct tevent_context *ev;
13684         struct wb_context **wb_ctx;
13685         struct winbindd_request wb_req;
13686         bool result = false;
13687         int i, j;
13688
13689         BlockSignals(True, SIGPIPE);
13690
13691         ev = tevent_context_init(talloc_tos());
13692         if (ev == NULL) {
13693                 goto fail;
13694         }
13695
13696         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
13697         if (wb_ctx == NULL) {
13698                 goto fail;
13699         }
13700
13701         ZERO_STRUCT(wb_req);
13702         wb_req.cmd = WINBINDD_PING;
13703
13704         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
13705
13706         for (i=0; i<torture_nprocs; i++) {
13707                 wb_ctx[i] = wb_context_init(ev, NULL);
13708                 if (wb_ctx[i] == NULL) {
13709                         goto fail;
13710                 }
13711                 for (j=0; j<torture_numops; j++) {
13712                         struct tevent_req *req;
13713                         req = wb_trans_send(ev, ev, wb_ctx[i],
13714                                             (j % 2) == 0, &wb_req);
13715                         if (req == NULL) {
13716                                 goto fail;
13717                         }
13718                         tevent_req_set_callback(req, wbclient_done, &i);
13719                 }
13720         }
13721
13722         i = 0;
13723
13724         while (i < torture_nprocs * torture_numops) {
13725                 tevent_loop_once(ev);
13726         }
13727
13728         result = true;
13729  fail:
13730         TALLOC_FREE(ev);
13731         return result;
13732 }
13733
13734 static bool dbtrans_inc(struct db_context *db)
13735 {
13736         struct db_record *rec;
13737         uint32_t val;
13738         bool ret = false;
13739         NTSTATUS status;
13740         TDB_DATA value;
13741
13742         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
13743         if (rec == NULL) {
13744                 printf(__location__ "fetch_lock failed\n");
13745                 return false;
13746         }
13747
13748         value = dbwrap_record_get_value(rec);
13749
13750         if (value.dsize != sizeof(uint32_t)) {
13751                 printf(__location__ "value.dsize = %d\n",
13752                        (int)value.dsize);
13753                 goto fail;
13754         }
13755
13756         memcpy(&val, value.dptr, sizeof(val));
13757         val += 1;
13758
13759         status = dbwrap_record_store(
13760                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
13761         if (!NT_STATUS_IS_OK(status)) {
13762                 printf(__location__ "store failed: %s\n",
13763                        nt_errstr(status));
13764                 goto fail;
13765         }
13766
13767         ret = true;
13768 fail:
13769         TALLOC_FREE(rec);
13770         return ret;
13771 }
13772
13773 static bool run_local_dbtrans(int dummy)
13774 {
13775         struct db_context *db;
13776         struct db_record *rec;
13777         NTSTATUS status;
13778         uint32_t initial;
13779         int res;
13780         TDB_DATA value;
13781
13782         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
13783                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
13784                      DBWRAP_FLAG_NONE);
13785         if (db == NULL) {
13786                 printf("Could not open transtest.db\n");
13787                 return false;
13788         }
13789
13790         res = dbwrap_transaction_start(db);
13791         if (res != 0) {
13792                 printf(__location__ "transaction_start failed\n");
13793                 return false;
13794         }
13795
13796         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
13797         if (rec == NULL) {
13798                 printf(__location__ "fetch_lock failed\n");
13799                 return false;
13800         }
13801
13802         value = dbwrap_record_get_value(rec);
13803
13804         if (value.dptr == NULL) {
13805                 initial = 0;
13806                 status = dbwrap_record_store(
13807                         rec, make_tdb_data((uint8_t *)&initial,
13808                                            sizeof(initial)),
13809                         0);
13810                 if (!NT_STATUS_IS_OK(status)) {
13811                         printf(__location__ "store returned %s\n",
13812                                nt_errstr(status));
13813                         return false;
13814                 }
13815         }
13816
13817         TALLOC_FREE(rec);
13818
13819         res = dbwrap_transaction_commit(db);
13820         if (res != 0) {
13821                 printf(__location__ "transaction_commit failed\n");
13822                 return false;
13823         }
13824
13825         while (true) {
13826                 uint32_t val, val2;
13827                 int i;
13828
13829                 res = dbwrap_transaction_start(db);
13830                 if (res != 0) {
13831                         printf(__location__ "transaction_start failed\n");
13832                         break;
13833                 }
13834
13835                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
13836                 if (!NT_STATUS_IS_OK(status)) {
13837                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
13838                                nt_errstr(status));
13839                         break;
13840                 }
13841
13842                 for (i=0; i<10; i++) {
13843                         if (!dbtrans_inc(db)) {
13844                                 return false;
13845                         }
13846                 }
13847
13848                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
13849                 if (!NT_STATUS_IS_OK(status)) {
13850                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
13851                                nt_errstr(status));
13852                         break;
13853                 }
13854
13855                 if (val2 != val + 10) {
13856                         printf(__location__ "val=%d, val2=%d\n",
13857                                (int)val, (int)val2);
13858                         break;
13859                 }
13860
13861                 printf("val2=%d\r", val2);
13862
13863                 res = dbwrap_transaction_commit(db);
13864                 if (res != 0) {
13865                         printf(__location__ "transaction_commit failed\n");
13866                         break;
13867                 }
13868         }
13869
13870         TALLOC_FREE(db);
13871         return true;
13872 }
13873
13874 /*
13875  * Just a dummy test to be run under a debugger. There's no real way
13876  * to inspect the tevent_poll specific function from outside of
13877  * tevent_poll.c.
13878  */
13879
13880 static bool run_local_tevent_poll(int dummy)
13881 {
13882         struct tevent_context *ev;
13883         struct tevent_fd *fd1, *fd2;
13884         bool result = false;
13885
13886         ev = tevent_context_init_byname(NULL, "poll");
13887         if (ev == NULL) {
13888                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
13889                 goto fail;
13890         }
13891
13892         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
13893         if (fd1 == NULL) {
13894                 d_fprintf(stderr, "tevent_add_fd failed\n");
13895                 goto fail;
13896         }
13897         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
13898         if (fd2 == NULL) {
13899                 d_fprintf(stderr, "tevent_add_fd failed\n");
13900                 goto fail;
13901         }
13902         TALLOC_FREE(fd2);
13903
13904         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
13905         if (fd2 == NULL) {
13906                 d_fprintf(stderr, "tevent_add_fd failed\n");
13907                 goto fail;
13908         }
13909
13910         result = true;
13911 fail:
13912         TALLOC_FREE(ev);
13913         return result;
13914 }
13915
13916 static bool run_local_hex_encode_buf(int dummy)
13917 {
13918         char buf[17];
13919         uint8_t src[8];
13920         int i;
13921
13922         for (i=0; i<sizeof(src); i++) {
13923                 src[i] = i;
13924         }
13925         hex_encode_buf(buf, src, sizeof(src));
13926         if (strcmp(buf, "0001020304050607") != 0) {
13927                 return false;
13928         }
13929         hex_encode_buf(buf, NULL, 0);
13930         if (buf[0] != '\0') {
13931                 return false;
13932         }
13933         return true;
13934 }
13935
13936 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
13937         "0.0.0.0",
13938         "::0",
13939         "1.2.3.1",
13940         "0.0.0.0",
13941         "0.0.0.0",
13942         "1.2.3.2",
13943         "1.2.3.3",
13944         "1.2.3.4",
13945         "1.2.3.5",
13946         "::0",
13947         "1.2.3.6",
13948         "1.2.3.7",
13949         "::0",
13950         "::0",
13951         "::0",
13952         "1.2.3.8",
13953         "1.2.3.9",
13954         "1.2.3.10",
13955         "1.2.3.11",
13956         "1.2.3.12",
13957         "1.2.3.13",
13958         "1001:1111:1111:1000:0:1111:1111:1111",
13959         "1.2.3.1",
13960         "1.2.3.2",
13961         "1.2.3.3",
13962         "1.2.3.12",
13963         "::0",
13964         "::0"
13965 };
13966
13967 static const char *remove_duplicate_addrs2_test_strings_result[] = {
13968         "1.2.3.1",
13969         "1.2.3.2",
13970         "1.2.3.3",
13971         "1.2.3.4",
13972         "1.2.3.5",
13973         "1.2.3.6",
13974         "1.2.3.7",
13975         "1.2.3.8",
13976         "1.2.3.9",
13977         "1.2.3.10",
13978         "1.2.3.11",
13979         "1.2.3.12",
13980         "1.2.3.13",
13981         "1001:1111:1111:1000:0:1111:1111:1111"
13982 };
13983
13984 static bool run_local_remove_duplicate_addrs2(int dummy)
13985 {
13986         struct ip_service test_vector[28];
13987         int count, i;
13988
13989         /* Construct the sockaddr_storage test vector. */
13990         for (i = 0; i < 28; i++) {
13991                 struct addrinfo hints;
13992                 struct addrinfo *res = NULL;
13993                 int ret;
13994
13995                 memset(&hints, '\0', sizeof(hints));
13996                 hints.ai_flags = AI_NUMERICHOST;
13997                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
13998                                 NULL,
13999                                 &hints,
14000                                 &res);
14001                 if (ret) {
14002                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
14003                                 remove_duplicate_addrs2_test_strings_vector[i]);
14004                         return false;
14005                 }
14006                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14007                 memcpy(&test_vector[i].ss,
14008                         res->ai_addr,
14009                         res->ai_addrlen);
14010                 freeaddrinfo(res);
14011         }
14012
14013         count = remove_duplicate_addrs2(test_vector, i);
14014
14015         if (count != 14) {
14016                 fprintf(stderr, "count wrong (%d) should be 14\n",
14017                         count);
14018                 return false;
14019         }
14020
14021         for (i = 0; i < count; i++) {
14022                 char addr[INET6_ADDRSTRLEN];
14023
14024                 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
14025
14026                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14027                         fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
14028                                 i,
14029                                 addr,
14030                                 remove_duplicate_addrs2_test_strings_result[i]);
14031                         return false;
14032                 }
14033         }
14034
14035         printf("run_local_remove_duplicate_addrs2: success\n");
14036         return true;
14037 }
14038
14039 static bool run_local_tdb_opener(int dummy)
14040 {
14041         TDB_CONTEXT *t;
14042         unsigned v = 0;
14043
14044         while (1) {
14045                 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14046                              O_RDWR|O_CREAT, 0755);
14047                 if (t == NULL) {
14048                         perror("tdb_open failed");
14049                         return false;
14050                 }
14051                 tdb_close(t);
14052
14053                 v += 1;
14054                 printf("\r%u", v);
14055         }
14056         return true;
14057 }
14058
14059 static bool run_local_tdb_writer(int dummy)
14060 {
14061         TDB_CONTEXT *t;
14062         unsigned v = 0;
14063         TDB_DATA val;
14064
14065         t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14066         if (t == 0) {
14067                 perror("tdb_open failed");
14068                 return 1;
14069         }
14070
14071         val.dptr = (uint8_t *)&v;
14072         val.dsize = sizeof(v);
14073
14074         while (1) {
14075                 TDB_DATA data;
14076                 int ret;
14077
14078                 ret = tdb_store(t, val, val, 0);
14079                 if (ret != 0) {
14080                         printf("%s\n", tdb_errorstr(t));
14081                 }
14082                 v += 1;
14083                 printf("\r%u", v);
14084
14085                 data = tdb_fetch(t, val);
14086                 if (data.dptr != NULL) {
14087                         SAFE_FREE(data.dptr);
14088                 }
14089         }
14090         return true;
14091 }
14092
14093 static bool run_local_canonicalize_path(int dummy)
14094 {
14095         const char *src[] = {
14096                         "/foo/..",
14097                         "/..",
14098                         "/foo/bar/../baz",
14099                         "/foo/././",
14100                         "/../foo",
14101                         ".././././",
14102                         ".././././../../../boo",
14103                         "./..",
14104                         "/",
14105                         "/../../",
14106                         "/foo/../",
14107                         "/./././",
14108                         "/./././.",
14109                         "/.../././.",
14110                         "/./././.foo",
14111                         "/./././.foo.",
14112                         "/./././foo.",
14113                         "/foo/bar/..",
14114                         "/foo/bar/../baz/",
14115                         "////////////////",
14116                         "/////////./././././.",
14117                         "/./.././../.boo/../baz",
14118                         "/a/component/path",
14119                         "/a/component/path/",
14120                         "/a/component/path/..",
14121                         "/a/component/../path/",
14122                         "///a/./././///component/../////path/",
14123                         NULL
14124                         };
14125         const char *dst[] = {
14126                         "/",
14127                         "/",
14128                         "/foo/baz",
14129                         "/foo",
14130                         "/foo",
14131                         "/",
14132                         "/boo",
14133                         "/",
14134                         "/",
14135                         "/",
14136                         "/",
14137                         "/",
14138                         "/",
14139                         "/...",
14140                         "/.foo",
14141                         "/.foo.",
14142                         "/foo.",
14143                         "/foo",
14144                         "/foo/baz",
14145                         "/",
14146                         "/",
14147                         "/baz",
14148                         "/a/component/path",
14149                         "/a/component/path",
14150                         "/a/component",
14151                         "/a/path",
14152                         "/a/path",
14153                         NULL
14154                         };
14155         unsigned int i;
14156
14157         for (i = 0; src[i] != NULL; i++) {
14158                 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14159                 if (d == NULL) {
14160                         perror("talloc fail\n");
14161                         return false;
14162                 }
14163                 if (strcmp(d, dst[i]) != 0) {
14164                         d_fprintf(stderr,
14165                                 "canonicalize mismatch %s -> %s != %s",
14166                                 src[i], d, dst[i]);
14167                         return false;
14168                 }
14169                 talloc_free(d);
14170         }
14171         return true;
14172 }
14173
14174 static bool run_ign_bad_negprot(int dummy)
14175 {
14176         struct tevent_context *ev;
14177         struct tevent_req *req;
14178         struct smbXcli_conn *conn;
14179         struct sockaddr_storage ss;
14180         NTSTATUS status;
14181         int fd;
14182         bool ok;
14183
14184         printf("starting ignore bad negprot\n");
14185
14186         ok = resolve_name(host, &ss, 0x20, true);
14187         if (!ok) {
14188                 d_fprintf(stderr, "Could not resolve name %s\n", host);
14189                 return false;
14190         }
14191
14192         status = open_socket_out(&ss, 445, 10000, &fd);
14193         if (!NT_STATUS_IS_OK(status)) {
14194                 d_fprintf(stderr, "open_socket_out failed: %s\n",
14195                           nt_errstr(status));
14196                 return false;
14197         }
14198
14199         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14200                                    NULL, 0);
14201         if (conn == NULL) {
14202                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14203                 return false;
14204         }
14205
14206         status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
14207         if (NT_STATUS_IS_OK(status)) {
14208                 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
14209                 return false;
14210         }
14211
14212         ev = samba_tevent_context_init(talloc_tos());
14213         if (ev == NULL) {
14214                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14215                 return false;
14216         }
14217
14218         req = smb1cli_session_setup_nt1_send(
14219                 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
14220                 data_blob_null, data_blob_null, 0x40,
14221                 "Windows 2000 2195", "Windows 2000 5.0");
14222         if (req == NULL) {
14223                 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
14224                 return false;
14225         }
14226
14227         ok = tevent_req_poll_ntstatus(req, ev, &status);
14228         if (!ok) {
14229                 d_fprintf(stderr, "tevent_req_poll failed\n");
14230                 return false;
14231         }
14232
14233         status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
14234                                                 NULL, NULL);
14235         if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
14236                 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
14237                           "%s, expected NT_STATUS_CONNECTION_RESET\n",
14238                           nt_errstr(status));
14239                 return false;
14240         }
14241
14242         TALLOC_FREE(conn);
14243
14244         printf("starting ignore bad negprot\n");
14245
14246         return true;
14247 }
14248
14249 static double create_procs(bool (*fn)(int), bool *result)
14250 {
14251         int i, status;
14252         volatile pid_t *child_status;
14253         volatile bool *child_status_out;
14254         int synccount;
14255         int tries = 8;
14256         struct timeval start;
14257
14258         synccount = 0;
14259
14260         child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
14261         if (!child_status) {
14262                 printf("Failed to setup shared memory\n");
14263                 return -1;
14264         }
14265
14266         child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
14267         if (!child_status_out) {
14268                 printf("Failed to setup result status shared memory\n");
14269                 return -1;
14270         }
14271
14272         for (i = 0; i < torture_nprocs; i++) {
14273                 child_status[i] = 0;
14274                 child_status_out[i] = True;
14275         }
14276
14277         start = timeval_current();
14278
14279         for (i=0;i<torture_nprocs;i++) {
14280                 procnum = i;
14281                 if (fork() == 0) {
14282                         pid_t mypid = getpid();
14283                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
14284
14285                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
14286
14287                         while (1) {
14288                                 if (torture_open_connection(&current_cli, i)) break;
14289                                 if (tries-- == 0) {
14290                                         printf("pid %d failed to start\n", (int)getpid());
14291                                         _exit(1);
14292                                 }
14293                                 smb_msleep(10); 
14294                         }
14295
14296                         child_status[i] = getpid();
14297
14298                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
14299
14300                         child_status_out[i] = fn(i);
14301                         _exit(0);
14302                 }
14303         }
14304
14305         do {
14306                 synccount = 0;
14307                 for (i=0;i<torture_nprocs;i++) {
14308                         if (child_status[i]) synccount++;
14309                 }
14310                 if (synccount == torture_nprocs) break;
14311                 smb_msleep(10);
14312         } while (timeval_elapsed(&start) < 30);
14313
14314         if (synccount != torture_nprocs) {
14315                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
14316                 *result = False;
14317                 return timeval_elapsed(&start);
14318         }
14319
14320         /* start the client load */
14321         start = timeval_current();
14322
14323         for (i=0;i<torture_nprocs;i++) {
14324                 child_status[i] = 0;
14325         }
14326
14327         printf("%d clients started\n", torture_nprocs);
14328
14329         for (i=0;i<torture_nprocs;i++) {
14330                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
14331         }
14332
14333         printf("\n");
14334
14335         for (i=0;i<torture_nprocs;i++) {
14336                 if (!child_status_out[i]) {
14337                         *result = False;
14338                 }
14339         }
14340         return timeval_elapsed(&start);
14341 }
14342
14343 #define FLAG_MULTIPROC 1
14344
14345 static struct {
14346         const char *name;
14347         bool (*fn)(int);
14348         unsigned flags;
14349 } torture_ops[] = {
14350         {
14351                 .name = "FDPASS",
14352                 .fn   = run_fdpasstest,
14353         },
14354         {
14355                 .name = "LOCK1",
14356                 .fn   = run_locktest1,
14357         },
14358         {
14359                 .name = "LOCK2",
14360                 .fn   =  run_locktest2,
14361         },
14362         {
14363                 .name = "LOCK3",
14364                 .fn   =  run_locktest3,
14365         },
14366         {
14367                 .name = "LOCK4",
14368                 .fn   =  run_locktest4,
14369         },
14370         {
14371                 .name = "LOCK5",
14372                 .fn   =  run_locktest5,
14373         },
14374         {
14375                 .name = "LOCK6",
14376                 .fn   =  run_locktest6,
14377         },
14378         {
14379                 .name = "LOCK7",
14380                 .fn   =  run_locktest7,
14381         },
14382         {
14383                 .name = "LOCK8",
14384                 .fn   =  run_locktest8,
14385         },
14386         {
14387                 .name = "LOCK9A",
14388                 .fn   =  run_locktest9a,
14389         },
14390         {
14391                 .name = "LOCK9B",
14392                 .fn   =  run_locktest9b,
14393         },
14394         {
14395                 .name = "LOCK10",
14396                 .fn   =  run_locktest10,
14397         },
14398         {
14399                 .name = "LOCK11",
14400                 .fn   =  run_locktest11,
14401         },
14402         {
14403                 .name = "LOCK12",
14404                 .fn   =  run_locktest12,
14405         },
14406         {
14407                 .name = "LOCK13",
14408                 .fn   =  run_locktest13,
14409         },
14410         {
14411                 .name = "UNLINK",
14412                 .fn   = run_unlinktest,
14413         },
14414         {
14415                 .name = "BROWSE",
14416                 .fn   = run_browsetest,
14417         },
14418         {
14419                 .name = "ATTR",
14420                 .fn   =   run_attrtest,
14421         },
14422         {
14423                 .name = "TRANS2",
14424                 .fn   = run_trans2test,
14425         },
14426         {
14427                 .name  = "MAXFID",
14428                 .fn    = run_maxfidtest,
14429                 .flags = FLAG_MULTIPROC,
14430         },
14431         {
14432                 .name  = "TORTURE",
14433                 .fn    = run_torture,
14434                 .flags = FLAG_MULTIPROC,
14435         },
14436         {
14437                 .name  = "RANDOMIPC",
14438                 .fn    = run_randomipc,
14439         },
14440         {
14441                 .name  = "NEGNOWAIT",
14442                 .fn    = run_negprot_nowait,
14443         },
14444         {
14445                 .name  = "NBENCH",
14446                 .fn    =  run_nbench,
14447         },
14448         {
14449                 .name  = "NBENCH2",
14450                 .fn    = run_nbench2,
14451         },
14452         {
14453                 .name  = "OPLOCK1",
14454                 .fn    =  run_oplock1,
14455         },
14456         {
14457                 .name  = "OPLOCK2",
14458                 .fn    =  run_oplock2,
14459         },
14460         {
14461                 .name  = "OPLOCK4",
14462                 .fn    =  run_oplock4,
14463         },
14464 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
14465         {
14466                 .name  = "OPLOCK5",
14467                 .fn    =  run_oplock5,
14468         },
14469 #endif
14470         {
14471                 .name  = "DIR",
14472                 .fn    =  run_dirtest,
14473         },
14474         {
14475                 .name  = "DIR1",
14476                 .fn    =  run_dirtest1,
14477         },
14478         {
14479                 .name  = "DIR-CREATETIME",
14480                 .fn    =  run_dir_createtime,
14481         },
14482         {
14483                 .name  = "DENY1",
14484                 .fn    =  torture_denytest1,
14485         },
14486         {
14487                 .name  = "DENY2",
14488                 .fn    =  torture_denytest2,
14489         },
14490         {
14491                 .name  = "TCON",
14492                 .fn    =  run_tcon_test,
14493         },
14494         {
14495                 .name  = "TCONDEV",
14496                 .fn    =  run_tcon_devtype_test,
14497         },
14498         {
14499                 .name  = "RW1",
14500                 .fn    =  run_readwritetest,
14501         },
14502         {
14503                 .name  = "RW2",
14504                 .fn    =  run_readwritemulti,
14505                 .flags = FLAG_MULTIPROC
14506         },
14507         {
14508                 .name  = "RW3",
14509                 .fn    =  run_readwritelarge,
14510         },
14511         {
14512                 .name  = "RW-SIGNING",
14513                 .fn    =  run_readwritelarge_signtest,
14514         },
14515         {
14516                 .name  = "OPEN",
14517                 .fn    = run_opentest,
14518         },
14519         {
14520                 .name  = "POSIX",
14521                 .fn    = run_simple_posix_open_test,
14522         },
14523         {
14524                 .name  = "POSIX-APPEND",
14525                 .fn    = run_posix_append,
14526         },
14527         {
14528                 .name  = "POSIX-SYMLINK-ACL",
14529                 .fn    = run_acl_symlink_test,
14530         },
14531         {
14532                 .name  = "POSIX-SYMLINK-EA",
14533                 .fn    = run_ea_symlink_test,
14534         },
14535         {
14536                 .name  = "POSIX-STREAM-DELETE",
14537                 .fn    = run_posix_stream_delete,
14538         },
14539         {
14540                 .name  = "POSIX-OFD-LOCK",
14541                 .fn    = run_posix_ofd_lock_test,
14542         },
14543         {
14544                 .name  = "POSIX-BLOCKING-LOCK",
14545                 .fn    = run_posix_blocking_lock,
14546         },
14547         {
14548                 .name  = "POSIX-MKDIR",
14549                 .fn    = run_posix_mkdir_test,
14550         },
14551         {
14552                 .name  = "POSIX-ACL-OPLOCK",
14553                 .fn    = run_posix_acl_oplock_test,
14554         },
14555         {
14556                 .name  = "POSIX-ACL-SHAREROOT",
14557                 .fn    = run_posix_acl_shareroot_test,
14558         },
14559         {
14560                 .name  = "WINDOWS-BAD-SYMLINK",
14561                 .fn    = run_symlink_open_test,
14562         },
14563         {
14564                 .name  = "CASE-INSENSITIVE-CREATE",
14565                 .fn    = run_case_insensitive_create,
14566         },
14567         {
14568                 .name  = "ASYNC-ECHO",
14569                 .fn    = run_async_echo,
14570         },
14571         {
14572                 .name  = "UID-REGRESSION-TEST",
14573                 .fn    = run_uid_regression_test,
14574         },
14575         {
14576                 .name  = "SHORTNAME-TEST",
14577                 .fn    = run_shortname_test,
14578         },
14579         {
14580                 .name  = "ADDRCHANGE",
14581                 .fn    = run_addrchange,
14582         },
14583 #if 1
14584         {
14585                 .name  = "OPENATTR",
14586                 .fn    = run_openattrtest,
14587         },
14588 #endif
14589         {
14590                 .name  = "XCOPY",
14591                 .fn    = run_xcopy,
14592         },
14593         {
14594                 .name  = "RENAME",
14595                 .fn    = run_rename,
14596         },
14597         {
14598                 .name  = "RENAME-ACCESS",
14599                 .fn    = run_rename_access,
14600         },
14601         {
14602                 .name  = "OWNER-RIGHTS",
14603                 .fn    = run_owner_rights,
14604         },
14605         {
14606                 .name  = "DELETE",
14607                 .fn    = run_deletetest,
14608         },
14609         {
14610                 .name  = "DELETE-STREAM",
14611                 .fn    = run_delete_stream,
14612         },
14613         {
14614                 .name  = "DELETE-PRINT",
14615                 .fn    = run_delete_print_test,
14616         },
14617         {
14618                 .name  = "WILDDELETE",
14619                 .fn    = run_wild_deletetest,
14620         },
14621         {
14622                 .name  = "DELETE-LN",
14623                 .fn    = run_deletetest_ln,
14624         },
14625         {
14626                 .name  = "PROPERTIES",
14627                 .fn    = run_properties,
14628         },
14629         {
14630                 .name  = "MANGLE",
14631                 .fn    = torture_mangle,
14632         },
14633         {
14634                 .name  = "MANGLE1",
14635                 .fn    = run_mangle1,
14636         },
14637         {
14638                 .name  = "MANGLE-ILLEGAL",
14639                 .fn    = run_mangle_illegal,
14640         },
14641         {
14642                 .name  = "W2K",
14643                 .fn    = run_w2ktest,
14644         },
14645         {
14646                 .name  = "TRANS2SCAN",
14647                 .fn    = torture_trans2_scan,
14648         },
14649         {
14650                 .name  = "NTTRANSSCAN",
14651                 .fn    = torture_nttrans_scan,
14652         },
14653         {
14654                 .name  = "UTABLE",
14655                 .fn    = torture_utable,
14656         },
14657         {
14658                 .name  = "CASETABLE",
14659                 .fn    = torture_casetable,
14660         },
14661         {
14662                 .name  = "ERRMAPEXTRACT",
14663                 .fn    = run_error_map_extract,
14664         },
14665         {
14666                 .name  = "PIPE_NUMBER",
14667                 .fn    = run_pipe_number,
14668         },
14669         {
14670                 .name  = "TCON2",
14671                 .fn    =  run_tcon2_test,
14672         },
14673         {
14674                 .name  = "IOCTL",
14675                 .fn    =  torture_ioctl_test,
14676         },
14677         {
14678                 .name  = "CHKPATH",
14679                 .fn    =  torture_chkpath_test,
14680         },
14681         {
14682                 .name  = "FDSESS",
14683                 .fn    = run_fdsesstest,
14684         },
14685         {
14686                 .name  = "EATEST",
14687                 .fn    = run_eatest,
14688         },
14689         {
14690                 .name  = "SESSSETUP_BENCH",
14691                 .fn    = run_sesssetup_bench,
14692         },
14693         {
14694                 .name  = "CHAIN1",
14695                 .fn    = run_chain1,
14696         },
14697         {
14698                 .name  = "CHAIN2",
14699                 .fn    = run_chain2,
14700         },
14701         {
14702                 .name  = "CHAIN3",
14703                 .fn    = run_chain3,
14704         },
14705         {
14706                 .name  = "WINDOWS-WRITE",
14707                 .fn    = run_windows_write,
14708         },
14709         {
14710                 .name  = "LARGE_READX",
14711                 .fn    = run_large_readx,
14712         },
14713         {
14714                 .name  = "MSDFS-ATTRIBUTE",
14715                 .fn    = run_msdfs_attribute,
14716         },
14717         {
14718                 .name  = "NTTRANS-CREATE",
14719                 .fn    = run_nttrans_create,
14720         },
14721         {
14722                 .name  = "NTTRANS-FSCTL",
14723                 .fn    = run_nttrans_fsctl,
14724         },
14725         {
14726                 .name  = "CLI_ECHO",
14727                 .fn    = run_cli_echo,
14728         },
14729         {
14730                 .name  = "CLI_SPLICE",
14731                 .fn    = run_cli_splice,
14732         },
14733         {
14734                 .name  = "TLDAP",
14735                 .fn    = run_tldap,
14736         },
14737         {
14738                 .name  = "STREAMERROR",
14739                 .fn    = run_streamerror,
14740         },
14741         {
14742                 .name  = "NOTIFY-BENCH",
14743                 .fn    = run_notify_bench,
14744         },
14745         {
14746                 .name  = "NOTIFY-BENCH2",
14747                 .fn    = run_notify_bench2,
14748         },
14749         {
14750                 .name  = "NOTIFY-BENCH3",
14751                 .fn    = run_notify_bench3,
14752         },
14753         {
14754                 .name  = "BAD-NBT-SESSION",
14755                 .fn    = run_bad_nbt_session,
14756         },
14757         {
14758                 .name  = "IGN-BAD-NEGPROT",
14759                 .fn    = run_ign_bad_negprot,
14760         },
14761         {
14762                 .name  = "SMB-ANY-CONNECT",
14763                 .fn    = run_smb_any_connect,
14764         },
14765         {
14766                 .name  = "NOTIFY-ONLINE",
14767                 .fn    = run_notify_online,
14768         },
14769         {
14770                 .name  = "SMB2-BASIC",
14771                 .fn    = run_smb2_basic,
14772         },
14773         {
14774                 .name  = "SMB2-NEGPROT",
14775                 .fn    = run_smb2_negprot,
14776         },
14777         {
14778                 .name  = "SMB2-ANONYMOUS",
14779                 .fn    = run_smb2_anonymous,
14780         },
14781         {
14782                 .name  = "SMB2-SESSION-RECONNECT",
14783                 .fn    = run_smb2_session_reconnect,
14784         },
14785         {
14786                 .name  = "SMB2-TCON-DEPENDENCE",
14787                 .fn    = run_smb2_tcon_dependence,
14788         },
14789         {
14790                 .name  = "SMB2-MULTI-CHANNEL",
14791                 .fn    = run_smb2_multi_channel,
14792         },
14793         {
14794                 .name  = "SMB2-SESSION-REAUTH",
14795                 .fn    = run_smb2_session_reauth,
14796         },
14797         {
14798                 .name  = "SMB2-FTRUNCATE",
14799                 .fn    = run_smb2_ftruncate,
14800         },
14801         {
14802                 .name  = "SMB2-DIR-FSYNC",
14803                 .fn    = run_smb2_dir_fsync,
14804         },
14805         {
14806                 .name  = "SMB2-PATH-SLASH",
14807                 .fn    = run_smb2_path_slash,
14808         },
14809         {
14810                 .name  = "SMB1-SYSTEM-SECURITY",
14811                 .fn    = run_smb1_system_security,
14812         },
14813         {
14814                 .name  = "SMB2-SACL",
14815                 .fn    = run_smb2_sacl,
14816         },
14817         {
14818                 .name  = "SMB2-QUOTA1",
14819                 .fn    = run_smb2_quota1,
14820         },
14821         {
14822                 .name  = "CLEANUP1",
14823                 .fn    = run_cleanup1,
14824         },
14825         {
14826                 .name  = "CLEANUP2",
14827                 .fn    = run_cleanup2,
14828         },
14829         {
14830                 .name  = "CLEANUP4",
14831                 .fn    = run_cleanup4,
14832         },
14833         {
14834                 .name  = "OPLOCK-CANCEL",
14835                 .fn    = run_oplock_cancel,
14836         },
14837         {
14838                 .name  = "PIDHIGH",
14839                 .fn    = run_pidhigh,
14840         },
14841         {
14842                 .name  = "LOCAL-SUBSTITUTE",
14843                 .fn    = run_local_substitute,
14844         },
14845         {
14846                 .name  = "LOCAL-GENCACHE",
14847                 .fn    = run_local_gencache,
14848         },
14849         {
14850                 .name  = "LOCAL-DBWRAP-WATCH1",
14851                 .fn    = run_dbwrap_watch1,
14852         },
14853         {
14854                 .name  = "LOCAL-DBWRAP-WATCH2",
14855                 .fn    = run_dbwrap_watch2,
14856         },
14857         {
14858                 .name  = "LOCAL-DBWRAP-WATCH3",
14859                 .fn    = run_dbwrap_watch3,
14860         },
14861         {
14862                 .name  = "LOCAL-DBWRAP-WATCH4",
14863                 .fn    = run_dbwrap_watch4,
14864         },
14865         {
14866                 .name  = "LOCAL-DBWRAP-DO-LOCKED1",
14867                 .fn    = run_dbwrap_do_locked1,
14868         },
14869         {
14870                 .name  = "LOCAL-MESSAGING-READ1",
14871                 .fn    = run_messaging_read1,
14872         },
14873         {
14874                 .name  = "LOCAL-MESSAGING-READ2",
14875                 .fn    = run_messaging_read2,
14876         },
14877         {
14878                 .name  = "LOCAL-MESSAGING-READ3",
14879                 .fn    = run_messaging_read3,
14880         },
14881         {
14882                 .name  = "LOCAL-MESSAGING-READ4",
14883                 .fn    = run_messaging_read4,
14884         },
14885         {
14886                 .name  = "LOCAL-MESSAGING-FDPASS1",
14887                 .fn    = run_messaging_fdpass1,
14888         },
14889         {
14890                 .name  = "LOCAL-MESSAGING-FDPASS2",
14891                 .fn    = run_messaging_fdpass2,
14892         },
14893         {
14894                 .name  = "LOCAL-MESSAGING-FDPASS2a",
14895                 .fn    = run_messaging_fdpass2a,
14896         },
14897         {
14898                 .name  = "LOCAL-MESSAGING-FDPASS2b",
14899                 .fn    = run_messaging_fdpass2b,
14900         },
14901         {
14902                 .name  = "LOCAL-MESSAGING-SEND-ALL",
14903                 .fn    = run_messaging_send_all,
14904         },
14905         {
14906                 .name  = "LOCAL-BASE64",
14907                 .fn    = run_local_base64,
14908         },
14909         {
14910                 .name  = "LOCAL-RBTREE",
14911                 .fn    = run_local_rbtree,
14912         },
14913         {
14914                 .name  = "LOCAL-MEMCACHE",
14915                 .fn    = run_local_memcache,
14916         },
14917         {
14918                 .name  = "LOCAL-STREAM-NAME",
14919                 .fn    = run_local_stream_name,
14920         },
14921         {
14922                 .name  = "WBCLIENT-MULTI-PING",
14923                 .fn    = run_wbclient_multi_ping,
14924         },
14925         {
14926                 .name  = "LOCAL-string_to_sid",
14927                 .fn    = run_local_string_to_sid,
14928         },
14929         {
14930                 .name  = "LOCAL-sid_to_string",
14931                 .fn    = run_local_sid_to_string,
14932         },
14933         {
14934                 .name  = "LOCAL-binary_to_sid",
14935                 .fn    = run_local_binary_to_sid,
14936         },
14937         {
14938                 .name  = "LOCAL-DBTRANS",
14939                 .fn    = run_local_dbtrans,
14940         },
14941         {
14942                 .name  = "LOCAL-TEVENT-POLL",
14943                 .fn    = run_local_tevent_poll,
14944         },
14945         {
14946                 .name  = "LOCAL-CONVERT-STRING",
14947                 .fn    = run_local_convert_string,
14948         },
14949         {
14950                 .name  = "LOCAL-CONV-AUTH-INFO",
14951                 .fn    = run_local_conv_auth_info,
14952         },
14953         {
14954                 .name  = "LOCAL-hex_encode_buf",
14955                 .fn    = run_local_hex_encode_buf,
14956         },
14957         {
14958                 .name  = "LOCAL-IDMAP-TDB-COMMON",
14959                 .fn    = run_idmap_tdb_common_test,
14960         },
14961         {
14962                 .name  = "LOCAL-remove_duplicate_addrs2",
14963                 .fn    = run_local_remove_duplicate_addrs2,
14964         },
14965         {
14966                 .name  = "local-tdb-opener",
14967                 .fn    = run_local_tdb_opener,
14968         },
14969         {
14970                 .name  = "local-tdb-writer",
14971                 .fn    = run_local_tdb_writer,
14972         },
14973         {
14974                 .name  = "LOCAL-DBWRAP-CTDB1",
14975                 .fn    = run_local_dbwrap_ctdb1,
14976         },
14977         {
14978                 .name  = "LOCAL-BENCH-PTHREADPOOL",
14979                 .fn    = run_bench_pthreadpool,
14980         },
14981         {
14982                 .name  = "LOCAL-PTHREADPOOL-TEVENT",
14983                 .fn    = run_pthreadpool_tevent,
14984         },
14985         {
14986                 .name  = "LOCAL-G-LOCK1",
14987                 .fn    = run_g_lock1,
14988         },
14989         {
14990                 .name  = "LOCAL-G-LOCK2",
14991                 .fn    = run_g_lock2,
14992         },
14993         {
14994                 .name  = "LOCAL-G-LOCK3",
14995                 .fn    = run_g_lock3,
14996         },
14997         {
14998                 .name  = "LOCAL-G-LOCK4",
14999                 .fn    = run_g_lock4,
15000         },
15001         {
15002                 .name  = "LOCAL-G-LOCK4A",
15003                 .fn    = run_g_lock4a,
15004         },
15005         {
15006                 .name  = "LOCAL-G-LOCK5",
15007                 .fn    = run_g_lock5,
15008         },
15009         {
15010                 .name  = "LOCAL-G-LOCK6",
15011                 .fn    = run_g_lock6,
15012         },
15013         {
15014                 .name  = "LOCAL-G-LOCK7",
15015                 .fn    = run_g_lock7,
15016         },
15017         {
15018                 .name  = "LOCAL-G-LOCK8",
15019                 .fn    = run_g_lock8,
15020         },
15021         {
15022                 .name  = "LOCAL-G-LOCK-PING-PONG",
15023                 .fn    = run_g_lock_ping_pong,
15024         },
15025         {
15026                 .name  = "LOCAL-CANONICALIZE-PATH",
15027                 .fn    = run_local_canonicalize_path,
15028         },
15029         {
15030                 .name  = "LOCAL-NAMEMAP-CACHE1",
15031                 .fn    = run_local_namemap_cache1,
15032         },
15033         {
15034                 .name  = "LOCAL-IDMAP-CACHE1",
15035                 .fn    = run_local_idmap_cache1,
15036         },
15037         {
15038                 .name  = "qpathinfo-bufsize",
15039                 .fn    = run_qpathinfo_bufsize,
15040         },
15041         {
15042                 .name  = "hide-new-files-timeout",
15043                 .fn    = run_hidenewfiles,
15044         },
15045 #ifdef CLUSTER_SUPPORT
15046         {
15047                 .name  = "ctdbd-conn1",
15048                 .fn    = run_ctdbd_conn1,
15049         },
15050 #endif
15051         {
15052                 .name  = "readdir-timestamp",
15053                 .fn    = run_readdir_timestamp,
15054         },
15055         {
15056                 .name = NULL,
15057         },
15058 };
15059
15060 /****************************************************************************
15061 run a specified test or "ALL"
15062 ****************************************************************************/
15063 static bool run_test(const char *name)
15064 {
15065         bool ret = True;
15066         bool result = True;
15067         bool found = False;
15068         int i;
15069         double t;
15070         if (strequal(name,"ALL")) {
15071                 for (i=0;torture_ops[i].name;i++) {
15072                         run_test(torture_ops[i].name);
15073                 }
15074                 found = True;
15075         }
15076
15077         for (i=0;torture_ops[i].name;i++) {
15078                 fstr_sprintf(randomfname, "\\XX%x", 
15079                          (unsigned)random());
15080
15081                 if (strequal(name, torture_ops[i].name)) {
15082                         found = True;
15083                         printf("Running %s\n", name);
15084                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
15085                                 t = create_procs(torture_ops[i].fn, &result);
15086                                 if (!result) { 
15087                                         ret = False;
15088                                         printf("TEST %s FAILED!\n", name);
15089                                 }
15090                         } else {
15091                                 struct timeval start;
15092                                 start = timeval_current();
15093                                 if (!torture_ops[i].fn(0)) {
15094                                         ret = False;
15095                                         printf("TEST %s FAILED!\n", name);
15096                                 }
15097                                 t = timeval_elapsed(&start);
15098                         }
15099                         printf("%s took %g secs\n\n", name, t);
15100                 }
15101         }
15102
15103         if (!found) {
15104                 printf("Did not find a test named %s\n", name);
15105                 ret = False;
15106         }
15107
15108         return ret;
15109 }
15110
15111
15112 static void usage(void)
15113 {
15114         int i;
15115
15116         printf("WARNING samba4 test suite is much more complete nowadays.\n");
15117         printf("Please use samba4 torture.\n\n");
15118
15119         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
15120
15121         printf("\t-d debuglevel\n");
15122         printf("\t-U user%%pass\n");
15123         printf("\t-k                    use kerberos\n");
15124         printf("\t-N numprocs\n");
15125         printf("\t-n my_netbios_name\n");
15126         printf("\t-W workgroup\n");
15127         printf("\t-o num_operations\n");
15128         printf("\t-O socket_options\n");
15129         printf("\t-m maximum protocol\n");
15130         printf("\t-L use oplocks\n");
15131         printf("\t-c CLIENT.TXT         specify client load file for NBENCH\n");
15132         printf("\t-A showall\n");
15133         printf("\t-p port\n");
15134         printf("\t-s seed\n");
15135         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
15136         printf("\t-f filename           filename to test\n");
15137         printf("\t-e                    encrypt\n");
15138         printf("\n\n");
15139
15140         printf("tests are:");
15141         for (i=0;torture_ops[i].name;i++) {
15142                 printf(" %s", torture_ops[i].name);
15143         }
15144         printf("\n");
15145
15146         printf("default test is ALL\n");
15147
15148         exit(1);
15149 }
15150
15151 /****************************************************************************
15152   main program
15153 ****************************************************************************/
15154  int main(int argc,char *argv[])
15155 {
15156         int opt, i;
15157         char *p;
15158         int gotuser = 0;
15159         int gotpass = 0;
15160         bool correct = True;
15161         TALLOC_CTX *frame = talloc_stackframe();
15162         int seed = time(NULL);
15163
15164 #ifdef HAVE_SETBUFFER
15165         setbuffer(stdout, NULL, 0);
15166 #endif
15167
15168         setup_logging("smbtorture", DEBUG_STDOUT);
15169
15170         smb_init_locale();
15171         fault_setup();
15172
15173         if (is_default_dyn_CONFIGFILE()) {
15174                 if(getenv("SMB_CONF_PATH")) {
15175                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
15176                 }
15177         }
15178         lp_load_global(get_dyn_CONFIGFILE());
15179         load_interfaces();
15180
15181         if (argc < 2) {
15182                 usage();
15183         }
15184
15185         for(p = argv[1]; *p; p++)
15186           if(*p == '\\')
15187             *p = '/';
15188
15189         if (strncmp(argv[1], "//", 2)) {
15190                 usage();
15191         }
15192
15193         fstrcpy(host, &argv[1][2]);
15194         p = strchr_m(&host[2],'/');
15195         if (!p) {
15196                 usage();
15197         }
15198         *p = 0;
15199         fstrcpy(share, p+1);
15200
15201         fstrcpy(myname, get_myname(talloc_tos()));
15202         if (!*myname) {
15203                 fprintf(stderr, "Failed to get my hostname.\n");
15204                 return 1;
15205         }
15206
15207         if (*username == 0 && getenv("LOGNAME")) {
15208           fstrcpy(username,getenv("LOGNAME"));
15209         }
15210
15211         argc--;
15212         argv++;
15213
15214         fstrcpy(workgroup, lp_workgroup());
15215
15216         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
15217                != EOF) {
15218                 switch (opt) {
15219                 case 'p':
15220                         port_to_use = atoi(optarg);
15221                         break;
15222                 case 's':
15223                         seed = atoi(optarg);
15224                         break;
15225                 case 'W':
15226                         fstrcpy(workgroup,optarg);
15227                         break;
15228                 case 'm':
15229                         lp_set_cmdline("client max protocol", optarg);
15230                         break;
15231                 case 'N':
15232                         torture_nprocs = atoi(optarg);
15233                         break;
15234                 case 'o':
15235                         torture_numops = atoi(optarg);
15236                         break;
15237                 case 'd':
15238                         lp_set_cmdline("log level", optarg);
15239                         break;
15240                 case 'O':
15241                         sockops = optarg;
15242                         break;
15243                 case 'L':
15244                         use_oplocks = True;
15245                         break;
15246                 case 'l':
15247                         local_path = optarg;
15248                         break;
15249                 case 'A':
15250                         torture_showall = True;
15251                         break;
15252                 case 'n':
15253                         fstrcpy(myname, optarg);
15254                         break;
15255                 case 'c':
15256                         client_txt = optarg;
15257                         break;
15258                 case 'e':
15259                         do_encrypt = true;
15260                         break;
15261                 case 'k':
15262 #ifdef HAVE_KRB5
15263                         use_kerberos = True;
15264 #else
15265                         d_printf("No kerberos support compiled in\n");
15266                         exit(1);
15267 #endif
15268                         break;
15269                 case 'U':
15270                         gotuser = 1;
15271                         fstrcpy(username,optarg);
15272                         p = strchr_m(username,'%');
15273                         if (p) {
15274                                 *p = 0;
15275                                 fstrcpy(password, p+1);
15276                                 gotpass = 1;
15277                         }
15278                         break;
15279                 case 'b':
15280                         fstrcpy(multishare_conn_fname, optarg);
15281                         use_multishare_conn = True;
15282                         break;
15283                 case 'B':
15284                         torture_blocksize = atoi(optarg);
15285                         break;
15286                 case 'f':
15287                         test_filename = SMB_STRDUP(optarg);
15288                         break;
15289                 default:
15290                         printf("Unknown option %c (%d)\n", (char)opt, opt);
15291                         usage();
15292                 }
15293         }
15294
15295         d_printf("using seed %d\n", seed);
15296
15297         srandom(seed);
15298
15299         if(use_kerberos && !gotuser) gotpass = True;
15300
15301         while (!gotpass) {
15302                 char pwd[256] = {0};
15303                 int rc;
15304
15305                 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
15306                 if (rc == 0) {
15307                         fstrcpy(password, pwd);
15308                         gotpass = 1;
15309                 }
15310         }
15311
15312         printf("host=%s share=%s user=%s myname=%s\n", 
15313                host, share, username, myname);
15314
15315         torture_creds = cli_session_creds_init(frame,
15316                                                username,
15317                                                workgroup,
15318                                                NULL, /* realm */
15319                                                password,
15320                                                use_kerberos,
15321                                                false, /* fallback_after_kerberos */
15322                                                false, /* use_ccache */
15323                                                false); /* password_is_nt_hash */
15324         if (torture_creds == NULL) {
15325                 d_printf("cli_session_creds_init() failed.\n");
15326                 exit(1);
15327         }
15328
15329         if (argc == optind) {
15330                 correct = run_test("ALL");
15331         } else {
15332                 for (i=optind;i<argc;i++) {
15333                         if (!run_test(argv[i])) {
15334                                 correct = False;
15335                         }
15336                 }
15337         }
15338
15339         TALLOC_FREE(frame);
15340
15341         if (correct) {
15342                 return(0);
15343         } else {
15344                 return(1);
15345         }
15346 }