s3: Fix dfs-reparse testing code to use 32-bit attributes. Change variable names...
[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         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4019         cli_openx(cli, fname, 
4020                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4021         cli_close(cli, fnum);
4022
4023         status = cli_getatr(cli, fname, NULL, NULL, &t);
4024         if (!NT_STATUS_IS_OK(status)) {
4025                 printf("getatr failed (%s)\n", nt_errstr(status));
4026                 correct = False;
4027         }
4028
4029         if (labs(t - time(NULL)) > 60*60*24*10) {
4030                 printf("ERROR: SMBgetatr bug. time is %s",
4031                        ctime(&t));
4032                 t = time(NULL);
4033                 correct = True;
4034         }
4035
4036         t2 = t-60*60*24; /* 1 day ago */
4037
4038         status = cli_setatr(cli, fname, 0, t2);
4039         if (!NT_STATUS_IS_OK(status)) {
4040                 printf("setatr failed (%s)\n", nt_errstr(status));
4041                 correct = True;
4042         }
4043
4044         status = cli_getatr(cli, fname, NULL, NULL, &t);
4045         if (!NT_STATUS_IS_OK(status)) {
4046                 printf("getatr failed (%s)\n", nt_errstr(status));
4047                 correct = True;
4048         }
4049
4050         if (t != t2) {
4051                 printf("ERROR: getatr/setatr bug. times are\n%s",
4052                        ctime(&t));
4053                 printf("%s", ctime(&t2));
4054                 correct = True;
4055         }
4056
4057         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4058
4059         /* Check cli_setpathinfo_ext() */
4060         /* Re-create the file. */
4061         status = cli_openx(cli, fname,
4062                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4063         if (!NT_STATUS_IS_OK(status)) {
4064                 printf("Failed to recreate %s (%s)\n",
4065                         fname, nt_errstr(status));
4066                 correct = false;
4067         }
4068         cli_close(cli, fnum);
4069
4070         status = cli_setpathinfo_ext(
4071                 cli,
4072                 fname,
4073                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4074                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4075                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4076                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4077                 FILE_ATTRIBUTE_SYSTEM |
4078                 FILE_ATTRIBUTE_HIDDEN |
4079                 FILE_ATTRIBUTE_READONLY);
4080         if (!NT_STATUS_IS_OK(status)) {
4081                 printf("cli_setpathinfo_ext failed with %s\n",
4082                         nt_errstr(status));
4083                 correct = false;
4084         }
4085
4086         /* Check attributes are correct. */
4087         correct = check_attributes(cli,
4088                         fname,
4089                         FILE_ATTRIBUTE_SYSTEM |
4090                         FILE_ATTRIBUTE_HIDDEN |
4091                         FILE_ATTRIBUTE_READONLY);
4092         if (correct == false) {
4093                 goto out;
4094         }
4095
4096         /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4097         status = cli_setpathinfo_ext(
4098                 cli,
4099                 fname,
4100                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4101                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4102                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4103                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4104                 FILE_ATTRIBUTE_NORMAL);
4105         if (!NT_STATUS_IS_OK(status)) {
4106                 printf("cli_setpathinfo_ext failed with %s\n",
4107                         nt_errstr(status));
4108                 correct = false;
4109         }
4110
4111         /* Check attributes are correct. */
4112         correct = check_attributes(cli,
4113                         fname,
4114                         FILE_ATTRIBUTE_SYSTEM |
4115                         FILE_ATTRIBUTE_HIDDEN |
4116                         FILE_ATTRIBUTE_READONLY);
4117         if (correct == false) {
4118                 goto out;
4119         }
4120
4121         /* Setting to (uint16_t)-1 should also be ignored. */
4122         status = cli_setpathinfo_ext(
4123                 cli,
4124                 fname,
4125                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4126                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4127                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4128                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4129                 (uint16_t)-1);
4130         if (!NT_STATUS_IS_OK(status)) {
4131                 printf("cli_setpathinfo_ext failed with %s\n",
4132                         nt_errstr(status));
4133                 correct = false;
4134         }
4135
4136         /* Check attributes are correct. */
4137         correct = check_attributes(cli,
4138                         fname,
4139                         FILE_ATTRIBUTE_SYSTEM |
4140                         FILE_ATTRIBUTE_HIDDEN |
4141                         FILE_ATTRIBUTE_READONLY);
4142         if (correct == false) {
4143                 goto out;
4144         }
4145
4146         /* Setting to 0 should clear them all. */
4147         status = cli_setpathinfo_ext(
4148                 cli,
4149                 fname,
4150                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4151                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4152                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4153                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4154                 0);
4155         if (!NT_STATUS_IS_OK(status)) {
4156                 printf("cli_setpathinfo_ext failed with %s\n",
4157                         nt_errstr(status));
4158                 correct = false;
4159         }
4160
4161         /* Check attributes are correct. */
4162         correct = check_attributes(cli,
4163                         fname,
4164                         FILE_ATTRIBUTE_NORMAL);
4165         if (correct == false) {
4166                 goto out;
4167         }
4168
4169   out:
4170
4171         cli_unlink(cli,
4172                 fname,
4173                 FILE_ATTRIBUTE_SYSTEM |
4174                 FILE_ATTRIBUTE_HIDDEN|
4175                 FILE_ATTRIBUTE_READONLY);
4176
4177         if (!torture_close_connection(cli)) {
4178                 correct = False;
4179         }
4180
4181         printf("attrib test finished\n");
4182
4183         return correct;
4184 }
4185
4186
4187 /*
4188   This checks a couple of trans2 calls
4189 */
4190 static bool run_trans2test(int dummy)
4191 {
4192         struct cli_state *cli;
4193         uint16_t fnum;
4194         off_t size;
4195         time_t c_time, a_time, m_time;
4196         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4197         const char *fname = "\\trans2.tst";
4198         const char *dname = "\\trans2";
4199         const char *fname2 = "\\trans2\\trans2.tst";
4200         char *pname;
4201         bool correct = True;
4202         NTSTATUS status;
4203         uint32_t fs_attr;
4204         uint64_t ino;
4205
4206         printf("starting trans2 test\n");
4207
4208         if (!torture_open_connection(&cli, 0)) {
4209                 return False;
4210         }
4211
4212         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4213                 /* Ensure ino is zero, SMB2 gets a real one. */
4214                 ino = 0;
4215         } else {
4216                 /* Ensure ino is -1, SMB1 never gets a real one. */
4217                 ino = (uint64_t)-1;
4218         }
4219
4220         status = cli_get_fs_attr_info(cli, &fs_attr);
4221         if (!NT_STATUS_IS_OK(status)) {
4222                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4223                        nt_errstr(status));
4224                 correct = false;
4225         }
4226
4227         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4228         cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4229         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4230                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4231         if (!NT_STATUS_IS_OK(status)) {
4232                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4233                 correct = False;
4234         }
4235
4236         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4237         if (!NT_STATUS_IS_OK(status)) {
4238                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4239                 correct = False;
4240         }
4241         else if (strcmp(pname, fname)) {
4242                 printf("qfilename gave different name? [%s] [%s]\n",
4243                        fname, pname);
4244                 correct = False;
4245         }
4246
4247         cli_close(cli, fnum);
4248
4249         sleep(2);
4250
4251         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4252         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4253                           &fnum);
4254         if (!NT_STATUS_IS_OK(status)) {
4255                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4256                 return False;
4257         }
4258         cli_close(cli, fnum);
4259
4260         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4261                                 NULL);
4262         if (!NT_STATUS_IS_OK(status)) {
4263                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4264                 correct = False;
4265         } else {
4266                 time_t t = time(NULL);
4267
4268                 if (c_time != m_time) {
4269                         printf("create time=%s", ctime(&c_time));
4270                         printf("modify time=%s", ctime(&m_time));
4271                         printf("This system appears to have sticky create times\n");
4272                 }
4273                 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4274                         printf("access time=%s", ctime(&a_time));
4275                         printf("This system appears to set a midnight access time\n");
4276                         correct = False;
4277                 }
4278
4279                 if (labs(m_time - t) > 60*60*24*7) {
4280                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4281                         correct = False;
4282                 }
4283         }
4284
4285
4286         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4287         cli_openx(cli, fname, 
4288                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4289         cli_close(cli, fnum);
4290         status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
4291                                 &m_time_ts, &size, NULL, &ino);
4292         if (!NT_STATUS_IS_OK(status)) {
4293                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4294                 correct = False;
4295         } else {
4296                 if (w_time_ts.tv_sec < 60*60*24*2) {
4297                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
4298                         printf("This system appears to set a initial 0 write time\n");
4299                         correct = False;
4300                 }
4301                 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4302                         /* SMB2 should always return an inode. */
4303                         if (ino == 0) {
4304                                 printf("SMB2 bad inode (0)\n");
4305                                 correct = false;
4306                         }
4307                 } else {
4308                         /* SMB1 must always return zero here. */
4309                         if (ino != 0) {
4310                                 printf("SMB1 bad inode (!0)\n");
4311                                 correct = false;
4312                         }
4313                 }
4314         }
4315
4316         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4317
4318
4319         /* check if the server updates the directory modification time
4320            when creating a new file */
4321         status = cli_mkdir(cli, dname);
4322         if (!NT_STATUS_IS_OK(status)) {
4323                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4324                 correct = False;
4325         }
4326         sleep(3);
4327         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4328                                 &w_time_ts, &m_time_ts, &size, NULL, NULL);
4329         if (!NT_STATUS_IS_OK(status)) {
4330                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4331                 correct = False;
4332         }
4333
4334         cli_openx(cli, fname2, 
4335                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4336         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4337         cli_close(cli, fnum);
4338         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4339                                 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
4340         if (!NT_STATUS_IS_OK(status)) {
4341                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4342                 correct = False;
4343         } else {
4344                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4345                     == 0) {
4346                         printf("This system does not update directory modification times\n");
4347                         correct = False;
4348                 }
4349         }
4350         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4351         cli_rmdir(cli, dname);
4352
4353         if (!torture_close_connection(cli)) {
4354                 correct = False;
4355         }
4356
4357         printf("trans2 test finished\n");
4358
4359         return correct;
4360 }
4361
4362 /*
4363   This checks new W2K calls.
4364 */
4365
4366 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4367 {
4368         uint8_t *buf = NULL;
4369         uint32_t len;
4370         NTSTATUS status;
4371
4372         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4373                                CLI_BUFFER_SIZE, NULL, &buf, &len);
4374         if (!NT_STATUS_IS_OK(status)) {
4375                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4376                        nt_errstr(status));
4377         } else {
4378                 printf("qfileinfo: level %d, len = %u\n", level, len);
4379                 dump_data(0, (uint8_t *)buf, len);
4380                 printf("\n");
4381         }
4382         TALLOC_FREE(buf);
4383         return status;
4384 }
4385
4386 static bool run_w2ktest(int dummy)
4387 {
4388         struct cli_state *cli;
4389         uint16_t fnum;
4390         const char *fname = "\\w2ktest\\w2k.tst";
4391         int level;
4392         bool correct = True;
4393
4394         printf("starting w2k test\n");
4395
4396         if (!torture_open_connection(&cli, 0)) {
4397                 return False;
4398         }
4399
4400         cli_openx(cli, fname, 
4401                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
4402
4403         for (level = 1004; level < 1040; level++) {
4404                 new_trans(cli, fnum, level);
4405         }
4406
4407         cli_close(cli, fnum);
4408
4409         if (!torture_close_connection(cli)) {
4410                 correct = False;
4411         }
4412
4413         printf("w2k test finished\n");
4414
4415         return correct;
4416 }
4417
4418
4419 /*
4420   this is a harness for some oplock tests
4421  */
4422 static bool run_oplock1(int dummy)
4423 {
4424         struct cli_state *cli1;
4425         const char *fname = "\\lockt1.lck";
4426         uint16_t fnum1;
4427         bool correct = True;
4428         NTSTATUS status;
4429
4430         printf("starting oplock test 1\n");
4431
4432         if (!torture_open_connection(&cli1, 0)) {
4433                 return False;
4434         }
4435
4436         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4437
4438         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4439
4440         cli1->use_oplocks = True;
4441
4442         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4443                           &fnum1);
4444         if (!NT_STATUS_IS_OK(status)) {
4445                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4446                 return False;
4447         }
4448
4449         cli1->use_oplocks = False;
4450
4451         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4452         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4453
4454         status = cli_close(cli1, fnum1);
4455         if (!NT_STATUS_IS_OK(status)) {
4456                 printf("close2 failed (%s)\n", nt_errstr(status));
4457                 return False;
4458         }
4459
4460         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4461         if (!NT_STATUS_IS_OK(status)) {
4462                 printf("unlink failed (%s)\n", nt_errstr(status));
4463                 return False;
4464         }
4465
4466         if (!torture_close_connection(cli1)) {
4467                 correct = False;
4468         }
4469
4470         printf("finished oplock test 1\n");
4471
4472         return correct;
4473 }
4474
4475 static bool run_oplock2(int dummy)
4476 {
4477         struct cli_state *cli1, *cli2;
4478         const char *fname = "\\lockt2.lck";
4479         uint16_t fnum1, fnum2;
4480         int saved_use_oplocks = use_oplocks;
4481         char buf[4];
4482         bool correct = True;
4483         volatile bool *shared_correct;
4484         size_t nread;
4485         NTSTATUS status;
4486
4487         shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4488         *shared_correct = True;
4489
4490         use_level_II_oplocks = True;
4491         use_oplocks = True;
4492
4493         printf("starting oplock test 2\n");
4494
4495         if (!torture_open_connection(&cli1, 0)) {
4496                 use_level_II_oplocks = False;
4497                 use_oplocks = saved_use_oplocks;
4498                 return False;
4499         }
4500
4501         if (!torture_open_connection(&cli2, 1)) {
4502                 use_level_II_oplocks = False;
4503                 use_oplocks = saved_use_oplocks;
4504                 return False;
4505         }
4506
4507         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4508
4509         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4510         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4511
4512         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4513                           &fnum1);
4514         if (!NT_STATUS_IS_OK(status)) {
4515                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4516                 return False;
4517         }
4518
4519         /* Don't need the globals any more. */
4520         use_level_II_oplocks = False;
4521         use_oplocks = saved_use_oplocks;
4522
4523         if (fork() == 0) {
4524                 /* Child code */
4525                 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4526                 if (!NT_STATUS_IS_OK(status)) {
4527                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4528                         *shared_correct = False;
4529                         exit(0);
4530                 }
4531
4532                 sleep(2);
4533
4534                 status = cli_close(cli2, fnum2);
4535                 if (!NT_STATUS_IS_OK(status)) {
4536                         printf("close2 failed (%s)\n", nt_errstr(status));
4537                         *shared_correct = False;
4538                 }
4539
4540                 exit(0);
4541         }
4542
4543         sleep(2);
4544
4545         /* Ensure cli1 processes the break. Empty file should always return 0
4546          * bytes.  */
4547         status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4548         if (!NT_STATUS_IS_OK(status)) {
4549                 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4550                 correct = false;
4551         } else if (nread != 0) {
4552                 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4553                       (unsigned long)nread, 0);
4554                 correct = false;
4555         }
4556
4557         /* Should now be at level II. */
4558         /* Test if sending a write locks causes a break to none. */
4559         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4560         if (!NT_STATUS_IS_OK(status)) {
4561                 printf("lock failed (%s)\n", nt_errstr(status));
4562                 correct = False;
4563         }
4564
4565         cli_unlock(cli1, fnum1, 0, 4);
4566
4567         sleep(2);
4568
4569         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4570         if (!NT_STATUS_IS_OK(status)) {
4571                 printf("lock failed (%s)\n", nt_errstr(status));
4572                 correct = False;
4573         }
4574
4575         cli_unlock(cli1, fnum1, 0, 4);
4576
4577         sleep(2);
4578
4579         cli_read(cli1, fnum1, buf, 0, 4, NULL);
4580
4581         status = cli_close(cli1, fnum1);
4582         if (!NT_STATUS_IS_OK(status)) {
4583                 printf("close1 failed (%s)\n", nt_errstr(status));
4584                 correct = False;
4585         }
4586
4587         sleep(4);
4588
4589         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4590         if (!NT_STATUS_IS_OK(status)) {
4591                 printf("unlink failed (%s)\n", nt_errstr(status));
4592                 correct = False;
4593         }
4594
4595         if (!torture_close_connection(cli1)) {
4596                 correct = False;
4597         }
4598
4599         if (!*shared_correct) {
4600                 correct = False;
4601         }
4602
4603         printf("finished oplock test 2\n");
4604
4605         return correct;
4606 }
4607
4608 struct oplock4_state {
4609         struct tevent_context *ev;
4610         struct cli_state *cli;
4611         bool *got_break;
4612         uint16_t *fnum2;
4613 };
4614
4615 static void oplock4_got_break(struct tevent_req *req);
4616 static void oplock4_got_open(struct tevent_req *req);
4617
4618 static bool run_oplock4(int dummy)
4619 {
4620         struct tevent_context *ev;
4621         struct cli_state *cli1, *cli2;
4622         struct tevent_req *oplock_req, *open_req;
4623         const char *fname = "\\lockt4.lck";
4624         const char *fname_ln = "\\lockt4_ln.lck";
4625         uint16_t fnum1, fnum2;
4626         int saved_use_oplocks = use_oplocks;
4627         NTSTATUS status;
4628         bool correct = true;
4629
4630         bool got_break;
4631
4632         struct oplock4_state *state;
4633
4634         printf("starting oplock test 4\n");
4635
4636         if (!torture_open_connection(&cli1, 0)) {
4637                 use_level_II_oplocks = false;
4638                 use_oplocks = saved_use_oplocks;
4639                 return false;
4640         }
4641
4642         if (!torture_open_connection(&cli2, 1)) {
4643                 use_level_II_oplocks = false;
4644                 use_oplocks = saved_use_oplocks;
4645                 return false;
4646         }
4647
4648         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4649         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4650
4651         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4652         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4653
4654         /* Create the file. */
4655         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4656                           &fnum1);
4657         if (!NT_STATUS_IS_OK(status)) {
4658                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4659                 return false;
4660         }
4661
4662         status = cli_close(cli1, fnum1);
4663         if (!NT_STATUS_IS_OK(status)) {
4664                 printf("close1 failed (%s)\n", nt_errstr(status));
4665                 return false;
4666         }
4667
4668         /* Now create a hardlink. */
4669         status = cli_hardlink(cli1, fname, fname_ln);
4670         if (!NT_STATUS_IS_OK(status)) {
4671                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4672                 return false;
4673         }
4674
4675         /* Prove that opening hardlinks cause deny modes to conflict. */
4676         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4677         if (!NT_STATUS_IS_OK(status)) {
4678                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4679                 return false;
4680         }
4681
4682         status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4683         if (NT_STATUS_IS_OK(status)) {
4684                 printf("open of %s succeeded - should fail with sharing violation.\n",
4685                         fname_ln);
4686                 return false;
4687         }
4688
4689         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4690                 printf("open of %s should fail with sharing violation. Got %s\n",
4691                         fname_ln, nt_errstr(status));
4692                 return false;
4693         }
4694
4695         status = cli_close(cli1, fnum1);
4696         if (!NT_STATUS_IS_OK(status)) {
4697                 printf("close1 failed (%s)\n", nt_errstr(status));
4698                 return false;
4699         }
4700
4701         cli1->use_oplocks = true;
4702         cli2->use_oplocks = true;
4703
4704         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4705         if (!NT_STATUS_IS_OK(status)) {
4706                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4707                 return false;
4708         }
4709
4710         ev = samba_tevent_context_init(talloc_tos());
4711         if (ev == NULL) {
4712                 printf("tevent_context_init failed\n");
4713                 return false;
4714         }
4715
4716         state = talloc(ev, struct oplock4_state);
4717         if (state == NULL) {
4718                 printf("talloc failed\n");
4719                 return false;
4720         }
4721         state->ev = ev;
4722         state->cli = cli1;
4723         state->got_break = &got_break;
4724         state->fnum2 = &fnum2;
4725
4726         oplock_req = cli_smb_oplock_break_waiter_send(
4727                 talloc_tos(), ev, cli1);
4728         if (oplock_req == NULL) {
4729                 printf("cli_smb_oplock_break_waiter_send failed\n");
4730                 return false;
4731         }
4732         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
4733
4734         open_req = cli_openx_send(
4735                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
4736         if (open_req == NULL) {
4737                 printf("cli_openx_send failed\n");
4738                 return false;
4739         }
4740         tevent_req_set_callback(open_req, oplock4_got_open, state);
4741
4742         got_break = false;
4743         fnum2 = 0xffff;
4744
4745         while (!got_break || fnum2 == 0xffff) {
4746                 int ret;
4747                 ret = tevent_loop_once(ev);
4748                 if (ret == -1) {
4749                         printf("tevent_loop_once failed: %s\n",
4750                                strerror(errno));
4751                         return false;
4752                 }
4753         }
4754
4755         status = cli_close(cli2, fnum2);
4756         if (!NT_STATUS_IS_OK(status)) {
4757                 printf("close2 failed (%s)\n", nt_errstr(status));
4758                 correct = false;
4759         }
4760
4761         status = cli_close(cli1, fnum1);
4762         if (!NT_STATUS_IS_OK(status)) {
4763                 printf("close1 failed (%s)\n", nt_errstr(status));
4764                 correct = false;
4765         }
4766
4767         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4768         if (!NT_STATUS_IS_OK(status)) {
4769                 printf("unlink failed (%s)\n", nt_errstr(status));
4770                 correct = false;
4771         }
4772
4773         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4774         if (!NT_STATUS_IS_OK(status)) {
4775                 printf("unlink failed (%s)\n", nt_errstr(status));
4776                 correct = false;
4777         }
4778
4779         if (!torture_close_connection(cli1)) {
4780                 correct = false;
4781         }
4782
4783         if (!got_break) {
4784                 correct = false;
4785         }
4786
4787         printf("finished oplock test 4\n");
4788
4789         return correct;
4790 }
4791
4792 static void oplock4_got_break(struct tevent_req *req)
4793 {
4794         struct oplock4_state *state = tevent_req_callback_data(
4795                 req, struct oplock4_state);
4796         uint16_t fnum;
4797         uint8_t level;
4798         NTSTATUS status;
4799
4800         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
4801         TALLOC_FREE(req);
4802         if (!NT_STATUS_IS_OK(status)) {
4803                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
4804                        nt_errstr(status));
4805                 return;
4806         }
4807         *state->got_break = true;
4808
4809         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
4810                                   NO_OPLOCK);
4811         if (req == NULL) {
4812                 printf("cli_oplock_ack_send failed\n");
4813                 return;
4814         }
4815 }
4816
4817 static void oplock4_got_open(struct tevent_req *req)
4818 {
4819         struct oplock4_state *state = tevent_req_callback_data(
4820                 req, struct oplock4_state);
4821         NTSTATUS status;
4822
4823         status = cli_openx_recv(req, state->fnum2);
4824         if (!NT_STATUS_IS_OK(status)) {
4825                 printf("cli_openx_recv returned %s\n", nt_errstr(status));
4826                 *state->fnum2 = 0xffff;
4827         }
4828 }
4829
4830 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
4831
4832 struct oplock5_state {
4833         int pipe_down_fd;
4834 };
4835
4836 /*
4837  * Async open the file that has a kernel oplock, do an echo to get
4838  * that 100% across, close the file to signal to the child fd that the
4839  * oplock can be dropped, wait for the open reply.
4840  */
4841
4842 static void oplock5_opened(struct tevent_req *subreq);
4843 static void oplock5_pong(struct tevent_req *subreq);
4844 static void oplock5_timedout(struct tevent_req *subreq);
4845
4846 static struct tevent_req *oplock5_send(
4847         TALLOC_CTX *mem_ctx,
4848         struct tevent_context *ev,
4849         struct cli_state *cli,
4850         const char *fname,
4851         int pipe_down_fd)
4852 {
4853         struct tevent_req *req = NULL, *subreq = NULL;
4854         struct oplock5_state *state = NULL;
4855         static uint8_t data = 0;
4856
4857         req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
4858         if (req == NULL) {
4859                 return NULL;
4860         }
4861         state->pipe_down_fd = pipe_down_fd;
4862
4863         subreq = cli_ntcreate_send(
4864                 state,
4865                 ev,
4866                 cli,
4867                 fname,
4868                 0,                      /* CreatFlags */
4869                 SEC_FILE_READ_DATA,    /* DesiredAccess */
4870                 FILE_ATTRIBUTE_NORMAL,  /* FileAttributes */
4871                 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
4872                 FILE_OPEN,               /* CreateDisposition */
4873                 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
4874                 0,                       /* Impersonation */
4875                 0);                      /* SecurityFlags */
4876         if (tevent_req_nomem(subreq, req)) {
4877                 return tevent_req_post(req, ev);
4878         }
4879         tevent_req_set_callback(subreq, oplock5_opened, req);
4880
4881         subreq = cli_echo_send(
4882                 state,
4883                 ev,
4884                 cli,
4885                 1,
4886                 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
4887         if (tevent_req_nomem(subreq, req)) {
4888                 return tevent_req_post(req, ev);
4889         }
4890         tevent_req_set_callback(subreq, oplock5_pong, req);
4891
4892         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
4893         if (tevent_req_nomem(subreq, req)) {
4894                 return tevent_req_post(req, ev);
4895         }
4896         tevent_req_set_callback(subreq, oplock5_timedout, req);
4897
4898         return req;
4899 }
4900
4901 static void oplock5_opened(struct tevent_req *subreq)
4902 {
4903         struct tevent_req *req = tevent_req_callback_data(
4904                 subreq, struct tevent_req);
4905         NTSTATUS status;
4906         uint16_t fnum;
4907
4908         status = cli_ntcreate_recv(subreq, &fnum, NULL);
4909         TALLOC_FREE(subreq);
4910         if (tevent_req_nterror(req, status)) {
4911                 return;
4912         }
4913         tevent_req_done(req);
4914 }
4915
4916 static void oplock5_pong(struct tevent_req *subreq)
4917 {
4918         struct tevent_req *req = tevent_req_callback_data(
4919                 subreq, struct tevent_req);
4920         struct oplock5_state *state = tevent_req_data(
4921                 req, struct oplock5_state);
4922         NTSTATUS status;
4923
4924         status = cli_echo_recv(subreq);
4925         TALLOC_FREE(subreq);
4926         if (tevent_req_nterror(req, status)) {
4927                 return;
4928         }
4929
4930         close(state->pipe_down_fd);
4931 }
4932
4933 static void oplock5_timedout(struct tevent_req *subreq)
4934 {
4935         struct tevent_req *req = tevent_req_callback_data(
4936                 subreq, struct tevent_req);
4937         bool ok;
4938
4939         ok = tevent_wakeup_recv(subreq);
4940         TALLOC_FREE(subreq);
4941         if (!ok) {
4942                 tevent_req_oom(req);
4943                 return;
4944         }
4945         tevent_req_nterror(req, NT_STATUS_TIMEOUT);
4946 }
4947
4948 static NTSTATUS oplock5_recv(struct tevent_req *req)
4949 {
4950         return tevent_req_simple_recv_ntstatus(req);
4951 }
4952
4953 static bool run_oplock5(int dummy)
4954 {
4955         struct tevent_context *ev = NULL;
4956         struct tevent_req *req = NULL;
4957         struct cli_state *cli = NULL;
4958         const char *fname = "oplock5.txt";
4959         int pipe_down[2], pipe_up[2];
4960         pid_t child_pid;
4961         uint8_t c = '\0';
4962         NTSTATUS status;
4963         int ret;
4964         bool ok;
4965
4966         printf("starting oplock5\n");
4967
4968         if (local_path == NULL) {
4969                 d_fprintf(stderr, "oplock5 must be given a local path via "
4970                           "-l <localpath>\n");
4971                 return false;
4972         }
4973
4974         ret = pipe(pipe_down);
4975         if (ret == -1) {
4976                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
4977                 return false;
4978         }
4979         ret = pipe(pipe_up);
4980         if (ret == -1) {
4981                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
4982                 return false;
4983         }
4984
4985         child_pid = fork();
4986         if (child_pid == -1) {
4987                 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
4988                 return false;
4989         }
4990
4991         if (child_pid == 0) {
4992                 char *local_file = NULL;
4993                 int fd;
4994
4995                 close(pipe_down[1]);
4996                 close(pipe_up[0]);
4997
4998                 local_file = talloc_asprintf(
4999                         talloc_tos(), "%s/%s", local_path, fname);
5000                 if (local_file == 0) {
5001                         c = 1;
5002                         goto do_write;
5003                 }
5004                 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5005                 if (fd == -1) {
5006                         d_fprintf(stderr,
5007                                   "open(%s) in child failed: %s\n",
5008                                   local_file,
5009                                   strerror(errno));
5010                         c = 2;
5011                         goto do_write;
5012                 }
5013
5014                 signal(SIGIO, SIG_IGN);
5015
5016                 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5017                 if (ret == -1) {
5018                         d_fprintf(stderr,
5019                                   "SETLEASE in child failed: %s\n",
5020                                   strerror(errno));
5021                         c = 3;
5022                         goto do_write;
5023                 }
5024
5025         do_write:
5026                 ret = sys_write(pipe_up[1], &c, sizeof(c));
5027                 if (ret == -1) {
5028                         d_fprintf(stderr,
5029                                   "sys_write failed: %s\n",
5030                                   strerror(errno));
5031                         exit(4);
5032                 }
5033                 ret = sys_read(pipe_down[0], &c, sizeof(c));
5034                 if (ret == -1) {
5035                         d_fprintf(stderr,
5036                                   "sys_read failed: %s\n",
5037                                   strerror(errno));
5038                         exit(5);
5039                 }
5040                 exit(0);
5041         }
5042
5043         close(pipe_up[1]);
5044         close(pipe_down[0]);
5045
5046         ret = sys_read(pipe_up[0], &c, sizeof(c));
5047         if (ret != 1) {
5048                 d_fprintf(stderr,
5049                           "sys_read failed: %s\n",
5050                           strerror(errno));
5051                 return false;
5052         }
5053         if (c != 0) {
5054                 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5055                 return false;
5056         }
5057
5058         ok = torture_open_connection(&cli, 0);
5059         if (!ok) {
5060                 d_fprintf(stderr, "torture_open_connection failed\n");
5061                 return false;
5062         }
5063
5064         ev = samba_tevent_context_init(talloc_tos());
5065         if (ev == NULL) {
5066                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5067                 return false;
5068         }
5069
5070         req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5071         if (req == NULL) {
5072                 d_fprintf(stderr, "oplock5_send failed\n");
5073                 return false;
5074         }
5075
5076         ok = tevent_req_poll_ntstatus(req, ev, &status);
5077         if (!ok) {
5078                 d_fprintf(stderr,
5079                           "tevent_req_poll_ntstatus failed: %s\n",
5080                           nt_errstr(status));
5081                 return false;
5082         }
5083
5084         status = oplock5_recv(req);
5085         TALLOC_FREE(req);
5086         if (!NT_STATUS_IS_OK(status)) {
5087                 d_fprintf(stderr,
5088                           "oplock5 failed: %s\n",
5089                           nt_errstr(status));
5090                 return false;
5091         }
5092
5093         return true;
5094 }
5095
5096 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5097
5098 /*
5099   Test delete on close semantics.
5100  */
5101 static bool run_deletetest(int dummy)
5102 {
5103         struct cli_state *cli1 = NULL;
5104         struct cli_state *cli2 = NULL;
5105         const char *fname = "\\delete.file";
5106         uint16_t fnum1 = (uint16_t)-1;
5107         uint16_t fnum2 = (uint16_t)-1;
5108         bool correct = false;
5109         NTSTATUS status;
5110
5111         printf("starting delete test\n");
5112
5113         if (!torture_open_connection(&cli1, 0)) {
5114                 return False;
5115         }
5116
5117         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5118
5119         /* Test 1 - this should delete the file on close. */
5120
5121         cli_setatr(cli1, fname, 0, 0);
5122         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5123
5124         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5125                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5126                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5127         if (!NT_STATUS_IS_OK(status)) {
5128                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5129                 goto fail;
5130         }
5131
5132         status = cli_close(cli1, fnum1);
5133         if (!NT_STATUS_IS_OK(status)) {
5134                 printf("[1] close failed (%s)\n", nt_errstr(status));
5135                 goto fail;
5136         }
5137
5138         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5139         if (NT_STATUS_IS_OK(status)) {
5140                 printf("[1] open of %s succeeded (should fail)\n", fname);
5141                 goto fail;
5142         }
5143
5144         printf("first delete on close test succeeded.\n");
5145
5146         /* Test 2 - this should delete the file on close. */
5147
5148         cli_setatr(cli1, fname, 0, 0);
5149         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5150
5151         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5152                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5153                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5154         if (!NT_STATUS_IS_OK(status)) {
5155                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5156                 goto fail;
5157         }
5158
5159         status = cli_nt_delete_on_close(cli1, fnum1, true);
5160         if (!NT_STATUS_IS_OK(status)) {
5161                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5162                 goto fail;
5163         }
5164
5165         status = cli_close(cli1, fnum1);
5166         if (!NT_STATUS_IS_OK(status)) {
5167                 printf("[2] close failed (%s)\n", nt_errstr(status));
5168                 goto fail;
5169         }
5170
5171         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5172         if (NT_STATUS_IS_OK(status)) {
5173                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5174                 status = cli_close(cli1, fnum1);
5175                 if (!NT_STATUS_IS_OK(status)) {
5176                         printf("[2] close failed (%s)\n", nt_errstr(status));
5177                 }
5178                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5179                 goto fail;
5180         }
5181
5182         printf("second delete on close test succeeded.\n");
5183
5184         /* Test 3 - ... */
5185         cli_setatr(cli1, fname, 0, 0);
5186         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5187
5188         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5189                               FILE_ATTRIBUTE_NORMAL,
5190                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5191                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5192         if (!NT_STATUS_IS_OK(status)) {
5193                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5194                 goto fail;
5195         }
5196
5197         /* This should fail with a sharing violation - open for delete is only compatible
5198            with SHARE_DELETE. */
5199
5200         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5201                               FILE_ATTRIBUTE_NORMAL,
5202                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5203                               FILE_OPEN, 0, 0, &fnum2, NULL);
5204         if (NT_STATUS_IS_OK(status)) {
5205                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
5206                 goto fail;
5207         }
5208
5209         /* This should succeed. */
5210         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5211                              FILE_ATTRIBUTE_NORMAL,
5212                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5213                              FILE_OPEN, 0, 0, &fnum2, NULL);
5214         if (!NT_STATUS_IS_OK(status)) {
5215                 printf("[3] open  - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5216                 goto fail;
5217         }
5218
5219         status = cli_nt_delete_on_close(cli1, fnum1, true);
5220         if (!NT_STATUS_IS_OK(status)) {
5221                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5222                 goto fail;
5223         }
5224
5225         status = cli_close(cli1, fnum1);
5226         if (!NT_STATUS_IS_OK(status)) {
5227                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5228                 goto fail;
5229         }
5230
5231         status = cli_close(cli1, fnum2);
5232         if (!NT_STATUS_IS_OK(status)) {
5233                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5234                 goto fail;
5235         }
5236
5237         /* This should fail - file should no longer be there. */
5238
5239         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5240         if (NT_STATUS_IS_OK(status)) {
5241                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5242                 status = cli_close(cli1, fnum1);
5243                 if (!NT_STATUS_IS_OK(status)) {
5244                         printf("[3] close failed (%s)\n", nt_errstr(status));
5245                 }
5246                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5247                 goto fail;
5248         }
5249
5250         printf("third delete on close test succeeded.\n");
5251
5252         /* Test 4 ... */
5253         cli_setatr(cli1, fname, 0, 0);
5254         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5255
5256         status = cli_ntcreate(cli1, fname, 0,
5257                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5258                               FILE_ATTRIBUTE_NORMAL,
5259                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5260                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5261         if (!NT_STATUS_IS_OK(status)) {
5262                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5263                 goto fail;
5264         }
5265
5266         /* This should succeed. */
5267         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5268                              FILE_ATTRIBUTE_NORMAL,
5269                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5270                              FILE_OPEN, 0, 0, &fnum2, NULL);
5271         if (!NT_STATUS_IS_OK(status)) {
5272                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5273                 goto fail;
5274         }
5275
5276         status = cli_close(cli1, fnum2);
5277         if (!NT_STATUS_IS_OK(status)) {
5278                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5279                 goto fail;
5280         }
5281
5282         status = cli_nt_delete_on_close(cli1, fnum1, true);
5283         if (!NT_STATUS_IS_OK(status)) {
5284                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5285                 goto fail;
5286         }
5287
5288         /* This should fail - no more opens once delete on close set. */
5289         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5290                               FILE_ATTRIBUTE_NORMAL,
5291                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5292                               FILE_OPEN, 0, 0, &fnum2, NULL);
5293         if (NT_STATUS_IS_OK(status)) {
5294                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
5295                 goto fail;
5296         }
5297
5298         status = cli_close(cli1, fnum1);
5299         if (!NT_STATUS_IS_OK(status)) {
5300                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5301                 goto fail;
5302         }
5303
5304         printf("fourth delete on close test succeeded.\n");
5305
5306         /* Test 5 ... */
5307         cli_setatr(cli1, fname, 0, 0);
5308         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5309
5310         status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5311         if (!NT_STATUS_IS_OK(status)) {
5312                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5313                 goto fail;
5314         }
5315
5316         /* This should fail - only allowed on NT opens with DELETE access. */
5317
5318         status = cli_nt_delete_on_close(cli1, fnum1, true);
5319         if (NT_STATUS_IS_OK(status)) {
5320                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5321                 goto fail;
5322         }
5323
5324         status = cli_close(cli1, fnum1);
5325         if (!NT_STATUS_IS_OK(status)) {
5326                 printf("[5] close failed (%s)\n", nt_errstr(status));
5327                 goto fail;
5328         }
5329
5330         printf("fifth delete on close test succeeded.\n");
5331
5332         /* Test 6 ... */
5333         cli_setatr(cli1, fname, 0, 0);
5334         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5335
5336         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5337                              FILE_ATTRIBUTE_NORMAL,
5338                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5339                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5340         if (!NT_STATUS_IS_OK(status)) {
5341                 printf("[6] open of %s failed (%s)\n", fname,
5342                        nt_errstr(status));
5343                 goto fail;
5344         }
5345
5346         /* This should fail - only allowed on NT opens with DELETE access. */
5347
5348         status = cli_nt_delete_on_close(cli1, fnum1, true);
5349         if (NT_STATUS_IS_OK(status)) {
5350                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5351                 goto fail;
5352         }
5353
5354         status = cli_close(cli1, fnum1);
5355         if (!NT_STATUS_IS_OK(status)) {
5356                 printf("[6] close failed (%s)\n", nt_errstr(status));
5357                 goto fail;
5358         }
5359
5360         printf("sixth delete on close test succeeded.\n");
5361
5362         /* Test 7 ... */
5363         cli_setatr(cli1, fname, 0, 0);
5364         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5365
5366         status = cli_ntcreate(cli1, fname, 0,
5367                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5368                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5369                               0, 0, &fnum1, NULL);
5370         if (!NT_STATUS_IS_OK(status)) {
5371                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5372                 goto fail;
5373         }
5374
5375         status = cli_nt_delete_on_close(cli1, fnum1, true);
5376         if (!NT_STATUS_IS_OK(status)) {
5377                 printf("[7] setting delete_on_close on file failed !\n");
5378                 goto fail;
5379         }
5380
5381         status = cli_nt_delete_on_close(cli1, fnum1, false);
5382         if (!NT_STATUS_IS_OK(status)) {
5383                 printf("[7] unsetting delete_on_close on file failed !\n");
5384                 goto fail;
5385         }
5386
5387         status = cli_close(cli1, fnum1);
5388         if (!NT_STATUS_IS_OK(status)) {
5389                 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5390                 goto fail;
5391         }
5392
5393         /* This next open should succeed - we reset the flag. */
5394         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5395         if (!NT_STATUS_IS_OK(status)) {
5396                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5397                 goto fail;
5398         }
5399
5400         status = cli_close(cli1, fnum1);
5401         if (!NT_STATUS_IS_OK(status)) {
5402                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5403                 goto fail;
5404         }
5405
5406         printf("seventh delete on close test succeeded.\n");
5407
5408         /* Test 8 ... */
5409         cli_setatr(cli1, fname, 0, 0);
5410         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5411
5412         if (!torture_open_connection(&cli2, 1)) {
5413                 printf("[8] failed to open second connection.\n");
5414                 goto fail;
5415         }
5416
5417         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5418
5419         status = cli_ntcreate(cli1, fname, 0,
5420                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5421                              FILE_ATTRIBUTE_NORMAL,
5422                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5423                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5424         if (!NT_STATUS_IS_OK(status)) {
5425                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5426                 goto fail;
5427         }
5428
5429         status = cli_ntcreate(cli2, fname, 0,
5430                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5431                              FILE_ATTRIBUTE_NORMAL,
5432                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5433                              FILE_OPEN, 0, 0, &fnum2, NULL);
5434         if (!NT_STATUS_IS_OK(status)) {
5435                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5436                 goto fail;
5437         }
5438
5439         status = cli_nt_delete_on_close(cli1, fnum1, true);
5440         if (!NT_STATUS_IS_OK(status)) {
5441                 printf("[8] setting delete_on_close on file failed !\n");
5442                 goto fail;
5443         }
5444
5445         status = cli_close(cli1, fnum1);
5446         if (!NT_STATUS_IS_OK(status)) {
5447                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5448                 goto fail;
5449         }
5450
5451         status = cli_close(cli2, fnum2);
5452         if (!NT_STATUS_IS_OK(status)) {
5453                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5454                 goto fail;
5455         }
5456
5457         /* This should fail.. */
5458         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5459         if (NT_STATUS_IS_OK(status)) {
5460                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5461                 goto fail;
5462         }
5463
5464         printf("eighth delete on close test succeeded.\n");
5465
5466         /* Test 9 ... */
5467
5468         /* This should fail - we need to set DELETE_ACCESS. */
5469         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5470                               FILE_ATTRIBUTE_NORMAL,
5471                               FILE_SHARE_NONE,
5472                               FILE_OVERWRITE_IF,
5473                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5474         if (NT_STATUS_IS_OK(status)) {
5475                 printf("[9] open of %s succeeded should have failed!\n", fname);
5476                 goto fail;
5477         }
5478
5479         printf("ninth delete on close test succeeded.\n");
5480
5481         /* Test 10 ... */
5482
5483         status = cli_ntcreate(cli1, fname, 0,
5484                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5485                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5486                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5487                              0, &fnum1, NULL);
5488         if (!NT_STATUS_IS_OK(status)) {
5489                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5490                 goto fail;
5491         }
5492
5493         /* This should delete the file. */
5494         status = cli_close(cli1, fnum1);
5495         if (!NT_STATUS_IS_OK(status)) {
5496                 printf("[10] close failed (%s)\n", nt_errstr(status));
5497                 goto fail;
5498         }
5499
5500         /* This should fail.. */
5501         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5502         if (NT_STATUS_IS_OK(status)) {
5503                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5504                 goto fail;
5505         }
5506
5507         printf("tenth delete on close test succeeded.\n");
5508
5509         /* Test 11 ... */
5510
5511         cli_setatr(cli1, fname, 0, 0);
5512         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5513
5514         /* Can we open a read-only file with delete access? */
5515
5516         /* Create a readonly file. */
5517         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5518                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5519                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5520         if (!NT_STATUS_IS_OK(status)) {
5521                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5522                 goto fail;
5523         }
5524
5525         status = cli_close(cli1, fnum1);
5526         if (!NT_STATUS_IS_OK(status)) {
5527                 printf("[11] close failed (%s)\n", nt_errstr(status));
5528                 goto fail;
5529         }
5530
5531         /* Now try open for delete access. */
5532         status = cli_ntcreate(cli1, fname, 0,
5533                              FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5534                              0,
5535                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5536                              FILE_OPEN, 0, 0, &fnum1, NULL);
5537         if (!NT_STATUS_IS_OK(status)) {
5538                 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5539                 goto fail;
5540         }
5541
5542         cli_close(cli1, fnum1);
5543
5544         printf("eleventh delete on close test succeeded.\n");
5545
5546         /*
5547          * Test 12
5548          * like test 4 but with initial delete on close
5549          */
5550
5551         cli_setatr(cli1, fname, 0, 0);
5552         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5553
5554         status = cli_ntcreate(cli1, fname, 0,
5555                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5556                               FILE_ATTRIBUTE_NORMAL,
5557                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5558                               FILE_OVERWRITE_IF,
5559                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5560         if (!NT_STATUS_IS_OK(status)) {
5561                 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5562                 goto fail;
5563         }
5564
5565         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5566                               FILE_ATTRIBUTE_NORMAL,
5567                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5568                               FILE_OPEN, 0, 0, &fnum2, NULL);
5569         if (!NT_STATUS_IS_OK(status)) {
5570                 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5571                 goto fail;
5572         }
5573
5574         status = cli_close(cli1, fnum2);
5575         if (!NT_STATUS_IS_OK(status)) {
5576                 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5577                 goto fail;
5578         }
5579
5580         status = cli_nt_delete_on_close(cli1, fnum1, true);
5581         if (!NT_STATUS_IS_OK(status)) {
5582                 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5583                 goto fail;
5584         }
5585
5586         /* This should fail - no more opens once delete on close set. */
5587         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5588                               FILE_ATTRIBUTE_NORMAL,
5589                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5590                               FILE_OPEN, 0, 0, &fnum2, NULL);
5591         if (NT_STATUS_IS_OK(status)) {
5592                 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5593                 goto fail;
5594         }
5595
5596         status = cli_nt_delete_on_close(cli1, fnum1, false);
5597         if (!NT_STATUS_IS_OK(status)) {
5598                 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5599                 goto fail;
5600         }
5601
5602         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5603                               FILE_ATTRIBUTE_NORMAL,
5604                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5605                               FILE_OPEN, 0, 0, &fnum2, NULL);
5606         if (!NT_STATUS_IS_OK(status)) {
5607                 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5608                 goto fail;
5609         }
5610
5611         status = cli_close(cli1, fnum2);
5612         if (!NT_STATUS_IS_OK(status)) {
5613                 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5614                 goto fail;
5615         }
5616
5617         status = cli_close(cli1, fnum1);
5618         if (!NT_STATUS_IS_OK(status)) {
5619                 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5620                 goto fail;
5621         }
5622
5623         /*
5624          * setting delete on close on the handle does
5625          * not unset the initial delete on close...
5626          */
5627         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5628                               FILE_ATTRIBUTE_NORMAL,
5629                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5630                               FILE_OPEN, 0, 0, &fnum2, NULL);
5631         if (NT_STATUS_IS_OK(status)) {
5632                 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5633                 goto fail;
5634         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5635                 printf("ntcreate returned %s, expected "
5636                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5637                        nt_errstr(status));
5638                 goto fail;
5639         }
5640
5641         printf("twelfth delete on close test succeeded.\n");
5642
5643
5644         printf("finished delete test\n");
5645
5646         correct = true;
5647
5648   fail:
5649         /* FIXME: This will crash if we aborted before cli2 got
5650          * intialized, because these functions don't handle
5651          * uninitialized connections. */
5652
5653         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5654         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5655         cli_setatr(cli1, fname, 0, 0);
5656         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5657
5658         if (cli1 && !torture_close_connection(cli1)) {
5659                 correct = False;
5660         }
5661         if (cli2 && !torture_close_connection(cli2)) {
5662                 correct = False;
5663         }
5664         return correct;
5665 }
5666
5667 struct delete_stream_state {
5668         bool closed;
5669 };
5670
5671 static void delete_stream_unlinked(struct tevent_req *subreq);
5672 static void delete_stream_closed(struct tevent_req *subreq);
5673
5674 static struct tevent_req *delete_stream_send(
5675         TALLOC_CTX *mem_ctx,
5676         struct tevent_context *ev,
5677         struct cli_state *cli,
5678         const char *base_fname,
5679         uint16_t stream_fnum)
5680 {
5681         struct tevent_req *req = NULL, *subreq = NULL;
5682         struct delete_stream_state *state = NULL;
5683
5684         req = tevent_req_create(
5685                 mem_ctx, &state, struct delete_stream_state);
5686         if (req == NULL) {
5687                 return NULL;
5688         }
5689
5690         subreq = cli_unlink_send(
5691                 state,
5692                 ev,
5693                 cli,
5694                 base_fname,
5695                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5696         if (tevent_req_nomem(subreq, req)) {
5697                 return tevent_req_post(req, ev);
5698         }
5699         tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5700
5701         subreq = cli_close_send(state, ev, cli, stream_fnum);
5702         if (tevent_req_nomem(subreq, req)) {
5703                 return tevent_req_post(req, ev);
5704         }
5705         tevent_req_set_callback(subreq, delete_stream_closed, req);
5706
5707         return req;
5708 }
5709
5710 static void delete_stream_unlinked(struct tevent_req *subreq)
5711 {
5712         struct tevent_req *req = tevent_req_callback_data(
5713                 subreq, struct tevent_req);
5714         struct delete_stream_state *state = tevent_req_data(
5715                 req, struct delete_stream_state);
5716         NTSTATUS status;
5717
5718         status = cli_unlink_recv(subreq);
5719         TALLOC_FREE(subreq);
5720         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5721                 printf("cli_unlink returned %s\n",
5722                        nt_errstr(status));
5723                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5724                 return;
5725         }
5726         if (!state->closed) {
5727                 /* close reply should have come in first */
5728                 printf("Not closed\n");
5729                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5730                 return;
5731         }
5732         tevent_req_done(req);
5733 }
5734
5735 static void delete_stream_closed(struct tevent_req *subreq)
5736 {
5737         struct tevent_req *req = tevent_req_callback_data(
5738                 subreq, struct tevent_req);
5739         struct delete_stream_state *state = tevent_req_data(
5740                 req, struct delete_stream_state);
5741         NTSTATUS status;
5742
5743         status = cli_close_recv(subreq);
5744         TALLOC_FREE(subreq);
5745         if (tevent_req_nterror(req, status)) {
5746                 return;
5747         }
5748         /* also waiting for the unlink to come back */
5749         state->closed = true;
5750 }
5751
5752 static NTSTATUS delete_stream_recv(struct tevent_req *req)
5753 {
5754         return tevent_req_simple_recv_ntstatus(req);
5755 }
5756
5757 static bool run_delete_stream(int dummy)
5758 {
5759         struct tevent_context *ev = NULL;
5760         struct tevent_req *req = NULL;
5761         struct cli_state *cli = NULL;
5762         const char fname[] = "delete_stream";
5763         const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
5764         uint16_t fnum1, fnum2;
5765         NTSTATUS status;
5766         bool ok;
5767
5768         printf("Starting stream delete test\n");
5769
5770         ok = torture_open_connection(&cli, 0);
5771         if (!ok) {
5772                 return false;
5773         }
5774
5775         cli_setatr(cli, fname, 0, 0);
5776         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5777
5778         /* Create the file. */
5779         status = cli_ntcreate(
5780                 cli,
5781                 fname,
5782                 0,
5783                 READ_CONTROL_ACCESS,
5784                 0,
5785                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5786                 FILE_CREATE,
5787                 0x0,
5788                 0x0,
5789                 &fnum1,
5790                 NULL);
5791         if (!NT_STATUS_IS_OK(status)) {
5792                 d_fprintf(stderr,
5793                           "cli_ntcreate of %s failed (%s)\n",
5794                           fname,
5795                           nt_errstr(status));
5796                 return false;
5797         }
5798         status = cli_close(cli, fnum1);
5799         if (!NT_STATUS_IS_OK(status)) {
5800                 d_fprintf(stderr,
5801                           "cli_close of %s failed (%s)\n",
5802                           fname,
5803                           nt_errstr(status));
5804                 return false;
5805         }
5806
5807         /* Now create the stream. */
5808         status = cli_ntcreate(
5809                 cli,
5810                 fname_stream,
5811                 0,
5812                 FILE_WRITE_DATA,
5813                 0,
5814                 FILE_SHARE_READ|FILE_SHARE_WRITE,
5815                 FILE_CREATE,
5816                 0x0,
5817                 0x0,
5818                 &fnum1,
5819                 NULL);
5820
5821         if (!NT_STATUS_IS_OK(status)) {
5822                 d_fprintf(stderr,
5823                           "cli_ntcreate of %s failed (%s)\n",
5824                           fname_stream,
5825                           nt_errstr(status));
5826                 return false;
5827         }
5828
5829         /* open it a second time */
5830
5831         status = cli_ntcreate(
5832                 cli,
5833                 fname_stream,
5834                 0,
5835                 FILE_WRITE_DATA,
5836                 0,
5837                 FILE_SHARE_READ|FILE_SHARE_WRITE,
5838                 FILE_OPEN,
5839                 0x0,
5840                 0x0,
5841                 &fnum2,
5842                 NULL);
5843
5844         if (!NT_STATUS_IS_OK(status)) {
5845                 d_fprintf(stderr,
5846                           "2nd cli_ntcreate of %s failed (%s)\n",
5847                           fname_stream,
5848                           nt_errstr(status));
5849                 return false;
5850         }
5851
5852         ev = samba_tevent_context_init(talloc_tos());
5853         if (ev == NULL) {
5854                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5855                 return false;
5856         }
5857
5858         req = delete_stream_send(ev, ev, cli, fname, fnum1);
5859         if (req == NULL) {
5860                 d_fprintf(stderr, "delete_stream_send failed\n");
5861                 return false;
5862         }
5863
5864         ok = tevent_req_poll_ntstatus(req, ev, &status);
5865         if (!ok) {
5866                 d_fprintf(stderr,
5867                           "tevent_req_poll_ntstatus failed: %s\n",
5868                           nt_errstr(status));
5869                 return false;
5870         }
5871
5872         status = delete_stream_recv(req);
5873         TALLOC_FREE(req);
5874         if (!NT_STATUS_IS_OK(status)) {
5875                 d_fprintf(stderr,
5876                           "delete_stream failed: %s\n",
5877                           nt_errstr(status));
5878                 return false;
5879         }
5880
5881         status = cli_close(cli, fnum2);
5882         if (!NT_STATUS_IS_OK(status)) {
5883                 d_fprintf(stderr,
5884                           "close failed: %s\n",
5885                           nt_errstr(status));
5886                 return false;
5887         }
5888
5889         status = cli_unlink(
5890                 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5891         if (!NT_STATUS_IS_OK(status)) {
5892                 d_fprintf(stderr,
5893                           "unlink failed: %s\n",
5894                           nt_errstr(status));
5895                 return false;
5896         }
5897
5898         return true;
5899 }
5900
5901 /*
5902   Exercise delete on close semantics - use on the PRINT1 share in torture
5903   testing.
5904  */
5905 static bool run_delete_print_test(int dummy)
5906 {
5907         struct cli_state *cli1 = NULL;
5908         const char *fname = "print_delete.file";
5909         uint16_t fnum1 = (uint16_t)-1;
5910         bool correct = false;
5911         const char *buf = "print file data\n";
5912         NTSTATUS status;
5913
5914         printf("starting print delete test\n");
5915
5916         if (!torture_open_connection(&cli1, 0)) {
5917                 return false;
5918         }
5919
5920         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5921
5922         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5923                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5924                               0, 0, &fnum1, NULL);
5925         if (!NT_STATUS_IS_OK(status)) {
5926                 printf("open of %s failed (%s)\n",
5927                         fname,
5928                         nt_errstr(status));
5929                 goto fail;
5930         }
5931
5932         status = cli_writeall(cli1,
5933                         fnum1,
5934                         0,
5935                         (const uint8_t *)buf,
5936                         0, /* offset */
5937                         strlen(buf), /* size */
5938                         NULL);
5939         if (!NT_STATUS_IS_OK(status)) {
5940                 printf("writing print file data failed (%s)\n",
5941                         nt_errstr(status));
5942                 goto fail;
5943         }
5944
5945         status = cli_nt_delete_on_close(cli1, fnum1, true);
5946         if (!NT_STATUS_IS_OK(status)) {
5947                 printf("setting delete_on_close failed (%s)\n",
5948                         nt_errstr(status));
5949                 goto fail;
5950         }
5951
5952         status = cli_close(cli1, fnum1);
5953         if (!NT_STATUS_IS_OK(status)) {
5954                 printf("close failed (%s)\n", nt_errstr(status));
5955                 goto fail;
5956         }
5957
5958         printf("finished print delete test\n");
5959
5960         correct = true;
5961
5962   fail:
5963
5964         if (fnum1 != (uint16_t)-1) {
5965                 cli_close(cli1, fnum1);
5966         }
5967
5968         if (cli1 && !torture_close_connection(cli1)) {
5969                 correct = false;
5970         }
5971         return correct;
5972 }
5973
5974 /*
5975   Test wildcard delete.
5976  */
5977 static bool run_wild_deletetest(int dummy)
5978 {
5979         struct cli_state *cli = NULL;
5980         const char *dname = "\\WTEST";
5981         const char *fname = "\\WTEST\\A";
5982         const char *wunlink_name = "\\WTEST\\*";
5983         uint16_t fnum1 = (uint16_t)-1;
5984         bool correct = false;
5985         NTSTATUS status;
5986
5987         printf("starting wildcard delete test\n");
5988
5989         if (!torture_open_connection(&cli, 0)) {
5990                 return false;
5991         }
5992
5993         smbXcli_conn_set_sockopt(cli->conn, sockops);
5994
5995         cli_unlink(cli, fname, 0);
5996         cli_rmdir(cli, dname);
5997         status = cli_mkdir(cli, dname);
5998         if (!NT_STATUS_IS_OK(status)) {
5999                 printf("mkdir of %s failed %s!\n", dname, nt_errstr(status));
6000                 goto fail;
6001         }
6002         status = cli_openx(cli, fname, O_CREAT|O_RDONLY, DENY_NONE, &fnum1);
6003         if (!NT_STATUS_IS_OK(status)) {
6004                 printf("open of %s failed %s!\n", fname, nt_errstr(status));
6005                 goto fail;
6006         }
6007         status = cli_close(cli, fnum1);
6008         fnum1 = -1;
6009
6010         /*
6011          * Note the unlink attribute-type of zero. This should
6012          * map into FILE_ATTRIBUTE_NORMAL at the server even
6013          * on a wildcard delete.
6014          */
6015
6016         status = cli_unlink(cli, wunlink_name, 0);
6017         if (!NT_STATUS_IS_OK(status)) {
6018                 printf("unlink of %s failed %s!\n",
6019                         wunlink_name, nt_errstr(status));
6020                 goto fail;
6021         }
6022
6023         printf("finished wildcard delete test\n");
6024
6025         correct = true;
6026
6027   fail:
6028
6029         if (fnum1 != (uint16_t)-1) cli_close(cli, fnum1);
6030         cli_unlink(cli, fname, 0);
6031         cli_rmdir(cli, dname);
6032
6033         if (cli && !torture_close_connection(cli)) {
6034                 correct = false;
6035         }
6036         return correct;
6037 }
6038
6039 static bool run_deletetest_ln(int dummy)
6040 {
6041         struct cli_state *cli;
6042         const char *fname = "\\delete1";
6043         const char *fname_ln = "\\delete1_ln";
6044         uint16_t fnum;
6045         uint16_t fnum1;
6046         NTSTATUS status;
6047         bool correct = true;
6048         time_t t;
6049
6050         printf("starting deletetest-ln\n");
6051
6052         if (!torture_open_connection(&cli, 0)) {
6053                 return false;
6054         }
6055
6056         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6057         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6058
6059         smbXcli_conn_set_sockopt(cli->conn, sockops);
6060
6061         /* Create the file. */
6062         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6063         if (!NT_STATUS_IS_OK(status)) {
6064                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6065                 return false;
6066         }
6067
6068         status = cli_close(cli, fnum);
6069         if (!NT_STATUS_IS_OK(status)) {
6070                 printf("close1 failed (%s)\n", nt_errstr(status));
6071                 return false;
6072         }
6073
6074         /* Now create a hardlink. */
6075         status = cli_hardlink(cli, fname, fname_ln);
6076         if (!NT_STATUS_IS_OK(status)) {
6077                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6078                 return false;
6079         }
6080
6081         /* Open the original file. */
6082         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6083                         FILE_ATTRIBUTE_NORMAL,
6084                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6085                         FILE_OPEN_IF, 0, 0, &fnum, NULL);
6086         if (!NT_STATUS_IS_OK(status)) {
6087                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6088                 return false;
6089         }
6090
6091         /* Unlink the hard link path. */
6092         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6093                         FILE_ATTRIBUTE_NORMAL,
6094                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6095                         FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6096         if (!NT_STATUS_IS_OK(status)) {
6097                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6098                 return false;
6099         }
6100         status = cli_nt_delete_on_close(cli, fnum1, true);
6101         if (!NT_STATUS_IS_OK(status)) {
6102                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6103                         __location__, fname_ln, nt_errstr(status));
6104                 return false;
6105         }
6106
6107         status = cli_close(cli, fnum1);
6108         if (!NT_STATUS_IS_OK(status)) {
6109                 printf("close %s failed (%s)\n",
6110                         fname_ln, nt_errstr(status));
6111                 return false;
6112         }
6113
6114         status = cli_close(cli, fnum);
6115         if (!NT_STATUS_IS_OK(status)) {
6116                 printf("close %s failed (%s)\n",
6117                         fname, nt_errstr(status));
6118                 return false;
6119         }
6120
6121         /* Ensure the original file is still there. */
6122         status = cli_getatr(cli, fname, NULL, NULL, &t);
6123         if (!NT_STATUS_IS_OK(status)) {
6124                 printf("%s getatr on file %s failed (%s)\n",
6125                         __location__,
6126                         fname,
6127                         nt_errstr(status));
6128                 correct = False;
6129         }
6130
6131         /* Ensure the link path is gone. */
6132         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6133         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6134                 printf("%s, getatr for file %s returned wrong error code %s "
6135                         "- should have been deleted\n",
6136                         __location__,
6137                         fname_ln, nt_errstr(status));
6138                 correct = False;
6139         }
6140
6141         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6142         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6143
6144         if (!torture_close_connection(cli)) {
6145                 correct = false;
6146         }
6147
6148         printf("finished deletetest-ln\n");
6149
6150         return correct;
6151 }
6152
6153 /*
6154   print out server properties
6155  */
6156 static bool run_properties(int dummy)
6157 {
6158         struct cli_state *cli;
6159         bool correct = True;
6160
6161         printf("starting properties test\n");
6162
6163         ZERO_STRUCT(cli);
6164
6165         if (!torture_open_connection(&cli, 0)) {
6166                 return False;
6167         }
6168
6169         smbXcli_conn_set_sockopt(cli->conn, sockops);
6170
6171         d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6172
6173         if (!torture_close_connection(cli)) {
6174                 correct = False;
6175         }
6176
6177         return correct;
6178 }
6179
6180
6181
6182 /* FIRST_DESIRED_ACCESS   0xf019f */
6183 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6184                                FILE_READ_EA|                           /* 0xf */ \
6185                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
6186                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
6187                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
6188                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
6189 /* SECOND_DESIRED_ACCESS  0xe0080 */
6190 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6191                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6192                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
6193
6194 #if 0
6195 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6196                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6197                                FILE_READ_DATA|\
6198                                WRITE_OWNER_ACCESS                      /* */
6199 #endif
6200
6201 /*
6202   Test ntcreate calls made by xcopy
6203  */
6204 static bool run_xcopy(int dummy)
6205 {
6206         static struct cli_state *cli1;
6207         const char *fname = "\\test.txt";
6208         bool correct = True;
6209         uint16_t fnum1, fnum2;
6210         NTSTATUS status;
6211
6212         printf("starting xcopy test\n");
6213
6214         if (!torture_open_connection(&cli1, 0)) {
6215                 return False;
6216         }
6217
6218         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6219                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6220                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6221         if (!NT_STATUS_IS_OK(status)) {
6222                 printf("First open failed - %s\n", nt_errstr(status));
6223                 return False;
6224         }
6225
6226         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6227                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6228                              FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6229         if (!NT_STATUS_IS_OK(status)) {
6230                 printf("second open failed - %s\n", nt_errstr(status));
6231                 return False;
6232         }
6233
6234         if (!torture_close_connection(cli1)) {
6235                 correct = False;
6236         }
6237
6238         return correct;
6239 }
6240
6241 /*
6242   Test rename on files open with share delete and no share delete.
6243  */
6244 static bool run_rename(int dummy)
6245 {
6246         static struct cli_state *cli1;
6247         const char *fname = "\\test.txt";
6248         const char *fname1 = "\\test1.txt";
6249         bool correct = True;
6250         uint16_t fnum1;
6251         uint32_t attr;
6252         NTSTATUS status;
6253
6254         printf("starting rename test\n");
6255
6256         if (!torture_open_connection(&cli1, 0)) {
6257                 return False;
6258         }
6259
6260         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6261         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6262
6263         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6264                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6265                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6266         if (!NT_STATUS_IS_OK(status)) {
6267                 printf("First open failed - %s\n", nt_errstr(status));
6268                 return False;
6269         }
6270
6271         status = cli_rename(cli1, fname, fname1, false);
6272         if (!NT_STATUS_IS_OK(status)) {
6273                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6274         } else {
6275                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6276                 correct = False;
6277         }
6278
6279         status = cli_close(cli1, fnum1);
6280         if (!NT_STATUS_IS_OK(status)) {
6281                 printf("close - 1 failed (%s)\n", nt_errstr(status));
6282                 return False;
6283         }
6284
6285         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6286         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6287         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6288 #if 0
6289                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
6290 #else
6291                               FILE_SHARE_DELETE|FILE_SHARE_READ,
6292 #endif
6293                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6294         if (!NT_STATUS_IS_OK(status)) {
6295                 printf("Second open failed - %s\n", nt_errstr(status));
6296                 return False;
6297         }
6298
6299         status = cli_rename(cli1, fname, fname1, false);
6300         if (!NT_STATUS_IS_OK(status)) {
6301                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6302                 correct = False;
6303         } else {
6304                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6305         }
6306
6307         status = cli_close(cli1, fnum1);
6308         if (!NT_STATUS_IS_OK(status)) {
6309                 printf("close - 2 failed (%s)\n", nt_errstr(status));
6310                 return False;
6311         }
6312
6313         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6314         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6315
6316         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6317                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6318                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6319         if (!NT_STATUS_IS_OK(status)) {
6320                 printf("Third open failed - %s\n", nt_errstr(status));
6321                 return False;
6322         }
6323
6324
6325         status = cli_rename(cli1, fname, fname1, false);
6326         if (!NT_STATUS_IS_OK(status)) {
6327                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6328                 correct = False;
6329         } else {
6330                 printf("Third rename succeeded (SHARE_NONE)\n");
6331         }
6332
6333         status = cli_close(cli1, fnum1);
6334         if (!NT_STATUS_IS_OK(status)) {
6335                 printf("close - 3 failed (%s)\n", nt_errstr(status));
6336                 return False;
6337         }
6338
6339         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6340         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6341
6342         /*----*/
6343
6344         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6345                               FILE_ATTRIBUTE_NORMAL,
6346                               FILE_SHARE_READ | FILE_SHARE_WRITE,
6347                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6348         if (!NT_STATUS_IS_OK(status)) {
6349                 printf("Fourth open failed - %s\n", nt_errstr(status));
6350                 return False;
6351         }
6352
6353         status = cli_rename(cli1, fname, fname1, false);
6354         if (!NT_STATUS_IS_OK(status)) {
6355                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6356         } else {
6357                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6358                 correct = False;
6359         }
6360
6361         status = cli_close(cli1, fnum1);
6362         if (!NT_STATUS_IS_OK(status)) {
6363                 printf("close - 4 failed (%s)\n", nt_errstr(status));
6364                 return False;
6365         }
6366
6367         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6368         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6369
6370         /*--*/
6371
6372         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6373                          FILE_ATTRIBUTE_NORMAL,
6374                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6375                          FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6376         if (!NT_STATUS_IS_OK(status)) {
6377                 printf("Fifth open failed - %s\n", nt_errstr(status));
6378                 return False;
6379         }
6380
6381         status = cli_rename(cli1, fname, fname1, false);
6382         if (!NT_STATUS_IS_OK(status)) {
6383                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6384                 correct = False;
6385         } else {
6386                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6387         }
6388
6389         /*--*/
6390         status = cli_close(cli1, fnum1);
6391         if (!NT_STATUS_IS_OK(status)) {
6392                 printf("close - 5 failed (%s)\n", nt_errstr(status));
6393                 return False;
6394         }
6395
6396         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6397         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6398         if (!NT_STATUS_IS_OK(status)) {
6399                 printf("getatr on file %s failed - %s ! \n",
6400                         fname1, nt_errstr(status));
6401                 correct = False;
6402         } else {
6403                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6404                         printf("Renamed file %s has wrong attr 0x%x "
6405                                 "(should be 0x%x)\n",
6406                                 fname1,
6407                                 attr,
6408                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6409                         correct = False;
6410                 } else {
6411                         printf("Renamed file %s has archive bit set\n", fname1);
6412                 }
6413         }
6414
6415         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6416         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6417
6418         if (!torture_close_connection(cli1)) {
6419                 correct = False;
6420         }
6421
6422         return correct;
6423 }
6424
6425 /*
6426   Test rename into a directory with an ACL denying it.
6427  */
6428 static bool run_rename_access(int dummy)
6429 {
6430         static struct cli_state *cli = NULL;
6431         static struct cli_state *posix_cli = NULL;
6432         const char *src = "test.txt";
6433         const char *dname = "dir";
6434         const char *dst = "dir\\test.txt";
6435         const char *dsrc = "test.dir";
6436         const char *ddst = "dir\\test.dir";
6437         uint16_t fnum = (uint16_t)-1;
6438         struct security_descriptor *sd = NULL;
6439         struct security_descriptor *newsd = NULL;
6440         NTSTATUS status;
6441         TALLOC_CTX *frame = NULL;
6442
6443         frame = talloc_stackframe();
6444         printf("starting rename access test\n");
6445
6446         /* Windows connection. */
6447         if (!torture_open_connection(&cli, 0)) {
6448                 goto fail;
6449         }
6450
6451         smbXcli_conn_set_sockopt(cli->conn, sockops);
6452
6453         /* Posix connection. */
6454         if (!torture_open_connection(&posix_cli, 0)) {
6455                 goto fail;
6456         }
6457
6458         smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6459
6460         status = torture_setup_unix_extensions(posix_cli);
6461         if (!NT_STATUS_IS_OK(status)) {
6462                 goto fail;
6463         }
6464
6465         /* Start with a clean slate. */
6466         cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6467         cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6468         cli_rmdir(cli, dsrc);
6469         cli_rmdir(cli, ddst);
6470         cli_rmdir(cli, dname);
6471
6472         /*
6473          * Setup the destination directory with a DENY ACE to
6474          * prevent new files within it.
6475          */
6476         status = cli_ntcreate(cli,
6477                                 dname,
6478                                 0,
6479                                 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6480                                         WRITE_DAC_ACCESS|FILE_READ_DATA|
6481                                         WRITE_OWNER_ACCESS,
6482                                 FILE_ATTRIBUTE_DIRECTORY,
6483                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6484                                 FILE_CREATE,
6485                                 FILE_DIRECTORY_FILE,
6486                                 0,
6487                                 &fnum,
6488                                 NULL);
6489         if (!NT_STATUS_IS_OK(status)) {
6490                 printf("Create of %s - %s\n", dname, nt_errstr(status));
6491                 goto fail;
6492         }
6493
6494         status = cli_query_secdesc(cli,
6495                                 fnum,
6496                                 frame,
6497                                 &sd);
6498         if (!NT_STATUS_IS_OK(status)) {
6499                 printf("cli_query_secdesc failed for %s (%s)\n",
6500                         dname, nt_errstr(status));
6501                 goto fail;
6502         }
6503
6504         newsd = security_descriptor_dacl_create(frame,
6505                                         0,
6506                                         NULL,
6507                                         NULL,
6508                                         SID_WORLD,
6509                                         SEC_ACE_TYPE_ACCESS_DENIED,
6510                                         SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6511                                         0,
6512                                         NULL);
6513         if (newsd == NULL) {
6514                 goto fail;
6515         }
6516         sd->dacl = security_acl_concatenate(frame,
6517                                         newsd->dacl,
6518                                         sd->dacl);
6519         if (sd->dacl == NULL) {
6520                 goto fail;
6521         }
6522         status = cli_set_secdesc(cli, fnum, sd);
6523         if (!NT_STATUS_IS_OK(status)) {
6524                 printf("cli_set_secdesc failed for %s (%s)\n",
6525                         dname, nt_errstr(status));
6526                 goto fail;
6527         }
6528         status = cli_close(cli, fnum);
6529         if (!NT_STATUS_IS_OK(status)) {
6530                 printf("close failed for %s (%s)\n",
6531                         dname, nt_errstr(status));
6532                 goto fail;
6533         }
6534         /* Now go around the back and chmod to 777 via POSIX. */
6535         status = cli_posix_chmod(posix_cli, dname, 0777);
6536         if (!NT_STATUS_IS_OK(status)) {
6537                 printf("cli_posix_chmod failed for %s (%s)\n",
6538                         dname, nt_errstr(status));
6539                 goto fail;
6540         }
6541
6542         /* Check we can't create a file within dname via Windows. */
6543         status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6544         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6545                 cli_close(posix_cli, fnum);
6546                 printf("Create of %s should be ACCESS denied, was %s\n",
6547                         dst, nt_errstr(status));
6548                 goto fail;
6549         }
6550
6551         /* Make the sample file/directory. */
6552         status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6553         if (!NT_STATUS_IS_OK(status)) {
6554                 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6555                 goto fail;
6556         }
6557         status = cli_close(cli, fnum);
6558         if (!NT_STATUS_IS_OK(status)) {
6559                 printf("cli_close failed (%s)\n", nt_errstr(status));
6560                 goto fail;
6561         }
6562
6563         status = cli_mkdir(cli, dsrc);
6564         if (!NT_STATUS_IS_OK(status)) {
6565                 printf("cli_mkdir of %s failed (%s)\n",
6566                         dsrc, nt_errstr(status));
6567                 goto fail;
6568         }
6569
6570         /*
6571          * OK - renames of the new file and directory into the
6572          * dst directory should fail.
6573          */
6574
6575         status = cli_rename(cli, src, dst, false);
6576         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6577                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6578                         src, dst, nt_errstr(status));
6579                 goto fail;
6580         }
6581         status = cli_rename(cli, dsrc, ddst, false);
6582         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6583                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6584                         src, dst, nt_errstr(status));
6585                 goto fail;
6586         }
6587
6588         TALLOC_FREE(frame);
6589         return true;
6590
6591   fail:
6592
6593         if (posix_cli) {
6594                 torture_close_connection(posix_cli);
6595         }
6596
6597         if (cli) {
6598                 if (fnum != (uint16_t)-1) {
6599                         cli_close(cli, fnum);
6600                 }
6601                 cli_unlink(cli, src,
6602                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6603                 cli_unlink(cli, dst,
6604                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6605                 cli_rmdir(cli, dsrc);
6606                 cli_rmdir(cli, ddst);
6607                 cli_rmdir(cli, dname);
6608
6609                 torture_close_connection(cli);
6610         }
6611
6612         TALLOC_FREE(frame);
6613         return false;
6614 }
6615
6616 /*
6617   Test owner rights ACE.
6618  */
6619 static bool run_owner_rights(int dummy)
6620 {
6621         static struct cli_state *cli = NULL;
6622         const char *fname = "owner_rights.txt";
6623         uint16_t fnum = (uint16_t)-1;
6624         struct security_descriptor *sd = NULL;
6625         struct security_descriptor *newsd = NULL;
6626         NTSTATUS status;
6627         TALLOC_CTX *frame = NULL;
6628
6629         frame = talloc_stackframe();
6630         printf("starting owner rights test\n");
6631
6632         /* Windows connection. */
6633         if (!torture_open_connection(&cli, 0)) {
6634                 goto fail;
6635         }
6636
6637         smbXcli_conn_set_sockopt(cli->conn, sockops);
6638
6639         /* Start with a clean slate. */
6640         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6641
6642         /* Create the test file. */
6643         /* Now try and open for read and write-dac. */
6644         status = cli_ntcreate(cli,
6645                                 fname,
6646                                 0,
6647                                 GENERIC_ALL_ACCESS,
6648                                 FILE_ATTRIBUTE_NORMAL,
6649                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6650                                         FILE_SHARE_DELETE,
6651                                 FILE_CREATE,
6652                                 0,
6653                                 0,
6654                                 &fnum,
6655                                 NULL);
6656         if (!NT_STATUS_IS_OK(status)) {
6657                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6658                 goto fail;
6659         }
6660
6661         /* Get the original SD. */
6662         status = cli_query_secdesc(cli,
6663                                 fnum,
6664                                 frame,
6665                                 &sd);
6666         if (!NT_STATUS_IS_OK(status)) {
6667                 printf("cli_query_secdesc failed for %s (%s)\n",
6668                         fname, nt_errstr(status));
6669                 goto fail;
6670         }
6671
6672         /*
6673          * Add an "owner-rights" ACE denying WRITE_DATA,
6674          * and an "owner-rights" ACE allowing READ_DATA.
6675          */
6676
6677         newsd = security_descriptor_dacl_create(frame,
6678                                         0,
6679                                         NULL,
6680                                         NULL,
6681                                         SID_OWNER_RIGHTS,
6682                                         SEC_ACE_TYPE_ACCESS_DENIED,
6683                                         FILE_WRITE_DATA,
6684                                         0,
6685                                         SID_OWNER_RIGHTS,
6686                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6687                                         FILE_READ_DATA,
6688                                         0,
6689                                         NULL);
6690         if (newsd == NULL) {
6691                 goto fail;
6692         }
6693         sd->dacl = security_acl_concatenate(frame,
6694                                         newsd->dacl,
6695                                         sd->dacl);
6696         if (sd->dacl == NULL) {
6697                 goto fail;
6698         }
6699         status = cli_set_secdesc(cli, fnum, sd);
6700         if (!NT_STATUS_IS_OK(status)) {
6701                 printf("cli_set_secdesc failed for %s (%s)\n",
6702                         fname, nt_errstr(status));
6703                 goto fail;
6704         }
6705         status = cli_close(cli, fnum);
6706         if (!NT_STATUS_IS_OK(status)) {
6707                 printf("close failed for %s (%s)\n",
6708                         fname, nt_errstr(status));
6709                 goto fail;
6710         }
6711         fnum = (uint16_t)-1;
6712
6713         /* Try and open for FILE_WRITE_DATA */
6714         status = cli_ntcreate(cli,
6715                                 fname,
6716                                 0,
6717                                 FILE_WRITE_DATA,
6718                                 FILE_ATTRIBUTE_NORMAL,
6719                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6720                                         FILE_SHARE_DELETE,
6721                                 FILE_OPEN,
6722                                 0,
6723                                 0,
6724                                 &fnum,
6725                                 NULL);
6726         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6727                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6728                 goto fail;
6729         }
6730
6731         /* Now try and open for FILE_READ_DATA */
6732         status = cli_ntcreate(cli,
6733                                 fname,
6734                                 0,
6735                                 FILE_READ_DATA,
6736                                 FILE_ATTRIBUTE_NORMAL,
6737                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6738                                         FILE_SHARE_DELETE,
6739                                 FILE_OPEN,
6740                                 0,
6741                                 0,
6742                                 &fnum,
6743                                 NULL);
6744         if (!NT_STATUS_IS_OK(status)) {
6745                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6746                 goto fail;
6747         }
6748
6749         status = cli_close(cli, fnum);
6750         if (!NT_STATUS_IS_OK(status)) {
6751                 printf("close failed for %s (%s)\n",
6752                         fname, nt_errstr(status));
6753                 goto fail;
6754         }
6755
6756         /* Restore clean slate. */
6757         TALLOC_FREE(sd);
6758         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6759
6760         /* Create the test file. */
6761         status = cli_ntcreate(cli,
6762                                 fname,
6763                                 0,
6764                                 GENERIC_ALL_ACCESS,
6765                                 FILE_ATTRIBUTE_NORMAL,
6766                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6767                                         FILE_SHARE_DELETE,
6768                                 FILE_CREATE,
6769                                 0,
6770                                 0,
6771                                 &fnum,
6772                                 NULL);
6773         if (!NT_STATUS_IS_OK(status)) {
6774                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6775                 goto fail;
6776         }
6777
6778         /* Get the original SD. */
6779         status = cli_query_secdesc(cli,
6780                                 fnum,
6781                                 frame,
6782                                 &sd);
6783         if (!NT_STATUS_IS_OK(status)) {
6784                 printf("cli_query_secdesc failed for %s (%s)\n",
6785                         fname, nt_errstr(status));
6786                 goto fail;
6787         }
6788
6789         /*
6790          * Add an "owner-rights ACE denying WRITE_DATA,
6791          * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6792          */
6793
6794         newsd = security_descriptor_dacl_create(frame,
6795                                         0,
6796                                         NULL,
6797                                         NULL,
6798                                         SID_OWNER_RIGHTS,
6799                                         SEC_ACE_TYPE_ACCESS_DENIED,
6800                                         FILE_WRITE_DATA,
6801                                         0,
6802                                         SID_OWNER_RIGHTS,
6803                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6804                                         FILE_READ_DATA|FILE_WRITE_DATA,
6805                                         0,
6806                                         NULL);
6807         if (newsd == NULL) {
6808                 goto fail;
6809         }
6810         sd->dacl = security_acl_concatenate(frame,
6811                                         newsd->dacl,
6812                                         sd->dacl);
6813         if (sd->dacl == NULL) {
6814                 goto fail;
6815         }
6816         status = cli_set_secdesc(cli, fnum, sd);
6817         if (!NT_STATUS_IS_OK(status)) {
6818                 printf("cli_set_secdesc failed for %s (%s)\n",
6819                         fname, nt_errstr(status));
6820                 goto fail;
6821         }
6822         status = cli_close(cli, fnum);
6823         if (!NT_STATUS_IS_OK(status)) {
6824                 printf("close failed for %s (%s)\n",
6825                         fname, nt_errstr(status));
6826                 goto fail;
6827         }
6828         fnum = (uint16_t)-1;
6829
6830         /* Try and open for FILE_WRITE_DATA */
6831         status = cli_ntcreate(cli,
6832                                 fname,
6833                                 0,
6834                                 FILE_WRITE_DATA,
6835                                 FILE_ATTRIBUTE_NORMAL,
6836                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6837                                         FILE_SHARE_DELETE,
6838                                 FILE_OPEN,
6839                                 0,
6840                                 0,
6841                                 &fnum,
6842                                 NULL);
6843         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6844                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6845                 goto fail;
6846         }
6847
6848         /* Now try and open for FILE_READ_DATA */
6849         status = cli_ntcreate(cli,
6850                                 fname,
6851                                 0,
6852                                 FILE_READ_DATA,
6853                                 FILE_ATTRIBUTE_NORMAL,
6854                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6855                                         FILE_SHARE_DELETE,
6856                                 FILE_OPEN,
6857                                 0,
6858                                 0,
6859                                 &fnum,
6860                                 NULL);
6861         if (!NT_STATUS_IS_OK(status)) {
6862                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6863                 goto fail;
6864         }
6865
6866         status = cli_close(cli, fnum);
6867         if (!NT_STATUS_IS_OK(status)) {
6868                 printf("close failed for %s (%s)\n",
6869                         fname, nt_errstr(status));
6870                 goto fail;
6871         }
6872
6873         /* Restore clean slate. */
6874         TALLOC_FREE(sd);
6875         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6876
6877
6878         /* Create the test file. */
6879         status = cli_ntcreate(cli,
6880                                 fname,
6881                                 0,
6882                                 GENERIC_ALL_ACCESS,
6883                                 FILE_ATTRIBUTE_NORMAL,
6884                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6885                                         FILE_SHARE_DELETE,
6886                                 FILE_CREATE,
6887                                 0,
6888                                 0,
6889                                 &fnum,
6890                                 NULL);
6891         if (!NT_STATUS_IS_OK(status)) {
6892                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6893                 goto fail;
6894         }
6895
6896         /* Get the original SD. */
6897         status = cli_query_secdesc(cli,
6898                                 fnum,
6899                                 frame,
6900                                 &sd);
6901         if (!NT_STATUS_IS_OK(status)) {
6902                 printf("cli_query_secdesc failed for %s (%s)\n",
6903                         fname, nt_errstr(status));
6904                 goto fail;
6905         }
6906
6907         /*
6908          * Add an "authenticated users" ACE allowing READ_DATA,
6909          * add an "owner-rights" denying READ_DATA,
6910          * and an "authenticated users" ACE allowing WRITE_DATA.
6911          */
6912
6913         newsd = security_descriptor_dacl_create(frame,
6914                                         0,
6915                                         NULL,
6916                                         NULL,
6917                                         SID_NT_AUTHENTICATED_USERS,
6918                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6919                                         FILE_READ_DATA,
6920                                         0,
6921                                         SID_OWNER_RIGHTS,
6922                                         SEC_ACE_TYPE_ACCESS_DENIED,
6923                                         FILE_READ_DATA,
6924                                         0,
6925                                         SID_NT_AUTHENTICATED_USERS,
6926                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6927                                         FILE_WRITE_DATA,
6928                                         0,
6929                                         NULL);
6930         if (newsd == NULL) {
6931                 printf("newsd == NULL\n");
6932                 goto fail;
6933         }
6934         sd->dacl = security_acl_concatenate(frame,
6935                                         newsd->dacl,
6936                                         sd->dacl);
6937         if (sd->dacl == NULL) {
6938                 printf("sd->dacl == NULL\n");
6939                 goto fail;
6940         }
6941         status = cli_set_secdesc(cli, fnum, sd);
6942         if (!NT_STATUS_IS_OK(status)) {
6943                 printf("cli_set_secdesc failed for %s (%s)\n",
6944                         fname, nt_errstr(status));
6945                 goto fail;
6946         }
6947         status = cli_close(cli, fnum);
6948         if (!NT_STATUS_IS_OK(status)) {
6949                 printf("close failed for %s (%s)\n",
6950                         fname, nt_errstr(status));
6951                 goto fail;
6952         }
6953         fnum = (uint16_t)-1;
6954
6955         /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
6956         status = cli_ntcreate(cli,
6957                                 fname,
6958                                 0,
6959                                 FILE_READ_DATA|FILE_WRITE_DATA,
6960                                 FILE_ATTRIBUTE_NORMAL,
6961                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6962                                         FILE_SHARE_DELETE,
6963                                 FILE_OPEN,
6964                                 0,
6965                                 0,
6966                                 &fnum,
6967                                 NULL);
6968         if (!NT_STATUS_IS_OK(status)) {
6969                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6970                 goto fail;
6971         }
6972
6973         status = cli_close(cli, fnum);
6974         if (!NT_STATUS_IS_OK(status)) {
6975                 printf("close failed for %s (%s)\n",
6976                         fname, nt_errstr(status));
6977                 goto fail;
6978         }
6979
6980         cli_unlink(cli, fname,
6981                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6982
6983         TALLOC_FREE(frame);
6984         return true;
6985
6986   fail:
6987
6988         if (cli) {
6989                 if (fnum != (uint16_t)-1) {
6990                         cli_close(cli, fnum);
6991                 }
6992                 cli_unlink(cli, fname,
6993                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6994                 torture_close_connection(cli);
6995         }
6996
6997         TALLOC_FREE(frame);
6998         return false;
6999 }
7000
7001 /*
7002  * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7003  * Note this test only works with a user with SeSecurityPrivilege set.
7004  *
7005  * NB. This is also tested in samba3.base.createx_access
7006  * but this makes it very explicit what we're looking for.
7007  */
7008 static bool run_smb1_system_security(int dummy)
7009 {
7010         static struct cli_state *cli = NULL;
7011         const char *fname = "system_security.txt";
7012         uint16_t fnum = (uint16_t)-1;
7013         NTSTATUS status;
7014         TALLOC_CTX *frame = NULL;
7015
7016         frame = talloc_stackframe();
7017         printf("starting smb1 system security test\n");
7018
7019         /* SMB1 connection - torture_open_connection() forces this. */
7020         if (!torture_open_connection(&cli, 0)) {
7021                 goto fail;
7022         }
7023
7024         smbXcli_conn_set_sockopt(cli->conn, sockops);
7025
7026         /* Start with a clean slate. */
7027         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7028
7029         /* Create the test file. */
7030         status = cli_ntcreate(cli,
7031                                 fname,
7032                                 0,
7033                                 GENERIC_ALL_ACCESS,
7034                                 FILE_ATTRIBUTE_NORMAL,
7035                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7036                                         FILE_SHARE_DELETE,
7037                                 FILE_CREATE,
7038                                 0,
7039                                 0,
7040                                 &fnum,
7041                                 NULL);
7042         if (!NT_STATUS_IS_OK(status)) {
7043                 printf("Create of %s - %s\n", fname, nt_errstr(status));
7044                 goto fail;
7045         }
7046
7047         status = cli_close(cli, fnum);
7048
7049         /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7050         /*
7051          * On SMB1 this succeeds - SMB2 it fails,
7052          * see the SMB2-SACL test.
7053          */
7054         status = cli_ntcreate(cli,
7055                                 fname,
7056                                 0,
7057                                 SEC_FLAG_SYSTEM_SECURITY,
7058                                 FILE_ATTRIBUTE_NORMAL,
7059                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7060                                         FILE_SHARE_DELETE,
7061                                 FILE_OPEN,
7062                                 0,
7063                                 0,
7064                                 &fnum,
7065                                 NULL);
7066         if (!NT_STATUS_IS_OK(status)) {
7067                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7068                 goto fail;
7069         }
7070
7071         status = cli_close(cli, fnum);
7072
7073         cli_unlink(cli, fname,
7074                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7075
7076         torture_close_connection(cli);
7077         TALLOC_FREE(frame);
7078         return true;
7079
7080   fail:
7081
7082         if (cli) {
7083                 if (fnum != (uint16_t)-1) {
7084                         cli_close(cli, fnum);
7085                 }
7086                 cli_unlink(cli, fname,
7087                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7088                 torture_close_connection(cli);
7089         }
7090
7091         TALLOC_FREE(frame);
7092         return false;
7093 }
7094
7095 static bool run_pipe_number(int dummy)
7096 {
7097         struct cli_state *cli1;
7098         const char *pipe_name = "\\SPOOLSS";
7099         uint16_t fnum;
7100         int num_pipes = 0;
7101         NTSTATUS status;
7102
7103         printf("starting pipenumber test\n");
7104         if (!torture_open_connection(&cli1, 0)) {
7105                 return False;
7106         }
7107
7108         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7109         while(1) {
7110                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7111                                       FILE_ATTRIBUTE_NORMAL,
7112                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
7113                                       FILE_OPEN_IF, 0, 0, &fnum, NULL);
7114                 if (!NT_STATUS_IS_OK(status)) {
7115                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7116                         break;
7117                 }
7118                 num_pipes++;
7119                 printf("\r%6d", num_pipes);
7120         }
7121
7122         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7123         torture_close_connection(cli1);
7124         return True;
7125 }
7126
7127 /*
7128   Test open mode returns on read-only files.
7129  */
7130 static bool run_opentest(int dummy)
7131 {
7132         static struct cli_state *cli1;
7133         static struct cli_state *cli2;
7134         const char *fname = "\\readonly.file";
7135         uint16_t fnum1, fnum2;
7136         char buf[20];
7137         off_t fsize;
7138         bool correct = True;
7139         char *tmp_path;
7140         NTSTATUS status;
7141
7142         printf("starting open test\n");
7143
7144         if (!torture_open_connection(&cli1, 0)) {
7145                 return False;
7146         }
7147
7148         cli_setatr(cli1, fname, 0, 0);
7149         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7150
7151         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7152
7153         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7154         if (!NT_STATUS_IS_OK(status)) {
7155                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7156                 return False;
7157         }
7158
7159         status = cli_close(cli1, fnum1);
7160         if (!NT_STATUS_IS_OK(status)) {
7161                 printf("close2 failed (%s)\n", nt_errstr(status));
7162                 return False;
7163         }
7164
7165         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7166         if (!NT_STATUS_IS_OK(status)) {
7167                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7168                 return False;
7169         }
7170
7171         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7172         if (!NT_STATUS_IS_OK(status)) {
7173                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7174                 return False;
7175         }
7176
7177         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7178         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7179
7180         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7181                         NT_STATUS_ACCESS_DENIED)) {
7182                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7183         }
7184
7185         printf("finished open test 1\n");
7186
7187         cli_close(cli1, fnum1);
7188
7189         /* Now try not readonly and ensure ERRbadshare is returned. */
7190
7191         cli_setatr(cli1, fname, 0, 0);
7192
7193         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7194         if (!NT_STATUS_IS_OK(status)) {
7195                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7196                 return False;
7197         }
7198
7199         /* This will fail - but the error should be ERRshare. */
7200         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7201
7202         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7203                         NT_STATUS_SHARING_VIOLATION)) {
7204                 printf("correct error code ERRDOS/ERRbadshare returned\n");
7205         }
7206
7207         status = cli_close(cli1, fnum1);
7208         if (!NT_STATUS_IS_OK(status)) {
7209                 printf("close2 failed (%s)\n", nt_errstr(status));
7210                 return False;
7211         }
7212
7213         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7214
7215         printf("finished open test 2\n");
7216
7217         /* Test truncate open disposition on file opened for read. */
7218         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7219         if (!NT_STATUS_IS_OK(status)) {
7220                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7221                 return False;
7222         }
7223
7224         /* write 20 bytes. */
7225
7226         memset(buf, '\0', 20);
7227
7228         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7229         if (!NT_STATUS_IS_OK(status)) {
7230                 printf("write failed (%s)\n", nt_errstr(status));
7231                 correct = False;
7232         }
7233
7234         status = cli_close(cli1, fnum1);
7235         if (!NT_STATUS_IS_OK(status)) {
7236                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7237                 return False;
7238         }
7239
7240         /* Ensure size == 20. */
7241         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7242         if (!NT_STATUS_IS_OK(status)) {
7243                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7244                 return False;
7245         }
7246
7247         if (fsize != 20) {
7248                 printf("(3) file size != 20\n");
7249                 return False;
7250         }
7251
7252         /* Now test if we can truncate a file opened for readonly. */
7253         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7254         if (!NT_STATUS_IS_OK(status)) {
7255                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7256                 return False;
7257         }
7258
7259         status = cli_close(cli1, fnum1);
7260         if (!NT_STATUS_IS_OK(status)) {
7261                 printf("close2 failed (%s)\n", nt_errstr(status));
7262                 return False;
7263         }
7264
7265         /* Ensure size == 0. */
7266         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7267         if (!NT_STATUS_IS_OK(status)) {
7268                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7269                 return False;
7270         }
7271
7272         if (fsize != 0) {
7273                 printf("(3) file size != 0\n");
7274                 return False;
7275         }
7276         printf("finished open test 3\n");
7277
7278         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7279
7280         printf("Do ctemp tests\n");
7281         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7282         if (!NT_STATUS_IS_OK(status)) {
7283                 printf("ctemp failed (%s)\n", nt_errstr(status));
7284                 return False;
7285         }
7286
7287         printf("ctemp gave path %s\n", tmp_path);
7288         status = cli_close(cli1, fnum1);
7289         if (!NT_STATUS_IS_OK(status)) {
7290                 printf("close of temp failed (%s)\n", nt_errstr(status));
7291         }
7292
7293         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7294         if (!NT_STATUS_IS_OK(status)) {
7295                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7296         }
7297
7298         /* Test the non-io opens... */
7299
7300         if (!torture_open_connection(&cli2, 1)) {
7301                 return False;
7302         }
7303
7304         cli_setatr(cli2, fname, 0, 0);
7305         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7306
7307         smbXcli_conn_set_sockopt(cli2->conn, sockops);
7308
7309         printf("TEST #1 testing 2 non-io opens (no delete)\n");
7310         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7311                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7312                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7313         if (!NT_STATUS_IS_OK(status)) {
7314                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7315                 return False;
7316         }
7317
7318         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7319                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7320                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7321         if (!NT_STATUS_IS_OK(status)) {
7322                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7323                 return False;
7324         }
7325
7326         status = cli_close(cli1, fnum1);
7327         if (!NT_STATUS_IS_OK(status)) {
7328                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7329                 return False;
7330         }
7331
7332         status = cli_close(cli2, fnum2);
7333         if (!NT_STATUS_IS_OK(status)) {
7334                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7335                 return False;
7336         }
7337
7338         printf("non-io open test #1 passed.\n");
7339
7340         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7341
7342         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7343
7344         status = cli_ntcreate(cli1, fname, 0,
7345                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7346                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7347                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7348         if (!NT_STATUS_IS_OK(status)) {
7349                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7350                 return False;
7351         }
7352
7353         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7354                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7355                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7356         if (!NT_STATUS_IS_OK(status)) {
7357                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7358                 return False;
7359         }
7360
7361         status = cli_close(cli1, fnum1);
7362         if (!NT_STATUS_IS_OK(status)) {
7363                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7364                 return False;
7365         }
7366
7367         status = cli_close(cli2, fnum2);
7368         if (!NT_STATUS_IS_OK(status)) {
7369                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7370                 return False;
7371         }
7372
7373         printf("non-io open test #2 passed.\n");
7374
7375         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7376
7377         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7378
7379         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7380                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7381                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7382         if (!NT_STATUS_IS_OK(status)) {
7383                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7384                 return False;
7385         }
7386
7387         status = cli_ntcreate(cli2, fname, 0,
7388                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7389                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7390                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7391         if (!NT_STATUS_IS_OK(status)) {
7392                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7393                 return False;
7394         }
7395
7396         status = cli_close(cli1, fnum1);
7397         if (!NT_STATUS_IS_OK(status)) {
7398                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7399                 return False;
7400         }
7401
7402         status = cli_close(cli2, fnum2);
7403         if (!NT_STATUS_IS_OK(status)) {
7404                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7405                 return False;
7406         }
7407
7408         printf("non-io open test #3 passed.\n");
7409
7410         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7411
7412         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7413
7414         status = cli_ntcreate(cli1, fname, 0,
7415                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7416                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7417                                FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7418         if (!NT_STATUS_IS_OK(status)) {
7419                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7420                 return False;
7421         }
7422
7423         status = cli_ntcreate(cli2, fname, 0,
7424                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7425                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7426                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7427         if (NT_STATUS_IS_OK(status)) {
7428                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7429                 return False;
7430         }
7431
7432         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7433
7434         status = cli_close(cli1, fnum1);
7435         if (!NT_STATUS_IS_OK(status)) {
7436                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7437                 return False;
7438         }
7439
7440         printf("non-io open test #4 passed.\n");
7441
7442         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7443
7444         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7445
7446         status = cli_ntcreate(cli1, fname, 0,
7447                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7448                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7449                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7450         if (!NT_STATUS_IS_OK(status)) {
7451                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7452                 return False;
7453         }
7454
7455         status = cli_ntcreate(cli2, fname, 0,
7456                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7457                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7458                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7459         if (!NT_STATUS_IS_OK(status)) {
7460                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7461                 return False;
7462         }
7463
7464         status = cli_close(cli1, fnum1);
7465         if (!NT_STATUS_IS_OK(status)) {
7466                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7467                 return False;
7468         }
7469
7470         status = cli_close(cli2, fnum2);
7471         if (!NT_STATUS_IS_OK(status)) {
7472                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7473                 return False;
7474         }
7475
7476         printf("non-io open test #5 passed.\n");
7477
7478         printf("TEST #6 testing 1 non-io open, one io open\n");
7479
7480         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7481
7482         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7483                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7484                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7485         if (!NT_STATUS_IS_OK(status)) {
7486                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7487                 return False;
7488         }
7489
7490         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7491                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7492                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7493         if (!NT_STATUS_IS_OK(status)) {
7494                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7495                 return False;
7496         }
7497
7498         status = cli_close(cli1, fnum1);
7499         if (!NT_STATUS_IS_OK(status)) {
7500                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7501                 return False;
7502         }
7503
7504         status = cli_close(cli2, fnum2);
7505         if (!NT_STATUS_IS_OK(status)) {
7506                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7507                 return False;
7508         }
7509
7510         printf("non-io open test #6 passed.\n");
7511
7512         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7513
7514         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7515
7516         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7517                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7518                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7519         if (!NT_STATUS_IS_OK(status)) {
7520                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7521                 return False;
7522         }
7523
7524         status = cli_ntcreate(cli2, fname, 0,
7525                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7526                               FILE_ATTRIBUTE_NORMAL,
7527                               FILE_SHARE_READ|FILE_SHARE_DELETE,
7528                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7529         if (NT_STATUS_IS_OK(status)) {
7530                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7531                 return False;
7532         }
7533
7534         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7535
7536         status = cli_close(cli1, fnum1);
7537         if (!NT_STATUS_IS_OK(status)) {
7538                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7539                 return False;
7540         }
7541
7542         printf("non-io open test #7 passed.\n");
7543
7544         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7545
7546         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7547         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7548                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7549                                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7550         if (!NT_STATUS_IS_OK(status)) {
7551                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7552                 correct = false;
7553                 goto out;
7554         }
7555
7556         /* Write to ensure we have to update the file time. */
7557         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7558                               NULL);
7559         if (!NT_STATUS_IS_OK(status)) {
7560                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7561                 correct = false;
7562                 goto out;
7563         }
7564
7565         status = cli_close(cli1, fnum1);
7566         if (!NT_STATUS_IS_OK(status)) {
7567                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7568                 correct = false;
7569         }
7570
7571   out:
7572
7573         if (!torture_close_connection(cli1)) {
7574                 correct = False;
7575         }
7576         if (!torture_close_connection(cli2)) {
7577                 correct = False;
7578         }
7579
7580         return correct;
7581 }
7582
7583 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7584 {
7585         uint16_t major, minor;
7586         uint32_t caplow, caphigh;
7587         NTSTATUS status;
7588
7589         if (!SERVER_HAS_UNIX_CIFS(cli)) {
7590                 printf("Server doesn't support UNIX CIFS extensions.\n");
7591                 return NT_STATUS_NOT_SUPPORTED;
7592         }
7593
7594         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7595                                              &caphigh);
7596         if (!NT_STATUS_IS_OK(status)) {
7597                 printf("Server didn't return UNIX CIFS extensions: %s\n",
7598                        nt_errstr(status));
7599                 return status;
7600         }
7601
7602         status = cli_set_unix_extensions_capabilities(cli, major, minor,
7603                                                       caplow, caphigh);
7604         if (!NT_STATUS_IS_OK(status)) {
7605                 printf("Server doesn't support setting UNIX CIFS extensions: "
7606                        "%s.\n", nt_errstr(status));
7607                 return status;
7608         }
7609
7610         return NT_STATUS_OK;
7611 }
7612
7613 /*
7614   Test POSIX open /mkdir calls.
7615  */
7616 static bool run_simple_posix_open_test(int dummy)
7617 {
7618         static struct cli_state *cli1;
7619         const char *fname = "posix:file";
7620         const char *hname = "posix:hlink";
7621         const char *sname = "posix:symlink";
7622         const char *dname = "posix:dir";
7623         char buf[10];
7624         char *target = NULL;
7625         uint16_t fnum1 = (uint16_t)-1;
7626         SMB_STRUCT_STAT sbuf;
7627         bool correct = false;
7628         NTSTATUS status;
7629         size_t nread;
7630         const char *fname_windows = "windows_file";
7631         uint16_t fnum2 = (uint16_t)-1;
7632
7633         printf("Starting simple POSIX open test\n");
7634
7635         if (!torture_open_connection(&cli1, 0)) {
7636                 return false;
7637         }
7638
7639         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7640
7641         status = torture_setup_unix_extensions(cli1);
7642         if (!NT_STATUS_IS_OK(status)) {
7643                 return false;
7644         }
7645
7646         cli_setatr(cli1, fname, 0, 0);
7647         cli_posix_unlink(cli1, fname);
7648         cli_setatr(cli1, dname, 0, 0);
7649         cli_posix_rmdir(cli1, dname);
7650         cli_setatr(cli1, hname, 0, 0);
7651         cli_posix_unlink(cli1, hname);
7652         cli_setatr(cli1, sname, 0, 0);
7653         cli_posix_unlink(cli1, sname);
7654         cli_setatr(cli1, fname_windows, 0, 0);
7655         cli_posix_unlink(cli1, fname_windows);
7656
7657         /* Create a directory. */
7658         status = cli_posix_mkdir(cli1, dname, 0777);
7659         if (!NT_STATUS_IS_OK(status)) {
7660                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7661                 goto out;
7662         }
7663
7664         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7665                                 0600, &fnum1);
7666         if (!NT_STATUS_IS_OK(status)) {
7667                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7668                 goto out;
7669         }
7670
7671         /* Test ftruncate - set file size. */
7672         status = cli_ftruncate(cli1, fnum1, 1000);
7673         if (!NT_STATUS_IS_OK(status)) {
7674                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7675                 goto out;
7676         }
7677
7678         /* Ensure st_size == 1000 */
7679         status = cli_posix_stat(cli1, fname, &sbuf);
7680         if (!NT_STATUS_IS_OK(status)) {
7681                 printf("stat failed (%s)\n", nt_errstr(status));
7682                 goto out;
7683         }
7684
7685         if (sbuf.st_ex_size != 1000) {
7686                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7687                 goto out;
7688         }
7689
7690         /* Ensure st_mode == 0600 */
7691         if ((sbuf.st_ex_mode & 07777) != 0600) {
7692                 printf("posix_open - bad permissions 0%o != 0600\n",
7693                                 (unsigned int)(sbuf.st_ex_mode & 07777));
7694                 goto out;
7695         }
7696
7697         /* Test ftruncate - set file size back to zero. */
7698         status = cli_ftruncate(cli1, fnum1, 0);
7699         if (!NT_STATUS_IS_OK(status)) {
7700                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7701                 goto out;
7702         }
7703
7704         status = cli_close(cli1, fnum1);
7705         if (!NT_STATUS_IS_OK(status)) {
7706                 printf("close failed (%s)\n", nt_errstr(status));
7707                 goto out;
7708         }
7709
7710         /* Now open the file again for read only. */
7711         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7712         if (!NT_STATUS_IS_OK(status)) {
7713                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7714                 goto out;
7715         }
7716
7717         /* Now unlink while open. */
7718         status = cli_posix_unlink(cli1, fname);
7719         if (!NT_STATUS_IS_OK(status)) {
7720                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7721                 goto out;
7722         }
7723
7724         status = cli_close(cli1, fnum1);
7725         if (!NT_STATUS_IS_OK(status)) {
7726                 printf("close(2) failed (%s)\n", nt_errstr(status));
7727                 goto out;
7728         }
7729
7730         /* Ensure the file has gone. */
7731         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7732         if (NT_STATUS_IS_OK(status)) {
7733                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7734                 goto out;
7735         }
7736
7737         /* Create again to test open with O_TRUNC. */
7738         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7739         if (!NT_STATUS_IS_OK(status)) {
7740                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7741                 goto out;
7742         }
7743
7744         /* Test ftruncate - set file size. */
7745         status = cli_ftruncate(cli1, fnum1, 1000);
7746         if (!NT_STATUS_IS_OK(status)) {
7747                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7748                 goto out;
7749         }
7750
7751         /* Ensure st_size == 1000 */
7752         status = cli_posix_stat(cli1, fname, &sbuf);
7753         if (!NT_STATUS_IS_OK(status)) {
7754                 printf("stat failed (%s)\n", nt_errstr(status));
7755                 goto out;
7756         }
7757
7758         if (sbuf.st_ex_size != 1000) {
7759                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7760                 goto out;
7761         }
7762
7763         status = cli_close(cli1, fnum1);
7764         if (!NT_STATUS_IS_OK(status)) {
7765                 printf("close(2) failed (%s)\n", nt_errstr(status));
7766                 goto out;
7767         }
7768
7769         /* Re-open with O_TRUNC. */
7770         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7771         if (!NT_STATUS_IS_OK(status)) {
7772                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7773                 goto out;
7774         }
7775
7776         /* Ensure st_size == 0 */
7777         status = cli_posix_stat(cli1, fname, &sbuf);
7778         if (!NT_STATUS_IS_OK(status)) {
7779                 printf("stat failed (%s)\n", nt_errstr(status));
7780                 goto out;
7781         }
7782
7783         if (sbuf.st_ex_size != 0) {
7784                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7785                 goto out;
7786         }
7787
7788         status = cli_close(cli1, fnum1);
7789         if (!NT_STATUS_IS_OK(status)) {
7790                 printf("close failed (%s)\n", nt_errstr(status));
7791                 goto out;
7792         }
7793
7794         status = cli_posix_unlink(cli1, fname);
7795         if (!NT_STATUS_IS_OK(status)) {
7796                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7797                 goto out;
7798         }
7799
7800         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
7801         if (!NT_STATUS_IS_OK(status)) {
7802                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
7803                         dname, nt_errstr(status));
7804                 goto out;
7805         }
7806
7807         cli_close(cli1, fnum1);
7808
7809         /* What happens when we try and POSIX open a directory for write ? */
7810         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
7811         if (NT_STATUS_IS_OK(status)) {
7812                 printf("POSIX open of directory %s succeeded, "
7813                        "should have failed.\n",
7814                        dname);
7815                 goto out;
7816         } else {
7817                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
7818                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
7819                         goto out;
7820                 }
7821         }
7822
7823         /* Create the file. */
7824         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7825                                 0600, &fnum1);
7826         if (!NT_STATUS_IS_OK(status)) {
7827                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7828                 goto out;
7829         }
7830
7831         /* Write some data into it. */
7832         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7833                               NULL);
7834         if (!NT_STATUS_IS_OK(status)) {
7835                 printf("cli_write failed: %s\n", nt_errstr(status));
7836                 goto out;
7837         }
7838
7839         cli_close(cli1, fnum1);
7840
7841         /* Now create a hardlink. */
7842         status = cli_posix_hardlink(cli1, fname, hname);
7843         if (!NT_STATUS_IS_OK(status)) {
7844                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
7845                 goto out;
7846         }
7847
7848         /* Now create a symlink. */
7849         status = cli_posix_symlink(cli1, fname, sname);
7850         if (!NT_STATUS_IS_OK(status)) {
7851                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
7852                 goto out;
7853         }
7854
7855         /* Open the hardlink for read. */
7856         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
7857         if (!NT_STATUS_IS_OK(status)) {
7858                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
7859                 goto out;
7860         }
7861
7862         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
7863         if (!NT_STATUS_IS_OK(status)) {
7864                 printf("POSIX read of %s failed (%s)\n", hname,
7865                        nt_errstr(status));
7866                 goto out;
7867         } else if (nread != 10) {
7868                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
7869                        hname, (unsigned long)nread, 10);
7870                 goto out;
7871         }
7872
7873         if (memcmp(buf, "TEST DATA\n", 10)) {
7874                 printf("invalid data read from hardlink\n");
7875                 goto out;
7876         }
7877
7878         /* Do a POSIX lock/unlock. */
7879         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
7880         if (!NT_STATUS_IS_OK(status)) {
7881                 printf("POSIX lock failed %s\n", nt_errstr(status));
7882                 goto out;
7883         }
7884
7885         /* Punch a hole in the locked area. */
7886         status = cli_posix_unlock(cli1, fnum1, 10, 80);
7887         if (!NT_STATUS_IS_OK(status)) {
7888                 printf("POSIX unlock failed %s\n", nt_errstr(status));
7889                 goto out;
7890         }
7891
7892         cli_close(cli1, fnum1);
7893
7894         /* Open the symlink for read - this should fail. A POSIX
7895            client should not be doing opens on a symlink. */
7896         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
7897         if (NT_STATUS_IS_OK(status)) {
7898                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
7899                 goto out;
7900         } else {
7901                 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
7902                                 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
7903                         printf("POSIX open of %s should have failed "
7904                                 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
7905                                 "failed with %s instead.\n",
7906                                 sname, nt_errstr(status));
7907                         goto out;
7908                 }
7909         }
7910
7911         status = cli_posix_readlink(cli1, sname, talloc_tos(), &target);
7912         if (!NT_STATUS_IS_OK(status)) {
7913                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
7914                 goto out;
7915         }
7916
7917         if (strcmp(target, fname) != 0) {
7918                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
7919                         sname, fname, target);
7920                 goto out;
7921         }
7922
7923         status = cli_posix_rmdir(cli1, dname);
7924         if (!NT_STATUS_IS_OK(status)) {
7925                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
7926                 goto out;
7927         }
7928
7929         /* Check directory opens with a specific permission. */
7930         status = cli_posix_mkdir(cli1, dname, 0700);
7931         if (!NT_STATUS_IS_OK(status)) {
7932                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7933                 goto out;
7934         }
7935
7936         /* Ensure st_mode == 0700 */
7937         status = cli_posix_stat(cli1, dname, &sbuf);
7938         if (!NT_STATUS_IS_OK(status)) {
7939                 printf("stat failed (%s)\n", nt_errstr(status));
7940                 goto out;
7941         }
7942
7943         if ((sbuf.st_ex_mode & 07777) != 0700) {
7944                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
7945                                 (unsigned int)(sbuf.st_ex_mode & 07777));
7946                 goto out;
7947         }
7948
7949         /*
7950          * Now create a Windows file, and attempt a POSIX unlink.
7951          * This should fail with a sharing violation but due to:
7952          *
7953          * [Bug 9571] Unlink after open causes smbd to panic
7954          *
7955          * ensure we've fixed the lock ordering violation.
7956          */
7957
7958         status = cli_ntcreate(cli1, fname_windows, 0,
7959                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
7960                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7961                         FILE_CREATE,
7962                         0x0, 0x0, &fnum2, NULL);
7963         if (!NT_STATUS_IS_OK(status)) {
7964                 printf("Windows create of %s failed (%s)\n", fname_windows,
7965                         nt_errstr(status));
7966                 goto out;
7967         }
7968
7969         /* Now try posix_unlink. */
7970         status = cli_posix_unlink(cli1, fname_windows);
7971         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7972                 printf("POSIX unlink of %s should fail "
7973                         "with NT_STATUS_SHARING_VIOLATION "
7974                         "got %s instead !\n",
7975                         fname_windows,
7976                         nt_errstr(status));
7977                 goto out;
7978         }
7979
7980         cli_close(cli1, fnum2);
7981
7982         printf("Simple POSIX open test passed\n");
7983         correct = true;
7984
7985   out:
7986
7987         if (fnum1 != (uint16_t)-1) {
7988                 cli_close(cli1, fnum1);
7989                 fnum1 = (uint16_t)-1;
7990         }
7991
7992         if (fnum2 != (uint16_t)-1) {
7993                 cli_close(cli1, fnum2);
7994                 fnum2 = (uint16_t)-1;
7995         }
7996
7997         cli_setatr(cli1, sname, 0, 0);
7998         cli_posix_unlink(cli1, sname);
7999         cli_setatr(cli1, hname, 0, 0);
8000         cli_posix_unlink(cli1, hname);
8001         cli_setatr(cli1, fname, 0, 0);
8002         cli_posix_unlink(cli1, fname);
8003         cli_setatr(cli1, dname, 0, 0);
8004         cli_posix_rmdir(cli1, dname);
8005         cli_setatr(cli1, fname_windows, 0, 0);
8006         cli_posix_unlink(cli1, fname_windows);
8007
8008         if (!torture_close_connection(cli1)) {
8009                 correct = false;
8010         }
8011
8012         return correct;
8013 }
8014
8015 /*
8016   Test POSIX and Windows ACLs are rejected on symlinks.
8017  */
8018 static bool run_acl_symlink_test(int dummy)
8019 {
8020         static struct cli_state *cli;
8021         const char *fname = "posix_file";
8022         const char *sname = "posix_symlink";
8023         uint16_t fnum = (uint16_t)-1;
8024         bool correct = false;
8025         NTSTATUS status;
8026         char *posix_acl = NULL;
8027         size_t posix_acl_len = 0;
8028         char *posix_acl_sym = NULL;
8029         size_t posix_acl_len_sym = 0;
8030         struct security_descriptor *sd = NULL;
8031         struct security_descriptor *sd_sym = NULL;
8032         TALLOC_CTX *frame = NULL;
8033
8034         frame = talloc_stackframe();
8035
8036         printf("Starting acl symlink test\n");
8037
8038         if (!torture_open_connection(&cli, 0)) {
8039                 TALLOC_FREE(frame);
8040                 return false;
8041         }
8042
8043         smbXcli_conn_set_sockopt(cli->conn, sockops);
8044
8045         status = torture_setup_unix_extensions(cli);
8046         if (!NT_STATUS_IS_OK(status)) {
8047                 TALLOC_FREE(frame);
8048                 return false;
8049         }
8050
8051         cli_setatr(cli, fname, 0, 0);
8052         cli_posix_unlink(cli, fname);
8053         cli_setatr(cli, sname, 0, 0);
8054         cli_posix_unlink(cli, sname);
8055
8056         status = cli_ntcreate(cli,
8057                         fname,
8058                         0,
8059                         READ_CONTROL_ACCESS,
8060                         0,
8061                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8062                         FILE_CREATE,
8063                         0x0,
8064                         0x0,
8065                         &fnum,
8066                         NULL);
8067
8068         if (!NT_STATUS_IS_OK(status)) {
8069                 printf("cli_ntcreate of %s failed (%s)\n",
8070                         fname,
8071                         nt_errstr(status));
8072                 goto out;
8073         }
8074
8075         /* Get the Windows ACL on the file. */
8076         status = cli_query_secdesc(cli,
8077                                 fnum,
8078                                 frame,
8079                                 &sd);
8080         if (!NT_STATUS_IS_OK(status)) {
8081                 printf("cli_query_secdesc failed (%s)\n",
8082                         nt_errstr(status));
8083                 goto out;
8084         }
8085
8086         /* Get the POSIX ACL on the file. */
8087         status = cli_posix_getacl(cli,
8088                                 fname,
8089                                 frame,
8090                                 &posix_acl_len,
8091                                 &posix_acl);
8092
8093         if (!NT_STATUS_IS_OK(status)) {
8094                 printf("cli_posix_getacl failed (%s)\n",
8095                         nt_errstr(status));
8096                 goto out;
8097         }
8098
8099         status = cli_close(cli, fnum);
8100         if (!NT_STATUS_IS_OK(status)) {
8101                 printf("close failed (%s)\n", nt_errstr(status));
8102                 goto out;
8103         }
8104         fnum = (uint16_t)-1;
8105
8106         /* Now create a symlink. */
8107         status = cli_posix_symlink(cli, fname, sname);
8108         if (!NT_STATUS_IS_OK(status)) {
8109                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8110                         sname,
8111                         fname,
8112                         nt_errstr(status));
8113                 goto out;
8114         }
8115
8116         /* Open a handle on the symlink for SD set/get should fail. */
8117         status = cli_ntcreate(cli,
8118                         sname,
8119                         0,
8120                         READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8121                         0,
8122                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8123                         FILE_OPEN,
8124                         0x0,
8125                         0x0,
8126                         &fnum,
8127                         NULL);
8128
8129         if (NT_STATUS_IS_OK(status)) {
8130                 printf("Symlink open for getsd/setsd of %s "
8131                         "succeeded (should fail)\n",
8132                         sname);
8133                 goto out;
8134         }
8135
8136         /* Open a handle on the symlink. */
8137         status = cli_ntcreate(cli,
8138                         sname,
8139                         0,
8140                         FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8141                         0,
8142                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8143                         FILE_OPEN,
8144                         0x0,
8145                         0x0,
8146                         &fnum,
8147                         NULL);
8148
8149         if (!NT_STATUS_IS_OK(status)) {
8150                 printf("cli_posix_open of %s failed (%s)\n",
8151                         sname,
8152                         nt_errstr(status));
8153                 goto out;
8154         }
8155
8156         /* Get the Windows ACL on the symlink handle. Should fail */
8157         status = cli_query_secdesc(cli,
8158                                 fnum,
8159                                 frame,
8160                                 &sd_sym);
8161
8162         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8163                 printf("cli_query_secdesc on a symlink gave %s. "
8164                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8165                         nt_errstr(status));
8166                 goto out;
8167         }
8168
8169         /* Get the POSIX ACL on the symlink pathname. Should fail. */
8170         status = cli_posix_getacl(cli,
8171                                 sname,
8172                                 frame,
8173                                 &posix_acl_len_sym,
8174                                 &posix_acl_sym);
8175
8176         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8177                 printf("cli_posix_getacl on a symlink gave %s. "
8178                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8179                         nt_errstr(status));
8180                 goto out;
8181         }
8182
8183         /* Set the Windows ACL on the symlink handle. Should fail */
8184         status = cli_set_security_descriptor(cli,
8185                                 fnum,
8186                                 SECINFO_DACL,
8187                                 sd);
8188
8189         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8190                 printf("cli_query_secdesc on a symlink gave %s. "
8191                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8192                         nt_errstr(status));
8193                 goto out;
8194         }
8195
8196         /* Set the POSIX ACL on the symlink pathname. Should fail. */
8197         status = cli_posix_setacl(cli,
8198                                 sname,
8199                                 posix_acl,
8200                                 posix_acl_len);
8201
8202         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8203                 printf("cli_posix_setacl on a symlink gave %s. "
8204                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8205                         nt_errstr(status));
8206                 goto out;
8207         }
8208
8209         printf("ACL symlink test passed\n");
8210         correct = true;
8211
8212   out:
8213
8214         if (fnum != (uint16_t)-1) {
8215                 cli_close(cli, fnum);
8216                 fnum = (uint16_t)-1;
8217         }
8218
8219         cli_setatr(cli, sname, 0, 0);
8220         cli_posix_unlink(cli, sname);
8221         cli_setatr(cli, fname, 0, 0);
8222         cli_posix_unlink(cli, fname);
8223
8224         if (!torture_close_connection(cli)) {
8225                 correct = false;
8226         }
8227
8228         TALLOC_FREE(frame);
8229         return correct;
8230 }
8231
8232 /*
8233   Test POSIX can delete a file containing streams.
8234  */
8235 static bool run_posix_stream_delete(int dummy)
8236 {
8237         struct cli_state *cli1 = NULL;
8238         struct cli_state *cli2 = NULL;
8239         const char *fname = "streamfile";
8240         const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8241         uint16_t fnum1 = (uint16_t)-1;
8242         bool correct = false;
8243         NTSTATUS status;
8244         TALLOC_CTX *frame = NULL;
8245
8246         frame = talloc_stackframe();
8247
8248         printf("Starting POSIX stream delete test\n");
8249
8250         if (!torture_open_connection(&cli1, 0) ||
8251                         !torture_open_connection(&cli2, 1)) {
8252                 TALLOC_FREE(frame);
8253                 return false;
8254         }
8255
8256         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8257         smbXcli_conn_set_sockopt(cli2->conn, sockops);
8258
8259         status = torture_setup_unix_extensions(cli2);
8260         if (!NT_STATUS_IS_OK(status)) {
8261                 goto out;
8262         }
8263
8264         cli_setatr(cli1, fname, 0, 0);
8265         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8266
8267         /* Create the file. */
8268         status = cli_ntcreate(cli1,
8269                         fname,
8270                         0,
8271                         READ_CONTROL_ACCESS,
8272                         0,
8273                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8274                         FILE_CREATE,
8275                         0x0,
8276                         0x0,
8277                         &fnum1,
8278                         NULL);
8279
8280         if (!NT_STATUS_IS_OK(status)) {
8281                 printf("cli_ntcreate of %s failed (%s)\n",
8282                         fname,
8283                         nt_errstr(status));
8284                 goto out;
8285         }
8286
8287         status = cli_close(cli1, fnum1);
8288         if (!NT_STATUS_IS_OK(status)) {
8289                 printf("cli_close of %s failed (%s)\n",
8290                         fname,
8291                         nt_errstr(status));
8292                 goto out;
8293         }
8294         fnum1 = (uint16_t)-1;
8295
8296         /* Now create the stream. */
8297         status = cli_ntcreate(cli1,
8298                         stream_fname,
8299                         0,
8300                         FILE_WRITE_DATA,
8301                         0,
8302                         FILE_SHARE_READ|FILE_SHARE_WRITE,
8303                         FILE_CREATE,
8304                         0x0,
8305                         0x0,
8306                         &fnum1,
8307                         NULL);
8308
8309         if (!NT_STATUS_IS_OK(status)) {
8310                 printf("cli_ntcreate of %s failed (%s)\n",
8311                         stream_fname,
8312                         nt_errstr(status));
8313                 goto out;
8314         }
8315
8316         /* Leave the stream handle open... */
8317
8318         /* POSIX unlink should fail. */
8319         status = cli_posix_unlink(cli2, fname);
8320         if (NT_STATUS_IS_OK(status)) {
8321                 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8322                         fname);
8323                 goto out;
8324         }
8325
8326         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8327                 printf("cli_posix_unlink of %s failed with (%s) "
8328                         "should have been NT_STATUS_SHARING_VIOLATION\n",
8329                         fname,
8330                         nt_errstr(status));
8331                 goto out;
8332         }
8333
8334         /* Close the stream handle. */
8335         status = cli_close(cli1, fnum1);
8336         if (!NT_STATUS_IS_OK(status)) {
8337                 printf("cli_close of %s failed (%s)\n",
8338                         stream_fname,
8339                         nt_errstr(status));
8340                 goto out;
8341         }
8342         fnum1 = (uint16_t)-1;
8343
8344         /* POSIX unlink after stream handle closed should succeed. */
8345         status = cli_posix_unlink(cli2, fname);
8346         if (!NT_STATUS_IS_OK(status)) {
8347                 printf("cli_posix_unlink of %s failed (%s)\n",
8348                         fname,
8349                         nt_errstr(status));
8350                 goto out;
8351         }
8352
8353         printf("POSIX stream delete test passed\n");
8354         correct = true;
8355
8356   out:
8357
8358         if (fnum1 != (uint16_t)-1) {
8359                 cli_close(cli1, fnum1);
8360                 fnum1 = (uint16_t)-1;
8361         }
8362
8363         cli_setatr(cli1, fname, 0, 0);
8364         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8365
8366         if (!torture_close_connection(cli1)) {
8367                 correct = false;
8368         }
8369         if (!torture_close_connection(cli2)) {
8370                 correct = false;
8371         }
8372
8373         TALLOC_FREE(frame);
8374         return correct;
8375 }
8376
8377 /*
8378   Test setting EA's are rejected on symlinks.
8379  */
8380 static bool run_ea_symlink_test(int dummy)
8381 {
8382         static struct cli_state *cli;
8383         const char *fname = "posix_file_ea";
8384         const char *sname = "posix_symlink_ea";
8385         const char *ea_name = "testea_name";
8386         const char *ea_value = "testea_value";
8387         uint16_t fnum = (uint16_t)-1;
8388         bool correct = false;
8389         NTSTATUS status;
8390         size_t i, num_eas;
8391         struct ea_struct *eas = NULL;
8392         TALLOC_CTX *frame = NULL;
8393
8394         frame = talloc_stackframe();
8395
8396         printf("Starting EA symlink test\n");
8397
8398         if (!torture_open_connection(&cli, 0)) {
8399                 TALLOC_FREE(frame);
8400                 return false;
8401         }
8402
8403         smbXcli_conn_set_sockopt(cli->conn, sockops);
8404
8405         status = torture_setup_unix_extensions(cli);
8406         if (!NT_STATUS_IS_OK(status)) {
8407                 TALLOC_FREE(frame);
8408                 return false;
8409         }
8410
8411         cli_setatr(cli, fname, 0, 0);
8412         cli_posix_unlink(cli, fname);
8413         cli_setatr(cli, sname, 0, 0);
8414         cli_posix_unlink(cli, sname);
8415
8416         status = cli_ntcreate(cli,
8417                         fname,
8418                         0,
8419                         READ_CONTROL_ACCESS,
8420                         0,
8421                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8422                         FILE_CREATE,
8423                         0x0,
8424                         0x0,
8425                         &fnum,
8426                         NULL);
8427
8428         if (!NT_STATUS_IS_OK(status)) {
8429                 printf("cli_ntcreate of %s failed (%s)\n",
8430                         fname,
8431                         nt_errstr(status));
8432                 goto out;
8433         }
8434
8435         status = cli_close(cli, fnum);
8436         if (!NT_STATUS_IS_OK(status)) {
8437                 printf("close failed (%s)\n",
8438                         nt_errstr(status));
8439                 goto out;
8440         }
8441         fnum = (uint16_t)-1;
8442
8443         /* Set an EA on the path. */
8444         status = cli_set_ea_path(cli,
8445                                 fname,
8446                                 ea_name,
8447                                 ea_value,
8448                                 strlen(ea_value)+1);
8449
8450         if (!NT_STATUS_IS_OK(status)) {
8451                 printf("cli_set_ea_path failed (%s)\n",
8452                         nt_errstr(status));
8453                 goto out;
8454         }
8455
8456         /* Now create a symlink. */
8457         status = cli_posix_symlink(cli, fname, sname);
8458         if (!NT_STATUS_IS_OK(status)) {
8459                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8460                         sname,
8461                         fname,
8462                         nt_errstr(status));
8463                 goto out;
8464         }
8465
8466         /* Get the EA list on the path. Should return value set. */
8467         status = cli_get_ea_list_path(cli,
8468                                 fname,
8469                                 frame,
8470                                 &num_eas,
8471                                 &eas);
8472
8473         if (!NT_STATUS_IS_OK(status)) {
8474                 printf("cli_get_ea_list_path failed (%s)\n",
8475                         nt_errstr(status));
8476                 goto out;
8477         }
8478
8479         /* Ensure the EA we set is there. */
8480         for (i=0; i<num_eas; i++) {
8481                 if (strcmp(eas[i].name, ea_name) == 0 &&
8482                                 eas[i].value.length == strlen(ea_value)+1 &&
8483                                 memcmp(eas[i].value.data,
8484                                         ea_value,
8485                                         eas[i].value.length) == 0) {
8486                         break;
8487                 }
8488         }
8489
8490         if (i == num_eas) {
8491                 printf("Didn't find EA on pathname %s\n",
8492                         fname);
8493                 goto out;
8494         }
8495
8496         num_eas = 0;
8497         TALLOC_FREE(eas);
8498
8499         /* Get the EA list on the symlink. Should return empty list. */
8500         status = cli_get_ea_list_path(cli,
8501                                 sname,
8502                                 frame,
8503                                 &num_eas,
8504                                 &eas);
8505
8506         if (!NT_STATUS_IS_OK(status)) {
8507                 printf("cli_get_ea_list_path failed (%s)\n",
8508                         nt_errstr(status));
8509                 goto out;
8510         }
8511
8512         if (num_eas != 0) {
8513                 printf("cli_get_ea_list_path failed (%s)\n",
8514                         nt_errstr(status));
8515                 goto out;
8516         }
8517
8518         /* Set an EA on the symlink. Should fail. */
8519         status = cli_set_ea_path(cli,
8520                                 sname,
8521                                 ea_name,
8522                                 ea_value,
8523                                 strlen(ea_value)+1);
8524
8525         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8526                 printf("cli_set_ea_path on a symlink gave %s. "
8527                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8528                         nt_errstr(status));
8529                 goto out;
8530         }
8531
8532         printf("EA symlink test passed\n");
8533         correct = true;
8534
8535   out:
8536
8537         if (fnum != (uint16_t)-1) {
8538                 cli_close(cli, fnum);
8539                 fnum = (uint16_t)-1;
8540         }
8541
8542         cli_setatr(cli, sname, 0, 0);
8543         cli_posix_unlink(cli, sname);
8544         cli_setatr(cli, fname, 0, 0);
8545         cli_posix_unlink(cli, fname);
8546
8547         if (!torture_close_connection(cli)) {
8548                 correct = false;
8549         }
8550
8551         TALLOC_FREE(frame);
8552         return correct;
8553 }
8554
8555 /*
8556   Test POSIX locks are OFD-locks.
8557  */
8558 static bool run_posix_ofd_lock_test(int dummy)
8559 {
8560         static struct cli_state *cli;
8561         const char *fname = "posix_file";
8562         uint16_t fnum1 = (uint16_t)-1;
8563         uint16_t fnum2 = (uint16_t)-1;
8564         bool correct = false;
8565         NTSTATUS status;
8566         TALLOC_CTX *frame = NULL;
8567
8568         frame = talloc_stackframe();
8569
8570         printf("Starting POSIX ofd-lock test\n");
8571
8572         if (!torture_open_connection(&cli, 0)) {
8573                 TALLOC_FREE(frame);
8574                 return false;
8575         }
8576
8577         smbXcli_conn_set_sockopt(cli->conn, sockops);
8578
8579         status = torture_setup_unix_extensions(cli);
8580         if (!NT_STATUS_IS_OK(status)) {
8581                 TALLOC_FREE(frame);
8582                 return false;
8583         }
8584
8585         cli_setatr(cli, fname, 0, 0);
8586         cli_posix_unlink(cli, fname);
8587
8588         /* Open the file twice. */
8589         status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8590                                 0600, &fnum1);
8591         if (!NT_STATUS_IS_OK(status)) {
8592                 printf("First POSIX open of %s failed\n", fname);
8593                 goto out;
8594         }
8595
8596         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8597         if (!NT_STATUS_IS_OK(status)) {
8598                 printf("First POSIX open of %s failed\n", fname);
8599                 goto out;
8600         }
8601
8602         /* Set a 0-50 lock on fnum1. */
8603         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8604         if (!NT_STATUS_IS_OK(status)) {
8605                 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8606                 goto out;
8607         }
8608
8609         /* Set a 60-100 lock on fnum2. */
8610         status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8611         if (!NT_STATUS_IS_OK(status)) {
8612                 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8613                 goto out;
8614         }
8615
8616         /* close fnum1 - 0-50 lock should go away. */
8617         status = cli_close(cli, fnum1);
8618         if (!NT_STATUS_IS_OK(status)) {
8619                 printf("close failed (%s)\n",
8620                         nt_errstr(status));
8621                 goto out;
8622         }
8623         fnum1 = (uint16_t)-1;
8624
8625         /* Change the lock context. */
8626         cli_setpid(cli, cli_getpid(cli) + 1);
8627
8628         /* Re-open fnum1. */
8629         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8630         if (!NT_STATUS_IS_OK(status)) {
8631                 printf("Third POSIX open of %s failed\n", fname);
8632                 goto out;
8633         }
8634
8635         /* 60-100 lock should still be there. */
8636         status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8637         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8638                 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8639                 goto out;
8640         }
8641
8642         /* 0-50 lock should be gone. */
8643         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8644         if (!NT_STATUS_IS_OK(status)) {
8645                 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8646                 goto out;
8647         }
8648
8649         printf("POSIX OFD lock test passed\n");
8650         correct = true;
8651
8652   out:
8653
8654         if (fnum1 != (uint16_t)-1) {
8655                 cli_close(cli, fnum1);
8656                 fnum1 = (uint16_t)-1;
8657         }
8658         if (fnum2 != (uint16_t)-1) {
8659                 cli_close(cli, fnum2);
8660                 fnum2 = (uint16_t)-1;
8661         }
8662
8663         cli_setatr(cli, fname, 0, 0);
8664         cli_posix_unlink(cli, fname);
8665
8666         if (!torture_close_connection(cli)) {
8667                 correct = false;
8668         }
8669
8670         TALLOC_FREE(frame);
8671         return correct;
8672 }
8673
8674 struct posix_blocking_state {
8675         struct tevent_context *ev;
8676         struct cli_state *cli1;
8677         uint16_t fnum1;
8678         struct cli_state *cli2;
8679         uint16_t fnum2;
8680         bool gotblocked;
8681         bool gotecho;
8682 };
8683
8684 static void posix_blocking_locked(struct tevent_req *subreq);
8685 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8686 static void posix_blocking_gotecho(struct tevent_req *subreq);
8687 static void posix_blocking_unlocked(struct tevent_req *subreq);
8688
8689 static struct tevent_req *posix_blocking_send(
8690         TALLOC_CTX *mem_ctx,
8691         struct tevent_context *ev,
8692         struct cli_state *cli1,
8693         uint16_t fnum1,
8694         struct cli_state *cli2,
8695         uint16_t fnum2)
8696 {
8697         struct tevent_req *req = NULL, *subreq = NULL;
8698         struct posix_blocking_state *state = NULL;
8699
8700         req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8701         if (req == NULL) {
8702                 return NULL;
8703         }
8704         state->ev = ev;
8705         state->cli1 = cli1;
8706         state->fnum1 = fnum1;
8707         state->cli2 = cli2;
8708         state->fnum2 = fnum2;
8709
8710         subreq = cli_posix_lock_send(
8711                 state,
8712                 state->ev,
8713                 state->cli1,
8714                 state->fnum1,
8715                 0,
8716                 1,
8717                 false,
8718                 WRITE_LOCK);
8719         if (tevent_req_nomem(subreq, req)) {
8720                 return tevent_req_post(req, ev);
8721         }
8722         tevent_req_set_callback(subreq, posix_blocking_locked, req);
8723         return req;
8724 }
8725
8726 static void posix_blocking_locked(struct tevent_req *subreq)
8727 {
8728         struct tevent_req *req = tevent_req_callback_data(
8729                 subreq, struct tevent_req);
8730         struct posix_blocking_state *state = tevent_req_data(
8731                 req, struct posix_blocking_state);
8732         NTSTATUS status;
8733
8734         status = cli_posix_lock_recv(subreq);
8735         TALLOC_FREE(subreq);
8736         if (tevent_req_nterror(req, status)) {
8737                 return;
8738         }
8739
8740         subreq = cli_posix_lock_send(
8741                 state,
8742                 state->ev,
8743                 state->cli2,
8744                 state->fnum2,
8745                 0,
8746                 1,
8747                 true,
8748                 WRITE_LOCK);
8749         if (tevent_req_nomem(subreq, req)) {
8750                 return;
8751         }
8752         tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8753
8754         /* Make sure the blocking request is delivered */
8755         subreq = cli_echo_send(
8756                 state,
8757                 state->ev,
8758                 state->cli2,
8759                 1,
8760                 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8761         if (tevent_req_nomem(subreq, req)) {
8762                 return;
8763         }
8764         tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8765 }
8766
8767 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8768 {
8769         struct tevent_req *req = tevent_req_callback_data(
8770                 subreq, struct tevent_req);
8771         struct posix_blocking_state *state = tevent_req_data(
8772                 req, struct posix_blocking_state);
8773         NTSTATUS status;
8774
8775         status = cli_posix_lock_recv(subreq);
8776         TALLOC_FREE(subreq);
8777         if (tevent_req_nterror(req, status)) {
8778                 return;
8779         }
8780         if (!state->gotecho) {
8781                 printf("blocked req got through before echo\n");
8782                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8783                 return;
8784         }
8785         tevent_req_done(req);
8786 }
8787
8788 static void posix_blocking_gotecho(struct tevent_req *subreq)
8789 {
8790         struct tevent_req *req = tevent_req_callback_data(
8791                 subreq, struct tevent_req);
8792         struct posix_blocking_state *state = tevent_req_data(
8793                 req, struct posix_blocking_state);
8794         NTSTATUS status;
8795
8796         status = cli_echo_recv(subreq);
8797         TALLOC_FREE(subreq);
8798         if (tevent_req_nterror(req, status)) {
8799                 return;
8800         }
8801         if (state->gotblocked) {
8802                 printf("blocked req got through before echo\n");
8803                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8804                 return;
8805         }
8806         state->gotecho = true;
8807
8808         subreq = cli_posix_lock_send(
8809                 state,
8810                 state->ev,
8811                 state->cli1,
8812                 state->fnum1,
8813                 0,
8814                 1,
8815                 false,
8816                 UNLOCK_LOCK);
8817         if (tevent_req_nomem(subreq, req)) {
8818                 return;
8819         }
8820         tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
8821 }
8822
8823 static void posix_blocking_unlocked(struct tevent_req *subreq)
8824 {
8825         struct tevent_req *req = tevent_req_callback_data(
8826                 subreq, struct tevent_req);
8827         NTSTATUS status;
8828
8829         status = cli_posix_lock_recv(subreq);
8830         TALLOC_FREE(subreq);
8831         if (tevent_req_nterror(req, status)) {
8832                 return;
8833         }
8834         /* tevent_req_done in posix_blocking_gotlocked */
8835 }
8836
8837 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
8838 {
8839         return tevent_req_simple_recv_ntstatus(req);
8840 }
8841
8842 static bool run_posix_blocking_lock(int dummy)
8843 {
8844         struct tevent_context *ev = NULL;
8845         struct cli_state *cli1 = NULL, *cli2 = NULL;
8846         const char *fname = "posix_blocking";
8847         uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
8848         struct tevent_req *req = NULL;
8849         NTSTATUS status;
8850         bool ret = false;
8851         bool ok;
8852
8853         printf("Starting posix blocking lock test\n");
8854
8855         ev = samba_tevent_context_init(NULL);
8856         if (ev == NULL) {
8857                 return false;
8858         }
8859
8860         ok = torture_open_connection(&cli1, 0);
8861         if (!ok) {
8862                 goto fail;
8863         }
8864         ok = torture_open_connection(&cli2, 0);
8865         if (!ok) {
8866                 goto fail;
8867         }
8868
8869         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8870
8871         status = torture_setup_unix_extensions(cli1);
8872         if (!NT_STATUS_IS_OK(status)) {
8873                 return false;
8874         }
8875
8876         cli_setatr(cli1, fname, 0, 0);
8877         cli_posix_unlink(cli1, fname);
8878
8879         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8880                                 0600, &fnum1);
8881         if (!NT_STATUS_IS_OK(status)) {
8882                 printf("First POSIX open of %s failed: %s\n",
8883                        fname,
8884                        nt_errstr(status));
8885                 goto fail;
8886         }
8887
8888         status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
8889         if (!NT_STATUS_IS_OK(status)) {
8890                 printf("Second POSIX open of %s failed: %s\n",
8891                        fname,
8892                        nt_errstr(status));
8893                 goto fail;
8894         }
8895
8896         req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
8897         if (req == NULL) {
8898                 printf("cli_posix_blocking failed\n");
8899                 goto fail;
8900         }
8901
8902         ok = tevent_req_poll_ntstatus(req, ev, &status);
8903         if (!ok) {
8904                 printf("tevent_req_poll_ntstatus failed: %s\n",
8905                        nt_errstr(status));
8906                 goto fail;
8907         }
8908         status = posix_blocking_recv(req);
8909         TALLOC_FREE(req);
8910         if (!NT_STATUS_IS_OK(status)) {
8911                 printf("posix_blocking_recv returned %s\n",
8912                        nt_errstr(status));
8913                 goto fail;
8914         }
8915
8916         ret = true;
8917 fail:
8918
8919         if (fnum1 != UINT16_MAX) {
8920                 cli_close(cli1, fnum1);
8921                 fnum1 = UINT16_MAX;
8922         }
8923         if (fnum2 != UINT16_MAX) {
8924                 cli_close(cli2, fnum2);
8925                 fnum2 = UINT16_MAX;
8926         }
8927
8928         if (cli1 != NULL) {
8929                 cli_setatr(cli1, fname, 0, 0);
8930                 cli_posix_unlink(cli1, fname);
8931         }
8932
8933         ok = true;
8934
8935         if (cli1 != NULL) {
8936                 ok &= torture_close_connection(cli1);
8937                 cli1 = NULL;
8938         }
8939         if (cli2 != NULL) {
8940                 ok &= torture_close_connection(cli2);
8941                 cli2 = NULL;
8942         }
8943
8944         if (!ok) {
8945                 ret = false;
8946         }
8947         TALLOC_FREE(ev);
8948         return ret;
8949 }
8950
8951 /*
8952   Test POSIX mkdir is case-sensitive.
8953  */
8954 static bool run_posix_mkdir_test(int dummy)
8955 {
8956         static struct cli_state *cli;
8957         const char *fname_foo = "POSIX_foo";
8958         const char *fname_foo_Foo = "POSIX_foo/Foo";
8959         const char *fname_foo_foo = "POSIX_foo/foo";
8960         const char *fname_Foo = "POSIX_Foo";
8961         const char *fname_Foo_Foo = "POSIX_Foo/Foo";
8962         const char *fname_Foo_foo = "POSIX_Foo/foo";
8963         bool correct = false;
8964         NTSTATUS status;
8965         TALLOC_CTX *frame = NULL;
8966         uint16_t fnum = (uint16_t)-1;
8967
8968         frame = talloc_stackframe();
8969
8970         printf("Starting POSIX mkdir test\n");
8971
8972         if (!torture_open_connection(&cli, 0)) {
8973                 TALLOC_FREE(frame);
8974                 return false;
8975         }
8976
8977         smbXcli_conn_set_sockopt(cli->conn, sockops);
8978
8979         status = torture_setup_unix_extensions(cli);
8980         if (!NT_STATUS_IS_OK(status)) {
8981                 TALLOC_FREE(frame);
8982                 return false;
8983         }
8984
8985         cli_posix_rmdir(cli, fname_foo_foo);
8986         cli_posix_rmdir(cli, fname_foo_Foo);
8987         cli_posix_rmdir(cli, fname_foo);
8988
8989         cli_posix_rmdir(cli, fname_Foo_foo);
8990         cli_posix_rmdir(cli, fname_Foo_Foo);
8991         cli_posix_rmdir(cli, fname_Foo);
8992
8993         /*
8994          * Create a file POSIX_foo then try
8995          * and use it in a directory path by
8996          * doing mkdir POSIX_foo/bar.
8997          * The mkdir should fail with
8998          * NT_STATUS_OBJECT_PATH_NOT_FOUND
8999          */
9000
9001         status = cli_posix_open(cli,
9002                         fname_foo,
9003                         O_RDWR|O_CREAT,
9004                         0666,
9005                         &fnum);
9006         if (!NT_STATUS_IS_OK(status)) {
9007                 printf("cli_posix_open of %s failed error %s\n",
9008                         fname_foo,
9009                         nt_errstr(status));
9010                 goto out;
9011         }
9012
9013         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9014         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9015                 printf("cli_posix_mkdir of %s should fail with "
9016                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9017                         "%s instead\n",
9018                         fname_foo_foo,
9019                         nt_errstr(status));
9020                 goto out;
9021         }
9022
9023         status = cli_close(cli, fnum);
9024         if (!NT_STATUS_IS_OK(status)) {
9025                 printf("cli_close failed %s\n", nt_errstr(status));
9026                 goto out;
9027         }
9028         fnum = (uint16_t)-1;
9029
9030         status = cli_posix_unlink(cli, fname_foo);
9031         if (!NT_STATUS_IS_OK(status)) {
9032                 printf("cli_posix_unlink of %s failed error %s\n",
9033                         fname_foo,
9034                         nt_errstr(status));
9035                 goto out;
9036         }
9037
9038         /*
9039          * Now we've deleted everything, posix_mkdir, posix_rmdir,
9040          * posix_open, posix_unlink, on
9041          * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9042          * not silently create POSIX_foo/foo.
9043          */
9044
9045         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9046         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9047                 printf("cli_posix_mkdir of %s should fail with "
9048                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9049                         "%s instead\n",
9050                         fname_foo_foo,
9051                         nt_errstr(status));
9052                 goto out;
9053         }
9054
9055         status = cli_posix_rmdir(cli, fname_foo_foo);
9056         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9057                 printf("cli_posix_rmdir of %s should fail with "
9058                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9059                         "%s instead\n",
9060                         fname_foo_foo,
9061                         nt_errstr(status));
9062                 goto out;
9063         }
9064
9065         status = cli_posix_open(cli,
9066                         fname_foo_foo,
9067                         O_RDWR|O_CREAT,
9068                         0666,
9069                         &fnum);
9070         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9071                 printf("cli_posix_open 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_unlink(cli, fname_foo_foo);
9080         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9081                 printf("cli_posix_unlink of %s should fail with "
9082                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9083                         "%s instead\n",
9084                         fname_foo_foo,
9085                         nt_errstr(status));
9086                 goto out;
9087         }
9088
9089         status = cli_posix_mkdir(cli, fname_foo, 0777);
9090         if (!NT_STATUS_IS_OK(status)) {
9091                 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9092                 goto out;
9093         }
9094
9095         status = cli_posix_mkdir(cli, fname_Foo, 0777);
9096         if (!NT_STATUS_IS_OK(status)) {
9097                 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9098                 goto out;
9099         }
9100
9101         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9102         if (!NT_STATUS_IS_OK(status)) {
9103                 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9104                 goto out;
9105         }
9106
9107         status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9108         if (!NT_STATUS_IS_OK(status)) {
9109                 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9110                 goto out;
9111         }
9112
9113         status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9114         if (!NT_STATUS_IS_OK(status)) {
9115                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9116                 goto out;
9117         }
9118
9119         status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9120         if (!NT_STATUS_IS_OK(status)) {
9121                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9122                 goto out;
9123         }
9124
9125         printf("POSIX mkdir test passed\n");
9126         correct = true;
9127
9128   out:
9129
9130         if (fnum != (uint16_t)-1) {
9131                 cli_close(cli, fnum);
9132                 fnum = (uint16_t)-1;
9133         }
9134
9135         cli_posix_rmdir(cli, fname_foo_foo);
9136         cli_posix_rmdir(cli, fname_foo_Foo);
9137         cli_posix_rmdir(cli, fname_foo);
9138
9139         cli_posix_rmdir(cli, fname_Foo_foo);
9140         cli_posix_rmdir(cli, fname_Foo_Foo);
9141         cli_posix_rmdir(cli, fname_Foo);
9142
9143         if (!torture_close_connection(cli)) {
9144                 correct = false;
9145         }
9146
9147         TALLOC_FREE(frame);
9148         return correct;
9149 }
9150
9151 struct posix_acl_oplock_state {
9152         struct tevent_context *ev;
9153         struct cli_state *cli;
9154         bool *got_break;
9155         bool *acl_ret;
9156         NTSTATUS status;
9157 };
9158
9159 static void posix_acl_oplock_got_break(struct tevent_req *req)
9160 {
9161         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9162                 req, struct posix_acl_oplock_state);
9163         uint16_t fnum;
9164         uint8_t level;
9165         NTSTATUS status;
9166
9167         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9168         TALLOC_FREE(req);
9169         if (!NT_STATUS_IS_OK(status)) {
9170                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9171                        nt_errstr(status));
9172                 return;
9173         }
9174         *state->got_break = true;
9175
9176         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9177                                   NO_OPLOCK);
9178         if (req == NULL) {
9179                 printf("cli_oplock_ack_send failed\n");
9180                 return;
9181         }
9182 }
9183
9184 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9185 {
9186         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9187                 req, struct posix_acl_oplock_state);
9188         size_t ret_size = 0;
9189         char *ret_data = NULL;
9190
9191         state->status = cli_posix_getacl_recv(req,
9192                         state,
9193                         &ret_size,
9194                         &ret_data);
9195
9196         if (!NT_STATUS_IS_OK(state->status)) {
9197                 printf("cli_posix_getacl_recv returned %s\n",
9198                         nt_errstr(state->status));
9199         }
9200         *state->acl_ret = true;
9201 }
9202
9203 static bool run_posix_acl_oplock_test(int dummy)
9204 {
9205         struct tevent_context *ev;
9206         struct cli_state *cli1, *cli2;
9207         struct tevent_req *oplock_req, *getacl_req;
9208         const char *fname = "posix_acl_oplock";
9209         uint16_t fnum;
9210         int saved_use_oplocks = use_oplocks;
9211         NTSTATUS status;
9212         bool correct = true;
9213         bool got_break = false;
9214         bool acl_ret = false;
9215
9216         struct posix_acl_oplock_state *state;
9217
9218         printf("starting posix_acl_oplock test\n");
9219
9220         if (!torture_open_connection(&cli1, 0)) {
9221                 use_level_II_oplocks = false;
9222                 use_oplocks = saved_use_oplocks;
9223                 return false;
9224         }
9225
9226         if (!torture_open_connection(&cli2, 1)) {
9227                 use_level_II_oplocks = false;
9228                 use_oplocks = saved_use_oplocks;
9229                 return false;
9230         }
9231
9232         /* Setup posix on cli2 only. */
9233         status = torture_setup_unix_extensions(cli2);
9234         if (!NT_STATUS_IS_OK(status)) {
9235                 return false;
9236         }
9237
9238         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9239         smbXcli_conn_set_sockopt(cli2->conn, sockops);
9240
9241         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9242
9243         /* Create the file on the Windows connection. */
9244         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9245                           &fnum);
9246         if (!NT_STATUS_IS_OK(status)) {
9247                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9248                 return false;
9249         }
9250
9251         status = cli_close(cli1, fnum);
9252         if (!NT_STATUS_IS_OK(status)) {
9253                 printf("close1 failed (%s)\n", nt_errstr(status));
9254                 return false;
9255         }
9256
9257         cli1->use_oplocks = true;
9258
9259         /* Open with oplock. */
9260         status = cli_ntcreate(cli1,
9261                         fname,
9262                         0,
9263                         FILE_READ_DATA,
9264                         FILE_ATTRIBUTE_NORMAL,
9265                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9266                         FILE_OPEN,
9267                         0,
9268                         0,
9269                         &fnum,
9270                         NULL);
9271
9272         if (!NT_STATUS_IS_OK(status)) {
9273                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9274                 return false;
9275         }
9276
9277         ev = samba_tevent_context_init(talloc_tos());
9278         if (ev == NULL) {
9279                 printf("tevent_context_init failed\n");
9280                 return false;
9281         }
9282
9283         state = talloc_zero(ev, struct posix_acl_oplock_state);
9284         if (state == NULL) {
9285                 printf("talloc failed\n");
9286                 return false;
9287         }
9288         state->ev = ev;
9289         state->cli = cli1;
9290         state->got_break = &got_break;
9291         state->acl_ret = &acl_ret;
9292
9293         oplock_req = cli_smb_oplock_break_waiter_send(
9294                 talloc_tos(), ev, cli1);
9295         if (oplock_req == NULL) {
9296                 printf("cli_smb_oplock_break_waiter_send failed\n");
9297                 return false;
9298         }
9299         tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9300
9301         /* Get ACL on POSIX connection - should break oplock. */
9302         getacl_req = cli_posix_getacl_send(talloc_tos(),
9303                                 ev,
9304                                 cli2,
9305                                 fname);
9306         if (getacl_req == NULL) {
9307                 printf("cli_posix_getacl_send failed\n");
9308                 return false;
9309         }
9310         tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9311
9312         while (!got_break || !acl_ret) {
9313                 int ret;
9314                 ret = tevent_loop_once(ev);
9315                 if (ret == -1) {
9316                         printf("tevent_loop_once failed: %s\n",
9317                                strerror(errno));
9318                         return false;
9319                 }
9320         }
9321
9322         if (!NT_STATUS_IS_OK(state->status)) {
9323                 printf("getacl failed (%s)\n", nt_errstr(state->status));
9324                 correct = false;
9325         }
9326
9327         status = cli_close(cli1, fnum);
9328         if (!NT_STATUS_IS_OK(status)) {
9329                 printf("close2 failed (%s)\n", nt_errstr(status));
9330                 correct = false;
9331         }
9332
9333         status = cli_unlink(cli1,
9334                         fname,
9335                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9336         if (!NT_STATUS_IS_OK(status)) {
9337                 printf("unlink failed (%s)\n", nt_errstr(status));
9338                 correct = false;
9339         }
9340
9341         if (!torture_close_connection(cli1)) {
9342                 correct = false;
9343         }
9344         if (!torture_close_connection(cli2)) {
9345                 correct = false;
9346         }
9347
9348         if (!got_break) {
9349                 correct = false;
9350         }
9351
9352         printf("finished posix acl oplock test\n");
9353
9354         return correct;
9355 }
9356
9357 static bool run_posix_acl_shareroot_test(int dummy)
9358 {
9359         struct cli_state *cli;
9360         NTSTATUS status;
9361         bool correct = false;
9362         char *posix_acl = NULL;
9363         size_t posix_acl_len = 0;
9364         uint16_t num_file_acls = 0;
9365         uint16_t num_dir_acls = 0;
9366         uint16_t i;
9367         uint32_t expected_size = 0;
9368         bool got_user = false;
9369         bool got_group = false;
9370         bool got_other = false;
9371         TALLOC_CTX *frame = NULL;
9372
9373         frame = talloc_stackframe();
9374
9375         printf("starting posix_acl_shareroot test\n");
9376
9377         if (!torture_open_connection(&cli, 0)) {
9378                 TALLOC_FREE(frame);
9379                 return false;
9380         }
9381
9382         smbXcli_conn_set_sockopt(cli->conn, sockops);
9383
9384         status = torture_setup_unix_extensions(cli);
9385         if (!NT_STATUS_IS_OK(status)) {
9386                 printf("Failed to setup unix extensions\n");
9387                 goto out;
9388         }
9389
9390         /* Get the POSIX ACL on the root of the share. */
9391         status = cli_posix_getacl(cli,
9392                                 ".",
9393                                 frame,
9394                                 &posix_acl_len,
9395                                 &posix_acl);
9396
9397         if (!NT_STATUS_IS_OK(status)) {
9398                 printf("cli_posix_getacl of '.' failed (%s)\n",
9399                         nt_errstr(status));
9400                 goto out;
9401         }
9402
9403         if (posix_acl_len < 6 ||
9404                         SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9405                 printf("getfacl ., unknown POSIX acl version %u.\n",
9406                         (unsigned int)CVAL(posix_acl,0) );
9407                 goto out;
9408         }
9409
9410         num_file_acls = SVAL(posix_acl,2);
9411         num_dir_acls = SVAL(posix_acl,4);
9412         expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9413                                 SMB_POSIX_ACL_ENTRY_SIZE*
9414                                 (num_file_acls+num_dir_acls);
9415
9416         if (posix_acl_len != expected_size) {
9417                 printf("incorrect POSIX acl buffer size "
9418                         "(should be %u, was %u).\n",
9419                         (unsigned int)expected_size,
9420                         (unsigned int)posix_acl_len);
9421                 goto out;
9422         }
9423
9424         /*
9425          * We don't need to know what the ACL's are
9426          * we just need to know we have at least 3
9427          * file entries (u,g,o).
9428          */
9429
9430         for (i = 0; i < num_file_acls; i++) {
9431                 unsigned char tagtype =
9432                         CVAL(posix_acl,
9433                                 SMB_POSIX_ACL_HEADER_SIZE+
9434                                 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9435
9436                 switch(tagtype) {
9437                         case SMB_POSIX_ACL_USER_OBJ:
9438                                 got_user = true;
9439                                 break;
9440                         case SMB_POSIX_ACL_GROUP_OBJ:
9441                                 got_group = true;
9442                                 break;
9443                         case SMB_POSIX_ACL_OTHER:
9444                                 got_other = true;
9445                                 break;
9446                         default:
9447                                 break;
9448                 }
9449         }
9450
9451         if (!got_user) {
9452                 printf("Missing user entry\n");
9453                 goto out;
9454         }
9455
9456         if (!got_group) {
9457                 printf("Missing group entry\n");
9458                 goto out;
9459         }
9460
9461         if (!got_other) {
9462                 printf("Missing other entry\n");
9463                 goto out;
9464         }
9465
9466         correct = true;
9467
9468   out:
9469
9470         if (!torture_close_connection(cli)) {
9471                 correct = false;
9472         }
9473
9474         printf("finished posix acl shareroot test\n");
9475         TALLOC_FREE(frame);
9476
9477         return correct;
9478 }
9479
9480 static uint32_t open_attrs_table[] = {
9481                 FILE_ATTRIBUTE_NORMAL,
9482                 FILE_ATTRIBUTE_ARCHIVE,
9483                 FILE_ATTRIBUTE_READONLY,
9484                 FILE_ATTRIBUTE_HIDDEN,
9485                 FILE_ATTRIBUTE_SYSTEM,
9486
9487                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9488                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9489                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9490                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9491                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9492                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9493
9494                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9495                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9496                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9497                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9498 };
9499
9500 struct trunc_open_results {
9501         unsigned int num;
9502         uint32_t init_attr;
9503         uint32_t trunc_attr;
9504         uint32_t result_attr;
9505 };
9506
9507 static struct trunc_open_results attr_results[] = {
9508         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9509         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9510         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9511         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9512         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9513         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9514         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9515         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9516         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9517         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9518         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9519         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9520         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9521         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9522         { 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 },
9523         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9524         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9525         { 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 },
9526         { 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 },
9527         { 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 },
9528         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9529         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9530         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9531         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9532         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9533         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9534 };
9535
9536 static bool run_openattrtest(int dummy)
9537 {
9538         static struct cli_state *cli1;
9539         const char *fname = "\\openattr.file";
9540         uint16_t fnum1;
9541         bool correct = True;
9542         uint32_t attr;
9543         unsigned int i, j, k, l;
9544         NTSTATUS status;
9545
9546         printf("starting open attr test\n");
9547
9548         if (!torture_open_connection(&cli1, 0)) {
9549                 return False;
9550         }
9551
9552         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9553
9554         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9555                 cli_setatr(cli1, fname, 0, 0);
9556                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9557
9558                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9559                                        open_attrs_table[i], FILE_SHARE_NONE,
9560                                        FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9561                 if (!NT_STATUS_IS_OK(status)) {
9562                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9563                         return False;
9564                 }
9565
9566                 status = cli_close(cli1, fnum1);
9567                 if (!NT_STATUS_IS_OK(status)) {
9568                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9569                         return False;
9570                 }
9571
9572                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9573                         status = cli_ntcreate(cli1, fname, 0,
9574                                               FILE_READ_DATA|FILE_WRITE_DATA,
9575                                               open_attrs_table[j],
9576                                               FILE_SHARE_NONE, FILE_OVERWRITE,
9577                                               0, 0, &fnum1, NULL);
9578                         if (!NT_STATUS_IS_OK(status)) {
9579                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9580                                         if (attr_results[l].num == k) {
9581                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9582                                                                 k, open_attrs_table[i],
9583                                                                 open_attrs_table[j],
9584                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
9585                                                 correct = False;
9586                                         }
9587                                 }
9588
9589                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9590                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9591                                                         k, open_attrs_table[i], open_attrs_table[j],
9592                                                         nt_errstr(status));
9593                                         correct = False;
9594                                 }
9595 #if 0
9596                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9597 #endif
9598                                 k++;
9599                                 continue;
9600                         }
9601
9602                         status = cli_close(cli1, fnum1);
9603                         if (!NT_STATUS_IS_OK(status)) {
9604                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9605                                 return False;
9606                         }
9607
9608                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9609                         if (!NT_STATUS_IS_OK(status)) {
9610                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9611                                 return False;
9612                         }
9613
9614 #if 0
9615                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9616                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
9617 #endif
9618
9619                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9620                                 if (attr_results[l].num == k) {
9621                                         if (attr != attr_results[l].result_attr ||
9622                                                         open_attrs_table[i] != attr_results[l].init_attr ||
9623                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
9624                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9625                                                 open_attrs_table[i],
9626                                                 open_attrs_table[j],
9627                                                 (unsigned int)attr,
9628                                                 attr_results[l].result_attr);
9629                                                 correct = False;
9630                                         }
9631                                         break;
9632                                 }
9633                         }
9634                         k++;
9635                 }
9636         }
9637
9638         cli_setatr(cli1, fname, 0, 0);
9639         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9640
9641         printf("open attr test %s.\n", correct ? "passed" : "failed");
9642
9643         if (!torture_close_connection(cli1)) {
9644                 correct = False;
9645         }
9646         return correct;
9647 }
9648
9649 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
9650                     const char *name, void *state)
9651 {
9652         int *matched = (int *)state;
9653         if (matched != NULL) {
9654                 *matched += 1;
9655         }
9656         return NT_STATUS_OK;
9657 }
9658
9659 /*
9660   test directory listing speed
9661  */
9662 static bool run_dirtest(int dummy)
9663 {
9664         int i;
9665         static struct cli_state *cli;
9666         uint16_t fnum;
9667         struct timeval core_start;
9668         bool correct = True;
9669         int matched;
9670
9671         printf("starting directory test\n");
9672
9673         if (!torture_open_connection(&cli, 0)) {
9674                 return False;
9675         }
9676
9677         smbXcli_conn_set_sockopt(cli->conn, sockops);
9678
9679         srandom(0);
9680         for (i=0;i<torture_numops;i++) {
9681                 fstring fname;
9682                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9683                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9684                         fprintf(stderr,"Failed to open %s\n", fname);
9685                         return False;
9686                 }
9687                 cli_close(cli, fnum);
9688         }
9689
9690         core_start = timeval_current();
9691
9692         matched = 0;
9693         cli_list(cli, "a*.*", 0, list_fn, &matched);
9694         printf("Matched %d\n", matched);
9695
9696         matched = 0;
9697         cli_list(cli, "b*.*", 0, list_fn, &matched);
9698         printf("Matched %d\n", matched);
9699
9700         matched = 0;
9701         cli_list(cli, "xyzabc", 0, list_fn, &matched);
9702         printf("Matched %d\n", matched);
9703
9704         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9705
9706         srandom(0);
9707         for (i=0;i<torture_numops;i++) {
9708                 fstring fname;
9709                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9710                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9711         }
9712
9713         if (!torture_close_connection(cli)) {
9714                 correct = False;
9715         }
9716
9717         printf("finished dirtest\n");
9718
9719         return correct;
9720 }
9721
9722 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
9723                    void *state)
9724 {
9725         struct cli_state *pcli = (struct cli_state *)state;
9726         fstring fname;
9727         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9728
9729         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9730                 return NT_STATUS_OK;
9731
9732         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9733                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9734                         printf("del_fn: failed to rmdir %s\n,", fname );
9735         } else {
9736                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9737                         printf("del_fn: failed to unlink %s\n,", fname );
9738         }
9739         return NT_STATUS_OK;
9740 }
9741
9742
9743 /*
9744   sees what IOCTLs are supported
9745  */
9746 bool torture_ioctl_test(int dummy)
9747 {
9748         static struct cli_state *cli;
9749         uint16_t device, function;
9750         uint16_t fnum;
9751         const char *fname = "\\ioctl.dat";
9752         DATA_BLOB blob;
9753         NTSTATUS status;
9754
9755         if (!torture_open_connection(&cli, 0)) {
9756                 return False;
9757         }
9758
9759         printf("starting ioctl test\n");
9760
9761         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9762
9763         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9764         if (!NT_STATUS_IS_OK(status)) {
9765                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9766                 return False;
9767         }
9768
9769         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9770         printf("ioctl device info: %s\n", nt_errstr(status));
9771
9772         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9773         printf("ioctl job info: %s\n", nt_errstr(status));
9774
9775         for (device=0;device<0x100;device++) {
9776                 printf("ioctl test with device = 0x%x\n", device);
9777                 for (function=0;function<0x100;function++) {
9778                         uint32_t code = (device<<16) | function;
9779
9780                         status = cli_raw_ioctl(cli, fnum, code, &blob);
9781
9782                         if (NT_STATUS_IS_OK(status)) {
9783                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
9784                                        (int)blob.length);
9785                                 data_blob_free(&blob);
9786                         }
9787                 }
9788         }
9789
9790         if (!torture_close_connection(cli)) {
9791                 return False;
9792         }
9793
9794         return True;
9795 }
9796
9797
9798 /*
9799   tries varients of chkpath
9800  */
9801 bool torture_chkpath_test(int dummy)
9802 {
9803         static struct cli_state *cli;
9804         uint16_t fnum;
9805         bool ret;
9806         NTSTATUS status;
9807
9808         if (!torture_open_connection(&cli, 0)) {
9809                 return False;
9810         }
9811
9812         printf("starting chkpath test\n");
9813
9814         /* cleanup from an old run */
9815         cli_rmdir(cli, "\\chkpath.dir\\dir2");
9816         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9817         cli_rmdir(cli, "\\chkpath.dir");
9818
9819         status = cli_mkdir(cli, "\\chkpath.dir");
9820         if (!NT_STATUS_IS_OK(status)) {
9821                 printf("mkdir1 failed : %s\n", nt_errstr(status));
9822                 return False;
9823         }
9824
9825         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
9826         if (!NT_STATUS_IS_OK(status)) {
9827                 printf("mkdir2 failed : %s\n", nt_errstr(status));
9828                 return False;
9829         }
9830
9831         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
9832                           DENY_NONE, &fnum);
9833         if (!NT_STATUS_IS_OK(status)) {
9834                 printf("open1 failed (%s)\n", nt_errstr(status));
9835                 return False;
9836         }
9837         cli_close(cli, fnum);
9838
9839         status = cli_chkpath(cli, "\\chkpath.dir");
9840         if (!NT_STATUS_IS_OK(status)) {
9841                 printf("chkpath1 failed: %s\n", nt_errstr(status));
9842                 ret = False;
9843         }
9844
9845         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
9846         if (!NT_STATUS_IS_OK(status)) {
9847                 printf("chkpath2 failed: %s\n", nt_errstr(status));
9848                 ret = False;
9849         }
9850
9851         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
9852         if (!NT_STATUS_IS_OK(status)) {
9853                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9854                                   NT_STATUS_NOT_A_DIRECTORY);
9855         } else {
9856                 printf("* chkpath on a file should fail\n");
9857                 ret = False;
9858         }
9859
9860         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
9861         if (!NT_STATUS_IS_OK(status)) {
9862                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
9863                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
9864         } else {
9865                 printf("* chkpath on a non existent file should fail\n");
9866                 ret = False;
9867         }
9868
9869         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
9870         if (!NT_STATUS_IS_OK(status)) {
9871                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9872                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
9873         } else {
9874                 printf("* chkpath on a non existent component should fail\n");
9875                 ret = False;
9876         }
9877
9878         cli_rmdir(cli, "\\chkpath.dir\\dir2");
9879         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9880         cli_rmdir(cli, "\\chkpath.dir");
9881
9882         if (!torture_close_connection(cli)) {
9883                 return False;
9884         }
9885
9886         return ret;
9887 }
9888
9889 static bool run_eatest(int dummy)
9890 {
9891         static struct cli_state *cli;
9892         const char *fname = "\\eatest.txt";
9893         bool correct = True;
9894         uint16_t fnum;
9895         int i;
9896         size_t num_eas;
9897         struct ea_struct *ea_list = NULL;
9898         TALLOC_CTX *mem_ctx = talloc_init("eatest");
9899         NTSTATUS status;
9900
9901         printf("starting eatest\n");
9902
9903         if (!torture_open_connection(&cli, 0)) {
9904                 talloc_destroy(mem_ctx);
9905                 return False;
9906         }
9907
9908         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9909
9910         status = cli_ntcreate(cli, fname, 0,
9911                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
9912                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
9913                               0x4044, 0, &fnum, NULL);
9914         if (!NT_STATUS_IS_OK(status)) {
9915                 printf("open failed - %s\n", nt_errstr(status));
9916                 talloc_destroy(mem_ctx);
9917                 return False;
9918         }
9919
9920         for (i = 0; i < 10; i++) {
9921                 fstring ea_name, ea_val;
9922
9923                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
9924                 memset(ea_val, (char)i+1, i+1);
9925                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
9926                 if (!NT_STATUS_IS_OK(status)) {
9927                         printf("ea_set of name %s failed - %s\n", ea_name,
9928                                nt_errstr(status));
9929                         talloc_destroy(mem_ctx);
9930                         return False;
9931                 }
9932         }
9933
9934         cli_close(cli, fnum);
9935         for (i = 0; i < 10; i++) {
9936                 fstring ea_name, ea_val;
9937
9938                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
9939                 memset(ea_val, (char)i+1, i+1);
9940                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
9941                 if (!NT_STATUS_IS_OK(status)) {
9942                         printf("ea_set of name %s failed - %s\n", ea_name,
9943                                nt_errstr(status));
9944                         talloc_destroy(mem_ctx);
9945                         return False;
9946                 }
9947         }
9948
9949         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
9950         if (!NT_STATUS_IS_OK(status)) {
9951                 printf("ea_get list failed - %s\n", nt_errstr(status));
9952                 correct = False;
9953         }
9954
9955         printf("num_eas = %d\n", (int)num_eas);
9956
9957         if (num_eas != 20) {
9958                 printf("Should be 20 EA's stored... failing.\n");
9959                 correct = False;
9960         }
9961
9962         for (i = 0; i < num_eas; i++) {
9963                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
9964                 dump_data(0, ea_list[i].value.data,
9965                           ea_list[i].value.length);
9966         }
9967
9968         /* Setting EA's to zero length deletes them. Test this */
9969         printf("Now deleting all EA's - case indepenent....\n");
9970
9971 #if 1
9972         cli_set_ea_path(cli, fname, "", "", 0);
9973 #else
9974         for (i = 0; i < 20; i++) {
9975                 fstring ea_name;
9976                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
9977                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
9978                 if (!NT_STATUS_IS_OK(status)) {
9979                         printf("ea_set of name %s failed - %s\n", ea_name,
9980                                nt_errstr(status));
9981                         talloc_destroy(mem_ctx);
9982                         return False;
9983                 }
9984         }
9985 #endif
9986
9987         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
9988         if (!NT_STATUS_IS_OK(status)) {
9989                 printf("ea_get list failed - %s\n", nt_errstr(status));
9990                 correct = False;
9991         }
9992
9993         printf("num_eas = %d\n", (int)num_eas);
9994         for (i = 0; i < num_eas; i++) {
9995                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
9996                 dump_data(0, ea_list[i].value.data,
9997                           ea_list[i].value.length);
9998         }
9999
10000         if (num_eas != 0) {
10001                 printf("deleting EA's failed.\n");
10002                 correct = False;
10003         }
10004
10005         /* Try and delete a non existent EA. */
10006         status = cli_set_ea_path(cli, fname, "foo", "", 0);
10007         if (!NT_STATUS_IS_OK(status)) {
10008                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10009                        nt_errstr(status));
10010                 correct = False;
10011         }
10012
10013         talloc_destroy(mem_ctx);
10014         if (!torture_close_connection(cli)) {
10015                 correct = False;
10016         }
10017
10018         return correct;
10019 }
10020
10021 static bool run_dirtest1(int dummy)
10022 {
10023         int i;
10024         static struct cli_state *cli;
10025         uint16_t fnum;
10026         int num_seen;
10027         bool correct = True;
10028
10029         printf("starting directory test\n");
10030
10031         if (!torture_open_connection(&cli, 0)) {
10032                 return False;
10033         }
10034
10035         smbXcli_conn_set_sockopt(cli->conn, sockops);
10036
10037         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10038         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10039         cli_rmdir(cli, "\\LISTDIR");
10040         cli_mkdir(cli, "\\LISTDIR");
10041
10042         /* Create 1000 files and 1000 directories. */
10043         for (i=0;i<1000;i++) {
10044                 fstring fname;
10045                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10046                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10047                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10048                                    0, 0, &fnum, NULL))) {
10049                         fprintf(stderr,"Failed to open %s\n", fname);
10050                         return False;
10051                 }
10052                 cli_close(cli, fnum);
10053         }
10054         for (i=0;i<1000;i++) {
10055                 fstring fname;
10056                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10057                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10058                         fprintf(stderr,"Failed to open %s\n", fname);
10059                         return False;
10060                 }
10061         }
10062
10063         /* Now ensure that doing an old list sees both files and directories. */
10064         num_seen = 0;
10065         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10066         printf("num_seen = %d\n", num_seen );
10067         /* We should see 100 files + 1000 directories + . and .. */
10068         if (num_seen != 2002)
10069                 correct = False;
10070
10071         /* Ensure if we have the "must have" bits we only see the
10072          * relevent entries.
10073          */
10074         num_seen = 0;
10075         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10076         printf("num_seen = %d\n", num_seen );
10077         if (num_seen != 1002)
10078                 correct = False;
10079
10080         num_seen = 0;
10081         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10082         printf("num_seen = %d\n", num_seen );
10083         if (num_seen != 1000)
10084                 correct = False;
10085
10086         /* Delete everything. */
10087         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10088         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10089         cli_rmdir(cli, "\\LISTDIR");
10090
10091 #if 0
10092         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10093         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10094         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10095 #endif
10096
10097         if (!torture_close_connection(cli)) {
10098                 correct = False;
10099         }
10100
10101         printf("finished dirtest1\n");
10102
10103         return correct;
10104 }
10105
10106 static bool run_error_map_extract(int dummy) {
10107
10108         static struct cli_state *c_dos;
10109         static struct cli_state *c_nt;
10110         NTSTATUS status;
10111
10112         uint32_t error;
10113
10114         uint32_t errnum;
10115         uint8_t errclass;
10116
10117         NTSTATUS nt_status;
10118
10119         fstring user;
10120
10121         /* NT-Error connection */
10122
10123         disable_spnego = true;
10124         if (!(c_nt = open_nbt_connection())) {
10125                 disable_spnego = false;
10126                 return False;
10127         }
10128         disable_spnego = false;
10129
10130         status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
10131                                  PROTOCOL_NT1);
10132
10133         if (!NT_STATUS_IS_OK(status)) {
10134                 printf("%s rejected the NT-error negprot (%s)\n", host,
10135                        nt_errstr(status));
10136                 cli_shutdown(c_nt);
10137                 return False;
10138         }
10139
10140         status = cli_session_setup_anon(c_nt);
10141         if (!NT_STATUS_IS_OK(status)) {
10142                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10143                 return False;
10144         }
10145
10146         /* DOS-Error connection */
10147
10148         disable_spnego = true;
10149         force_dos_errors = true;
10150         if (!(c_dos = open_nbt_connection())) {
10151                 disable_spnego = false;
10152                 force_dos_errors = false;
10153                 return False;
10154         }
10155         disable_spnego = false;
10156         force_dos_errors = false;
10157
10158         status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
10159                                  PROTOCOL_NT1);
10160         if (!NT_STATUS_IS_OK(status)) {
10161                 printf("%s rejected the DOS-error negprot (%s)\n", host,
10162                        nt_errstr(status));
10163                 cli_shutdown(c_dos);
10164                 return False;
10165         }
10166
10167         status = cli_session_setup_anon(c_dos);
10168         if (!NT_STATUS_IS_OK(status)) {
10169                 printf("%s rejected the DOS-error initial session setup (%s)\n",
10170                         host, nt_errstr(status));
10171                 return False;
10172         }
10173
10174         c_nt->map_dos_errors = false;
10175         c_dos->map_dos_errors = false;
10176
10177         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10178                 struct cli_credentials *user_creds = NULL;
10179
10180                 fstr_sprintf(user, "%X", error);
10181
10182                 user_creds = cli_session_creds_init(talloc_tos(),
10183                                                     user,
10184                                                     workgroup,
10185                                                     NULL, /* realm */
10186                                                     password,
10187                                                     false, /* use_kerberos */
10188                                                     false, /* fallback_after_kerberos */
10189                                                     false, /* use_ccache */
10190                                                     false); /* password_is_nt_hash */
10191                 if (user_creds == NULL) {
10192                         printf("cli_session_creds_init(%s) failed\n", user);
10193                         return false;
10194                 }
10195
10196                 status = cli_session_setup_creds(c_nt, user_creds);
10197                 if (NT_STATUS_IS_OK(status)) {
10198                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10199                 }
10200
10201                 /* Case #1: 32-bit NT errors */
10202                 if (!NT_STATUS_IS_DOS(status)) {
10203                         nt_status = status;
10204                 } else {
10205                         printf("/** Dos error on NT connection! (%s) */\n", 
10206                                nt_errstr(status));
10207                         nt_status = NT_STATUS(0xc0000000);
10208                 }
10209
10210                 status = cli_session_setup_creds(c_dos, 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                         printf("/** NT error on DOS connection! (%s) */\n", 
10218                                nt_errstr(status));
10219                         errnum = errclass = 0;
10220                 } else {
10221                         errclass = NT_STATUS_DOS_CLASS(status);
10222                         errnum = NT_STATUS_DOS_CODE(status);
10223                 }
10224
10225                 if (NT_STATUS_V(nt_status) != error) { 
10226                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
10227                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
10228                                get_nt_error_c_code(talloc_tos(), nt_status));
10229                 }
10230
10231                 printf("\t{%s,\t%s,\t%s},\n", 
10232                        smb_dos_err_class(errclass), 
10233                        smb_dos_err_name(errclass, errnum), 
10234                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10235
10236                 TALLOC_FREE(user_creds);
10237         }
10238         return True;
10239 }
10240
10241 static bool run_sesssetup_bench(int dummy)
10242 {
10243         static struct cli_state *c;
10244         const char *fname = "\\file.dat";
10245         uint16_t fnum;
10246         NTSTATUS status;
10247         int i;
10248
10249         if (!torture_open_connection(&c, 0)) {
10250                 return false;
10251         }
10252
10253         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10254                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10255                               FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10256         if (!NT_STATUS_IS_OK(status)) {
10257                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10258                 return false;
10259         }
10260
10261         for (i=0; i<torture_numops; i++) {
10262                 status = cli_session_setup_creds(c, torture_creds);
10263                 if (!NT_STATUS_IS_OK(status)) {
10264                         d_printf("(%s) cli_session_setup_creds failed: %s\n",
10265                                  __location__, nt_errstr(status));
10266                         return false;
10267                 }
10268
10269                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
10270
10271                 status = cli_ulogoff(c);
10272                 if (!NT_STATUS_IS_OK(status)) {
10273                         d_printf("(%s) cli_ulogoff failed: %s\n",
10274                                  __location__, nt_errstr(status));
10275                         return false;
10276                 }
10277         }
10278
10279         return true;
10280 }
10281
10282 static bool subst_test(const char *str, const char *user, const char *domain,
10283                        uid_t uid, gid_t gid, const char *expected)
10284 {
10285         char *subst;
10286         bool result = true;
10287
10288         subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10289
10290         if (strcmp(subst, expected) != 0) {
10291                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10292                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10293                        expected);
10294                 result = false;
10295         }
10296
10297         TALLOC_FREE(subst);
10298         return result;
10299 }
10300
10301 static void chain1_open_completion(struct tevent_req *req)
10302 {
10303         uint16_t fnum;
10304         NTSTATUS status;
10305         status = cli_openx_recv(req, &fnum);
10306         TALLOC_FREE(req);
10307
10308         d_printf("cli_openx_recv returned %s: %d\n",
10309                  nt_errstr(status),
10310                  NT_STATUS_IS_OK(status) ? fnum : -1);
10311 }
10312
10313 static void chain1_write_completion(struct tevent_req *req)
10314 {
10315         size_t written;
10316         NTSTATUS status;
10317         status = cli_write_andx_recv(req, &written);
10318         TALLOC_FREE(req);
10319
10320         d_printf("cli_write_andx_recv returned %s: %d\n",
10321                  nt_errstr(status),
10322                  NT_STATUS_IS_OK(status) ? (int)written : -1);
10323 }
10324
10325 static void chain1_close_completion(struct tevent_req *req)
10326 {
10327         NTSTATUS status;
10328         bool *done = (bool *)tevent_req_callback_data_void(req);
10329
10330         status = cli_close_recv(req);
10331         *done = true;
10332
10333         TALLOC_FREE(req);
10334
10335         d_printf("cli_close returned %s\n", nt_errstr(status));
10336 }
10337
10338 static bool run_chain1(int dummy)
10339 {
10340         struct cli_state *cli1;
10341         struct tevent_context *evt = samba_tevent_context_init(NULL);
10342         struct tevent_req *reqs[3], *smbreqs[3];
10343         bool done = false;
10344         const char *str = "foobar";
10345         const char *fname = "\\test_chain";
10346         NTSTATUS status;
10347
10348         printf("starting chain1 test\n");
10349         if (!torture_open_connection(&cli1, 0)) {
10350                 return False;
10351         }
10352
10353         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10354
10355         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10356
10357         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10358                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
10359         if (reqs[0] == NULL) return false;
10360         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10361
10362
10363         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10364                                         (const uint8_t *)str, 0, strlen(str)+1,
10365                                         smbreqs, 1, &smbreqs[1]);
10366         if (reqs[1] == NULL) return false;
10367         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10368
10369         reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10370         if (reqs[2] == NULL) return false;
10371         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10372
10373         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10374         if (!NT_STATUS_IS_OK(status)) {
10375                 return false;
10376         }
10377
10378         while (!done) {
10379                 tevent_loop_once(evt);
10380         }
10381
10382         torture_close_connection(cli1);
10383         return True;
10384 }
10385
10386 static void chain2_sesssetup_completion(struct tevent_req *req)
10387 {
10388         NTSTATUS status;
10389         status = cli_session_setup_guest_recv(req);
10390         d_printf("sesssetup returned %s\n", nt_errstr(status));
10391 }
10392
10393 static void chain2_tcon_completion(struct tevent_req *req)
10394 {
10395         bool *done = (bool *)tevent_req_callback_data_void(req);
10396         NTSTATUS status;
10397         status = cli_tcon_andx_recv(req);
10398         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10399         *done = true;
10400 }
10401
10402 static bool run_chain2(int dummy)
10403 {
10404         struct cli_state *cli1;
10405         struct tevent_context *evt = samba_tevent_context_init(NULL);
10406         struct tevent_req *reqs[2], *smbreqs[2];
10407         bool done = false;
10408         NTSTATUS status;
10409         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10410
10411         printf("starting chain2 test\n");
10412         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10413                                       port_to_use, SMB_SIGNING_DEFAULT, flags);
10414         if (!NT_STATUS_IS_OK(status)) {
10415                 return False;
10416         }
10417
10418         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10419
10420         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10421                                                  &smbreqs[0]);
10422         if (reqs[0] == NULL) return false;
10423         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10424
10425         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10426                                        "?????", NULL, 0, &smbreqs[1]);
10427         if (reqs[1] == NULL) return false;
10428         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10429
10430         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10431         if (!NT_STATUS_IS_OK(status)) {
10432                 return false;
10433         }
10434
10435         while (!done) {
10436                 tevent_loop_once(evt);
10437         }
10438
10439         torture_close_connection(cli1);
10440         return True;
10441 }
10442
10443
10444 struct torture_createdel_state {
10445         struct tevent_context *ev;
10446         struct cli_state *cli;
10447 };
10448
10449 static void torture_createdel_created(struct tevent_req *subreq);
10450 static void torture_createdel_closed(struct tevent_req *subreq);
10451
10452 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10453                                                  struct tevent_context *ev,
10454                                                  struct cli_state *cli,
10455                                                  const char *name)
10456 {
10457         struct tevent_req *req, *subreq;
10458         struct torture_createdel_state *state;
10459
10460         req = tevent_req_create(mem_ctx, &state,
10461                                 struct torture_createdel_state);
10462         if (req == NULL) {
10463                 return NULL;
10464         }
10465         state->ev = ev;
10466         state->cli = cli;
10467
10468         subreq = cli_ntcreate_send(
10469                 state, ev, cli, name, 0,
10470                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10471                 FILE_ATTRIBUTE_NORMAL,
10472                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10473                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10474                 SMB2_IMPERSONATION_IMPERSONATION, 0);
10475
10476         if (tevent_req_nomem(subreq, req)) {
10477                 return tevent_req_post(req, ev);
10478         }
10479         tevent_req_set_callback(subreq, torture_createdel_created, req);
10480         return req;
10481 }
10482
10483 static void torture_createdel_created(struct tevent_req *subreq)
10484 {
10485         struct tevent_req *req = tevent_req_callback_data(
10486                 subreq, struct tevent_req);
10487         struct torture_createdel_state *state = tevent_req_data(
10488                 req, struct torture_createdel_state);
10489         NTSTATUS status;
10490         uint16_t fnum;
10491
10492         status = cli_ntcreate_recv(subreq, &fnum, NULL);
10493         TALLOC_FREE(subreq);
10494         if (tevent_req_nterror(req, status)) {
10495                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10496                            nt_errstr(status)));
10497                 return;
10498         }
10499
10500         subreq = cli_close_send(state, state->ev, state->cli, fnum);
10501         if (tevent_req_nomem(subreq, req)) {
10502                 return;
10503         }
10504         tevent_req_set_callback(subreq, torture_createdel_closed, req);
10505 }
10506
10507 static void torture_createdel_closed(struct tevent_req *subreq)
10508 {
10509         struct tevent_req *req = tevent_req_callback_data(
10510                 subreq, struct tevent_req);
10511         NTSTATUS status;
10512
10513         status = cli_close_recv(subreq);
10514         if (tevent_req_nterror(req, status)) {
10515                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10516                 return;
10517         }
10518         tevent_req_done(req);
10519 }
10520
10521 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10522 {
10523         return tevent_req_simple_recv_ntstatus(req);
10524 }
10525
10526 struct torture_createdels_state {
10527         struct tevent_context *ev;
10528         struct cli_state *cli;
10529         const char *base_name;
10530         int sent;
10531         int received;
10532         int num_files;
10533         struct tevent_req **reqs;
10534 };
10535
10536 static void torture_createdels_done(struct tevent_req *subreq);
10537
10538 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10539                                                   struct tevent_context *ev,
10540                                                   struct cli_state *cli,
10541                                                   const char *base_name,
10542                                                   int num_parallel,
10543                                                   int num_files)
10544 {
10545         struct tevent_req *req;
10546         struct torture_createdels_state *state;
10547         int i;
10548
10549         req = tevent_req_create(mem_ctx, &state,
10550                                 struct torture_createdels_state);
10551         if (req == NULL) {
10552                 return NULL;
10553         }
10554         state->ev = ev;
10555         state->cli = cli;
10556         state->base_name = talloc_strdup(state, base_name);
10557         if (tevent_req_nomem(state->base_name, req)) {
10558                 return tevent_req_post(req, ev);
10559         }
10560         state->num_files = MAX(num_parallel, num_files);
10561         state->sent = 0;
10562         state->received = 0;
10563
10564         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10565         if (tevent_req_nomem(state->reqs, req)) {
10566                 return tevent_req_post(req, ev);
10567         }
10568
10569         for (i=0; i<num_parallel; i++) {
10570                 char *name;
10571
10572                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10573                                        state->sent);
10574                 if (tevent_req_nomem(name, req)) {
10575                         return tevent_req_post(req, ev);
10576                 }
10577                 state->reqs[i] = torture_createdel_send(
10578                         state->reqs, state->ev, state->cli, name);
10579                 if (tevent_req_nomem(state->reqs[i], req)) {
10580                         return tevent_req_post(req, ev);
10581                 }
10582                 name = talloc_move(state->reqs[i], &name);
10583                 tevent_req_set_callback(state->reqs[i],
10584                                         torture_createdels_done, req);
10585                 state->sent += 1;
10586         }
10587         return req;
10588 }
10589
10590 static void torture_createdels_done(struct tevent_req *subreq)
10591 {
10592         struct tevent_req *req = tevent_req_callback_data(
10593                 subreq, struct tevent_req);
10594         struct torture_createdels_state *state = tevent_req_data(
10595                 req, struct torture_createdels_state);
10596         size_t num_parallel = talloc_array_length(state->reqs);
10597         NTSTATUS status;
10598         char *name;
10599         int i;
10600
10601         status = torture_createdel_recv(subreq);
10602         if (!NT_STATUS_IS_OK(status)){
10603                 DEBUG(10, ("torture_createdel_recv returned %s\n",
10604                            nt_errstr(status)));
10605                 TALLOC_FREE(subreq);
10606                 tevent_req_nterror(req, status);
10607                 return;
10608         }
10609
10610         for (i=0; i<num_parallel; i++) {
10611                 if (subreq == state->reqs[i]) {
10612                         break;
10613                 }
10614         }
10615         if (i == num_parallel) {
10616                 DEBUG(10, ("received something we did not send\n"));
10617                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10618                 return;
10619         }
10620         TALLOC_FREE(state->reqs[i]);
10621
10622         if (state->sent >= state->num_files) {
10623                 tevent_req_done(req);
10624                 return;
10625         }
10626
10627         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10628                                state->sent);
10629         if (tevent_req_nomem(name, req)) {
10630                 return;
10631         }
10632         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10633                                                 state->cli, name);
10634         if (tevent_req_nomem(state->reqs[i], req)) {
10635                 return;
10636         }
10637         name = talloc_move(state->reqs[i], &name);
10638         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10639         state->sent += 1;
10640 }
10641
10642 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10643 {
10644         return tevent_req_simple_recv_ntstatus(req);
10645 }
10646
10647 struct swallow_notify_state {
10648         struct tevent_context *ev;
10649         struct cli_state *cli;
10650         uint16_t fnum;
10651         uint32_t completion_filter;
10652         bool recursive;
10653         bool (*fn)(uint32_t action, const char *name, void *priv);
10654         void *priv;
10655 };
10656
10657 static void swallow_notify_done(struct tevent_req *subreq);
10658
10659 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10660                                               struct tevent_context *ev,
10661                                               struct cli_state *cli,
10662                                               uint16_t fnum,
10663                                               uint32_t completion_filter,
10664                                               bool recursive,
10665                                               bool (*fn)(uint32_t action,
10666                                                          const char *name,
10667                                                          void *priv),
10668                                               void *priv)
10669 {
10670         struct tevent_req *req, *subreq;
10671         struct swallow_notify_state *state;
10672
10673         req = tevent_req_create(mem_ctx, &state,
10674                                 struct swallow_notify_state);
10675         if (req == NULL) {
10676                 return NULL;
10677         }
10678         state->ev = ev;
10679         state->cli = cli;
10680         state->fnum = fnum;
10681         state->completion_filter = completion_filter;
10682         state->recursive = recursive;
10683         state->fn = fn;
10684         state->priv = priv;
10685
10686         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10687                                  0xffff, state->completion_filter,
10688                                  state->recursive);
10689         if (tevent_req_nomem(subreq, req)) {
10690                 return tevent_req_post(req, ev);
10691         }
10692         tevent_req_set_callback(subreq, swallow_notify_done, req);
10693         return req;
10694 }
10695
10696 static void swallow_notify_done(struct tevent_req *subreq)
10697 {
10698         struct tevent_req *req = tevent_req_callback_data(
10699                 subreq, struct tevent_req);
10700         struct swallow_notify_state *state = tevent_req_data(
10701                 req, struct swallow_notify_state);
10702         NTSTATUS status;
10703         uint32_t i, num_changes;
10704         struct notify_change *changes;
10705
10706         status = cli_notify_recv(subreq, state, &num_changes, &changes);
10707         TALLOC_FREE(subreq);
10708         if (!NT_STATUS_IS_OK(status)) {
10709                 DEBUG(10, ("cli_notify_recv returned %s\n",
10710                            nt_errstr(status)));
10711                 tevent_req_nterror(req, status);
10712                 return;
10713         }
10714
10715         for (i=0; i<num_changes; i++) {
10716                 state->fn(changes[i].action, changes[i].name, state->priv);
10717         }
10718         TALLOC_FREE(changes);
10719
10720         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10721                                  0xffff, state->completion_filter,
10722                                  state->recursive);
10723         if (tevent_req_nomem(subreq, req)) {
10724                 return;
10725         }
10726         tevent_req_set_callback(subreq, swallow_notify_done, req);
10727 }
10728
10729 static bool print_notifies(uint32_t action, const char *name, void *priv)
10730 {
10731         if (DEBUGLEVEL > 5) {
10732                 d_printf("%d %s\n", (int)action, name);
10733         }
10734         return true;
10735 }
10736
10737 static void notify_bench_done(struct tevent_req *req)
10738 {
10739         int *num_finished = (int *)tevent_req_callback_data_void(req);
10740         *num_finished += 1;
10741 }
10742
10743 static bool run_notify_bench(int dummy)
10744 {
10745         const char *dname = "\\notify-bench";
10746         struct tevent_context *ev;
10747         NTSTATUS status;
10748         uint16_t dnum;
10749         struct tevent_req *req1;
10750         struct tevent_req *req2 = NULL;
10751         int i, num_unc_names;
10752         int num_finished = 0;
10753
10754         printf("starting notify-bench test\n");
10755
10756         if (use_multishare_conn) {
10757                 char **unc_list;
10758                 unc_list = file_lines_load(multishare_conn_fname,
10759                                            &num_unc_names, 0, NULL);
10760                 if (!unc_list || num_unc_names <= 0) {
10761                         d_printf("Failed to load unc names list from '%s'\n",
10762                                  multishare_conn_fname);
10763                         return false;
10764                 }
10765                 TALLOC_FREE(unc_list);
10766         } else {
10767                 num_unc_names = 1;
10768         }
10769
10770         ev = samba_tevent_context_init(talloc_tos());
10771         if (ev == NULL) {
10772                 d_printf("tevent_context_init failed\n");
10773                 return false;
10774         }
10775
10776         for (i=0; i<num_unc_names; i++) {
10777                 struct cli_state *cli;
10778                 char *base_fname;
10779
10780                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
10781                                              dname, i);
10782                 if (base_fname == NULL) {
10783                         return false;
10784                 }
10785
10786                 if (!torture_open_connection(&cli, i)) {
10787                         return false;
10788                 }
10789
10790                 status = cli_ntcreate(cli, dname, 0,
10791                                       MAXIMUM_ALLOWED_ACCESS,
10792                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
10793                                       FILE_SHARE_DELETE,
10794                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
10795                                       &dnum, NULL);
10796
10797                 if (!NT_STATUS_IS_OK(status)) {
10798                         d_printf("Could not create %s: %s\n", dname,
10799                                  nt_errstr(status));
10800                         return false;
10801                 }
10802
10803                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
10804                                            FILE_NOTIFY_CHANGE_FILE_NAME |
10805                                            FILE_NOTIFY_CHANGE_DIR_NAME |
10806                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
10807                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
10808                                            false, print_notifies, NULL);
10809                 if (req1 == NULL) {
10810                         d_printf("Could not create notify request\n");
10811                         return false;
10812                 }
10813
10814                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
10815                                                base_fname, 10, torture_numops);
10816                 if (req2 == NULL) {
10817                         d_printf("Could not create createdels request\n");
10818                         return false;
10819                 }
10820                 TALLOC_FREE(base_fname);
10821
10822                 tevent_req_set_callback(req2, notify_bench_done,
10823                                         &num_finished);
10824         }
10825
10826         while (num_finished < num_unc_names) {
10827                 int ret;
10828                 ret = tevent_loop_once(ev);
10829                 if (ret != 0) {
10830                         d_printf("tevent_loop_once failed\n");
10831                         return false;
10832                 }
10833         }
10834
10835         if (!tevent_req_poll(req2, ev)) {
10836                 d_printf("tevent_req_poll failed\n");
10837         }
10838
10839         status = torture_createdels_recv(req2);
10840         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
10841
10842         return true;
10843 }
10844
10845 static bool run_mangle1(int dummy)
10846 {
10847         struct cli_state *cli;
10848         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
10849         uint16_t fnum;
10850         fstring alt_name;
10851         NTSTATUS status;
10852         time_t change_time, access_time, write_time;
10853         off_t size;
10854         uint32_t attr;
10855
10856         printf("starting mangle1 test\n");
10857         if (!torture_open_connection(&cli, 0)) {
10858                 return False;
10859         }
10860
10861         smbXcli_conn_set_sockopt(cli->conn, sockops);
10862
10863         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10864                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10865                               0, 0, &fnum, NULL);
10866         if (!NT_STATUS_IS_OK(status)) {
10867                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10868                 return false;
10869         }
10870         cli_close(cli, fnum);
10871
10872         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
10873         if (!NT_STATUS_IS_OK(status)) {
10874                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
10875                          nt_errstr(status));
10876                 return false;
10877         }
10878         d_printf("alt_name: %s\n", alt_name);
10879
10880         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
10881         if (!NT_STATUS_IS_OK(status)) {
10882                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
10883                          nt_errstr(status));
10884                 return false;
10885         }
10886         cli_close(cli, fnum);
10887
10888         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
10889                                 &write_time, &size, &attr);
10890         if (!NT_STATUS_IS_OK(status)) {
10891                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
10892                          nt_errstr(status));
10893                 return false;
10894         }
10895
10896         return true;
10897 }
10898
10899 static NTSTATUS mangle_illegal_list_shortname_fn(const char *mntpoint,
10900                                                  struct file_info *f,
10901                                                  const char *mask,
10902                                                  void *state)
10903 {
10904         if (f->short_name == NULL) {
10905                 return NT_STATUS_OK;
10906         }
10907
10908         if (strlen(f->short_name) == 0) {
10909                 return NT_STATUS_OK;
10910         }
10911
10912         printf("unexpected shortname: %s\n", f->short_name);
10913
10914         return NT_STATUS_OBJECT_NAME_INVALID;
10915 }
10916
10917 static NTSTATUS mangle_illegal_list_name_fn(const char *mntpoint,
10918                                             struct file_info *f,
10919                                             const char *mask,
10920                                             void *state)
10921 {
10922         char *name = state;
10923
10924         printf("name: %s\n", f->name);
10925         fstrcpy(name, f->name);
10926         return NT_STATUS_OK;
10927 }
10928
10929 static bool run_mangle_illegal(int dummy)
10930 {
10931         struct cli_state *cli = NULL;
10932         struct cli_state *cli_posix = NULL;
10933         const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
10934         const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
10935         char *mangled_path = NULL;
10936         uint16_t fnum;
10937         fstring name;
10938         fstring alt_name;
10939         NTSTATUS status;
10940
10941         printf("starting mangle-illegal test\n");
10942
10943         if (!torture_open_connection(&cli, 0)) {
10944                 return False;
10945         }
10946
10947         smbXcli_conn_set_sockopt(cli->conn, sockops);
10948
10949         if (!torture_open_connection(&cli_posix, 0)) {
10950                 return false;
10951         }
10952
10953         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
10954
10955         status = torture_setup_unix_extensions(cli_posix);
10956         if (!NT_STATUS_IS_OK(status)) {
10957                 return false;
10958         }
10959
10960         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
10961         status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
10962         if (!NT_STATUS_IS_OK(status)) {
10963                 printf("mkdir1 failed : %s\n", nt_errstr(status));
10964                 return False;
10965         }
10966
10967         /*
10968          * Create a file with illegal NTFS characters and test that we
10969          * get a usable mangled name
10970          */
10971
10972         cli_setatr(cli_posix, illegal_fname, 0, 0);
10973         cli_posix_unlink(cli_posix, illegal_fname);
10974
10975         status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
10976                                 0600, &fnum);
10977         if (!NT_STATUS_IS_OK(status)) {
10978                 printf("POSIX create of %s failed (%s)\n",
10979                        illegal_fname, nt_errstr(status));
10980                 return false;
10981         }
10982
10983         status = cli_close(cli_posix, fnum);
10984         if (!NT_STATUS_IS_OK(status)) {
10985                 printf("close failed (%s)\n", nt_errstr(status));
10986                 return false;
10987         }
10988
10989         status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
10990         if (!NT_STATUS_IS_OK(status)) {
10991                 d_printf("cli_list failed: %s\n", nt_errstr(status));
10992                 return false;
10993         }
10994
10995         mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
10996         if (mangled_path == NULL) {
10997                 return false;
10998         }
10999
11000         status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11001         if (!NT_STATUS_IS_OK(status)) {
11002                 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11003                 TALLOC_FREE(mangled_path);
11004                 return false;
11005         }
11006         TALLOC_FREE(mangled_path);
11007         cli_close(cli, fnum);
11008
11009         cli_setatr(cli_posix, illegal_fname, 0, 0);
11010         cli_posix_unlink(cli_posix, illegal_fname);
11011
11012         /*
11013          * Create a file with a long name and check that we got *no* short name.
11014          */
11015
11016         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11017                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11018                               0, 0, &fnum, NULL);
11019         if (!NT_STATUS_IS_OK(status)) {
11020                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11021                 return false;
11022         }
11023         cli_close(cli, fnum);
11024
11025         status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11026         if (!NT_STATUS_IS_OK(status)) {
11027                 d_printf("cli_list failed\n");
11028                 return false;
11029         }
11030
11031         cli_unlink(cli, fname, 0);
11032         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11033
11034         if (!torture_close_connection(cli_posix)) {
11035                 return false;
11036         }
11037
11038         if (!torture_close_connection(cli)) {
11039                 return false;
11040         }
11041
11042         return true;
11043 }
11044
11045 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11046 {
11047         size_t *to_pull = (size_t *)priv;
11048         size_t thistime = *to_pull;
11049
11050         thistime = MIN(thistime, n);
11051         if (thistime == 0) {
11052                 return 0;
11053         }
11054
11055         memset(buf, 0, thistime);
11056         *to_pull -= thistime;
11057         return thistime;
11058 }
11059
11060 static bool run_windows_write(int dummy)
11061 {
11062         struct cli_state *cli1;
11063         uint16_t fnum;
11064         int i;
11065         bool ret = false;
11066         const char *fname = "\\writetest.txt";
11067         struct timeval start_time;
11068         double seconds;
11069         double kbytes;
11070         NTSTATUS status;
11071
11072         printf("starting windows_write test\n");
11073         if (!torture_open_connection(&cli1, 0)) {
11074                 return False;
11075         }
11076
11077         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11078         if (!NT_STATUS_IS_OK(status)) {
11079                 printf("open failed (%s)\n", nt_errstr(status));
11080                 return False;
11081         }
11082
11083         smbXcli_conn_set_sockopt(cli1->conn, sockops);
11084
11085         start_time = timeval_current();
11086
11087         for (i=0; i<torture_numops; i++) {
11088                 uint8_t c = 0;
11089                 off_t start = i * torture_blocksize;
11090                 size_t to_pull = torture_blocksize - 1;
11091
11092                 status = cli_writeall(cli1, fnum, 0, &c,
11093                                       start + torture_blocksize - 1, 1, NULL);
11094                 if (!NT_STATUS_IS_OK(status)) {
11095                         printf("cli_write failed: %s\n", nt_errstr(status));
11096                         goto fail;
11097                 }
11098
11099                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11100                                   null_source, &to_pull);
11101                 if (!NT_STATUS_IS_OK(status)) {
11102                         printf("cli_push returned: %s\n", nt_errstr(status));
11103                         goto fail;
11104                 }
11105         }
11106
11107         seconds = timeval_elapsed(&start_time);
11108         kbytes = (double)torture_blocksize * torture_numops;
11109         kbytes /= 1024;
11110
11111         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11112                (double)seconds, (int)(kbytes/seconds));
11113
11114         ret = true;
11115  fail:
11116         cli_close(cli1, fnum);
11117         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11118         torture_close_connection(cli1);
11119         return ret;
11120 }
11121
11122 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11123 {
11124         size_t max_pdu = 0x1FFFF;
11125
11126         if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11127                 max_pdu = 0xFFFFFF;
11128         }
11129
11130         if (smb1cli_conn_signing_is_active(cli->conn)) {
11131                 max_pdu = 0x1FFFF;
11132         }
11133
11134         if (smb1cli_conn_encryption_on(cli->conn)) {
11135                 max_pdu = CLI_BUFFER_SIZE;
11136         }
11137
11138         if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11139                 len_requested &= 0xFFFF;
11140         }
11141
11142         return MIN(len_requested,
11143                    max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11144 }
11145
11146 static bool check_read_call(struct cli_state *cli,
11147                             uint16_t fnum,
11148                             uint8_t *buf,
11149                             size_t len_requested)
11150 {
11151         NTSTATUS status;
11152         struct tevent_req *subreq = NULL;
11153         ssize_t len_read = 0;
11154         size_t len_expected = 0;
11155         struct tevent_context *ev = NULL;
11156
11157         ev = samba_tevent_context_init(talloc_tos());
11158         if (ev == NULL) {
11159                 return false;
11160         }
11161
11162         subreq = cli_read_andx_send(talloc_tos(),
11163                                     ev,
11164                                     cli,
11165                                     fnum,
11166                                     0,
11167                                     len_requested);
11168
11169         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11170                 return false;
11171         }
11172
11173         status = cli_read_andx_recv(subreq, &len_read, &buf);
11174         if (!NT_STATUS_IS_OK(status)) {
11175                 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11176                 return false;
11177         }
11178
11179         TALLOC_FREE(subreq);
11180         TALLOC_FREE(ev);
11181
11182         len_expected = calc_expected_return(cli, len_requested);
11183
11184         if (len_expected > 0x10000 && len_read == 0x10000) {
11185                 /* Windows servers only return a max of 0x10000,
11186                    doesn't matter if you set CAP_LARGE_READX in
11187                    the client sessionsetupX call or not. */
11188                 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11189                         (unsigned int)len_requested);
11190         } else if (len_read != len_expected) {
11191                 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11192                         (unsigned int)len_requested,
11193                         (unsigned int)len_read,
11194                         (unsigned int)len_expected);
11195                 return false;
11196         } else {
11197                 d_printf("Correct read reply.\n");
11198         }
11199
11200         return true;
11201 }
11202
11203 /* Test large readX variants. */
11204 static bool large_readx_tests(struct cli_state *cli,
11205                                 uint16_t fnum,
11206                                 uint8_t *buf)
11207 {
11208         /* A read of 0xFFFF0001 should *always* return 1 byte. */
11209         if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11210                 return false;
11211         }
11212         /* A read of 0x10000 should return 0x10000 bytes. */
11213         if (check_read_call(cli, fnum, buf,    0x10000) == false) {
11214                 return false;
11215         }
11216         /* A read of 0x10000 should return 0x10001 bytes. */
11217         if (check_read_call(cli, fnum, buf,    0x10001) == false) {
11218                 return false;
11219         }
11220         /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11221            the requested number of bytes. */
11222         if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11223                 return false;
11224         }
11225         /* A read of 1MB should return 1MB bytes (on Samba). */
11226         if (check_read_call(cli, fnum, buf,   0x100000) == false) {
11227                 return false;
11228         }
11229
11230         if (check_read_call(cli, fnum, buf,    0x20001) == false) {
11231                 return false;
11232         }
11233         if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11234                 return false;
11235         }
11236         if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11237                 return false;
11238         }
11239         return true;
11240 }
11241
11242 static bool run_large_readx(int dummy)
11243 {
11244         uint8_t *buf = NULL;
11245         struct cli_state *cli1 = NULL;
11246         struct cli_state *cli2 = NULL;
11247         bool correct = false;
11248         const char *fname = "\\large_readx.dat";
11249         NTSTATUS status;
11250         uint16_t fnum1 = UINT16_MAX;
11251         uint32_t normal_caps = 0;
11252         size_t file_size = 20*1024*1024;
11253         TALLOC_CTX *frame = talloc_stackframe();
11254         size_t i;
11255         struct {
11256                 const char *name;
11257                 enum smb_signing_setting signing_setting;
11258                 enum protocol_types protocol;
11259         } runs[] = {
11260                 {
11261                         .name = "NT1",
11262                         .signing_setting = SMB_SIGNING_IF_REQUIRED,
11263                         .protocol = PROTOCOL_NT1,
11264                 },{
11265                         .name = "NT1 - SIGNING_REQUIRED",
11266                         .signing_setting = SMB_SIGNING_REQUIRED,
11267                         .protocol = PROTOCOL_NT1,
11268                 },
11269         };
11270
11271         printf("starting large_readx test\n");
11272
11273         if (!torture_open_connection(&cli1, 0)) {
11274                 goto out;
11275         }
11276
11277         normal_caps = smb1cli_conn_capabilities(cli1->conn);
11278
11279         if (!(normal_caps & CAP_LARGE_READX)) {
11280                 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11281                         (unsigned int)normal_caps);
11282                 goto out;
11283         }
11284
11285         /* Create a file of size 4MB. */
11286         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11287                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11288                         0, 0, &fnum1, NULL);
11289
11290         if (!NT_STATUS_IS_OK(status)) {
11291                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11292                 goto out;
11293         }
11294
11295         /* Write file_size bytes. */
11296         buf = talloc_zero_array(frame, uint8_t, file_size);
11297         if (buf == NULL) {
11298                 goto out;
11299         }
11300
11301         status = cli_writeall(cli1,
11302                               fnum1,
11303                               0,
11304                               buf,
11305                               0,
11306                               file_size,
11307                               NULL);
11308         if (!NT_STATUS_IS_OK(status)) {
11309                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11310                 goto out;
11311         }
11312
11313         status = cli_close(cli1, fnum1);
11314         if (!NT_STATUS_IS_OK(status)) {
11315                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11316                 goto out;
11317         }
11318
11319         fnum1 = UINT16_MAX;
11320
11321         for (i=0; i < ARRAY_SIZE(runs); i++) {
11322                 enum smb_signing_setting saved_signing_setting = signing_state;
11323                 uint16_t fnum2 = -1;
11324
11325                 if (do_encrypt &&
11326                     (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11327                 {
11328                         d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11329                         continue;
11330                 }
11331
11332                 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11333
11334                 signing_state = runs[i].signing_setting;
11335                 cli2 = open_nbt_connection();
11336                 signing_state = saved_signing_setting;
11337                 if (cli2 == NULL) {
11338                         goto out;
11339                 }
11340
11341                 status = smbXcli_negprot(cli2->conn,
11342                                          cli2->timeout,
11343                                          runs[i].protocol,
11344                                          runs[i].protocol);
11345                 if (!NT_STATUS_IS_OK(status)) {
11346                         goto out;
11347                 }
11348
11349                 status = cli_session_setup_creds(cli2, torture_creds);
11350                 if (!NT_STATUS_IS_OK(status)) {
11351                         goto out;
11352                 }
11353
11354                 status = cli_tree_connect(cli2,
11355                                         share,
11356                                         "?????",
11357                                         password);
11358                 if (!NT_STATUS_IS_OK(status)) {
11359                         goto out;
11360                 }
11361
11362                 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11363
11364                 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11365
11366                 if (!(normal_caps & CAP_LARGE_READX)) {
11367                         d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11368                                 (unsigned int)normal_caps);
11369                         goto out;
11370                 }
11371
11372                 if (do_encrypt) {
11373                         if (force_cli_encryption(cli2, share) == false) {
11374                                 goto out;
11375                         }
11376                 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11377                         uint16_t major, minor;
11378                         uint32_t caplow, caphigh;
11379
11380                         status = cli_unix_extensions_version(cli2,
11381                                                              &major, &minor,
11382                                                              &caplow, &caphigh);
11383                         if (!NT_STATUS_IS_OK(status)) {
11384                                 goto out;
11385                         }
11386                 }
11387
11388                 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11389                                 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11390                                 0, 0, &fnum2, NULL);
11391                 if (!NT_STATUS_IS_OK(status)) {
11392                         d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11393                         goto out;
11394                 }
11395
11396                 /* All reads must return less than file_size bytes. */
11397                 if (!large_readx_tests(cli2, fnum2, buf)) {
11398                         goto out;
11399                 }
11400
11401                 status = cli_close(cli2, fnum2);
11402                 if (!NT_STATUS_IS_OK(status)) {
11403                         d_printf("cli_close failed: %s\n", nt_errstr(status));
11404                         goto out;
11405                 }
11406                 fnum2 = -1;
11407
11408                 if (!torture_close_connection(cli2)) {
11409                         goto out;
11410                 }
11411                 cli2 = NULL;
11412         }
11413
11414         correct = true;
11415         printf("Success on large_readx test\n");
11416
11417   out:
11418
11419         if (cli2) {
11420                 if (!torture_close_connection(cli2)) {
11421                         correct = false;
11422                 }
11423         }
11424
11425         if (cli1) {
11426                 if (fnum1 != UINT16_MAX) {
11427                         status = cli_close(cli1, fnum1);
11428                         if (!NT_STATUS_IS_OK(status)) {
11429                                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11430                         }
11431                         fnum1 = UINT16_MAX;
11432                 }
11433
11434                 status = cli_unlink(cli1, fname,
11435                                     FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11436                 if (!NT_STATUS_IS_OK(status)) {
11437                         printf("unlink failed (%s)\n", nt_errstr(status));
11438                 }
11439
11440                 if (!torture_close_connection(cli1)) {
11441                         correct = false;
11442                 }
11443         }
11444
11445         TALLOC_FREE(frame);
11446
11447         printf("finished large_readx test\n");
11448         return correct;
11449 }
11450
11451 static NTSTATUS msdfs_attribute_list_fn(const char *mnt,
11452                                   struct file_info *finfo,
11453                                   const char *mask,
11454                                   void *private_data)
11455 {
11456         uint32_t *p_attr = (uint32_t *)private_data;
11457
11458         if (strequal(finfo->name, test_filename)) {
11459                 *p_attr = finfo->attr;
11460         }
11461
11462         return NT_STATUS_OK;
11463 }
11464
11465 static bool run_msdfs_attribute(int dummy)
11466 {
11467         static struct cli_state *cli;
11468         bool correct = false;
11469         uint32_t attr = 0;
11470         NTSTATUS status;
11471
11472         printf("Starting MSDFS-ATTRIBUTE test\n");
11473
11474         if (test_filename == NULL || test_filename[0] == '\0') {
11475                 printf("MSDFS-ATTRIBUTE test "
11476                         "needs -f filename-of-msdfs-link\n");
11477                 return false;
11478         }
11479
11480         /*
11481          * NB. We use torture_open_connection_flags() not
11482          * torture_open_connection() as the latter forces
11483          * SMB1.
11484          */
11485         if (!torture_open_connection_flags(&cli, 0, 0)) {
11486                 return false;
11487         }
11488
11489         smbXcli_conn_set_sockopt(cli->conn, sockops);
11490
11491         status = cli_list(cli,
11492                         "*",
11493                         FILE_ATTRIBUTE_DIRECTORY,
11494                         msdfs_attribute_list_fn,
11495                         &attr);
11496
11497         if (!NT_STATUS_IS_OK(status)) {
11498                 printf("cli_list failed with %s\n",
11499                         nt_errstr(status));
11500                 goto out;
11501         }
11502         if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11503                 printf("file %s should have "
11504                         "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11505                         test_filename,
11506                         (unsigned int)attr);
11507                 goto out;
11508         }
11509
11510         if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11511                 printf("file %s should have "
11512                         "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11513                         test_filename,
11514                         (unsigned int)attr);
11515                 goto out;
11516         }
11517
11518         correct = true;
11519
11520   out:
11521
11522         torture_close_connection(cli);
11523         return correct;
11524 }
11525
11526 static bool run_cli_echo(int dummy)
11527 {
11528         struct cli_state *cli;
11529         NTSTATUS status;
11530
11531         printf("starting cli_echo test\n");
11532         if (!torture_open_connection(&cli, 0)) {
11533                 return false;
11534         }
11535         smbXcli_conn_set_sockopt(cli->conn, sockops);
11536
11537         status = cli_echo(cli, 5, data_blob_const("hello", 5));
11538
11539         d_printf("cli_echo returned %s\n", nt_errstr(status));
11540
11541         torture_close_connection(cli);
11542         return NT_STATUS_IS_OK(status);
11543 }
11544
11545 static int splice_status(off_t written, void *priv)
11546 {
11547         return true;
11548 }
11549
11550 static bool run_cli_splice(int dummy)
11551 {
11552         uint8_t *buf = NULL;
11553         struct cli_state *cli1 = NULL;
11554         bool correct = false;
11555         const char *fname_src = "\\splice_src.dat";
11556         const char *fname_dst = "\\splice_dst.dat";
11557         NTSTATUS status;
11558         uint16_t fnum1 = UINT16_MAX;
11559         uint16_t fnum2 = UINT16_MAX;
11560         size_t file_size = 2*1024*1024;
11561         size_t splice_size = 1*1024*1024 + 713;
11562         uint8_t digest1[16], digest2[16];
11563         off_t written = 0;
11564         size_t nread = 0;
11565         TALLOC_CTX *frame = talloc_stackframe();
11566
11567         printf("starting cli_splice test\n");
11568
11569         if (!torture_open_connection(&cli1, 0)) {
11570                 goto out;
11571         }
11572
11573         cli_unlink(cli1, fname_src,
11574                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11575         cli_unlink(cli1, fname_dst,
11576                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11577
11578         /* Create a file */
11579         status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11580                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11581                         0, 0, &fnum1, NULL);
11582
11583         if (!NT_STATUS_IS_OK(status)) {
11584                 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11585                 goto out;
11586         }
11587
11588         /* Write file_size bytes - must be bigger than splice_size. */
11589         buf = talloc_zero_array(frame, uint8_t, file_size);
11590         if (buf == NULL) {
11591                 d_printf("talloc_fail\n");
11592                 goto out;
11593         }
11594
11595         /* Fill it with random numbers. */
11596         generate_random_buffer(buf, file_size);
11597
11598         /* MD5 the first 1MB + 713 bytes. */
11599         gnutls_hash_fast(GNUTLS_DIG_MD5,
11600                          buf,
11601                          splice_size,
11602                          digest1);
11603
11604         status = cli_writeall(cli1,
11605                               fnum1,
11606                               0,
11607                               buf,
11608                               0,
11609                               file_size,
11610                               NULL);
11611         if (!NT_STATUS_IS_OK(status)) {
11612                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11613                 goto out;
11614         }
11615
11616         status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11617                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11618                         0, 0, &fnum2, NULL);
11619
11620         if (!NT_STATUS_IS_OK(status)) {
11621                 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11622                 goto out;
11623         }
11624
11625         /* Now splice 1MB + 713 bytes. */
11626         status = cli_splice(cli1,
11627                                 cli1,
11628                                 fnum1,
11629                                 fnum2,
11630                                 splice_size,
11631                                 0,
11632                                 0,
11633                                 &written,
11634                                 splice_status,
11635                                 NULL);
11636
11637         if (!NT_STATUS_IS_OK(status)) {
11638                 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11639                 goto out;
11640         }
11641
11642         /* Clear the old buffer. */
11643         memset(buf, '\0', file_size);
11644
11645         /* Read the new file. */
11646         status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11647         if (!NT_STATUS_IS_OK(status)) {
11648                 d_printf("cli_read failed: %s\n", nt_errstr(status));
11649                 goto out;
11650         }
11651         if (nread != splice_size) {
11652                 d_printf("bad read of 0x%x, should be 0x%x\n",
11653                         (unsigned int)nread,
11654                         (unsigned int)splice_size);
11655                 goto out;
11656         }
11657
11658         /* MD5 the first 1MB + 713 bytes. */
11659         gnutls_hash_fast(GNUTLS_DIG_MD5,
11660                          buf,
11661                          splice_size,
11662                          digest2);
11663
11664         /* Must be the same. */
11665         if (memcmp(digest1, digest2, 16) != 0) {
11666                 d_printf("bad MD5 compare\n");
11667                 goto out;
11668         }
11669
11670         correct = true;
11671         printf("Success on cli_splice test\n");
11672
11673   out:
11674
11675         if (cli1) {
11676                 if (fnum1 != UINT16_MAX) {
11677                         cli_close(cli1, fnum1);
11678                 }
11679                 if (fnum2 != UINT16_MAX) {
11680                         cli_close(cli1, fnum2);
11681                 }
11682
11683                 cli_unlink(cli1, fname_src,
11684                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11685                 cli_unlink(cli1, fname_dst,
11686                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11687
11688                 if (!torture_close_connection(cli1)) {
11689                         correct = false;
11690                 }
11691         }
11692
11693         TALLOC_FREE(frame);
11694         return correct;
11695 }
11696
11697 static bool run_uid_regression_test(int dummy)
11698 {
11699         static struct cli_state *cli;
11700         int16_t old_vuid;
11701         int32_t old_cnum;
11702         bool correct = True;
11703         struct smbXcli_tcon *orig_tcon = NULL;
11704         NTSTATUS status;
11705
11706         printf("starting uid regression test\n");
11707
11708         if (!torture_open_connection(&cli, 0)) {
11709                 return False;
11710         }
11711
11712         smbXcli_conn_set_sockopt(cli->conn, sockops);
11713
11714         /* Ok - now save then logoff our current user. */
11715         old_vuid = cli_state_get_uid(cli);
11716
11717         status = cli_ulogoff(cli);
11718         if (!NT_STATUS_IS_OK(status)) {
11719                 d_printf("(%s) cli_ulogoff failed: %s\n",
11720                          __location__, nt_errstr(status));
11721                 correct = false;
11722                 goto out;
11723         }
11724
11725         cli_state_set_uid(cli, old_vuid);
11726
11727         /* Try an operation. */
11728         status = cli_mkdir(cli, "\\uid_reg_test");
11729         if (NT_STATUS_IS_OK(status)) {
11730                 d_printf("(%s) cli_mkdir succeeded\n",
11731                          __location__);
11732                 correct = false;
11733                 goto out;
11734         } else {
11735                 /* Should be bad uid. */
11736                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11737                                  NT_STATUS_USER_SESSION_DELETED)) {
11738                         correct = false;
11739                         goto out;
11740                 }
11741         }
11742
11743         old_cnum = cli_state_get_tid(cli);
11744         orig_tcon = cli_state_save_tcon(cli);
11745         if (orig_tcon == NULL) {
11746                 correct = false;
11747                 goto out;
11748         }
11749
11750         /* Now try a SMBtdis with the invalid vuid set to zero. */
11751         cli_state_set_uid(cli, 0);
11752
11753         /* This should succeed. */
11754         status = cli_tdis(cli);
11755
11756         if (NT_STATUS_IS_OK(status)) {
11757                 d_printf("First tdis with invalid vuid should succeed.\n");
11758         } else {
11759                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
11760                 correct = false;
11761                 cli_state_restore_tcon(cli, orig_tcon);
11762                 goto out;
11763         }
11764
11765         cli_state_restore_tcon(cli, orig_tcon);
11766         cli_state_set_uid(cli, old_vuid);
11767         cli_state_set_tid(cli, old_cnum);
11768
11769         /* This should fail. */
11770         status = cli_tdis(cli);
11771         if (NT_STATUS_IS_OK(status)) {
11772                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
11773                 correct = false;
11774                 goto out;
11775         } else {
11776                 /* Should be bad tid. */
11777                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
11778                                 NT_STATUS_NETWORK_NAME_DELETED)) {
11779                         correct = false;
11780                         goto out;
11781                 }
11782         }
11783
11784         cli_rmdir(cli, "\\uid_reg_test");
11785
11786   out:
11787
11788         cli_shutdown(cli);
11789         return correct;
11790 }
11791
11792
11793 static const char *illegal_chars = "*\\/?<>|\":";
11794 static char force_shortname_chars[] = " +,.[];=\177";
11795
11796 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
11797                              const char *mask, void *state)
11798 {
11799         struct cli_state *pcli = (struct cli_state *)state;
11800         fstring fname;
11801         NTSTATUS status = NT_STATUS_OK;
11802
11803         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
11804
11805         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
11806                 return NT_STATUS_OK;
11807
11808         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
11809                 status = cli_rmdir(pcli, fname);
11810                 if (!NT_STATUS_IS_OK(status)) {
11811                         printf("del_fn: failed to rmdir %s\n,", fname );
11812                 }
11813         } else {
11814                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11815                 if (!NT_STATUS_IS_OK(status)) {
11816                         printf("del_fn: failed to unlink %s\n,", fname );
11817                 }
11818         }
11819         return status;
11820 }
11821
11822 struct sn_state {
11823         int matched;
11824         int i;
11825         bool val;
11826 };
11827
11828 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
11829                               const char *name, void *state)
11830 {
11831         struct sn_state *s = (struct sn_state  *)state;
11832         int i = s->i;
11833
11834 #if 0
11835         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
11836                 i, finfo->name, finfo->short_name);
11837 #endif
11838
11839         if (strchr(force_shortname_chars, i)) {
11840                 if (!finfo->short_name) {
11841                         /* Shortname not created when it should be. */
11842                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
11843                                 __location__, finfo->name, i);
11844                         s->val = true;
11845                 }
11846         } else if (finfo->short_name){
11847                 /* Shortname created when it should not be. */
11848                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
11849                         __location__, finfo->short_name, finfo->name);
11850                 s->val = true;
11851         }
11852         s->matched += 1;
11853         return NT_STATUS_OK;
11854 }
11855
11856 static bool run_shortname_test(int dummy)
11857 {
11858         static struct cli_state *cli;
11859         bool correct = True;
11860         int i;
11861         struct sn_state s;
11862         char fname[40];
11863         NTSTATUS status;
11864
11865         printf("starting shortname test\n");
11866
11867         if (!torture_open_connection(&cli, 0)) {
11868                 return False;
11869         }
11870
11871         smbXcli_conn_set_sockopt(cli->conn, sockops);
11872
11873         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11874         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11875         cli_rmdir(cli, "\\shortname");
11876
11877         status = cli_mkdir(cli, "\\shortname");
11878         if (!NT_STATUS_IS_OK(status)) {
11879                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
11880                         __location__, nt_errstr(status));
11881                 correct = false;
11882                 goto out;
11883         }
11884
11885         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
11886                 correct = false;
11887                 goto out;
11888         }
11889         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
11890                 correct = false;
11891                 goto out;
11892         }
11893
11894         s.val = false;
11895
11896         for (i = 32; i < 128; i++) {
11897                 uint16_t fnum = (uint16_t)-1;
11898
11899                 s.i = i;
11900
11901                 if (strchr(illegal_chars, i)) {
11902                         continue;
11903                 }
11904                 fname[15] = i;
11905
11906                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
11907                                    FILE_SHARE_READ|FILE_SHARE_WRITE,
11908                                    FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
11909                 if (!NT_STATUS_IS_OK(status)) {
11910                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
11911                                 __location__, fname, nt_errstr(status));
11912                         correct = false;
11913                         goto out;
11914                 }
11915                 cli_close(cli, fnum);
11916
11917                 s.matched = 0;
11918                 status = cli_list(cli, "\\shortname\\test*.*", 0,
11919                                   shortname_list_fn, &s);
11920                 if (s.matched != 1) {
11921                         d_printf("(%s) failed to list %s: %s\n",
11922                                 __location__, fname, nt_errstr(status));
11923                         correct = false;
11924                         goto out;
11925                 }
11926
11927                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11928                 if (!NT_STATUS_IS_OK(status)) {
11929                         d_printf("(%s) failed to delete %s: %s\n",
11930                                 __location__, fname, nt_errstr(status));
11931                         correct = false;
11932                         goto out;
11933                 }
11934
11935                 if (s.val) {
11936                         correct = false;
11937                         goto out;
11938                 }
11939         }
11940
11941   out:
11942
11943         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11944         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11945         cli_rmdir(cli, "\\shortname");
11946         torture_close_connection(cli);
11947         return correct;
11948 }
11949
11950 TLDAPRC callback_code;
11951
11952 static void pagedsearch_cb(struct tevent_req *req)
11953 {
11954         TLDAPRC rc;
11955         struct tldap_message *msg;
11956         char *dn;
11957
11958         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
11959         if (!TLDAP_RC_IS_SUCCESS(rc)) {
11960                 d_printf("tldap_search_paged_recv failed: %s\n",
11961                          tldap_rc2string(rc));
11962                 callback_code = rc;
11963                 return;
11964         }
11965         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
11966                 TALLOC_FREE(msg);
11967                 return;
11968         }
11969         if (!tldap_entry_dn(msg, &dn)) {
11970                 d_printf("tldap_entry_dn failed\n");
11971                 return;
11972         }
11973         d_printf("%s\n", dn);
11974         TALLOC_FREE(msg);
11975 }
11976
11977 enum tldap_extended_val {
11978         EXTENDED_ZERO = 0,
11979         EXTENDED_ONE = 1,
11980         EXTENDED_NONE = 2,
11981 };
11982
11983 /*
11984  * Construct an extended dn control with either no value, 0 or 1
11985  *
11986  * No value and 0 are equivalent (non-hyphenated GUID)
11987  * 1 has the hyphenated GUID
11988  */
11989 static struct tldap_control *
11990 tldap_build_extended_control(enum tldap_extended_val val)
11991 {
11992         struct tldap_control empty_control;
11993         struct asn1_data *data;
11994
11995         ZERO_STRUCT(empty_control);
11996
11997         if (val != EXTENDED_NONE) {
11998                 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
11999
12000                 if (!data) {
12001                         return NULL;
12002                 }
12003
12004                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12005                         return NULL;
12006                 }
12007
12008                 if (!asn1_write_Integer(data, (int)val)) {
12009                         return NULL;
12010                 }
12011
12012                 if (!asn1_pop_tag(data)) {
12013                         return NULL;
12014                 }
12015
12016                 if (!asn1_blob(data, &empty_control.value)) {
12017                         return NULL;
12018                 }
12019         }
12020
12021         empty_control.oid = "1.2.840.113556.1.4.529";
12022         empty_control.critical = true;
12023
12024         return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12025
12026 }
12027
12028 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12029                                       enum tldap_extended_val control_val)
12030 {
12031         struct tldap_control *control = tldap_build_extended_control(control_val);
12032         char *dn = NULL;
12033         struct tldap_message **msg;
12034         TLDAPRC rc;
12035
12036         rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12037                           "(objectClass=*)", NULL, 0, 0,
12038                           control, 1, NULL,
12039                           0, 0, 0, 0, talloc_tos(), &msg);
12040         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12041                 d_printf("tldap_search for domain DN failed: %s\n",
12042                          tldap_errstr(talloc_tos(), ld, rc));
12043                 return false;
12044         }
12045
12046         if (!tldap_entry_dn(msg[0], &dn)) {
12047                 d_printf("tldap_search domain DN fetch failed: %s\n",
12048                          tldap_errstr(talloc_tos(), ld, rc));
12049                 return false;
12050         }
12051
12052         d_printf("%s\n", dn);
12053         {
12054                 uint32_t time_low;
12055                 uint32_t time_mid, time_hi_and_version;
12056                 uint32_t clock_seq[2];
12057                 uint32_t node[6];
12058                 char next;
12059
12060                 switch (control_val) {
12061                 case EXTENDED_NONE:
12062                 case EXTENDED_ZERO:
12063                         /*
12064                          * When reading GUIDs with hyphens, scanf will treat
12065                          * hyphen as a hex character (and counts as part of the
12066                          * width). This creates leftover GUID string which we
12067                          * check will for with 'next' and closing '>'.
12068                          */
12069                         if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12070                                          &time_low, &time_mid,
12071                                          &time_hi_and_version, &clock_seq[0],
12072                                          &clock_seq[1], &node[0], &node[1],
12073                                          &node[2], &node[3], &node[4],
12074                                          &node[5], &next)) {
12075                                 /* This GUID is good */
12076                         } else {
12077                                 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12078                                 return false;
12079                         }
12080
12081                         break;
12082                 case EXTENDED_ONE:
12083                         if (12 == sscanf(dn,
12084                                          "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12085                                          &time_low, &time_mid,
12086                                          &time_hi_and_version, &clock_seq[0],
12087                                          &clock_seq[1], &node[0], &node[1],
12088                                          &node[2], &node[3], &node[4],
12089                                          &node[5], &next)) {
12090                                 /* This GUID is good */
12091                         } else {
12092                                 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12093                                 return false;
12094                         }
12095
12096                         break;
12097                 default:
12098                         return false;
12099                 }
12100         }
12101
12102         return true;
12103 }
12104
12105 static bool run_tldap(int dummy)
12106 {
12107         struct tldap_context *ld;
12108         int fd;
12109         TLDAPRC rc;
12110         NTSTATUS status;
12111         struct sockaddr_storage addr;
12112         struct tevent_context *ev;
12113         struct tevent_req *req;
12114         char *basedn;
12115         const char *filter;
12116
12117         if (!resolve_name(host, &addr, 0, false)) {
12118                 d_printf("could not find host %s\n", host);
12119                 return false;
12120         }
12121         status = open_socket_out(&addr, 389, 9999, &fd);
12122         if (!NT_STATUS_IS_OK(status)) {
12123                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12124                 return false;
12125         }
12126
12127         ld = tldap_context_create(talloc_tos(), fd);
12128         if (ld == NULL) {
12129                 close(fd);
12130                 d_printf("tldap_context_create failed\n");
12131                 return false;
12132         }
12133
12134         rc = tldap_fetch_rootdse(ld);
12135         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12136                 d_printf("tldap_fetch_rootdse failed: %s\n",
12137                          tldap_errstr(talloc_tos(), ld, rc));
12138                 return false;
12139         }
12140
12141         basedn = tldap_talloc_single_attribute(
12142                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12143         if (basedn == NULL) {
12144                 d_printf("no defaultNamingContext\n");
12145                 return false;
12146         }
12147         d_printf("defaultNamingContext: %s\n", basedn);
12148
12149         ev = samba_tevent_context_init(talloc_tos());
12150         if (ev == NULL) {
12151                 d_printf("tevent_context_init failed\n");
12152                 return false;
12153         }
12154
12155         rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12156                                loadparm_init_s3(talloc_tos(),
12157                                                 loadparm_s3_helpers()),
12158                                GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12159
12160         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12161                 d_printf("tldap_gensec_bind failed\n");
12162                 return false;
12163         }
12164
12165         callback_code = TLDAP_SUCCESS;
12166
12167         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12168                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
12169                                       NULL, 0, 0,
12170                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
12171         if (req == NULL) {
12172                 d_printf("tldap_search_paged_send failed\n");
12173                 return false;
12174         }
12175         tevent_req_set_callback(req, pagedsearch_cb, NULL);
12176
12177         tevent_req_poll(req, ev);
12178
12179         TALLOC_FREE(req);
12180
12181         rc = callback_code;
12182
12183         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12184                 d_printf("tldap_search with paging failed: %s\n",
12185                          tldap_errstr(talloc_tos(), ld, rc));
12186                 return false;
12187         }
12188
12189         /* test search filters against rootDSE */
12190         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12191                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12192
12193         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12194                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12195                           talloc_tos(), NULL);
12196         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12197                 d_printf("tldap_search with complex filter failed: %s\n",
12198                          tldap_errstr(talloc_tos(), ld, rc));
12199                 return false;
12200         }
12201
12202         /*
12203          * Tests to check for regression of:
12204          *
12205          * https://bugzilla.samba.org/show_bug.cgi?id=14029
12206          *
12207          * TLDAP used here to pick apart the original string DN (with GUID)
12208          */
12209         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12210                 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12211                          tldap_errstr(talloc_tos(), ld, rc));
12212                 return false;
12213         }
12214         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12215                 d_printf("tldap_search with extended dn (0) failed: %s\n",
12216                          tldap_errstr(talloc_tos(), ld, rc));
12217                 return false;
12218         }
12219         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12220                 d_printf("tldap_search with extended dn (1) failed: %s\n",
12221                          tldap_errstr(talloc_tos(), ld, rc));
12222                 return false;
12223         }
12224
12225         TALLOC_FREE(ld);
12226         return true;
12227 }
12228
12229 /* Torture test to ensure no regression of :
12230 https://bugzilla.samba.org/show_bug.cgi?id=7084
12231 */
12232
12233 static bool run_dir_createtime(int dummy)
12234 {
12235         struct cli_state *cli;
12236         const char *dname = "\\testdir_createtime";
12237         const char *fname = "\\testdir_createtime\\testfile";
12238         NTSTATUS status;
12239         struct timespec create_time;
12240         struct timespec create_time1;
12241         uint16_t fnum;
12242         bool ret = false;
12243         uint64_t ino;
12244
12245         if (!torture_open_connection(&cli, 0)) {
12246                 return false;
12247         }
12248
12249         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12250                 /* Ensure ino is zero, SMB2 gets a real one. */
12251                 ino = 0;
12252         } else {
12253                 /* Ensure ino is -1, SMB1 never gets a real one. */
12254                 ino = (uint64_t)-1;
12255         }
12256
12257         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12258         cli_rmdir(cli, dname);
12259
12260         status = cli_mkdir(cli, dname);
12261         if (!NT_STATUS_IS_OK(status)) {
12262                 printf("mkdir failed: %s\n", nt_errstr(status));
12263                 goto out;
12264         }
12265
12266         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
12267                                 NULL, NULL, &ino);
12268         if (!NT_STATUS_IS_OK(status)) {
12269                 printf("cli_qpathinfo2 returned %s\n",
12270                        nt_errstr(status));
12271                 goto out;
12272         }
12273
12274         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12275                 /* SMB2 should always return an inode. */
12276                 if (ino == 0) {
12277                         printf("SMB2 bad inode (0)\n");
12278                         goto out;
12279                 }
12280         } else {
12281                 /* SMB1 must always return zero here. */
12282                 if (ino != 0) {
12283                         printf("SMB1 bad inode (!0)\n");
12284                         goto out;
12285                 }
12286         }
12287
12288         /* Sleep 3 seconds, then create a file. */
12289         sleep(3);
12290
12291         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12292                          DENY_NONE, &fnum);
12293         if (!NT_STATUS_IS_OK(status)) {
12294                 printf("cli_openx failed: %s\n", nt_errstr(status));
12295                 goto out;
12296         }
12297
12298         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
12299                                 NULL, NULL, NULL);
12300         if (!NT_STATUS_IS_OK(status)) {
12301                 printf("cli_qpathinfo2 (2) returned %s\n",
12302                        nt_errstr(status));
12303                 goto out;
12304         }
12305
12306         if (timespec_compare(&create_time1, &create_time)) {
12307                 printf("run_dir_createtime: create time was updated (error)\n");
12308         } else {
12309                 printf("run_dir_createtime: create time was not updated (correct)\n");
12310                 ret = true;
12311         }
12312
12313   out:
12314
12315         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12316         cli_rmdir(cli, dname);
12317         if (!torture_close_connection(cli)) {
12318                 ret = false;
12319         }
12320         return ret;
12321 }
12322
12323
12324 static bool run_streamerror(int dummy)
12325 {
12326         struct cli_state *cli;
12327         const char *dname = "\\testdir_streamerror";
12328         const char *streamname =
12329                 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12330         NTSTATUS status;
12331         time_t change_time, access_time, write_time;
12332         off_t size;
12333         uint16_t fnum;
12334         uint32_t attr;
12335         bool ret = true;
12336
12337         if (!torture_open_connection(&cli, 0)) {
12338                 return false;
12339         }
12340
12341         cli_unlink(cli, "\\testdir_streamerror\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12342         cli_rmdir(cli, dname);
12343
12344         status = cli_mkdir(cli, dname);
12345         if (!NT_STATUS_IS_OK(status)) {
12346                 printf("mkdir failed: %s\n", nt_errstr(status));
12347                 return false;
12348         }
12349
12350         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12351                                 &write_time, &size, &attr);
12352         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12353                 printf("pathinfo returned %s, expected "
12354                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12355                        nt_errstr(status));
12356                 ret = false;
12357         }
12358
12359         status = cli_ntcreate(cli, streamname, 0x16,
12360                               FILE_READ_DATA|FILE_READ_EA|
12361                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12362                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12363                               FILE_OPEN, 0, 0, &fnum, NULL);
12364
12365         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12366                 printf("ntcreate returned %s, expected "
12367                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12368                        nt_errstr(status));
12369                 ret = false;
12370         }
12371
12372
12373         cli_rmdir(cli, dname);
12374         return ret;
12375 }
12376
12377 struct pidtest_state {
12378         bool success;
12379         uint16_t vwv[1];
12380         DATA_BLOB data;
12381 };
12382
12383 static void pid_echo_done(struct tevent_req *subreq);
12384
12385 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12386                         struct tevent_context *ev,
12387                         struct cli_state *cli)
12388 {
12389         struct tevent_req *req, *subreq;
12390         struct pidtest_state *state;
12391
12392         req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12393         if (req == NULL) {
12394                 return NULL;
12395         }
12396
12397         SSVAL(state->vwv, 0, 1);
12398         state->data = data_blob_const("hello", 5);
12399
12400         subreq = smb1cli_req_send(state,
12401                                 ev,
12402                                 cli->conn,
12403                                 SMBecho,
12404                                 0, 0, /* *_flags */
12405                                 0, 0, /* *_flags2 */
12406                                 cli->timeout,
12407                                 0xDEADBEEF, /* pid */
12408                                 NULL, /* tcon */
12409                                 NULL, /* session */
12410                                 ARRAY_SIZE(state->vwv), state->vwv,
12411                                 state->data.length, state->data.data);
12412
12413         if (tevent_req_nomem(subreq, req)) {
12414                 return tevent_req_post(req, ev);
12415         }
12416         tevent_req_set_callback(subreq, pid_echo_done, req);
12417         return req;
12418 }
12419
12420 static void pid_echo_done(struct tevent_req *subreq)
12421 {
12422         struct tevent_req *req = tevent_req_callback_data(
12423                 subreq, struct tevent_req);
12424         struct pidtest_state *state = tevent_req_data(
12425                 req, struct pidtest_state);
12426         NTSTATUS status;
12427         uint32_t num_bytes;
12428         uint8_t *bytes = NULL;
12429         struct iovec *recv_iov = NULL;
12430         uint8_t *phdr = NULL;
12431         uint16_t pidlow = 0;
12432         uint16_t pidhigh = 0;
12433         struct smb1cli_req_expected_response expected[] = {
12434         {
12435                 .status = NT_STATUS_OK,
12436                 .wct    = 1,
12437         },
12438         };
12439
12440         status = smb1cli_req_recv(subreq, state,
12441                                 &recv_iov,
12442                                 &phdr,
12443                                 NULL, /* pwct */
12444                                 NULL, /* pvwv */
12445                                 NULL, /* pvwv_offset */
12446                                 &num_bytes,
12447                                 &bytes,
12448                                 NULL, /* pbytes_offset */
12449                                 NULL, /* pinbuf */
12450                                 expected, ARRAY_SIZE(expected));
12451
12452         TALLOC_FREE(subreq);
12453
12454         if (!NT_STATUS_IS_OK(status)) {
12455                 tevent_req_nterror(req, status);
12456                 return;
12457         }
12458
12459         if (num_bytes != state->data.length) {
12460                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12461                 return;
12462         }
12463
12464         if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12465                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12466                 return;
12467         }
12468
12469         /* Check pid low/high == DEADBEEF */
12470         pidlow = SVAL(phdr, HDR_PID);
12471         if (pidlow != 0xBEEF){
12472                 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12473                         (unsigned int)pidlow);
12474                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12475                 return;
12476         }
12477         pidhigh = SVAL(phdr, HDR_PIDHIGH);
12478         if (pidhigh != 0xDEAD){
12479                 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12480                         (unsigned int)pidhigh);
12481                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12482                 return;
12483         }
12484
12485         tevent_req_done(req);
12486 }
12487
12488 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12489 {
12490         return tevent_req_simple_recv_ntstatus(req);
12491 }
12492
12493 static bool run_pidhigh(int dummy)
12494 {
12495         bool success = false;
12496         struct cli_state *cli = NULL;
12497         NTSTATUS status;
12498         struct tevent_context *ev = NULL;
12499         struct tevent_req *req = NULL;
12500         TALLOC_CTX *frame = talloc_stackframe();
12501
12502         printf("starting pid high test\n");
12503         if (!torture_open_connection(&cli, 0)) {
12504                 return false;
12505         }
12506         smbXcli_conn_set_sockopt(cli->conn, sockops);
12507
12508         ev = samba_tevent_context_init(frame);
12509         if (ev == NULL) {
12510                 goto fail;
12511         }
12512
12513         req = pid_echo_send(frame, ev, cli);
12514         if (req == NULL) {
12515                 goto fail;
12516         }
12517
12518         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12519                 goto fail;
12520         }
12521
12522         status = pid_echo_recv(req);
12523         if (NT_STATUS_IS_OK(status)) {
12524                 printf("pid high test ok\n");
12525                 success = true;
12526         }
12527
12528  fail:
12529
12530         TALLOC_FREE(frame);
12531         torture_close_connection(cli);
12532         return success;
12533 }
12534
12535 /*
12536   Test Windows open on a bad POSIX symlink.
12537  */
12538 static bool run_symlink_open_test(int dummy)
12539 {
12540         static struct cli_state *cli;
12541         const char *fname = "non_existant_file";
12542         const char *sname = "dangling_symlink";
12543         uint16_t fnum = (uint16_t)-1;
12544         bool correct = false;
12545         NTSTATUS status;
12546         TALLOC_CTX *frame = NULL;
12547
12548         frame = talloc_stackframe();
12549
12550         printf("Starting Windows bad symlink open test\n");
12551
12552         if (!torture_open_connection(&cli, 0)) {
12553                 TALLOC_FREE(frame);
12554                 return false;
12555         }
12556
12557         smbXcli_conn_set_sockopt(cli->conn, sockops);
12558
12559         status = torture_setup_unix_extensions(cli);
12560         if (!NT_STATUS_IS_OK(status)) {
12561                 TALLOC_FREE(frame);
12562                 return false;
12563         }
12564
12565         /* Ensure nothing exists. */
12566         cli_setatr(cli, fname, 0, 0);
12567         cli_posix_unlink(cli, fname);
12568         cli_setatr(cli, sname, 0, 0);
12569         cli_posix_unlink(cli, sname);
12570
12571         /* Create a symlink pointing nowhere. */
12572         status = cli_posix_symlink(cli, fname, sname);
12573         if (!NT_STATUS_IS_OK(status)) {
12574                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12575                         sname,
12576                         fname,
12577                         nt_errstr(status));
12578                 goto out;
12579         }
12580
12581         /* Now ensure that a Windows open doesn't hang. */
12582         status = cli_ntcreate(cli,
12583                         sname,
12584                         0,
12585                         FILE_READ_DATA|FILE_WRITE_DATA,
12586                         0,
12587                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12588                         FILE_OPEN_IF,
12589                         0x0,
12590                         0x0,
12591                         &fnum,
12592                         NULL);
12593
12594         /*
12595          * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12596          * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12597          * we use O_NOFOLLOW on the server or not.
12598          */
12599         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12600             NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12601         {
12602                 correct = true;
12603         } else {
12604                 printf("cli_ntcreate of %s returned %s - should return"
12605                                 " either (%s) or (%s)\n",
12606                         sname,
12607                         nt_errstr(status),
12608                         nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12609                         nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12610                 goto out;
12611         }
12612
12613         correct = true;
12614
12615   out:
12616
12617         if (fnum != (uint16_t)-1) {
12618                 cli_close(cli, fnum);
12619                 fnum = (uint16_t)-1;
12620         }
12621
12622         cli_setatr(cli, sname, 0, 0);
12623         cli_posix_unlink(cli, sname);
12624         cli_setatr(cli, fname, 0, 0);
12625         cli_posix_unlink(cli, fname);
12626
12627         if (!torture_close_connection(cli)) {
12628                 correct = false;
12629         }
12630
12631         TALLOC_FREE(frame);
12632         return correct;
12633 }
12634
12635 /*
12636  * Only testing minimal time strings, as the others
12637  * need (locale-dependent) guessing at what strftime does and
12638  * even may differ in builds.
12639  */
12640 static bool timesubst_test(void)
12641 {
12642         TALLOC_CTX *ctx = NULL;
12643         /* Sa 23. Dez 04:33:20 CET 2017 */
12644         const struct timeval tv = { 1514000000, 123 };
12645         const char* expect_minimal = "20171223_033320";
12646         const char* expect_minus   = "20171223_033320_000123";
12647         char *s;
12648         char *env_tz, *orig_tz = NULL;
12649         bool result = true;
12650
12651         ctx = talloc_new(NULL);
12652
12653         env_tz = getenv("TZ");
12654         if(env_tz) {
12655                 orig_tz = talloc_strdup(ctx, env_tz);
12656         }
12657         setenv("TZ", "UTC", 1);
12658
12659         s = minimal_timeval_string(ctx, &tv, false);
12660
12661         if(!s || strcmp(s, expect_minimal)) {
12662                 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
12663                        "[%s]\n", s ? s : "<nil>", expect_minimal);
12664                 result = false;
12665         }
12666         TALLOC_FREE(s);
12667         s = minimal_timeval_string(ctx, &tv, true);
12668         if(!s || strcmp(s, expect_minus)) {
12669                 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
12670                        "[%s]\n", s ? s : "<nil>", expect_minus);
12671                 result = false;
12672         }
12673         TALLOC_FREE(s);
12674
12675         if(orig_tz) {
12676                 setenv("TZ", orig_tz, 1);
12677         }
12678
12679         TALLOC_FREE(ctx);
12680         return result;
12681 }
12682
12683 static bool run_local_substitute(int dummy)
12684 {
12685         bool ok = true;
12686
12687         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
12688         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
12689         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
12690         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
12691         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
12692         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
12693         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
12694         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
12695         ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
12696         /* Substitution depends on current time, so better test the underlying
12697            formatting function. At least covers %t. */
12698         ok &= timesubst_test();
12699
12700         /* Different captialization rules in sub_basic... */
12701
12702         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
12703                        "blaDOM") == 0);
12704
12705         return ok;
12706 }
12707
12708 static bool run_local_base64(int dummy)
12709 {
12710         int i;
12711         bool ret = true;
12712
12713         for (i=1; i<2000; i++) {
12714                 DATA_BLOB blob1, blob2;
12715                 char *b64;
12716
12717                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
12718                 blob1.length = i;
12719                 generate_random_buffer(blob1.data, blob1.length);
12720
12721                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
12722                 if (b64 == NULL) {
12723                         d_fprintf(stderr, "base64_encode_data_blob failed "
12724                                   "for %d bytes\n", i);
12725                         ret = false;
12726                 }
12727                 blob2 = base64_decode_data_blob(b64);
12728                 TALLOC_FREE(b64);
12729
12730                 if (data_blob_cmp(&blob1, &blob2)) {
12731                         d_fprintf(stderr, "data_blob_cmp failed for %d "
12732                                   "bytes\n", i);
12733                         ret = false;
12734                 }
12735                 TALLOC_FREE(blob1.data);
12736                 data_blob_free(&blob2);
12737         }
12738         return ret;
12739 }
12740
12741 static void parse_fn(const struct gencache_timeout *t,
12742                      DATA_BLOB blob,
12743                      void *private_data)
12744 {
12745         return;
12746 }
12747
12748 static bool run_local_gencache(int dummy)
12749 {
12750         char *val;
12751         time_t tm;
12752         DATA_BLOB blob;
12753         char v;
12754         struct memcache *mem;
12755         int i;
12756
12757         mem = memcache_init(NULL, 0);
12758         if (mem == NULL) {
12759                 d_printf("%s: memcache_init failed\n", __location__);
12760                 return false;
12761         }
12762         memcache_set_global(mem);
12763
12764         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
12765                 d_printf("%s: gencache_set() failed\n", __location__);
12766                 return False;
12767         }
12768
12769         if (!gencache_get("foo", NULL, NULL, NULL)) {
12770                 d_printf("%s: gencache_get() failed\n", __location__);
12771                 return False;
12772         }
12773
12774         for (i=0; i<1000000; i++) {
12775                 gencache_parse("foo", parse_fn, NULL);
12776         }
12777
12778         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
12779                 d_printf("%s: gencache_get() failed\n", __location__);
12780                 return False;
12781         }
12782         TALLOC_FREE(val);
12783
12784         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
12785                 d_printf("%s: gencache_get() failed\n", __location__);
12786                 return False;
12787         }
12788
12789         if (strcmp(val, "bar") != 0) {
12790                 d_printf("%s: gencache_get() returned %s, expected %s\n",
12791                          __location__, val, "bar");
12792                 TALLOC_FREE(val);
12793                 return False;
12794         }
12795
12796         TALLOC_FREE(val);
12797
12798         if (!gencache_del("foo")) {
12799                 d_printf("%s: gencache_del() failed\n", __location__);
12800                 return False;
12801         }
12802         if (gencache_del("foo")) {
12803                 d_printf("%s: second gencache_del() succeeded\n",
12804                          __location__);
12805                 return False;
12806         }
12807
12808         if (gencache_get("foo", talloc_tos(), &val, &tm)) {
12809                 d_printf("%s: gencache_get() on deleted entry "
12810                          "succeeded\n", __location__);
12811                 return False;
12812         }
12813
12814         blob = data_blob_string_const_null("bar");
12815         tm = time(NULL) + 60;
12816
12817         if (!gencache_set_data_blob("foo", blob, tm)) {
12818                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
12819                 return False;
12820         }
12821
12822         if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
12823                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
12824                 return False;
12825         }
12826
12827         if (strcmp((const char *)blob.data, "bar") != 0) {
12828                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
12829                          __location__, (const char *)blob.data, "bar");
12830                 data_blob_free(&blob);
12831                 return False;
12832         }
12833
12834         data_blob_free(&blob);
12835
12836         if (!gencache_del("foo")) {
12837                 d_printf("%s: gencache_del() failed\n", __location__);
12838                 return False;
12839         }
12840         if (gencache_del("foo")) {
12841                 d_printf("%s: second gencache_del() succeeded\n",
12842                          __location__);
12843                 return False;
12844         }
12845
12846         if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
12847                 d_printf("%s: gencache_get_data_blob() on deleted entry "
12848                          "succeeded\n", __location__);
12849                 return False;
12850         }
12851
12852         v = 1;
12853         blob.data = (uint8_t *)&v;
12854         blob.length = sizeof(v);
12855
12856         if (!gencache_set_data_blob("blob", blob, tm)) {
12857                 d_printf("%s: gencache_set_data_blob() failed\n",
12858                          __location__);
12859                 return false;
12860         }
12861         if (gencache_get("blob", talloc_tos(), &val, &tm)) {
12862                 d_printf("%s: gencache_get succeeded\n", __location__);
12863                 return false;
12864         }
12865
12866         return True;
12867 }
12868
12869 static bool rbt_testval(struct db_context *db, const char *key,
12870                         const char *value)
12871 {
12872         struct db_record *rec;
12873         TDB_DATA data = string_tdb_data(value);
12874         bool ret = false;
12875         NTSTATUS status;
12876         TDB_DATA dbvalue;
12877
12878         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
12879         if (rec == NULL) {
12880                 d_fprintf(stderr, "fetch_locked failed\n");
12881                 goto done;
12882         }
12883         status = dbwrap_record_store(rec, data, 0);
12884         if (!NT_STATUS_IS_OK(status)) {
12885                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
12886                 goto done;
12887         }
12888         TALLOC_FREE(rec);
12889
12890         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
12891         if (rec == NULL) {
12892                 d_fprintf(stderr, "second fetch_locked failed\n");
12893                 goto done;
12894         }
12895
12896         dbvalue = dbwrap_record_get_value(rec);
12897         if ((dbvalue.dsize != data.dsize)
12898             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
12899                 d_fprintf(stderr, "Got wrong data back\n");
12900                 goto done;
12901         }
12902
12903         ret = true;
12904  done:
12905         TALLOC_FREE(rec);
12906         return ret;
12907 }
12908
12909 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
12910 {
12911         int *count2 = (int *)private_data;
12912         (*count2)++;
12913         return 0;
12914 }
12915
12916 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
12917 {
12918         int *count2 = (int *)private_data;
12919         (*count2)++;
12920         dbwrap_record_delete(rec);
12921         return 0;
12922 }
12923
12924 static bool run_local_rbtree(int dummy)
12925 {
12926         struct db_context *db;
12927         bool ret = false;
12928         int i;
12929         NTSTATUS status;
12930         int count = 0;
12931         int count2 = 0;
12932
12933         db = db_open_rbt(NULL);
12934
12935         if (db == NULL) {
12936                 d_fprintf(stderr, "db_open_rbt failed\n");
12937                 return false;
12938         }
12939
12940         for (i=0; i<1000; i++) {
12941                 char *key, *value;
12942
12943                 if (asprintf(&key, "key%ld", random()) == -1) {
12944                         goto done;
12945                 }
12946                 if (asprintf(&value, "value%ld", random()) == -1) {
12947                         SAFE_FREE(key);
12948                         goto done;
12949                 }
12950
12951                 if (!rbt_testval(db, key, value)) {
12952                         SAFE_FREE(key);
12953                         SAFE_FREE(value);
12954                         goto done;
12955                 }
12956
12957                 SAFE_FREE(value);
12958                 if (asprintf(&value, "value%ld", random()) == -1) {
12959                         SAFE_FREE(key);
12960                         goto done;
12961                 }
12962
12963                 if (!rbt_testval(db, key, value)) {
12964                         SAFE_FREE(key);
12965                         SAFE_FREE(value);
12966                         goto done;
12967                 }
12968
12969                 SAFE_FREE(key);
12970                 SAFE_FREE(value);
12971         }
12972
12973         ret = true;
12974         count = 0; count2 = 0;
12975         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
12976                                       &count2, &count);
12977         printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
12978         if ((count != count2) || (count != 1000)) {
12979                 ret = false;
12980         }
12981         count = 0; count2 = 0;
12982         status = dbwrap_traverse(db, local_rbtree_traverse_delete,
12983                                  &count2, &count);
12984         printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
12985         if ((count != count2) || (count != 1000)) {
12986                 ret = false;
12987         }
12988         count = 0; count2 = 0;
12989         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
12990                                       &count2, &count);
12991         printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
12992         if ((count != count2) || (count != 0)) {
12993                 ret = false;
12994         }
12995
12996  done:
12997         TALLOC_FREE(db);
12998         return ret;
12999 }
13000
13001
13002 /*
13003   local test for character set functions
13004
13005   This is a very simple test for the functionality in convert_string_error()
13006  */
13007 static bool run_local_convert_string(int dummy)
13008 {
13009         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13010         const char *test_strings[2] = { "March", "M\303\244rz" };
13011         char dst[7];
13012         int i;
13013
13014         for (i=0; i<2; i++) {
13015                 const char *str = test_strings[i];
13016                 int len = strlen(str);
13017                 size_t converted_size;
13018                 bool ret;
13019
13020                 memset(dst, 'X', sizeof(dst));
13021
13022                 /* first try with real source length */
13023                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13024                                            str, len,
13025                                            dst, sizeof(dst),
13026                                            &converted_size);
13027                 if (ret != true) {
13028                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13029                         goto failed;
13030                 }
13031
13032                 if (converted_size != len) {
13033                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13034                                   str, len, (int)converted_size);
13035                         goto failed;
13036                 }
13037
13038                 if (strncmp(str, dst, converted_size) != 0) {
13039                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13040                         goto failed;
13041                 }
13042
13043                 if (strlen(str) != converted_size) {
13044                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13045                                   (int)strlen(str), (int)converted_size);
13046                         goto failed;
13047                 }
13048
13049                 if (dst[converted_size] != 'X') {
13050                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13051                         goto failed;
13052                 }
13053
13054                 /* now with srclen==-1, this causes the nul to be
13055                  * converted too */
13056                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13057                                            str, -1,
13058                                            dst, sizeof(dst),
13059                                            &converted_size);
13060                 if (ret != true) {
13061                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13062                         goto failed;
13063                 }
13064
13065                 if (converted_size != len+1) {
13066                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13067                                   str, len, (int)converted_size);
13068                         goto failed;
13069                 }
13070
13071                 if (strncmp(str, dst, converted_size) != 0) {
13072                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13073                         goto failed;
13074                 }
13075
13076                 if (len+1 != converted_size) {
13077                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13078                                   len+1, (int)converted_size);
13079                         goto failed;
13080                 }
13081
13082                 if (dst[converted_size] != 'X') {
13083                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13084                         goto failed;
13085                 }
13086
13087         }
13088
13089
13090         TALLOC_FREE(tmp_ctx);
13091         return true;
13092 failed:
13093         TALLOC_FREE(tmp_ctx);
13094         return false;
13095 }
13096
13097 static bool run_local_string_to_sid(int dummy) {
13098         struct dom_sid sid;
13099
13100         if (string_to_sid(&sid, "S--1-5-32-545")) {
13101                 printf("allowing S--1-5-32-545\n");
13102                 return false;
13103         }
13104         if (string_to_sid(&sid, "S-1-5-32-+545")) {
13105                 printf("allowing S-1-5-32-+545\n");
13106                 return false;
13107         }
13108         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")) {
13109                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13110                 return false;
13111         }
13112         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13113                 printf("allowing S-1-5-32-545-abc\n");
13114                 return false;
13115         }
13116         if (string_to_sid(&sid, "S-300-5-32-545")) {
13117                 printf("allowing S-300-5-32-545\n");
13118                 return false;
13119         }
13120         if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13121                 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13122                 return false;
13123         }
13124         if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13125                 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13126                 return false;
13127         }
13128         if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13129                 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13130                 return false;
13131         }
13132         if (!string_to_sid(&sid, "S-1-5-32-545")) {
13133                 printf("could not parse S-1-5-32-545\n");
13134                 return false;
13135         }
13136         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13137                 struct dom_sid_buf buf;
13138                 printf("mis-parsed S-1-5-32-545 as %s\n",
13139                        dom_sid_str_buf(&sid, &buf));
13140                 return false;
13141         }
13142         return true;
13143 }
13144
13145 static bool sid_to_string_test(const char *expected) {
13146         char *str;
13147         bool res = true;
13148         struct dom_sid sid;
13149
13150         if (!string_to_sid(&sid, expected)) {
13151                 printf("could not parse %s\n", expected);
13152                 return false;
13153         }
13154
13155         str = dom_sid_string(NULL, &sid);
13156         if (strcmp(str, expected)) {
13157                 printf("Comparison failed (%s != %s)\n", str, expected);
13158                 res = false;
13159         }
13160         TALLOC_FREE(str);
13161         return res;
13162 }
13163
13164 static bool run_local_sid_to_string(int dummy) {
13165         if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13166                 return false;
13167         if (!sid_to_string_test("S-1-545"))
13168                 return false;
13169         if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13170                 return false;
13171         return true;
13172 }
13173
13174 static bool run_local_binary_to_sid(int dummy) {
13175         ssize_t ret;
13176         struct dom_sid *sid = talloc(NULL, struct dom_sid);
13177         static const uint8_t good_binary_sid[] = {
13178                 0x1, /* revision number */
13179                 15, /* num auths */
13180                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13181                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13182                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13183                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13184                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13185                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13186                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13187                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13188                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13189                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13190                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13191                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13192                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13193                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13194                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13195                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13196         };
13197
13198         static const uint8_t long_binary_sid[] = {
13199                 0x1, /* revision number */
13200                 15, /* num auths */
13201                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13202                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13203                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13204                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13205                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13206                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13207                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13208                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13209                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13210                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13211                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13212                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13213                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13214                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13215                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13216                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13217                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13218                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13219                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13220         };
13221
13222         static const uint8_t long_binary_sid2[] = {
13223                 0x1, /* revision number */
13224                 32, /* num auths */
13225                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13226                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13227                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13228                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13229                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13230                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13231                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13232                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13233                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13234                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13235                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13236                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13237                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13238                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13239                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13240                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13241                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13242                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13243                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13244                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13245                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13246                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13247                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13248                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13249                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13250                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13251                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13252                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13253                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13254                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13255                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13256                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13257                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13258         };
13259
13260         ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13261         if (ret == -1) {
13262                 return false;
13263         }
13264         ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13265         if (ret != -1) {
13266                 return false;
13267         }
13268         ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13269         if (ret != -1) {
13270                 return false;
13271         }
13272         return true;
13273 }
13274
13275 /* Split a path name into filename and stream name components. Canonicalise
13276  * such that an implicit $DATA token is always explicit.
13277  *
13278  * The "specification" of this function can be found in the
13279  * run_local_stream_name() function in torture.c, I've tried those
13280  * combinations against a W2k3 server.
13281  */
13282
13283 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13284                                        char **pbase, char **pstream)
13285 {
13286         char *base = NULL;
13287         char *stream = NULL;
13288         char *sname; /* stream name */
13289         const char *stype; /* stream type */
13290
13291         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13292
13293         sname = strchr_m(fname, ':');
13294
13295         if (sname == NULL) {
13296                 if (pbase != NULL) {
13297                         base = talloc_strdup(mem_ctx, fname);
13298                         NT_STATUS_HAVE_NO_MEMORY(base);
13299                 }
13300                 goto done;
13301         }
13302
13303         if (pbase != NULL) {
13304                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13305                 NT_STATUS_HAVE_NO_MEMORY(base);
13306         }
13307
13308         sname += 1;
13309
13310         stype = strchr_m(sname, ':');
13311
13312         if (stype == NULL) {
13313                 sname = talloc_strdup(mem_ctx, sname);
13314                 stype = "$DATA";
13315         }
13316         else {
13317                 if (strcasecmp_m(stype, ":$DATA") != 0) {
13318                         /*
13319                          * If there is an explicit stream type, so far we only
13320                          * allow $DATA. Is there anything else allowed? -- vl
13321                          */
13322                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13323                         TALLOC_FREE(base);
13324                         return NT_STATUS_OBJECT_NAME_INVALID;
13325                 }
13326                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13327                 stype += 1;
13328         }
13329
13330         if (sname == NULL) {
13331                 TALLOC_FREE(base);
13332                 return NT_STATUS_NO_MEMORY;
13333         }
13334
13335         if (sname[0] == '\0') {
13336                 /*
13337                  * no stream name, so no stream
13338                  */
13339                 goto done;
13340         }
13341
13342         if (pstream != NULL) {
13343                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13344                 if (stream == NULL) {
13345                         TALLOC_FREE(sname);
13346                         TALLOC_FREE(base);
13347                         return NT_STATUS_NO_MEMORY;
13348                 }
13349                 /*
13350                  * upper-case the type field
13351                  */
13352                 (void)strupper_m(strchr_m(stream, ':')+1);
13353         }
13354
13355  done:
13356         if (pbase != NULL) {
13357                 *pbase = base;
13358         }
13359         if (pstream != NULL) {
13360                 *pstream = stream;
13361         }
13362         return NT_STATUS_OK;
13363 }
13364
13365 static bool test_stream_name(const char *fname, const char *expected_base,
13366                              const char *expected_stream,
13367                              NTSTATUS expected_status)
13368 {
13369         NTSTATUS status;
13370         char *base = NULL;
13371         char *stream = NULL;
13372
13373         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13374         if (!NT_STATUS_EQUAL(status, expected_status)) {
13375                 goto error;
13376         }
13377
13378         if (!NT_STATUS_IS_OK(status)) {
13379                 return true;
13380         }
13381
13382         if (base == NULL) goto error;
13383
13384         if (strcmp(expected_base, base) != 0) goto error;
13385
13386         if ((expected_stream != NULL) && (stream == NULL)) goto error;
13387         if ((expected_stream == NULL) && (stream != NULL)) goto error;
13388
13389         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
13390                 goto error;
13391
13392         TALLOC_FREE(base);
13393         TALLOC_FREE(stream);
13394         return true;
13395
13396  error:
13397         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
13398                   fname, expected_base ? expected_base : "<NULL>",
13399                   expected_stream ? expected_stream : "<NULL>",
13400                   nt_errstr(expected_status));
13401         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
13402                   base ? base : "<NULL>", stream ? stream : "<NULL>",
13403                   nt_errstr(status));
13404         TALLOC_FREE(base);
13405         TALLOC_FREE(stream);
13406         return false;
13407 }
13408
13409 static bool run_local_stream_name(int dummy)
13410 {
13411         bool ret = true;
13412
13413         ret &= test_stream_name(
13414                 "bla", "bla", NULL, NT_STATUS_OK);
13415         ret &= test_stream_name(
13416                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
13417         ret &= test_stream_name(
13418                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13419         ret &= test_stream_name(
13420                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
13421         ret &= test_stream_name(
13422                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13423         ret &= test_stream_name(
13424                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
13425         ret &= test_stream_name(
13426                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
13427         ret &= test_stream_name(
13428                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
13429
13430         return ret;
13431 }
13432
13433 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
13434 {
13435         if (a.length != b.length) {
13436                 printf("a.length=%d != b.length=%d\n",
13437                        (int)a.length, (int)b.length);
13438                 return false;
13439         }
13440         if (memcmp(a.data, b.data, a.length) != 0) {
13441                 printf("a.data and b.data differ\n");
13442                 return false;
13443         }
13444         return true;
13445 }
13446
13447 static bool run_local_memcache(int dummy)
13448 {
13449         struct memcache *cache;
13450         DATA_BLOB k1, k2, k3, k4, k5;
13451         DATA_BLOB d1, d3;
13452         DATA_BLOB v1, v3;
13453
13454         TALLOC_CTX *mem_ctx;
13455         char *ptr1 = NULL;
13456         char *ptr2 = NULL;
13457         char *ptr3 = NULL;
13458
13459         char *str1, *str2;
13460         size_t size1, size2;
13461         bool ret = false;
13462
13463         mem_ctx = talloc_init("foo");
13464         if (mem_ctx == NULL) {
13465                 return false;
13466         }
13467
13468         /* STAT_CACHE TESTS */
13469
13470         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13471
13472         if (cache == NULL) {
13473                 printf("memcache_init failed\n");
13474                 return false;
13475         }
13476
13477         d1 = data_blob_const("d1", 2);
13478         d3 = data_blob_const("d3", 2);
13479
13480         k1 = data_blob_const("d1", 2);
13481         k2 = data_blob_const("d2", 2);
13482         k3 = data_blob_const("d3", 2);
13483         k4 = data_blob_const("d4", 2);
13484         k5 = data_blob_const("d5", 2);
13485
13486         memcache_add(cache, STAT_CACHE, k1, d1);
13487
13488         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
13489                 printf("could not find k1\n");
13490                 return false;
13491         }
13492         if (!data_blob_equal(d1, v1)) {
13493                 return false;
13494         }
13495
13496         memcache_add(cache, STAT_CACHE, k1, d3);
13497
13498         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
13499                 printf("could not find replaced k1\n");
13500                 return false;
13501         }
13502         if (!data_blob_equal(d3, v3)) {
13503                 return false;
13504         }
13505
13506         TALLOC_FREE(cache);
13507
13508         /* GETWD_CACHE TESTS */
13509         str1 = talloc_strdup(mem_ctx, "string1");
13510         if (str1 == NULL) {
13511                 return false;
13512         }
13513         ptr2 = str1; /* Keep an alias for comparison. */
13514
13515         str2 = talloc_strdup(mem_ctx, "string2");
13516         if (str2 == NULL) {
13517                 return false;
13518         }
13519
13520         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13521         if (cache == NULL) {
13522                 printf("memcache_init failed\n");
13523                 return false;
13524         }
13525
13526         memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
13527         /* str1 == NULL now. */
13528         ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
13529         if (ptr1 == NULL) {
13530                 printf("could not find k2\n");
13531                 return false;
13532         }
13533         if (ptr1 != ptr2) {
13534                 printf("fetch of k2 got wrong string\n");
13535                 return false;
13536         }
13537
13538         /* Add a blob to ensure k2 gets purged. */
13539         d3 = data_blob_talloc_zero(mem_ctx, 180);
13540         memcache_add(cache, STAT_CACHE, k3, d3);
13541
13542         ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
13543         if (ptr2 != NULL) {
13544                 printf("Did find k2, should have been purged\n");
13545                 return false;
13546         }
13547
13548         /*
13549          * Test that talloc size also is accounted in memcache and
13550          * causes purge of other object.
13551          */
13552
13553         str1 = talloc_zero_size(mem_ctx, 100);
13554         str2 = talloc_zero_size(mem_ctx, 100);
13555
13556         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13557         memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
13558
13559         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
13560         if (ptr3 != NULL) {
13561                 printf("Did find k4, should have been purged\n");
13562                 return false;
13563         }
13564
13565         /*
13566          * Test that adding a duplicate non-talloced
13567          * key/value on top of a talloced key/value takes account
13568          * of the talloc_freed value size.
13569          */
13570         TALLOC_FREE(cache);
13571         TALLOC_FREE(mem_ctx);
13572
13573         mem_ctx = talloc_init("key_replace");
13574         if (mem_ctx == NULL) {
13575                 return false;
13576         }
13577
13578         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13579         if (cache == NULL) {
13580                 return false;
13581         }
13582
13583         /*
13584          * Add a 100 byte talloced string. This will
13585          * store a (4 or 8 byte) pointer and record the
13586          * total talloced size.
13587          */
13588         str1 = talloc_zero_size(mem_ctx, 100);
13589         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13590         /*
13591          * Now overwrite with a small talloced
13592          * value. This should fit in the existing size
13593          * and the total talloced size should be removed
13594          * from the cache size.
13595          */
13596         str1 = talloc_zero_size(mem_ctx, 2);
13597         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13598         /*
13599          * Now store a 20 byte string. If the
13600          * total talloced size wasn't accounted for
13601          * and removed in the overwrite, then this
13602          * will evict k4.
13603          */
13604         str2 = talloc_zero_size(mem_ctx, 20);
13605         memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
13606
13607         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
13608         if (ptr3 == NULL) {
13609                 printf("Did not find k4, should not have been purged\n");
13610                 return false;
13611         }
13612
13613         TALLOC_FREE(cache);
13614         TALLOC_FREE(mem_ctx);
13615
13616         mem_ctx = talloc_init("foo");
13617         if (mem_ctx == NULL) {
13618                 return false;
13619         }
13620
13621         cache = memcache_init(NULL, 0);
13622         if (cache == NULL) {
13623                 return false;
13624         }
13625
13626         str1 = talloc_strdup(mem_ctx, "string1");
13627         if (str1 == NULL) {
13628                 return false;
13629         }
13630         str2 = talloc_strdup(mem_ctx, "string2");
13631         if (str2 == NULL) {
13632                 return false;
13633         }
13634         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
13635                             data_blob_string_const("torture"), &str1);
13636         size1 = talloc_total_size(cache);
13637
13638         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
13639                             data_blob_string_const("torture"), &str2);
13640         size2 = talloc_total_size(cache);
13641
13642         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
13643
13644         if (size2 > size1) {
13645                 printf("memcache leaks memory!\n");
13646                 goto fail;
13647         }
13648
13649         ret = true;
13650  fail:
13651         TALLOC_FREE(cache);
13652         return ret;
13653 }
13654
13655 static void wbclient_done(struct tevent_req *req)
13656 {
13657         wbcErr wbc_err;
13658         struct winbindd_response *wb_resp;
13659         int *i = (int *)tevent_req_callback_data_void(req);
13660
13661         wbc_err = wb_trans_recv(req, req, &wb_resp);
13662         TALLOC_FREE(req);
13663         *i += 1;
13664         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
13665 }
13666
13667 static bool run_wbclient_multi_ping(int dummy)
13668 {
13669         struct tevent_context *ev;
13670         struct wb_context **wb_ctx;
13671         struct winbindd_request wb_req;
13672         bool result = false;
13673         int i, j;
13674
13675         BlockSignals(True, SIGPIPE);
13676
13677         ev = tevent_context_init(talloc_tos());
13678         if (ev == NULL) {
13679                 goto fail;
13680         }
13681
13682         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
13683         if (wb_ctx == NULL) {
13684                 goto fail;
13685         }
13686
13687         ZERO_STRUCT(wb_req);
13688         wb_req.cmd = WINBINDD_PING;
13689
13690         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
13691
13692         for (i=0; i<torture_nprocs; i++) {
13693                 wb_ctx[i] = wb_context_init(ev, NULL);
13694                 if (wb_ctx[i] == NULL) {
13695                         goto fail;
13696                 }
13697                 for (j=0; j<torture_numops; j++) {
13698                         struct tevent_req *req;
13699                         req = wb_trans_send(ev, ev, wb_ctx[i],
13700                                             (j % 2) == 0, &wb_req);
13701                         if (req == NULL) {
13702                                 goto fail;
13703                         }
13704                         tevent_req_set_callback(req, wbclient_done, &i);
13705                 }
13706         }
13707
13708         i = 0;
13709
13710         while (i < torture_nprocs * torture_numops) {
13711                 tevent_loop_once(ev);
13712         }
13713
13714         result = true;
13715  fail:
13716         TALLOC_FREE(ev);
13717         return result;
13718 }
13719
13720 static bool dbtrans_inc(struct db_context *db)
13721 {
13722         struct db_record *rec;
13723         uint32_t val;
13724         bool ret = false;
13725         NTSTATUS status;
13726         TDB_DATA value;
13727
13728         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
13729         if (rec == NULL) {
13730                 printf(__location__ "fetch_lock failed\n");
13731                 return false;
13732         }
13733
13734         value = dbwrap_record_get_value(rec);
13735
13736         if (value.dsize != sizeof(uint32_t)) {
13737                 printf(__location__ "value.dsize = %d\n",
13738                        (int)value.dsize);
13739                 goto fail;
13740         }
13741
13742         memcpy(&val, value.dptr, sizeof(val));
13743         val += 1;
13744
13745         status = dbwrap_record_store(
13746                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
13747         if (!NT_STATUS_IS_OK(status)) {
13748                 printf(__location__ "store failed: %s\n",
13749                        nt_errstr(status));
13750                 goto fail;
13751         }
13752
13753         ret = true;
13754 fail:
13755         TALLOC_FREE(rec);
13756         return ret;
13757 }
13758
13759 static bool run_local_dbtrans(int dummy)
13760 {
13761         struct db_context *db;
13762         struct db_record *rec;
13763         NTSTATUS status;
13764         uint32_t initial;
13765         int res;
13766         TDB_DATA value;
13767
13768         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
13769                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
13770                      DBWRAP_FLAG_NONE);
13771         if (db == NULL) {
13772                 printf("Could not open transtest.db\n");
13773                 return false;
13774         }
13775
13776         res = dbwrap_transaction_start(db);
13777         if (res != 0) {
13778                 printf(__location__ "transaction_start failed\n");
13779                 return false;
13780         }
13781
13782         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
13783         if (rec == NULL) {
13784                 printf(__location__ "fetch_lock failed\n");
13785                 return false;
13786         }
13787
13788         value = dbwrap_record_get_value(rec);
13789
13790         if (value.dptr == NULL) {
13791                 initial = 0;
13792                 status = dbwrap_record_store(
13793                         rec, make_tdb_data((uint8_t *)&initial,
13794                                            sizeof(initial)),
13795                         0);
13796                 if (!NT_STATUS_IS_OK(status)) {
13797                         printf(__location__ "store returned %s\n",
13798                                nt_errstr(status));
13799                         return false;
13800                 }
13801         }
13802
13803         TALLOC_FREE(rec);
13804
13805         res = dbwrap_transaction_commit(db);
13806         if (res != 0) {
13807                 printf(__location__ "transaction_commit failed\n");
13808                 return false;
13809         }
13810
13811         while (true) {
13812                 uint32_t val, val2;
13813                 int i;
13814
13815                 res = dbwrap_transaction_start(db);
13816                 if (res != 0) {
13817                         printf(__location__ "transaction_start failed\n");
13818                         break;
13819                 }
13820
13821                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
13822                 if (!NT_STATUS_IS_OK(status)) {
13823                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
13824                                nt_errstr(status));
13825                         break;
13826                 }
13827
13828                 for (i=0; i<10; i++) {
13829                         if (!dbtrans_inc(db)) {
13830                                 return false;
13831                         }
13832                 }
13833
13834                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
13835                 if (!NT_STATUS_IS_OK(status)) {
13836                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
13837                                nt_errstr(status));
13838                         break;
13839                 }
13840
13841                 if (val2 != val + 10) {
13842                         printf(__location__ "val=%d, val2=%d\n",
13843                                (int)val, (int)val2);
13844                         break;
13845                 }
13846
13847                 printf("val2=%d\r", val2);
13848
13849                 res = dbwrap_transaction_commit(db);
13850                 if (res != 0) {
13851                         printf(__location__ "transaction_commit failed\n");
13852                         break;
13853                 }
13854         }
13855
13856         TALLOC_FREE(db);
13857         return true;
13858 }
13859
13860 /*
13861  * Just a dummy test to be run under a debugger. There's no real way
13862  * to inspect the tevent_poll specific function from outside of
13863  * tevent_poll.c.
13864  */
13865
13866 static bool run_local_tevent_poll(int dummy)
13867 {
13868         struct tevent_context *ev;
13869         struct tevent_fd *fd1, *fd2;
13870         bool result = false;
13871
13872         ev = tevent_context_init_byname(NULL, "poll");
13873         if (ev == NULL) {
13874                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
13875                 goto fail;
13876         }
13877
13878         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
13879         if (fd1 == NULL) {
13880                 d_fprintf(stderr, "tevent_add_fd failed\n");
13881                 goto fail;
13882         }
13883         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
13884         if (fd2 == NULL) {
13885                 d_fprintf(stderr, "tevent_add_fd failed\n");
13886                 goto fail;
13887         }
13888         TALLOC_FREE(fd2);
13889
13890         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
13891         if (fd2 == NULL) {
13892                 d_fprintf(stderr, "tevent_add_fd failed\n");
13893                 goto fail;
13894         }
13895
13896         result = true;
13897 fail:
13898         TALLOC_FREE(ev);
13899         return result;
13900 }
13901
13902 static bool run_local_hex_encode_buf(int dummy)
13903 {
13904         char buf[17];
13905         uint8_t src[8];
13906         int i;
13907
13908         for (i=0; i<sizeof(src); i++) {
13909                 src[i] = i;
13910         }
13911         hex_encode_buf(buf, src, sizeof(src));
13912         if (strcmp(buf, "0001020304050607") != 0) {
13913                 return false;
13914         }
13915         hex_encode_buf(buf, NULL, 0);
13916         if (buf[0] != '\0') {
13917                 return false;
13918         }
13919         return true;
13920 }
13921
13922 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
13923         "0.0.0.0",
13924         "::0",
13925         "1.2.3.1",
13926         "0.0.0.0",
13927         "0.0.0.0",
13928         "1.2.3.2",
13929         "1.2.3.3",
13930         "1.2.3.4",
13931         "1.2.3.5",
13932         "::0",
13933         "1.2.3.6",
13934         "1.2.3.7",
13935         "::0",
13936         "::0",
13937         "::0",
13938         "1.2.3.8",
13939         "1.2.3.9",
13940         "1.2.3.10",
13941         "1.2.3.11",
13942         "1.2.3.12",
13943         "1.2.3.13",
13944         "1001:1111:1111:1000:0:1111:1111:1111",
13945         "1.2.3.1",
13946         "1.2.3.2",
13947         "1.2.3.3",
13948         "1.2.3.12",
13949         "::0",
13950         "::0"
13951 };
13952
13953 static const char *remove_duplicate_addrs2_test_strings_result[] = {
13954         "1.2.3.1",
13955         "1.2.3.2",
13956         "1.2.3.3",
13957         "1.2.3.4",
13958         "1.2.3.5",
13959         "1.2.3.6",
13960         "1.2.3.7",
13961         "1.2.3.8",
13962         "1.2.3.9",
13963         "1.2.3.10",
13964         "1.2.3.11",
13965         "1.2.3.12",
13966         "1.2.3.13",
13967         "1001:1111:1111:1000:0:1111:1111:1111"
13968 };
13969
13970 static bool run_local_remove_duplicate_addrs2(int dummy)
13971 {
13972         struct ip_service test_vector[28];
13973         int count, i;
13974
13975         /* Construct the sockaddr_storage test vector. */
13976         for (i = 0; i < 28; i++) {
13977                 struct addrinfo hints;
13978                 struct addrinfo *res = NULL;
13979                 int ret;
13980
13981                 memset(&hints, '\0', sizeof(hints));
13982                 hints.ai_flags = AI_NUMERICHOST;
13983                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
13984                                 NULL,
13985                                 &hints,
13986                                 &res);
13987                 if (ret) {
13988                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
13989                                 remove_duplicate_addrs2_test_strings_vector[i]);
13990                         return false;
13991                 }
13992                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
13993                 memcpy(&test_vector[i].ss,
13994                         res->ai_addr,
13995                         res->ai_addrlen);
13996                 freeaddrinfo(res);
13997         }
13998
13999         count = remove_duplicate_addrs2(test_vector, i);
14000
14001         if (count != 14) {
14002                 fprintf(stderr, "count wrong (%d) should be 14\n",
14003                         count);
14004                 return false;
14005         }
14006
14007         for (i = 0; i < count; i++) {
14008                 char addr[INET6_ADDRSTRLEN];
14009
14010                 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
14011
14012                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14013                         fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
14014                                 i,
14015                                 addr,
14016                                 remove_duplicate_addrs2_test_strings_result[i]);
14017                         return false;
14018                 }
14019         }
14020
14021         printf("run_local_remove_duplicate_addrs2: success\n");
14022         return true;
14023 }
14024
14025 static bool run_local_tdb_opener(int dummy)
14026 {
14027         TDB_CONTEXT *t;
14028         unsigned v = 0;
14029
14030         while (1) {
14031                 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14032                              O_RDWR|O_CREAT, 0755);
14033                 if (t == NULL) {
14034                         perror("tdb_open failed");
14035                         return false;
14036                 }
14037                 tdb_close(t);
14038
14039                 v += 1;
14040                 printf("\r%u", v);
14041         }
14042         return true;
14043 }
14044
14045 static bool run_local_tdb_writer(int dummy)
14046 {
14047         TDB_CONTEXT *t;
14048         unsigned v = 0;
14049         TDB_DATA val;
14050
14051         t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14052         if (t == 0) {
14053                 perror("tdb_open failed");
14054                 return 1;
14055         }
14056
14057         val.dptr = (uint8_t *)&v;
14058         val.dsize = sizeof(v);
14059
14060         while (1) {
14061                 TDB_DATA data;
14062                 int ret;
14063
14064                 ret = tdb_store(t, val, val, 0);
14065                 if (ret != 0) {
14066                         printf("%s\n", tdb_errorstr(t));
14067                 }
14068                 v += 1;
14069                 printf("\r%u", v);
14070
14071                 data = tdb_fetch(t, val);
14072                 if (data.dptr != NULL) {
14073                         SAFE_FREE(data.dptr);
14074                 }
14075         }
14076         return true;
14077 }
14078
14079 static bool run_local_canonicalize_path(int dummy)
14080 {
14081         const char *src[] = {
14082                         "/foo/..",
14083                         "/..",
14084                         "/foo/bar/../baz",
14085                         "/foo/././",
14086                         "/../foo",
14087                         ".././././",
14088                         ".././././../../../boo",
14089                         "./..",
14090                         "/",
14091                         "/../../",
14092                         "/foo/../",
14093                         "/./././",
14094                         "/./././.",
14095                         "/.../././.",
14096                         "/./././.foo",
14097                         "/./././.foo.",
14098                         "/./././foo.",
14099                         "/foo/bar/..",
14100                         "/foo/bar/../baz/",
14101                         "////////////////",
14102                         "/////////./././././.",
14103                         "/./.././../.boo/../baz",
14104                         "/a/component/path",
14105                         "/a/component/path/",
14106                         "/a/component/path/..",
14107                         "/a/component/../path/",
14108                         "///a/./././///component/../////path/",
14109                         NULL
14110                         };
14111         const char *dst[] = {
14112                         "/",
14113                         "/",
14114                         "/foo/baz",
14115                         "/foo",
14116                         "/foo",
14117                         "/",
14118                         "/boo",
14119                         "/",
14120                         "/",
14121                         "/",
14122                         "/",
14123                         "/",
14124                         "/",
14125                         "/...",
14126                         "/.foo",
14127                         "/.foo.",
14128                         "/foo.",
14129                         "/foo",
14130                         "/foo/baz",
14131                         "/",
14132                         "/",
14133                         "/baz",
14134                         "/a/component/path",
14135                         "/a/component/path",
14136                         "/a/component",
14137                         "/a/path",
14138                         "/a/path",
14139                         NULL
14140                         };
14141         unsigned int i;
14142
14143         for (i = 0; src[i] != NULL; i++) {
14144                 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14145                 if (d == NULL) {
14146                         perror("talloc fail\n");
14147                         return false;
14148                 }
14149                 if (strcmp(d, dst[i]) != 0) {
14150                         d_fprintf(stderr,
14151                                 "canonicalize mismatch %s -> %s != %s",
14152                                 src[i], d, dst[i]);
14153                         return false;
14154                 }
14155                 talloc_free(d);
14156         }
14157         return true;
14158 }
14159
14160 static bool run_ign_bad_negprot(int dummy)
14161 {
14162         struct tevent_context *ev;
14163         struct tevent_req *req;
14164         struct smbXcli_conn *conn;
14165         struct sockaddr_storage ss;
14166         NTSTATUS status;
14167         int fd;
14168         bool ok;
14169
14170         printf("starting ignore bad negprot\n");
14171
14172         ok = resolve_name(host, &ss, 0x20, true);
14173         if (!ok) {
14174                 d_fprintf(stderr, "Could not resolve name %s\n", host);
14175                 return false;
14176         }
14177
14178         status = open_socket_out(&ss, 445, 10000, &fd);
14179         if (!NT_STATUS_IS_OK(status)) {
14180                 d_fprintf(stderr, "open_socket_out failed: %s\n",
14181                           nt_errstr(status));
14182                 return false;
14183         }
14184
14185         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14186                                    NULL, 0);
14187         if (conn == NULL) {
14188                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14189                 return false;
14190         }
14191
14192         status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
14193         if (NT_STATUS_IS_OK(status)) {
14194                 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
14195                 return false;
14196         }
14197
14198         ev = samba_tevent_context_init(talloc_tos());
14199         if (ev == NULL) {
14200                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14201                 return false;
14202         }
14203
14204         req = smb1cli_session_setup_nt1_send(
14205                 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
14206                 data_blob_null, data_blob_null, 0x40,
14207                 "Windows 2000 2195", "Windows 2000 5.0");
14208         if (req == NULL) {
14209                 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
14210                 return false;
14211         }
14212
14213         ok = tevent_req_poll_ntstatus(req, ev, &status);
14214         if (!ok) {
14215                 d_fprintf(stderr, "tevent_req_poll failed\n");
14216                 return false;
14217         }
14218
14219         status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
14220                                                 NULL, NULL);
14221         if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
14222                 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
14223                           "%s, expected NT_STATUS_CONNECTION_RESET\n",
14224                           nt_errstr(status));
14225                 return false;
14226         }
14227
14228         TALLOC_FREE(conn);
14229
14230         printf("starting ignore bad negprot\n");
14231
14232         return true;
14233 }
14234
14235 static double create_procs(bool (*fn)(int), bool *result)
14236 {
14237         int i, status;
14238         volatile pid_t *child_status;
14239         volatile bool *child_status_out;
14240         int synccount;
14241         int tries = 8;
14242         struct timeval start;
14243
14244         synccount = 0;
14245
14246         child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
14247         if (!child_status) {
14248                 printf("Failed to setup shared memory\n");
14249                 return -1;
14250         }
14251
14252         child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
14253         if (!child_status_out) {
14254                 printf("Failed to setup result status shared memory\n");
14255                 return -1;
14256         }
14257
14258         for (i = 0; i < torture_nprocs; i++) {
14259                 child_status[i] = 0;
14260                 child_status_out[i] = True;
14261         }
14262
14263         start = timeval_current();
14264
14265         for (i=0;i<torture_nprocs;i++) {
14266                 procnum = i;
14267                 if (fork() == 0) {
14268                         pid_t mypid = getpid();
14269                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
14270
14271                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
14272
14273                         while (1) {
14274                                 if (torture_open_connection(&current_cli, i)) break;
14275                                 if (tries-- == 0) {
14276                                         printf("pid %d failed to start\n", (int)getpid());
14277                                         _exit(1);
14278                                 }
14279                                 smb_msleep(10); 
14280                         }
14281
14282                         child_status[i] = getpid();
14283
14284                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
14285
14286                         child_status_out[i] = fn(i);
14287                         _exit(0);
14288                 }
14289         }
14290
14291         do {
14292                 synccount = 0;
14293                 for (i=0;i<torture_nprocs;i++) {
14294                         if (child_status[i]) synccount++;
14295                 }
14296                 if (synccount == torture_nprocs) break;
14297                 smb_msleep(10);
14298         } while (timeval_elapsed(&start) < 30);
14299
14300         if (synccount != torture_nprocs) {
14301                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
14302                 *result = False;
14303                 return timeval_elapsed(&start);
14304         }
14305
14306         /* start the client load */
14307         start = timeval_current();
14308
14309         for (i=0;i<torture_nprocs;i++) {
14310                 child_status[i] = 0;
14311         }
14312
14313         printf("%d clients started\n", torture_nprocs);
14314
14315         for (i=0;i<torture_nprocs;i++) {
14316                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
14317         }
14318
14319         printf("\n");
14320
14321         for (i=0;i<torture_nprocs;i++) {
14322                 if (!child_status_out[i]) {
14323                         *result = False;
14324                 }
14325         }
14326         return timeval_elapsed(&start);
14327 }
14328
14329 #define FLAG_MULTIPROC 1
14330
14331 static struct {
14332         const char *name;
14333         bool (*fn)(int);
14334         unsigned flags;
14335 } torture_ops[] = {
14336         {
14337                 .name = "FDPASS",
14338                 .fn   = run_fdpasstest,
14339         },
14340         {
14341                 .name = "LOCK1",
14342                 .fn   = run_locktest1,
14343         },
14344         {
14345                 .name = "LOCK2",
14346                 .fn   =  run_locktest2,
14347         },
14348         {
14349                 .name = "LOCK3",
14350                 .fn   =  run_locktest3,
14351         },
14352         {
14353                 .name = "LOCK4",
14354                 .fn   =  run_locktest4,
14355         },
14356         {
14357                 .name = "LOCK5",
14358                 .fn   =  run_locktest5,
14359         },
14360         {
14361                 .name = "LOCK6",
14362                 .fn   =  run_locktest6,
14363         },
14364         {
14365                 .name = "LOCK7",
14366                 .fn   =  run_locktest7,
14367         },
14368         {
14369                 .name = "LOCK8",
14370                 .fn   =  run_locktest8,
14371         },
14372         {
14373                 .name = "LOCK9A",
14374                 .fn   =  run_locktest9a,
14375         },
14376         {
14377                 .name = "LOCK9B",
14378                 .fn   =  run_locktest9b,
14379         },
14380         {
14381                 .name = "LOCK10",
14382                 .fn   =  run_locktest10,
14383         },
14384         {
14385                 .name = "LOCK11",
14386                 .fn   =  run_locktest11,
14387         },
14388         {
14389                 .name = "LOCK12",
14390                 .fn   =  run_locktest12,
14391         },
14392         {
14393                 .name = "LOCK13",
14394                 .fn   =  run_locktest13,
14395         },
14396         {
14397                 .name = "UNLINK",
14398                 .fn   = run_unlinktest,
14399         },
14400         {
14401                 .name = "BROWSE",
14402                 .fn   = run_browsetest,
14403         },
14404         {
14405                 .name = "ATTR",
14406                 .fn   =   run_attrtest,
14407         },
14408         {
14409                 .name = "TRANS2",
14410                 .fn   = run_trans2test,
14411         },
14412         {
14413                 .name  = "MAXFID",
14414                 .fn    = run_maxfidtest,
14415                 .flags = FLAG_MULTIPROC,
14416         },
14417         {
14418                 .name  = "TORTURE",
14419                 .fn    = run_torture,
14420                 .flags = FLAG_MULTIPROC,
14421         },
14422         {
14423                 .name  = "RANDOMIPC",
14424                 .fn    = run_randomipc,
14425         },
14426         {
14427                 .name  = "NEGNOWAIT",
14428                 .fn    = run_negprot_nowait,
14429         },
14430         {
14431                 .name  = "NBENCH",
14432                 .fn    =  run_nbench,
14433         },
14434         {
14435                 .name  = "NBENCH2",
14436                 .fn    = run_nbench2,
14437         },
14438         {
14439                 .name  = "OPLOCK1",
14440                 .fn    =  run_oplock1,
14441         },
14442         {
14443                 .name  = "OPLOCK2",
14444                 .fn    =  run_oplock2,
14445         },
14446         {
14447                 .name  = "OPLOCK4",
14448                 .fn    =  run_oplock4,
14449         },
14450 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
14451         {
14452                 .name  = "OPLOCK5",
14453                 .fn    =  run_oplock5,
14454         },
14455 #endif
14456         {
14457                 .name  = "DIR",
14458                 .fn    =  run_dirtest,
14459         },
14460         {
14461                 .name  = "DIR1",
14462                 .fn    =  run_dirtest1,
14463         },
14464         {
14465                 .name  = "DIR-CREATETIME",
14466                 .fn    =  run_dir_createtime,
14467         },
14468         {
14469                 .name  = "DENY1",
14470                 .fn    =  torture_denytest1,
14471         },
14472         {
14473                 .name  = "DENY2",
14474                 .fn    =  torture_denytest2,
14475         },
14476         {
14477                 .name  = "TCON",
14478                 .fn    =  run_tcon_test,
14479         },
14480         {
14481                 .name  = "TCONDEV",
14482                 .fn    =  run_tcon_devtype_test,
14483         },
14484         {
14485                 .name  = "RW1",
14486                 .fn    =  run_readwritetest,
14487         },
14488         {
14489                 .name  = "RW2",
14490                 .fn    =  run_readwritemulti,
14491                 .flags = FLAG_MULTIPROC
14492         },
14493         {
14494                 .name  = "RW3",
14495                 .fn    =  run_readwritelarge,
14496         },
14497         {
14498                 .name  = "RW-SIGNING",
14499                 .fn    =  run_readwritelarge_signtest,
14500         },
14501         {
14502                 .name  = "OPEN",
14503                 .fn    = run_opentest,
14504         },
14505         {
14506                 .name  = "POSIX",
14507                 .fn    = run_simple_posix_open_test,
14508         },
14509         {
14510                 .name  = "POSIX-APPEND",
14511                 .fn    = run_posix_append,
14512         },
14513         {
14514                 .name  = "POSIX-SYMLINK-ACL",
14515                 .fn    = run_acl_symlink_test,
14516         },
14517         {
14518                 .name  = "POSIX-SYMLINK-EA",
14519                 .fn    = run_ea_symlink_test,
14520         },
14521         {
14522                 .name  = "POSIX-STREAM-DELETE",
14523                 .fn    = run_posix_stream_delete,
14524         },
14525         {
14526                 .name  = "POSIX-OFD-LOCK",
14527                 .fn    = run_posix_ofd_lock_test,
14528         },
14529         {
14530                 .name  = "POSIX-BLOCKING-LOCK",
14531                 .fn    = run_posix_blocking_lock,
14532         },
14533         {
14534                 .name  = "POSIX-MKDIR",
14535                 .fn    = run_posix_mkdir_test,
14536         },
14537         {
14538                 .name  = "POSIX-ACL-OPLOCK",
14539                 .fn    = run_posix_acl_oplock_test,
14540         },
14541         {
14542                 .name  = "POSIX-ACL-SHAREROOT",
14543                 .fn    = run_posix_acl_shareroot_test,
14544         },
14545         {
14546                 .name  = "WINDOWS-BAD-SYMLINK",
14547                 .fn    = run_symlink_open_test,
14548         },
14549         {
14550                 .name  = "CASE-INSENSITIVE-CREATE",
14551                 .fn    = run_case_insensitive_create,
14552         },
14553         {
14554                 .name  = "ASYNC-ECHO",
14555                 .fn    = run_async_echo,
14556         },
14557         {
14558                 .name  = "UID-REGRESSION-TEST",
14559                 .fn    = run_uid_regression_test,
14560         },
14561         {
14562                 .name  = "SHORTNAME-TEST",
14563                 .fn    = run_shortname_test,
14564         },
14565         {
14566                 .name  = "ADDRCHANGE",
14567                 .fn    = run_addrchange,
14568         },
14569 #if 1
14570         {
14571                 .name  = "OPENATTR",
14572                 .fn    = run_openattrtest,
14573         },
14574 #endif
14575         {
14576                 .name  = "XCOPY",
14577                 .fn    = run_xcopy,
14578         },
14579         {
14580                 .name  = "RENAME",
14581                 .fn    = run_rename,
14582         },
14583         {
14584                 .name  = "RENAME-ACCESS",
14585                 .fn    = run_rename_access,
14586         },
14587         {
14588                 .name  = "OWNER-RIGHTS",
14589                 .fn    = run_owner_rights,
14590         },
14591         {
14592                 .name  = "DELETE",
14593                 .fn    = run_deletetest,
14594         },
14595         {
14596                 .name  = "DELETE-STREAM",
14597                 .fn    = run_delete_stream,
14598         },
14599         {
14600                 .name  = "DELETE-PRINT",
14601                 .fn    = run_delete_print_test,
14602         },
14603         {
14604                 .name  = "WILDDELETE",
14605                 .fn    = run_wild_deletetest,
14606         },
14607         {
14608                 .name  = "DELETE-LN",
14609                 .fn    = run_deletetest_ln,
14610         },
14611         {
14612                 .name  = "PROPERTIES",
14613                 .fn    = run_properties,
14614         },
14615         {
14616                 .name  = "MANGLE",
14617                 .fn    = torture_mangle,
14618         },
14619         {
14620                 .name  = "MANGLE1",
14621                 .fn    = run_mangle1,
14622         },
14623         {
14624                 .name  = "MANGLE-ILLEGAL",
14625                 .fn    = run_mangle_illegal,
14626         },
14627         {
14628                 .name  = "W2K",
14629                 .fn    = run_w2ktest,
14630         },
14631         {
14632                 .name  = "TRANS2SCAN",
14633                 .fn    = torture_trans2_scan,
14634         },
14635         {
14636                 .name  = "NTTRANSSCAN",
14637                 .fn    = torture_nttrans_scan,
14638         },
14639         {
14640                 .name  = "UTABLE",
14641                 .fn    = torture_utable,
14642         },
14643         {
14644                 .name  = "CASETABLE",
14645                 .fn    = torture_casetable,
14646         },
14647         {
14648                 .name  = "ERRMAPEXTRACT",
14649                 .fn    = run_error_map_extract,
14650         },
14651         {
14652                 .name  = "PIPE_NUMBER",
14653                 .fn    = run_pipe_number,
14654         },
14655         {
14656                 .name  = "TCON2",
14657                 .fn    =  run_tcon2_test,
14658         },
14659         {
14660                 .name  = "IOCTL",
14661                 .fn    =  torture_ioctl_test,
14662         },
14663         {
14664                 .name  = "CHKPATH",
14665                 .fn    =  torture_chkpath_test,
14666         },
14667         {
14668                 .name  = "FDSESS",
14669                 .fn    = run_fdsesstest,
14670         },
14671         {
14672                 .name  = "EATEST",
14673                 .fn    = run_eatest,
14674         },
14675         {
14676                 .name  = "SESSSETUP_BENCH",
14677                 .fn    = run_sesssetup_bench,
14678         },
14679         {
14680                 .name  = "CHAIN1",
14681                 .fn    = run_chain1,
14682         },
14683         {
14684                 .name  = "CHAIN2",
14685                 .fn    = run_chain2,
14686         },
14687         {
14688                 .name  = "CHAIN3",
14689                 .fn    = run_chain3,
14690         },
14691         {
14692                 .name  = "WINDOWS-WRITE",
14693                 .fn    = run_windows_write,
14694         },
14695         {
14696                 .name  = "LARGE_READX",
14697                 .fn    = run_large_readx,
14698         },
14699         {
14700                 .name  = "MSDFS-ATTRIBUTE",
14701                 .fn    = run_msdfs_attribute,
14702         },
14703         {
14704                 .name  = "NTTRANS-CREATE",
14705                 .fn    = run_nttrans_create,
14706         },
14707         {
14708                 .name  = "NTTRANS-FSCTL",
14709                 .fn    = run_nttrans_fsctl,
14710         },
14711         {
14712                 .name  = "CLI_ECHO",
14713                 .fn    = run_cli_echo,
14714         },
14715         {
14716                 .name  = "CLI_SPLICE",
14717                 .fn    = run_cli_splice,
14718         },
14719         {
14720                 .name  = "TLDAP",
14721                 .fn    = run_tldap,
14722         },
14723         {
14724                 .name  = "STREAMERROR",
14725                 .fn    = run_streamerror,
14726         },
14727         {
14728                 .name  = "NOTIFY-BENCH",
14729                 .fn    = run_notify_bench,
14730         },
14731         {
14732                 .name  = "NOTIFY-BENCH2",
14733                 .fn    = run_notify_bench2,
14734         },
14735         {
14736                 .name  = "NOTIFY-BENCH3",
14737                 .fn    = run_notify_bench3,
14738         },
14739         {
14740                 .name  = "BAD-NBT-SESSION",
14741                 .fn    = run_bad_nbt_session,
14742         },
14743         {
14744                 .name  = "IGN-BAD-NEGPROT",
14745                 .fn    = run_ign_bad_negprot,
14746         },
14747         {
14748                 .name  = "SMB-ANY-CONNECT",
14749                 .fn    = run_smb_any_connect,
14750         },
14751         {
14752                 .name  = "NOTIFY-ONLINE",
14753                 .fn    = run_notify_online,
14754         },
14755         {
14756                 .name  = "SMB2-BASIC",
14757                 .fn    = run_smb2_basic,
14758         },
14759         {
14760                 .name  = "SMB2-NEGPROT",
14761                 .fn    = run_smb2_negprot,
14762         },
14763         {
14764                 .name  = "SMB2-ANONYMOUS",
14765                 .fn    = run_smb2_anonymous,
14766         },
14767         {
14768                 .name  = "SMB2-SESSION-RECONNECT",
14769                 .fn    = run_smb2_session_reconnect,
14770         },
14771         {
14772                 .name  = "SMB2-TCON-DEPENDENCE",
14773                 .fn    = run_smb2_tcon_dependence,
14774         },
14775         {
14776                 .name  = "SMB2-MULTI-CHANNEL",
14777                 .fn    = run_smb2_multi_channel,
14778         },
14779         {
14780                 .name  = "SMB2-SESSION-REAUTH",
14781                 .fn    = run_smb2_session_reauth,
14782         },
14783         {
14784                 .name  = "SMB2-FTRUNCATE",
14785                 .fn    = run_smb2_ftruncate,
14786         },
14787         {
14788                 .name  = "SMB2-DIR-FSYNC",
14789                 .fn    = run_smb2_dir_fsync,
14790         },
14791         {
14792                 .name  = "SMB2-PATH-SLASH",
14793                 .fn    = run_smb2_path_slash,
14794         },
14795         {
14796                 .name  = "SMB1-SYSTEM-SECURITY",
14797                 .fn    = run_smb1_system_security,
14798         },
14799         {
14800                 .name  = "SMB2-SACL",
14801                 .fn    = run_smb2_sacl,
14802         },
14803         {
14804                 .name  = "SMB2-QUOTA1",
14805                 .fn    = run_smb2_quota1,
14806         },
14807         {
14808                 .name  = "CLEANUP1",
14809                 .fn    = run_cleanup1,
14810         },
14811         {
14812                 .name  = "CLEANUP2",
14813                 .fn    = run_cleanup2,
14814         },
14815         {
14816                 .name  = "CLEANUP4",
14817                 .fn    = run_cleanup4,
14818         },
14819         {
14820                 .name  = "OPLOCK-CANCEL",
14821                 .fn    = run_oplock_cancel,
14822         },
14823         {
14824                 .name  = "PIDHIGH",
14825                 .fn    = run_pidhigh,
14826         },
14827         {
14828                 .name  = "LOCAL-SUBSTITUTE",
14829                 .fn    = run_local_substitute,
14830         },
14831         {
14832                 .name  = "LOCAL-GENCACHE",
14833                 .fn    = run_local_gencache,
14834         },
14835         {
14836                 .name  = "LOCAL-DBWRAP-WATCH1",
14837                 .fn    = run_dbwrap_watch1,
14838         },
14839         {
14840                 .name  = "LOCAL-DBWRAP-WATCH2",
14841                 .fn    = run_dbwrap_watch2,
14842         },
14843         {
14844                 .name  = "LOCAL-DBWRAP-WATCH3",
14845                 .fn    = run_dbwrap_watch3,
14846         },
14847         {
14848                 .name  = "LOCAL-DBWRAP-WATCH4",
14849                 .fn    = run_dbwrap_watch4,
14850         },
14851         {
14852                 .name  = "LOCAL-DBWRAP-DO-LOCKED1",
14853                 .fn    = run_dbwrap_do_locked1,
14854         },
14855         {
14856                 .name  = "LOCAL-MESSAGING-READ1",
14857                 .fn    = run_messaging_read1,
14858         },
14859         {
14860                 .name  = "LOCAL-MESSAGING-READ2",
14861                 .fn    = run_messaging_read2,
14862         },
14863         {
14864                 .name  = "LOCAL-MESSAGING-READ3",
14865                 .fn    = run_messaging_read3,
14866         },
14867         {
14868                 .name  = "LOCAL-MESSAGING-READ4",
14869                 .fn    = run_messaging_read4,
14870         },
14871         {
14872                 .name  = "LOCAL-MESSAGING-FDPASS1",
14873                 .fn    = run_messaging_fdpass1,
14874         },
14875         {
14876                 .name  = "LOCAL-MESSAGING-FDPASS2",
14877                 .fn    = run_messaging_fdpass2,
14878         },
14879         {
14880                 .name  = "LOCAL-MESSAGING-FDPASS2a",
14881                 .fn    = run_messaging_fdpass2a,
14882         },
14883         {
14884                 .name  = "LOCAL-MESSAGING-FDPASS2b",
14885                 .fn    = run_messaging_fdpass2b,
14886         },
14887         {
14888                 .name  = "LOCAL-MESSAGING-SEND-ALL",
14889                 .fn    = run_messaging_send_all,
14890         },
14891         {
14892                 .name  = "LOCAL-BASE64",
14893                 .fn    = run_local_base64,
14894         },
14895         {
14896                 .name  = "LOCAL-RBTREE",
14897                 .fn    = run_local_rbtree,
14898         },
14899         {
14900                 .name  = "LOCAL-MEMCACHE",
14901                 .fn    = run_local_memcache,
14902         },
14903         {
14904                 .name  = "LOCAL-STREAM-NAME",
14905                 .fn    = run_local_stream_name,
14906         },
14907         {
14908                 .name  = "WBCLIENT-MULTI-PING",
14909                 .fn    = run_wbclient_multi_ping,
14910         },
14911         {
14912                 .name  = "LOCAL-string_to_sid",
14913                 .fn    = run_local_string_to_sid,
14914         },
14915         {
14916                 .name  = "LOCAL-sid_to_string",
14917                 .fn    = run_local_sid_to_string,
14918         },
14919         {
14920                 .name  = "LOCAL-binary_to_sid",
14921                 .fn    = run_local_binary_to_sid,
14922         },
14923         {
14924                 .name  = "LOCAL-DBTRANS",
14925                 .fn    = run_local_dbtrans,
14926         },
14927         {
14928                 .name  = "LOCAL-TEVENT-POLL",
14929                 .fn    = run_local_tevent_poll,
14930         },
14931         {
14932                 .name  = "LOCAL-CONVERT-STRING",
14933                 .fn    = run_local_convert_string,
14934         },
14935         {
14936                 .name  = "LOCAL-CONV-AUTH-INFO",
14937                 .fn    = run_local_conv_auth_info,
14938         },
14939         {
14940                 .name  = "LOCAL-hex_encode_buf",
14941                 .fn    = run_local_hex_encode_buf,
14942         },
14943         {
14944                 .name  = "LOCAL-IDMAP-TDB-COMMON",
14945                 .fn    = run_idmap_tdb_common_test,
14946         },
14947         {
14948                 .name  = "LOCAL-remove_duplicate_addrs2",
14949                 .fn    = run_local_remove_duplicate_addrs2,
14950         },
14951         {
14952                 .name  = "local-tdb-opener",
14953                 .fn    = run_local_tdb_opener,
14954         },
14955         {
14956                 .name  = "local-tdb-writer",
14957                 .fn    = run_local_tdb_writer,
14958         },
14959         {
14960                 .name  = "LOCAL-DBWRAP-CTDB1",
14961                 .fn    = run_local_dbwrap_ctdb1,
14962         },
14963         {
14964                 .name  = "LOCAL-BENCH-PTHREADPOOL",
14965                 .fn    = run_bench_pthreadpool,
14966         },
14967         {
14968                 .name  = "LOCAL-PTHREADPOOL-TEVENT",
14969                 .fn    = run_pthreadpool_tevent,
14970         },
14971         {
14972                 .name  = "LOCAL-G-LOCK1",
14973                 .fn    = run_g_lock1,
14974         },
14975         {
14976                 .name  = "LOCAL-G-LOCK2",
14977                 .fn    = run_g_lock2,
14978         },
14979         {
14980                 .name  = "LOCAL-G-LOCK3",
14981                 .fn    = run_g_lock3,
14982         },
14983         {
14984                 .name  = "LOCAL-G-LOCK4",
14985                 .fn    = run_g_lock4,
14986         },
14987         {
14988                 .name  = "LOCAL-G-LOCK4A",
14989                 .fn    = run_g_lock4a,
14990         },
14991         {
14992                 .name  = "LOCAL-G-LOCK5",
14993                 .fn    = run_g_lock5,
14994         },
14995         {
14996                 .name  = "LOCAL-G-LOCK6",
14997                 .fn    = run_g_lock6,
14998         },
14999         {
15000                 .name  = "LOCAL-G-LOCK7",
15001                 .fn    = run_g_lock7,
15002         },
15003         {
15004                 .name  = "LOCAL-G-LOCK8",
15005                 .fn    = run_g_lock8,
15006         },
15007         {
15008                 .name  = "LOCAL-G-LOCK-PING-PONG",
15009                 .fn    = run_g_lock_ping_pong,
15010         },
15011         {
15012                 .name  = "LOCAL-CANONICALIZE-PATH",
15013                 .fn    = run_local_canonicalize_path,
15014         },
15015         {
15016                 .name  = "LOCAL-NAMEMAP-CACHE1",
15017                 .fn    = run_local_namemap_cache1,
15018         },
15019         {
15020                 .name  = "LOCAL-IDMAP-CACHE1",
15021                 .fn    = run_local_idmap_cache1,
15022         },
15023         {
15024                 .name  = "qpathinfo-bufsize",
15025                 .fn    = run_qpathinfo_bufsize,
15026         },
15027         {
15028                 .name  = "hide-new-files-timeout",
15029                 .fn    = run_hidenewfiles,
15030         },
15031 #ifdef CLUSTER_SUPPORT
15032         {
15033                 .name  = "ctdbd-conn1",
15034                 .fn    = run_ctdbd_conn1,
15035         },
15036 #endif
15037         {
15038                 .name  = "readdir-timestamp",
15039                 .fn    = run_readdir_timestamp,
15040         },
15041         {
15042                 .name = NULL,
15043         },
15044 };
15045
15046 /****************************************************************************
15047 run a specified test or "ALL"
15048 ****************************************************************************/
15049 static bool run_test(const char *name)
15050 {
15051         bool ret = True;
15052         bool result = True;
15053         bool found = False;
15054         int i;
15055         double t;
15056         if (strequal(name,"ALL")) {
15057                 for (i=0;torture_ops[i].name;i++) {
15058                         run_test(torture_ops[i].name);
15059                 }
15060                 found = True;
15061         }
15062
15063         for (i=0;torture_ops[i].name;i++) {
15064                 fstr_sprintf(randomfname, "\\XX%x", 
15065                          (unsigned)random());
15066
15067                 if (strequal(name, torture_ops[i].name)) {
15068                         found = True;
15069                         printf("Running %s\n", name);
15070                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
15071                                 t = create_procs(torture_ops[i].fn, &result);
15072                                 if (!result) { 
15073                                         ret = False;
15074                                         printf("TEST %s FAILED!\n", name);
15075                                 }
15076                         } else {
15077                                 struct timeval start;
15078                                 start = timeval_current();
15079                                 if (!torture_ops[i].fn(0)) {
15080                                         ret = False;
15081                                         printf("TEST %s FAILED!\n", name);
15082                                 }
15083                                 t = timeval_elapsed(&start);
15084                         }
15085                         printf("%s took %g secs\n\n", name, t);
15086                 }
15087         }
15088
15089         if (!found) {
15090                 printf("Did not find a test named %s\n", name);
15091                 ret = False;
15092         }
15093
15094         return ret;
15095 }
15096
15097
15098 static void usage(void)
15099 {
15100         int i;
15101
15102         printf("WARNING samba4 test suite is much more complete nowadays.\n");
15103         printf("Please use samba4 torture.\n\n");
15104
15105         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
15106
15107         printf("\t-d debuglevel\n");
15108         printf("\t-U user%%pass\n");
15109         printf("\t-k                    use kerberos\n");
15110         printf("\t-N numprocs\n");
15111         printf("\t-n my_netbios_name\n");
15112         printf("\t-W workgroup\n");
15113         printf("\t-o num_operations\n");
15114         printf("\t-O socket_options\n");
15115         printf("\t-m maximum protocol\n");
15116         printf("\t-L use oplocks\n");
15117         printf("\t-c CLIENT.TXT         specify client load file for NBENCH\n");
15118         printf("\t-A showall\n");
15119         printf("\t-p port\n");
15120         printf("\t-s seed\n");
15121         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
15122         printf("\t-f filename           filename to test\n");
15123         printf("\t-e                    encrypt\n");
15124         printf("\n\n");
15125
15126         printf("tests are:");
15127         for (i=0;torture_ops[i].name;i++) {
15128                 printf(" %s", torture_ops[i].name);
15129         }
15130         printf("\n");
15131
15132         printf("default test is ALL\n");
15133
15134         exit(1);
15135 }
15136
15137 /****************************************************************************
15138   main program
15139 ****************************************************************************/
15140  int main(int argc,char *argv[])
15141 {
15142         int opt, i;
15143         char *p;
15144         int gotuser = 0;
15145         int gotpass = 0;
15146         bool correct = True;
15147         TALLOC_CTX *frame = talloc_stackframe();
15148         int seed = time(NULL);
15149
15150 #ifdef HAVE_SETBUFFER
15151         setbuffer(stdout, NULL, 0);
15152 #endif
15153
15154         setup_logging("smbtorture", DEBUG_STDOUT);
15155
15156         smb_init_locale();
15157         fault_setup();
15158
15159         if (is_default_dyn_CONFIGFILE()) {
15160                 if(getenv("SMB_CONF_PATH")) {
15161                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
15162                 }
15163         }
15164         lp_load_global(get_dyn_CONFIGFILE());
15165         load_interfaces();
15166
15167         if (argc < 2) {
15168                 usage();
15169         }
15170
15171         for(p = argv[1]; *p; p++)
15172           if(*p == '\\')
15173             *p = '/';
15174
15175         if (strncmp(argv[1], "//", 2)) {
15176                 usage();
15177         }
15178
15179         fstrcpy(host, &argv[1][2]);
15180         p = strchr_m(&host[2],'/');
15181         if (!p) {
15182                 usage();
15183         }
15184         *p = 0;
15185         fstrcpy(share, p+1);
15186
15187         fstrcpy(myname, get_myname(talloc_tos()));
15188         if (!*myname) {
15189                 fprintf(stderr, "Failed to get my hostname.\n");
15190                 return 1;
15191         }
15192
15193         if (*username == 0 && getenv("LOGNAME")) {
15194           fstrcpy(username,getenv("LOGNAME"));
15195         }
15196
15197         argc--;
15198         argv++;
15199
15200         fstrcpy(workgroup, lp_workgroup());
15201
15202         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
15203                != EOF) {
15204                 switch (opt) {
15205                 case 'p':
15206                         port_to_use = atoi(optarg);
15207                         break;
15208                 case 's':
15209                         seed = atoi(optarg);
15210                         break;
15211                 case 'W':
15212                         fstrcpy(workgroup,optarg);
15213                         break;
15214                 case 'm':
15215                         lp_set_cmdline("client max protocol", optarg);
15216                         break;
15217                 case 'N':
15218                         torture_nprocs = atoi(optarg);
15219                         break;
15220                 case 'o':
15221                         torture_numops = atoi(optarg);
15222                         break;
15223                 case 'd':
15224                         lp_set_cmdline("log level", optarg);
15225                         break;
15226                 case 'O':
15227                         sockops = optarg;
15228                         break;
15229                 case 'L':
15230                         use_oplocks = True;
15231                         break;
15232                 case 'l':
15233                         local_path = optarg;
15234                         break;
15235                 case 'A':
15236                         torture_showall = True;
15237                         break;
15238                 case 'n':
15239                         fstrcpy(myname, optarg);
15240                         break;
15241                 case 'c':
15242                         client_txt = optarg;
15243                         break;
15244                 case 'e':
15245                         do_encrypt = true;
15246                         break;
15247                 case 'k':
15248 #ifdef HAVE_KRB5
15249                         use_kerberos = True;
15250 #else
15251                         d_printf("No kerberos support compiled in\n");
15252                         exit(1);
15253 #endif
15254                         break;
15255                 case 'U':
15256                         gotuser = 1;
15257                         fstrcpy(username,optarg);
15258                         p = strchr_m(username,'%');
15259                         if (p) {
15260                                 *p = 0;
15261                                 fstrcpy(password, p+1);
15262                                 gotpass = 1;
15263                         }
15264                         break;
15265                 case 'b':
15266                         fstrcpy(multishare_conn_fname, optarg);
15267                         use_multishare_conn = True;
15268                         break;
15269                 case 'B':
15270                         torture_blocksize = atoi(optarg);
15271                         break;
15272                 case 'f':
15273                         test_filename = SMB_STRDUP(optarg);
15274                         break;
15275                 default:
15276                         printf("Unknown option %c (%d)\n", (char)opt, opt);
15277                         usage();
15278                 }
15279         }
15280
15281         d_printf("using seed %d\n", seed);
15282
15283         srandom(seed);
15284
15285         if(use_kerberos && !gotuser) gotpass = True;
15286
15287         while (!gotpass) {
15288                 char pwd[256] = {0};
15289                 int rc;
15290
15291                 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
15292                 if (rc == 0) {
15293                         fstrcpy(password, pwd);
15294                         gotpass = 1;
15295                 }
15296         }
15297
15298         printf("host=%s share=%s user=%s myname=%s\n", 
15299                host, share, username, myname);
15300
15301         torture_creds = cli_session_creds_init(frame,
15302                                                username,
15303                                                workgroup,
15304                                                NULL, /* realm */
15305                                                password,
15306                                                use_kerberos,
15307                                                false, /* fallback_after_kerberos */
15308                                                false, /* use_ccache */
15309                                                false); /* password_is_nt_hash */
15310         if (torture_creds == NULL) {
15311                 d_printf("cli_session_creds_init() failed.\n");
15312                 exit(1);
15313         }
15314
15315         if (argc == optind) {
15316                 correct = run_test("ALL");
15317         } else {
15318                 for (i=optind;i<argc;i++) {
15319                         if (!run_test(argv[i])) {
15320                                 correct = False;
15321                         }
15322                 }
15323         }
15324
15325         TALLOC_FREE(frame);
15326
15327         if (correct) {
15328                 return(0);
15329         } else {
15330                 return(1);
15331         }
15332 }