torture3: Add oplock5 kernel-oplock test
[samba.git] / source3 / torture / torture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-1998
5    Copyright (C) Jeremy Allison 2009
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/shmem.h"
23 #include "libsmb/namequery.h"
24 #include "wbc_async.h"
25 #include "torture/proto.h"
26 #include "libcli/security/security.h"
27 #include "tldap.h"
28 #include "tldap_util.h"
29 #include "../librpc/gen_ndr/svcctl.h"
30 #include "../lib/util/memcache.h"
31 #include "nsswitch/winbind_client.h"
32 #include "dbwrap/dbwrap.h"
33 #include "dbwrap/dbwrap_open.h"
34 #include "dbwrap/dbwrap_rbt.h"
35 #include "async_smb.h"
36 #include "libsmb/libsmb.h"
37 #include "libsmb/clirap.h"
38 #include "trans2.h"
39 #include "libsmb/nmblib.h"
40 #include "../lib/util/tevent_ntstatus.h"
41 #include "util_tdb.h"
42 #include "../libcli/smb/read_smb.h"
43 #include "../libcli/smb/smbXcli_base.h"
44 #include "lib/util/sys_rw_data.h"
45 #include "lib/util/base64.h"
46 #include "lib/util/time.h"
47 #include "lib/gencache.h"
48 #include "lib/util/sys_rw.h"
49
50 #include <gnutls/gnutls.h>
51 #include <gnutls/crypto.h>
52
53 extern char *optarg;
54 extern int optind;
55
56 fstring host, workgroup, share, password, username, myname;
57 struct cli_credentials *torture_creds;
58 static const char *sockops="TCP_NODELAY";
59 int torture_nprocs=1;
60 static int port_to_use=0;
61 int torture_numops=100;
62 int torture_blocksize=1024*1024;
63 static int procnum; /* records process count number when forking */
64 static struct cli_state *current_cli;
65 static fstring randomfname;
66 static bool use_oplocks;
67 static bool use_level_II_oplocks;
68 static const char *client_txt = "client_oplocks.txt";
69 static bool disable_spnego;
70 static bool use_kerberos;
71 static bool force_dos_errors;
72 static fstring multishare_conn_fname;
73 static bool use_multishare_conn = False;
74 static bool do_encrypt;
75 static const char *local_path = NULL;
76 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
77 char *test_filename;
78
79 bool torture_showall = False;
80
81 static double create_procs(bool (*fn)(int), bool *result);
82
83 /********************************************************************
84  Ensure a connection is encrypted.
85 ********************************************************************/
86
87 static bool force_cli_encryption(struct cli_state *c,
88                         const char *sharename)
89 {
90         uint16_t major, minor;
91         uint32_t caplow, caphigh;
92         NTSTATUS status;
93
94         if (!SERVER_HAS_UNIX_CIFS(c)) {
95                 d_printf("Encryption required and "
96                         "server that doesn't support "
97                         "UNIX extensions - failing connect\n");
98                         return false;
99         }
100
101         status = cli_unix_extensions_version(c, &major, &minor, &caplow,
102                                              &caphigh);
103         if (!NT_STATUS_IS_OK(status)) {
104                 d_printf("Encryption required and "
105                         "can't get UNIX CIFS extensions "
106                         "version from server: %s\n", nt_errstr(status));
107                 return false;
108         }
109
110         if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
111                 d_printf("Encryption required and "
112                         "share %s doesn't support "
113                         "encryption.\n", sharename);
114                 return false;
115         }
116
117         status = cli_smb1_setup_encryption(c, torture_creds);
118         if (!NT_STATUS_IS_OK(status)) {
119                 d_printf("Encryption required and "
120                         "setup failed with error %s.\n",
121                         nt_errstr(status));
122                 return false;
123         }
124
125         return true;
126 }
127
128
129 static struct cli_state *open_nbt_connection(void)
130 {
131         struct cli_state *c;
132         NTSTATUS status;
133         int flags = 0;
134
135         if (disable_spnego) {
136                 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
137         }
138
139         if (use_oplocks) {
140                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
141         }
142
143         if (use_level_II_oplocks) {
144                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
145         }
146
147         if (use_kerberos) {
148                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
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 #if 0
1014         /* ToDo - set allocation. JRA */
1015         if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1016                 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1017                 return False;
1018         }
1019         if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1020                                  NULL, NULL)) {
1021                 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1022                 correct = False;
1023         }
1024         if (fsize != 0)
1025                 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1026 #endif
1027
1028         status = cli_close(cli1, fnum1);
1029         if (!NT_STATUS_IS_OK(status)) {
1030                 printf("close failed (%s)\n", nt_errstr(status));
1031                 correct = False;
1032         }
1033
1034         if (!torture_close_connection(cli1)) {
1035                 correct = False;
1036         }
1037         return correct;
1038 }
1039
1040 static bool run_readwritelarge(int dummy)
1041 {
1042         return run_readwritelarge_internal();
1043 }
1044
1045 static bool run_readwritelarge_signtest(int dummy)
1046 {
1047         bool ret;
1048         signing_state = SMB_SIGNING_REQUIRED;
1049         ret = run_readwritelarge_internal();
1050         signing_state = SMB_SIGNING_DEFAULT;
1051         return ret;
1052 }
1053
1054 int line_count = 0;
1055 int nbio_id;
1056
1057 #define ival(s) strtol(s, NULL, 0)
1058
1059 /* run a test that simulates an approximate netbench client load */
1060 static bool run_netbench(int client)
1061 {
1062         struct cli_state *cli;
1063         int i;
1064         char line[1024];
1065         char cname[20];
1066         FILE *f;
1067         const char *params[20];
1068         bool correct = True;
1069
1070         cli = current_cli;
1071
1072         nbio_id = client;
1073
1074         smbXcli_conn_set_sockopt(cli->conn, sockops);
1075
1076         nb_setup(cli);
1077
1078         slprintf(cname,sizeof(cname)-1, "client%d", client);
1079
1080         f = fopen(client_txt, "r");
1081
1082         if (!f) {
1083                 perror(client_txt);
1084                 return False;
1085         }
1086
1087         while (fgets(line, sizeof(line)-1, f)) {
1088                 char *saveptr;
1089                 line_count++;
1090
1091                 line[strlen(line)-1] = 0;
1092
1093                 /* printf("[%d] %s\n", line_count, line); */
1094
1095                 all_string_sub(line,"client1", cname, sizeof(line));
1096
1097                 /* parse the command parameters */
1098                 params[0] = strtok_r(line, " ", &saveptr);
1099                 i = 0;
1100                 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1101
1102                 params[i] = "";
1103
1104                 if (i < 2) continue;
1105
1106                 if (!strncmp(params[0],"SMB", 3)) {
1107                         printf("ERROR: You are using a dbench 1 load file\n");
1108                         exit(1);
1109                 }
1110
1111                 if (!strcmp(params[0],"NTCreateX")) {
1112                         nb_createx(params[1], ival(params[2]), ival(params[3]), 
1113                                    ival(params[4]));
1114                 } else if (!strcmp(params[0],"Close")) {
1115                         nb_close(ival(params[1]));
1116                 } else if (!strcmp(params[0],"Rename")) {
1117                         nb_rename(params[1], params[2]);
1118                 } else if (!strcmp(params[0],"Unlink")) {
1119                         nb_unlink(params[1]);
1120                 } else if (!strcmp(params[0],"Deltree")) {
1121                         nb_deltree(params[1]);
1122                 } else if (!strcmp(params[0],"Rmdir")) {
1123                         nb_rmdir(params[1]);
1124                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1125                         nb_qpathinfo(params[1]);
1126                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1127                         nb_qfileinfo(ival(params[1]));
1128                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1129                         nb_qfsinfo(ival(params[1]));
1130                 } else if (!strcmp(params[0],"FIND_FIRST")) {
1131                         nb_findfirst(params[1]);
1132                 } else if (!strcmp(params[0],"WriteX")) {
1133                         nb_writex(ival(params[1]), 
1134                                   ival(params[2]), ival(params[3]), ival(params[4]));
1135                 } else if (!strcmp(params[0],"ReadX")) {
1136                         nb_readx(ival(params[1]), 
1137                                   ival(params[2]), ival(params[3]), ival(params[4]));
1138                 } else if (!strcmp(params[0],"Flush")) {
1139                         nb_flush(ival(params[1]));
1140                 } else {
1141                         printf("Unknown operation %s\n", params[0]);
1142                         exit(1);
1143                 }
1144         }
1145         fclose(f);
1146
1147         nb_cleanup();
1148
1149         if (!torture_close_connection(cli)) {
1150                 correct = False;
1151         }
1152
1153         return correct;
1154 }
1155
1156
1157 /* run a test that simulates an approximate netbench client load */
1158 static bool run_nbench(int dummy)
1159 {
1160         double t;
1161         bool correct = True;
1162
1163         nbio_shmem(torture_nprocs);
1164
1165         nbio_id = -1;
1166
1167         signal(SIGALRM, nb_alarm);
1168         alarm(1);
1169         t = create_procs(run_netbench, &correct);
1170         alarm(0);
1171
1172         printf("\nThroughput %g MB/sec\n", 
1173                1.0e-6 * nbio_total() / t);
1174         return correct;
1175 }
1176
1177
1178 /*
1179   This test checks for two things:
1180
1181   1) correct support for retaining locks over a close (ie. the server
1182      must not use posix semantics)
1183   2) support for lock timeouts
1184  */
1185 static bool run_locktest1(int dummy)
1186 {
1187         struct cli_state *cli1, *cli2;
1188         const char *fname = "\\lockt1.lck";
1189         uint16_t fnum1, fnum2, fnum3;
1190         time_t t1, t2;
1191         unsigned lock_timeout;
1192         NTSTATUS status;
1193
1194         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1195                 return False;
1196         }
1197         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1198         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1199
1200         printf("starting locktest1\n");
1201
1202         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1203
1204         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1205                           &fnum1);
1206         if (!NT_STATUS_IS_OK(status)) {
1207                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1208                 return False;
1209         }
1210
1211         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1212         if (!NT_STATUS_IS_OK(status)) {
1213                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1214                 return False;
1215         }
1216
1217         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1218         if (!NT_STATUS_IS_OK(status)) {
1219                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1220                 return False;
1221         }
1222
1223         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1224         if (!NT_STATUS_IS_OK(status)) {
1225                 printf("lock1 failed (%s)\n", nt_errstr(status));
1226                 return false;
1227         }
1228
1229         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1230         if (NT_STATUS_IS_OK(status)) {
1231                 printf("lock2 succeeded! This is a locking bug\n");
1232                 return false;
1233         } else {
1234                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1235                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1236                         return false;
1237                 }
1238         }
1239
1240         lock_timeout = (1 + (random() % 20));
1241         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1242         t1 = time(NULL);
1243         status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1244         if (NT_STATUS_IS_OK(status)) {
1245                 printf("lock3 succeeded! This is a locking bug\n");
1246                 return false;
1247         } else {
1248                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1249                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1250                         return false;
1251                 }
1252         }
1253         t2 = time(NULL);
1254
1255         if (ABS(t2 - t1) < lock_timeout-1) {
1256                 printf("error: This server appears not to support timed lock requests\n");
1257         }
1258
1259         printf("server slept for %u seconds for a %u second timeout\n",
1260                (unsigned int)(t2-t1), lock_timeout);
1261
1262         status = cli_close(cli1, fnum2);
1263         if (!NT_STATUS_IS_OK(status)) {
1264                 printf("close1 failed (%s)\n", nt_errstr(status));
1265                 return False;
1266         }
1267
1268         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1269         if (NT_STATUS_IS_OK(status)) {
1270                 printf("lock4 succeeded! This is a locking bug\n");
1271                 return false;
1272         } else {
1273                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1274                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1275                         return false;
1276                 }
1277         }
1278
1279         status = cli_close(cli1, fnum1);
1280         if (!NT_STATUS_IS_OK(status)) {
1281                 printf("close2 failed (%s)\n", nt_errstr(status));
1282                 return False;
1283         }
1284
1285         status = cli_close(cli2, fnum3);
1286         if (!NT_STATUS_IS_OK(status)) {
1287                 printf("close3 failed (%s)\n", nt_errstr(status));
1288                 return False;
1289         }
1290
1291         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1292         if (!NT_STATUS_IS_OK(status)) {
1293                 printf("unlink failed (%s)\n", nt_errstr(status));
1294                 return False;
1295         }
1296
1297
1298         if (!torture_close_connection(cli1)) {
1299                 return False;
1300         }
1301
1302         if (!torture_close_connection(cli2)) {
1303                 return False;
1304         }
1305
1306         printf("Passed locktest1\n");
1307         return True;
1308 }
1309
1310 /*
1311   this checks to see if a secondary tconx can use open files from an
1312   earlier tconx
1313  */
1314 static bool run_tcon_test(int dummy)
1315 {
1316         static struct cli_state *cli;
1317         const char *fname = "\\tcontest.tmp";
1318         uint16_t fnum1;
1319         uint32_t cnum1, cnum2, cnum3;
1320         struct smbXcli_tcon *orig_tcon = NULL;
1321         uint16_t vuid1, vuid2;
1322         char buf[4];
1323         bool ret = True;
1324         NTSTATUS status;
1325
1326         memset(buf, '\0', sizeof(buf));
1327
1328         if (!torture_open_connection(&cli, 0)) {
1329                 return False;
1330         }
1331         smbXcli_conn_set_sockopt(cli->conn, sockops);
1332
1333         printf("starting tcontest\n");
1334
1335         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1336
1337         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1338         if (!NT_STATUS_IS_OK(status)) {
1339                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1340                 return False;
1341         }
1342
1343         cnum1 = cli_state_get_tid(cli);
1344         vuid1 = cli_state_get_uid(cli);
1345
1346         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1347         if (!NT_STATUS_IS_OK(status)) {
1348                 printf("initial write failed (%s)", nt_errstr(status));
1349                 return False;
1350         }
1351
1352         orig_tcon = cli_state_save_tcon(cli);
1353         if (orig_tcon == NULL) {
1354                 return false;
1355         }
1356
1357         status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1358         if (!NT_STATUS_IS_OK(status)) {
1359                 printf("%s refused 2nd tree connect (%s)\n", host,
1360                        nt_errstr(status));
1361                 cli_shutdown(cli);
1362                 return False;
1363         }
1364
1365         cnum2 = cli_state_get_tid(cli);
1366         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1367         vuid2 = cli_state_get_uid(cli) + 1;
1368
1369         /* try a write with the wrong tid */
1370         cli_state_set_tid(cli, cnum2);
1371
1372         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1373         if (NT_STATUS_IS_OK(status)) {
1374                 printf("* server allows write with wrong TID\n");
1375                 ret = False;
1376         } else {
1377                 printf("server fails write with wrong TID : %s\n",
1378                        nt_errstr(status));
1379         }
1380
1381
1382         /* try a write with an invalid tid */
1383         cli_state_set_tid(cli, cnum3);
1384
1385         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1386         if (NT_STATUS_IS_OK(status)) {
1387                 printf("* server allows write with invalid TID\n");
1388                 ret = False;
1389         } else {
1390                 printf("server fails write with invalid TID : %s\n",
1391                        nt_errstr(status));
1392         }
1393
1394         /* try a write with an invalid vuid */
1395         cli_state_set_uid(cli, vuid2);
1396         cli_state_set_tid(cli, cnum1);
1397
1398         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1399         if (NT_STATUS_IS_OK(status)) {
1400                 printf("* server allows write with invalid VUID\n");
1401                 ret = False;
1402         } else {
1403                 printf("server fails write with invalid VUID : %s\n",
1404                        nt_errstr(status));
1405         }
1406
1407         cli_state_set_tid(cli, cnum1);
1408         cli_state_set_uid(cli, vuid1);
1409
1410         status = cli_close(cli, fnum1);
1411         if (!NT_STATUS_IS_OK(status)) {
1412                 printf("close failed (%s)\n", nt_errstr(status));
1413                 return False;
1414         }
1415
1416         cli_state_set_tid(cli, cnum2);
1417
1418         status = cli_tdis(cli);
1419         if (!NT_STATUS_IS_OK(status)) {
1420                 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1421                 return False;
1422         }
1423
1424         cli_state_restore_tcon(cli, orig_tcon);
1425
1426         cli_state_set_tid(cli, cnum1);
1427
1428         if (!torture_close_connection(cli)) {
1429                 return False;
1430         }
1431
1432         return ret;
1433 }
1434
1435
1436 /*
1437  checks for old style tcon support
1438  */
1439 static bool run_tcon2_test(int dummy)
1440 {
1441         static struct cli_state *cli;
1442         uint16_t cnum, max_xmit;
1443         char *service;
1444         NTSTATUS status;
1445
1446         if (!torture_open_connection(&cli, 0)) {
1447                 return False;
1448         }
1449         smbXcli_conn_set_sockopt(cli->conn, sockops);
1450
1451         printf("starting tcon2 test\n");
1452
1453         if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1454                 return false;
1455         }
1456
1457         status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1458
1459         SAFE_FREE(service);
1460
1461         if (!NT_STATUS_IS_OK(status)) {
1462                 printf("tcon2 failed : %s\n", nt_errstr(status));
1463         } else {
1464                 printf("tcon OK : max_xmit=%d cnum=%d\n",
1465                        (int)max_xmit, (int)cnum);
1466         }
1467
1468         if (!torture_close_connection(cli)) {
1469                 return False;
1470         }
1471
1472         printf("Passed tcon2 test\n");
1473         return True;
1474 }
1475
1476 static bool tcon_devtest(struct cli_state *cli,
1477                          const char *myshare, const char *devtype,
1478                          const char *return_devtype,
1479                          NTSTATUS expected_error)
1480 {
1481         NTSTATUS status;
1482         bool ret;
1483
1484         status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1485
1486         if (NT_STATUS_IS_OK(expected_error)) {
1487                 if (NT_STATUS_IS_OK(status)) {
1488                         if (return_devtype != NULL &&
1489                             strequal(cli->dev, return_devtype)) {
1490                                 ret = True;
1491                         } else { 
1492                                 printf("tconX to share %s with type %s "
1493                                        "succeeded but returned the wrong "
1494                                        "device type (got [%s] but should have got [%s])\n",
1495                                        myshare, devtype, cli->dev, return_devtype);
1496                                 ret = False;
1497                         }
1498                 } else {
1499                         printf("tconX to share %s with type %s "
1500                                "should have succeeded but failed\n",
1501                                myshare, devtype);
1502                         ret = False;
1503                 }
1504                 cli_tdis(cli);
1505         } else {
1506                 if (NT_STATUS_IS_OK(status)) {
1507                         printf("tconx to share %s with type %s "
1508                                "should have failed but succeeded\n",
1509                                myshare, devtype);
1510                         ret = False;
1511                 } else {
1512                         if (NT_STATUS_EQUAL(status, expected_error)) {
1513                                 ret = True;
1514                         } else {
1515                                 printf("Returned unexpected error\n");
1516                                 ret = False;
1517                         }
1518                 }
1519         }
1520         return ret;
1521 }
1522
1523 /*
1524  checks for correct tconX support
1525  */
1526 static bool run_tcon_devtype_test(int dummy)
1527 {
1528         static struct cli_state *cli1 = NULL;
1529         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1530         NTSTATUS status;
1531         bool ret = True;
1532
1533         status = cli_full_connection_creds(&cli1,
1534                                            myname,
1535                                            host,
1536                                            NULL, /* dest_ss */
1537                                            port_to_use,
1538                                            NULL, /* service */
1539                                            NULL, /* service_type */
1540                                            torture_creds,
1541                                            flags,
1542                                            signing_state);
1543
1544         if (!NT_STATUS_IS_OK(status)) {
1545                 printf("could not open connection\n");
1546                 return False;
1547         }
1548
1549         if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1550                 ret = False;
1551
1552         if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1553                 ret = False;
1554
1555         if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1556                 ret = False;
1557
1558         if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1559                 ret = False;
1560
1561         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1562                 ret = False;
1563
1564         if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1565                 ret = False;
1566
1567         if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1568                 ret = False;
1569
1570         if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1571                 ret = False;
1572
1573         if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1574                 ret = False;
1575
1576         if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1577                 ret = False;
1578
1579         cli_shutdown(cli1);
1580
1581         if (ret)
1582                 printf("Passed tcondevtest\n");
1583
1584         return ret;
1585 }
1586
1587
1588 /*
1589   This test checks that 
1590
1591   1) the server supports multiple locking contexts on the one SMB
1592   connection, distinguished by PID.  
1593
1594   2) the server correctly fails overlapping locks made by the same PID (this
1595      goes against POSIX behaviour, which is why it is tricky to implement)
1596
1597   3) the server denies unlock requests by an incorrect client PID
1598 */
1599 static bool run_locktest2(int dummy)
1600 {
1601         static struct cli_state *cli;
1602         const char *fname = "\\lockt2.lck";
1603         uint16_t fnum1, fnum2, fnum3;
1604         bool correct = True;
1605         NTSTATUS status;
1606
1607         if (!torture_open_connection(&cli, 0)) {
1608                 return False;
1609         }
1610
1611         smbXcli_conn_set_sockopt(cli->conn, sockops);
1612
1613         printf("starting locktest2\n");
1614
1615         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1616
1617         cli_setpid(cli, 1);
1618
1619         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1620         if (!NT_STATUS_IS_OK(status)) {
1621                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1622                 return False;
1623         }
1624
1625         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1626         if (!NT_STATUS_IS_OK(status)) {
1627                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1628                 return False;
1629         }
1630
1631         cli_setpid(cli, 2);
1632
1633         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1634         if (!NT_STATUS_IS_OK(status)) {
1635                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1636                 return False;
1637         }
1638
1639         cli_setpid(cli, 1);
1640
1641         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1642         if (!NT_STATUS_IS_OK(status)) {
1643                 printf("lock1 failed (%s)\n", nt_errstr(status));
1644                 return false;
1645         }
1646
1647         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1648         if (NT_STATUS_IS_OK(status)) {
1649                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1650                 correct = false;
1651         } else {
1652                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1653                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1654                         return false;
1655                 }
1656         }
1657
1658         status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1659         if (NT_STATUS_IS_OK(status)) {
1660                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1661                 correct = false;
1662         } else {
1663                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1664                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1665                         return false;
1666                 }
1667         }
1668
1669         status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1670         if (NT_STATUS_IS_OK(status)) {
1671                 printf("READ lock2 succeeded! This is a locking bug\n");
1672                 correct = false;
1673         } else {
1674                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1675                                  NT_STATUS_FILE_LOCK_CONFLICT)) {
1676                         return false;
1677                 }
1678         }
1679
1680         status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1681         if (!NT_STATUS_IS_OK(status)) {
1682                 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1683         }
1684         cli_setpid(cli, 2);
1685         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1686                 printf("unlock at 100 succeeded! This is a locking bug\n");
1687                 correct = False;
1688         }
1689
1690         status = cli_unlock(cli, fnum1, 0, 4);
1691         if (NT_STATUS_IS_OK(status)) {
1692                 printf("unlock1 succeeded! This is a locking bug\n");
1693                 correct = false;
1694         } else {
1695                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1696                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1697                         return false;
1698                 }
1699         }
1700
1701         status = cli_unlock(cli, fnum1, 0, 8);
1702         if (NT_STATUS_IS_OK(status)) {
1703                 printf("unlock2 succeeded! This is a locking bug\n");
1704                 correct = false;
1705         } else {
1706                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1707                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1708                         return false;
1709                 }
1710         }
1711
1712         status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1713         if (NT_STATUS_IS_OK(status)) {
1714                 printf("lock3 succeeded! This is a locking bug\n");
1715                 correct = false;
1716         } else {
1717                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1718                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1719                         return false;
1720                 }
1721         }
1722
1723         cli_setpid(cli, 1);
1724
1725         status = cli_close(cli, fnum1);
1726         if (!NT_STATUS_IS_OK(status)) {
1727                 printf("close1 failed (%s)\n", nt_errstr(status));
1728                 return False;
1729         }
1730
1731         status = cli_close(cli, fnum2);
1732         if (!NT_STATUS_IS_OK(status)) {
1733                 printf("close2 failed (%s)\n", nt_errstr(status));
1734                 return False;
1735         }
1736
1737         status = cli_close(cli, fnum3);
1738         if (!NT_STATUS_IS_OK(status)) {
1739                 printf("close3 failed (%s)\n", nt_errstr(status));
1740                 return False;
1741         }
1742
1743         if (!torture_close_connection(cli)) {
1744                 correct = False;
1745         }
1746
1747         printf("locktest2 finished\n");
1748
1749         return correct;
1750 }
1751
1752
1753 /*
1754   This test checks that 
1755
1756   1) the server supports the full offset range in lock requests
1757 */
1758 static bool run_locktest3(int dummy)
1759 {
1760         static struct cli_state *cli1, *cli2;
1761         const char *fname = "\\lockt3.lck";
1762         uint16_t fnum1, fnum2;
1763         int i;
1764         uint32_t offset;
1765         bool correct = True;
1766         NTSTATUS status;
1767
1768 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1769
1770         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1771                 return False;
1772         }
1773         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1774         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1775
1776         printf("starting locktest3\n");
1777
1778         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1779
1780         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1781                          &fnum1);
1782         if (!NT_STATUS_IS_OK(status)) {
1783                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1784                 return False;
1785         }
1786
1787         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1788         if (!NT_STATUS_IS_OK(status)) {
1789                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1790                 return False;
1791         }
1792
1793         for (offset=i=0;i<torture_numops;i++) {
1794                 NEXT_OFFSET;
1795
1796                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1797                 if (!NT_STATUS_IS_OK(status)) {
1798                         printf("lock1 %d failed (%s)\n", 
1799                                i,
1800                                nt_errstr(status));
1801                         return False;
1802                 }
1803
1804                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1805                 if (!NT_STATUS_IS_OK(status)) {
1806                         printf("lock2 %d failed (%s)\n", 
1807                                i,
1808                                nt_errstr(status));
1809                         return False;
1810                 }
1811         }
1812
1813         for (offset=i=0;i<torture_numops;i++) {
1814                 NEXT_OFFSET;
1815
1816                 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1817                 if (NT_STATUS_IS_OK(status)) {
1818                         printf("error: lock1 %d succeeded!\n", i);
1819                         return False;
1820                 }
1821
1822                 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1823                 if (NT_STATUS_IS_OK(status)) {
1824                         printf("error: lock2 %d succeeded!\n", i);
1825                         return False;
1826                 }
1827
1828                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1829                 if (NT_STATUS_IS_OK(status)) {
1830                         printf("error: lock3 %d succeeded!\n", i);
1831                         return False;
1832                 }
1833
1834                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1835                 if (NT_STATUS_IS_OK(status)) {
1836                         printf("error: lock4 %d succeeded!\n", i);
1837                         return False;
1838                 }
1839         }
1840
1841         for (offset=i=0;i<torture_numops;i++) {
1842                 NEXT_OFFSET;
1843
1844                 status = cli_unlock(cli1, fnum1, offset-1, 1);
1845                 if (!NT_STATUS_IS_OK(status)) {
1846                         printf("unlock1 %d failed (%s)\n", 
1847                                i,
1848                                nt_errstr(status));
1849                         return False;
1850                 }
1851
1852                 status = cli_unlock(cli2, fnum2, offset-2, 1);
1853                 if (!NT_STATUS_IS_OK(status)) {
1854                         printf("unlock2 %d failed (%s)\n", 
1855                                i,
1856                                nt_errstr(status));
1857                         return False;
1858                 }
1859         }
1860
1861         status = cli_close(cli1, fnum1);
1862         if (!NT_STATUS_IS_OK(status)) {
1863                 printf("close1 failed (%s)\n", nt_errstr(status));
1864                 return False;
1865         }
1866
1867         status = cli_close(cli2, fnum2);
1868         if (!NT_STATUS_IS_OK(status)) {
1869                 printf("close2 failed (%s)\n", nt_errstr(status));
1870                 return False;
1871         }
1872
1873         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1874         if (!NT_STATUS_IS_OK(status)) {
1875                 printf("unlink failed (%s)\n", nt_errstr(status));
1876                 return False;
1877         }
1878
1879         if (!torture_close_connection(cli1)) {
1880                 correct = False;
1881         }
1882
1883         if (!torture_close_connection(cli2)) {
1884                 correct = False;
1885         }
1886
1887         printf("finished locktest3\n");
1888
1889         return correct;
1890 }
1891
1892 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1893                            char *buf, off_t offset, size_t size,
1894                            size_t *nread, size_t expect)
1895 {
1896         NTSTATUS status;
1897         size_t l_nread;
1898
1899         status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1900
1901         if(!NT_STATUS_IS_OK(status)) {
1902                 return false;
1903         } else if (l_nread != expect) {
1904                 return false;
1905         }
1906
1907         if (nread) {
1908                 *nread = l_nread;
1909         }
1910
1911         return true;
1912 }
1913
1914 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1915         printf("** "); correct = False; \
1916         }
1917
1918 /*
1919   looks at overlapping locks
1920 */
1921 static bool run_locktest4(int dummy)
1922 {
1923         static struct cli_state *cli1, *cli2;
1924         const char *fname = "\\lockt4.lck";
1925         uint16_t fnum1, fnum2, f;
1926         bool ret;
1927         char buf[1000];
1928         bool correct = True;
1929         NTSTATUS status;
1930
1931         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1932                 return False;
1933         }
1934
1935         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1936         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1937
1938         printf("starting locktest4\n");
1939
1940         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1941
1942         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1943         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1944
1945         memset(buf, 0, sizeof(buf));
1946
1947         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1948                               NULL);
1949         if (!NT_STATUS_IS_OK(status)) {
1950                 printf("Failed to create file: %s\n", nt_errstr(status));
1951                 correct = False;
1952                 goto fail;
1953         }
1954
1955         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1956               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1957         EXPECTED(ret, False);
1958         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1959
1960         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1961               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1962         EXPECTED(ret, True);
1963         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1964
1965         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1966               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1967         EXPECTED(ret, False);
1968         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1969
1970         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1971               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1972         EXPECTED(ret, True);
1973         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1974
1975         ret = (cli_setpid(cli1, 1),
1976               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1977               (cli_setpid(cli1, 2),
1978               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1979         EXPECTED(ret, False);
1980         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1981
1982         ret = (cli_setpid(cli1, 1),
1983               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1984               (cli_setpid(cli1, 2),
1985               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1986         EXPECTED(ret, True);
1987         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1988
1989         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1990               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1991         EXPECTED(ret, True);
1992         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1993
1994         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1995               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1996         EXPECTED(ret, False);
1997         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1998
1999         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2000               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2001         EXPECTED(ret, False);
2002         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2003
2004         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2005               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2006         EXPECTED(ret, True);
2007         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2008
2009         ret = (cli_setpid(cli1, 1),
2010              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2011              (cli_setpid(cli1, 2),
2012              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2013         EXPECTED(ret, False);
2014         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2015
2016         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2017               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2018               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2019         EXPECTED(ret, False);
2020         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2021
2022
2023         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2024               test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2025         EXPECTED(ret, False);
2026         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2027
2028         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2029         ret = NT_STATUS_IS_OK(status);
2030         if (ret) {
2031                 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2032                                       NULL);
2033                 ret = NT_STATUS_IS_OK(status);
2034         }
2035         EXPECTED(ret, False);
2036         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2037
2038
2039         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2040               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2041               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2042               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2043         EXPECTED(ret, True);
2044         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2045
2046
2047         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2048               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2049               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2050               test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2051               !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2052                                              150, 4, NULL))) &&
2053               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2054         EXPECTED(ret, True);
2055         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2056
2057         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2058               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2059               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2060                                            160, 4, NULL)) &&
2061               test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2062         EXPECTED(ret, True);
2063         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2064
2065         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2066               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2067               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2068                                            170, 4, NULL)) &&
2069               test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2070         EXPECTED(ret, True);
2071         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2072
2073         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2074               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2075               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2076               !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2077                                             190, 4, NULL)) &&
2078               test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2079         EXPECTED(ret, True);
2080         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2081
2082         cli_close(cli1, fnum1);
2083         cli_close(cli2, fnum2);
2084         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2085         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2086         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2087               NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2088               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2089               NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2090               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2091         cli_close(cli1, f);
2092         cli_close(cli1, fnum1);
2093         EXPECTED(ret, True);
2094         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2095
2096  fail:
2097         cli_close(cli1, fnum1);
2098         cli_close(cli2, fnum2);
2099         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2100         torture_close_connection(cli1);
2101         torture_close_connection(cli2);
2102
2103         printf("finished locktest4\n");
2104         return correct;
2105 }
2106
2107 /*
2108   looks at lock upgrade/downgrade.
2109 */
2110 static bool run_locktest5(int dummy)
2111 {
2112         static struct cli_state *cli1, *cli2;
2113         const char *fname = "\\lockt5.lck";
2114         uint16_t fnum1, fnum2, fnum3;
2115         bool ret;
2116         char buf[1000];
2117         bool correct = True;
2118         NTSTATUS status;
2119
2120         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2121                 return False;
2122         }
2123
2124         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2125         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2126
2127         printf("starting locktest5\n");
2128
2129         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2130
2131         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2132         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2133         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2134
2135         memset(buf, 0, sizeof(buf));
2136
2137         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2138                               NULL);
2139         if (!NT_STATUS_IS_OK(status)) {
2140                 printf("Failed to create file: %s\n", nt_errstr(status));
2141                 correct = False;
2142                 goto fail;
2143         }
2144
2145         /* Check for NT bug... */
2146         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2147               NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2148         cli_close(cli1, fnum1);
2149         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2150         status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2151         ret = NT_STATUS_IS_OK(status);
2152         EXPECTED(ret, True);
2153         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2154         cli_close(cli1, fnum1);
2155         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2156         cli_unlock(cli1, fnum3, 0, 1);
2157
2158         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2159               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2160         EXPECTED(ret, True);
2161         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2162
2163         status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2164         ret = NT_STATUS_IS_OK(status);
2165         EXPECTED(ret, False);
2166
2167         printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2168
2169         /* Unlock the process 2 lock. */
2170         cli_unlock(cli2, fnum2, 0, 4);
2171
2172         status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2173         ret = NT_STATUS_IS_OK(status);
2174         EXPECTED(ret, False);
2175
2176         printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2177
2178         /* Unlock the process 1 fnum3 lock. */
2179         cli_unlock(cli1, fnum3, 0, 4);
2180
2181         /* Stack 2 more locks here. */
2182         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2183               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2184
2185         EXPECTED(ret, True);
2186         printf("the same process %s stack read locks\n", ret?"can":"cannot");
2187
2188         /* Unlock the first process lock, then check this was the WRITE lock that was
2189                 removed. */
2190
2191         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2192               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2193
2194         EXPECTED(ret, True);
2195         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2196
2197         /* Unlock the process 2 lock. */
2198         cli_unlock(cli2, fnum2, 0, 4);
2199
2200         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2201
2202         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2203                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2204                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2205
2206         EXPECTED(ret, True);
2207         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
2208
2209         /* Ensure the next unlock fails. */
2210         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2211         EXPECTED(ret, False);
2212         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
2213
2214         /* Ensure connection 2 can get a write lock. */
2215         status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2216         ret = NT_STATUS_IS_OK(status);
2217         EXPECTED(ret, True);
2218
2219         printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2220
2221
2222  fail:
2223         cli_close(cli1, fnum1);
2224         cli_close(cli2, fnum2);
2225         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2226         if (!torture_close_connection(cli1)) {
2227                 correct = False;
2228         }
2229         if (!torture_close_connection(cli2)) {
2230                 correct = False;
2231         }
2232
2233         printf("finished locktest5\n");
2234
2235         return correct;
2236 }
2237
2238 /*
2239   tries the unusual lockingX locktype bits
2240 */
2241 static bool run_locktest6(int dummy)
2242 {
2243         static struct cli_state *cli;
2244         const char *fname[1] = { "\\lock6.txt" };
2245         int i;
2246         uint16_t fnum;
2247         NTSTATUS status;
2248
2249         if (!torture_open_connection(&cli, 0)) {
2250                 return False;
2251         }
2252
2253         smbXcli_conn_set_sockopt(cli->conn, sockops);
2254
2255         printf("starting locktest6\n");
2256
2257         for (i=0;i<1;i++) {
2258                 printf("Testing %s\n", fname[i]);
2259
2260                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2261
2262                 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2263                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2264                 cli_close(cli, fnum);
2265                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2266
2267                 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2268                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2269                 cli_close(cli, fnum);
2270                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2271
2272                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2273         }
2274
2275         torture_close_connection(cli);
2276
2277         printf("finished locktest6\n");
2278         return True;
2279 }
2280
2281 static bool run_locktest7(int dummy)
2282 {
2283         struct cli_state *cli1;
2284         const char *fname = "\\lockt7.lck";
2285         uint16_t fnum1;
2286         char buf[200];
2287         bool correct = False;
2288         size_t nread;
2289         NTSTATUS status;
2290
2291         if (!torture_open_connection(&cli1, 0)) {
2292                 return False;
2293         }
2294
2295         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2296
2297         printf("starting locktest7\n");
2298
2299         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2300
2301         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2302
2303         memset(buf, 0, sizeof(buf));
2304
2305         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2306                               NULL);
2307         if (!NT_STATUS_IS_OK(status)) {
2308                 printf("Failed to create file: %s\n", nt_errstr(status));
2309                 goto fail;
2310         }
2311
2312         cli_setpid(cli1, 1);
2313
2314         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2315         if (!NT_STATUS_IS_OK(status)) {
2316                 printf("Unable to apply read lock on range 130:4, "
2317                        "error was %s\n", nt_errstr(status));
2318                 goto fail;
2319         } else {
2320                 printf("pid1 successfully locked range 130:4 for READ\n");
2321         }
2322
2323         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2324         if (!NT_STATUS_IS_OK(status)) {
2325                 printf("pid1 unable to read the range 130:4, error was %s\n",
2326                       nt_errstr(status));
2327                 goto fail;
2328         } else if (nread != 4) {
2329                 printf("pid1 unable to read the range 130:4, "
2330                        "recv %ld req %d\n", (unsigned long)nread, 4);
2331                 goto fail;
2332         } else {
2333                 printf("pid1 successfully read the range 130:4\n");
2334         }
2335
2336         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2337         if (!NT_STATUS_IS_OK(status)) {
2338                 printf("pid1 unable to write to the range 130:4, error was "
2339                        "%s\n", nt_errstr(status));
2340                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2341                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2342                         goto fail;
2343                 }
2344         } else {
2345                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2346                 goto fail;
2347         }
2348
2349         cli_setpid(cli1, 2);
2350
2351         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2352         if (!NT_STATUS_IS_OK(status)) {
2353                 printf("pid2 unable to read the range 130:4, error was %s\n",
2354                       nt_errstr(status));
2355                 goto fail;
2356         } else if (nread != 4) {
2357                 printf("pid2 unable to read the range 130:4, "
2358                        "recv %ld req %d\n", (unsigned long)nread, 4);
2359                 goto fail;
2360         } else {
2361                 printf("pid2 successfully read the range 130:4\n");
2362         }
2363
2364         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2365         if (!NT_STATUS_IS_OK(status)) {
2366                 printf("pid2 unable to write to the range 130:4, error was "
2367                        "%s\n", nt_errstr(status));
2368                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2369                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2370                         goto fail;
2371                 }
2372         } else {
2373                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2374                 goto fail;
2375         }
2376
2377         cli_setpid(cli1, 1);
2378         cli_unlock(cli1, fnum1, 130, 4);
2379
2380         status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2381         if (!NT_STATUS_IS_OK(status)) {
2382                 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2383                 goto fail;
2384         } else {
2385                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2386         }
2387
2388         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2389         if (!NT_STATUS_IS_OK(status)) {
2390                 printf("pid1 unable to read the range 130:4, error was %s\n",
2391                       nt_errstr(status));
2392                 goto fail;
2393         } else if (nread != 4) {
2394                 printf("pid1 unable to read the range 130:4, "
2395                        "recv %ld req %d\n", (unsigned long)nread, 4);
2396                 goto fail;
2397         } else {
2398                 printf("pid1 successfully read the range 130:4\n");
2399         }
2400
2401         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2402         if (!NT_STATUS_IS_OK(status)) {
2403                 printf("pid1 unable to write to the range 130:4, error was "
2404                        "%s\n", nt_errstr(status));
2405                 goto fail;
2406         } else {
2407                 printf("pid1 successfully wrote to the range 130:4\n");
2408         }
2409
2410         cli_setpid(cli1, 2);
2411
2412         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2413         if (!NT_STATUS_IS_OK(status)) {
2414                 printf("pid2 unable to read the range 130:4, error was "
2415                        "%s\n", nt_errstr(status));
2416                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2417                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2418                         goto fail;
2419                 }
2420         } else {
2421                 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2422                        (unsigned long)nread);
2423                 goto fail;
2424         }
2425
2426         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2427         if (!NT_STATUS_IS_OK(status)) {
2428                 printf("pid2 unable to write to the range 130:4, error was "
2429                        "%s\n", nt_errstr(status));
2430                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2431                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2432                         goto fail;
2433                 }
2434         } else {
2435                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2436                 goto fail;
2437         }
2438
2439         cli_unlock(cli1, fnum1, 130, 0);
2440         correct = True;
2441
2442 fail:
2443         cli_close(cli1, fnum1);
2444         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2445         torture_close_connection(cli1);
2446
2447         printf("finished locktest7\n");
2448         return correct;
2449 }
2450
2451 /*
2452  * This demonstrates a problem with our use of GPFS share modes: A file
2453  * descriptor sitting in the pending close queue holding a GPFS share mode
2454  * blocks opening a file another time. Happens with Word 2007 temp files.
2455  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2456  * open is denied with NT_STATUS_SHARING_VIOLATION.
2457  */
2458
2459 static bool run_locktest8(int dummy)
2460 {
2461         struct cli_state *cli1;
2462         const char *fname = "\\lockt8.lck";
2463         uint16_t fnum1, fnum2;
2464         char buf[200];
2465         bool correct = False;
2466         NTSTATUS status;
2467
2468         if (!torture_open_connection(&cli1, 0)) {
2469                 return False;
2470         }
2471
2472         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2473
2474         printf("starting locktest8\n");
2475
2476         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2477
2478         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2479                           &fnum1);
2480         if (!NT_STATUS_IS_OK(status)) {
2481                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2482                 return false;
2483         }
2484
2485         memset(buf, 0, sizeof(buf));
2486
2487         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2488         if (!NT_STATUS_IS_OK(status)) {
2489                 d_fprintf(stderr, "cli_openx second time returned %s\n",
2490                           nt_errstr(status));
2491                 goto fail;
2492         }
2493
2494         status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2495         if (!NT_STATUS_IS_OK(status)) {
2496                 printf("Unable to apply read lock on range 1:1, error was "
2497                        "%s\n", nt_errstr(status));
2498                 goto fail;
2499         }
2500
2501         status = cli_close(cli1, fnum1);
2502         if (!NT_STATUS_IS_OK(status)) {
2503                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2504                 goto fail;
2505         }
2506
2507         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2508         if (!NT_STATUS_IS_OK(status)) {
2509                 d_fprintf(stderr, "cli_openx third time returned %s\n",
2510                           nt_errstr(status));
2511                 goto fail;
2512         }
2513
2514         correct = true;
2515
2516 fail:
2517         cli_close(cli1, fnum1);
2518         cli_close(cli1, fnum2);
2519         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2520         torture_close_connection(cli1);
2521
2522         printf("finished locktest8\n");
2523         return correct;
2524 }
2525
2526 /*
2527  * This test is designed to be run in conjunction with
2528  * external NFS or POSIX locks taken in the filesystem.
2529  * It checks that the smbd server will block until the
2530  * lock is released and then acquire it. JRA.
2531  */
2532
2533 static bool got_alarm;
2534 static struct cli_state *alarm_cli;
2535
2536 static void alarm_handler(int dummy)
2537 {
2538         got_alarm = True;
2539 }
2540
2541 static void alarm_handler_parent(int dummy)
2542 {
2543         smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_OK);
2544 }
2545
2546 static void do_local_lock(int read_fd, int write_fd)
2547 {
2548         int fd;
2549         char c = '\0';
2550         struct flock lock;
2551         const char *local_pathname = NULL;
2552         int ret;
2553
2554         local_pathname = talloc_asprintf(talloc_tos(),
2555                         "%s/lockt9.lck", local_path);
2556         if (!local_pathname) {
2557                 printf("child: alloc fail\n");
2558                 exit(1);
2559         }
2560
2561         unlink(local_pathname);
2562         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2563         if (fd == -1) {
2564                 printf("child: open of %s failed %s.\n",
2565                         local_pathname, strerror(errno));
2566                 exit(1);
2567         }
2568
2569         /* Now take a fcntl lock. */
2570         lock.l_type = F_WRLCK;
2571         lock.l_whence = SEEK_SET;
2572         lock.l_start = 0;
2573         lock.l_len = 4;
2574         lock.l_pid = getpid();
2575
2576         ret = fcntl(fd,F_SETLK,&lock);
2577         if (ret == -1) {
2578                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2579                         local_pathname, strerror(errno));
2580                 exit(1);
2581         } else {
2582                 printf("child: got lock 0:4 on file %s.\n",
2583                         local_pathname );
2584                 fflush(stdout);
2585         }
2586
2587         CatchSignal(SIGALRM, alarm_handler);
2588         alarm(5);
2589         /* Signal the parent. */
2590         if (write(write_fd, &c, 1) != 1) {
2591                 printf("child: start signal fail %s.\n",
2592                         strerror(errno));
2593                 exit(1);
2594         }
2595         alarm(0);
2596
2597         alarm(10);
2598         /* Wait for the parent to be ready. */
2599         if (read(read_fd, &c, 1) != 1) {
2600                 printf("child: reply signal fail %s.\n",
2601                         strerror(errno));
2602                 exit(1);
2603         }
2604         alarm(0);
2605
2606         sleep(5);
2607         close(fd);
2608         printf("child: released lock 0:4 on file %s.\n",
2609                 local_pathname );
2610         fflush(stdout);
2611         exit(0);
2612 }
2613
2614 static bool run_locktest9(int dummy)
2615 {
2616         struct cli_state *cli1;
2617         const char *fname = "\\lockt9.lck";
2618         uint16_t fnum;
2619         bool correct = False;
2620         int pipe_in[2], pipe_out[2];
2621         pid_t child_pid;
2622         char c = '\0';
2623         int ret;
2624         struct timeval start;
2625         double seconds;
2626         NTSTATUS status;
2627
2628         printf("starting locktest9\n");
2629
2630         if (local_path == NULL) {
2631                 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2632                 return false;
2633         }
2634
2635         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2636                 return false;
2637         }
2638
2639         child_pid = fork();
2640         if (child_pid == -1) {
2641                 return false;
2642         }
2643
2644         if (child_pid == 0) {
2645                 /* Child. */
2646                 do_local_lock(pipe_out[0], pipe_in[1]);
2647                 exit(0);
2648         }
2649
2650         close(pipe_out[0]);
2651         close(pipe_in[1]);
2652         pipe_out[0] = -1;
2653         pipe_in[1] = -1;
2654
2655         /* Parent. */
2656         ret = read(pipe_in[0], &c, 1);
2657         if (ret != 1) {
2658                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2659                         strerror(errno));
2660                 return false;
2661         }
2662
2663         if (!torture_open_connection(&cli1, 0)) {
2664                 return false;
2665         }
2666
2667         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2668
2669         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE,
2670                           &fnum);
2671         if (!NT_STATUS_IS_OK(status)) {
2672                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2673                 return false;
2674         }
2675
2676         /* Ensure the child has the lock. */
2677         status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2678         if (NT_STATUS_IS_OK(status)) {
2679                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2680                 goto fail;
2681         } else {
2682                 d_printf("Child has the lock.\n");
2683         }
2684
2685         /* Tell the child to wait 5 seconds then exit. */
2686         ret = write(pipe_out[1], &c, 1);
2687         if (ret != 1) {
2688                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2689                         strerror(errno));
2690                 goto fail;
2691         }
2692
2693         /* Wait 20 seconds for the lock. */
2694         alarm_cli = cli1;
2695         CatchSignal(SIGALRM, alarm_handler_parent);
2696         alarm(20);
2697
2698         start = timeval_current();
2699
2700         status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2701         if (!NT_STATUS_IS_OK(status)) {
2702                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2703                        "%s\n", nt_errstr(status));
2704                 goto fail_nofd;
2705         }
2706         alarm(0);
2707
2708         seconds = timeval_elapsed(&start);
2709
2710         printf("Parent got the lock after %.2f seconds.\n",
2711                 seconds);
2712
2713         status = cli_close(cli1, fnum);
2714         if (!NT_STATUS_IS_OK(status)) {
2715                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2716                 goto fail;
2717         }
2718
2719         correct = true;
2720
2721 fail:
2722         cli_close(cli1, fnum);
2723         torture_close_connection(cli1);
2724
2725 fail_nofd:
2726
2727         printf("finished locktest9\n");
2728         return correct;
2729 }
2730
2731 struct locktest10_state {
2732         bool ok;
2733         bool done;
2734 };
2735
2736 static void locktest10_lockingx_done(struct tevent_req *subreq);
2737 static void locktest10_read_andx_done(struct tevent_req *subreq);
2738
2739 static bool run_locktest10(int dummy)
2740 {
2741         struct tevent_context *ev = NULL;
2742         struct cli_state *cli1 = NULL;
2743         struct cli_state *cli2 = NULL;
2744         struct smb1_lock_element lck = { 0 };
2745         struct tevent_req *reqs[2] = { NULL };
2746         struct tevent_req *smbreqs[2] = { NULL };
2747         const char fname[] = "\\lockt10.lck";
2748         uint16_t fnum1, fnum2;
2749         bool ret = false;
2750         bool ok;
2751         uint8_t data = 1;
2752         struct locktest10_state state = { .ok = true };
2753         NTSTATUS status;
2754
2755         printf("starting locktest10\n");
2756
2757         ev = samba_tevent_context_init(NULL);
2758         if (ev == NULL) {
2759                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2760                 goto done;
2761         }
2762
2763         ok = torture_open_connection(&cli1, 0);
2764         if (!ok) {
2765                 goto done;
2766         }
2767         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2768
2769         ok = torture_open_connection(&cli2, 1);
2770         if (!ok) {
2771                 goto done;
2772         }
2773         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2774
2775         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2776         if (!NT_STATUS_IS_OK(status)) {
2777                 d_fprintf(stderr,
2778                           "cli_openx failed: %s\n",
2779                           nt_errstr(status));
2780                 goto done;
2781         }
2782
2783         status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2784         if (!NT_STATUS_IS_OK(status)) {
2785                 d_fprintf(stderr,
2786                           "cli_writeall failed: %s\n",
2787                           nt_errstr(status));
2788                 goto done;
2789         }
2790
2791         status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2792         if (!NT_STATUS_IS_OK(status)) {
2793                 d_fprintf(stderr,
2794                           "cli_openx failed: %s\n",
2795                           nt_errstr(status));
2796                 goto done;
2797         }
2798
2799         status = cli_locktype(
2800                 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2801         if (!NT_STATUS_IS_OK(status)) {
2802                 d_fprintf(stderr,
2803                           "cli_locktype failed: %s\n",
2804                           nt_errstr(status));
2805                 goto done;
2806         }
2807
2808         lck = (struct smb1_lock_element) {
2809                 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2810         };
2811
2812         reqs[0] = cli_lockingx_create(
2813                 ev,                             /* mem_ctx */
2814                 ev,                             /* tevent_context */
2815                 cli1,                           /* cli */
2816                 fnum1,                          /* fnum */
2817                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
2818                 0,                              /* newoplocklevel */
2819                 1,                              /* timeout */
2820                 0,                              /* num_unlocks */
2821                 NULL,                           /* unlocks */
2822                 1,                              /* num_locks */
2823                 &lck,                           /* locks */
2824                 &smbreqs[0]);                   /* psmbreq */
2825         if (reqs[0] == NULL) {
2826                 d_fprintf(stderr, "cli_lockingx_create failed\n");
2827                 goto done;
2828         }
2829         tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
2830
2831         reqs[1] = cli_read_andx_create(
2832                 ev,             /* mem_ctx */
2833                 ev,             /* ev */
2834                 cli1,           /* cli */
2835                 fnum1,          /* fnum */
2836                 0,              /* offset */
2837                 1,              /* size */
2838                 &smbreqs[1]);   /* psmbreq */
2839         if (reqs[1] == NULL) {
2840                 d_fprintf(stderr, "cli_read_andx_create failed\n");
2841                 goto done;
2842         }
2843         tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
2844
2845         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
2846         if (!NT_STATUS_IS_OK(status)) {
2847                 d_fprintf(stderr,
2848                           "smb1cli_req_chain_submit failed: %s\n",
2849                           nt_errstr(status));
2850                 goto done;
2851         }
2852
2853         while (!state.done) {
2854                 tevent_loop_once(ev);
2855         }
2856
2857         torture_close_connection(cli1);
2858
2859         if (state.ok) {
2860                 ret = true;
2861         }
2862 done:
2863         return ret;
2864 }
2865
2866 static void locktest10_lockingx_done(struct tevent_req *subreq)
2867 {
2868         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
2869         NTSTATUS status;
2870
2871         status = cli_lockingx_recv(subreq);
2872         TALLOC_FREE(subreq);
2873
2874         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2875                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
2876                 state->ok = false;
2877         }
2878 }
2879
2880 static void locktest10_read_andx_done(struct tevent_req *subreq)
2881 {
2882         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
2883         ssize_t received = -1;
2884         uint8_t *rcvbuf = NULL;
2885         NTSTATUS status;
2886
2887         status = cli_read_andx_recv(subreq, &received, &rcvbuf);
2888
2889         if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
2890                 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
2891                 state->ok = false;
2892         }
2893
2894         state->done = true;
2895         TALLOC_FREE(subreq);
2896 }
2897
2898 static bool run_locktest11(int dummy)
2899 {
2900         struct cli_state *cli1;
2901         const char *fname = "\\lockt11.lck";
2902         NTSTATUS status;
2903         uint16_t fnum;
2904         bool ret = false;
2905
2906         if (!torture_open_connection(&cli1, 0)) {
2907                 return false;
2908         }
2909
2910         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2911
2912         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2913
2914         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
2915         if (!NT_STATUS_IS_OK(status)) {
2916                 d_fprintf(stderr,
2917                           "cli_openx returned %s\n",
2918                           nt_errstr(status));
2919                 return false;
2920         }
2921
2922         /*
2923          * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
2924          * returns NT_STATUS_OK
2925          */
2926
2927         status = cli_lockingx(
2928                 cli1,                           /* cli */
2929                 fnum,                           /* fnum */
2930                 LOCKING_ANDX_CANCEL_LOCK,       /* typeoflock */
2931                 0,                              /* newoplocklevel */
2932                 0,                              /* timeout */
2933                 0,                              /* num_unlocks */
2934                 NULL,                           /* unlocks */
2935                 0,                              /* num_locks */
2936                 NULL);                          /* locks */
2937
2938         if (!NT_STATUS_IS_OK(status)) {
2939                 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
2940                 goto fail;
2941         }
2942
2943         ret = true;
2944 fail:
2945         cli_close(cli1, fnum);
2946         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2947
2948         return ret;
2949 }
2950
2951 struct deferred_close_state {
2952         struct tevent_context *ev;
2953         struct cli_state *cli;
2954         uint16_t fnum;
2955 };
2956
2957 static void deferred_close_waited(struct tevent_req *subreq);
2958 static void deferred_close_done(struct tevent_req *subreq);
2959
2960 static struct tevent_req *deferred_close_send(
2961         TALLOC_CTX *mem_ctx,
2962         struct tevent_context *ev,
2963         int wait_secs,
2964         struct cli_state *cli,
2965         uint16_t fnum)
2966 {
2967         struct tevent_req *req = NULL, *subreq = NULL;
2968         struct deferred_close_state *state = NULL;
2969         struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
2970
2971         req = tevent_req_create(
2972                 mem_ctx, &state, struct deferred_close_state);
2973         if (req == NULL) {
2974                 return NULL;
2975         }
2976         state->ev = ev;
2977         state->cli = cli;
2978         state->fnum = fnum;
2979
2980         subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
2981         if (tevent_req_nomem(subreq, req)) {
2982                 return tevent_req_post(req, ev);
2983         }
2984         tevent_req_set_callback(subreq, deferred_close_waited, req);
2985         return req;
2986 }
2987
2988 static void deferred_close_waited(struct tevent_req *subreq)
2989 {
2990         struct tevent_req *req = tevent_req_callback_data(
2991                 subreq, struct tevent_req);
2992         struct deferred_close_state *state = tevent_req_data(
2993                 req, struct deferred_close_state);
2994         bool ok;
2995
2996         ok = tevent_wakeup_recv(subreq);
2997         TALLOC_FREE(subreq);
2998         if (!ok) {
2999                 tevent_req_oom(req);
3000                 return;
3001         }
3002
3003         subreq = cli_close_send(state, state->ev, state->cli, state->fnum);
3004         if (tevent_req_nomem(subreq, req)) {
3005                 return;
3006         }
3007         tevent_req_set_callback(subreq, deferred_close_done, req);
3008 }
3009
3010 static void deferred_close_done(struct tevent_req *subreq)
3011 {
3012         NTSTATUS status = cli_close_recv(subreq);
3013         tevent_req_simple_finish_ntstatus(subreq, status);
3014 }
3015
3016 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3017 {
3018         return tevent_req_simple_recv_ntstatus(req);
3019 }
3020
3021 struct lockread_state {
3022         struct smb1_lock_element lck;
3023         struct tevent_req *reqs[2];
3024         struct tevent_req *smbreqs[2];
3025         NTSTATUS lock_status;
3026         NTSTATUS read_status;
3027         uint8_t *readbuf;
3028 };
3029
3030 static void lockread_lockingx_done(struct tevent_req *subreq);
3031 static void lockread_read_andx_done(struct tevent_req *subreq);
3032
3033 static struct tevent_req *lockread_send(
3034         TALLOC_CTX *mem_ctx,
3035         struct tevent_context *ev,
3036         struct cli_state *cli,
3037         uint16_t fnum)
3038 {
3039         struct tevent_req *req = NULL;
3040         struct lockread_state *state = NULL;
3041         NTSTATUS status;
3042
3043         req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3044         if (req == NULL) {
3045                 return NULL;
3046         }
3047
3048         state->lck = (struct smb1_lock_element) {
3049                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3050         };
3051
3052         state->reqs[0] = cli_lockingx_create(
3053                 ev,                             /* mem_ctx */
3054                 ev,                             /* tevent_context */
3055                 cli,                            /* cli */
3056                 fnum,                           /* fnum */
3057                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3058                 0,                              /* newoplocklevel */
3059                 10000,                          /* timeout */
3060                 0,                              /* num_unlocks */
3061                 NULL,                           /* unlocks */
3062                 1,                              /* num_locks */
3063                 &state->lck,                    /* locks */
3064                 &state->smbreqs[0]);            /* psmbreq */
3065         if (tevent_req_nomem(state->reqs[0], req)) {
3066                 return tevent_req_post(req, ev);
3067         }
3068         tevent_req_set_callback(
3069                 state->reqs[0], lockread_lockingx_done, req);
3070
3071         state->reqs[1] = cli_read_andx_create(
3072                 ev,             /* mem_ctx */
3073                 ev,             /* ev */
3074                 cli,            /* cli */
3075                 fnum,           /* fnum */
3076                 0,              /* offset */
3077                 1,              /* size */
3078                 &state->smbreqs[1]);    /* psmbreq */
3079         if (tevent_req_nomem(state->reqs[1], req)) {
3080                 return tevent_req_post(req, ev);
3081         }
3082         tevent_req_set_callback(
3083                 state->reqs[1], lockread_read_andx_done, req);
3084
3085         status = smb1cli_req_chain_submit(state->smbreqs, 2);
3086         if (tevent_req_nterror(req, status)) {
3087                 return tevent_req_post(req, ev);
3088         }
3089         return req;
3090 }
3091
3092 static void lockread_lockingx_done(struct tevent_req *subreq)
3093 {
3094         struct tevent_req *req = tevent_req_callback_data(
3095                 subreq, struct tevent_req);
3096         struct lockread_state *state = tevent_req_data(
3097                 req, struct lockread_state);
3098         state->lock_status = cli_lockingx_recv(subreq);
3099         TALLOC_FREE(subreq);
3100         d_fprintf(stderr,
3101                   "lockingx returned %s\n",
3102                   nt_errstr(state->lock_status));
3103 }
3104
3105 static void lockread_read_andx_done(struct tevent_req *subreq)
3106 {
3107         struct tevent_req *req = tevent_req_callback_data(
3108                 subreq, struct tevent_req);
3109         struct lockread_state *state = tevent_req_data(
3110                 req, struct lockread_state);
3111         ssize_t received = -1;
3112         uint8_t *rcvbuf = NULL;
3113
3114         state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3115
3116         d_fprintf(stderr,
3117                   "read returned %s\n",
3118                   nt_errstr(state->read_status));
3119
3120         if (!NT_STATUS_IS_OK(state->read_status)) {
3121                 TALLOC_FREE(subreq);
3122                 tevent_req_done(req);
3123                 return;
3124         }
3125
3126         if (received > 0) {
3127                 state->readbuf = talloc_memdup(state, rcvbuf, received);
3128                 TALLOC_FREE(subreq);
3129                 if (tevent_req_nomem(state->readbuf, req)) {
3130                         return;
3131                 }
3132         }
3133         TALLOC_FREE(subreq);
3134         tevent_req_done(req);
3135 }
3136
3137 static NTSTATUS lockread_recv(
3138         struct tevent_req *req,
3139         NTSTATUS *lock_status,
3140         NTSTATUS *read_status,
3141         TALLOC_CTX *mem_ctx,
3142         uint8_t **read_buf)
3143 {
3144         struct lockread_state *state = tevent_req_data(
3145                 req, struct lockread_state);
3146         NTSTATUS status;
3147
3148         if (tevent_req_is_nterror(req, &status)) {
3149                 return status;
3150         }
3151
3152         *lock_status = state->lock_status;
3153         *read_status = state->read_status;
3154         if (state->readbuf != NULL) {
3155                 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3156         } else {
3157                 *read_buf = NULL;
3158         }
3159
3160         return NT_STATUS_OK;
3161 }
3162
3163 struct lock12_state {
3164         uint8_t dummy;
3165 };
3166
3167 static void lock12_closed(struct tevent_req *subreq);
3168 static void lock12_read(struct tevent_req *subreq);
3169
3170 static struct tevent_req *lock12_send(
3171         TALLOC_CTX *mem_ctx,
3172         struct tevent_context *ev,
3173         struct cli_state *cli,
3174         uint16_t fnum1,
3175         uint16_t fnum2)
3176 {
3177         struct tevent_req *req = NULL, *subreq = NULL;
3178         struct lock12_state *state = NULL;
3179
3180         req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3181         if (req == NULL) {
3182                 return NULL;
3183         }
3184
3185         subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3186         if (tevent_req_nomem(subreq, req)) {
3187                 return tevent_req_post(req, ev);
3188         }
3189         tevent_req_set_callback(subreq, lock12_closed, req);
3190
3191         subreq = lockread_send(state, ev, cli, fnum2);
3192         if (tevent_req_nomem(subreq, req)) {
3193                 return tevent_req_post(req, ev);
3194         }
3195         tevent_req_set_callback(subreq, lock12_read, req);
3196
3197         return req;
3198 }
3199
3200 static void lock12_closed(struct tevent_req *subreq)
3201 {
3202         struct tevent_req *req = tevent_req_callback_data(
3203                 subreq, struct tevent_req);
3204         NTSTATUS status;
3205
3206         status = deferred_close_recv(subreq);
3207         TALLOC_FREE(subreq);
3208         DBG_DEBUG("close returned %s\n", nt_errstr(status));
3209         if (tevent_req_nterror(req, status)) {
3210                 return;
3211         }
3212 }
3213
3214 static void lock12_read(struct tevent_req *subreq)
3215 {
3216         struct tevent_req *req = tevent_req_callback_data(
3217                 subreq, struct tevent_req);
3218         struct lock12_state *state = tevent_req_data(
3219                 req, struct lock12_state);
3220         NTSTATUS status, lock_status, read_status;
3221         uint8_t *buf = NULL;
3222
3223         status = lockread_recv(
3224                 subreq, &lock_status, &read_status, state, &buf);
3225         TALLOC_FREE(subreq);
3226         if (tevent_req_nterror(req, status) ||
3227             tevent_req_nterror(req, lock_status) ||
3228             tevent_req_nterror(req, read_status)) {
3229                 return;
3230         }
3231         tevent_req_done(req);
3232 }
3233
3234 static NTSTATUS lock12_recv(struct tevent_req *req)
3235
3236 {
3237         NTSTATUS status;
3238
3239         if (tevent_req_is_nterror(req, &status)) {
3240                 return status;
3241         }
3242         return NT_STATUS_OK;
3243 }
3244
3245 static bool run_locktest12(int dummy)
3246 {
3247         struct tevent_context *ev = NULL;
3248         struct tevent_req *req = NULL;
3249         struct cli_state *cli = NULL;
3250         const char fname[] = "\\lockt12.lck";
3251         uint16_t fnum1, fnum2;
3252         bool ret = false;
3253         bool ok;
3254         uint8_t data = 1;
3255         NTSTATUS status;
3256
3257         printf("starting locktest12\n");
3258
3259         ev = samba_tevent_context_init(NULL);
3260         if (ev == NULL) {
3261                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3262                 goto done;
3263         }
3264
3265         ok = torture_open_connection(&cli, 0);
3266         if (!ok) {
3267                 goto done;
3268         }
3269         smbXcli_conn_set_sockopt(cli->conn, sockops);
3270
3271         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3272         if (!NT_STATUS_IS_OK(status)) {
3273                 d_fprintf(stderr,
3274                           "cli_openx failed: %s\n",
3275                           nt_errstr(status));
3276                 goto done;
3277         }
3278
3279         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3280         if (!NT_STATUS_IS_OK(status)) {
3281                 d_fprintf(stderr,
3282                           "cli_openx failed: %s\n",
3283                           nt_errstr(status));
3284                 goto done;
3285         }
3286
3287         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3288         if (!NT_STATUS_IS_OK(status)) {
3289                 d_fprintf(stderr,
3290                           "cli_writeall failed: %s\n",
3291                           nt_errstr(status));
3292                 goto done;
3293         }
3294
3295         status = cli_locktype(
3296                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3297         if (!NT_STATUS_IS_OK(status)) {
3298                 d_fprintf(stderr,
3299                           "cli_locktype failed: %s\n",
3300                           nt_errstr(status));
3301                 goto done;
3302         }
3303
3304         req = lock12_send(ev, ev, cli, fnum1, fnum2);
3305         if (req == NULL) {
3306                 d_fprintf(stderr, "lock12_send failed\n");
3307                 goto done;
3308         }
3309
3310         ok = tevent_req_poll_ntstatus(req, ev, &status);
3311         if (!ok) {
3312                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3313                 goto done;
3314         }
3315
3316         if (!NT_STATUS_IS_OK(status)) {
3317                 d_fprintf(stderr,
3318                           "tevent_req_poll_ntstatus returned %s\n",
3319                           nt_errstr(status));
3320                 goto done;
3321         }
3322
3323         status = lock12_recv(req);
3324         if (!NT_STATUS_IS_OK(status)) {
3325                 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3326                 goto done;
3327         }
3328
3329         ret = true;
3330 done:
3331         torture_close_connection(cli);
3332         return ret;
3333 }
3334
3335 struct lock_ntcancel_state {
3336         struct timeval start;
3337         struct smb1_lock_element lck;
3338         struct tevent_req *subreq;
3339 };
3340
3341 static void lock_ntcancel_waited(struct tevent_req *subreq);
3342 static void lock_ntcancel_done(struct tevent_req *subreq);
3343
3344 static struct tevent_req *lock_ntcancel_send(
3345         TALLOC_CTX *mem_ctx,
3346         struct tevent_context *ev,
3347         struct cli_state *cli,
3348         uint16_t fnum)
3349 {
3350         struct tevent_req *req = NULL, *subreq = NULL;
3351         struct lock_ntcancel_state *state = NULL;
3352
3353         req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3354         if (req == NULL) {
3355                 return NULL;
3356         }
3357         state->lck = (struct smb1_lock_element) {
3358                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3359         };
3360         state->start = timeval_current();
3361
3362         state->subreq = cli_lockingx_send(
3363                 state,                          /* mem_ctx */
3364                 ev,                             /* tevent_context */
3365                 cli,                            /* cli */
3366                 fnum,                           /* fnum */
3367                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3368                 0,                              /* newoplocklevel */
3369                 10000,                          /* timeout */
3370                 0,                              /* num_unlocks */
3371                 NULL,                           /* unlocks */
3372                 1,                              /* num_locks */
3373                 &state->lck);                   /* locks */
3374         if (tevent_req_nomem(state->subreq, req)) {
3375                 return tevent_req_post(req, ev);
3376         }
3377         tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3378
3379         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3380         if (tevent_req_nomem(subreq, req)) {
3381                 return tevent_req_post(req, ev);
3382         }
3383         tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3384         return req;
3385 }
3386
3387 static void lock_ntcancel_waited(struct tevent_req *subreq)
3388 {
3389         struct tevent_req *req = tevent_req_callback_data(
3390                 subreq, struct tevent_req);
3391         struct lock_ntcancel_state *state = tevent_req_data(
3392                 req, struct lock_ntcancel_state);
3393         bool ok;
3394
3395         ok = tevent_wakeup_recv(subreq);
3396         TALLOC_FREE(subreq);
3397         if (!ok) {
3398                 tevent_req_oom(req);
3399                 return;
3400         }
3401
3402         ok = tevent_req_cancel(state->subreq);
3403         if (!ok) {
3404                 d_fprintf(stderr, "Could not cancel subreq\n");
3405                 tevent_req_oom(req);
3406                 return;
3407         }
3408 }
3409
3410 static void lock_ntcancel_done(struct tevent_req *subreq)
3411 {
3412         struct tevent_req *req = tevent_req_callback_data(
3413                 subreq, struct tevent_req);
3414         struct lock_ntcancel_state *state = tevent_req_data(
3415                 req, struct lock_ntcancel_state);
3416         NTSTATUS status;
3417         double elapsed;
3418
3419         status = cli_lockingx_recv(subreq);
3420         TALLOC_FREE(subreq);
3421
3422         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3423                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3424                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3425                 return;
3426         }
3427
3428         elapsed = timeval_elapsed(&state->start);
3429
3430         if (elapsed > 3) {
3431                 d_printf("cli_lockingx was too slow, cancel did not work\n");
3432                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3433                 return;
3434         }
3435
3436         tevent_req_done(req);
3437 }
3438
3439 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3440 {
3441         return tevent_req_simple_recv_ntstatus(req);
3442 }
3443
3444 static bool run_locktest13(int dummy)
3445 {
3446         struct tevent_context *ev = NULL;
3447         struct tevent_req *req = NULL;
3448         struct cli_state *cli = NULL;
3449         const char fname[] = "\\lockt13.lck";
3450         uint16_t fnum1, fnum2;
3451         bool ret = false;
3452         bool ok;
3453         uint8_t data = 1;
3454         NTSTATUS status;
3455
3456         printf("starting locktest13\n");
3457
3458         ev = samba_tevent_context_init(NULL);
3459         if (ev == NULL) {
3460                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3461                 goto done;
3462         }
3463
3464         ok = torture_open_connection(&cli, 0);
3465         if (!ok) {
3466                 goto done;
3467         }
3468         smbXcli_conn_set_sockopt(cli->conn, sockops);
3469
3470         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3471         if (!NT_STATUS_IS_OK(status)) {
3472                 d_fprintf(stderr,
3473                           "cli_openx failed: %s\n",
3474                           nt_errstr(status));
3475                 goto done;
3476         }
3477
3478         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3479         if (!NT_STATUS_IS_OK(status)) {
3480                 d_fprintf(stderr,
3481                           "cli_openx failed: %s\n",
3482                           nt_errstr(status));
3483                 goto done;
3484         }
3485
3486         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3487         if (!NT_STATUS_IS_OK(status)) {
3488                 d_fprintf(stderr,
3489                           "cli_writeall failed: %s\n",
3490                           nt_errstr(status));
3491                 goto done;
3492         }
3493
3494         status = cli_locktype(
3495                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3496         if (!NT_STATUS_IS_OK(status)) {
3497                 d_fprintf(stderr,
3498                           "cli_locktype failed: %s\n",
3499                           nt_errstr(status));
3500                 goto done;
3501         }
3502
3503         req = lock_ntcancel_send(ev, ev, cli, fnum2);
3504         if (req == NULL) {
3505                 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3506                 goto done;
3507         }
3508
3509         ok = tevent_req_poll_ntstatus(req, ev, &status);
3510         if (!ok) {
3511                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3512                 goto done;
3513         }
3514
3515         if (!NT_STATUS_IS_OK(status)) {
3516                 d_fprintf(stderr,
3517                           "tevent_req_poll_ntstatus returned %s\n",
3518                           nt_errstr(status));
3519                 goto done;
3520         }
3521
3522         status = lock_ntcancel_recv(req);
3523         if (!NT_STATUS_IS_OK(status)) {
3524                 d_fprintf(stderr,
3525                           "lock_ntcancel returned %s\n",
3526                           nt_errstr(status));
3527                 goto done;
3528         }
3529
3530         ret = true;
3531 done:
3532         torture_close_connection(cli);
3533         return ret;
3534 }
3535
3536 /*
3537 test whether fnums and tids open on one VC are available on another (a major
3538 security hole)
3539 */
3540 static bool run_fdpasstest(int dummy)
3541 {
3542         struct cli_state *cli1, *cli2;
3543         const char *fname = "\\fdpass.tst";
3544         uint16_t fnum1;
3545         char buf[1024];
3546         NTSTATUS status;
3547
3548         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3549                 return False;
3550         }
3551         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3552         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3553
3554         printf("starting fdpasstest\n");
3555
3556         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3557
3558         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3559                           &fnum1);
3560         if (!NT_STATUS_IS_OK(status)) {
3561                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3562                 return False;
3563         }
3564
3565         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3566                               13, NULL);
3567         if (!NT_STATUS_IS_OK(status)) {
3568                 printf("write failed (%s)\n", nt_errstr(status));
3569                 return False;
3570         }
3571
3572         cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3573         cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3574         cli_setpid(cli2, cli_getpid(cli1));
3575
3576         if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3577                 printf("read succeeded! nasty security hole [%s]\n", buf);
3578                 return false;
3579         }
3580
3581         cli_close(cli1, fnum1);
3582         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3583
3584         torture_close_connection(cli1);
3585         torture_close_connection(cli2);
3586
3587         printf("finished fdpasstest\n");
3588         return True;
3589 }
3590
3591 static bool run_fdsesstest(int dummy)
3592 {
3593         struct cli_state *cli;
3594         uint16_t new_vuid;
3595         uint16_t saved_vuid;
3596         uint32_t new_cnum;
3597         uint32_t saved_cnum;
3598         const char *fname = "\\fdsess.tst";
3599         const char *fname1 = "\\fdsess1.tst";
3600         uint16_t fnum1;
3601         uint16_t fnum2;
3602         char buf[1024];
3603         bool ret = True;
3604         NTSTATUS status;
3605
3606         if (!torture_open_connection(&cli, 0))
3607                 return False;
3608         smbXcli_conn_set_sockopt(cli->conn, sockops);
3609
3610         if (!torture_cli_session_setup2(cli, &new_vuid))
3611                 return False;
3612
3613         saved_cnum = cli_state_get_tid(cli);
3614         if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3615                 return False;
3616         new_cnum = cli_state_get_tid(cli);
3617         cli_state_set_tid(cli, saved_cnum);
3618
3619         printf("starting fdsesstest\n");
3620
3621         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3622         cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3623
3624         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3625         if (!NT_STATUS_IS_OK(status)) {
3626                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3627                 return False;
3628         }
3629
3630         status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3631                               NULL);
3632         if (!NT_STATUS_IS_OK(status)) {
3633                 printf("write failed (%s)\n", nt_errstr(status));
3634                 return False;
3635         }
3636
3637         saved_vuid = cli_state_get_uid(cli);
3638         cli_state_set_uid(cli, new_vuid);
3639
3640         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3641                 printf("read succeeded with different vuid! "
3642                        "nasty security hole [%s]\n", buf);
3643                 ret = false;
3644         }
3645         /* Try to open a file with different vuid, samba cnum. */
3646         if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3647                 printf("create with different vuid, same cnum succeeded.\n");
3648                 cli_close(cli, fnum2);
3649                 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3650         } else {
3651                 printf("create with different vuid, same cnum failed.\n");
3652                 printf("This will cause problems with service clients.\n");
3653                 ret = False;
3654         }
3655
3656         cli_state_set_uid(cli, saved_vuid);
3657
3658         /* Try with same vuid, different cnum. */
3659         cli_state_set_tid(cli, new_cnum);
3660
3661         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3662                 printf("read succeeded with different cnum![%s]\n", buf);
3663                 ret = false;
3664         }
3665
3666         cli_state_set_tid(cli, saved_cnum);
3667         cli_close(cli, fnum1);
3668         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3669
3670         torture_close_connection(cli);
3671
3672         printf("finished fdsesstest\n");
3673         return ret;
3674 }
3675
3676 /*
3677   This test checks that 
3678
3679   1) the server does not allow an unlink on a file that is open
3680 */
3681 static bool run_unlinktest(int dummy)
3682 {
3683         struct cli_state *cli;
3684         const char *fname = "\\unlink.tst";
3685         uint16_t fnum;
3686         bool correct = True;
3687         NTSTATUS status;
3688
3689         if (!torture_open_connection(&cli, 0)) {
3690                 return False;
3691         }
3692
3693         smbXcli_conn_set_sockopt(cli->conn, sockops);
3694
3695         printf("starting unlink test\n");
3696
3697         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3698
3699         cli_setpid(cli, 1);
3700
3701         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3702         if (!NT_STATUS_IS_OK(status)) {
3703                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3704                 return False;
3705         }
3706
3707         status = cli_unlink(cli, fname,
3708                             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3709         if (NT_STATUS_IS_OK(status)) {
3710                 printf("error: server allowed unlink on an open file\n");
3711                 correct = False;
3712         } else {
3713                 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3714                                       NT_STATUS_SHARING_VIOLATION);
3715         }
3716
3717         cli_close(cli, fnum);
3718         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3719
3720         if (!torture_close_connection(cli)) {
3721                 correct = False;
3722         }
3723
3724         printf("unlink test finished\n");
3725
3726         return correct;
3727 }
3728
3729
3730 /*
3731 test how many open files this server supports on the one socket
3732 */
3733 static bool run_maxfidtest(int dummy)
3734 {
3735         struct cli_state *cli;
3736         fstring fname;
3737         uint16_t fnums[0x11000];
3738         int i;
3739         int retries=4;
3740         bool correct = True;
3741         NTSTATUS status;
3742
3743         cli = current_cli;
3744
3745         if (retries <= 0) {
3746                 printf("failed to connect\n");
3747                 return False;
3748         }
3749
3750         smbXcli_conn_set_sockopt(cli->conn, sockops);
3751
3752         for (i=0; i<0x11000; i++) {
3753                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3754                 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3755                                   &fnums[i]);
3756                 if (!NT_STATUS_IS_OK(status)) {
3757                         printf("open of %s failed (%s)\n", 
3758                                fname, nt_errstr(status));
3759                         printf("maximum fnum is %d\n", i);
3760                         break;
3761                 }
3762                 printf("%6d\r", i);
3763         }
3764         printf("%6d\n", i);
3765         i--;
3766
3767         printf("cleaning up\n");
3768         for (;i>=0;i--) {
3769                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3770                 cli_close(cli, fnums[i]);
3771
3772                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3773                 if (!NT_STATUS_IS_OK(status)) {
3774                         printf("unlink of %s failed (%s)\n", 
3775                                fname, nt_errstr(status));
3776                         correct = False;
3777                 }
3778                 printf("%6d\r", i);
3779         }
3780         printf("%6d\n", 0);
3781
3782         printf("maxfid test finished\n");
3783         if (!torture_close_connection(cli)) {
3784                 correct = False;
3785         }
3786         return correct;
3787 }
3788
3789 /* generate a random buffer */
3790 static void rand_buf(char *buf, int len)
3791 {
3792         while (len--) {
3793                 *buf = (char)sys_random();
3794                 buf++;
3795         }
3796 }
3797
3798 /* send smb negprot commands, not reading the response */
3799 static bool run_negprot_nowait(int dummy)
3800 {
3801         struct tevent_context *ev;
3802         int i;
3803         struct cli_state *cli;
3804         bool correct = True;
3805
3806         printf("starting negprot nowait test\n");
3807
3808         ev = samba_tevent_context_init(talloc_tos());
3809         if (ev == NULL) {
3810                 return false;
3811         }
3812
3813         if (!(cli = open_nbt_connection())) {
3814                 TALLOC_FREE(ev);
3815                 return False;
3816         }
3817
3818         for (i=0;i<50000;i++) {
3819                 struct tevent_req *req;
3820
3821                 req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
3822                                            PROTOCOL_CORE, PROTOCOL_NT1, 0);
3823                 if (req == NULL) {
3824                         TALLOC_FREE(ev);
3825                         return false;
3826                 }
3827                 if (!tevent_req_poll(req, ev)) {
3828                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3829                                   strerror(errno));
3830                         TALLOC_FREE(ev);
3831                         return false;
3832                 }
3833                 TALLOC_FREE(req);
3834         }
3835
3836         if (torture_close_connection(cli)) {
3837                 correct = False;
3838         }
3839
3840         printf("finished negprot nowait test\n");
3841
3842         return correct;
3843 }
3844
3845 /* send smb negprot commands, not reading the response */
3846 static bool run_bad_nbt_session(int dummy)
3847 {
3848         struct nmb_name called, calling;
3849         struct sockaddr_storage ss;
3850         NTSTATUS status;
3851         int fd;
3852         bool ret;
3853
3854         printf("starting bad nbt session test\n");
3855
3856         make_nmb_name(&calling, myname, 0x0);
3857         make_nmb_name(&called , host, 0x20);
3858
3859         if (!resolve_name(host, &ss, 0x20, true)) {
3860                 d_fprintf(stderr, "Could not resolve name %s\n", host);
3861                 return false;
3862         }
3863
3864         status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3865         if (!NT_STATUS_IS_OK(status)) {
3866                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3867                           nt_errstr(status));
3868                 return false;
3869         }
3870
3871         ret = cli_bad_session_request(fd, &calling, &called);
3872         close(fd);
3873         if (!ret) {
3874                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3875                           nt_errstr(status));
3876                 return false;
3877         }
3878
3879         printf("finished bad nbt session test\n");
3880         return true;
3881 }
3882
3883 /* send random IPC commands */
3884 static bool run_randomipc(int dummy)
3885 {
3886         char *rparam = NULL;
3887         char *rdata = NULL;
3888         unsigned int rdrcnt,rprcnt;
3889         char param[1024];
3890         int api, param_len, i;
3891         struct cli_state *cli;
3892         bool correct = True;
3893         int count = 50000;
3894
3895         printf("starting random ipc test\n");
3896
3897         if (!torture_open_connection(&cli, 0)) {
3898                 return False;
3899         }
3900
3901         for (i=0;i<count;i++) {
3902                 api = sys_random() % 500;
3903                 param_len = (sys_random() % 64);
3904
3905                 rand_buf(param, param_len);
3906
3907                 SSVAL(param,0,api); 
3908
3909                 cli_api(cli, 
3910                         param, param_len, 8,  
3911                         NULL, 0, CLI_BUFFER_SIZE,
3912                         &rparam, &rprcnt,     
3913                         &rdata, &rdrcnt);
3914                 if (i % 100 == 0) {
3915                         printf("%d/%d\r", i,count);
3916                 }
3917         }
3918         printf("%d/%d\n", i, count);
3919
3920         if (!torture_close_connection(cli)) {
3921                 correct = False;
3922         }
3923
3924         SAFE_FREE(rparam);
3925         SAFE_FREE(rdata);
3926
3927         printf("finished random ipc test\n");
3928
3929         return correct;
3930 }
3931
3932
3933
3934 static void browse_callback(const char *sname, uint32_t stype,
3935                             const char *comment, void *state)
3936 {
3937         printf("\t%20.20s %08x %s\n", sname, stype, comment);
3938 }
3939
3940
3941
3942 /*
3943   This test checks the browse list code
3944
3945 */
3946 static bool run_browsetest(int dummy)
3947 {
3948         static struct cli_state *cli;
3949         bool correct = True;
3950
3951         printf("starting browse test\n");
3952
3953         if (!torture_open_connection(&cli, 0)) {
3954                 return False;
3955         }
3956
3957         printf("domain list:\n");
3958         cli_NetServerEnum(cli, cli->server_domain, 
3959                           SV_TYPE_DOMAIN_ENUM,
3960                           browse_callback, NULL);
3961
3962         printf("machine list:\n");
3963         cli_NetServerEnum(cli, cli->server_domain, 
3964                           SV_TYPE_ALL,
3965                           browse_callback, NULL);
3966
3967         if (!torture_close_connection(cli)) {
3968                 correct = False;
3969         }
3970
3971         printf("browse test finished\n");
3972
3973         return correct;
3974
3975 }
3976
3977 static bool check_attributes(struct cli_state *cli,
3978                                 const char *fname,
3979                                 uint16_t expected_attrs)
3980 {
3981         uint16_t attrs = 0;
3982         NTSTATUS status = cli_getatr(cli,
3983                                 fname,
3984                                 &attrs,
3985                                 NULL,
3986                                 NULL);
3987         if (!NT_STATUS_IS_OK(status)) {
3988                 printf("cli_getatr failed with %s\n",
3989                         nt_errstr(status));
3990                 return false;
3991         }
3992         if (attrs != expected_attrs) {
3993                 printf("Attributes incorrect 0x%x, should be 0x%x\n",
3994                         (unsigned int)attrs,
3995                         (unsigned int)expected_attrs);
3996                 return false;
3997         }
3998         return true;
3999 }
4000
4001 /*
4002   This checks how the getatr calls works
4003 */
4004 static bool run_attrtest(int dummy)
4005 {
4006         struct cli_state *cli;
4007         uint16_t fnum;
4008         time_t t, t2;
4009         const char *fname = "\\attrib123456789.tst";
4010         bool correct = True;
4011         NTSTATUS status;
4012
4013         printf("starting attrib test\n");
4014
4015         if (!torture_open_connection(&cli, 0)) {
4016                 return False;
4017         }
4018
4019         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4020         cli_openx(cli, fname, 
4021                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4022         cli_close(cli, fnum);
4023
4024         status = cli_getatr(cli, fname, NULL, NULL, &t);
4025         if (!NT_STATUS_IS_OK(status)) {
4026                 printf("getatr failed (%s)\n", nt_errstr(status));
4027                 correct = False;
4028         }
4029
4030         if (labs(t - time(NULL)) > 60*60*24*10) {
4031                 printf("ERROR: SMBgetatr bug. time is %s",
4032                        ctime(&t));
4033                 t = time(NULL);
4034                 correct = True;
4035         }
4036
4037         t2 = t-60*60*24; /* 1 day ago */
4038
4039         status = cli_setatr(cli, fname, 0, t2);
4040         if (!NT_STATUS_IS_OK(status)) {
4041                 printf("setatr failed (%s)\n", nt_errstr(status));
4042                 correct = True;
4043         }
4044
4045         status = cli_getatr(cli, fname, NULL, NULL, &t);
4046         if (!NT_STATUS_IS_OK(status)) {
4047                 printf("getatr failed (%s)\n", nt_errstr(status));
4048                 correct = True;
4049         }
4050
4051         if (t != t2) {
4052                 printf("ERROR: getatr/setatr bug. times are\n%s",
4053                        ctime(&t));
4054                 printf("%s", ctime(&t2));
4055                 correct = True;
4056         }
4057
4058         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4059
4060         /* Check cli_setpathinfo_basic() */
4061         /* Re-create the file. */
4062         status = cli_openx(cli, fname,
4063                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4064         if (!NT_STATUS_IS_OK(status)) {
4065                 printf("Failed to recreate %s (%s)\n",
4066                         fname, nt_errstr(status));
4067                 correct = false;
4068         }
4069         cli_close(cli, fnum);
4070
4071         status = cli_setpathinfo_basic(cli,
4072                                         fname,
4073                                         0, /* create */
4074                                         0, /* access */
4075                                         0, /* write */
4076                                         0, /* change */
4077                                         FILE_ATTRIBUTE_SYSTEM |
4078                                         FILE_ATTRIBUTE_HIDDEN |
4079                                         FILE_ATTRIBUTE_READONLY);
4080         if (!NT_STATUS_IS_OK(status)) {
4081                 printf("cli_setpathinfo_basic 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_basic(cli,
4098                                         fname,
4099                                         0, /* create */
4100                                         0, /* access */
4101                                         0, /* write */
4102                                         0, /* change */
4103                                         FILE_ATTRIBUTE_NORMAL);
4104         if (!NT_STATUS_IS_OK(status)) {
4105                 printf("cli_setpathinfo_basic failed with %s\n",
4106                         nt_errstr(status));
4107                 correct = false;
4108         }
4109
4110         /* Check attributes are correct. */
4111         correct = check_attributes(cli,
4112                         fname,
4113                         FILE_ATTRIBUTE_SYSTEM |
4114                         FILE_ATTRIBUTE_HIDDEN |
4115                         FILE_ATTRIBUTE_READONLY);
4116         if (correct == false) {
4117                 goto out;
4118         }
4119
4120         /* Setting to (uint16_t)-1 should also be ignored. */
4121         status = cli_setpathinfo_basic(cli,
4122                                         fname,
4123                                         0, /* create */
4124                                         0, /* access */
4125                                         0, /* write */
4126                                         0, /* change */
4127                                         (uint16_t)-1);
4128         if (!NT_STATUS_IS_OK(status)) {
4129                 printf("cli_setpathinfo_basic failed with %s\n",
4130                         nt_errstr(status));
4131                 correct = false;
4132         }
4133
4134         /* Check attributes are correct. */
4135         correct = check_attributes(cli,
4136                         fname,
4137                         FILE_ATTRIBUTE_SYSTEM |
4138                         FILE_ATTRIBUTE_HIDDEN |
4139                         FILE_ATTRIBUTE_READONLY);
4140         if (correct == false) {
4141                 goto out;
4142         }
4143
4144         /* Setting to 0 should clear them all. */
4145         status = cli_setpathinfo_basic(cli,
4146                                         fname,
4147                                         0, /* create */
4148                                         0, /* access */
4149                                         0, /* write */
4150                                         0, /* change */
4151                                         0);
4152         if (!NT_STATUS_IS_OK(status)) {
4153                 printf("cli_setpathinfo_basic failed with %s\n",
4154                         nt_errstr(status));
4155                 correct = false;
4156         }
4157
4158         /* Check attributes are correct. */
4159         correct = check_attributes(cli,
4160                         fname,
4161                         FILE_ATTRIBUTE_NORMAL);
4162         if (correct == false) {
4163                 goto out;
4164         }
4165
4166   out:
4167
4168         cli_unlink(cli,
4169                 fname,
4170                 FILE_ATTRIBUTE_SYSTEM |
4171                 FILE_ATTRIBUTE_HIDDEN|
4172                 FILE_ATTRIBUTE_READONLY);
4173
4174         if (!torture_close_connection(cli)) {
4175                 correct = False;
4176         }
4177
4178         printf("attrib test finished\n");
4179
4180         return correct;
4181 }
4182
4183
4184 /*
4185   This checks a couple of trans2 calls
4186 */
4187 static bool run_trans2test(int dummy)
4188 {
4189         struct cli_state *cli;
4190         uint16_t fnum;
4191         off_t size;
4192         time_t c_time, a_time, m_time;
4193         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4194         const char *fname = "\\trans2.tst";
4195         const char *dname = "\\trans2";
4196         const char *fname2 = "\\trans2\\trans2.tst";
4197         char *pname;
4198         bool correct = True;
4199         NTSTATUS status;
4200         uint32_t fs_attr;
4201
4202         printf("starting trans2 test\n");
4203
4204         if (!torture_open_connection(&cli, 0)) {
4205                 return False;
4206         }
4207
4208         status = cli_get_fs_attr_info(cli, &fs_attr);
4209         if (!NT_STATUS_IS_OK(status)) {
4210                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4211                        nt_errstr(status));
4212                 correct = false;
4213         }
4214
4215         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4216         cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4217         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4218                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4219         if (!NT_STATUS_IS_OK(status)) {
4220                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4221                 correct = False;
4222         }
4223
4224         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4225         if (!NT_STATUS_IS_OK(status)) {
4226                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4227                 correct = False;
4228         }
4229         else if (strcmp(pname, fname)) {
4230                 printf("qfilename gave different name? [%s] [%s]\n",
4231                        fname, pname);
4232                 correct = False;
4233         }
4234
4235         cli_close(cli, fnum);
4236
4237         sleep(2);
4238
4239         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4240         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4241                           &fnum);
4242         if (!NT_STATUS_IS_OK(status)) {
4243                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4244                 return False;
4245         }
4246         cli_close(cli, fnum);
4247
4248         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4249                                 NULL);
4250         if (!NT_STATUS_IS_OK(status)) {
4251                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4252                 correct = False;
4253         } else {
4254                 time_t t = time(NULL);
4255
4256                 if (c_time != m_time) {
4257                         printf("create time=%s", ctime(&c_time));
4258                         printf("modify time=%s", ctime(&m_time));
4259                         printf("This system appears to have sticky create times\n");
4260                 }
4261                 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4262                         printf("access time=%s", ctime(&a_time));
4263                         printf("This system appears to set a midnight access time\n");
4264                         correct = False;
4265                 }
4266
4267                 if (labs(m_time - t) > 60*60*24*7) {
4268                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4269                         correct = False;
4270                 }
4271         }
4272
4273
4274         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4275         cli_openx(cli, fname, 
4276                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4277         cli_close(cli, fnum);
4278         status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
4279                                 &m_time_ts, &size, NULL, NULL);
4280         if (!NT_STATUS_IS_OK(status)) {
4281                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4282                 correct = False;
4283         } else {
4284                 if (w_time_ts.tv_sec < 60*60*24*2) {
4285                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
4286                         printf("This system appears to set a initial 0 write time\n");
4287                         correct = False;
4288                 }
4289         }
4290
4291         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4292
4293
4294         /* check if the server updates the directory modification time
4295            when creating a new file */
4296         status = cli_mkdir(cli, dname);
4297         if (!NT_STATUS_IS_OK(status)) {
4298                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4299                 correct = False;
4300         }
4301         sleep(3);
4302         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4303                                 &w_time_ts, &m_time_ts, &size, NULL, NULL);
4304         if (!NT_STATUS_IS_OK(status)) {
4305                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4306                 correct = False;
4307         }
4308
4309         cli_openx(cli, fname2, 
4310                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4311         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4312         cli_close(cli, fnum);
4313         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4314                                 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
4315         if (!NT_STATUS_IS_OK(status)) {
4316                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4317                 correct = False;
4318         } else {
4319                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4320                     == 0) {
4321                         printf("This system does not update directory modification times\n");
4322                         correct = False;
4323                 }
4324         }
4325         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4326         cli_rmdir(cli, dname);
4327
4328         if (!torture_close_connection(cli)) {
4329                 correct = False;
4330         }
4331
4332         printf("trans2 test finished\n");
4333
4334         return correct;
4335 }
4336
4337 /*
4338   This checks new W2K calls.
4339 */
4340
4341 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4342 {
4343         uint8_t *buf = NULL;
4344         uint32_t len;
4345         NTSTATUS status;
4346
4347         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4348                                CLI_BUFFER_SIZE, NULL, &buf, &len);
4349         if (!NT_STATUS_IS_OK(status)) {
4350                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4351                        nt_errstr(status));
4352         } else {
4353                 printf("qfileinfo: level %d, len = %u\n", level, len);
4354                 dump_data(0, (uint8_t *)buf, len);
4355                 printf("\n");
4356         }
4357         TALLOC_FREE(buf);
4358         return status;
4359 }
4360
4361 static bool run_w2ktest(int dummy)
4362 {
4363         struct cli_state *cli;
4364         uint16_t fnum;
4365         const char *fname = "\\w2ktest\\w2k.tst";
4366         int level;
4367         bool correct = True;
4368
4369         printf("starting w2k test\n");
4370
4371         if (!torture_open_connection(&cli, 0)) {
4372                 return False;
4373         }
4374
4375         cli_openx(cli, fname, 
4376                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
4377
4378         for (level = 1004; level < 1040; level++) {
4379                 new_trans(cli, fnum, level);
4380         }
4381
4382         cli_close(cli, fnum);
4383
4384         if (!torture_close_connection(cli)) {
4385                 correct = False;
4386         }
4387
4388         printf("w2k test finished\n");
4389
4390         return correct;
4391 }
4392
4393
4394 /*
4395   this is a harness for some oplock tests
4396  */
4397 static bool run_oplock1(int dummy)
4398 {
4399         struct cli_state *cli1;
4400         const char *fname = "\\lockt1.lck";
4401         uint16_t fnum1;
4402         bool correct = True;
4403         NTSTATUS status;
4404
4405         printf("starting oplock test 1\n");
4406
4407         if (!torture_open_connection(&cli1, 0)) {
4408                 return False;
4409         }
4410
4411         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4412
4413         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4414
4415         cli1->use_oplocks = True;
4416
4417         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4418                           &fnum1);
4419         if (!NT_STATUS_IS_OK(status)) {
4420                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4421                 return False;
4422         }
4423
4424         cli1->use_oplocks = False;
4425
4426         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4427         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4428
4429         status = cli_close(cli1, fnum1);
4430         if (!NT_STATUS_IS_OK(status)) {
4431                 printf("close2 failed (%s)\n", nt_errstr(status));
4432                 return False;
4433         }
4434
4435         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4436         if (!NT_STATUS_IS_OK(status)) {
4437                 printf("unlink failed (%s)\n", nt_errstr(status));
4438                 return False;
4439         }
4440
4441         if (!torture_close_connection(cli1)) {
4442                 correct = False;
4443         }
4444
4445         printf("finished oplock test 1\n");
4446
4447         return correct;
4448 }
4449
4450 static bool run_oplock2(int dummy)
4451 {
4452         struct cli_state *cli1, *cli2;
4453         const char *fname = "\\lockt2.lck";
4454         uint16_t fnum1, fnum2;
4455         int saved_use_oplocks = use_oplocks;
4456         char buf[4];
4457         bool correct = True;
4458         volatile bool *shared_correct;
4459         size_t nread;
4460         NTSTATUS status;
4461
4462         shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4463         *shared_correct = True;
4464
4465         use_level_II_oplocks = True;
4466         use_oplocks = True;
4467
4468         printf("starting oplock test 2\n");
4469
4470         if (!torture_open_connection(&cli1, 0)) {
4471                 use_level_II_oplocks = False;
4472                 use_oplocks = saved_use_oplocks;
4473                 return False;
4474         }
4475
4476         if (!torture_open_connection(&cli2, 1)) {
4477                 use_level_II_oplocks = False;
4478                 use_oplocks = saved_use_oplocks;
4479                 return False;
4480         }
4481
4482         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4483
4484         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4485         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4486
4487         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4488                           &fnum1);
4489         if (!NT_STATUS_IS_OK(status)) {
4490                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4491                 return False;
4492         }
4493
4494         /* Don't need the globals any more. */
4495         use_level_II_oplocks = False;
4496         use_oplocks = saved_use_oplocks;
4497
4498         if (fork() == 0) {
4499                 /* Child code */
4500                 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4501                 if (!NT_STATUS_IS_OK(status)) {
4502                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4503                         *shared_correct = False;
4504                         exit(0);
4505                 }
4506
4507                 sleep(2);
4508
4509                 status = cli_close(cli2, fnum2);
4510                 if (!NT_STATUS_IS_OK(status)) {
4511                         printf("close2 failed (%s)\n", nt_errstr(status));
4512                         *shared_correct = False;
4513                 }
4514
4515                 exit(0);
4516         }
4517
4518         sleep(2);
4519
4520         /* Ensure cli1 processes the break. Empty file should always return 0
4521          * bytes.  */
4522         status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4523         if (!NT_STATUS_IS_OK(status)) {
4524                 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4525                 correct = false;
4526         } else if (nread != 0) {
4527                 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4528                       (unsigned long)nread, 0);
4529                 correct = false;
4530         }
4531
4532         /* Should now be at level II. */
4533         /* Test if sending a write locks causes a break to none. */
4534         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4535         if (!NT_STATUS_IS_OK(status)) {
4536                 printf("lock failed (%s)\n", nt_errstr(status));
4537                 correct = False;
4538         }
4539
4540         cli_unlock(cli1, fnum1, 0, 4);
4541
4542         sleep(2);
4543
4544         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4545         if (!NT_STATUS_IS_OK(status)) {
4546                 printf("lock failed (%s)\n", nt_errstr(status));
4547                 correct = False;
4548         }
4549
4550         cli_unlock(cli1, fnum1, 0, 4);
4551
4552         sleep(2);
4553
4554         cli_read(cli1, fnum1, buf, 0, 4, NULL);
4555
4556         status = cli_close(cli1, fnum1);
4557         if (!NT_STATUS_IS_OK(status)) {
4558                 printf("close1 failed (%s)\n", nt_errstr(status));
4559                 correct = False;
4560         }
4561
4562         sleep(4);
4563
4564         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4565         if (!NT_STATUS_IS_OK(status)) {
4566                 printf("unlink failed (%s)\n", nt_errstr(status));
4567                 correct = False;
4568         }
4569
4570         if (!torture_close_connection(cli1)) {
4571                 correct = False;
4572         }
4573
4574         if (!*shared_correct) {
4575                 correct = False;
4576         }
4577
4578         printf("finished oplock test 2\n");
4579
4580         return correct;
4581 }
4582
4583 struct oplock4_state {
4584         struct tevent_context *ev;
4585         struct cli_state *cli;
4586         bool *got_break;
4587         uint16_t *fnum2;
4588 };
4589
4590 static void oplock4_got_break(struct tevent_req *req);
4591 static void oplock4_got_open(struct tevent_req *req);
4592
4593 static bool run_oplock4(int dummy)
4594 {
4595         struct tevent_context *ev;
4596         struct cli_state *cli1, *cli2;
4597         struct tevent_req *oplock_req, *open_req;
4598         const char *fname = "\\lockt4.lck";
4599         const char *fname_ln = "\\lockt4_ln.lck";
4600         uint16_t fnum1, fnum2;
4601         int saved_use_oplocks = use_oplocks;
4602         NTSTATUS status;
4603         bool correct = true;
4604
4605         bool got_break;
4606
4607         struct oplock4_state *state;
4608
4609         printf("starting oplock test 4\n");
4610
4611         if (!torture_open_connection(&cli1, 0)) {
4612                 use_level_II_oplocks = false;
4613                 use_oplocks = saved_use_oplocks;
4614                 return false;
4615         }
4616
4617         if (!torture_open_connection(&cli2, 1)) {
4618                 use_level_II_oplocks = false;
4619                 use_oplocks = saved_use_oplocks;
4620                 return false;
4621         }
4622
4623         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4624         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4625
4626         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4627         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4628
4629         /* Create the file. */
4630         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4631                           &fnum1);
4632         if (!NT_STATUS_IS_OK(status)) {
4633                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4634                 return false;
4635         }
4636
4637         status = cli_close(cli1, fnum1);
4638         if (!NT_STATUS_IS_OK(status)) {
4639                 printf("close1 failed (%s)\n", nt_errstr(status));
4640                 return false;
4641         }
4642
4643         /* Now create a hardlink. */
4644         status = cli_hardlink(cli1, fname, fname_ln);
4645         if (!NT_STATUS_IS_OK(status)) {
4646                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4647                 return false;
4648         }
4649
4650         /* Prove that opening hardlinks cause deny modes to conflict. */
4651         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4652         if (!NT_STATUS_IS_OK(status)) {
4653                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4654                 return false;
4655         }
4656
4657         status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4658         if (NT_STATUS_IS_OK(status)) {
4659                 printf("open of %s succeeded - should fail with sharing violation.\n",
4660                         fname_ln);
4661                 return false;
4662         }
4663
4664         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4665                 printf("open of %s should fail with sharing violation. Got %s\n",
4666                         fname_ln, nt_errstr(status));
4667                 return false;
4668         }
4669
4670         status = cli_close(cli1, fnum1);
4671         if (!NT_STATUS_IS_OK(status)) {
4672                 printf("close1 failed (%s)\n", nt_errstr(status));
4673                 return false;
4674         }
4675
4676         cli1->use_oplocks = true;
4677         cli2->use_oplocks = true;
4678
4679         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4680         if (!NT_STATUS_IS_OK(status)) {
4681                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4682                 return false;
4683         }
4684
4685         ev = samba_tevent_context_init(talloc_tos());
4686         if (ev == NULL) {
4687                 printf("tevent_context_init failed\n");
4688                 return false;
4689         }
4690
4691         state = talloc(ev, struct oplock4_state);
4692         if (state == NULL) {
4693                 printf("talloc failed\n");
4694                 return false;
4695         }
4696         state->ev = ev;
4697         state->cli = cli1;
4698         state->got_break = &got_break;
4699         state->fnum2 = &fnum2;
4700
4701         oplock_req = cli_smb_oplock_break_waiter_send(
4702                 talloc_tos(), ev, cli1);
4703         if (oplock_req == NULL) {
4704                 printf("cli_smb_oplock_break_waiter_send failed\n");
4705                 return false;
4706         }
4707         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
4708
4709         open_req = cli_openx_send(
4710                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
4711         if (open_req == NULL) {
4712                 printf("cli_openx_send failed\n");
4713                 return false;
4714         }
4715         tevent_req_set_callback(open_req, oplock4_got_open, state);
4716
4717         got_break = false;
4718         fnum2 = 0xffff;
4719
4720         while (!got_break || fnum2 == 0xffff) {
4721                 int ret;
4722                 ret = tevent_loop_once(ev);
4723                 if (ret == -1) {
4724                         printf("tevent_loop_once failed: %s\n",
4725                                strerror(errno));
4726                         return false;
4727                 }
4728         }
4729
4730         status = cli_close(cli2, fnum2);
4731         if (!NT_STATUS_IS_OK(status)) {
4732                 printf("close2 failed (%s)\n", nt_errstr(status));
4733                 correct = false;
4734         }
4735
4736         status = cli_close(cli1, fnum1);
4737         if (!NT_STATUS_IS_OK(status)) {
4738                 printf("close1 failed (%s)\n", nt_errstr(status));
4739                 correct = false;
4740         }
4741
4742         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4743         if (!NT_STATUS_IS_OK(status)) {
4744                 printf("unlink failed (%s)\n", nt_errstr(status));
4745                 correct = false;
4746         }
4747
4748         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4749         if (!NT_STATUS_IS_OK(status)) {
4750                 printf("unlink failed (%s)\n", nt_errstr(status));
4751                 correct = false;
4752         }
4753
4754         if (!torture_close_connection(cli1)) {
4755                 correct = false;
4756         }
4757
4758         if (!got_break) {
4759                 correct = false;
4760         }
4761
4762         printf("finished oplock test 4\n");
4763
4764         return correct;
4765 }
4766
4767 static void oplock4_got_break(struct tevent_req *req)
4768 {
4769         struct oplock4_state *state = tevent_req_callback_data(
4770                 req, struct oplock4_state);
4771         uint16_t fnum;
4772         uint8_t level;
4773         NTSTATUS status;
4774
4775         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
4776         TALLOC_FREE(req);
4777         if (!NT_STATUS_IS_OK(status)) {
4778                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
4779                        nt_errstr(status));
4780                 return;
4781         }
4782         *state->got_break = true;
4783
4784         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
4785                                   NO_OPLOCK);
4786         if (req == NULL) {
4787                 printf("cli_oplock_ack_send failed\n");
4788                 return;
4789         }
4790 }
4791
4792 static void oplock4_got_open(struct tevent_req *req)
4793 {
4794         struct oplock4_state *state = tevent_req_callback_data(
4795                 req, struct oplock4_state);
4796         NTSTATUS status;
4797
4798         status = cli_openx_recv(req, state->fnum2);
4799         if (!NT_STATUS_IS_OK(status)) {
4800                 printf("cli_openx_recv returned %s\n", nt_errstr(status));
4801                 *state->fnum2 = 0xffff;
4802         }
4803 }
4804
4805 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
4806
4807 struct oplock5_state {
4808         int pipe_down_fd;
4809 };
4810
4811 /*
4812  * Async open the file that has a kernel oplock, do an echo to get
4813  * that 100% across, close the file to signal to the child fd that the
4814  * oplock can be dropped, wait for the open reply.
4815  */
4816
4817 static void oplock5_opened(struct tevent_req *subreq);
4818 static void oplock5_pong(struct tevent_req *subreq);
4819 static void oplock5_timedout(struct tevent_req *subreq);
4820
4821 static struct tevent_req *oplock5_send(
4822         TALLOC_CTX *mem_ctx,
4823         struct tevent_context *ev,
4824         struct cli_state *cli,
4825         const char *fname,
4826         int pipe_down_fd)
4827 {
4828         struct tevent_req *req = NULL, *subreq = NULL;
4829         struct oplock5_state *state = NULL;
4830         static uint8_t data = 0;
4831
4832         req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
4833         if (req == NULL) {
4834                 return NULL;
4835         }
4836         state->pipe_down_fd = pipe_down_fd;
4837
4838         subreq = cli_ntcreate_send(
4839                 state,
4840                 ev,
4841                 cli,
4842                 fname,
4843                 0,                      /* CreatFlags */
4844                 SEC_FILE_READ_DATA,    /* DesiredAccess */
4845                 FILE_ATTRIBUTE_NORMAL,  /* FileAttributes */
4846                 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
4847                 FILE_OPEN,               /* CreateDisposition */
4848                 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
4849                 0,                       /* Impersonation */
4850                 0);                      /* SecurityFlags */
4851         if (tevent_req_nomem(subreq, req)) {
4852                 return tevent_req_post(req, ev);
4853         }
4854         tevent_req_set_callback(subreq, oplock5_opened, req);
4855
4856         subreq = cli_echo_send(
4857                 state,
4858                 ev,
4859                 cli,
4860                 1,
4861                 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
4862         if (tevent_req_nomem(subreq, req)) {
4863                 return tevent_req_post(req, ev);
4864         }
4865         tevent_req_set_callback(subreq, oplock5_pong, req);
4866
4867         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
4868         if (tevent_req_nomem(subreq, req)) {
4869                 return tevent_req_post(req, ev);
4870         }
4871         tevent_req_set_callback(subreq, oplock5_timedout, req);
4872
4873         return req;
4874 }
4875
4876 static void oplock5_opened(struct tevent_req *subreq)
4877 {
4878         struct tevent_req *req = tevent_req_callback_data(
4879                 subreq, struct tevent_req);
4880         NTSTATUS status;
4881         uint16_t fnum;
4882
4883         status = cli_ntcreate_recv(subreq, &fnum, NULL);
4884         TALLOC_FREE(subreq);
4885         if (tevent_req_nterror(req, status)) {
4886                 return;
4887         }
4888         tevent_req_done(req);
4889 }
4890
4891 static void oplock5_pong(struct tevent_req *subreq)
4892 {
4893         struct tevent_req *req = tevent_req_callback_data(
4894                 subreq, struct tevent_req);
4895         struct oplock5_state *state = tevent_req_data(
4896                 req, struct oplock5_state);
4897         NTSTATUS status;
4898
4899         status = cli_echo_recv(subreq);
4900         TALLOC_FREE(subreq);
4901         if (tevent_req_nterror(req, status)) {
4902                 return;
4903         }
4904
4905         close(state->pipe_down_fd);
4906 }
4907
4908 static void oplock5_timedout(struct tevent_req *subreq)
4909 {
4910         struct tevent_req *req = tevent_req_callback_data(
4911                 subreq, struct tevent_req);
4912         bool ok;
4913
4914         ok = tevent_wakeup_recv(subreq);
4915         TALLOC_FREE(subreq);
4916         if (!ok) {
4917                 tevent_req_oom(req);
4918                 return;
4919         }
4920         tevent_req_nterror(req, NT_STATUS_TIMEOUT);
4921 }
4922
4923 static NTSTATUS oplock5_recv(struct tevent_req *req)
4924 {
4925         return tevent_req_simple_recv_ntstatus(req);
4926 }
4927
4928 static bool run_oplock5(int dummy)
4929 {
4930         struct tevent_context *ev = NULL;
4931         struct tevent_req *req = NULL;
4932         struct cli_state *cli = NULL;
4933         const char *fname = "oplock5.txt";
4934         int pipe_down[2], pipe_up[2];
4935         pid_t child_pid;
4936         uint8_t c = '\0';
4937         NTSTATUS status;
4938         int ret;
4939         bool ok;
4940
4941         printf("starting oplock5\n");
4942
4943         if (local_path == NULL) {
4944                 d_fprintf(stderr, "oplock5 must be given a local path via "
4945                           "-l <localpath>\n");
4946                 return false;
4947         }
4948
4949         ret = pipe(pipe_down);
4950         if (ret == -1) {
4951                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
4952                 return false;
4953         }
4954         ret = pipe(pipe_up);
4955         if (ret == -1) {
4956                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
4957                 return false;
4958         }
4959
4960         child_pid = fork();
4961         if (child_pid == -1) {
4962                 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
4963                 return false;
4964         }
4965
4966         if (child_pid == 0) {
4967                 char *local_file = NULL;
4968                 int fd;
4969
4970                 close(pipe_down[1]);
4971                 close(pipe_up[0]);
4972
4973                 local_file = talloc_asprintf(
4974                         talloc_tos(), "%s/%s", local_path, fname);
4975                 if (local_file == 0) {
4976                         c = 1;
4977                         goto do_write;
4978                 }
4979                 fd = open(local_file, O_RDWR|O_CREAT, 0644);
4980                 if (fd == -1) {
4981                         d_fprintf(stderr,
4982                                   "open(%s) in child failed: %s\n",
4983                                   local_file,
4984                                   strerror(errno));
4985                         c = 2;
4986                         goto do_write;
4987                 }
4988
4989                 signal(SIGIO, SIG_IGN);
4990
4991                 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
4992                 if (ret == -1) {
4993                         d_fprintf(stderr,
4994                                   "SETLEASE in child failed: %s\n",
4995                                   strerror(errno));
4996                         c = 3;
4997                         goto do_write;
4998                 }
4999
5000         do_write:
5001                 ret = sys_write(pipe_up[1], &c, sizeof(c));
5002                 if (ret == -1) {
5003                         d_fprintf(stderr,
5004                                   "sys_write failed: %s\n",
5005                                   strerror(errno));
5006                         exit(4);
5007                 }
5008                 ret = sys_read(pipe_down[0], &c, sizeof(c));
5009                 if (ret == -1) {
5010                         d_fprintf(stderr,
5011                                   "sys_read failed: %s\n",
5012                                   strerror(errno));
5013                         exit(5);
5014                 }
5015                 exit(0);
5016         }
5017
5018         close(pipe_up[1]);
5019         close(pipe_down[0]);
5020
5021         ret = sys_read(pipe_up[0], &c, sizeof(c));
5022         if (ret != 1) {
5023                 d_fprintf(stderr,
5024                           "sys_read failed: %s\n",
5025                           strerror(errno));
5026                 return false;
5027         }
5028         if (c != 0) {
5029                 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5030                 return false;
5031         }
5032
5033         ok = torture_open_connection(&cli, 0);
5034         if (!ok) {
5035                 d_fprintf(stderr, "torture_open_connection failed\n");
5036                 return false;
5037         }
5038
5039         ev = samba_tevent_context_init(talloc_tos());
5040         if (ev == NULL) {
5041                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5042                 return false;
5043         }
5044
5045         req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5046         if (req == NULL) {
5047                 d_fprintf(stderr, "oplock5_send failed\n");
5048                 return false;
5049         }
5050
5051         ok = tevent_req_poll_ntstatus(req, ev, &status);
5052         if (!ok) {
5053                 d_fprintf(stderr,
5054                           "tevent_req_poll_ntstatus failed: %s\n",
5055                           nt_errstr(status));
5056                 return false;
5057         }
5058
5059         status = oplock5_recv(req);
5060         TALLOC_FREE(req);
5061         if (!NT_STATUS_IS_OK(status)) {
5062                 d_fprintf(stderr,
5063                           "oplock5 failed: %s\n",
5064                           nt_errstr(status));
5065                 return false;
5066         }
5067
5068         return true;
5069 }
5070
5071 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5072
5073 /*
5074   Test delete on close semantics.
5075  */
5076 static bool run_deletetest(int dummy)
5077 {
5078         struct cli_state *cli1 = NULL;
5079         struct cli_state *cli2 = NULL;
5080         const char *fname = "\\delete.file";
5081         uint16_t fnum1 = (uint16_t)-1;
5082         uint16_t fnum2 = (uint16_t)-1;
5083         bool correct = false;
5084         NTSTATUS status;
5085
5086         printf("starting delete test\n");
5087
5088         if (!torture_open_connection(&cli1, 0)) {
5089                 return False;
5090         }
5091
5092         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5093
5094         /* Test 1 - this should delete the file on close. */
5095
5096         cli_setatr(cli1, fname, 0, 0);
5097         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5098
5099         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5100                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5101                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5102         if (!NT_STATUS_IS_OK(status)) {
5103                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5104                 goto fail;
5105         }
5106
5107         status = cli_close(cli1, fnum1);
5108         if (!NT_STATUS_IS_OK(status)) {
5109                 printf("[1] close failed (%s)\n", nt_errstr(status));
5110                 goto fail;
5111         }
5112
5113         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5114         if (NT_STATUS_IS_OK(status)) {
5115                 printf("[1] open of %s succeeded (should fail)\n", fname);
5116                 goto fail;
5117         }
5118
5119         printf("first delete on close test succeeded.\n");
5120
5121         /* Test 2 - this should delete the file on close. */
5122
5123         cli_setatr(cli1, fname, 0, 0);
5124         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5125
5126         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5127                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5128                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5129         if (!NT_STATUS_IS_OK(status)) {
5130                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5131                 goto fail;
5132         }
5133
5134         status = cli_nt_delete_on_close(cli1, fnum1, true);
5135         if (!NT_STATUS_IS_OK(status)) {
5136                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5137                 goto fail;
5138         }
5139
5140         status = cli_close(cli1, fnum1);
5141         if (!NT_STATUS_IS_OK(status)) {
5142                 printf("[2] close failed (%s)\n", nt_errstr(status));
5143                 goto fail;
5144         }
5145
5146         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5147         if (NT_STATUS_IS_OK(status)) {
5148                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5149                 status = cli_close(cli1, fnum1);
5150                 if (!NT_STATUS_IS_OK(status)) {
5151                         printf("[2] close failed (%s)\n", nt_errstr(status));
5152                 }
5153                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5154                 goto fail;
5155         }
5156
5157         printf("second delete on close test succeeded.\n");
5158
5159         /* Test 3 - ... */
5160         cli_setatr(cli1, fname, 0, 0);
5161         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5162
5163         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5164                               FILE_ATTRIBUTE_NORMAL,
5165                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5166                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5167         if (!NT_STATUS_IS_OK(status)) {
5168                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5169                 goto fail;
5170         }
5171
5172         /* This should fail with a sharing violation - open for delete is only compatible
5173            with SHARE_DELETE. */
5174
5175         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5176                               FILE_ATTRIBUTE_NORMAL,
5177                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5178                               FILE_OPEN, 0, 0, &fnum2, NULL);
5179         if (NT_STATUS_IS_OK(status)) {
5180                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
5181                 goto fail;
5182         }
5183
5184         /* This should succeed. */
5185         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5186                              FILE_ATTRIBUTE_NORMAL,
5187                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5188                              FILE_OPEN, 0, 0, &fnum2, NULL);
5189         if (!NT_STATUS_IS_OK(status)) {
5190                 printf("[3] open  - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5191                 goto fail;
5192         }
5193
5194         status = cli_nt_delete_on_close(cli1, fnum1, true);
5195         if (!NT_STATUS_IS_OK(status)) {
5196                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5197                 goto fail;
5198         }
5199
5200         status = cli_close(cli1, fnum1);
5201         if (!NT_STATUS_IS_OK(status)) {
5202                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5203                 goto fail;
5204         }
5205
5206         status = cli_close(cli1, fnum2);
5207         if (!NT_STATUS_IS_OK(status)) {
5208                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5209                 goto fail;
5210         }
5211
5212         /* This should fail - file should no longer be there. */
5213
5214         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5215         if (NT_STATUS_IS_OK(status)) {
5216                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5217                 status = cli_close(cli1, fnum1);
5218                 if (!NT_STATUS_IS_OK(status)) {
5219                         printf("[3] close failed (%s)\n", nt_errstr(status));
5220                 }
5221                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5222                 goto fail;
5223         }
5224
5225         printf("third delete on close test succeeded.\n");
5226
5227         /* Test 4 ... */
5228         cli_setatr(cli1, fname, 0, 0);
5229         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5230
5231         status = cli_ntcreate(cli1, fname, 0,
5232                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5233                               FILE_ATTRIBUTE_NORMAL,
5234                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5235                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5236         if (!NT_STATUS_IS_OK(status)) {
5237                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5238                 goto fail;
5239         }
5240
5241         /* This should succeed. */
5242         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5243                              FILE_ATTRIBUTE_NORMAL,
5244                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5245                              FILE_OPEN, 0, 0, &fnum2, NULL);
5246         if (!NT_STATUS_IS_OK(status)) {
5247                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5248                 goto fail;
5249         }
5250
5251         status = cli_close(cli1, fnum2);
5252         if (!NT_STATUS_IS_OK(status)) {
5253                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5254                 goto fail;
5255         }
5256
5257         status = cli_nt_delete_on_close(cli1, fnum1, true);
5258         if (!NT_STATUS_IS_OK(status)) {
5259                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5260                 goto fail;
5261         }
5262
5263         /* This should fail - no more opens once delete on close set. */
5264         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5265                               FILE_ATTRIBUTE_NORMAL,
5266                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5267                               FILE_OPEN, 0, 0, &fnum2, NULL);
5268         if (NT_STATUS_IS_OK(status)) {
5269                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
5270                 goto fail;
5271         }
5272
5273         status = cli_close(cli1, fnum1);
5274         if (!NT_STATUS_IS_OK(status)) {
5275                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5276                 goto fail;
5277         }
5278
5279         printf("fourth delete on close test succeeded.\n");
5280
5281         /* Test 5 ... */
5282         cli_setatr(cli1, fname, 0, 0);
5283         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5284
5285         status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5286         if (!NT_STATUS_IS_OK(status)) {
5287                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5288                 goto fail;
5289         }
5290
5291         /* This should fail - only allowed on NT opens with DELETE access. */
5292
5293         status = cli_nt_delete_on_close(cli1, fnum1, true);
5294         if (NT_STATUS_IS_OK(status)) {
5295                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5296                 goto fail;
5297         }
5298
5299         status = cli_close(cli1, fnum1);
5300         if (!NT_STATUS_IS_OK(status)) {
5301                 printf("[5] close failed (%s)\n", nt_errstr(status));
5302                 goto fail;
5303         }
5304
5305         printf("fifth delete on close test succeeded.\n");
5306
5307         /* Test 6 ... */
5308         cli_setatr(cli1, fname, 0, 0);
5309         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5310
5311         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5312                              FILE_ATTRIBUTE_NORMAL,
5313                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5314                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5315         if (!NT_STATUS_IS_OK(status)) {
5316                 printf("[6] open of %s failed (%s)\n", fname,
5317                        nt_errstr(status));
5318                 goto fail;
5319         }
5320
5321         /* This should fail - only allowed on NT opens with DELETE access. */
5322
5323         status = cli_nt_delete_on_close(cli1, fnum1, true);
5324         if (NT_STATUS_IS_OK(status)) {
5325                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5326                 goto fail;
5327         }
5328
5329         status = cli_close(cli1, fnum1);
5330         if (!NT_STATUS_IS_OK(status)) {
5331                 printf("[6] close failed (%s)\n", nt_errstr(status));
5332                 goto fail;
5333         }
5334
5335         printf("sixth delete on close test succeeded.\n");
5336
5337         /* Test 7 ... */
5338         cli_setatr(cli1, fname, 0, 0);
5339         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5340
5341         status = cli_ntcreate(cli1, fname, 0,
5342                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5343                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5344                               0, 0, &fnum1, NULL);
5345         if (!NT_STATUS_IS_OK(status)) {
5346                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5347                 goto fail;
5348         }
5349
5350         status = cli_nt_delete_on_close(cli1, fnum1, true);
5351         if (!NT_STATUS_IS_OK(status)) {
5352                 printf("[7] setting delete_on_close on file failed !\n");
5353                 goto fail;
5354         }
5355
5356         status = cli_nt_delete_on_close(cli1, fnum1, false);
5357         if (!NT_STATUS_IS_OK(status)) {
5358                 printf("[7] unsetting delete_on_close on file failed !\n");
5359                 goto fail;
5360         }
5361
5362         status = cli_close(cli1, fnum1);
5363         if (!NT_STATUS_IS_OK(status)) {
5364                 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5365                 goto fail;
5366         }
5367
5368         /* This next open should succeed - we reset the flag. */
5369         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
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_close(cli1, fnum1);
5376         if (!NT_STATUS_IS_OK(status)) {
5377                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5378                 goto fail;
5379         }
5380
5381         printf("seventh delete on close test succeeded.\n");
5382
5383         /* Test 8 ... */
5384         cli_setatr(cli1, fname, 0, 0);
5385         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5386
5387         if (!torture_open_connection(&cli2, 1)) {
5388                 printf("[8] failed to open second connection.\n");
5389                 goto fail;
5390         }
5391
5392         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5393
5394         status = cli_ntcreate(cli1, fname, 0,
5395                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5396                              FILE_ATTRIBUTE_NORMAL,
5397                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5398                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5399         if (!NT_STATUS_IS_OK(status)) {
5400                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5401                 goto fail;
5402         }
5403
5404         status = cli_ntcreate(cli2, fname, 0,
5405                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5406                              FILE_ATTRIBUTE_NORMAL,
5407                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5408                              FILE_OPEN, 0, 0, &fnum2, NULL);
5409         if (!NT_STATUS_IS_OK(status)) {
5410                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5411                 goto fail;
5412         }
5413
5414         status = cli_nt_delete_on_close(cli1, fnum1, true);
5415         if (!NT_STATUS_IS_OK(status)) {
5416                 printf("[8] setting delete_on_close on file failed !\n");
5417                 goto fail;
5418         }
5419
5420         status = cli_close(cli1, fnum1);
5421         if (!NT_STATUS_IS_OK(status)) {
5422                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5423                 goto fail;
5424         }
5425
5426         status = cli_close(cli2, fnum2);
5427         if (!NT_STATUS_IS_OK(status)) {
5428                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5429                 goto fail;
5430         }
5431
5432         /* This should fail.. */
5433         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5434         if (NT_STATUS_IS_OK(status)) {
5435                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5436                 goto fail;
5437         }
5438
5439         printf("eighth delete on close test succeeded.\n");
5440
5441         /* Test 9 ... */
5442
5443         /* This should fail - we need to set DELETE_ACCESS. */
5444         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5445                               FILE_ATTRIBUTE_NORMAL,
5446                               FILE_SHARE_NONE,
5447                               FILE_OVERWRITE_IF,
5448                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5449         if (NT_STATUS_IS_OK(status)) {
5450                 printf("[9] open of %s succeeded should have failed!\n", fname);
5451                 goto fail;
5452         }
5453
5454         printf("ninth delete on close test succeeded.\n");
5455
5456         /* Test 10 ... */
5457
5458         status = cli_ntcreate(cli1, fname, 0,
5459                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5460                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5461                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5462                              0, &fnum1, NULL);
5463         if (!NT_STATUS_IS_OK(status)) {
5464                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5465                 goto fail;
5466         }
5467
5468         /* This should delete the file. */
5469         status = cli_close(cli1, fnum1);
5470         if (!NT_STATUS_IS_OK(status)) {
5471                 printf("[10] close failed (%s)\n", nt_errstr(status));
5472                 goto fail;
5473         }
5474
5475         /* This should fail.. */
5476         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5477         if (NT_STATUS_IS_OK(status)) {
5478                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5479                 goto fail;
5480         }
5481
5482         printf("tenth delete on close test succeeded.\n");
5483
5484         /* Test 11 ... */
5485
5486         cli_setatr(cli1, fname, 0, 0);
5487         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5488
5489         /* Can we open a read-only file with delete access? */
5490
5491         /* Create a readonly file. */
5492         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5493                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5494                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5495         if (!NT_STATUS_IS_OK(status)) {
5496                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5497                 goto fail;
5498         }
5499
5500         status = cli_close(cli1, fnum1);
5501         if (!NT_STATUS_IS_OK(status)) {
5502                 printf("[11] close failed (%s)\n", nt_errstr(status));
5503                 goto fail;
5504         }
5505
5506         /* Now try open for delete access. */
5507         status = cli_ntcreate(cli1, fname, 0,
5508                              FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5509                              0,
5510                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5511                              FILE_OPEN, 0, 0, &fnum1, NULL);
5512         if (!NT_STATUS_IS_OK(status)) {
5513                 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5514                 goto fail;
5515         }
5516
5517         cli_close(cli1, fnum1);
5518
5519         printf("eleventh delete on close test succeeded.\n");
5520
5521         /*
5522          * Test 12
5523          * like test 4 but with initial delete on close
5524          */
5525
5526         cli_setatr(cli1, fname, 0, 0);
5527         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5528
5529         status = cli_ntcreate(cli1, fname, 0,
5530                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5531                               FILE_ATTRIBUTE_NORMAL,
5532                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5533                               FILE_OVERWRITE_IF,
5534                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5535         if (!NT_STATUS_IS_OK(status)) {
5536                 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5537                 goto fail;
5538         }
5539
5540         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5541                               FILE_ATTRIBUTE_NORMAL,
5542                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5543                               FILE_OPEN, 0, 0, &fnum2, NULL);
5544         if (!NT_STATUS_IS_OK(status)) {
5545                 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5546                 goto fail;
5547         }
5548
5549         status = cli_close(cli1, fnum2);
5550         if (!NT_STATUS_IS_OK(status)) {
5551                 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5552                 goto fail;
5553         }
5554
5555         status = cli_nt_delete_on_close(cli1, fnum1, true);
5556         if (!NT_STATUS_IS_OK(status)) {
5557                 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5558                 goto fail;
5559         }
5560
5561         /* This should fail - no more opens once delete on close set. */
5562         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5563                               FILE_ATTRIBUTE_NORMAL,
5564                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5565                               FILE_OPEN, 0, 0, &fnum2, NULL);
5566         if (NT_STATUS_IS_OK(status)) {
5567                 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5568                 goto fail;
5569         }
5570
5571         status = cli_nt_delete_on_close(cli1, fnum1, false);
5572         if (!NT_STATUS_IS_OK(status)) {
5573                 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5574                 goto fail;
5575         }
5576
5577         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5578                               FILE_ATTRIBUTE_NORMAL,
5579                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5580                               FILE_OPEN, 0, 0, &fnum2, NULL);
5581         if (!NT_STATUS_IS_OK(status)) {
5582                 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5583                 goto fail;
5584         }
5585
5586         status = cli_close(cli1, fnum2);
5587         if (!NT_STATUS_IS_OK(status)) {
5588                 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5589                 goto fail;
5590         }
5591
5592         status = cli_close(cli1, fnum1);
5593         if (!NT_STATUS_IS_OK(status)) {
5594                 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5595                 goto fail;
5596         }
5597
5598         /*
5599          * setting delete on close on the handle does
5600          * not unset the initial delete on close...
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 5 of %s succeeded - should fail).\n", fname);
5608                 goto fail;
5609         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5610                 printf("ntcreate returned %s, expected "
5611                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5612                        nt_errstr(status));
5613                 goto fail;
5614         }
5615
5616         printf("twelfth delete on close test succeeded.\n");
5617
5618
5619         printf("finished delete test\n");
5620
5621         correct = true;
5622
5623   fail:
5624         /* FIXME: This will crash if we aborted before cli2 got
5625          * intialized, because these functions don't handle
5626          * uninitialized connections. */
5627
5628         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5629         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5630         cli_setatr(cli1, fname, 0, 0);
5631         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5632
5633         if (cli1 && !torture_close_connection(cli1)) {
5634                 correct = False;
5635         }
5636         if (cli2 && !torture_close_connection(cli2)) {
5637                 correct = False;
5638         }
5639         return correct;
5640 }
5641
5642 /*
5643   Exercise delete on close semantics - use on the PRINT1 share in torture
5644   testing.
5645  */
5646 static bool run_delete_print_test(int dummy)
5647 {
5648         struct cli_state *cli1 = NULL;
5649         const char *fname = "print_delete.file";
5650         uint16_t fnum1 = (uint16_t)-1;
5651         bool correct = false;
5652         const char *buf = "print file data\n";
5653         NTSTATUS status;
5654
5655         printf("starting print delete test\n");
5656
5657         if (!torture_open_connection(&cli1, 0)) {
5658                 return false;
5659         }
5660
5661         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5662
5663         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5664                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5665                               0, 0, &fnum1, NULL);
5666         if (!NT_STATUS_IS_OK(status)) {
5667                 printf("open of %s failed (%s)\n",
5668                         fname,
5669                         nt_errstr(status));
5670                 goto fail;
5671         }
5672
5673         status = cli_writeall(cli1,
5674                         fnum1,
5675                         0,
5676                         (const uint8_t *)buf,
5677                         0, /* offset */
5678                         strlen(buf), /* size */
5679                         NULL);
5680         if (!NT_STATUS_IS_OK(status)) {
5681                 printf("writing print file data failed (%s)\n",
5682                         nt_errstr(status));
5683                 goto fail;
5684         }
5685
5686         status = cli_nt_delete_on_close(cli1, fnum1, true);
5687         if (!NT_STATUS_IS_OK(status)) {
5688                 printf("setting delete_on_close failed (%s)\n",
5689                         nt_errstr(status));
5690                 goto fail;
5691         }
5692
5693         status = cli_close(cli1, fnum1);
5694         if (!NT_STATUS_IS_OK(status)) {
5695                 printf("close failed (%s)\n", nt_errstr(status));
5696                 goto fail;
5697         }
5698
5699         printf("finished print delete test\n");
5700
5701         correct = true;
5702
5703   fail:
5704
5705         if (fnum1 != (uint16_t)-1) {
5706                 cli_close(cli1, fnum1);
5707         }
5708
5709         if (cli1 && !torture_close_connection(cli1)) {
5710                 correct = false;
5711         }
5712         return correct;
5713 }
5714
5715 /*
5716   Test wildcard delete.
5717  */
5718 static bool run_wild_deletetest(int dummy)
5719 {
5720         struct cli_state *cli = NULL;
5721         const char *dname = "\\WTEST";
5722         const char *fname = "\\WTEST\\A";
5723         const char *wunlink_name = "\\WTEST\\*";
5724         uint16_t fnum1 = (uint16_t)-1;
5725         bool correct = false;
5726         NTSTATUS status;
5727
5728         printf("starting wildcard delete test\n");
5729
5730         if (!torture_open_connection(&cli, 0)) {
5731                 return false;
5732         }
5733
5734         smbXcli_conn_set_sockopt(cli->conn, sockops);
5735
5736         cli_unlink(cli, fname, 0);
5737         cli_rmdir(cli, dname);
5738         status = cli_mkdir(cli, dname);
5739         if (!NT_STATUS_IS_OK(status)) {
5740                 printf("mkdir of %s failed %s!\n", dname, nt_errstr(status));
5741                 goto fail;
5742         }
5743         status = cli_openx(cli, fname, O_CREAT|O_RDONLY, DENY_NONE, &fnum1);
5744         if (!NT_STATUS_IS_OK(status)) {
5745                 printf("open of %s failed %s!\n", fname, nt_errstr(status));
5746                 goto fail;
5747         }
5748         status = cli_close(cli, fnum1);
5749         fnum1 = -1;
5750
5751         /*
5752          * Note the unlink attribute-type of zero. This should
5753          * map into FILE_ATTRIBUTE_NORMAL at the server even
5754          * on a wildcard delete.
5755          */
5756
5757         status = cli_unlink(cli, wunlink_name, 0);
5758         if (!NT_STATUS_IS_OK(status)) {
5759                 printf("unlink of %s failed %s!\n",
5760                         wunlink_name, nt_errstr(status));
5761                 goto fail;
5762         }
5763
5764         printf("finished wildcard delete test\n");
5765
5766         correct = true;
5767
5768   fail:
5769
5770         if (fnum1 != (uint16_t)-1) cli_close(cli, fnum1);
5771         cli_unlink(cli, fname, 0);
5772         cli_rmdir(cli, dname);
5773
5774         if (cli && !torture_close_connection(cli)) {
5775                 correct = false;
5776         }
5777         return correct;
5778 }
5779
5780 static bool run_deletetest_ln(int dummy)
5781 {
5782         struct cli_state *cli;
5783         const char *fname = "\\delete1";
5784         const char *fname_ln = "\\delete1_ln";
5785         uint16_t fnum;
5786         uint16_t fnum1;
5787         NTSTATUS status;
5788         bool correct = true;
5789         time_t t;
5790
5791         printf("starting deletetest-ln\n");
5792
5793         if (!torture_open_connection(&cli, 0)) {
5794                 return false;
5795         }
5796
5797         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5798         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5799
5800         smbXcli_conn_set_sockopt(cli->conn, sockops);
5801
5802         /* Create the file. */
5803         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5804         if (!NT_STATUS_IS_OK(status)) {
5805                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5806                 return false;
5807         }
5808
5809         status = cli_close(cli, fnum);
5810         if (!NT_STATUS_IS_OK(status)) {
5811                 printf("close1 failed (%s)\n", nt_errstr(status));
5812                 return false;
5813         }
5814
5815         /* Now create a hardlink. */
5816         status = cli_hardlink(cli, fname, fname_ln);
5817         if (!NT_STATUS_IS_OK(status)) {
5818                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
5819                 return false;
5820         }
5821
5822         /* Open the original file. */
5823         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
5824                         FILE_ATTRIBUTE_NORMAL,
5825                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5826                         FILE_OPEN_IF, 0, 0, &fnum, NULL);
5827         if (!NT_STATUS_IS_OK(status)) {
5828                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
5829                 return false;
5830         }
5831
5832         /* Unlink the hard link path. */
5833         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
5834                         FILE_ATTRIBUTE_NORMAL,
5835                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5836                         FILE_OPEN_IF, 0, 0, &fnum1, NULL);
5837         if (!NT_STATUS_IS_OK(status)) {
5838                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
5839                 return false;
5840         }
5841         status = cli_nt_delete_on_close(cli, fnum1, true);
5842         if (!NT_STATUS_IS_OK(status)) {
5843                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
5844                         __location__, fname_ln, nt_errstr(status));
5845                 return false;
5846         }
5847
5848         status = cli_close(cli, fnum1);
5849         if (!NT_STATUS_IS_OK(status)) {
5850                 printf("close %s failed (%s)\n",
5851                         fname_ln, nt_errstr(status));
5852                 return false;
5853         }
5854
5855         status = cli_close(cli, fnum);
5856         if (!NT_STATUS_IS_OK(status)) {
5857                 printf("close %s failed (%s)\n",
5858                         fname, nt_errstr(status));
5859                 return false;
5860         }
5861
5862         /* Ensure the original file is still there. */
5863         status = cli_getatr(cli, fname, NULL, NULL, &t);
5864         if (!NT_STATUS_IS_OK(status)) {
5865                 printf("%s getatr on file %s failed (%s)\n",
5866                         __location__,
5867                         fname,
5868                         nt_errstr(status));
5869                 correct = False;
5870         }
5871
5872         /* Ensure the link path is gone. */
5873         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
5874         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5875                 printf("%s, getatr for file %s returned wrong error code %s "
5876                         "- should have been deleted\n",
5877                         __location__,
5878                         fname_ln, nt_errstr(status));
5879                 correct = False;
5880         }
5881
5882         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5883         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5884
5885         if (!torture_close_connection(cli)) {
5886                 correct = false;
5887         }
5888
5889         printf("finished deletetest-ln\n");
5890
5891         return correct;
5892 }
5893
5894 /*
5895   print out server properties
5896  */
5897 static bool run_properties(int dummy)
5898 {
5899         struct cli_state *cli;
5900         bool correct = True;
5901
5902         printf("starting properties test\n");
5903
5904         ZERO_STRUCT(cli);
5905
5906         if (!torture_open_connection(&cli, 0)) {
5907                 return False;
5908         }
5909
5910         smbXcli_conn_set_sockopt(cli->conn, sockops);
5911
5912         d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
5913
5914         if (!torture_close_connection(cli)) {
5915                 correct = False;
5916         }
5917
5918         return correct;
5919 }
5920
5921
5922
5923 /* FIRST_DESIRED_ACCESS   0xf019f */
5924 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
5925                                FILE_READ_EA|                           /* 0xf */ \
5926                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
5927                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
5928                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
5929                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
5930 /* SECOND_DESIRED_ACCESS  0xe0080 */
5931 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
5932                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
5933                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
5934
5935 #if 0
5936 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
5937                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
5938                                FILE_READ_DATA|\
5939                                WRITE_OWNER_ACCESS                      /* */
5940 #endif
5941
5942 /*
5943   Test ntcreate calls made by xcopy
5944  */
5945 static bool run_xcopy(int dummy)
5946 {
5947         static struct cli_state *cli1;
5948         const char *fname = "\\test.txt";
5949         bool correct = True;
5950         uint16_t fnum1, fnum2;
5951         NTSTATUS status;
5952
5953         printf("starting xcopy test\n");
5954
5955         if (!torture_open_connection(&cli1, 0)) {
5956                 return False;
5957         }
5958
5959         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
5960                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
5961                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
5962         if (!NT_STATUS_IS_OK(status)) {
5963                 printf("First open failed - %s\n", nt_errstr(status));
5964                 return False;
5965         }
5966
5967         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
5968                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5969                              FILE_OPEN, 0x200000, 0, &fnum2, NULL);
5970         if (!NT_STATUS_IS_OK(status)) {
5971                 printf("second open failed - %s\n", nt_errstr(status));
5972                 return False;
5973         }
5974
5975         if (!torture_close_connection(cli1)) {
5976                 correct = False;
5977         }
5978
5979         return correct;
5980 }
5981
5982 /*
5983   Test rename on files open with share delete and no share delete.
5984  */
5985 static bool run_rename(int dummy)
5986 {
5987         static struct cli_state *cli1;
5988         const char *fname = "\\test.txt";
5989         const char *fname1 = "\\test1.txt";
5990         bool correct = True;
5991         uint16_t fnum1;
5992         uint16_t attr;
5993         NTSTATUS status;
5994
5995         printf("starting rename test\n");
5996
5997         if (!torture_open_connection(&cli1, 0)) {
5998                 return False;
5999         }
6000
6001         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6002         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6003
6004         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6005                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6006                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6007         if (!NT_STATUS_IS_OK(status)) {
6008                 printf("First open failed - %s\n", nt_errstr(status));
6009                 return False;
6010         }
6011
6012         status = cli_rename(cli1, fname, fname1, false);
6013         if (!NT_STATUS_IS_OK(status)) {
6014                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6015         } else {
6016                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6017                 correct = False;
6018         }
6019
6020         status = cli_close(cli1, fnum1);
6021         if (!NT_STATUS_IS_OK(status)) {
6022                 printf("close - 1 failed (%s)\n", nt_errstr(status));
6023                 return False;
6024         }
6025
6026         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6027         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6028         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6029 #if 0
6030                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
6031 #else
6032                               FILE_SHARE_DELETE|FILE_SHARE_READ,
6033 #endif
6034                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6035         if (!NT_STATUS_IS_OK(status)) {
6036                 printf("Second open failed - %s\n", nt_errstr(status));
6037                 return False;
6038         }
6039
6040         status = cli_rename(cli1, fname, fname1, false);
6041         if (!NT_STATUS_IS_OK(status)) {
6042                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6043                 correct = False;
6044         } else {
6045                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6046         }
6047
6048         status = cli_close(cli1, fnum1);
6049         if (!NT_STATUS_IS_OK(status)) {
6050                 printf("close - 2 failed (%s)\n", nt_errstr(status));
6051                 return False;
6052         }
6053
6054         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6055         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6056
6057         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6058                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6059                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6060         if (!NT_STATUS_IS_OK(status)) {
6061                 printf("Third open failed - %s\n", nt_errstr(status));
6062                 return False;
6063         }
6064
6065
6066 #if 0
6067   {
6068         uint16_t fnum2;
6069
6070         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
6071                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
6072                 printf("Fourth open failed - %s\n", cli_errstr(cli1));
6073                 return False;
6074         }
6075         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
6076                 printf("[8] setting delete_on_close on file failed !\n");
6077                 return False;
6078         }
6079
6080         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
6081                 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
6082                 return False;
6083         }
6084   }
6085 #endif
6086
6087         status = cli_rename(cli1, fname, fname1, false);
6088         if (!NT_STATUS_IS_OK(status)) {
6089                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6090                 correct = False;
6091         } else {
6092                 printf("Third rename succeeded (SHARE_NONE)\n");
6093         }
6094
6095         status = cli_close(cli1, fnum1);
6096         if (!NT_STATUS_IS_OK(status)) {
6097                 printf("close - 3 failed (%s)\n", nt_errstr(status));
6098                 return False;
6099         }
6100
6101         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6102         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6103
6104         /*----*/
6105
6106         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6107                               FILE_ATTRIBUTE_NORMAL,
6108                               FILE_SHARE_READ | FILE_SHARE_WRITE,
6109                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6110         if (!NT_STATUS_IS_OK(status)) {
6111                 printf("Fourth open failed - %s\n", nt_errstr(status));
6112                 return False;
6113         }
6114
6115         status = cli_rename(cli1, fname, fname1, false);
6116         if (!NT_STATUS_IS_OK(status)) {
6117                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6118         } else {
6119                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6120                 correct = False;
6121         }
6122
6123         status = cli_close(cli1, fnum1);
6124         if (!NT_STATUS_IS_OK(status)) {
6125                 printf("close - 4 failed (%s)\n", nt_errstr(status));
6126                 return False;
6127         }
6128
6129         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6130         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6131
6132         /*--*/
6133
6134         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6135                          FILE_ATTRIBUTE_NORMAL,
6136                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6137                          FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6138         if (!NT_STATUS_IS_OK(status)) {
6139                 printf("Fifth open failed - %s\n", nt_errstr(status));
6140                 return False;
6141         }
6142
6143         status = cli_rename(cli1, fname, fname1, false);
6144         if (!NT_STATUS_IS_OK(status)) {
6145                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6146                 correct = False;
6147         } else {
6148                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6149         }
6150
6151         /*
6152          * Now check if the first name still exists ...
6153          */
6154
6155         /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6156                                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6157                                    FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
6158           printf("Opening original file after rename of open file fails: %s\n",
6159               cli_errstr(cli1));
6160         }
6161         else {
6162           printf("Opening original file after rename of open file works ...\n");
6163           (void)cli_close(cli1, fnum2);
6164           } */
6165
6166         /*--*/
6167         status = cli_close(cli1, fnum1);
6168         if (!NT_STATUS_IS_OK(status)) {
6169                 printf("close - 5 failed (%s)\n", nt_errstr(status));
6170                 return False;
6171         }
6172
6173         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6174         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6175         if (!NT_STATUS_IS_OK(status)) {
6176                 printf("getatr on file %s failed - %s ! \n",
6177                         fname1, nt_errstr(status));
6178                 correct = False;
6179         } else {
6180                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6181                         printf("Renamed file %s has wrong attr 0x%x "
6182                                 "(should be 0x%x)\n",
6183                                 fname1,
6184                                 attr,
6185                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6186                         correct = False;
6187                 } else {
6188                         printf("Renamed file %s has archive bit set\n", fname1);
6189                 }
6190         }
6191
6192         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6193         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6194
6195         if (!torture_close_connection(cli1)) {
6196                 correct = False;
6197         }
6198
6199         return correct;
6200 }
6201
6202 /*
6203   Test rename into a directory with an ACL denying it.
6204  */
6205 static bool run_rename_access(int dummy)
6206 {
6207         static struct cli_state *cli = NULL;
6208         static struct cli_state *posix_cli = NULL;
6209         const char *src = "test.txt";
6210         const char *dname = "dir";
6211         const char *dst = "dir\\test.txt";
6212         const char *dsrc = "test.dir";
6213         const char *ddst = "dir\\test.dir";
6214         uint16_t fnum = (uint16_t)-1;
6215         struct security_descriptor *sd = NULL;
6216         struct security_descriptor *newsd = NULL;
6217         NTSTATUS status;
6218         TALLOC_CTX *frame = NULL;
6219
6220         frame = talloc_stackframe();
6221         printf("starting rename access test\n");
6222
6223         /* Windows connection. */
6224         if (!torture_open_connection(&cli, 0)) {
6225                 goto fail;
6226         }
6227
6228         smbXcli_conn_set_sockopt(cli->conn, sockops);
6229
6230         /* Posix connection. */
6231         if (!torture_open_connection(&posix_cli, 0)) {
6232                 goto fail;
6233         }
6234
6235         smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6236
6237         status = torture_setup_unix_extensions(posix_cli);
6238         if (!NT_STATUS_IS_OK(status)) {
6239                 goto fail;
6240         }
6241
6242         /* Start with a clean slate. */
6243         cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6244         cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6245         cli_rmdir(cli, dsrc);
6246         cli_rmdir(cli, ddst);
6247         cli_rmdir(cli, dname);
6248
6249         /*
6250          * Setup the destination directory with a DENY ACE to
6251          * prevent new files within it.
6252          */
6253         status = cli_ntcreate(cli,
6254                                 dname,
6255                                 0,
6256                                 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6257                                         WRITE_DAC_ACCESS|FILE_READ_DATA|
6258                                         WRITE_OWNER_ACCESS,
6259                                 FILE_ATTRIBUTE_DIRECTORY,
6260                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6261                                 FILE_CREATE,
6262                                 FILE_DIRECTORY_FILE,
6263                                 0,
6264                                 &fnum,
6265                                 NULL);
6266         if (!NT_STATUS_IS_OK(status)) {
6267                 printf("Create of %s - %s\n", dname, nt_errstr(status));
6268                 goto fail;
6269         }
6270
6271         status = cli_query_secdesc(cli,
6272                                 fnum,
6273                                 frame,
6274                                 &sd);
6275         if (!NT_STATUS_IS_OK(status)) {
6276                 printf("cli_query_secdesc failed for %s (%s)\n",
6277                         dname, nt_errstr(status));
6278                 goto fail;
6279         }
6280
6281         newsd = security_descriptor_dacl_create(frame,
6282                                         0,
6283                                         NULL,
6284                                         NULL,
6285                                         SID_WORLD,
6286                                         SEC_ACE_TYPE_ACCESS_DENIED,
6287                                         SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6288                                         0,
6289                                         NULL);
6290         if (newsd == NULL) {
6291                 goto fail;
6292         }
6293         sd->dacl = security_acl_concatenate(frame,
6294                                         newsd->dacl,
6295                                         sd->dacl);
6296         if (sd->dacl == NULL) {
6297                 goto fail;
6298         }
6299         status = cli_set_secdesc(cli, fnum, sd);
6300         if (!NT_STATUS_IS_OK(status)) {
6301                 printf("cli_set_secdesc failed for %s (%s)\n",
6302                         dname, nt_errstr(status));
6303                 goto fail;
6304         }
6305         status = cli_close(cli, fnum);
6306         if (!NT_STATUS_IS_OK(status)) {
6307                 printf("close failed for %s (%s)\n",
6308                         dname, nt_errstr(status));
6309                 goto fail;
6310         }
6311         /* Now go around the back and chmod to 777 via POSIX. */
6312         status = cli_posix_chmod(posix_cli, dname, 0777);
6313         if (!NT_STATUS_IS_OK(status)) {
6314                 printf("cli_posix_chmod failed for %s (%s)\n",
6315                         dname, nt_errstr(status));
6316                 goto fail;
6317         }
6318
6319         /* Check we can't create a file within dname via Windows. */
6320         status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6321         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6322                 cli_close(posix_cli, fnum);
6323                 printf("Create of %s should be ACCESS denied, was %s\n",
6324                         dst, nt_errstr(status));
6325                 goto fail;
6326         }
6327
6328         /* Make the sample file/directory. */
6329         status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6330         if (!NT_STATUS_IS_OK(status)) {
6331                 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6332                 goto fail;
6333         }
6334         status = cli_close(cli, fnum);
6335         if (!NT_STATUS_IS_OK(status)) {
6336                 printf("cli_close failed (%s)\n", nt_errstr(status));
6337                 goto fail;
6338         }
6339
6340         status = cli_mkdir(cli, dsrc);
6341         if (!NT_STATUS_IS_OK(status)) {
6342                 printf("cli_mkdir of %s failed (%s)\n",
6343                         dsrc, nt_errstr(status));
6344                 goto fail;
6345         }
6346
6347         /*
6348          * OK - renames of the new file and directory into the
6349          * dst directory should fail.
6350          */
6351
6352         status = cli_rename(cli, src, dst, false);
6353         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6354                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6355                         src, dst, nt_errstr(status));
6356                 goto fail;
6357         }
6358         status = cli_rename(cli, dsrc, ddst, false);
6359         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6360                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6361                         src, dst, nt_errstr(status));
6362                 goto fail;
6363         }
6364
6365         TALLOC_FREE(frame);
6366         return true;
6367
6368   fail:
6369
6370         if (posix_cli) {
6371                 torture_close_connection(posix_cli);
6372         }
6373
6374         if (cli) {
6375                 if (fnum != (uint16_t)-1) {
6376                         cli_close(cli, fnum);
6377                 }
6378                 cli_unlink(cli, src,
6379                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6380                 cli_unlink(cli, dst,
6381                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6382                 cli_rmdir(cli, dsrc);
6383                 cli_rmdir(cli, ddst);
6384                 cli_rmdir(cli, dname);
6385
6386                 torture_close_connection(cli);
6387         }
6388
6389         TALLOC_FREE(frame);
6390         return false;
6391 }
6392
6393 /*
6394   Test owner rights ACE.
6395  */
6396 static bool run_owner_rights(int dummy)
6397 {
6398         static struct cli_state *cli = NULL;
6399         const char *fname = "owner_rights.txt";
6400         uint16_t fnum = (uint16_t)-1;
6401         struct security_descriptor *sd = NULL;
6402         struct security_descriptor *newsd = NULL;
6403         NTSTATUS status;
6404         TALLOC_CTX *frame = NULL;
6405
6406         frame = talloc_stackframe();
6407         printf("starting owner rights test\n");
6408
6409         /* Windows connection. */
6410         if (!torture_open_connection(&cli, 0)) {
6411                 goto fail;
6412         }
6413
6414         smbXcli_conn_set_sockopt(cli->conn, sockops);
6415
6416         /* Start with a clean slate. */
6417         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6418
6419         /* Create the test file. */
6420         /* Now try and open for read and write-dac. */
6421         status = cli_ntcreate(cli,
6422                                 fname,
6423                                 0,
6424                                 GENERIC_ALL_ACCESS,
6425                                 FILE_ATTRIBUTE_NORMAL,
6426                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6427                                         FILE_SHARE_DELETE,
6428                                 FILE_CREATE,
6429                                 0,
6430                                 0,
6431                                 &fnum,
6432                                 NULL);
6433         if (!NT_STATUS_IS_OK(status)) {
6434                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6435                 goto fail;
6436         }
6437
6438         /* Get the original SD. */
6439         status = cli_query_secdesc(cli,
6440                                 fnum,
6441                                 frame,
6442                                 &sd);
6443         if (!NT_STATUS_IS_OK(status)) {
6444                 printf("cli_query_secdesc failed for %s (%s)\n",
6445                         fname, nt_errstr(status));
6446                 goto fail;
6447         }
6448
6449         /*
6450          * Add an "owner-rights" ACE denying WRITE_DATA,
6451          * and an "owner-rights" ACE allowing READ_DATA.
6452          */
6453
6454         newsd = security_descriptor_dacl_create(frame,
6455                                         0,
6456                                         NULL,
6457                                         NULL,
6458                                         SID_OWNER_RIGHTS,
6459                                         SEC_ACE_TYPE_ACCESS_DENIED,
6460                                         FILE_WRITE_DATA,
6461                                         0,
6462                                         SID_OWNER_RIGHTS,
6463                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6464                                         FILE_READ_DATA,
6465                                         0,
6466                                         NULL);
6467         if (newsd == NULL) {
6468                 goto fail;
6469         }
6470         sd->dacl = security_acl_concatenate(frame,
6471                                         newsd->dacl,
6472                                         sd->dacl);
6473         if (sd->dacl == NULL) {
6474                 goto fail;
6475         }
6476         status = cli_set_secdesc(cli, fnum, sd);
6477         if (!NT_STATUS_IS_OK(status)) {
6478                 printf("cli_set_secdesc failed for %s (%s)\n",
6479                         fname, nt_errstr(status));
6480                 goto fail;
6481         }
6482         status = cli_close(cli, fnum);
6483         if (!NT_STATUS_IS_OK(status)) {
6484                 printf("close failed for %s (%s)\n",
6485                         fname, nt_errstr(status));
6486                 goto fail;
6487         }
6488         fnum = (uint16_t)-1;
6489
6490         /* Try and open for FILE_WRITE_DATA */
6491         status = cli_ntcreate(cli,
6492                                 fname,
6493                                 0,
6494                                 FILE_WRITE_DATA,
6495                                 FILE_ATTRIBUTE_NORMAL,
6496                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6497                                         FILE_SHARE_DELETE,
6498                                 FILE_OPEN,
6499                                 0,
6500                                 0,
6501                                 &fnum,
6502                                 NULL);
6503         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6504                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6505                 goto fail;
6506         }
6507
6508         /* Now try and open for FILE_READ_DATA */
6509         status = cli_ntcreate(cli,
6510                                 fname,
6511                                 0,
6512                                 FILE_READ_DATA,
6513                                 FILE_ATTRIBUTE_NORMAL,
6514                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6515                                         FILE_SHARE_DELETE,
6516                                 FILE_OPEN,
6517                                 0,
6518                                 0,
6519                                 &fnum,
6520                                 NULL);
6521         if (!NT_STATUS_IS_OK(status)) {
6522                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6523                 goto fail;
6524         }
6525
6526         status = cli_close(cli, fnum);
6527         if (!NT_STATUS_IS_OK(status)) {
6528                 printf("close failed for %s (%s)\n",
6529                         fname, nt_errstr(status));
6530                 goto fail;
6531         }
6532
6533         /* Restore clean slate. */
6534         TALLOC_FREE(sd);
6535         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6536
6537         /* Create the test file. */
6538         status = cli_ntcreate(cli,
6539                                 fname,
6540                                 0,
6541                                 GENERIC_ALL_ACCESS,
6542                                 FILE_ATTRIBUTE_NORMAL,
6543                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6544                                         FILE_SHARE_DELETE,
6545                                 FILE_CREATE,
6546                                 0,
6547                                 0,
6548                                 &fnum,
6549                                 NULL);
6550         if (!NT_STATUS_IS_OK(status)) {
6551                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6552                 goto fail;
6553         }
6554
6555         /* Get the original SD. */
6556         status = cli_query_secdesc(cli,
6557                                 fnum,
6558                                 frame,
6559                                 &sd);
6560         if (!NT_STATUS_IS_OK(status)) {
6561                 printf("cli_query_secdesc failed for %s (%s)\n",
6562                         fname, nt_errstr(status));
6563                 goto fail;
6564         }
6565
6566         /*
6567          * Add an "owner-rights ACE denying WRITE_DATA,
6568          * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6569          */
6570
6571         newsd = security_descriptor_dacl_create(frame,
6572                                         0,
6573                                         NULL,
6574                                         NULL,
6575                                         SID_OWNER_RIGHTS,
6576                                         SEC_ACE_TYPE_ACCESS_DENIED,
6577                                         FILE_WRITE_DATA,
6578                                         0,
6579                                         SID_OWNER_RIGHTS,
6580                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6581                                         FILE_READ_DATA|FILE_WRITE_DATA,
6582                                         0,
6583                                         NULL);
6584         if (newsd == NULL) {
6585                 goto fail;
6586         }
6587         sd->dacl = security_acl_concatenate(frame,
6588                                         newsd->dacl,
6589                                         sd->dacl);
6590         if (sd->dacl == NULL) {
6591                 goto fail;
6592         }
6593         status = cli_set_secdesc(cli, fnum, sd);
6594         if (!NT_STATUS_IS_OK(status)) {
6595                 printf("cli_set_secdesc failed for %s (%s)\n",
6596                         fname, nt_errstr(status));
6597                 goto fail;
6598         }
6599         status = cli_close(cli, fnum);
6600         if (!NT_STATUS_IS_OK(status)) {
6601                 printf("close failed for %s (%s)\n",
6602                         fname, nt_errstr(status));
6603                 goto fail;
6604         }
6605         fnum = (uint16_t)-1;
6606
6607         /* Try and open for FILE_WRITE_DATA */
6608         status = cli_ntcreate(cli,
6609                                 fname,
6610                                 0,
6611                                 FILE_WRITE_DATA,
6612                                 FILE_ATTRIBUTE_NORMAL,
6613                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6614                                         FILE_SHARE_DELETE,
6615                                 FILE_OPEN,
6616                                 0,
6617                                 0,
6618                                 &fnum,
6619                                 NULL);
6620         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6621                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6622                 goto fail;
6623         }
6624
6625         /* Now try and open for FILE_READ_DATA */
6626         status = cli_ntcreate(cli,
6627                                 fname,
6628                                 0,
6629                                 FILE_READ_DATA,
6630                                 FILE_ATTRIBUTE_NORMAL,
6631                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6632                                         FILE_SHARE_DELETE,
6633                                 FILE_OPEN,
6634                                 0,
6635                                 0,
6636                                 &fnum,
6637                                 NULL);
6638         if (!NT_STATUS_IS_OK(status)) {
6639                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6640                 goto fail;
6641         }
6642
6643         status = cli_close(cli, fnum);
6644         if (!NT_STATUS_IS_OK(status)) {
6645                 printf("close failed for %s (%s)\n",
6646                         fname, nt_errstr(status));
6647                 goto fail;
6648         }
6649
6650         /* Restore clean slate. */
6651         TALLOC_FREE(sd);
6652         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6653
6654
6655         /* Create the test file. */
6656         status = cli_ntcreate(cli,
6657                                 fname,
6658                                 0,
6659                                 GENERIC_ALL_ACCESS,
6660                                 FILE_ATTRIBUTE_NORMAL,
6661                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6662                                         FILE_SHARE_DELETE,
6663                                 FILE_CREATE,
6664                                 0,
6665                                 0,
6666                                 &fnum,
6667                                 NULL);
6668         if (!NT_STATUS_IS_OK(status)) {
6669                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6670                 goto fail;
6671         }
6672
6673         /* Get the original SD. */
6674         status = cli_query_secdesc(cli,
6675                                 fnum,
6676                                 frame,
6677                                 &sd);
6678         if (!NT_STATUS_IS_OK(status)) {
6679                 printf("cli_query_secdesc failed for %s (%s)\n",
6680                         fname, nt_errstr(status));
6681                 goto fail;
6682         }
6683
6684         /*
6685          * Add an "authenticated users" ACE allowing READ_DATA,
6686          * add an "owner-rights" denying READ_DATA,
6687          * and an "authenticated users" ACE allowing WRITE_DATA.
6688          */
6689
6690         newsd = security_descriptor_dacl_create(frame,
6691                                         0,
6692                                         NULL,
6693                                         NULL,
6694                                         SID_NT_AUTHENTICATED_USERS,
6695                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6696                                         FILE_READ_DATA,
6697                                         0,
6698                                         SID_OWNER_RIGHTS,
6699                                         SEC_ACE_TYPE_ACCESS_DENIED,
6700                                         FILE_READ_DATA,
6701                                         0,
6702                                         SID_NT_AUTHENTICATED_USERS,
6703                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6704                                         FILE_WRITE_DATA,
6705                                         0,
6706                                         NULL);
6707         if (newsd == NULL) {
6708                 printf("newsd == NULL\n");
6709                 goto fail;
6710         }
6711         sd->dacl = security_acl_concatenate(frame,
6712                                         newsd->dacl,
6713                                         sd->dacl);
6714         if (sd->dacl == NULL) {
6715                 printf("sd->dacl == NULL\n");
6716                 goto fail;
6717         }
6718         status = cli_set_secdesc(cli, fnum, sd);
6719         if (!NT_STATUS_IS_OK(status)) {
6720                 printf("cli_set_secdesc failed for %s (%s)\n",
6721                         fname, nt_errstr(status));
6722                 goto fail;
6723         }
6724         status = cli_close(cli, fnum);
6725         if (!NT_STATUS_IS_OK(status)) {
6726                 printf("close failed for %s (%s)\n",
6727                         fname, nt_errstr(status));
6728                 goto fail;
6729         }
6730         fnum = (uint16_t)-1;
6731
6732         /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
6733         status = cli_ntcreate(cli,
6734                                 fname,
6735                                 0,
6736                                 FILE_READ_DATA|FILE_WRITE_DATA,
6737                                 FILE_ATTRIBUTE_NORMAL,
6738                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6739                                         FILE_SHARE_DELETE,
6740                                 FILE_OPEN,
6741                                 0,
6742                                 0,
6743                                 &fnum,
6744                                 NULL);
6745         if (!NT_STATUS_IS_OK(status)) {
6746                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6747                 goto fail;
6748         }
6749
6750         status = cli_close(cli, fnum);
6751         if (!NT_STATUS_IS_OK(status)) {
6752                 printf("close failed for %s (%s)\n",
6753                         fname, nt_errstr(status));
6754                 goto fail;
6755         }
6756
6757         cli_unlink(cli, fname,
6758                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6759
6760         TALLOC_FREE(frame);
6761         return true;
6762
6763   fail:
6764
6765         if (cli) {
6766                 if (fnum != (uint16_t)-1) {
6767                         cli_close(cli, fnum);
6768                 }
6769                 cli_unlink(cli, fname,
6770                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6771                 torture_close_connection(cli);
6772         }
6773
6774         TALLOC_FREE(frame);
6775         return false;
6776 }
6777
6778 static bool run_pipe_number(int dummy)
6779 {
6780         struct cli_state *cli1;
6781         const char *pipe_name = "\\SPOOLSS";
6782         uint16_t fnum;
6783         int num_pipes = 0;
6784         NTSTATUS status;
6785
6786         printf("starting pipenumber test\n");
6787         if (!torture_open_connection(&cli1, 0)) {
6788                 return False;
6789         }
6790
6791         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6792         while(1) {
6793                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
6794                                       FILE_ATTRIBUTE_NORMAL,
6795                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
6796                                       FILE_OPEN_IF, 0, 0, &fnum, NULL);
6797                 if (!NT_STATUS_IS_OK(status)) {
6798                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
6799                         break;
6800                 }
6801                 num_pipes++;
6802                 printf("\r%6d", num_pipes);
6803         }
6804
6805         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
6806         torture_close_connection(cli1);
6807         return True;
6808 }
6809
6810 /*
6811   Test open mode returns on read-only files.
6812  */
6813 static bool run_opentest(int dummy)
6814 {
6815         static struct cli_state *cli1;
6816         static struct cli_state *cli2;
6817         const char *fname = "\\readonly.file";
6818         uint16_t fnum1, fnum2;
6819         char buf[20];
6820         off_t fsize;
6821         bool correct = True;
6822         char *tmp_path;
6823         NTSTATUS status;
6824
6825         printf("starting open test\n");
6826
6827         if (!torture_open_connection(&cli1, 0)) {
6828                 return False;
6829         }
6830
6831         cli_setatr(cli1, fname, 0, 0);
6832         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6833
6834         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6835
6836         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
6837         if (!NT_STATUS_IS_OK(status)) {
6838                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6839                 return False;
6840         }
6841
6842         status = cli_close(cli1, fnum1);
6843         if (!NT_STATUS_IS_OK(status)) {
6844                 printf("close2 failed (%s)\n", nt_errstr(status));
6845                 return False;
6846         }
6847
6848         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
6849         if (!NT_STATUS_IS_OK(status)) {
6850                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
6851                 return False;
6852         }
6853
6854         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
6855         if (!NT_STATUS_IS_OK(status)) {
6856                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6857                 return False;
6858         }
6859
6860         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
6861         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
6862
6863         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
6864                         NT_STATUS_ACCESS_DENIED)) {
6865                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
6866         }
6867
6868         printf("finished open test 1\n");
6869
6870         cli_close(cli1, fnum1);
6871
6872         /* Now try not readonly and ensure ERRbadshare is returned. */
6873
6874         cli_setatr(cli1, fname, 0, 0);
6875
6876         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
6877         if (!NT_STATUS_IS_OK(status)) {
6878                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6879                 return False;
6880         }
6881
6882         /* This will fail - but the error should be ERRshare. */
6883         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
6884
6885         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
6886                         NT_STATUS_SHARING_VIOLATION)) {
6887                 printf("correct error code ERRDOS/ERRbadshare returned\n");
6888         }
6889
6890         status = cli_close(cli1, fnum1);
6891         if (!NT_STATUS_IS_OK(status)) {
6892                 printf("close2 failed (%s)\n", nt_errstr(status));
6893                 return False;
6894         }
6895
6896         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6897
6898         printf("finished open test 2\n");
6899
6900         /* Test truncate open disposition on file opened for read. */
6901         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
6902         if (!NT_STATUS_IS_OK(status)) {
6903                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
6904                 return False;
6905         }
6906
6907         /* write 20 bytes. */
6908
6909         memset(buf, '\0', 20);
6910
6911         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
6912         if (!NT_STATUS_IS_OK(status)) {
6913                 printf("write failed (%s)\n", nt_errstr(status));
6914                 correct = False;
6915         }
6916
6917         status = cli_close(cli1, fnum1);
6918         if (!NT_STATUS_IS_OK(status)) {
6919                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
6920                 return False;
6921         }
6922
6923         /* Ensure size == 20. */
6924         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
6925         if (!NT_STATUS_IS_OK(status)) {
6926                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
6927                 return False;
6928         }
6929
6930         if (fsize != 20) {
6931                 printf("(3) file size != 20\n");
6932                 return False;
6933         }
6934
6935         /* Now test if we can truncate a file opened for readonly. */
6936         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
6937         if (!NT_STATUS_IS_OK(status)) {
6938                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
6939                 return False;
6940         }
6941
6942         status = cli_close(cli1, fnum1);
6943         if (!NT_STATUS_IS_OK(status)) {
6944                 printf("close2 failed (%s)\n", nt_errstr(status));
6945                 return False;
6946         }
6947
6948         /* Ensure size == 0. */
6949         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
6950         if (!NT_STATUS_IS_OK(status)) {
6951                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
6952                 return False;
6953         }
6954
6955         if (fsize != 0) {
6956                 printf("(3) file size != 0\n");
6957                 return False;
6958         }
6959         printf("finished open test 3\n");
6960
6961         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6962
6963         printf("Do ctemp tests\n");
6964         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
6965         if (!NT_STATUS_IS_OK(status)) {
6966                 printf("ctemp failed (%s)\n", nt_errstr(status));
6967                 return False;
6968         }
6969
6970         printf("ctemp gave path %s\n", tmp_path);
6971         status = cli_close(cli1, fnum1);
6972         if (!NT_STATUS_IS_OK(status)) {
6973                 printf("close of temp failed (%s)\n", nt_errstr(status));
6974         }
6975
6976         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6977         if (!NT_STATUS_IS_OK(status)) {
6978                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
6979         }
6980
6981         /* Test the non-io opens... */
6982
6983         if (!torture_open_connection(&cli2, 1)) {
6984                 return False;
6985         }
6986
6987         cli_setatr(cli2, fname, 0, 0);
6988         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6989
6990         smbXcli_conn_set_sockopt(cli2->conn, sockops);
6991
6992         printf("TEST #1 testing 2 non-io opens (no delete)\n");
6993         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
6994                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6995                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6996         if (!NT_STATUS_IS_OK(status)) {
6997                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
6998                 return False;
6999         }
7000
7001         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7002                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7003                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7004         if (!NT_STATUS_IS_OK(status)) {
7005                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7006                 return False;
7007         }
7008
7009         status = cli_close(cli1, fnum1);
7010         if (!NT_STATUS_IS_OK(status)) {
7011                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7012                 return False;
7013         }
7014
7015         status = cli_close(cli2, fnum2);
7016         if (!NT_STATUS_IS_OK(status)) {
7017                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7018                 return False;
7019         }
7020
7021         printf("non-io open test #1 passed.\n");
7022
7023         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7024
7025         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7026
7027         status = cli_ntcreate(cli1, fname, 0,
7028                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7029                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7030                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7031         if (!NT_STATUS_IS_OK(status)) {
7032                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7033                 return False;
7034         }
7035
7036         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7037                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7038                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7039         if (!NT_STATUS_IS_OK(status)) {
7040                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7041                 return False;
7042         }
7043
7044         status = cli_close(cli1, fnum1);
7045         if (!NT_STATUS_IS_OK(status)) {
7046                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7047                 return False;
7048         }
7049
7050         status = cli_close(cli2, fnum2);
7051         if (!NT_STATUS_IS_OK(status)) {
7052                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7053                 return False;
7054         }
7055
7056         printf("non-io open test #2 passed.\n");
7057
7058         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7059
7060         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7061
7062         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7063                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7064                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7065         if (!NT_STATUS_IS_OK(status)) {
7066                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7067                 return False;
7068         }
7069
7070         status = cli_ntcreate(cli2, fname, 0,
7071                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7072                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7073                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7074         if (!NT_STATUS_IS_OK(status)) {
7075                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7076                 return False;
7077         }
7078
7079         status = cli_close(cli1, fnum1);
7080         if (!NT_STATUS_IS_OK(status)) {
7081                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7082                 return False;
7083         }
7084
7085         status = cli_close(cli2, fnum2);
7086         if (!NT_STATUS_IS_OK(status)) {
7087                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7088                 return False;
7089         }
7090
7091         printf("non-io open test #3 passed.\n");
7092
7093         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7094
7095         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7096
7097         status = cli_ntcreate(cli1, fname, 0,
7098                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7099                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7100                                FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7101         if (!NT_STATUS_IS_OK(status)) {
7102                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7103                 return False;
7104         }
7105
7106         status = cli_ntcreate(cli2, fname, 0,
7107                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7108                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7109                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7110         if (NT_STATUS_IS_OK(status)) {
7111                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7112                 return False;
7113         }
7114
7115         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7116
7117         status = cli_close(cli1, fnum1);
7118         if (!NT_STATUS_IS_OK(status)) {
7119                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7120                 return False;
7121         }
7122
7123         printf("non-io open test #4 passed.\n");
7124
7125         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7126
7127         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7128
7129         status = cli_ntcreate(cli1, fname, 0,
7130                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7131                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7132                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7133         if (!NT_STATUS_IS_OK(status)) {
7134                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7135                 return False;
7136         }
7137
7138         status = cli_ntcreate(cli2, fname, 0,
7139                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7140                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7141                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7142         if (!NT_STATUS_IS_OK(status)) {
7143                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7144                 return False;
7145         }
7146
7147         status = cli_close(cli1, fnum1);
7148         if (!NT_STATUS_IS_OK(status)) {
7149                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7150                 return False;
7151         }
7152
7153         status = cli_close(cli2, fnum2);
7154         if (!NT_STATUS_IS_OK(status)) {
7155                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7156                 return False;
7157         }
7158
7159         printf("non-io open test #5 passed.\n");
7160
7161         printf("TEST #6 testing 1 non-io open, one io open\n");
7162
7163         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7164
7165         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7166                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7167                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7168         if (!NT_STATUS_IS_OK(status)) {
7169                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7170                 return False;
7171         }
7172
7173         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7174                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7175                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7176         if (!NT_STATUS_IS_OK(status)) {
7177                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7178                 return False;
7179         }
7180
7181         status = cli_close(cli1, fnum1);
7182         if (!NT_STATUS_IS_OK(status)) {
7183                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7184                 return False;
7185         }
7186
7187         status = cli_close(cli2, fnum2);
7188         if (!NT_STATUS_IS_OK(status)) {
7189                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7190                 return False;
7191         }
7192
7193         printf("non-io open test #6 passed.\n");
7194
7195         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7196
7197         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7198
7199         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7200                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7201                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7202         if (!NT_STATUS_IS_OK(status)) {
7203                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7204                 return False;
7205         }
7206
7207         status = cli_ntcreate(cli2, fname, 0,
7208                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7209                               FILE_ATTRIBUTE_NORMAL,
7210                               FILE_SHARE_READ|FILE_SHARE_DELETE,
7211                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7212         if (NT_STATUS_IS_OK(status)) {
7213                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7214                 return False;
7215         }
7216
7217         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7218
7219         status = cli_close(cli1, fnum1);
7220         if (!NT_STATUS_IS_OK(status)) {
7221                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7222                 return False;
7223         }
7224
7225         printf("non-io open test #7 passed.\n");
7226
7227         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7228
7229         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7230         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7231                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7232                                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7233         if (!NT_STATUS_IS_OK(status)) {
7234                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7235                 correct = false;
7236                 goto out;
7237         }
7238
7239         /* Write to ensure we have to update the file time. */
7240         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7241                               NULL);
7242         if (!NT_STATUS_IS_OK(status)) {
7243                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7244                 correct = false;
7245                 goto out;
7246         }
7247
7248         status = cli_close(cli1, fnum1);
7249         if (!NT_STATUS_IS_OK(status)) {
7250                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7251                 correct = false;
7252         }
7253
7254   out:
7255
7256         if (!torture_close_connection(cli1)) {
7257                 correct = False;
7258         }
7259         if (!torture_close_connection(cli2)) {
7260                 correct = False;
7261         }
7262
7263         return correct;
7264 }
7265
7266 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7267 {
7268         uint16_t major, minor;
7269         uint32_t caplow, caphigh;
7270         NTSTATUS status;
7271
7272         if (!SERVER_HAS_UNIX_CIFS(cli)) {
7273                 printf("Server doesn't support UNIX CIFS extensions.\n");
7274                 return NT_STATUS_NOT_SUPPORTED;
7275         }
7276
7277         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7278                                              &caphigh);
7279         if (!NT_STATUS_IS_OK(status)) {
7280                 printf("Server didn't return UNIX CIFS extensions: %s\n",
7281                        nt_errstr(status));
7282                 return status;
7283         }
7284
7285         status = cli_set_unix_extensions_capabilities(cli, major, minor,
7286                                                       caplow, caphigh);
7287         if (!NT_STATUS_IS_OK(status)) {
7288                 printf("Server doesn't support setting UNIX CIFS extensions: "
7289                        "%s.\n", nt_errstr(status));
7290                 return status;
7291         }
7292
7293         return NT_STATUS_OK;
7294 }
7295
7296 /*
7297   Test POSIX open /mkdir calls.
7298  */
7299 static bool run_simple_posix_open_test(int dummy)
7300 {
7301         static struct cli_state *cli1;
7302         const char *fname = "posix:file";
7303         const char *hname = "posix:hlink";
7304         const char *sname = "posix:symlink";
7305         const char *dname = "posix:dir";
7306         char buf[10];
7307         char *target = NULL;
7308         uint16_t fnum1 = (uint16_t)-1;
7309         SMB_STRUCT_STAT sbuf;
7310         bool correct = false;
7311         NTSTATUS status;
7312         size_t nread;
7313         const char *fname_windows = "windows_file";
7314         uint16_t fnum2 = (uint16_t)-1;
7315
7316         printf("Starting simple POSIX open test\n");
7317
7318         if (!torture_open_connection(&cli1, 0)) {
7319                 return false;
7320         }
7321
7322         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7323
7324         status = torture_setup_unix_extensions(cli1);
7325         if (!NT_STATUS_IS_OK(status)) {
7326                 return false;
7327         }
7328
7329         cli_setatr(cli1, fname, 0, 0);
7330         cli_posix_unlink(cli1, fname);
7331         cli_setatr(cli1, dname, 0, 0);
7332         cli_posix_rmdir(cli1, dname);
7333         cli_setatr(cli1, hname, 0, 0);
7334         cli_posix_unlink(cli1, hname);
7335         cli_setatr(cli1, sname, 0, 0);
7336         cli_posix_unlink(cli1, sname);
7337         cli_setatr(cli1, fname_windows, 0, 0);
7338         cli_posix_unlink(cli1, fname_windows);
7339
7340         /* Create a directory. */
7341         status = cli_posix_mkdir(cli1, dname, 0777);
7342         if (!NT_STATUS_IS_OK(status)) {
7343                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7344                 goto out;
7345         }
7346
7347         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7348                                 0600, &fnum1);
7349         if (!NT_STATUS_IS_OK(status)) {
7350                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7351                 goto out;
7352         }
7353
7354         /* Test ftruncate - set file size. */
7355         status = cli_ftruncate(cli1, fnum1, 1000);
7356         if (!NT_STATUS_IS_OK(status)) {
7357                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7358                 goto out;
7359         }
7360
7361         /* Ensure st_size == 1000 */
7362         status = cli_posix_stat(cli1, fname, &sbuf);
7363         if (!NT_STATUS_IS_OK(status)) {
7364                 printf("stat failed (%s)\n", nt_errstr(status));
7365                 goto out;
7366         }
7367
7368         if (sbuf.st_ex_size != 1000) {
7369                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7370                 goto out;
7371         }
7372
7373         /* Ensure st_mode == 0600 */
7374         if ((sbuf.st_ex_mode & 07777) != 0600) {
7375                 printf("posix_open - bad permissions 0%o != 0600\n",
7376                                 (unsigned int)(sbuf.st_ex_mode & 07777));
7377                 goto out;
7378         }
7379
7380         /* Test ftruncate - set file size back to zero. */
7381         status = cli_ftruncate(cli1, fnum1, 0);
7382         if (!NT_STATUS_IS_OK(status)) {
7383                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7384                 goto out;
7385         }
7386
7387         status = cli_close(cli1, fnum1);
7388         if (!NT_STATUS_IS_OK(status)) {
7389                 printf("close failed (%s)\n", nt_errstr(status));
7390                 goto out;
7391         }
7392
7393         /* Now open the file again for read only. */
7394         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7395         if (!NT_STATUS_IS_OK(status)) {
7396                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7397                 goto out;
7398         }
7399
7400         /* Now unlink while open. */
7401         status = cli_posix_unlink(cli1, fname);
7402         if (!NT_STATUS_IS_OK(status)) {
7403                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7404                 goto out;
7405         }
7406
7407         status = cli_close(cli1, fnum1);
7408         if (!NT_STATUS_IS_OK(status)) {
7409                 printf("close(2) failed (%s)\n", nt_errstr(status));
7410                 goto out;
7411         }
7412
7413         /* Ensure the file has gone. */
7414         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7415         if (NT_STATUS_IS_OK(status)) {
7416                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7417                 goto out;
7418         }
7419
7420         /* Create again to test open with O_TRUNC. */
7421         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7422         if (!NT_STATUS_IS_OK(status)) {
7423                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7424                 goto out;
7425         }
7426
7427         /* Test ftruncate - set file size. */
7428         status = cli_ftruncate(cli1, fnum1, 1000);
7429         if (!NT_STATUS_IS_OK(status)) {
7430                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7431                 goto out;
7432         }
7433
7434         /* Ensure st_size == 1000 */
7435         status = cli_posix_stat(cli1, fname, &sbuf);
7436         if (!NT_STATUS_IS_OK(status)) {
7437                 printf("stat failed (%s)\n", nt_errstr(status));
7438                 goto out;
7439         }
7440
7441         if (sbuf.st_ex_size != 1000) {
7442                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7443                 goto out;
7444         }
7445
7446         status = cli_close(cli1, fnum1);
7447         if (!NT_STATUS_IS_OK(status)) {
7448                 printf("close(2) failed (%s)\n", nt_errstr(status));
7449                 goto out;
7450         }
7451
7452         /* Re-open with O_TRUNC. */
7453         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7454         if (!NT_STATUS_IS_OK(status)) {
7455                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7456                 goto out;
7457         }
7458
7459         /* Ensure st_size == 0 */
7460         status = cli_posix_stat(cli1, fname, &sbuf);
7461         if (!NT_STATUS_IS_OK(status)) {
7462                 printf("stat failed (%s)\n", nt_errstr(status));
7463                 goto out;
7464         }
7465
7466         if (sbuf.st_ex_size != 0) {
7467                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7468                 goto out;
7469         }
7470
7471         status = cli_close(cli1, fnum1);
7472         if (!NT_STATUS_IS_OK(status)) {
7473                 printf("close failed (%s)\n", nt_errstr(status));
7474                 goto out;
7475         }
7476
7477         status = cli_posix_unlink(cli1, fname);
7478         if (!NT_STATUS_IS_OK(status)) {
7479                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7480                 goto out;
7481         }
7482
7483         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
7484         if (!NT_STATUS_IS_OK(status)) {
7485                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
7486                         dname, nt_errstr(status));
7487                 goto out;
7488         }
7489
7490         cli_close(cli1, fnum1);
7491
7492         /* What happens when we try and POSIX open a directory for write ? */
7493         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
7494         if (NT_STATUS_IS_OK(status)) {
7495                 printf("POSIX open of directory %s succeeded, "
7496                        "should have failed.\n",
7497                        dname);
7498                 goto out;
7499         } else {
7500                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
7501                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
7502                         goto out;
7503                 }
7504         }
7505
7506         /* Create the file. */
7507         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7508                                 0600, &fnum1);
7509         if (!NT_STATUS_IS_OK(status)) {
7510                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7511                 goto out;
7512         }
7513
7514         /* Write some data into it. */
7515         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7516                               NULL);
7517         if (!NT_STATUS_IS_OK(status)) {
7518                 printf("cli_write failed: %s\n", nt_errstr(status));
7519                 goto out;
7520         }
7521
7522         cli_close(cli1, fnum1);
7523
7524         /* Now create a hardlink. */
7525         status = cli_posix_hardlink(cli1, fname, hname);
7526         if (!NT_STATUS_IS_OK(status)) {
7527                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
7528                 goto out;
7529         }
7530
7531         /* Now create a symlink. */
7532         status = cli_posix_symlink(cli1, fname, sname);
7533         if (!NT_STATUS_IS_OK(status)) {
7534                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
7535                 goto out;
7536         }
7537
7538         /* Open the hardlink for read. */
7539         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
7540         if (!NT_STATUS_IS_OK(status)) {
7541                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
7542                 goto out;
7543         }
7544
7545         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
7546         if (!NT_STATUS_IS_OK(status)) {
7547                 printf("POSIX read of %s failed (%s)\n", hname,
7548                        nt_errstr(status));
7549                 goto out;
7550         } else if (nread != 10) {
7551                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
7552                        hname, (unsigned long)nread, 10);
7553                 goto out;
7554         }
7555
7556         if (memcmp(buf, "TEST DATA\n", 10)) {
7557                 printf("invalid data read from hardlink\n");
7558                 goto out;
7559         }
7560
7561         /* Do a POSIX lock/unlock. */
7562         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
7563         if (!NT_STATUS_IS_OK(status)) {
7564                 printf("POSIX lock failed %s\n", nt_errstr(status));
7565                 goto out;
7566         }
7567
7568         /* Punch a hole in the locked area. */
7569         status = cli_posix_unlock(cli1, fnum1, 10, 80);
7570         if (!NT_STATUS_IS_OK(status)) {
7571                 printf("POSIX unlock failed %s\n", nt_errstr(status));
7572                 goto out;
7573         }
7574
7575         cli_close(cli1, fnum1);
7576
7577         /* Open the symlink for read - this should fail. A POSIX
7578            client should not be doing opens on a symlink. */
7579         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
7580         if (NT_STATUS_IS_OK(status)) {
7581                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
7582                 goto out;
7583         } else {
7584                 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
7585                                 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
7586                         printf("POSIX open of %s should have failed "
7587                                 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
7588                                 "failed with %s instead.\n",
7589                                 sname, nt_errstr(status));
7590                         goto out;
7591                 }
7592         }
7593
7594         status = cli_posix_readlink(cli1, sname, talloc_tos(), &target);
7595         if (!NT_STATUS_IS_OK(status)) {
7596                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
7597                 goto out;
7598         }
7599
7600         if (strcmp(target, fname) != 0) {
7601                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
7602                         sname, fname, target);
7603                 goto out;
7604         }
7605
7606         status = cli_posix_rmdir(cli1, dname);
7607         if (!NT_STATUS_IS_OK(status)) {
7608                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
7609                 goto out;
7610         }
7611
7612         /* Check directory opens with a specific permission. */
7613         status = cli_posix_mkdir(cli1, dname, 0700);
7614         if (!NT_STATUS_IS_OK(status)) {
7615                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7616                 goto out;
7617         }
7618
7619         /* Ensure st_mode == 0700 */
7620         status = cli_posix_stat(cli1, dname, &sbuf);
7621         if (!NT_STATUS_IS_OK(status)) {
7622                 printf("stat failed (%s)\n", nt_errstr(status));
7623                 goto out;
7624         }
7625
7626         if ((sbuf.st_ex_mode & 07777) != 0700) {
7627                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
7628                                 (unsigned int)(sbuf.st_ex_mode & 07777));
7629                 goto out;
7630         }
7631
7632         /*
7633          * Now create a Windows file, and attempt a POSIX unlink.
7634          * This should fail with a sharing violation but due to:
7635          *
7636          * [Bug 9571] Unlink after open causes smbd to panic
7637          *
7638          * ensure we've fixed the lock ordering violation.
7639          */
7640
7641         status = cli_ntcreate(cli1, fname_windows, 0,
7642                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
7643                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7644                         FILE_CREATE,
7645                         0x0, 0x0, &fnum2, NULL);
7646         if (!NT_STATUS_IS_OK(status)) {
7647                 printf("Windows create of %s failed (%s)\n", fname_windows,
7648                         nt_errstr(status));
7649                 goto out;
7650         }
7651
7652         /* Now try posix_unlink. */
7653         status = cli_posix_unlink(cli1, fname_windows);
7654         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7655                 printf("POSIX unlink of %s should fail "
7656                         "with NT_STATUS_SHARING_VIOLATION "
7657                         "got %s instead !\n",
7658                         fname_windows,
7659                         nt_errstr(status));
7660                 goto out;
7661         }
7662
7663         cli_close(cli1, fnum2);
7664
7665         printf("Simple POSIX open test passed\n");
7666         correct = true;
7667
7668   out:
7669
7670         if (fnum1 != (uint16_t)-1) {
7671                 cli_close(cli1, fnum1);
7672                 fnum1 = (uint16_t)-1;
7673         }
7674
7675         if (fnum2 != (uint16_t)-1) {
7676                 cli_close(cli1, fnum2);
7677                 fnum2 = (uint16_t)-1;
7678         }
7679
7680         cli_setatr(cli1, sname, 0, 0);
7681         cli_posix_unlink(cli1, sname);
7682         cli_setatr(cli1, hname, 0, 0);
7683         cli_posix_unlink(cli1, hname);
7684         cli_setatr(cli1, fname, 0, 0);
7685         cli_posix_unlink(cli1, fname);
7686         cli_setatr(cli1, dname, 0, 0);
7687         cli_posix_rmdir(cli1, dname);
7688         cli_setatr(cli1, fname_windows, 0, 0);
7689         cli_posix_unlink(cli1, fname_windows);
7690
7691         if (!torture_close_connection(cli1)) {
7692                 correct = false;
7693         }
7694
7695         return correct;
7696 }
7697
7698 /*
7699   Test POSIX and Windows ACLs are rejected on symlinks.
7700  */
7701 static bool run_acl_symlink_test(int dummy)
7702 {
7703         static struct cli_state *cli;
7704         const char *fname = "posix_file";
7705         const char *sname = "posix_symlink";
7706         uint16_t fnum = (uint16_t)-1;
7707         bool correct = false;
7708         NTSTATUS status;
7709         char *posix_acl = NULL;
7710         size_t posix_acl_len = 0;
7711         char *posix_acl_sym = NULL;
7712         size_t posix_acl_len_sym = 0;
7713         struct security_descriptor *sd = NULL;
7714         struct security_descriptor *sd_sym = NULL;
7715         TALLOC_CTX *frame = NULL;
7716
7717         frame = talloc_stackframe();
7718
7719         printf("Starting acl symlink test\n");
7720
7721         if (!torture_open_connection(&cli, 0)) {
7722                 TALLOC_FREE(frame);
7723                 return false;
7724         }
7725
7726         smbXcli_conn_set_sockopt(cli->conn, sockops);
7727
7728         status = torture_setup_unix_extensions(cli);
7729         if (!NT_STATUS_IS_OK(status)) {
7730                 TALLOC_FREE(frame);
7731                 return false;
7732         }
7733
7734         cli_setatr(cli, fname, 0, 0);
7735         cli_posix_unlink(cli, fname);
7736         cli_setatr(cli, sname, 0, 0);
7737         cli_posix_unlink(cli, sname);
7738
7739         status = cli_ntcreate(cli,
7740                         fname,
7741                         0,
7742                         READ_CONTROL_ACCESS,
7743                         0,
7744                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7745                         FILE_CREATE,
7746                         0x0,
7747                         0x0,
7748                         &fnum,
7749                         NULL);
7750
7751         if (!NT_STATUS_IS_OK(status)) {
7752                 printf("cli_ntcreate of %s failed (%s)\n",
7753                         fname,
7754                         nt_errstr(status));
7755                 goto out;
7756         }
7757
7758         /* Get the Windows ACL on the file. */
7759         status = cli_query_secdesc(cli,
7760                                 fnum,
7761                                 frame,
7762                                 &sd);
7763         if (!NT_STATUS_IS_OK(status)) {
7764                 printf("cli_query_secdesc failed (%s)\n",
7765                         nt_errstr(status));
7766                 goto out;
7767         }
7768
7769         /* Get the POSIX ACL on the file. */
7770         status = cli_posix_getacl(cli,
7771                                 fname,
7772                                 frame,
7773                                 &posix_acl_len,
7774                                 &posix_acl);
7775
7776         if (!NT_STATUS_IS_OK(status)) {
7777                 printf("cli_posix_getacl failed (%s)\n",
7778                         nt_errstr(status));
7779                 goto out;
7780         }
7781
7782         status = cli_close(cli, fnum);
7783         if (!NT_STATUS_IS_OK(status)) {
7784                 printf("close failed (%s)\n", nt_errstr(status));
7785                 goto out;
7786         }
7787         fnum = (uint16_t)-1;
7788
7789         /* Now create a symlink. */
7790         status = cli_posix_symlink(cli, fname, sname);
7791         if (!NT_STATUS_IS_OK(status)) {
7792                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
7793                         sname,
7794                         fname,
7795                         nt_errstr(status));
7796                 goto out;
7797         }
7798
7799         /* Open a handle on the symlink for SD set/get should fail. */
7800         status = cli_ntcreate(cli,
7801                         sname,
7802                         0,
7803                         READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
7804                         0,
7805                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7806                         FILE_OPEN,
7807                         0x0,
7808                         0x0,
7809                         &fnum,
7810                         NULL);
7811
7812         if (NT_STATUS_IS_OK(status)) {
7813                 printf("Symlink open for getsd/setsd of %s "
7814                         "succeeded (should fail)\n",
7815                         sname);
7816                 goto out;
7817         }
7818
7819         /* Open a handle on the symlink. */
7820         status = cli_ntcreate(cli,
7821                         sname,
7822                         0,
7823                         FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
7824                         0,
7825                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7826                         FILE_OPEN,
7827                         0x0,
7828                         0x0,
7829                         &fnum,
7830                         NULL);
7831
7832         if (!NT_STATUS_IS_OK(status)) {
7833                 printf("cli_posix_open of %s failed (%s)\n",
7834                         sname,
7835                         nt_errstr(status));
7836                 goto out;
7837         }
7838
7839         /* Get the Windows ACL on the symlink handle. Should fail */
7840         status = cli_query_secdesc(cli,
7841                                 fnum,
7842                                 frame,
7843                                 &sd_sym);
7844
7845         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7846                 printf("cli_query_secdesc on a symlink gave %s. "
7847                         "Should be NT_STATUS_ACCESS_DENIED.\n",
7848                         nt_errstr(status));
7849                 goto out;
7850         }
7851
7852         /* Get the POSIX ACL on the symlink pathname. Should fail. */
7853         status = cli_posix_getacl(cli,
7854                                 sname,
7855                                 frame,
7856                                 &posix_acl_len_sym,
7857                                 &posix_acl_sym);
7858
7859         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7860                 printf("cli_posix_getacl on a symlink gave %s. "
7861                         "Should be NT_STATUS_ACCESS_DENIED.\n",
7862                         nt_errstr(status));
7863                 goto out;
7864         }
7865
7866         /* Set the Windows ACL on the symlink handle. Should fail */
7867         status = cli_set_security_descriptor(cli,
7868                                 fnum,
7869                                 SECINFO_DACL,
7870                                 sd);
7871
7872         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7873                 printf("cli_query_secdesc on a symlink gave %s. "
7874                         "Should be NT_STATUS_ACCESS_DENIED.\n",
7875                         nt_errstr(status));
7876                 goto out;
7877         }
7878
7879         /* Set the POSIX ACL on the symlink pathname. Should fail. */
7880         status = cli_posix_setacl(cli,
7881                                 sname,
7882                                 posix_acl,
7883                                 posix_acl_len);
7884
7885         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7886                 printf("cli_posix_setacl on a symlink gave %s. "
7887                         "Should be NT_STATUS_ACCESS_DENIED.\n",
7888                         nt_errstr(status));
7889                 goto out;
7890         }
7891
7892         printf("ACL symlink test passed\n");
7893         correct = true;
7894
7895   out:
7896
7897         if (fnum != (uint16_t)-1) {
7898                 cli_close(cli, fnum);
7899                 fnum = (uint16_t)-1;
7900         }
7901
7902         cli_setatr(cli, sname, 0, 0);
7903         cli_posix_unlink(cli, sname);
7904         cli_setatr(cli, fname, 0, 0);
7905         cli_posix_unlink(cli, fname);
7906
7907         if (!torture_close_connection(cli)) {
7908                 correct = false;
7909         }
7910
7911         TALLOC_FREE(frame);
7912         return correct;
7913 }
7914
7915 /*
7916   Test POSIX can delete a file containing streams.
7917  */
7918 static bool run_posix_stream_delete(int dummy)
7919 {
7920         struct cli_state *cli1 = NULL;
7921         struct cli_state *cli2 = NULL;
7922         const char *fname = "streamfile";
7923         const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
7924         uint16_t fnum1 = (uint16_t)-1;
7925         bool correct = false;
7926         NTSTATUS status;
7927         TALLOC_CTX *frame = NULL;
7928
7929         frame = talloc_stackframe();
7930
7931         printf("Starting POSIX stream delete test\n");
7932
7933         if (!torture_open_connection(&cli1, 0) ||
7934                         !torture_open_connection(&cli2, 1)) {
7935                 TALLOC_FREE(frame);
7936                 return false;
7937         }
7938
7939         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7940         smbXcli_conn_set_sockopt(cli2->conn, sockops);
7941
7942         status = torture_setup_unix_extensions(cli2);
7943         if (!NT_STATUS_IS_OK(status)) {
7944                 goto out;
7945         }
7946
7947         cli_setatr(cli1, fname, 0, 0);
7948         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7949
7950         /* Create the file. */
7951         status = cli_ntcreate(cli1,
7952                         fname,
7953                         0,
7954                         READ_CONTROL_ACCESS,
7955                         0,
7956                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7957                         FILE_CREATE,
7958                         0x0,
7959                         0x0,
7960                         &fnum1,
7961                         NULL);
7962
7963         if (!NT_STATUS_IS_OK(status)) {
7964                 printf("cli_ntcreate of %s failed (%s)\n",
7965                         fname,
7966                         nt_errstr(status));
7967                 goto out;
7968         }
7969
7970         status = cli_close(cli1, fnum1);
7971         if (!NT_STATUS_IS_OK(status)) {
7972                 printf("cli_close of %s failed (%s)\n",
7973                         fname,
7974                         nt_errstr(status));
7975                 goto out;
7976         }
7977         fnum1 = (uint16_t)-1;
7978
7979         /* Now create the stream. */
7980         status = cli_ntcreate(cli1,
7981                         stream_fname,
7982                         0,
7983                         FILE_WRITE_DATA,
7984                         0,
7985                         FILE_SHARE_READ|FILE_SHARE_WRITE,
7986                         FILE_CREATE,
7987                         0x0,
7988                         0x0,
7989                         &fnum1,
7990                         NULL);
7991
7992         if (!NT_STATUS_IS_OK(status)) {
7993                 printf("cli_ntcreate of %s failed (%s)\n",
7994                         stream_fname,
7995                         nt_errstr(status));
7996                 goto out;
7997         }
7998
7999         /* Leave the stream handle open... */
8000
8001         /* POSIX unlink should fail. */
8002         status = cli_posix_unlink(cli2, fname);
8003         if (NT_STATUS_IS_OK(status)) {
8004                 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8005                         fname);
8006                 goto out;
8007         }
8008
8009         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8010                 printf("cli_posix_unlink of %s failed with (%s) "
8011                         "should have been NT_STATUS_SHARING_VIOLATION\n",
8012                         fname,
8013                         nt_errstr(status));
8014                 goto out;
8015         }
8016
8017         /* Close the stream handle. */
8018         status = cli_close(cli1, fnum1);
8019         if (!NT_STATUS_IS_OK(status)) {
8020                 printf("cli_close of %s failed (%s)\n",
8021                         stream_fname,
8022                         nt_errstr(status));
8023                 goto out;
8024         }
8025         fnum1 = (uint16_t)-1;
8026
8027         /* POSIX unlink after stream handle closed should succeed. */
8028         status = cli_posix_unlink(cli2, fname);
8029         if (!NT_STATUS_IS_OK(status)) {
8030                 printf("cli_posix_unlink of %s failed (%s)\n",
8031                         fname,
8032                         nt_errstr(status));
8033                 goto out;
8034         }
8035
8036         printf("POSIX stream delete test passed\n");
8037         correct = true;
8038
8039   out:
8040
8041         if (fnum1 != (uint16_t)-1) {
8042                 cli_close(cli1, fnum1);
8043                 fnum1 = (uint16_t)-1;
8044         }
8045
8046         cli_setatr(cli1, fname, 0, 0);
8047         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8048
8049         if (!torture_close_connection(cli1)) {
8050                 correct = false;
8051         }
8052         if (!torture_close_connection(cli2)) {
8053                 correct = false;
8054         }
8055
8056         TALLOC_FREE(frame);
8057         return correct;
8058 }
8059
8060 /*
8061   Test setting EA's are rejected on symlinks.
8062  */
8063 static bool run_ea_symlink_test(int dummy)
8064 {
8065         static struct cli_state *cli;
8066         const char *fname = "posix_file_ea";
8067         const char *sname = "posix_symlink_ea";
8068         const char *ea_name = "testea_name";
8069         const char *ea_value = "testea_value";
8070         uint16_t fnum = (uint16_t)-1;
8071         bool correct = false;
8072         NTSTATUS status;
8073         size_t i, num_eas;
8074         struct ea_struct *eas = NULL;
8075         TALLOC_CTX *frame = NULL;
8076
8077         frame = talloc_stackframe();
8078
8079         printf("Starting EA symlink test\n");
8080
8081         if (!torture_open_connection(&cli, 0)) {
8082                 TALLOC_FREE(frame);
8083                 return false;
8084         }
8085
8086         smbXcli_conn_set_sockopt(cli->conn, sockops);
8087
8088         status = torture_setup_unix_extensions(cli);
8089         if (!NT_STATUS_IS_OK(status)) {
8090                 TALLOC_FREE(frame);
8091                 return false;
8092         }
8093
8094         cli_setatr(cli, fname, 0, 0);
8095         cli_posix_unlink(cli, fname);
8096         cli_setatr(cli, sname, 0, 0);
8097         cli_posix_unlink(cli, sname);
8098
8099         status = cli_ntcreate(cli,
8100                         fname,
8101                         0,
8102                         READ_CONTROL_ACCESS,
8103                         0,
8104                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8105                         FILE_CREATE,
8106                         0x0,
8107                         0x0,
8108                         &fnum,
8109                         NULL);
8110
8111         if (!NT_STATUS_IS_OK(status)) {
8112                 printf("cli_ntcreate of %s failed (%s)\n",
8113                         fname,
8114                         nt_errstr(status));
8115                 goto out;
8116         }
8117
8118         status = cli_close(cli, fnum);
8119         if (!NT_STATUS_IS_OK(status)) {
8120                 printf("close failed (%s)\n",
8121                         nt_errstr(status));
8122                 goto out;
8123         }
8124         fnum = (uint16_t)-1;
8125
8126         /* Set an EA on the path. */
8127         status = cli_set_ea_path(cli,
8128                                 fname,
8129                                 ea_name,
8130                                 ea_value,
8131                                 strlen(ea_value)+1);
8132
8133         if (!NT_STATUS_IS_OK(status)) {
8134                 printf("cli_set_ea_path failed (%s)\n",
8135                         nt_errstr(status));
8136                 goto out;
8137         }
8138
8139         /* Now create a symlink. */
8140         status = cli_posix_symlink(cli, fname, sname);
8141         if (!NT_STATUS_IS_OK(status)) {
8142                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8143                         sname,
8144                         fname,
8145                         nt_errstr(status));
8146                 goto out;
8147         }
8148
8149         /* Get the EA list on the path. Should return value set. */
8150         status = cli_get_ea_list_path(cli,
8151                                 fname,
8152                                 frame,
8153                                 &num_eas,
8154                                 &eas);
8155
8156         if (!NT_STATUS_IS_OK(status)) {
8157                 printf("cli_get_ea_list_path failed (%s)\n",
8158                         nt_errstr(status));
8159                 goto out;
8160         }
8161
8162         /* Ensure the EA we set is there. */
8163         for (i=0; i<num_eas; i++) {
8164                 if (strcmp(eas[i].name, ea_name) == 0 &&
8165                                 eas[i].value.length == strlen(ea_value)+1 &&
8166                                 memcmp(eas[i].value.data,
8167                                         ea_value,
8168                                         eas[i].value.length) == 0) {
8169                         break;
8170                 }
8171         }
8172
8173         if (i == num_eas) {
8174                 printf("Didn't find EA on pathname %s\n",
8175                         fname);
8176                 goto out;
8177         }
8178
8179         num_eas = 0;
8180         TALLOC_FREE(eas);
8181
8182         /* Get the EA list on the symlink. Should return empty list. */
8183         status = cli_get_ea_list_path(cli,
8184                                 sname,
8185                                 frame,
8186                                 &num_eas,
8187                                 &eas);
8188
8189         if (!NT_STATUS_IS_OK(status)) {
8190                 printf("cli_get_ea_list_path failed (%s)\n",
8191                         nt_errstr(status));
8192                 goto out;
8193         }
8194
8195         if (num_eas != 0) {
8196                 printf("cli_get_ea_list_path failed (%s)\n",
8197                         nt_errstr(status));
8198                 goto out;
8199         }
8200
8201         /* Set an EA on the symlink. Should fail. */
8202         status = cli_set_ea_path(cli,
8203                                 sname,
8204                                 ea_name,
8205                                 ea_value,
8206                                 strlen(ea_value)+1);
8207
8208         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8209                 printf("cli_set_ea_path on a symlink gave %s. "
8210                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8211                         nt_errstr(status));
8212                 goto out;
8213         }
8214
8215         printf("EA symlink test passed\n");
8216         correct = true;
8217
8218   out:
8219
8220         if (fnum != (uint16_t)-1) {
8221                 cli_close(cli, fnum);
8222                 fnum = (uint16_t)-1;
8223         }
8224
8225         cli_setatr(cli, sname, 0, 0);
8226         cli_posix_unlink(cli, sname);
8227         cli_setatr(cli, fname, 0, 0);
8228         cli_posix_unlink(cli, fname);
8229
8230         if (!torture_close_connection(cli)) {
8231                 correct = false;
8232         }
8233
8234         TALLOC_FREE(frame);
8235         return correct;
8236 }
8237
8238 /*
8239   Test POSIX locks are OFD-locks.
8240  */
8241 static bool run_posix_ofd_lock_test(int dummy)
8242 {
8243         static struct cli_state *cli;
8244         const char *fname = "posix_file";
8245         uint16_t fnum1 = (uint16_t)-1;
8246         uint16_t fnum2 = (uint16_t)-1;
8247         bool correct = false;
8248         NTSTATUS status;
8249         TALLOC_CTX *frame = NULL;
8250
8251         frame = talloc_stackframe();
8252
8253         printf("Starting POSIX ofd-lock test\n");
8254
8255         if (!torture_open_connection(&cli, 0)) {
8256                 TALLOC_FREE(frame);
8257                 return false;
8258         }
8259
8260         smbXcli_conn_set_sockopt(cli->conn, sockops);
8261
8262         status = torture_setup_unix_extensions(cli);
8263         if (!NT_STATUS_IS_OK(status)) {
8264                 TALLOC_FREE(frame);
8265                 return false;
8266         }
8267
8268         cli_setatr(cli, fname, 0, 0);
8269         cli_posix_unlink(cli, fname);
8270
8271         /* Open the file twice. */
8272         status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8273                                 0600, &fnum1);
8274         if (!NT_STATUS_IS_OK(status)) {
8275                 printf("First POSIX open of %s failed\n", fname);
8276                 goto out;
8277         }
8278
8279         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8280         if (!NT_STATUS_IS_OK(status)) {
8281                 printf("First POSIX open of %s failed\n", fname);
8282                 goto out;
8283         }
8284
8285         /* Set a 0-50 lock on fnum1. */
8286         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8287         if (!NT_STATUS_IS_OK(status)) {
8288                 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8289                 goto out;
8290         }
8291
8292         /* Set a 60-100 lock on fnum2. */
8293         status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8294         if (!NT_STATUS_IS_OK(status)) {
8295                 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8296                 goto out;
8297         }
8298
8299         /* close fnum1 - 0-50 lock should go away. */
8300         status = cli_close(cli, fnum1);
8301         if (!NT_STATUS_IS_OK(status)) {
8302                 printf("close failed (%s)\n",
8303                         nt_errstr(status));
8304                 goto out;
8305         }
8306         fnum1 = (uint16_t)-1;
8307
8308         /* Change the lock context. */
8309         cli_setpid(cli, cli_getpid(cli) + 1);
8310
8311         /* Re-open fnum1. */
8312         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8313         if (!NT_STATUS_IS_OK(status)) {
8314                 printf("Third POSIX open of %s failed\n", fname);
8315                 goto out;
8316         }
8317
8318         /* 60-100 lock should still be there. */
8319         status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8320         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8321                 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8322                 goto out;
8323         }
8324
8325         /* 0-50 lock should be gone. */
8326         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8327         if (!NT_STATUS_IS_OK(status)) {
8328                 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8329                 goto out;
8330         }
8331
8332         printf("POSIX OFD lock test passed\n");
8333         correct = true;
8334
8335   out:
8336
8337         if (fnum1 != (uint16_t)-1) {
8338                 cli_close(cli, fnum1);
8339                 fnum1 = (uint16_t)-1;
8340         }
8341         if (fnum2 != (uint16_t)-1) {
8342                 cli_close(cli, fnum2);
8343                 fnum2 = (uint16_t)-1;
8344         }
8345
8346         cli_setatr(cli, fname, 0, 0);
8347         cli_posix_unlink(cli, fname);
8348
8349         if (!torture_close_connection(cli)) {
8350                 correct = false;
8351         }
8352
8353         TALLOC_FREE(frame);
8354         return correct;
8355 }
8356
8357 struct posix_blocking_state {
8358         struct tevent_context *ev;
8359         struct cli_state *cli1;
8360         uint16_t fnum1;
8361         struct cli_state *cli2;
8362         uint16_t fnum2;
8363         bool gotblocked;
8364         bool gotecho;
8365 };
8366
8367 static void posix_blocking_locked(struct tevent_req *subreq);
8368 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8369 static void posix_blocking_gotecho(struct tevent_req *subreq);
8370 static void posix_blocking_unlocked(struct tevent_req *subreq);
8371
8372 static struct tevent_req *posix_blocking_send(
8373         TALLOC_CTX *mem_ctx,
8374         struct tevent_context *ev,
8375         struct cli_state *cli1,
8376         uint16_t fnum1,
8377         struct cli_state *cli2,
8378         uint16_t fnum2)
8379 {
8380         struct tevent_req *req = NULL, *subreq = NULL;
8381         struct posix_blocking_state *state = NULL;
8382
8383         req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8384         if (req == NULL) {
8385                 return NULL;
8386         }
8387         state->ev = ev;
8388         state->cli1 = cli1;
8389         state->fnum1 = fnum1;
8390         state->cli2 = cli2;
8391         state->fnum2 = fnum2;
8392
8393         subreq = cli_posix_lock_send(
8394                 state,
8395                 state->ev,
8396                 state->cli1,
8397                 state->fnum1,
8398                 0,
8399                 1,
8400                 false,
8401                 WRITE_LOCK);
8402         if (tevent_req_nomem(subreq, req)) {
8403                 return tevent_req_post(req, ev);
8404         }
8405         tevent_req_set_callback(subreq, posix_blocking_locked, req);
8406         return req;
8407 }
8408
8409 static void posix_blocking_locked(struct tevent_req *subreq)
8410 {
8411         struct tevent_req *req = tevent_req_callback_data(
8412                 subreq, struct tevent_req);
8413         struct posix_blocking_state *state = tevent_req_data(
8414                 req, struct posix_blocking_state);
8415         NTSTATUS status;
8416
8417         status = cli_posix_lock_recv(subreq);
8418         TALLOC_FREE(subreq);
8419         if (tevent_req_nterror(req, status)) {
8420                 return;
8421         }
8422
8423         subreq = cli_posix_lock_send(
8424                 state,
8425                 state->ev,
8426                 state->cli2,
8427                 state->fnum2,
8428                 0,
8429                 1,
8430                 true,
8431                 WRITE_LOCK);
8432         if (tevent_req_nomem(subreq, req)) {
8433                 return;
8434         }
8435         tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8436
8437         /* Make sure the blocking request is delivered */
8438         subreq = cli_echo_send(
8439                 state,
8440                 state->ev,
8441                 state->cli2,
8442                 1,
8443                 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8444         if (tevent_req_nomem(subreq, req)) {
8445                 return;
8446         }
8447         tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8448 }
8449
8450 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8451 {
8452         struct tevent_req *req = tevent_req_callback_data(
8453                 subreq, struct tevent_req);
8454         struct posix_blocking_state *state = tevent_req_data(
8455                 req, struct posix_blocking_state);
8456         NTSTATUS status;
8457
8458         status = cli_posix_lock_recv(subreq);
8459         TALLOC_FREE(subreq);
8460         if (tevent_req_nterror(req, status)) {
8461                 return;
8462         }
8463         if (!state->gotecho) {
8464                 printf("blocked req got through before echo\n");
8465                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8466                 return;
8467         }
8468         tevent_req_done(req);
8469 }
8470
8471 static void posix_blocking_gotecho(struct tevent_req *subreq)
8472 {
8473         struct tevent_req *req = tevent_req_callback_data(
8474                 subreq, struct tevent_req);
8475         struct posix_blocking_state *state = tevent_req_data(
8476                 req, struct posix_blocking_state);
8477         NTSTATUS status;
8478
8479         status = cli_echo_recv(subreq);
8480         TALLOC_FREE(subreq);
8481         if (tevent_req_nterror(req, status)) {
8482                 return;
8483         }
8484         if (state->gotblocked) {
8485                 printf("blocked req got through before echo\n");
8486                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8487                 return;
8488         }
8489         state->gotecho = true;
8490
8491         subreq = cli_posix_lock_send(
8492                 state,
8493                 state->ev,
8494                 state->cli1,
8495                 state->fnum1,
8496                 0,
8497                 1,
8498                 false,
8499                 UNLOCK_LOCK);
8500         if (tevent_req_nomem(subreq, req)) {
8501                 return;
8502         }
8503         tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
8504 }
8505
8506 static void posix_blocking_unlocked(struct tevent_req *subreq)
8507 {
8508         struct tevent_req *req = tevent_req_callback_data(
8509                 subreq, struct tevent_req);
8510         NTSTATUS status;
8511
8512         status = cli_posix_lock_recv(subreq);
8513         TALLOC_FREE(subreq);
8514         if (tevent_req_nterror(req, status)) {
8515                 return;
8516         }
8517         /* tevent_req_done in posix_blocking_gotlocked */
8518 }
8519
8520 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
8521 {
8522         return tevent_req_simple_recv_ntstatus(req);
8523 }
8524
8525 static bool run_posix_blocking_lock(int dummy)
8526 {
8527         struct tevent_context *ev = NULL;
8528         struct cli_state *cli1 = NULL, *cli2 = NULL;
8529         const char *fname = "posix_blocking";
8530         uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
8531         struct tevent_req *req = NULL;
8532         NTSTATUS status;
8533         bool ret = false;
8534         bool ok;
8535
8536         printf("Starting posix blocking lock test\n");
8537
8538         ev = samba_tevent_context_init(NULL);
8539         if (ev == NULL) {
8540                 return false;
8541         }
8542
8543         ok = torture_open_connection(&cli1, 0);
8544         if (!ok) {
8545                 goto fail;
8546         }
8547         ok = torture_open_connection(&cli2, 0);
8548         if (!ok) {
8549                 goto fail;
8550         }
8551
8552         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8553
8554         status = torture_setup_unix_extensions(cli1);
8555         if (!NT_STATUS_IS_OK(status)) {
8556                 return false;
8557         }
8558
8559         cli_setatr(cli1, fname, 0, 0);
8560         cli_posix_unlink(cli1, fname);
8561
8562         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8563                                 0600, &fnum1);
8564         if (!NT_STATUS_IS_OK(status)) {
8565                 printf("First POSIX open of %s failed: %s\n",
8566                        fname,
8567                        nt_errstr(status));
8568                 goto fail;
8569         }
8570
8571         status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
8572         if (!NT_STATUS_IS_OK(status)) {
8573                 printf("Second POSIX open of %s failed: %s\n",
8574                        fname,
8575                        nt_errstr(status));
8576                 goto fail;
8577         }
8578
8579         req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
8580         if (req == NULL) {
8581                 printf("cli_posix_blocking failed\n");
8582                 goto fail;
8583         }
8584
8585         ok = tevent_req_poll_ntstatus(req, ev, &status);
8586         if (!ok) {
8587                 printf("tevent_req_poll_ntstatus failed: %s\n",
8588                        nt_errstr(status));
8589                 goto fail;
8590         }
8591         status = posix_blocking_recv(req);
8592         TALLOC_FREE(req);
8593         if (!NT_STATUS_IS_OK(status)) {
8594                 printf("posix_blocking_recv returned %s\n",
8595                        nt_errstr(status));
8596                 goto fail;
8597         }
8598
8599         ret = true;
8600 fail:
8601
8602         if (fnum1 != UINT16_MAX) {
8603                 cli_close(cli1, fnum1);
8604                 fnum1 = UINT16_MAX;
8605         }
8606         if (fnum2 != UINT16_MAX) {
8607                 cli_close(cli2, fnum2);
8608                 fnum2 = UINT16_MAX;
8609         }
8610
8611         if (cli1 != NULL) {
8612                 cli_setatr(cli1, fname, 0, 0);
8613                 cli_posix_unlink(cli1, fname);
8614         }
8615
8616         ok = true;
8617
8618         if (cli1 != NULL) {
8619                 ok &= torture_close_connection(cli1);
8620                 cli1 = NULL;
8621         }
8622         if (cli2 != NULL) {
8623                 ok &= torture_close_connection(cli2);
8624                 cli2 = NULL;
8625         }
8626
8627         if (!ok) {
8628                 ret = false;
8629         }
8630         TALLOC_FREE(ev);
8631         return ret;
8632 }
8633
8634 /*
8635   Test POSIX mkdir is case-sensitive.
8636  */
8637 static bool run_posix_mkdir_test(int dummy)
8638 {
8639         static struct cli_state *cli;
8640         const char *fname_foo = "POSIX_foo";
8641         const char *fname_foo_Foo = "POSIX_foo/Foo";
8642         const char *fname_foo_foo = "POSIX_foo/foo";
8643         const char *fname_Foo = "POSIX_Foo";
8644         const char *fname_Foo_Foo = "POSIX_Foo/Foo";
8645         const char *fname_Foo_foo = "POSIX_Foo/foo";
8646         bool correct = false;
8647         NTSTATUS status;
8648         TALLOC_CTX *frame = NULL;
8649         uint16_t fnum = (uint16_t)-1;
8650
8651         frame = talloc_stackframe();
8652
8653         printf("Starting POSIX mkdir test\n");
8654
8655         if (!torture_open_connection(&cli, 0)) {
8656                 TALLOC_FREE(frame);
8657                 return false;
8658         }
8659
8660         smbXcli_conn_set_sockopt(cli->conn, sockops);
8661
8662         status = torture_setup_unix_extensions(cli);
8663         if (!NT_STATUS_IS_OK(status)) {
8664                 TALLOC_FREE(frame);
8665                 return false;
8666         }
8667
8668         cli_posix_rmdir(cli, fname_foo_foo);
8669         cli_posix_rmdir(cli, fname_foo_Foo);
8670         cli_posix_rmdir(cli, fname_foo);
8671
8672         cli_posix_rmdir(cli, fname_Foo_foo);
8673         cli_posix_rmdir(cli, fname_Foo_Foo);
8674         cli_posix_rmdir(cli, fname_Foo);
8675
8676         /*
8677          * Create a file POSIX_foo then try
8678          * and use it in a directory path by
8679          * doing mkdir POSIX_foo/bar.
8680          * The mkdir should fail with
8681          * NT_STATUS_OBJECT_PATH_NOT_FOUND
8682          */
8683
8684         status = cli_posix_open(cli,
8685                         fname_foo,
8686                         O_RDWR|O_CREAT,
8687                         0666,
8688                         &fnum);
8689         if (!NT_STATUS_IS_OK(status)) {
8690                 printf("cli_posix_open of %s failed error %s\n",
8691                         fname_foo,
8692                         nt_errstr(status));
8693                 goto out;
8694         }
8695
8696         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
8697         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
8698                 printf("cli_posix_mkdir of %s should fail with "
8699                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
8700                         "%s instead\n",
8701                         fname_foo_foo,
8702                         nt_errstr(status));
8703                 goto out;
8704         }
8705
8706         status = cli_close(cli, fnum);
8707         if (!NT_STATUS_IS_OK(status)) {
8708                 printf("cli_close failed %s\n", nt_errstr(status));
8709                 goto out;
8710         }
8711         fnum = (uint16_t)-1;
8712
8713         status = cli_posix_unlink(cli, fname_foo);
8714         if (!NT_STATUS_IS_OK(status)) {
8715                 printf("cli_posix_unlink of %s failed error %s\n",
8716                         fname_foo,
8717                         nt_errstr(status));
8718                 goto out;
8719         }
8720
8721         /*
8722          * Now we've deleted everything, posix_mkdir, posix_rmdir,
8723          * posix_open, posix_unlink, on
8724          * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
8725          * not silently create POSIX_foo/foo.
8726          */
8727
8728         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
8729         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
8730                 printf("cli_posix_mkdir of %s should fail with "
8731                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
8732                         "%s instead\n",
8733                         fname_foo_foo,
8734                         nt_errstr(status));
8735                 goto out;
8736         }
8737
8738         status = cli_posix_rmdir(cli, fname_foo_foo);
8739         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
8740                 printf("cli_posix_rmdir of %s should fail with "
8741                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
8742                         "%s instead\n",
8743                         fname_foo_foo,
8744                         nt_errstr(status));
8745                 goto out;
8746         }
8747
8748         status = cli_posix_open(cli,
8749                         fname_foo_foo,
8750                         O_RDWR|O_CREAT,
8751                         0666,
8752                         &fnum);
8753         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
8754                 printf("cli_posix_open of %s should fail with "
8755                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
8756                         "%s instead\n",
8757                         fname_foo_foo,
8758                         nt_errstr(status));
8759                 goto out;
8760         }
8761
8762         status = cli_posix_unlink(cli, fname_foo_foo);
8763         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
8764                 printf("cli_posix_unlink of %s should fail with "
8765                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
8766                         "%s instead\n",
8767                         fname_foo_foo,
8768                         nt_errstr(status));
8769                 goto out;
8770         }
8771
8772         status = cli_posix_mkdir(cli, fname_foo, 0777);
8773         if (!NT_STATUS_IS_OK(status)) {
8774                 printf("cli_posix_mkdir of %s failed\n", fname_foo);
8775                 goto out;
8776         }
8777
8778         status = cli_posix_mkdir(cli, fname_Foo, 0777);
8779         if (!NT_STATUS_IS_OK(status)) {
8780                 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
8781                 goto out;
8782         }
8783
8784         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
8785         if (!NT_STATUS_IS_OK(status)) {
8786                 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
8787                 goto out;
8788         }
8789
8790         status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
8791         if (!NT_STATUS_IS_OK(status)) {
8792                 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
8793                 goto out;
8794         }
8795
8796         status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
8797         if (!NT_STATUS_IS_OK(status)) {
8798                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
8799                 goto out;
8800         }
8801
8802         status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
8803         if (!NT_STATUS_IS_OK(status)) {
8804                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
8805                 goto out;
8806         }
8807
8808         printf("POSIX mkdir test passed\n");
8809         correct = true;
8810
8811   out:
8812
8813         if (fnum != (uint16_t)-1) {
8814                 cli_close(cli, fnum);
8815                 fnum = (uint16_t)-1;
8816         }
8817
8818         cli_posix_rmdir(cli, fname_foo_foo);
8819         cli_posix_rmdir(cli, fname_foo_Foo);
8820         cli_posix_rmdir(cli, fname_foo);
8821
8822         cli_posix_rmdir(cli, fname_Foo_foo);
8823         cli_posix_rmdir(cli, fname_Foo_Foo);
8824         cli_posix_rmdir(cli, fname_Foo);
8825
8826         if (!torture_close_connection(cli)) {
8827                 correct = false;
8828         }
8829
8830         TALLOC_FREE(frame);
8831         return correct;
8832 }
8833
8834 struct posix_acl_oplock_state {
8835         struct tevent_context *ev;
8836         struct cli_state *cli;
8837         bool *got_break;
8838         bool *acl_ret;
8839         NTSTATUS status;
8840 };
8841
8842 static void posix_acl_oplock_got_break(struct tevent_req *req)
8843 {
8844         struct posix_acl_oplock_state *state = tevent_req_callback_data(
8845                 req, struct posix_acl_oplock_state);
8846         uint16_t fnum;
8847         uint8_t level;
8848         NTSTATUS status;
8849
8850         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
8851         TALLOC_FREE(req);
8852         if (!NT_STATUS_IS_OK(status)) {
8853                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
8854                        nt_errstr(status));
8855                 return;
8856         }
8857         *state->got_break = true;
8858
8859         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
8860                                   NO_OPLOCK);
8861         if (req == NULL) {
8862                 printf("cli_oplock_ack_send failed\n");
8863                 return;
8864         }
8865 }
8866
8867 static void posix_acl_oplock_got_acl(struct tevent_req *req)
8868 {
8869         struct posix_acl_oplock_state *state = tevent_req_callback_data(
8870                 req, struct posix_acl_oplock_state);
8871         size_t ret_size = 0;
8872         char *ret_data = NULL;
8873
8874         state->status = cli_posix_getacl_recv(req,
8875                         state,
8876                         &ret_size,
8877                         &ret_data);
8878
8879         if (!NT_STATUS_IS_OK(state->status)) {
8880                 printf("cli_posix_getacl_recv returned %s\n",
8881                         nt_errstr(state->status));
8882         }
8883         *state->acl_ret = true;
8884 }
8885
8886 static bool run_posix_acl_oplock_test(int dummy)
8887 {
8888         struct tevent_context *ev;
8889         struct cli_state *cli1, *cli2;
8890         struct tevent_req *oplock_req, *getacl_req;
8891         const char *fname = "posix_acl_oplock";
8892         uint16_t fnum;
8893         int saved_use_oplocks = use_oplocks;
8894         NTSTATUS status;
8895         bool correct = true;
8896         bool got_break = false;
8897         bool acl_ret = false;
8898
8899         struct posix_acl_oplock_state *state;
8900
8901         printf("starting posix_acl_oplock test\n");
8902
8903         if (!torture_open_connection(&cli1, 0)) {
8904                 use_level_II_oplocks = false;
8905                 use_oplocks = saved_use_oplocks;
8906                 return false;
8907         }
8908
8909         if (!torture_open_connection(&cli2, 1)) {
8910                 use_level_II_oplocks = false;
8911                 use_oplocks = saved_use_oplocks;
8912                 return false;
8913         }
8914
8915         /* Setup posix on cli2 only. */
8916         status = torture_setup_unix_extensions(cli2);
8917         if (!NT_STATUS_IS_OK(status)) {
8918                 return false;
8919         }
8920
8921         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8922         smbXcli_conn_set_sockopt(cli2->conn, sockops);
8923
8924         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8925
8926         /* Create the file on the Windows connection. */
8927         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
8928                           &fnum);
8929         if (!NT_STATUS_IS_OK(status)) {
8930                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
8931                 return false;
8932         }
8933
8934         status = cli_close(cli1, fnum);
8935         if (!NT_STATUS_IS_OK(status)) {
8936                 printf("close1 failed (%s)\n", nt_errstr(status));
8937                 return false;
8938         }
8939
8940         cli1->use_oplocks = true;
8941
8942         /* Open with oplock. */
8943         status = cli_ntcreate(cli1,
8944                         fname,
8945                         0,
8946                         FILE_READ_DATA,
8947                         FILE_ATTRIBUTE_NORMAL,
8948                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8949                         FILE_OPEN,
8950                         0,
8951                         0,
8952                         &fnum,
8953                         NULL);
8954
8955         if (!NT_STATUS_IS_OK(status)) {
8956                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
8957                 return false;
8958         }
8959
8960         ev = samba_tevent_context_init(talloc_tos());
8961         if (ev == NULL) {
8962                 printf("tevent_context_init failed\n");
8963                 return false;
8964         }
8965
8966         state = talloc_zero(ev, struct posix_acl_oplock_state);
8967         if (state == NULL) {
8968                 printf("talloc failed\n");
8969                 return false;
8970         }
8971         state->ev = ev;
8972         state->cli = cli1;
8973         state->got_break = &got_break;
8974         state->acl_ret = &acl_ret;
8975
8976         oplock_req = cli_smb_oplock_break_waiter_send(
8977                 talloc_tos(), ev, cli1);
8978         if (oplock_req == NULL) {
8979                 printf("cli_smb_oplock_break_waiter_send failed\n");
8980                 return false;
8981         }
8982         tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
8983
8984         /* Get ACL on POSIX connection - should break oplock. */
8985         getacl_req = cli_posix_getacl_send(talloc_tos(),
8986                                 ev,
8987                                 cli2,
8988                                 fname);
8989         if (getacl_req == NULL) {
8990                 printf("cli_posix_getacl_send failed\n");
8991                 return false;
8992         }
8993         tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
8994
8995         while (!got_break || !acl_ret) {
8996                 int ret;
8997                 ret = tevent_loop_once(ev);
8998                 if (ret == -1) {
8999                         printf("tevent_loop_once failed: %s\n",
9000                                strerror(errno));
9001                         return false;
9002                 }
9003         }
9004
9005         if (!NT_STATUS_IS_OK(state->status)) {
9006                 printf("getacl failed (%s)\n", nt_errstr(state->status));
9007                 correct = false;
9008         }
9009
9010         status = cli_close(cli1, fnum);
9011         if (!NT_STATUS_IS_OK(status)) {
9012                 printf("close2 failed (%s)\n", nt_errstr(status));
9013                 correct = false;
9014         }
9015
9016         status = cli_unlink(cli1,
9017                         fname,
9018                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9019         if (!NT_STATUS_IS_OK(status)) {
9020                 printf("unlink failed (%s)\n", nt_errstr(status));
9021                 correct = false;
9022         }
9023
9024         if (!torture_close_connection(cli1)) {
9025                 correct = false;
9026         }
9027         if (!torture_close_connection(cli2)) {
9028                 correct = false;
9029         }
9030
9031         if (!got_break) {
9032                 correct = false;
9033         }
9034
9035         printf("finished posix acl oplock test\n");
9036
9037         return correct;
9038 }
9039
9040 static bool run_posix_acl_shareroot_test(int dummy)
9041 {
9042         struct cli_state *cli;
9043         NTSTATUS status;
9044         bool correct = false;
9045         char *posix_acl = NULL;
9046         size_t posix_acl_len = 0;
9047         uint16_t num_file_acls = 0;
9048         uint16_t num_dir_acls = 0;
9049         uint16_t i;
9050         uint32_t expected_size = 0;
9051         bool got_user = false;
9052         bool got_group = false;
9053         bool got_other = false;
9054         TALLOC_CTX *frame = NULL;
9055
9056         frame = talloc_stackframe();
9057
9058         printf("starting posix_acl_shareroot test\n");
9059
9060         if (!torture_open_connection(&cli, 0)) {
9061                 TALLOC_FREE(frame);
9062                 return false;
9063         }
9064
9065         smbXcli_conn_set_sockopt(cli->conn, sockops);
9066
9067         status = torture_setup_unix_extensions(cli);
9068         if (!NT_STATUS_IS_OK(status)) {
9069                 printf("Failed to setup unix extensions\n");
9070                 goto out;
9071         }
9072
9073         /* Get the POSIX ACL on the root of the share. */
9074         status = cli_posix_getacl(cli,
9075                                 ".",
9076                                 frame,
9077                                 &posix_acl_len,
9078                                 &posix_acl);
9079
9080         if (!NT_STATUS_IS_OK(status)) {
9081                 printf("cli_posix_getacl of '.' failed (%s)\n",
9082                         nt_errstr(status));
9083                 goto out;
9084         }
9085
9086         if (posix_acl_len < 6 ||
9087                         SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9088                 printf("getfacl ., unknown POSIX acl version %u.\n",
9089                         (unsigned int)CVAL(posix_acl,0) );
9090                 goto out;
9091         }
9092
9093         num_file_acls = SVAL(posix_acl,2);
9094         num_dir_acls = SVAL(posix_acl,4);
9095         expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9096                                 SMB_POSIX_ACL_ENTRY_SIZE*
9097                                 (num_file_acls+num_dir_acls);
9098
9099         if (posix_acl_len != expected_size) {
9100                 printf("incorrect POSIX acl buffer size "
9101                         "(should be %u, was %u).\n",
9102                         (unsigned int)expected_size,
9103                         (unsigned int)posix_acl_len);
9104                 goto out;
9105         }
9106
9107         /*
9108          * We don't need to know what the ACL's are
9109          * we just need to know we have at least 3
9110          * file entries (u,g,o).
9111          */
9112
9113         for (i = 0; i < num_file_acls; i++) {
9114                 unsigned char tagtype =
9115                         CVAL(posix_acl,
9116                                 SMB_POSIX_ACL_HEADER_SIZE+
9117                                 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9118
9119                 switch(tagtype) {
9120                         case SMB_POSIX_ACL_USER_OBJ:
9121                                 got_user = true;
9122                                 break;
9123                         case SMB_POSIX_ACL_GROUP_OBJ:
9124                                 got_group = true;
9125                                 break;
9126                         case SMB_POSIX_ACL_OTHER:
9127                                 got_other = true;
9128                                 break;
9129                         default:
9130                                 break;
9131                 }
9132         }
9133
9134         if (!got_user) {
9135                 printf("Missing user entry\n");
9136                 goto out;
9137         }
9138
9139         if (!got_group) {
9140                 printf("Missing group entry\n");
9141                 goto out;
9142         }
9143
9144         if (!got_other) {
9145                 printf("Missing other entry\n");
9146                 goto out;
9147         }
9148
9149         correct = true;
9150
9151   out:
9152
9153         if (!torture_close_connection(cli)) {
9154                 correct = false;
9155         }
9156
9157         printf("finished posix acl shareroot test\n");
9158         TALLOC_FREE(frame);
9159
9160         return correct;
9161 }
9162
9163 static uint32_t open_attrs_table[] = {
9164                 FILE_ATTRIBUTE_NORMAL,
9165                 FILE_ATTRIBUTE_ARCHIVE,
9166                 FILE_ATTRIBUTE_READONLY,
9167                 FILE_ATTRIBUTE_HIDDEN,
9168                 FILE_ATTRIBUTE_SYSTEM,
9169
9170                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9171                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9172                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9173                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9174                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9175                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9176
9177                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9178                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9179                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9180                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9181 };
9182
9183 struct trunc_open_results {
9184         unsigned int num;
9185         uint32_t init_attr;
9186         uint32_t trunc_attr;
9187         uint32_t result_attr;
9188 };
9189
9190 static struct trunc_open_results attr_results[] = {
9191         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9192         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9193         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9194         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9195         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9196         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9197         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9198         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9199         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9200         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9201         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9202         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9203         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9204         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9205         { 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 },
9206         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9207         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9208         { 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 },
9209         { 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 },
9210         { 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 },
9211         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9212         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9213         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9214         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9215         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9216         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9217 };
9218
9219 static bool run_openattrtest(int dummy)
9220 {
9221         static struct cli_state *cli1;
9222         const char *fname = "\\openattr.file";
9223         uint16_t fnum1;
9224         bool correct = True;
9225         uint16_t attr;
9226         unsigned int i, j, k, l;
9227         NTSTATUS status;
9228
9229         printf("starting open attr test\n");
9230
9231         if (!torture_open_connection(&cli1, 0)) {
9232                 return False;
9233         }
9234
9235         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9236
9237         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9238                 cli_setatr(cli1, fname, 0, 0);
9239                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9240
9241                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9242                                        open_attrs_table[i], FILE_SHARE_NONE,
9243                                        FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9244                 if (!NT_STATUS_IS_OK(status)) {
9245                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9246                         return False;
9247                 }
9248
9249                 status = cli_close(cli1, fnum1);
9250                 if (!NT_STATUS_IS_OK(status)) {
9251                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9252                         return False;
9253                 }
9254
9255                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9256                         status = cli_ntcreate(cli1, fname, 0,
9257                                               FILE_READ_DATA|FILE_WRITE_DATA,
9258                                               open_attrs_table[j],
9259                                               FILE_SHARE_NONE, FILE_OVERWRITE,
9260                                               0, 0, &fnum1, NULL);
9261                         if (!NT_STATUS_IS_OK(status)) {
9262                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9263                                         if (attr_results[l].num == k) {
9264                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9265                                                                 k, open_attrs_table[i],
9266                                                                 open_attrs_table[j],
9267                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
9268                                                 correct = False;
9269                                         }
9270                                 }
9271
9272                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9273                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9274                                                         k, open_attrs_table[i], open_attrs_table[j],
9275                                                         nt_errstr(status));
9276                                         correct = False;
9277                                 }
9278 #if 0
9279                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9280 #endif
9281                                 k++;
9282                                 continue;
9283                         }
9284
9285                         status = cli_close(cli1, fnum1);
9286                         if (!NT_STATUS_IS_OK(status)) {
9287                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9288                                 return False;
9289                         }
9290
9291                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9292                         if (!NT_STATUS_IS_OK(status)) {
9293                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9294                                 return False;
9295                         }
9296
9297 #if 0
9298                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9299                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
9300 #endif
9301
9302                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9303                                 if (attr_results[l].num == k) {
9304                                         if (attr != attr_results[l].result_attr ||
9305                                                         open_attrs_table[i] != attr_results[l].init_attr ||
9306                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
9307                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9308                                                 open_attrs_table[i],
9309                                                 open_attrs_table[j],
9310                                                 (unsigned int)attr,
9311                                                 attr_results[l].result_attr);
9312                                                 correct = False;
9313                                         }
9314                                         break;
9315                                 }
9316                         }
9317                         k++;
9318                 }
9319         }
9320
9321         cli_setatr(cli1, fname, 0, 0);
9322         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9323
9324         printf("open attr test %s.\n", correct ? "passed" : "failed");
9325
9326         if (!torture_close_connection(cli1)) {
9327                 correct = False;
9328         }
9329         return correct;
9330 }
9331
9332 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
9333                     const char *name, void *state)
9334 {
9335         int *matched = (int *)state;
9336         if (matched != NULL) {
9337                 *matched += 1;
9338         }
9339         return NT_STATUS_OK;
9340 }
9341
9342 /*
9343   test directory listing speed
9344  */
9345 static bool run_dirtest(int dummy)
9346 {
9347         int i;
9348         static struct cli_state *cli;
9349         uint16_t fnum;
9350         struct timeval core_start;
9351         bool correct = True;
9352         int matched;
9353
9354         printf("starting directory test\n");
9355
9356         if (!torture_open_connection(&cli, 0)) {
9357                 return False;
9358         }
9359
9360         smbXcli_conn_set_sockopt(cli->conn, sockops);
9361
9362         srandom(0);
9363         for (i=0;i<torture_numops;i++) {
9364                 fstring fname;
9365                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9366                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9367                         fprintf(stderr,"Failed to open %s\n", fname);
9368                         return False;
9369                 }
9370                 cli_close(cli, fnum);
9371         }
9372
9373         core_start = timeval_current();
9374
9375         matched = 0;
9376         cli_list(cli, "a*.*", 0, list_fn, &matched);
9377         printf("Matched %d\n", matched);
9378
9379         matched = 0;
9380         cli_list(cli, "b*.*", 0, list_fn, &matched);
9381         printf("Matched %d\n", matched);
9382
9383         matched = 0;
9384         cli_list(cli, "xyzabc", 0, list_fn, &matched);
9385         printf("Matched %d\n", matched);
9386
9387         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9388
9389         srandom(0);
9390         for (i=0;i<torture_numops;i++) {
9391                 fstring fname;
9392                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9393                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9394         }
9395
9396         if (!torture_close_connection(cli)) {
9397                 correct = False;
9398         }
9399
9400         printf("finished dirtest\n");
9401
9402         return correct;
9403 }
9404
9405 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
9406                    void *state)
9407 {
9408         struct cli_state *pcli = (struct cli_state *)state;
9409         fstring fname;
9410         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9411
9412         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9413                 return NT_STATUS_OK;
9414
9415         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
9416                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9417                         printf("del_fn: failed to rmdir %s\n,", fname );
9418         } else {
9419                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9420                         printf("del_fn: failed to unlink %s\n,", fname );
9421         }
9422         return NT_STATUS_OK;
9423 }
9424
9425
9426 /*
9427   sees what IOCTLs are supported
9428  */
9429 bool torture_ioctl_test(int dummy)
9430 {
9431         static struct cli_state *cli;
9432         uint16_t device, function;
9433         uint16_t fnum;
9434         const char *fname = "\\ioctl.dat";
9435         DATA_BLOB blob;
9436         NTSTATUS status;
9437
9438         if (!torture_open_connection(&cli, 0)) {
9439                 return False;
9440         }
9441
9442         printf("starting ioctl test\n");
9443
9444         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9445
9446         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9447         if (!NT_STATUS_IS_OK(status)) {
9448                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9449                 return False;
9450         }
9451
9452         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9453         printf("ioctl device info: %s\n", nt_errstr(status));
9454
9455         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9456         printf("ioctl job info: %s\n", nt_errstr(status));
9457
9458         for (device=0;device<0x100;device++) {
9459                 printf("ioctl test with device = 0x%x\n", device);
9460                 for (function=0;function<0x100;function++) {
9461                         uint32_t code = (device<<16) | function;
9462
9463                         status = cli_raw_ioctl(cli, fnum, code, &blob);
9464
9465                         if (NT_STATUS_IS_OK(status)) {
9466                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
9467                                        (int)blob.length);
9468                                 data_blob_free(&blob);
9469                         }
9470                 }
9471         }
9472
9473         if (!torture_close_connection(cli)) {
9474                 return False;
9475         }
9476
9477         return True;
9478 }
9479
9480
9481 /*
9482   tries varients of chkpath
9483  */
9484 bool torture_chkpath_test(int dummy)
9485 {
9486         static struct cli_state *cli;
9487         uint16_t fnum;
9488         bool ret;
9489         NTSTATUS status;
9490
9491         if (!torture_open_connection(&cli, 0)) {
9492                 return False;
9493         }
9494
9495         printf("starting chkpath test\n");
9496
9497         /* cleanup from an old run */
9498         cli_rmdir(cli, "\\chkpath.dir\\dir2");
9499         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9500         cli_rmdir(cli, "\\chkpath.dir");
9501
9502         status = cli_mkdir(cli, "\\chkpath.dir");
9503         if (!NT_STATUS_IS_OK(status)) {
9504                 printf("mkdir1 failed : %s\n", nt_errstr(status));
9505                 return False;
9506         }
9507
9508         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
9509         if (!NT_STATUS_IS_OK(status)) {
9510                 printf("mkdir2 failed : %s\n", nt_errstr(status));
9511                 return False;
9512         }
9513
9514         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
9515                           DENY_NONE, &fnum);
9516         if (!NT_STATUS_IS_OK(status)) {
9517                 printf("open1 failed (%s)\n", nt_errstr(status));
9518                 return False;
9519         }
9520         cli_close(cli, fnum);
9521
9522         status = cli_chkpath(cli, "\\chkpath.dir");
9523         if (!NT_STATUS_IS_OK(status)) {
9524                 printf("chkpath1 failed: %s\n", nt_errstr(status));
9525                 ret = False;
9526         }
9527
9528         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
9529         if (!NT_STATUS_IS_OK(status)) {
9530                 printf("chkpath2 failed: %s\n", nt_errstr(status));
9531                 ret = False;
9532         }
9533
9534         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
9535         if (!NT_STATUS_IS_OK(status)) {
9536                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9537                                   NT_STATUS_NOT_A_DIRECTORY);
9538         } else {
9539                 printf("* chkpath on a file should fail\n");
9540                 ret = False;
9541         }
9542
9543         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
9544         if (!NT_STATUS_IS_OK(status)) {
9545                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
9546                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
9547         } else {
9548                 printf("* chkpath on a non existent file should fail\n");
9549                 ret = False;
9550         }
9551
9552         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
9553         if (!NT_STATUS_IS_OK(status)) {
9554                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9555                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
9556         } else {
9557                 printf("* chkpath on a non existent component should fail\n");
9558                 ret = False;
9559         }
9560
9561         cli_rmdir(cli, "\\chkpath.dir\\dir2");
9562         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9563         cli_rmdir(cli, "\\chkpath.dir");
9564
9565         if (!torture_close_connection(cli)) {
9566                 return False;
9567         }
9568
9569         return ret;
9570 }
9571
9572 static bool run_eatest(int dummy)
9573 {
9574         static struct cli_state *cli;
9575         const char *fname = "\\eatest.txt";
9576         bool correct = True;
9577         uint16_t fnum;
9578         int i;
9579         size_t num_eas;
9580         struct ea_struct *ea_list = NULL;
9581         TALLOC_CTX *mem_ctx = talloc_init("eatest");
9582         NTSTATUS status;
9583
9584         printf("starting eatest\n");
9585
9586         if (!torture_open_connection(&cli, 0)) {
9587                 talloc_destroy(mem_ctx);
9588                 return False;
9589         }
9590
9591         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9592
9593         status = cli_ntcreate(cli, fname, 0,
9594                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
9595                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
9596                               0x4044, 0, &fnum, NULL);
9597         if (!NT_STATUS_IS_OK(status)) {
9598                 printf("open failed - %s\n", nt_errstr(status));
9599                 talloc_destroy(mem_ctx);
9600                 return False;
9601         }
9602
9603         for (i = 0; i < 10; i++) {
9604                 fstring ea_name, ea_val;
9605
9606                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
9607                 memset(ea_val, (char)i+1, i+1);
9608                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
9609                 if (!NT_STATUS_IS_OK(status)) {
9610                         printf("ea_set of name %s failed - %s\n", ea_name,
9611                                nt_errstr(status));
9612                         talloc_destroy(mem_ctx);
9613                         return False;
9614                 }
9615         }
9616
9617         cli_close(cli, fnum);
9618         for (i = 0; i < 10; i++) {
9619                 fstring ea_name, ea_val;
9620
9621                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
9622                 memset(ea_val, (char)i+1, i+1);
9623                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
9624                 if (!NT_STATUS_IS_OK(status)) {
9625                         printf("ea_set of name %s failed - %s\n", ea_name,
9626                                nt_errstr(status));
9627                         talloc_destroy(mem_ctx);
9628                         return False;
9629                 }
9630         }
9631
9632         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
9633         if (!NT_STATUS_IS_OK(status)) {
9634                 printf("ea_get list failed - %s\n", nt_errstr(status));
9635                 correct = False;
9636         }
9637
9638         printf("num_eas = %d\n", (int)num_eas);
9639
9640         if (num_eas != 20) {
9641                 printf("Should be 20 EA's stored... failing.\n");
9642                 correct = False;
9643         }
9644
9645         for (i = 0; i < num_eas; i++) {
9646                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
9647                 dump_data(0, ea_list[i].value.data,
9648                           ea_list[i].value.length);
9649         }
9650
9651         /* Setting EA's to zero length deletes them. Test this */
9652         printf("Now deleting all EA's - case indepenent....\n");
9653
9654 #if 1
9655         cli_set_ea_path(cli, fname, "", "", 0);
9656 #else
9657         for (i = 0; i < 20; i++) {
9658                 fstring ea_name;
9659                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
9660                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
9661                 if (!NT_STATUS_IS_OK(status)) {
9662                         printf("ea_set of name %s failed - %s\n", ea_name,
9663                                nt_errstr(status));
9664                         talloc_destroy(mem_ctx);
9665                         return False;
9666                 }
9667         }
9668 #endif
9669
9670         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
9671         if (!NT_STATUS_IS_OK(status)) {
9672                 printf("ea_get list failed - %s\n", nt_errstr(status));
9673                 correct = False;
9674         }
9675
9676         printf("num_eas = %d\n", (int)num_eas);
9677         for (i = 0; i < num_eas; i++) {
9678                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
9679                 dump_data(0, ea_list[i].value.data,
9680                           ea_list[i].value.length);
9681         }
9682
9683         if (num_eas != 0) {
9684                 printf("deleting EA's failed.\n");
9685                 correct = False;
9686         }
9687
9688         /* Try and delete a non existent EA. */
9689         status = cli_set_ea_path(cli, fname, "foo", "", 0);
9690         if (!NT_STATUS_IS_OK(status)) {
9691                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
9692                        nt_errstr(status));
9693                 correct = False;
9694         }
9695
9696         talloc_destroy(mem_ctx);
9697         if (!torture_close_connection(cli)) {
9698                 correct = False;
9699         }
9700
9701         return correct;
9702 }
9703
9704 static bool run_dirtest1(int dummy)
9705 {
9706         int i;
9707         static struct cli_state *cli;
9708         uint16_t fnum;
9709         int num_seen;
9710         bool correct = True;
9711
9712         printf("starting directory test\n");
9713
9714         if (!torture_open_connection(&cli, 0)) {
9715                 return False;
9716         }
9717
9718         smbXcli_conn_set_sockopt(cli->conn, sockops);
9719
9720         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
9721         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
9722         cli_rmdir(cli, "\\LISTDIR");
9723         cli_mkdir(cli, "\\LISTDIR");
9724
9725         /* Create 1000 files and 1000 directories. */
9726         for (i=0;i<1000;i++) {
9727                 fstring fname;
9728                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
9729                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
9730                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
9731                                    0, 0, &fnum, NULL))) {
9732                         fprintf(stderr,"Failed to open %s\n", fname);
9733                         return False;
9734                 }
9735                 cli_close(cli, fnum);
9736         }
9737         for (i=0;i<1000;i++) {
9738                 fstring fname;
9739                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
9740                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
9741                         fprintf(stderr,"Failed to open %s\n", fname);
9742                         return False;
9743                 }
9744         }
9745
9746         /* Now ensure that doing an old list sees both files and directories. */
9747         num_seen = 0;
9748         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
9749         printf("num_seen = %d\n", num_seen );
9750         /* We should see 100 files + 1000 directories + . and .. */
9751         if (num_seen != 2002)
9752                 correct = False;
9753
9754         /* Ensure if we have the "must have" bits we only see the
9755          * relevent entries.
9756          */
9757         num_seen = 0;
9758         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
9759         printf("num_seen = %d\n", num_seen );
9760         if (num_seen != 1002)
9761                 correct = False;
9762
9763         num_seen = 0;
9764         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
9765         printf("num_seen = %d\n", num_seen );
9766         if (num_seen != 1000)
9767                 correct = False;
9768
9769         /* Delete everything. */
9770         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
9771         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
9772         cli_rmdir(cli, "\\LISTDIR");
9773
9774 #if 0
9775         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
9776         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
9777         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
9778 #endif
9779
9780         if (!torture_close_connection(cli)) {
9781                 correct = False;
9782         }
9783
9784         printf("finished dirtest1\n");
9785
9786         return correct;
9787 }
9788
9789 static bool run_error_map_extract(int dummy) {
9790
9791         static struct cli_state *c_dos;
9792         static struct cli_state *c_nt;
9793         NTSTATUS status;
9794
9795         uint32_t error;
9796
9797         uint32_t errnum;
9798         uint8_t errclass;
9799
9800         NTSTATUS nt_status;
9801
9802         fstring user;
9803
9804         /* NT-Error connection */
9805
9806         disable_spnego = true;
9807         if (!(c_nt = open_nbt_connection())) {
9808                 disable_spnego = false;
9809                 return False;
9810         }
9811         disable_spnego = false;
9812
9813         status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
9814                                  PROTOCOL_NT1);
9815
9816         if (!NT_STATUS_IS_OK(status)) {
9817                 printf("%s rejected the NT-error negprot (%s)\n", host,
9818                        nt_errstr(status));
9819                 cli_shutdown(c_nt);
9820                 return False;
9821         }
9822
9823         status = cli_session_setup_anon(c_nt);
9824         if (!NT_STATUS_IS_OK(status)) {
9825                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
9826                 return False;
9827         }
9828
9829         /* DOS-Error connection */
9830
9831         disable_spnego = true;
9832         force_dos_errors = true;
9833         if (!(c_dos = open_nbt_connection())) {
9834                 disable_spnego = false;
9835                 force_dos_errors = false;
9836                 return False;
9837         }
9838         disable_spnego = false;
9839         force_dos_errors = false;
9840
9841         status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
9842                                  PROTOCOL_NT1);
9843         if (!NT_STATUS_IS_OK(status)) {
9844                 printf("%s rejected the DOS-error negprot (%s)\n", host,
9845                        nt_errstr(status));
9846                 cli_shutdown(c_dos);
9847                 return False;
9848         }
9849
9850         status = cli_session_setup_anon(c_dos);
9851         if (!NT_STATUS_IS_OK(status)) {
9852                 printf("%s rejected the DOS-error initial session setup (%s)\n",
9853                         host, nt_errstr(status));
9854                 return False;
9855         }
9856
9857         c_nt->map_dos_errors = false;
9858         c_dos->map_dos_errors = false;
9859
9860         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
9861                 struct cli_credentials *user_creds = NULL;
9862
9863                 fstr_sprintf(user, "%X", error);
9864
9865                 user_creds = cli_session_creds_init(talloc_tos(),
9866                                                     user,
9867                                                     workgroup,
9868                                                     NULL, /* realm */
9869                                                     password,
9870                                                     false, /* use_kerberos */
9871                                                     false, /* fallback_after_kerberos */
9872                                                     false, /* use_ccache */
9873                                                     false); /* password_is_nt_hash */
9874                 if (user_creds == NULL) {
9875                         printf("cli_session_creds_init(%s) failed\n", user);
9876                         return false;
9877                 }
9878
9879                 status = cli_session_setup_creds(c_nt, user_creds);
9880                 if (NT_STATUS_IS_OK(status)) {
9881                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
9882                 }
9883
9884                 /* Case #1: 32-bit NT errors */
9885                 if (!NT_STATUS_IS_DOS(status)) {
9886                         nt_status = status;
9887                 } else {
9888                         printf("/** Dos error on NT connection! (%s) */\n", 
9889                                nt_errstr(status));
9890                         nt_status = NT_STATUS(0xc0000000);
9891                 }
9892
9893                 status = cli_session_setup_creds(c_dos, user_creds);
9894                 if (NT_STATUS_IS_OK(status)) {
9895                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
9896                 }
9897
9898                 /* Case #1: 32-bit NT errors */
9899                 if (NT_STATUS_IS_DOS(status)) {
9900                         printf("/** NT error on DOS connection! (%s) */\n", 
9901                                nt_errstr(status));
9902                         errnum = errclass = 0;
9903                 } else {
9904                         errclass = NT_STATUS_DOS_CLASS(status);
9905                         errnum = NT_STATUS_DOS_CODE(status);
9906                 }
9907
9908                 if (NT_STATUS_V(nt_status) != error) { 
9909                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
9910                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
9911                                get_nt_error_c_code(talloc_tos(), nt_status));
9912                 }
9913
9914                 printf("\t{%s,\t%s,\t%s},\n", 
9915                        smb_dos_err_class(errclass), 
9916                        smb_dos_err_name(errclass, errnum), 
9917                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
9918
9919                 TALLOC_FREE(user_creds);
9920         }
9921         return True;
9922 }
9923
9924 static bool run_sesssetup_bench(int dummy)
9925 {
9926         static struct cli_state *c;
9927         const char *fname = "\\file.dat";
9928         uint16_t fnum;
9929         NTSTATUS status;
9930         int i;
9931
9932         if (!torture_open_connection(&c, 0)) {
9933                 return false;
9934         }
9935
9936         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
9937                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
9938                               FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
9939         if (!NT_STATUS_IS_OK(status)) {
9940                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
9941                 return false;
9942         }
9943
9944         for (i=0; i<torture_numops; i++) {
9945                 status = cli_session_setup_creds(c, torture_creds);
9946                 if (!NT_STATUS_IS_OK(status)) {
9947                         d_printf("(%s) cli_session_setup_creds failed: %s\n",
9948                                  __location__, nt_errstr(status));
9949                         return false;
9950                 }
9951
9952                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
9953
9954                 status = cli_ulogoff(c);
9955                 if (!NT_STATUS_IS_OK(status)) {
9956                         d_printf("(%s) cli_ulogoff failed: %s\n",
9957                                  __location__, nt_errstr(status));
9958                         return false;
9959                 }
9960         }
9961
9962         return true;
9963 }
9964
9965 static bool subst_test(const char *str, const char *user, const char *domain,
9966                        uid_t uid, gid_t gid, const char *expected)
9967 {
9968         char *subst;
9969         bool result = true;
9970
9971         subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
9972
9973         if (strcmp(subst, expected) != 0) {
9974                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
9975                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
9976                        expected);
9977                 result = false;
9978         }
9979
9980         TALLOC_FREE(subst);
9981         return result;
9982 }
9983
9984 static void chain1_open_completion(struct tevent_req *req)
9985 {
9986         uint16_t fnum;
9987         NTSTATUS status;
9988         status = cli_openx_recv(req, &fnum);
9989         TALLOC_FREE(req);
9990
9991         d_printf("cli_openx_recv returned %s: %d\n",
9992                  nt_errstr(status),
9993                  NT_STATUS_IS_OK(status) ? fnum : -1);
9994 }
9995
9996 static void chain1_write_completion(struct tevent_req *req)
9997 {
9998         size_t written;
9999         NTSTATUS status;
10000         status = cli_write_andx_recv(req, &written);
10001         TALLOC_FREE(req);
10002
10003         d_printf("cli_write_andx_recv returned %s: %d\n",
10004                  nt_errstr(status),
10005                  NT_STATUS_IS_OK(status) ? (int)written : -1);
10006 }
10007
10008 static void chain1_close_completion(struct tevent_req *req)
10009 {
10010         NTSTATUS status;
10011         bool *done = (bool *)tevent_req_callback_data_void(req);
10012
10013         status = cli_close_recv(req);
10014         *done = true;
10015
10016         TALLOC_FREE(req);
10017
10018         d_printf("cli_close returned %s\n", nt_errstr(status));
10019 }
10020
10021 static bool run_chain1(int dummy)
10022 {
10023         struct cli_state *cli1;
10024         struct tevent_context *evt = samba_tevent_context_init(NULL);
10025         struct tevent_req *reqs[3], *smbreqs[3];
10026         bool done = false;
10027         const char *str = "foobar";
10028         const char *fname = "\\test_chain";
10029         NTSTATUS status;
10030
10031         printf("starting chain1 test\n");
10032         if (!torture_open_connection(&cli1, 0)) {
10033                 return False;
10034         }
10035
10036         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10037
10038         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10039
10040         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10041                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
10042         if (reqs[0] == NULL) return false;
10043         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10044
10045
10046         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10047                                         (const uint8_t *)str, 0, strlen(str)+1,
10048                                         smbreqs, 1, &smbreqs[1]);
10049         if (reqs[1] == NULL) return false;
10050         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10051
10052         reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10053         if (reqs[2] == NULL) return false;
10054         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10055
10056         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10057         if (!NT_STATUS_IS_OK(status)) {
10058                 return false;
10059         }
10060
10061         while (!done) {
10062                 tevent_loop_once(evt);
10063         }
10064
10065         torture_close_connection(cli1);
10066         return True;
10067 }
10068
10069 static void chain2_sesssetup_completion(struct tevent_req *req)
10070 {
10071         NTSTATUS status;
10072         status = cli_session_setup_guest_recv(req);
10073         d_printf("sesssetup returned %s\n", nt_errstr(status));
10074 }
10075
10076 static void chain2_tcon_completion(struct tevent_req *req)
10077 {
10078         bool *done = (bool *)tevent_req_callback_data_void(req);
10079         NTSTATUS status;
10080         status = cli_tcon_andx_recv(req);
10081         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10082         *done = true;
10083 }
10084
10085 static bool run_chain2(int dummy)
10086 {
10087         struct cli_state *cli1;
10088         struct tevent_context *evt = samba_tevent_context_init(NULL);
10089         struct tevent_req *reqs[2], *smbreqs[2];
10090         bool done = false;
10091         NTSTATUS status;
10092         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10093
10094         printf("starting chain2 test\n");
10095         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10096                                       port_to_use, SMB_SIGNING_DEFAULT, flags);
10097         if (!NT_STATUS_IS_OK(status)) {
10098                 return False;
10099         }
10100
10101         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10102
10103         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10104                                                  &smbreqs[0]);
10105         if (reqs[0] == NULL) return false;
10106         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10107
10108         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10109                                        "?????", NULL, 0, &smbreqs[1]);
10110         if (reqs[1] == NULL) return false;
10111         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10112
10113         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10114         if (!NT_STATUS_IS_OK(status)) {
10115                 return false;
10116         }
10117
10118         while (!done) {
10119                 tevent_loop_once(evt);
10120         }
10121
10122         torture_close_connection(cli1);
10123         return True;
10124 }
10125
10126
10127 struct torture_createdel_state {
10128         struct tevent_context *ev;
10129         struct cli_state *cli;
10130 };
10131
10132 static void torture_createdel_created(struct tevent_req *subreq);
10133 static void torture_createdel_closed(struct tevent_req *subreq);
10134
10135 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10136                                                  struct tevent_context *ev,
10137                                                  struct cli_state *cli,
10138                                                  const char *name)
10139 {
10140         struct tevent_req *req, *subreq;
10141         struct torture_createdel_state *state;
10142
10143         req = tevent_req_create(mem_ctx, &state,
10144                                 struct torture_createdel_state);
10145         if (req == NULL) {
10146                 return NULL;
10147         }
10148         state->ev = ev;
10149         state->cli = cli;
10150
10151         subreq = cli_ntcreate_send(
10152                 state, ev, cli, name, 0,
10153                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10154                 FILE_ATTRIBUTE_NORMAL,
10155                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10156                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10157                 SMB2_IMPERSONATION_IMPERSONATION, 0);
10158
10159         if (tevent_req_nomem(subreq, req)) {
10160                 return tevent_req_post(req, ev);
10161         }
10162         tevent_req_set_callback(subreq, torture_createdel_created, req);
10163         return req;
10164 }
10165
10166 static void torture_createdel_created(struct tevent_req *subreq)
10167 {
10168         struct tevent_req *req = tevent_req_callback_data(
10169                 subreq, struct tevent_req);
10170         struct torture_createdel_state *state = tevent_req_data(
10171                 req, struct torture_createdel_state);
10172         NTSTATUS status;
10173         uint16_t fnum;
10174
10175         status = cli_ntcreate_recv(subreq, &fnum, NULL);
10176         TALLOC_FREE(subreq);
10177         if (tevent_req_nterror(req, status)) {
10178                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10179                            nt_errstr(status)));
10180                 return;
10181         }
10182
10183         subreq = cli_close_send(state, state->ev, state->cli, fnum);
10184         if (tevent_req_nomem(subreq, req)) {
10185                 return;
10186         }
10187         tevent_req_set_callback(subreq, torture_createdel_closed, req);
10188 }
10189
10190 static void torture_createdel_closed(struct tevent_req *subreq)
10191 {
10192         struct tevent_req *req = tevent_req_callback_data(
10193                 subreq, struct tevent_req);
10194         NTSTATUS status;
10195
10196         status = cli_close_recv(subreq);
10197         if (tevent_req_nterror(req, status)) {
10198                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10199                 return;
10200         }
10201         tevent_req_done(req);
10202 }
10203
10204 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10205 {
10206         return tevent_req_simple_recv_ntstatus(req);
10207 }
10208
10209 struct torture_createdels_state {
10210         struct tevent_context *ev;
10211         struct cli_state *cli;
10212         const char *base_name;
10213         int sent;
10214         int received;
10215         int num_files;
10216         struct tevent_req **reqs;
10217 };
10218
10219 static void torture_createdels_done(struct tevent_req *subreq);
10220
10221 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10222                                                   struct tevent_context *ev,
10223                                                   struct cli_state *cli,
10224                                                   const char *base_name,
10225                                                   int num_parallel,
10226                                                   int num_files)
10227 {
10228         struct tevent_req *req;
10229         struct torture_createdels_state *state;
10230         int i;
10231
10232         req = tevent_req_create(mem_ctx, &state,
10233                                 struct torture_createdels_state);
10234         if (req == NULL) {
10235                 return NULL;
10236         }
10237         state->ev = ev;
10238         state->cli = cli;
10239         state->base_name = talloc_strdup(state, base_name);
10240         if (tevent_req_nomem(state->base_name, req)) {
10241                 return tevent_req_post(req, ev);
10242         }
10243         state->num_files = MAX(num_parallel, num_files);
10244         state->sent = 0;
10245         state->received = 0;
10246
10247         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10248         if (tevent_req_nomem(state->reqs, req)) {
10249                 return tevent_req_post(req, ev);
10250         }
10251
10252         for (i=0; i<num_parallel; i++) {
10253                 char *name;
10254
10255                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10256                                        state->sent);
10257                 if (tevent_req_nomem(name, req)) {
10258                         return tevent_req_post(req, ev);
10259                 }
10260                 state->reqs[i] = torture_createdel_send(
10261                         state->reqs, state->ev, state->cli, name);
10262                 if (tevent_req_nomem(state->reqs[i], req)) {
10263                         return tevent_req_post(req, ev);
10264                 }
10265                 name = talloc_move(state->reqs[i], &name);
10266                 tevent_req_set_callback(state->reqs[i],
10267                                         torture_createdels_done, req);
10268                 state->sent += 1;
10269         }
10270         return req;
10271 }
10272
10273 static void torture_createdels_done(struct tevent_req *subreq)
10274 {
10275         struct tevent_req *req = tevent_req_callback_data(
10276                 subreq, struct tevent_req);
10277         struct torture_createdels_state *state = tevent_req_data(
10278                 req, struct torture_createdels_state);
10279         size_t num_parallel = talloc_array_length(state->reqs);
10280         NTSTATUS status;
10281         char *name;
10282         int i;
10283
10284         status = torture_createdel_recv(subreq);
10285         if (!NT_STATUS_IS_OK(status)){
10286                 DEBUG(10, ("torture_createdel_recv returned %s\n",
10287                            nt_errstr(status)));
10288                 TALLOC_FREE(subreq);
10289                 tevent_req_nterror(req, status);
10290                 return;
10291         }
10292
10293         for (i=0; i<num_parallel; i++) {
10294                 if (subreq == state->reqs[i]) {
10295                         break;
10296                 }
10297         }
10298         if (i == num_parallel) {
10299                 DEBUG(10, ("received something we did not send\n"));
10300                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10301                 return;
10302         }
10303         TALLOC_FREE(state->reqs[i]);
10304
10305         if (state->sent >= state->num_files) {
10306                 tevent_req_done(req);
10307                 return;
10308         }
10309
10310         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10311                                state->sent);
10312         if (tevent_req_nomem(name, req)) {
10313                 return;
10314         }
10315         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10316                                                 state->cli, name);
10317         if (tevent_req_nomem(state->reqs[i], req)) {
10318                 return;
10319         }
10320         name = talloc_move(state->reqs[i], &name);
10321         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10322         state->sent += 1;
10323 }
10324
10325 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10326 {
10327         return tevent_req_simple_recv_ntstatus(req);
10328 }
10329
10330 struct swallow_notify_state {
10331         struct tevent_context *ev;
10332         struct cli_state *cli;
10333         uint16_t fnum;
10334         uint32_t completion_filter;
10335         bool recursive;
10336         bool (*fn)(uint32_t action, const char *name, void *priv);
10337         void *priv;
10338 };
10339
10340 static void swallow_notify_done(struct tevent_req *subreq);
10341
10342 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10343                                               struct tevent_context *ev,
10344                                               struct cli_state *cli,
10345                                               uint16_t fnum,
10346                                               uint32_t completion_filter,
10347                                               bool recursive,
10348                                               bool (*fn)(uint32_t action,
10349                                                          const char *name,
10350                                                          void *priv),
10351                                               void *priv)
10352 {
10353         struct tevent_req *req, *subreq;
10354         struct swallow_notify_state *state;
10355
10356         req = tevent_req_create(mem_ctx, &state,
10357                                 struct swallow_notify_state);
10358         if (req == NULL) {
10359                 return NULL;
10360         }
10361         state->ev = ev;
10362         state->cli = cli;
10363         state->fnum = fnum;
10364         state->completion_filter = completion_filter;
10365         state->recursive = recursive;
10366         state->fn = fn;
10367         state->priv = priv;
10368
10369         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10370                                  0xffff, state->completion_filter,
10371                                  state->recursive);
10372         if (tevent_req_nomem(subreq, req)) {
10373                 return tevent_req_post(req, ev);
10374         }
10375         tevent_req_set_callback(subreq, swallow_notify_done, req);
10376         return req;
10377 }
10378
10379 static void swallow_notify_done(struct tevent_req *subreq)
10380 {
10381         struct tevent_req *req = tevent_req_callback_data(
10382                 subreq, struct tevent_req);
10383         struct swallow_notify_state *state = tevent_req_data(
10384                 req, struct swallow_notify_state);
10385         NTSTATUS status;
10386         uint32_t i, num_changes;
10387         struct notify_change *changes;
10388
10389         status = cli_notify_recv(subreq, state, &num_changes, &changes);
10390         TALLOC_FREE(subreq);
10391         if (!NT_STATUS_IS_OK(status)) {
10392                 DEBUG(10, ("cli_notify_recv returned %s\n",
10393                            nt_errstr(status)));
10394                 tevent_req_nterror(req, status);
10395                 return;
10396         }
10397
10398         for (i=0; i<num_changes; i++) {
10399                 state->fn(changes[i].action, changes[i].name, state->priv);
10400         }
10401         TALLOC_FREE(changes);
10402
10403         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10404                                  0xffff, state->completion_filter,
10405                                  state->recursive);
10406         if (tevent_req_nomem(subreq, req)) {
10407                 return;
10408         }
10409         tevent_req_set_callback(subreq, swallow_notify_done, req);
10410 }
10411
10412 static bool print_notifies(uint32_t action, const char *name, void *priv)
10413 {
10414         if (DEBUGLEVEL > 5) {
10415                 d_printf("%d %s\n", (int)action, name);
10416         }
10417         return true;
10418 }
10419
10420 static void notify_bench_done(struct tevent_req *req)
10421 {
10422         int *num_finished = (int *)tevent_req_callback_data_void(req);
10423         *num_finished += 1;
10424 }
10425
10426 static bool run_notify_bench(int dummy)
10427 {
10428         const char *dname = "\\notify-bench";
10429         struct tevent_context *ev;
10430         NTSTATUS status;
10431         uint16_t dnum;
10432         struct tevent_req *req1;
10433         struct tevent_req *req2 = NULL;
10434         int i, num_unc_names;
10435         int num_finished = 0;
10436
10437         printf("starting notify-bench test\n");
10438
10439         if (use_multishare_conn) {
10440                 char **unc_list;
10441                 unc_list = file_lines_load(multishare_conn_fname,
10442                                            &num_unc_names, 0, NULL);
10443                 if (!unc_list || num_unc_names <= 0) {
10444                         d_printf("Failed to load unc names list from '%s'\n",
10445                                  multishare_conn_fname);
10446                         return false;
10447                 }
10448                 TALLOC_FREE(unc_list);
10449         } else {
10450                 num_unc_names = 1;
10451         }
10452
10453         ev = samba_tevent_context_init(talloc_tos());
10454         if (ev == NULL) {
10455                 d_printf("tevent_context_init failed\n");
10456                 return false;
10457         }
10458
10459         for (i=0; i<num_unc_names; i++) {
10460                 struct cli_state *cli;
10461                 char *base_fname;
10462
10463                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
10464                                              dname, i);
10465                 if (base_fname == NULL) {
10466                         return false;
10467                 }
10468
10469                 if (!torture_open_connection(&cli, i)) {
10470                         return false;
10471                 }
10472
10473                 status = cli_ntcreate(cli, dname, 0,
10474                                       MAXIMUM_ALLOWED_ACCESS,
10475                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
10476                                       FILE_SHARE_DELETE,
10477                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
10478                                       &dnum, NULL);
10479
10480                 if (!NT_STATUS_IS_OK(status)) {
10481                         d_printf("Could not create %s: %s\n", dname,
10482                                  nt_errstr(status));
10483                         return false;
10484                 }
10485
10486                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
10487                                            FILE_NOTIFY_CHANGE_FILE_NAME |
10488                                            FILE_NOTIFY_CHANGE_DIR_NAME |
10489                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
10490                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
10491                                            false, print_notifies, NULL);
10492                 if (req1 == NULL) {
10493                         d_printf("Could not create notify request\n");
10494                         return false;
10495                 }
10496
10497                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
10498                                                base_fname, 10, torture_numops);
10499                 if (req2 == NULL) {
10500                         d_printf("Could not create createdels request\n");
10501                         return false;
10502                 }
10503                 TALLOC_FREE(base_fname);
10504
10505                 tevent_req_set_callback(req2, notify_bench_done,
10506                                         &num_finished);
10507         }
10508
10509         while (num_finished < num_unc_names) {
10510                 int ret;
10511                 ret = tevent_loop_once(ev);
10512                 if (ret != 0) {
10513                         d_printf("tevent_loop_once failed\n");
10514                         return false;
10515                 }
10516         }
10517
10518         if (!tevent_req_poll(req2, ev)) {
10519                 d_printf("tevent_req_poll failed\n");
10520         }
10521
10522         status = torture_createdels_recv(req2);
10523         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
10524
10525         return true;
10526 }
10527
10528 static bool run_mangle1(int dummy)
10529 {
10530         struct cli_state *cli;
10531         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
10532         uint16_t fnum;
10533         fstring alt_name;
10534         NTSTATUS status;
10535         time_t change_time, access_time, write_time;
10536         off_t size;
10537         uint16_t mode;
10538
10539         printf("starting mangle1 test\n");
10540         if (!torture_open_connection(&cli, 0)) {
10541                 return False;
10542         }
10543
10544         smbXcli_conn_set_sockopt(cli->conn, sockops);
10545
10546         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10547                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10548                               0, 0, &fnum, NULL);
10549         if (!NT_STATUS_IS_OK(status)) {
10550                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10551                 return false;
10552         }
10553         cli_close(cli, fnum);
10554
10555         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
10556         if (!NT_STATUS_IS_OK(status)) {
10557                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
10558                          nt_errstr(status));
10559                 return false;
10560         }
10561         d_printf("alt_name: %s\n", alt_name);
10562
10563         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
10564         if (!NT_STATUS_IS_OK(status)) {
10565                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
10566                          nt_errstr(status));
10567                 return false;
10568         }
10569         cli_close(cli, fnum);
10570
10571         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
10572                                 &write_time, &size, &mode);
10573         if (!NT_STATUS_IS_OK(status)) {
10574                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
10575                          nt_errstr(status));
10576                 return false;
10577         }
10578
10579         return true;
10580 }
10581
10582 static NTSTATUS mangle_illegal_list_shortname_fn(const char *mntpoint,
10583                                                  struct file_info *f,
10584                                                  const char *mask,
10585                                                  void *state)
10586 {
10587         if (f->short_name == NULL) {
10588                 return NT_STATUS_OK;
10589         }
10590
10591         if (strlen(f->short_name) == 0) {
10592                 return NT_STATUS_OK;
10593         }
10594
10595         printf("unexpected shortname: %s\n", f->short_name);
10596
10597         return NT_STATUS_OBJECT_NAME_INVALID;
10598 }
10599
10600 static NTSTATUS mangle_illegal_list_name_fn(const char *mntpoint,
10601                                             struct file_info *f,
10602                                             const char *mask,
10603                                             void *state)
10604 {
10605         char *name = state;
10606
10607         printf("name: %s\n", f->name);
10608         fstrcpy(name, f->name);
10609         return NT_STATUS_OK;
10610 }
10611
10612 static bool run_mangle_illegal(int dummy)
10613 {
10614         struct cli_state *cli = NULL;
10615         struct cli_state *cli_posix = NULL;
10616         const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
10617         const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
10618         char *mangled_path = NULL;
10619         uint16_t fnum;
10620         fstring name;
10621         fstring alt_name;
10622         NTSTATUS status;
10623
10624         printf("starting mangle-illegal test\n");
10625
10626         if (!torture_open_connection(&cli, 0)) {
10627                 return False;
10628         }
10629
10630         smbXcli_conn_set_sockopt(cli->conn, sockops);
10631
10632         if (!torture_open_connection(&cli_posix, 0)) {
10633                 return false;
10634         }
10635
10636         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
10637
10638         status = torture_setup_unix_extensions(cli_posix);
10639         if (!NT_STATUS_IS_OK(status)) {
10640                 return false;
10641         }
10642
10643         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
10644         status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
10645         if (!NT_STATUS_IS_OK(status)) {
10646                 printf("mkdir1 failed : %s\n", nt_errstr(status));
10647                 return False;
10648         }
10649
10650         /*
10651          * Create a file with illegal NTFS characters and test that we
10652          * get a usable mangled name
10653          */
10654
10655         cli_setatr(cli_posix, illegal_fname, 0, 0);
10656         cli_posix_unlink(cli_posix, illegal_fname);
10657
10658         status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
10659                                 0600, &fnum);
10660         if (!NT_STATUS_IS_OK(status)) {
10661                 printf("POSIX create of %s failed (%s)\n",
10662                        illegal_fname, nt_errstr(status));
10663                 return false;
10664         }
10665
10666         status = cli_close(cli_posix, fnum);
10667         if (!NT_STATUS_IS_OK(status)) {
10668                 printf("close failed (%s)\n", nt_errstr(status));
10669                 return false;
10670         }
10671
10672         status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
10673         if (!NT_STATUS_IS_OK(status)) {
10674                 d_printf("cli_list failed: %s\n", nt_errstr(status));
10675                 return false;
10676         }
10677
10678         mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
10679         if (mangled_path == NULL) {
10680                 return false;
10681         }
10682
10683         status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
10684         if (!NT_STATUS_IS_OK(status)) {
10685                 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
10686                 TALLOC_FREE(mangled_path);
10687                 return false;
10688         }
10689         TALLOC_FREE(mangled_path);
10690         cli_close(cli, fnum);
10691
10692         cli_setatr(cli_posix, illegal_fname, 0, 0);
10693         cli_posix_unlink(cli_posix, illegal_fname);
10694
10695         /*
10696          * Create a file with a long name and check that we got *no* short name.
10697          */
10698
10699         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10700                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10701                               0, 0, &fnum, NULL);
10702         if (!NT_STATUS_IS_OK(status)) {
10703                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10704                 return false;
10705         }
10706         cli_close(cli, fnum);
10707
10708         status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
10709         if (!NT_STATUS_IS_OK(status)) {
10710                 d_printf("cli_list failed\n");
10711                 return false;
10712         }
10713
10714         cli_unlink(cli, fname, 0);
10715         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
10716
10717         if (!torture_close_connection(cli_posix)) {
10718                 return false;
10719         }
10720
10721         if (!torture_close_connection(cli)) {
10722                 return false;
10723         }
10724
10725         return true;
10726 }
10727
10728 static size_t null_source(uint8_t *buf, size_t n, void *priv)
10729 {
10730         size_t *to_pull = (size_t *)priv;
10731         size_t thistime = *to_pull;
10732
10733         thistime = MIN(thistime, n);
10734         if (thistime == 0) {
10735                 return 0;
10736         }
10737
10738         memset(buf, 0, thistime);
10739         *to_pull -= thistime;
10740         return thistime;
10741 }
10742
10743 static bool run_windows_write(int dummy)
10744 {
10745         struct cli_state *cli1;
10746         uint16_t fnum;
10747         int i;
10748         bool ret = false;
10749         const char *fname = "\\writetest.txt";
10750         struct timeval start_time;
10751         double seconds;
10752         double kbytes;
10753         NTSTATUS status;
10754
10755         printf("starting windows_write test\n");
10756         if (!torture_open_connection(&cli1, 0)) {
10757                 return False;
10758         }
10759
10760         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
10761         if (!NT_STATUS_IS_OK(status)) {
10762                 printf("open failed (%s)\n", nt_errstr(status));
10763                 return False;
10764         }
10765
10766         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10767
10768         start_time = timeval_current();
10769
10770         for (i=0; i<torture_numops; i++) {
10771                 uint8_t c = 0;
10772                 off_t start = i * torture_blocksize;
10773                 size_t to_pull = torture_blocksize - 1;
10774
10775                 status = cli_writeall(cli1, fnum, 0, &c,
10776                                       start + torture_blocksize - 1, 1, NULL);
10777                 if (!NT_STATUS_IS_OK(status)) {
10778                         printf("cli_write failed: %s\n", nt_errstr(status));
10779                         goto fail;
10780                 }
10781
10782                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
10783                                   null_source, &to_pull);
10784                 if (!NT_STATUS_IS_OK(status)) {
10785                         printf("cli_push returned: %s\n", nt_errstr(status));
10786                         goto fail;
10787                 }
10788         }
10789
10790         seconds = timeval_elapsed(&start_time);
10791         kbytes = (double)torture_blocksize * torture_numops;
10792         kbytes /= 1024;
10793
10794         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
10795                (double)seconds, (int)(kbytes/seconds));
10796
10797         ret = true;
10798  fail:
10799         cli_close(cli1, fnum);
10800         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10801         torture_close_connection(cli1);
10802         return ret;
10803 }
10804
10805 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
10806 {
10807         size_t max_pdu = 0x1FFFF;
10808
10809         if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
10810                 max_pdu = 0xFFFFFF;
10811         }
10812
10813         if (smb1cli_conn_signing_is_active(cli->conn)) {
10814                 max_pdu = 0x1FFFF;
10815         }
10816
10817         if (smb1cli_conn_encryption_on(cli->conn)) {
10818                 max_pdu = CLI_BUFFER_SIZE;
10819         }
10820
10821         if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
10822                 len_requested &= 0xFFFF;
10823         }
10824
10825         return MIN(len_requested,
10826                    max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
10827 }
10828
10829 static bool check_read_call(struct cli_state *cli,
10830                             uint16_t fnum,
10831                             uint8_t *buf,
10832                             size_t len_requested)
10833 {
10834         NTSTATUS status;
10835         struct tevent_req *subreq = NULL;
10836         ssize_t len_read = 0;
10837         size_t len_expected = 0;
10838         struct tevent_context *ev = NULL;
10839
10840         ev = samba_tevent_context_init(talloc_tos());
10841         if (ev == NULL) {
10842                 return false;
10843         }
10844
10845         subreq = cli_read_andx_send(talloc_tos(),
10846                                     ev,
10847                                     cli,
10848                                     fnum,
10849                                     0,
10850                                     len_requested);
10851
10852         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
10853                 return false;
10854         }
10855
10856         status = cli_read_andx_recv(subreq, &len_read, &buf);
10857         if (!NT_STATUS_IS_OK(status)) {
10858                 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
10859                 return false;
10860         }
10861
10862         TALLOC_FREE(subreq);
10863         TALLOC_FREE(ev);
10864
10865         len_expected = calc_expected_return(cli, len_requested);
10866
10867         if (len_expected > 0x10000 && len_read == 0x10000) {
10868                 /* Windows servers only return a max of 0x10000,
10869                    doesn't matter if you set CAP_LARGE_READX in
10870                    the client sessionsetupX call or not. */
10871                 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
10872                         (unsigned int)len_requested);
10873         } else if (len_read != len_expected) {
10874                 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
10875                         (unsigned int)len_requested,
10876                         (unsigned int)len_read,
10877                         (unsigned int)len_expected);
10878                 return false;
10879         } else {
10880                 d_printf("Correct read reply.\n");
10881         }
10882
10883         return true;
10884 }
10885
10886 /* Test large readX variants. */
10887 static bool large_readx_tests(struct cli_state *cli,
10888                                 uint16_t fnum,
10889                                 uint8_t *buf)
10890 {
10891         /* A read of 0xFFFF0001 should *always* return 1 byte. */
10892         if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
10893                 return false;
10894         }
10895         /* A read of 0x10000 should return 0x10000 bytes. */
10896         if (check_read_call(cli, fnum, buf,    0x10000) == false) {
10897                 return false;
10898         }
10899         /* A read of 0x10000 should return 0x10001 bytes. */
10900         if (check_read_call(cli, fnum, buf,    0x10001) == false) {
10901                 return false;
10902         }
10903         /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
10904            the requested number of bytes. */
10905         if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
10906                 return false;
10907         }
10908         /* A read of 1MB should return 1MB bytes (on Samba). */
10909         if (check_read_call(cli, fnum, buf,   0x100000) == false) {
10910                 return false;
10911         }
10912
10913         if (check_read_call(cli, fnum, buf,    0x20001) == false) {
10914                 return false;
10915         }
10916         if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
10917                 return false;
10918         }
10919         if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
10920                 return false;
10921         }
10922         return true;
10923 }
10924
10925 static bool run_large_readx(int dummy)
10926 {
10927         uint8_t *buf = NULL;
10928         struct cli_state *cli1 = NULL;
10929         struct cli_state *cli2 = NULL;
10930         bool correct = false;
10931         const char *fname = "\\large_readx.dat";
10932         NTSTATUS status;
10933         uint16_t fnum1 = UINT16_MAX;
10934         uint32_t normal_caps = 0;
10935         size_t file_size = 20*1024*1024;
10936         TALLOC_CTX *frame = talloc_stackframe();
10937         size_t i;
10938         struct {
10939                 const char *name;
10940                 enum smb_signing_setting signing_setting;
10941                 enum protocol_types protocol;
10942         } runs[] = {
10943                 {
10944                         .name = "NT1",
10945                         .signing_setting = SMB_SIGNING_IF_REQUIRED,
10946                         .protocol = PROTOCOL_NT1,
10947                 },{
10948                         .name = "NT1 - SIGNING_REQUIRED",
10949                         .signing_setting = SMB_SIGNING_REQUIRED,
10950                         .protocol = PROTOCOL_NT1,
10951                 },
10952         };
10953
10954         printf("starting large_readx test\n");
10955
10956         if (!torture_open_connection(&cli1, 0)) {
10957                 goto out;
10958         }
10959
10960         normal_caps = smb1cli_conn_capabilities(cli1->conn);
10961
10962         if (!(normal_caps & CAP_LARGE_READX)) {
10963                 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
10964                         (unsigned int)normal_caps);
10965                 goto out;
10966         }
10967
10968         /* Create a file of size 4MB. */
10969         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
10970                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10971                         0, 0, &fnum1, NULL);
10972
10973         if (!NT_STATUS_IS_OK(status)) {
10974                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10975                 goto out;
10976         }
10977
10978         /* Write file_size bytes. */
10979         buf = talloc_zero_array(frame, uint8_t, file_size);
10980         if (buf == NULL) {
10981                 goto out;
10982         }
10983
10984         status = cli_writeall(cli1,
10985                               fnum1,
10986                               0,
10987                               buf,
10988                               0,
10989                               file_size,
10990                               NULL);
10991         if (!NT_STATUS_IS_OK(status)) {
10992                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
10993                 goto out;
10994         }
10995
10996         status = cli_close(cli1, fnum1);
10997         if (!NT_STATUS_IS_OK(status)) {
10998                 d_printf("cli_close failed: %s\n", nt_errstr(status));
10999                 goto out;
11000         }
11001
11002         fnum1 = UINT16_MAX;
11003
11004         for (i=0; i < ARRAY_SIZE(runs); i++) {
11005                 enum smb_signing_setting saved_signing_setting = signing_state;
11006                 uint16_t fnum2 = -1;
11007
11008                 if (do_encrypt &&
11009                     (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11010                 {
11011                         d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11012                         continue;
11013                 }
11014
11015                 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11016
11017                 signing_state = runs[i].signing_setting;
11018                 cli2 = open_nbt_connection();
11019                 signing_state = saved_signing_setting;
11020                 if (cli2 == NULL) {
11021                         goto out;
11022                 }
11023
11024                 status = smbXcli_negprot(cli2->conn,
11025                                          cli2->timeout,
11026                                          runs[i].protocol,
11027                                          runs[i].protocol);
11028                 if (!NT_STATUS_IS_OK(status)) {
11029                         goto out;
11030                 }
11031
11032                 status = cli_session_setup_creds(cli2, torture_creds);
11033                 if (!NT_STATUS_IS_OK(status)) {
11034                         goto out;
11035                 }
11036
11037                 status = cli_tree_connect(cli2,
11038                                         share,
11039                                         "?????",
11040                                         password);
11041                 if (!NT_STATUS_IS_OK(status)) {
11042                         goto out;
11043                 }
11044
11045                 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11046
11047                 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11048
11049                 if (!(normal_caps & CAP_LARGE_READX)) {
11050                         d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11051                                 (unsigned int)normal_caps);
11052                         goto out;
11053                 }
11054
11055                 if (do_encrypt) {
11056                         if (force_cli_encryption(cli2, share) == false) {
11057                                 goto out;
11058                         }
11059                 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11060                         uint16_t major, minor;
11061                         uint32_t caplow, caphigh;
11062
11063                         status = cli_unix_extensions_version(cli2,
11064                                                              &major, &minor,
11065                                                              &caplow, &caphigh);
11066                         if (!NT_STATUS_IS_OK(status)) {
11067                                 goto out;
11068                         }
11069                 }
11070
11071                 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11072                                 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11073                                 0, 0, &fnum2, NULL);
11074                 if (!NT_STATUS_IS_OK(status)) {
11075                         d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11076                         goto out;
11077                 }
11078
11079                 /* All reads must return less than file_size bytes. */
11080                 if (!large_readx_tests(cli2, fnum2, buf)) {
11081                         goto out;
11082                 }
11083
11084                 status = cli_close(cli2, fnum2);
11085                 if (!NT_STATUS_IS_OK(status)) {
11086                         d_printf("cli_close failed: %s\n", nt_errstr(status));
11087                         goto out;
11088                 }
11089                 fnum2 = -1;
11090
11091                 if (!torture_close_connection(cli2)) {
11092                         goto out;
11093                 }
11094                 cli2 = NULL;
11095         }
11096
11097         correct = true;
11098         printf("Success on large_readx test\n");
11099
11100   out:
11101
11102         if (cli2) {
11103                 if (!torture_close_connection(cli2)) {
11104                         correct = false;
11105                 }
11106         }
11107
11108         if (cli1) {
11109                 if (fnum1 != UINT16_MAX) {
11110                         status = cli_close(cli1, fnum1);
11111                         if (!NT_STATUS_IS_OK(status)) {
11112                                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11113                         }
11114                         fnum1 = UINT16_MAX;
11115                 }
11116
11117                 status = cli_unlink(cli1, fname,
11118                                     FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11119                 if (!NT_STATUS_IS_OK(status)) {
11120                         printf("unlink failed (%s)\n", nt_errstr(status));
11121                 }
11122
11123                 if (!torture_close_connection(cli1)) {
11124                         correct = false;
11125                 }
11126         }
11127
11128         TALLOC_FREE(frame);
11129
11130         printf("finished large_readx test\n");
11131         return correct;
11132 }
11133
11134 static bool run_cli_echo(int dummy)
11135 {
11136         struct cli_state *cli;
11137         NTSTATUS status;
11138
11139         printf("starting cli_echo test\n");
11140         if (!torture_open_connection(&cli, 0)) {
11141                 return false;
11142         }
11143         smbXcli_conn_set_sockopt(cli->conn, sockops);
11144
11145         status = cli_echo(cli, 5, data_blob_const("hello", 5));
11146
11147         d_printf("cli_echo returned %s\n", nt_errstr(status));
11148
11149         torture_close_connection(cli);
11150         return NT_STATUS_IS_OK(status);
11151 }
11152
11153 static int splice_status(off_t written, void *priv)
11154 {
11155         return true;
11156 }
11157
11158 static bool run_cli_splice(int dummy)
11159 {
11160         uint8_t *buf = NULL;
11161         struct cli_state *cli1 = NULL;
11162         bool correct = false;
11163         const char *fname_src = "\\splice_src.dat";
11164         const char *fname_dst = "\\splice_dst.dat";
11165         NTSTATUS status;
11166         uint16_t fnum1 = UINT16_MAX;
11167         uint16_t fnum2 = UINT16_MAX;
11168         size_t file_size = 2*1024*1024;
11169         size_t splice_size = 1*1024*1024 + 713;
11170         uint8_t digest1[16], digest2[16];
11171         off_t written = 0;
11172         size_t nread = 0;
11173         TALLOC_CTX *frame = talloc_stackframe();
11174
11175         printf("starting cli_splice test\n");
11176
11177         if (!torture_open_connection(&cli1, 0)) {
11178                 goto out;
11179         }
11180
11181         cli_unlink(cli1, fname_src,
11182                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11183         cli_unlink(cli1, fname_dst,
11184                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11185
11186         /* Create a file */
11187         status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11188                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11189                         0, 0, &fnum1, NULL);
11190
11191         if (!NT_STATUS_IS_OK(status)) {
11192                 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11193                 goto out;
11194         }
11195
11196         /* Write file_size bytes - must be bigger than splice_size. */
11197         buf = talloc_zero_array(frame, uint8_t, file_size);
11198         if (buf == NULL) {
11199                 d_printf("talloc_fail\n");
11200                 goto out;
11201         }
11202
11203         /* Fill it with random numbers. */
11204         generate_random_buffer(buf, file_size);
11205
11206         /* MD5 the first 1MB + 713 bytes. */
11207         gnutls_hash_fast(GNUTLS_DIG_MD5,
11208                          buf,
11209                          splice_size,
11210                          digest1);
11211
11212         status = cli_writeall(cli1,
11213                               fnum1,
11214                               0,
11215                               buf,
11216                               0,
11217                               file_size,
11218                               NULL);
11219         if (!NT_STATUS_IS_OK(status)) {
11220                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11221                 goto out;
11222         }
11223
11224         status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11225                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11226                         0, 0, &fnum2, NULL);
11227
11228         if (!NT_STATUS_IS_OK(status)) {
11229                 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11230                 goto out;
11231         }
11232
11233         /* Now splice 1MB + 713 bytes. */
11234         status = cli_splice(cli1,
11235                                 cli1,
11236                                 fnum1,
11237                                 fnum2,
11238                                 splice_size,
11239                                 0,
11240                                 0,
11241                                 &written,
11242                                 splice_status,
11243                                 NULL);
11244
11245         if (!NT_STATUS_IS_OK(status)) {
11246                 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11247                 goto out;
11248         }
11249
11250         /* Clear the old buffer. */
11251         memset(buf, '\0', file_size);
11252
11253         /* Read the new file. */
11254         status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11255         if (!NT_STATUS_IS_OK(status)) {
11256                 d_printf("cli_read failed: %s\n", nt_errstr(status));
11257                 goto out;
11258         }
11259         if (nread != splice_size) {
11260                 d_printf("bad read of 0x%x, should be 0x%x\n",
11261                         (unsigned int)nread,
11262                         (unsigned int)splice_size);
11263                 goto out;
11264         }
11265
11266         /* MD5 the first 1MB + 713 bytes. */
11267         gnutls_hash_fast(GNUTLS_DIG_MD5,
11268                          buf,
11269                          splice_size,
11270                          digest2);
11271
11272         /* Must be the same. */
11273         if (memcmp(digest1, digest2, 16) != 0) {
11274                 d_printf("bad MD5 compare\n");
11275                 goto out;
11276         }
11277
11278         correct = true;
11279         printf("Success on cli_splice test\n");
11280
11281   out:
11282
11283         if (cli1) {
11284                 if (fnum1 != UINT16_MAX) {
11285                         cli_close(cli1, fnum1);
11286                 }
11287                 if (fnum2 != UINT16_MAX) {
11288                         cli_close(cli1, fnum2);
11289                 }
11290
11291                 cli_unlink(cli1, fname_src,
11292                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11293                 cli_unlink(cli1, fname_dst,
11294                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11295
11296                 if (!torture_close_connection(cli1)) {
11297                         correct = false;
11298                 }
11299         }
11300
11301         TALLOC_FREE(frame);
11302         return correct;
11303 }
11304
11305 static bool run_uid_regression_test(int dummy)
11306 {
11307         static struct cli_state *cli;
11308         int16_t old_vuid;
11309         int32_t old_cnum;
11310         bool correct = True;
11311         struct smbXcli_tcon *orig_tcon = NULL;
11312         NTSTATUS status;
11313
11314         printf("starting uid regression test\n");
11315
11316         if (!torture_open_connection(&cli, 0)) {
11317                 return False;
11318         }
11319
11320         smbXcli_conn_set_sockopt(cli->conn, sockops);
11321
11322         /* Ok - now save then logoff our current user. */
11323         old_vuid = cli_state_get_uid(cli);
11324
11325         status = cli_ulogoff(cli);
11326         if (!NT_STATUS_IS_OK(status)) {
11327                 d_printf("(%s) cli_ulogoff failed: %s\n",
11328                          __location__, nt_errstr(status));
11329                 correct = false;
11330                 goto out;
11331         }
11332
11333         cli_state_set_uid(cli, old_vuid);
11334
11335         /* Try an operation. */
11336         status = cli_mkdir(cli, "\\uid_reg_test");
11337         if (NT_STATUS_IS_OK(status)) {
11338                 d_printf("(%s) cli_mkdir succeeded\n",
11339                          __location__);
11340                 correct = false;
11341                 goto out;
11342         } else {
11343                 /* Should be bad uid. */
11344                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11345                                  NT_STATUS_USER_SESSION_DELETED)) {
11346                         correct = false;
11347                         goto out;
11348                 }
11349         }
11350
11351         old_cnum = cli_state_get_tid(cli);
11352         orig_tcon = cli_state_save_tcon(cli);
11353         if (orig_tcon == NULL) {
11354                 correct = false;
11355                 goto out;
11356         }
11357
11358         /* Now try a SMBtdis with the invalid vuid set to zero. */
11359         cli_state_set_uid(cli, 0);
11360
11361         /* This should succeed. */
11362         status = cli_tdis(cli);
11363
11364         if (NT_STATUS_IS_OK(status)) {
11365                 d_printf("First tdis with invalid vuid should succeed.\n");
11366         } else {
11367                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
11368                 correct = false;
11369                 cli_state_restore_tcon(cli, orig_tcon);
11370                 goto out;
11371         }
11372
11373         cli_state_restore_tcon(cli, orig_tcon);
11374         cli_state_set_uid(cli, old_vuid);
11375         cli_state_set_tid(cli, old_cnum);
11376
11377         /* This should fail. */
11378         status = cli_tdis(cli);
11379         if (NT_STATUS_IS_OK(status)) {
11380                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
11381                 correct = false;
11382                 goto out;
11383         } else {
11384                 /* Should be bad tid. */
11385                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
11386                                 NT_STATUS_NETWORK_NAME_DELETED)) {
11387                         correct = false;
11388                         goto out;
11389                 }
11390         }
11391
11392         cli_rmdir(cli, "\\uid_reg_test");
11393
11394   out:
11395
11396         cli_shutdown(cli);
11397         return correct;
11398 }
11399
11400
11401 static const char *illegal_chars = "*\\/?<>|\":";
11402 static char force_shortname_chars[] = " +,.[];=\177";
11403
11404 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
11405                              const char *mask, void *state)
11406 {
11407         struct cli_state *pcli = (struct cli_state *)state;
11408         fstring fname;
11409         NTSTATUS status = NT_STATUS_OK;
11410
11411         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
11412
11413         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
11414                 return NT_STATUS_OK;
11415
11416         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
11417                 status = cli_rmdir(pcli, fname);
11418                 if (!NT_STATUS_IS_OK(status)) {
11419                         printf("del_fn: failed to rmdir %s\n,", fname );
11420                 }
11421         } else {
11422                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11423                 if (!NT_STATUS_IS_OK(status)) {
11424                         printf("del_fn: failed to unlink %s\n,", fname );
11425                 }
11426         }
11427         return status;
11428 }
11429
11430 struct sn_state {
11431         int matched;
11432         int i;
11433         bool val;
11434 };
11435
11436 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
11437                               const char *name, void *state)
11438 {
11439         struct sn_state *s = (struct sn_state  *)state;
11440         int i = s->i;
11441
11442 #if 0
11443         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
11444                 i, finfo->name, finfo->short_name);
11445 #endif
11446
11447         if (strchr(force_shortname_chars, i)) {
11448                 if (!finfo->short_name) {
11449                         /* Shortname not created when it should be. */
11450                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
11451                                 __location__, finfo->name, i);
11452                         s->val = true;
11453                 }
11454         } else if (finfo->short_name){
11455                 /* Shortname created when it should not be. */
11456                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
11457                         __location__, finfo->short_name, finfo->name);
11458                 s->val = true;
11459         }
11460         s->matched += 1;
11461         return NT_STATUS_OK;
11462 }
11463
11464 static bool run_shortname_test(int dummy)
11465 {
11466         static struct cli_state *cli;
11467         bool correct = True;
11468         int i;
11469         struct sn_state s;
11470         char fname[40];
11471         NTSTATUS status;
11472
11473         printf("starting shortname test\n");
11474
11475         if (!torture_open_connection(&cli, 0)) {
11476                 return False;
11477         }
11478
11479         smbXcli_conn_set_sockopt(cli->conn, sockops);
11480
11481         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11482         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11483         cli_rmdir(cli, "\\shortname");
11484
11485         status = cli_mkdir(cli, "\\shortname");
11486         if (!NT_STATUS_IS_OK(status)) {
11487                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
11488                         __location__, nt_errstr(status));
11489                 correct = false;
11490                 goto out;
11491         }
11492
11493         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
11494                 correct = false;
11495                 goto out;
11496         }
11497         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
11498                 correct = false;
11499                 goto out;
11500         }
11501
11502         s.val = false;
11503
11504         for (i = 32; i < 128; i++) {
11505                 uint16_t fnum = (uint16_t)-1;
11506
11507                 s.i = i;
11508
11509                 if (strchr(illegal_chars, i)) {
11510                         continue;
11511                 }
11512                 fname[15] = i;
11513
11514                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
11515                                    FILE_SHARE_READ|FILE_SHARE_WRITE,
11516                                    FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
11517                 if (!NT_STATUS_IS_OK(status)) {
11518                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
11519                                 __location__, fname, nt_errstr(status));
11520                         correct = false;
11521                         goto out;
11522                 }
11523                 cli_close(cli, fnum);
11524
11525                 s.matched = 0;
11526                 status = cli_list(cli, "\\shortname\\test*.*", 0,
11527                                   shortname_list_fn, &s);
11528                 if (s.matched != 1) {
11529                         d_printf("(%s) failed to list %s: %s\n",
11530                                 __location__, fname, nt_errstr(status));
11531                         correct = false;
11532                         goto out;
11533                 }
11534
11535                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11536                 if (!NT_STATUS_IS_OK(status)) {
11537                         d_printf("(%s) failed to delete %s: %s\n",
11538                                 __location__, fname, nt_errstr(status));
11539                         correct = false;
11540                         goto out;
11541                 }
11542
11543                 if (s.val) {
11544                         correct = false;
11545                         goto out;
11546                 }
11547         }
11548
11549   out:
11550
11551         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11552         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11553         cli_rmdir(cli, "\\shortname");
11554         torture_close_connection(cli);
11555         return correct;
11556 }
11557
11558 static void pagedsearch_cb(struct tevent_req *req)
11559 {
11560         TLDAPRC rc;
11561         struct tldap_message *msg;
11562         char *dn;
11563
11564         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
11565         if (!TLDAP_RC_IS_SUCCESS(rc)) {
11566                 d_printf("tldap_search_paged_recv failed: %s\n",
11567                          tldap_rc2string(rc));
11568                 return;
11569         }
11570         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
11571                 TALLOC_FREE(msg);
11572                 return;
11573         }
11574         if (!tldap_entry_dn(msg, &dn)) {
11575                 d_printf("tldap_entry_dn failed\n");
11576                 return;
11577         }
11578         d_printf("%s\n", dn);
11579         TALLOC_FREE(msg);
11580 }
11581
11582 static bool run_tldap(int dummy)
11583 {
11584         struct tldap_context *ld;
11585         int fd;
11586         TLDAPRC rc;
11587         NTSTATUS status;
11588         struct sockaddr_storage addr;
11589         struct tevent_context *ev;
11590         struct tevent_req *req;
11591         char *basedn;
11592         const char *filter;
11593
11594         if (!resolve_name(host, &addr, 0, false)) {
11595                 d_printf("could not find host %s\n", host);
11596                 return false;
11597         }
11598         status = open_socket_out(&addr, 389, 9999, &fd);
11599         if (!NT_STATUS_IS_OK(status)) {
11600                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
11601                 return false;
11602         }
11603
11604         ld = tldap_context_create(talloc_tos(), fd);
11605         if (ld == NULL) {
11606                 close(fd);
11607                 d_printf("tldap_context_create failed\n");
11608                 return false;
11609         }
11610
11611         rc = tldap_fetch_rootdse(ld);
11612         if (!TLDAP_RC_IS_SUCCESS(rc)) {
11613                 d_printf("tldap_fetch_rootdse failed: %s\n",
11614                          tldap_errstr(talloc_tos(), ld, rc));
11615                 return false;
11616         }
11617
11618         basedn = tldap_talloc_single_attribute(
11619                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
11620         if (basedn == NULL) {
11621                 d_printf("no defaultNamingContext\n");
11622                 return false;
11623         }
11624         d_printf("defaultNamingContext: %s\n", basedn);
11625
11626         ev = samba_tevent_context_init(talloc_tos());
11627         if (ev == NULL) {
11628                 d_printf("tevent_context_init failed\n");
11629                 return false;
11630         }
11631
11632         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
11633                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
11634                                       NULL, 0, 0,
11635                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
11636         if (req == NULL) {
11637                 d_printf("tldap_search_paged_send failed\n");
11638                 return false;
11639         }
11640         tevent_req_set_callback(req, pagedsearch_cb, NULL);
11641
11642         tevent_req_poll(req, ev);
11643
11644         TALLOC_FREE(req);
11645
11646         /* test search filters against rootDSE */
11647         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
11648                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
11649
11650         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
11651                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
11652                           talloc_tos(), NULL);
11653         if (!TLDAP_RC_IS_SUCCESS(rc)) {
11654                 d_printf("tldap_search with complex filter failed: %s\n",
11655                          tldap_errstr(talloc_tos(), ld, rc));
11656                 return false;
11657         }
11658
11659         TALLOC_FREE(ld);
11660         return true;
11661 }
11662
11663 /* Torture test to ensure no regression of :
11664 https://bugzilla.samba.org/show_bug.cgi?id=7084
11665 */
11666
11667 static bool run_dir_createtime(int dummy)
11668 {
11669         struct cli_state *cli;
11670         const char *dname = "\\testdir_createtime";
11671         const char *fname = "\\testdir_createtime\\testfile";
11672         NTSTATUS status;
11673         struct timespec create_time;
11674         struct timespec create_time1;
11675         uint16_t fnum;
11676         bool ret = false;
11677
11678         if (!torture_open_connection(&cli, 0)) {
11679                 return false;
11680         }
11681
11682         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11683         cli_rmdir(cli, dname);
11684
11685         status = cli_mkdir(cli, dname);
11686         if (!NT_STATUS_IS_OK(status)) {
11687                 printf("mkdir failed: %s\n", nt_errstr(status));
11688                 goto out;
11689         }
11690
11691         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
11692                                 NULL, NULL, NULL);
11693         if (!NT_STATUS_IS_OK(status)) {
11694                 printf("cli_qpathinfo2 returned %s\n",
11695                        nt_errstr(status));
11696                 goto out;
11697         }
11698
11699         /* Sleep 3 seconds, then create a file. */
11700         sleep(3);
11701
11702         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
11703                          DENY_NONE, &fnum);
11704         if (!NT_STATUS_IS_OK(status)) {
11705                 printf("cli_openx failed: %s\n", nt_errstr(status));
11706                 goto out;
11707         }
11708
11709         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
11710                                 NULL, NULL, NULL);
11711         if (!NT_STATUS_IS_OK(status)) {
11712                 printf("cli_qpathinfo2 (2) returned %s\n",
11713                        nt_errstr(status));
11714                 goto out;
11715         }
11716
11717         if (timespec_compare(&create_time1, &create_time)) {
11718                 printf("run_dir_createtime: create time was updated (error)\n");
11719         } else {
11720                 printf("run_dir_createtime: create time was not updated (correct)\n");
11721                 ret = true;
11722         }
11723
11724   out:
11725
11726         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11727         cli_rmdir(cli, dname);
11728         if (!torture_close_connection(cli)) {
11729                 ret = false;
11730         }
11731         return ret;
11732 }
11733
11734
11735 static bool run_streamerror(int dummy)
11736 {
11737         struct cli_state *cli;
11738         const char *dname = "\\testdir_streamerror";
11739         const char *streamname =
11740                 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
11741         NTSTATUS status;
11742         time_t change_time, access_time, write_time;
11743         off_t size;
11744         uint16_t mode, fnum;
11745         bool ret = true;
11746
11747         if (!torture_open_connection(&cli, 0)) {
11748                 return false;
11749         }
11750
11751         cli_unlink(cli, "\\testdir_streamerror\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11752         cli_rmdir(cli, dname);
11753
11754         status = cli_mkdir(cli, dname);
11755         if (!NT_STATUS_IS_OK(status)) {
11756                 printf("mkdir failed: %s\n", nt_errstr(status));
11757                 return false;
11758         }
11759
11760         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
11761                                 &write_time, &size, &mode);
11762         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
11763                 printf("pathinfo returned %s, expected "
11764                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
11765                        nt_errstr(status));
11766                 ret = false;
11767         }
11768
11769         status = cli_ntcreate(cli, streamname, 0x16,
11770                               FILE_READ_DATA|FILE_READ_EA|
11771                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
11772                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
11773                               FILE_OPEN, 0, 0, &fnum, NULL);
11774
11775         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
11776                 printf("ntcreate returned %s, expected "
11777                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
11778                        nt_errstr(status));
11779                 ret = false;
11780         }
11781
11782
11783         cli_rmdir(cli, dname);
11784         return ret;
11785 }
11786
11787 struct pidtest_state {
11788         bool success;
11789         uint16_t vwv[1];
11790         DATA_BLOB data;
11791 };
11792
11793 static void pid_echo_done(struct tevent_req *subreq);
11794
11795 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
11796                         struct tevent_context *ev,
11797                         struct cli_state *cli)
11798 {
11799         struct tevent_req *req, *subreq;
11800         struct pidtest_state *state;
11801
11802         req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
11803         if (req == NULL) {
11804                 return NULL;
11805         }
11806
11807         SSVAL(state->vwv, 0, 1);
11808         state->data = data_blob_const("hello", 5);
11809
11810         subreq = smb1cli_req_send(state,
11811                                 ev,
11812                                 cli->conn,
11813                                 SMBecho,
11814                                 0, 0, /* *_flags */
11815                                 0, 0, /* *_flags2 */
11816                                 cli->timeout,
11817                                 0xDEADBEEF, /* pid */
11818                                 NULL, /* tcon */
11819                                 NULL, /* session */
11820                                 ARRAY_SIZE(state->vwv), state->vwv,
11821                                 state->data.length, state->data.data);
11822
11823         if (tevent_req_nomem(subreq, req)) {
11824                 return tevent_req_post(req, ev);
11825         }
11826         tevent_req_set_callback(subreq, pid_echo_done, req);
11827         return req;
11828 }
11829
11830 static void pid_echo_done(struct tevent_req *subreq)
11831 {
11832         struct tevent_req *req = tevent_req_callback_data(
11833                 subreq, struct tevent_req);
11834         struct pidtest_state *state = tevent_req_data(
11835                 req, struct pidtest_state);
11836         NTSTATUS status;
11837         uint32_t num_bytes;
11838         uint8_t *bytes = NULL;
11839         struct iovec *recv_iov = NULL;
11840         uint8_t *phdr = NULL;
11841         uint16_t pidlow = 0;
11842         uint16_t pidhigh = 0;
11843         struct smb1cli_req_expected_response expected[] = {
11844         {
11845                 .status = NT_STATUS_OK,
11846                 .wct    = 1,
11847         },
11848         };
11849
11850         status = smb1cli_req_recv(subreq, state,
11851                                 &recv_iov,
11852                                 &phdr,
11853                                 NULL, /* pwct */
11854                                 NULL, /* pvwv */
11855                                 NULL, /* pvwv_offset */
11856                                 &num_bytes,
11857                                 &bytes,
11858                                 NULL, /* pbytes_offset */
11859                                 NULL, /* pinbuf */
11860                                 expected, ARRAY_SIZE(expected));
11861
11862         TALLOC_FREE(subreq);
11863
11864         if (!NT_STATUS_IS_OK(status)) {
11865                 tevent_req_nterror(req, status);
11866                 return;
11867         }
11868
11869         if (num_bytes != state->data.length) {
11870                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
11871                 return;
11872         }
11873
11874         if (memcmp(bytes, state->data.data, num_bytes) != 0) {
11875                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
11876                 return;
11877         }
11878
11879         /* Check pid low/high == DEADBEEF */
11880         pidlow = SVAL(phdr, HDR_PID);
11881         if (pidlow != 0xBEEF){
11882                 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
11883                         (unsigned int)pidlow);
11884                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
11885                 return;
11886         }
11887         pidhigh = SVAL(phdr, HDR_PIDHIGH);
11888         if (pidhigh != 0xDEAD){
11889                 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
11890                         (unsigned int)pidhigh);
11891                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
11892                 return;
11893         }
11894
11895         tevent_req_done(req);
11896 }
11897
11898 static NTSTATUS pid_echo_recv(struct tevent_req *req)
11899 {
11900         return tevent_req_simple_recv_ntstatus(req);
11901 }
11902
11903 static bool run_pidhigh(int dummy)
11904 {
11905         bool success = false;
11906         struct cli_state *cli = NULL;
11907         NTSTATUS status;
11908         struct tevent_context *ev = NULL;
11909         struct tevent_req *req = NULL;
11910         TALLOC_CTX *frame = talloc_stackframe();
11911
11912         printf("starting pid high test\n");
11913         if (!torture_open_connection(&cli, 0)) {
11914                 return false;
11915         }
11916         smbXcli_conn_set_sockopt(cli->conn, sockops);
11917
11918         ev = samba_tevent_context_init(frame);
11919         if (ev == NULL) {
11920                 goto fail;
11921         }
11922
11923         req = pid_echo_send(frame, ev, cli);
11924         if (req == NULL) {
11925                 goto fail;
11926         }
11927
11928         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
11929                 goto fail;
11930         }
11931
11932         status = pid_echo_recv(req);
11933         if (NT_STATUS_IS_OK(status)) {
11934                 printf("pid high test ok\n");
11935                 success = true;
11936         }
11937
11938  fail:
11939
11940         TALLOC_FREE(frame);
11941         torture_close_connection(cli);
11942         return success;
11943 }
11944
11945 /*
11946   Test Windows open on a bad POSIX symlink.
11947  */
11948 static bool run_symlink_open_test(int dummy)
11949 {
11950         static struct cli_state *cli;
11951         const char *fname = "non_existant_file";
11952         const char *sname = "dangling_symlink";
11953         uint16_t fnum = (uint16_t)-1;
11954         bool correct = false;
11955         NTSTATUS status;
11956         TALLOC_CTX *frame = NULL;
11957
11958         frame = talloc_stackframe();
11959
11960         printf("Starting Windows bad symlink open test\n");
11961
11962         if (!torture_open_connection(&cli, 0)) {
11963                 TALLOC_FREE(frame);
11964                 return false;
11965         }
11966
11967         smbXcli_conn_set_sockopt(cli->conn, sockops);
11968
11969         status = torture_setup_unix_extensions(cli);
11970         if (!NT_STATUS_IS_OK(status)) {
11971                 TALLOC_FREE(frame);
11972                 return false;
11973         }
11974
11975         /* Ensure nothing exists. */
11976         cli_setatr(cli, fname, 0, 0);
11977         cli_posix_unlink(cli, fname);
11978         cli_setatr(cli, sname, 0, 0);
11979         cli_posix_unlink(cli, sname);
11980
11981         /* Create a symlink pointing nowhere. */
11982         status = cli_posix_symlink(cli, fname, sname);
11983         if (!NT_STATUS_IS_OK(status)) {
11984                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
11985                         sname,
11986                         fname,
11987                         nt_errstr(status));
11988                 goto out;
11989         }
11990
11991         /* Now ensure that a Windows open doesn't hang. */
11992         status = cli_ntcreate(cli,
11993                         sname,
11994                         0,
11995                         FILE_READ_DATA|FILE_WRITE_DATA,
11996                         0,
11997                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
11998                         FILE_OPEN_IF,
11999                         0x0,
12000                         0x0,
12001                         &fnum,
12002                         NULL);
12003
12004         /*
12005          * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12006          * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12007          * we use O_NOFOLLOW on the server or not.
12008          */
12009         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12010             NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12011         {
12012                 correct = true;
12013         } else {
12014                 printf("cli_ntcreate of %s returned %s - should return"
12015                                 " either (%s) or (%s)\n",
12016                         sname,
12017                         nt_errstr(status),
12018                         nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12019                         nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12020                 goto out;
12021         }
12022
12023         correct = true;
12024
12025   out:
12026
12027         if (fnum != (uint16_t)-1) {
12028                 cli_close(cli, fnum);
12029                 fnum = (uint16_t)-1;
12030         }
12031
12032         cli_setatr(cli, sname, 0, 0);
12033         cli_posix_unlink(cli, sname);
12034         cli_setatr(cli, fname, 0, 0);
12035         cli_posix_unlink(cli, fname);
12036
12037         if (!torture_close_connection(cli)) {
12038                 correct = false;
12039         }
12040
12041         TALLOC_FREE(frame);
12042         return correct;
12043 }
12044
12045 /*
12046  * Only testing minimal time strings, as the others
12047  * need (locale-dependent) guessing at what strftime does and
12048  * even may differ in builds.
12049  */
12050 static bool timesubst_test(void)
12051 {
12052         TALLOC_CTX *ctx = NULL;
12053         /* Sa 23. Dez 04:33:20 CET 2017 */
12054         const struct timeval tv = { 1514000000, 123 };
12055         const char* expect_minimal = "20171223_033320";
12056         const char* expect_minus   = "20171223_033320_000123";
12057         char *s;
12058         char *env_tz, *orig_tz = NULL;
12059         bool result = true;
12060
12061         ctx = talloc_new(NULL);
12062
12063         env_tz = getenv("TZ");
12064         if(env_tz) {
12065                 orig_tz = talloc_strdup(ctx, env_tz);
12066         }
12067         setenv("TZ", "UTC", 1);
12068
12069         s = minimal_timeval_string(ctx, &tv, false);
12070
12071         if(!s || strcmp(s, expect_minimal)) {
12072                 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
12073                        "[%s]\n", s ? s : "<nil>", expect_minimal);
12074                 result = false;
12075         }
12076         TALLOC_FREE(s);
12077         s = minimal_timeval_string(ctx, &tv, true);
12078         if(!s || strcmp(s, expect_minus)) {
12079                 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
12080                        "[%s]\n", s ? s : "<nil>", expect_minus);
12081                 result = false;
12082         }
12083         TALLOC_FREE(s);
12084
12085         if(orig_tz) {
12086                 setenv("TZ", orig_tz, 1);
12087         }
12088
12089         TALLOC_FREE(ctx);
12090         return result;
12091 }
12092
12093 static bool run_local_substitute(int dummy)
12094 {
12095         bool ok = true;
12096
12097         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
12098         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
12099         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
12100         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
12101         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
12102         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
12103         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
12104         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
12105         ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
12106         /* Substitution depends on current time, so better test the underlying
12107            formatting function. At least covers %t. */
12108         ok &= timesubst_test();
12109
12110         /* Different captialization rules in sub_basic... */
12111
12112         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
12113                        "blaDOM") == 0);
12114
12115         return ok;
12116 }
12117
12118 static bool run_local_base64(int dummy)
12119 {
12120         int i;
12121         bool ret = true;
12122
12123         for (i=1; i<2000; i++) {
12124                 DATA_BLOB blob1, blob2;
12125                 char *b64;
12126
12127                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
12128                 blob1.length = i;
12129                 generate_random_buffer(blob1.data, blob1.length);
12130
12131                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
12132                 if (b64 == NULL) {
12133                         d_fprintf(stderr, "base64_encode_data_blob failed "
12134                                   "for %d bytes\n", i);
12135                         ret = false;
12136                 }
12137                 blob2 = base64_decode_data_blob(b64);
12138                 TALLOC_FREE(b64);
12139
12140                 if (data_blob_cmp(&blob1, &blob2)) {
12141                         d_fprintf(stderr, "data_blob_cmp failed for %d "
12142                                   "bytes\n", i);
12143                         ret = false;
12144                 }
12145                 TALLOC_FREE(blob1.data);
12146                 data_blob_free(&blob2);
12147         }
12148         return ret;
12149 }
12150
12151 static void parse_fn(const struct gencache_timeout *t,
12152                      DATA_BLOB blob,
12153                      void *private_data)
12154 {
12155         return;
12156 }
12157
12158 static bool run_local_gencache(int dummy)
12159 {
12160         char *val;
12161         time_t tm;
12162         DATA_BLOB blob;
12163         char v;
12164         struct memcache *mem;
12165         int i;
12166
12167         mem = memcache_init(NULL, 0);
12168         if (mem == NULL) {
12169                 d_printf("%s: memcache_init failed\n", __location__);
12170                 return false;
12171         }
12172         memcache_set_global(mem);
12173
12174         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
12175                 d_printf("%s: gencache_set() failed\n", __location__);
12176                 return False;
12177         }
12178
12179         if (!gencache_get("foo", NULL, NULL, NULL)) {
12180                 d_printf("%s: gencache_get() failed\n", __location__);
12181                 return False;
12182         }
12183
12184         for (i=0; i<1000000; i++) {
12185                 gencache_parse("foo", parse_fn, NULL);
12186         }
12187
12188         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
12189                 d_printf("%s: gencache_get() failed\n", __location__);
12190                 return False;
12191         }
12192         TALLOC_FREE(val);
12193
12194         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
12195                 d_printf("%s: gencache_get() failed\n", __location__);
12196                 return False;
12197         }
12198
12199         if (strcmp(val, "bar") != 0) {
12200                 d_printf("%s: gencache_get() returned %s, expected %s\n",
12201                          __location__, val, "bar");
12202                 TALLOC_FREE(val);
12203                 return False;
12204         }
12205
12206         TALLOC_FREE(val);
12207
12208         if (!gencache_del("foo")) {
12209                 d_printf("%s: gencache_del() failed\n", __location__);
12210                 return False;
12211         }
12212         if (gencache_del("foo")) {
12213                 d_printf("%s: second gencache_del() succeeded\n",
12214                          __location__);
12215                 return False;
12216         }
12217
12218         if (gencache_get("foo", talloc_tos(), &val, &tm)) {
12219                 d_printf("%s: gencache_get() on deleted entry "
12220                          "succeeded\n", __location__);
12221                 return False;
12222         }
12223
12224         blob = data_blob_string_const_null("bar");
12225         tm = time(NULL) + 60;
12226
12227         if (!gencache_set_data_blob("foo", blob, tm)) {
12228                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
12229                 return False;
12230         }
12231
12232         if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
12233                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
12234                 return False;
12235         }
12236
12237         if (strcmp((const char *)blob.data, "bar") != 0) {
12238                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
12239                          __location__, (const char *)blob.data, "bar");
12240                 data_blob_free(&blob);
12241                 return False;
12242         }
12243
12244         data_blob_free(&blob);
12245
12246         if (!gencache_del("foo")) {
12247                 d_printf("%s: gencache_del() failed\n", __location__);
12248                 return False;
12249         }
12250         if (gencache_del("foo")) {
12251                 d_printf("%s: second gencache_del() succeeded\n",
12252                          __location__);
12253                 return False;
12254         }
12255
12256         if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
12257                 d_printf("%s: gencache_get_data_blob() on deleted entry "
12258                          "succeeded\n", __location__);
12259                 return False;
12260         }
12261
12262         v = 1;
12263         blob.data = (uint8_t *)&v;
12264         blob.length = sizeof(v);
12265
12266         if (!gencache_set_data_blob("blob", blob, tm)) {
12267                 d_printf("%s: gencache_set_data_blob() failed\n",
12268                          __location__);
12269                 return false;
12270         }
12271         if (gencache_get("blob", talloc_tos(), &val, &tm)) {
12272                 d_printf("%s: gencache_get succeeded\n", __location__);
12273                 return false;
12274         }
12275
12276         return True;
12277 }
12278
12279 static bool rbt_testval(struct db_context *db, const char *key,
12280                         const char *value)
12281 {
12282         struct db_record *rec;
12283         TDB_DATA data = string_tdb_data(value);
12284         bool ret = false;
12285         NTSTATUS status;
12286         TDB_DATA dbvalue;
12287
12288         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
12289         if (rec == NULL) {
12290                 d_fprintf(stderr, "fetch_locked failed\n");
12291                 goto done;
12292         }
12293         status = dbwrap_record_store(rec, data, 0);
12294         if (!NT_STATUS_IS_OK(status)) {
12295                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
12296                 goto done;
12297         }
12298         TALLOC_FREE(rec);
12299
12300         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
12301         if (rec == NULL) {
12302                 d_fprintf(stderr, "second fetch_locked failed\n");
12303                 goto done;
12304         }
12305
12306         dbvalue = dbwrap_record_get_value(rec);
12307         if ((dbvalue.dsize != data.dsize)
12308             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
12309                 d_fprintf(stderr, "Got wrong data back\n");
12310                 goto done;
12311         }
12312
12313         ret = true;
12314  done:
12315         TALLOC_FREE(rec);
12316         return ret;
12317 }
12318
12319 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
12320 {
12321         int *count2 = (int *)private_data;
12322         (*count2)++;
12323         return 0;
12324 }
12325
12326 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
12327 {
12328         int *count2 = (int *)private_data;
12329         (*count2)++;
12330         dbwrap_record_delete(rec);
12331         return 0;
12332 }
12333
12334 static bool run_local_rbtree(int dummy)
12335 {
12336         struct db_context *db;
12337         bool ret = false;
12338         int i;
12339         NTSTATUS status;
12340         int count = 0;
12341         int count2 = 0;
12342
12343         db = db_open_rbt(NULL);
12344
12345         if (db == NULL) {
12346                 d_fprintf(stderr, "db_open_rbt failed\n");
12347                 return false;
12348         }
12349
12350         for (i=0; i<1000; i++) {
12351                 char *key, *value;
12352
12353                 if (asprintf(&key, "key%ld", random()) == -1) {
12354                         goto done;
12355                 }
12356                 if (asprintf(&value, "value%ld", random()) == -1) {
12357                         SAFE_FREE(key);
12358                         goto done;
12359                 }
12360
12361                 if (!rbt_testval(db, key, value)) {
12362                         SAFE_FREE(key);
12363                         SAFE_FREE(value);
12364                         goto done;
12365                 }
12366
12367                 SAFE_FREE(value);
12368                 if (asprintf(&value, "value%ld", random()) == -1) {
12369                         SAFE_FREE(key);
12370                         goto done;
12371                 }
12372
12373                 if (!rbt_testval(db, key, value)) {
12374                         SAFE_FREE(key);
12375                         SAFE_FREE(value);
12376                         goto done;
12377                 }
12378
12379                 SAFE_FREE(key);
12380                 SAFE_FREE(value);
12381         }
12382
12383         ret = true;
12384         count = 0; count2 = 0;
12385         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
12386                                       &count2, &count);
12387         printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
12388         if ((count != count2) || (count != 1000)) {
12389                 ret = false;
12390         }
12391         count = 0; count2 = 0;
12392         status = dbwrap_traverse(db, local_rbtree_traverse_delete,
12393                                  &count2, &count);
12394         printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
12395         if ((count != count2) || (count != 1000)) {
12396                 ret = false;
12397         }
12398         count = 0; count2 = 0;
12399         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
12400                                       &count2, &count);
12401         printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
12402         if ((count != count2) || (count != 0)) {
12403                 ret = false;
12404         }
12405
12406  done:
12407         TALLOC_FREE(db);
12408         return ret;
12409 }
12410
12411
12412 /*
12413   local test for character set functions
12414
12415   This is a very simple test for the functionality in convert_string_error()
12416  */
12417 static bool run_local_convert_string(int dummy)
12418 {
12419         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
12420         const char *test_strings[2] = { "March", "M\303\244rz" };
12421         char dst[7];
12422         int i;
12423
12424         for (i=0; i<2; i++) {
12425                 const char *str = test_strings[i];
12426                 int len = strlen(str);
12427                 size_t converted_size;
12428                 bool ret;
12429
12430                 memset(dst, 'X', sizeof(dst));
12431
12432                 /* first try with real source length */
12433                 ret = convert_string_error(CH_UNIX, CH_UTF8,
12434                                            str, len,
12435                                            dst, sizeof(dst),
12436                                            &converted_size);
12437                 if (ret != true) {
12438                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
12439                         goto failed;
12440                 }
12441
12442                 if (converted_size != len) {
12443                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
12444                                   str, len, (int)converted_size);
12445                         goto failed;
12446                 }
12447
12448                 if (strncmp(str, dst, converted_size) != 0) {
12449                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
12450                         goto failed;
12451                 }
12452
12453                 if (strlen(str) != converted_size) {
12454                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
12455                                   (int)strlen(str), (int)converted_size);
12456                         goto failed;
12457                 }
12458
12459                 if (dst[converted_size] != 'X') {
12460                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
12461                         goto failed;
12462                 }
12463
12464                 /* now with srclen==-1, this causes the nul to be
12465                  * converted too */
12466                 ret = convert_string_error(CH_UNIX, CH_UTF8,
12467                                            str, -1,
12468                                            dst, sizeof(dst),
12469                                            &converted_size);
12470                 if (ret != true) {
12471                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
12472                         goto failed;
12473                 }
12474
12475                 if (converted_size != len+1) {
12476                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
12477                                   str, len, (int)converted_size);
12478                         goto failed;
12479                 }
12480
12481                 if (strncmp(str, dst, converted_size) != 0) {
12482                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
12483                         goto failed;
12484                 }
12485
12486                 if (len+1 != converted_size) {
12487                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
12488                                   len+1, (int)converted_size);
12489                         goto failed;
12490                 }
12491
12492                 if (dst[converted_size] != 'X') {
12493                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
12494                         goto failed;
12495                 }
12496
12497         }
12498
12499
12500         TALLOC_FREE(tmp_ctx);
12501         return true;
12502 failed:
12503         TALLOC_FREE(tmp_ctx);
12504         return false;
12505 }
12506
12507 static bool run_local_string_to_sid(int dummy) {
12508         struct dom_sid sid;
12509
12510         if (string_to_sid(&sid, "S--1-5-32-545")) {
12511                 printf("allowing S--1-5-32-545\n");
12512                 return false;
12513         }
12514         if (string_to_sid(&sid, "S-1-5-32-+545")) {
12515                 printf("allowing S-1-5-32-+545\n");
12516                 return false;
12517         }
12518         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")) {
12519                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
12520                 return false;
12521         }
12522         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
12523                 printf("allowing S-1-5-32-545-abc\n");
12524                 return false;
12525         }
12526         if (string_to_sid(&sid, "S-300-5-32-545")) {
12527                 printf("allowing S-300-5-32-545\n");
12528                 return false;
12529         }
12530         if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
12531                 printf("allowing S-1-0xfffffffffffffe-32-545\n");
12532                 return false;
12533         }
12534         if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
12535                 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
12536                 return false;
12537         }
12538         if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
12539                 printf("could not parse S-1-0xfffffffffffe-32-545\n");
12540                 return false;
12541         }
12542         if (!string_to_sid(&sid, "S-1-5-32-545")) {
12543                 printf("could not parse S-1-5-32-545\n");
12544                 return false;
12545         }
12546         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
12547                 struct dom_sid_buf buf;
12548                 printf("mis-parsed S-1-5-32-545 as %s\n",
12549                        dom_sid_str_buf(&sid, &buf));
12550                 return false;
12551         }
12552         return true;
12553 }
12554
12555 static bool sid_to_string_test(const char *expected) {
12556         char *str;
12557         bool res = true;
12558         struct dom_sid sid;
12559
12560         if (!string_to_sid(&sid, expected)) {
12561                 printf("could not parse %s\n", expected);
12562                 return false;
12563         }
12564
12565         str = dom_sid_string(NULL, &sid);
12566         if (strcmp(str, expected)) {
12567                 printf("Comparison failed (%s != %s)\n", str, expected);
12568                 res = false;
12569         }
12570         TALLOC_FREE(str);
12571         return res;
12572 }
12573
12574 static bool run_local_sid_to_string(int dummy) {
12575         if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
12576                 return false;
12577         if (!sid_to_string_test("S-1-545"))
12578                 return false;
12579         if (!sid_to_string_test("S-255-3840-1-1-1-1"))
12580                 return false;
12581         return true;
12582 }
12583
12584 static bool run_local_binary_to_sid(int dummy) {
12585         ssize_t ret;
12586         struct dom_sid *sid = talloc(NULL, struct dom_sid);
12587         static const uint8_t good_binary_sid[] = {
12588                 0x1, /* revision number */
12589                 15, /* num auths */
12590                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
12591                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
12592                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
12593                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
12594                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
12595                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
12596                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
12597                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
12598                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
12599                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
12600                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
12601                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
12602                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
12603                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
12604                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
12605                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
12606         };
12607
12608         static const uint8_t long_binary_sid[] = {
12609                 0x1, /* revision number */
12610                 15, /* num auths */
12611                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
12612                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
12613                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
12614                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
12615                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
12616                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
12617                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
12618                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
12619                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
12620                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
12621                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
12622                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
12623                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
12624                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
12625                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
12626                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
12627                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
12628                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
12629                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
12630         };
12631
12632         static const uint8_t long_binary_sid2[] = {
12633                 0x1, /* revision number */
12634                 32, /* num auths */
12635                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
12636                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
12637                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
12638                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
12639                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
12640                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
12641                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
12642                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
12643                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
12644                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
12645                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
12646                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
12647                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
12648                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
12649                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
12650                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
12651                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
12652                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
12653                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
12654                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
12655                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
12656                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
12657                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
12658                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
12659                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
12660                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
12661                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
12662                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
12663                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
12664                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
12665                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
12666                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
12667                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
12668         };
12669
12670         ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
12671         if (ret == -1) {
12672                 return false;
12673         }
12674         ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
12675         if (ret != -1) {
12676                 return false;
12677         }
12678         ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
12679         if (ret != -1) {
12680                 return false;
12681         }
12682         return true;
12683 }
12684
12685 /* Split a path name into filename and stream name components. Canonicalise
12686  * such that an implicit $DATA token is always explicit.
12687  *
12688  * The "specification" of this function can be found in the
12689  * run_local_stream_name() function in torture.c, I've tried those
12690  * combinations against a W2k3 server.
12691  */
12692
12693 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
12694                                        char **pbase, char **pstream)
12695 {
12696         char *base = NULL;
12697         char *stream = NULL;
12698         char *sname; /* stream name */
12699         const char *stype; /* stream type */
12700
12701         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
12702
12703         sname = strchr_m(fname, ':');
12704
12705         if (sname == NULL) {
12706                 if (pbase != NULL) {
12707                         base = talloc_strdup(mem_ctx, fname);
12708                         NT_STATUS_HAVE_NO_MEMORY(base);
12709                 }
12710                 goto done;
12711         }
12712
12713         if (pbase != NULL) {
12714                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
12715                 NT_STATUS_HAVE_NO_MEMORY(base);
12716         }
12717
12718         sname += 1;
12719
12720         stype = strchr_m(sname, ':');
12721
12722         if (stype == NULL) {
12723                 sname = talloc_strdup(mem_ctx, sname);
12724                 stype = "$DATA";
12725         }
12726         else {
12727                 if (strcasecmp_m(stype, ":$DATA") != 0) {
12728                         /*
12729                          * If there is an explicit stream type, so far we only
12730                          * allow $DATA. Is there anything else allowed? -- vl
12731                          */
12732                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
12733                         TALLOC_FREE(base);
12734                         return NT_STATUS_OBJECT_NAME_INVALID;
12735                 }
12736                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
12737                 stype += 1;
12738         }
12739
12740         if (sname == NULL) {
12741                 TALLOC_FREE(base);
12742                 return NT_STATUS_NO_MEMORY;
12743         }
12744
12745         if (sname[0] == '\0') {
12746                 /*
12747                  * no stream name, so no stream
12748                  */
12749                 goto done;
12750         }
12751
12752         if (pstream != NULL) {
12753                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
12754                 if (stream == NULL) {
12755                         TALLOC_FREE(sname);
12756                         TALLOC_FREE(base);
12757                         return NT_STATUS_NO_MEMORY;
12758                 }
12759                 /*
12760                  * upper-case the type field
12761                  */
12762                 (void)strupper_m(strchr_m(stream, ':')+1);
12763         }
12764
12765  done:
12766         if (pbase != NULL) {
12767                 *pbase = base;
12768         }
12769         if (pstream != NULL) {
12770                 *pstream = stream;
12771         }
12772         return NT_STATUS_OK;
12773 }
12774
12775 static bool test_stream_name(const char *fname, const char *expected_base,
12776                              const char *expected_stream,
12777                              NTSTATUS expected_status)
12778 {
12779         NTSTATUS status;
12780         char *base = NULL;
12781         char *stream = NULL;
12782
12783         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
12784         if (!NT_STATUS_EQUAL(status, expected_status)) {
12785                 goto error;
12786         }
12787
12788         if (!NT_STATUS_IS_OK(status)) {
12789                 return true;
12790         }
12791
12792         if (base == NULL) goto error;
12793
12794         if (strcmp(expected_base, base) != 0) goto error;
12795
12796         if ((expected_stream != NULL) && (stream == NULL)) goto error;
12797         if ((expected_stream == NULL) && (stream != NULL)) goto error;
12798
12799         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
12800                 goto error;
12801
12802         TALLOC_FREE(base);
12803         TALLOC_FREE(stream);
12804         return true;
12805
12806  error:
12807         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
12808                   fname, expected_base ? expected_base : "<NULL>",
12809                   expected_stream ? expected_stream : "<NULL>",
12810                   nt_errstr(expected_status));
12811         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
12812                   base ? base : "<NULL>", stream ? stream : "<NULL>",
12813                   nt_errstr(status));
12814         TALLOC_FREE(base);
12815         TALLOC_FREE(stream);
12816         return false;
12817 }
12818
12819 static bool run_local_stream_name(int dummy)
12820 {
12821         bool ret = true;
12822
12823         ret &= test_stream_name(
12824                 "bla", "bla", NULL, NT_STATUS_OK);
12825         ret &= test_stream_name(
12826                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
12827         ret &= test_stream_name(
12828                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
12829         ret &= test_stream_name(
12830                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
12831         ret &= test_stream_name(
12832                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
12833         ret &= test_stream_name(
12834                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
12835         ret &= test_stream_name(
12836                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
12837         ret &= test_stream_name(
12838                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
12839
12840         return ret;
12841 }
12842
12843 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
12844 {
12845         if (a.length != b.length) {
12846                 printf("a.length=%d != b.length=%d\n",
12847                        (int)a.length, (int)b.length);
12848                 return false;
12849         }
12850         if (memcmp(a.data, b.data, a.length) != 0) {
12851                 printf("a.data and b.data differ\n");
12852                 return false;
12853         }
12854         return true;
12855 }
12856
12857 static bool run_local_memcache(int dummy)
12858 {
12859         struct memcache *cache;
12860         DATA_BLOB k1, k2, k3, k4, k5;
12861         DATA_BLOB d1, d3;
12862         DATA_BLOB v1, v3;
12863
12864         TALLOC_CTX *mem_ctx;
12865         char *ptr1 = NULL;
12866         char *ptr2 = NULL;
12867         char *ptr3 = NULL;
12868
12869         char *str1, *str2;
12870         size_t size1, size2;
12871         bool ret = false;
12872
12873         mem_ctx = talloc_init("foo");
12874         if (mem_ctx == NULL) {
12875                 return false;
12876         }
12877
12878         /* STAT_CACHE TESTS */
12879
12880         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
12881
12882         if (cache == NULL) {
12883                 printf("memcache_init failed\n");
12884                 return false;
12885         }
12886
12887         d1 = data_blob_const("d1", 2);
12888         d3 = data_blob_const("d3", 2);
12889
12890         k1 = data_blob_const("d1", 2);
12891         k2 = data_blob_const("d2", 2);
12892         k3 = data_blob_const("d3", 2);
12893         k4 = data_blob_const("d4", 2);
12894         k5 = data_blob_const("d5", 2);
12895
12896         memcache_add(cache, STAT_CACHE, k1, d1);
12897
12898         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
12899                 printf("could not find k1\n");
12900                 return false;
12901         }
12902         if (!data_blob_equal(d1, v1)) {
12903                 return false;
12904         }
12905
12906         memcache_add(cache, STAT_CACHE, k1, d3);
12907
12908         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
12909                 printf("could not find replaced k1\n");
12910                 return false;
12911         }
12912         if (!data_blob_equal(d3, v3)) {
12913                 return false;
12914         }
12915
12916         TALLOC_FREE(cache);
12917
12918         /* GETWD_CACHE TESTS */
12919         str1 = talloc_strdup(mem_ctx, "string1");
12920         if (str1 == NULL) {
12921                 return false;
12922         }
12923         ptr2 = str1; /* Keep an alias for comparison. */
12924
12925         str2 = talloc_strdup(mem_ctx, "string2");
12926         if (str2 == NULL) {
12927                 return false;
12928         }
12929
12930         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
12931         if (cache == NULL) {
12932                 printf("memcache_init failed\n");
12933                 return false;
12934         }
12935
12936         memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
12937         /* str1 == NULL now. */
12938         ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
12939         if (ptr1 == NULL) {
12940                 printf("could not find k2\n");
12941                 return false;
12942         }
12943         if (ptr1 != ptr2) {
12944                 printf("fetch of k2 got wrong string\n");
12945                 return false;
12946         }
12947
12948         /* Add a blob to ensure k2 gets purged. */
12949         d3 = data_blob_talloc_zero(mem_ctx, 180);
12950         memcache_add(cache, STAT_CACHE, k3, d3);
12951
12952         ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
12953         if (ptr2 != NULL) {
12954                 printf("Did find k2, should have been purged\n");
12955                 return false;
12956         }
12957
12958         /*
12959          * Test that talloc size also is accounted in memcache and
12960          * causes purge of other object.
12961          */
12962
12963         str1 = talloc_zero_size(mem_ctx, 100);
12964         str2 = talloc_zero_size(mem_ctx, 100);
12965
12966         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
12967         memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
12968
12969         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
12970         if (ptr3 != NULL) {
12971                 printf("Did find k4, should have been purged\n");
12972                 return false;
12973         }
12974
12975         /*
12976          * Test that adding a duplicate non-talloced
12977          * key/value on top of a talloced key/value takes account
12978          * of the talloc_freed value size.
12979          */
12980         TALLOC_FREE(cache);
12981         TALLOC_FREE(mem_ctx);
12982
12983         mem_ctx = talloc_init("key_replace");
12984         if (mem_ctx == NULL) {
12985                 return false;
12986         }
12987
12988         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
12989         if (cache == NULL) {
12990                 return false;
12991         }
12992
12993         /*
12994          * Add a 100 byte talloced string. This will
12995          * store a (4 or 8 byte) pointer and record the
12996          * total talloced size.
12997          */
12998         str1 = talloc_zero_size(mem_ctx, 100);
12999         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13000         /*
13001          * Now overwrite with a small talloced
13002          * value. This should fit in the existing size
13003          * and the total talloced size should be removed
13004          * from the cache size.
13005          */
13006         str1 = talloc_zero_size(mem_ctx, 2);
13007         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13008         /*
13009          * Now store a 20 byte string. If the
13010          * total talloced size wasn't accounted for
13011          * and removed in the overwrite, then this
13012          * will evict k4.
13013          */
13014         str2 = talloc_zero_size(mem_ctx, 20);
13015         memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
13016
13017         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
13018         if (ptr3 == NULL) {
13019                 printf("Did not find k4, should not have been purged\n");
13020                 return false;
13021         }
13022
13023         TALLOC_FREE(cache);
13024         TALLOC_FREE(mem_ctx);
13025
13026         mem_ctx = talloc_init("foo");
13027         if (mem_ctx == NULL) {
13028                 return false;
13029         }
13030
13031         cache = memcache_init(NULL, 0);
13032         if (cache == NULL) {
13033                 return false;
13034         }
13035
13036         str1 = talloc_strdup(mem_ctx, "string1");
13037         if (str1 == NULL) {
13038                 return false;
13039         }
13040         str2 = talloc_strdup(mem_ctx, "string2");
13041         if (str2 == NULL) {
13042                 return false;
13043         }
13044         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
13045                             data_blob_string_const("torture"), &str1);
13046         size1 = talloc_total_size(cache);
13047
13048         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
13049                             data_blob_string_const("torture"), &str2);
13050         size2 = talloc_total_size(cache);
13051
13052         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
13053
13054         if (size2 > size1) {
13055                 printf("memcache leaks memory!\n");
13056                 goto fail;
13057         }
13058
13059         ret = true;
13060  fail:
13061         TALLOC_FREE(cache);
13062         return ret;
13063 }
13064
13065 static void wbclient_done(struct tevent_req *req)
13066 {
13067         wbcErr wbc_err;
13068         struct winbindd_response *wb_resp;
13069         int *i = (int *)tevent_req_callback_data_void(req);
13070
13071         wbc_err = wb_trans_recv(req, req, &wb_resp);
13072         TALLOC_FREE(req);
13073         *i += 1;
13074         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
13075 }
13076
13077 static bool run_wbclient_multi_ping(int dummy)
13078 {
13079         struct tevent_context *ev;
13080         struct wb_context **wb_ctx;
13081         struct winbindd_request wb_req;
13082         bool result = false;
13083         int i, j;
13084
13085         BlockSignals(True, SIGPIPE);
13086
13087         ev = tevent_context_init(talloc_tos());
13088         if (ev == NULL) {
13089                 goto fail;
13090         }
13091
13092         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
13093         if (wb_ctx == NULL) {
13094                 goto fail;
13095         }
13096
13097         ZERO_STRUCT(wb_req);
13098         wb_req.cmd = WINBINDD_PING;
13099
13100         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
13101
13102         for (i=0; i<torture_nprocs; i++) {
13103                 wb_ctx[i] = wb_context_init(ev, NULL);
13104                 if (wb_ctx[i] == NULL) {
13105                         goto fail;
13106                 }
13107                 for (j=0; j<torture_numops; j++) {
13108                         struct tevent_req *req;
13109                         req = wb_trans_send(ev, ev, wb_ctx[i],
13110                                             (j % 2) == 0, &wb_req);
13111                         if (req == NULL) {
13112                                 goto fail;
13113                         }
13114                         tevent_req_set_callback(req, wbclient_done, &i);
13115                 }
13116         }
13117
13118         i = 0;
13119
13120         while (i < torture_nprocs * torture_numops) {
13121                 tevent_loop_once(ev);
13122         }
13123
13124         result = true;
13125  fail:
13126         TALLOC_FREE(ev);
13127         return result;
13128 }
13129
13130 static bool dbtrans_inc(struct db_context *db)
13131 {
13132         struct db_record *rec;
13133         uint32_t val;
13134         bool ret = false;
13135         NTSTATUS status;
13136         TDB_DATA value;
13137
13138         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
13139         if (rec == NULL) {
13140                 printf(__location__ "fetch_lock failed\n");
13141                 return false;
13142         }
13143
13144         value = dbwrap_record_get_value(rec);
13145
13146         if (value.dsize != sizeof(uint32_t)) {
13147                 printf(__location__ "value.dsize = %d\n",
13148                        (int)value.dsize);
13149                 goto fail;
13150         }
13151
13152         memcpy(&val, value.dptr, sizeof(val));
13153         val += 1;
13154
13155         status = dbwrap_record_store(
13156                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
13157         if (!NT_STATUS_IS_OK(status)) {
13158                 printf(__location__ "store failed: %s\n",
13159                        nt_errstr(status));
13160                 goto fail;
13161         }
13162
13163         ret = true;
13164 fail:
13165         TALLOC_FREE(rec);
13166         return ret;
13167 }
13168
13169 static bool run_local_dbtrans(int dummy)
13170 {
13171         struct db_context *db;
13172         struct db_record *rec;
13173         NTSTATUS status;
13174         uint32_t initial;
13175         int res;
13176         TDB_DATA value;
13177
13178         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
13179                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
13180                      DBWRAP_FLAG_NONE);
13181         if (db == NULL) {
13182                 printf("Could not open transtest.db\n");
13183                 return false;
13184         }
13185
13186         res = dbwrap_transaction_start(db);
13187         if (res != 0) {
13188                 printf(__location__ "transaction_start failed\n");
13189                 return false;
13190         }
13191
13192         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
13193         if (rec == NULL) {
13194                 printf(__location__ "fetch_lock failed\n");
13195                 return false;
13196         }
13197
13198         value = dbwrap_record_get_value(rec);
13199
13200         if (value.dptr == NULL) {
13201                 initial = 0;
13202                 status = dbwrap_record_store(
13203                         rec, make_tdb_data((uint8_t *)&initial,
13204                                            sizeof(initial)),
13205                         0);
13206                 if (!NT_STATUS_IS_OK(status)) {
13207                         printf(__location__ "store returned %s\n",
13208                                nt_errstr(status));
13209                         return false;
13210                 }
13211         }
13212
13213         TALLOC_FREE(rec);
13214
13215         res = dbwrap_transaction_commit(db);
13216         if (res != 0) {
13217                 printf(__location__ "transaction_commit failed\n");
13218                 return false;
13219         }
13220
13221         while (true) {
13222                 uint32_t val, val2;
13223                 int i;
13224
13225                 res = dbwrap_transaction_start(db);
13226                 if (res != 0) {
13227                         printf(__location__ "transaction_start failed\n");
13228                         break;
13229                 }
13230
13231                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
13232                 if (!NT_STATUS_IS_OK(status)) {
13233                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
13234                                nt_errstr(status));
13235                         break;
13236                 }
13237
13238                 for (i=0; i<10; i++) {
13239                         if (!dbtrans_inc(db)) {
13240                                 return false;
13241                         }
13242                 }
13243
13244                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
13245                 if (!NT_STATUS_IS_OK(status)) {
13246                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
13247                                nt_errstr(status));
13248                         break;
13249                 }
13250
13251                 if (val2 != val + 10) {
13252                         printf(__location__ "val=%d, val2=%d\n",
13253                                (int)val, (int)val2);
13254                         break;
13255                 }
13256
13257                 printf("val2=%d\r", val2);
13258
13259                 res = dbwrap_transaction_commit(db);
13260                 if (res != 0) {
13261                         printf(__location__ "transaction_commit failed\n");
13262                         break;
13263                 }
13264         }
13265
13266         TALLOC_FREE(db);
13267         return true;
13268 }
13269
13270 /*
13271  * Just a dummy test to be run under a debugger. There's no real way
13272  * to inspect the tevent_poll specific function from outside of
13273  * tevent_poll.c.
13274  */
13275
13276 static bool run_local_tevent_poll(int dummy)
13277 {
13278         struct tevent_context *ev;
13279         struct tevent_fd *fd1, *fd2;
13280         bool result = false;
13281
13282         ev = tevent_context_init_byname(NULL, "poll");
13283         if (ev == NULL) {
13284                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
13285                 goto fail;
13286         }
13287
13288         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
13289         if (fd1 == NULL) {
13290                 d_fprintf(stderr, "tevent_add_fd failed\n");
13291                 goto fail;
13292         }
13293         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
13294         if (fd2 == NULL) {
13295                 d_fprintf(stderr, "tevent_add_fd failed\n");
13296                 goto fail;
13297         }
13298         TALLOC_FREE(fd2);
13299
13300         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
13301         if (fd2 == NULL) {
13302                 d_fprintf(stderr, "tevent_add_fd failed\n");
13303                 goto fail;
13304         }
13305
13306         result = true;
13307 fail:
13308         TALLOC_FREE(ev);
13309         return result;
13310 }
13311
13312 static bool run_local_hex_encode_buf(int dummy)
13313 {
13314         char buf[17];
13315         uint8_t src[8];
13316         int i;
13317
13318         for (i=0; i<sizeof(src); i++) {
13319                 src[i] = i;
13320         }
13321         hex_encode_buf(buf, src, sizeof(src));
13322         if (strcmp(buf, "0001020304050607") != 0) {
13323                 return false;
13324         }
13325         hex_encode_buf(buf, NULL, 0);
13326         if (buf[0] != '\0') {
13327                 return false;
13328         }
13329         return true;
13330 }
13331
13332 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
13333         "0.0.0.0",
13334         "::0",
13335         "1.2.3.1",
13336         "0.0.0.0",
13337         "0.0.0.0",
13338         "1.2.3.2",
13339         "1.2.3.3",
13340         "1.2.3.4",
13341         "1.2.3.5",
13342         "::0",
13343         "1.2.3.6",
13344         "1.2.3.7",
13345         "::0",
13346         "::0",
13347         "::0",
13348         "1.2.3.8",
13349         "1.2.3.9",
13350         "1.2.3.10",
13351         "1.2.3.11",
13352         "1.2.3.12",
13353         "1.2.3.13",
13354         "1001:1111:1111:1000:0:1111:1111:1111",
13355         "1.2.3.1",
13356         "1.2.3.2",
13357         "1.2.3.3",
13358         "1.2.3.12",
13359         "::0",
13360         "::0"
13361 };
13362
13363 static const char *remove_duplicate_addrs2_test_strings_result[] = {
13364         "1.2.3.1",
13365         "1.2.3.2",
13366         "1.2.3.3",
13367         "1.2.3.4",
13368         "1.2.3.5",
13369         "1.2.3.6",
13370         "1.2.3.7",
13371         "1.2.3.8",
13372         "1.2.3.9",
13373         "1.2.3.10",
13374         "1.2.3.11",
13375         "1.2.3.12",
13376         "1.2.3.13",
13377         "1001:1111:1111:1000:0:1111:1111:1111"
13378 };
13379
13380 static bool run_local_remove_duplicate_addrs2(int dummy)
13381 {
13382         struct ip_service test_vector[28];
13383         int count, i;
13384
13385         /* Construct the sockaddr_storage test vector. */
13386         for (i = 0; i < 28; i++) {
13387                 struct addrinfo hints;
13388                 struct addrinfo *res = NULL;
13389                 int ret;
13390
13391                 memset(&hints, '\0', sizeof(hints));
13392                 hints.ai_flags = AI_NUMERICHOST;
13393                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
13394                                 NULL,
13395                                 &hints,
13396                                 &res);
13397                 if (ret) {
13398                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
13399                                 remove_duplicate_addrs2_test_strings_vector[i]);
13400                         return false;
13401                 }
13402                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
13403                 memcpy(&test_vector[i].ss,
13404                         res->ai_addr,
13405                         res->ai_addrlen);
13406                 freeaddrinfo(res);
13407         }
13408
13409         count = remove_duplicate_addrs2(test_vector, i);
13410
13411         if (count != 14) {
13412                 fprintf(stderr, "count wrong (%d) should be 14\n",
13413                         count);
13414                 return false;
13415         }
13416
13417         for (i = 0; i < count; i++) {
13418                 char addr[INET6_ADDRSTRLEN];
13419
13420                 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
13421
13422                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
13423                         fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
13424                                 i,
13425                                 addr,
13426                                 remove_duplicate_addrs2_test_strings_result[i]);
13427                         return false;
13428                 }
13429         }
13430
13431         printf("run_local_remove_duplicate_addrs2: success\n");
13432         return true;
13433 }
13434
13435 static bool run_local_tdb_opener(int dummy)
13436 {
13437         TDB_CONTEXT *t;
13438         unsigned v = 0;
13439
13440         while (1) {
13441                 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
13442                              O_RDWR|O_CREAT, 0755);
13443                 if (t == NULL) {
13444                         perror("tdb_open failed");
13445                         return false;
13446                 }
13447                 tdb_close(t);
13448
13449                 v += 1;
13450                 printf("\r%u", v);
13451         }
13452         return true;
13453 }
13454
13455 static bool run_local_tdb_writer(int dummy)
13456 {
13457         TDB_CONTEXT *t;
13458         unsigned v = 0;
13459         TDB_DATA val;
13460
13461         t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
13462         if (t == 0) {
13463                 perror("tdb_open failed");
13464                 return 1;
13465         }
13466
13467         val.dptr = (uint8_t *)&v;
13468         val.dsize = sizeof(v);
13469
13470         while (1) {
13471                 TDB_DATA data;
13472                 int ret;
13473
13474                 ret = tdb_store(t, val, val, 0);
13475                 if (ret != 0) {
13476                         printf("%s\n", tdb_errorstr(t));
13477                 }
13478                 v += 1;
13479                 printf("\r%u", v);
13480
13481                 data = tdb_fetch(t, val);
13482                 if (data.dptr != NULL) {
13483                         SAFE_FREE(data.dptr);
13484                 }
13485         }
13486         return true;
13487 }
13488
13489 static bool run_local_canonicalize_path(int dummy)
13490 {
13491         const char *src[] = {
13492                         "/foo/..",
13493                         "/..",
13494                         "/foo/bar/../baz",
13495                         "/foo/././",
13496                         "/../foo",
13497                         ".././././",
13498                         ".././././../../../boo",
13499                         "./..",
13500                         NULL
13501                         };
13502         const char *dst[] = {
13503                         "/",
13504                         "/",
13505                         "/foo/baz",
13506                         "/foo",
13507                         "/foo",
13508                         "/",
13509                         "/boo",
13510                         "/",
13511                         NULL
13512                         };
13513         unsigned int i;
13514
13515         for (i = 0; src[i] != NULL; i++) {
13516                 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
13517                 if (d == NULL) {
13518                         perror("talloc fail\n");
13519                         return false;
13520                 }
13521                 if (strcmp(d, dst[i]) != 0) {
13522                         d_fprintf(stderr,
13523                                 "canonicalize mismatch %s -> %s != %s",
13524                                 src[i], d, dst[i]);
13525                         return false;
13526                 }
13527                 talloc_free(d);
13528         }
13529         return true;
13530 }
13531
13532 static bool run_ign_bad_negprot(int dummy)
13533 {
13534         struct tevent_context *ev;
13535         struct tevent_req *req;
13536         struct smbXcli_conn *conn;
13537         struct sockaddr_storage ss;
13538         NTSTATUS status;
13539         int fd;
13540         bool ok;
13541
13542         printf("starting ignore bad negprot\n");
13543
13544         ok = resolve_name(host, &ss, 0x20, true);
13545         if (!ok) {
13546                 d_fprintf(stderr, "Could not resolve name %s\n", host);
13547                 return false;
13548         }
13549
13550         status = open_socket_out(&ss, 445, 10000, &fd);
13551         if (!NT_STATUS_IS_OK(status)) {
13552                 d_fprintf(stderr, "open_socket_out failed: %s\n",
13553                           nt_errstr(status));
13554                 return false;
13555         }
13556
13557         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
13558                                    NULL, 0);
13559         if (conn == NULL) {
13560                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
13561                 return false;
13562         }
13563
13564         status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
13565         if (NT_STATUS_IS_OK(status)) {
13566                 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
13567                 return false;
13568         }
13569
13570         ev = samba_tevent_context_init(talloc_tos());
13571         if (ev == NULL) {
13572                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
13573                 return false;
13574         }
13575
13576         req = smb1cli_session_setup_nt1_send(
13577                 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
13578                 data_blob_null, data_blob_null, 0x40,
13579                 "Windows 2000 2195", "Windows 2000 5.0");
13580         if (req == NULL) {
13581                 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
13582                 return false;
13583         }
13584
13585         ok = tevent_req_poll_ntstatus(req, ev, &status);
13586         if (!ok) {
13587                 d_fprintf(stderr, "tevent_req_poll failed\n");
13588                 return false;
13589         }
13590
13591         status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
13592                                                 NULL, NULL);
13593         if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
13594                 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
13595                           "%s, expected NT_STATUS_CONNECTION_RESET\n",
13596                           nt_errstr(status));
13597                 return false;
13598         }
13599
13600         TALLOC_FREE(conn);
13601
13602         printf("starting ignore bad negprot\n");
13603
13604         return true;
13605 }
13606
13607 static double create_procs(bool (*fn)(int), bool *result)
13608 {
13609         int i, status;
13610         volatile pid_t *child_status;
13611         volatile bool *child_status_out;
13612         int synccount;
13613         int tries = 8;
13614         struct timeval start;
13615
13616         synccount = 0;
13617
13618         child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
13619         if (!child_status) {
13620                 printf("Failed to setup shared memory\n");
13621                 return -1;
13622         }
13623
13624         child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
13625         if (!child_status_out) {
13626                 printf("Failed to setup result status shared memory\n");
13627                 return -1;
13628         }
13629
13630         for (i = 0; i < torture_nprocs; i++) {
13631                 child_status[i] = 0;
13632                 child_status_out[i] = True;
13633         }
13634
13635         start = timeval_current();
13636
13637         for (i=0;i<torture_nprocs;i++) {
13638                 procnum = i;
13639                 if (fork() == 0) {
13640                         pid_t mypid = getpid();
13641                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
13642
13643                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
13644
13645                         while (1) {
13646                                 if (torture_open_connection(&current_cli, i)) break;
13647                                 if (tries-- == 0) {
13648                                         printf("pid %d failed to start\n", (int)getpid());
13649                                         _exit(1);
13650                                 }
13651                                 smb_msleep(10); 
13652                         }
13653
13654                         child_status[i] = getpid();
13655
13656                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
13657
13658                         child_status_out[i] = fn(i);
13659                         _exit(0);
13660                 }
13661         }
13662
13663         do {
13664                 synccount = 0;
13665                 for (i=0;i<torture_nprocs;i++) {
13666                         if (child_status[i]) synccount++;
13667                 }
13668                 if (synccount == torture_nprocs) break;
13669                 smb_msleep(10);
13670         } while (timeval_elapsed(&start) < 30);
13671
13672         if (synccount != torture_nprocs) {
13673                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
13674                 *result = False;
13675                 return timeval_elapsed(&start);
13676         }
13677
13678         /* start the client load */
13679         start = timeval_current();
13680
13681         for (i=0;i<torture_nprocs;i++) {
13682                 child_status[i] = 0;
13683         }
13684
13685         printf("%d clients started\n", torture_nprocs);
13686
13687         for (i=0;i<torture_nprocs;i++) {
13688                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
13689         }
13690
13691         printf("\n");
13692
13693         for (i=0;i<torture_nprocs;i++) {
13694                 if (!child_status_out[i]) {
13695                         *result = False;
13696                 }
13697         }
13698         return timeval_elapsed(&start);
13699 }
13700
13701 #define FLAG_MULTIPROC 1
13702
13703 static struct {
13704         const char *name;
13705         bool (*fn)(int);
13706         unsigned flags;
13707 } torture_ops[] = {
13708         {
13709                 .name = "FDPASS",
13710                 .fn   = run_fdpasstest,
13711         },
13712         {
13713                 .name = "LOCK1",
13714                 .fn   = run_locktest1,
13715         },
13716         {
13717                 .name = "LOCK2",
13718                 .fn   =  run_locktest2,
13719         },
13720         {
13721                 .name = "LOCK3",
13722                 .fn   =  run_locktest3,
13723         },
13724         {
13725                 .name = "LOCK4",
13726                 .fn   =  run_locktest4,
13727         },
13728         {
13729                 .name = "LOCK5",
13730                 .fn   =  run_locktest5,
13731         },
13732         {
13733                 .name = "LOCK6",
13734                 .fn   =  run_locktest6,
13735         },
13736         {
13737                 .name = "LOCK7",
13738                 .fn   =  run_locktest7,
13739         },
13740         {
13741                 .name = "LOCK8",
13742                 .fn   =  run_locktest8,
13743         },
13744         {
13745                 .name = "LOCK9",
13746                 .fn   =  run_locktest9,
13747         },
13748         {
13749                 .name = "LOCK10",
13750                 .fn   =  run_locktest10,
13751         },
13752         {
13753                 .name = "LOCK11",
13754                 .fn   =  run_locktest11,
13755         },
13756         {
13757                 .name = "LOCK12",
13758                 .fn   =  run_locktest12,
13759         },
13760         {
13761                 .name = "LOCK13",
13762                 .fn   =  run_locktest13,
13763         },
13764         {
13765                 .name = "UNLINK",
13766                 .fn   = run_unlinktest,
13767         },
13768         {
13769                 .name = "BROWSE",
13770                 .fn   = run_browsetest,
13771         },
13772         {
13773                 .name = "ATTR",
13774                 .fn   =   run_attrtest,
13775         },
13776         {
13777                 .name = "TRANS2",
13778                 .fn   = run_trans2test,
13779         },
13780         {
13781                 .name  = "MAXFID",
13782                 .fn    = run_maxfidtest,
13783                 .flags = FLAG_MULTIPROC,
13784         },
13785         {
13786                 .name  = "TORTURE",
13787                 .fn    = run_torture,
13788                 .flags = FLAG_MULTIPROC,
13789         },
13790         {
13791                 .name  = "RANDOMIPC",
13792                 .fn    = run_randomipc,
13793         },
13794         {
13795                 .name  = "NEGNOWAIT",
13796                 .fn    = run_negprot_nowait,
13797         },
13798         {
13799                 .name  = "NBENCH",
13800                 .fn    =  run_nbench,
13801         },
13802         {
13803                 .name  = "NBENCH2",
13804                 .fn    = run_nbench2,
13805         },
13806         {
13807                 .name  = "OPLOCK1",
13808                 .fn    =  run_oplock1,
13809         },
13810         {
13811                 .name  = "OPLOCK2",
13812                 .fn    =  run_oplock2,
13813         },
13814         {
13815                 .name  = "OPLOCK4",
13816                 .fn    =  run_oplock4,
13817         },
13818         {
13819                 .name  = "OPLOCK5",
13820                 .fn    =  run_oplock5,
13821         },
13822         {
13823                 .name  = "DIR",
13824                 .fn    =  run_dirtest,
13825         },
13826         {
13827                 .name  = "DIR1",
13828                 .fn    =  run_dirtest1,
13829         },
13830         {
13831                 .name  = "DIR-CREATETIME",
13832                 .fn    =  run_dir_createtime,
13833         },
13834         {
13835                 .name  = "DENY1",
13836                 .fn    =  torture_denytest1,
13837         },
13838         {
13839                 .name  = "DENY2",
13840                 .fn    =  torture_denytest2,
13841         },
13842         {
13843                 .name  = "TCON",
13844                 .fn    =  run_tcon_test,
13845         },
13846         {
13847                 .name  = "TCONDEV",
13848                 .fn    =  run_tcon_devtype_test,
13849         },
13850         {
13851                 .name  = "RW1",
13852                 .fn    =  run_readwritetest,
13853         },
13854         {
13855                 .name  = "RW2",
13856                 .fn    =  run_readwritemulti,
13857                 .flags = FLAG_MULTIPROC
13858         },
13859         {
13860                 .name  = "RW3",
13861                 .fn    =  run_readwritelarge,
13862         },
13863         {
13864                 .name  = "RW-SIGNING",
13865                 .fn    =  run_readwritelarge_signtest,
13866         },
13867         {
13868                 .name  = "OPEN",
13869                 .fn    = run_opentest,
13870         },
13871         {
13872                 .name  = "POSIX",
13873                 .fn    = run_simple_posix_open_test,
13874         },
13875         {
13876                 .name  = "POSIX-APPEND",
13877                 .fn    = run_posix_append,
13878         },
13879         {
13880                 .name  = "POSIX-SYMLINK-ACL",
13881                 .fn    = run_acl_symlink_test,
13882         },
13883         {
13884                 .name  = "POSIX-SYMLINK-EA",
13885                 .fn    = run_ea_symlink_test,
13886         },
13887         {
13888                 .name  = "POSIX-STREAM-DELETE",
13889                 .fn    = run_posix_stream_delete,
13890         },
13891         {
13892                 .name  = "POSIX-OFD-LOCK",
13893                 .fn    = run_posix_ofd_lock_test,
13894         },
13895         {
13896                 .name  = "POSIX-BLOCKING-LOCK",
13897                 .fn    = run_posix_blocking_lock,
13898         },
13899         {
13900                 .name  = "POSIX-MKDIR",
13901                 .fn    = run_posix_mkdir_test,
13902         },
13903         {
13904                 .name  = "POSIX-ACL-OPLOCK",
13905                 .fn    = run_posix_acl_oplock_test,
13906         },
13907         {
13908                 .name  = "POSIX-ACL-SHAREROOT",
13909                 .fn    = run_posix_acl_shareroot_test,
13910         },
13911         {
13912                 .name  = "WINDOWS-BAD-SYMLINK",
13913                 .fn    = run_symlink_open_test,
13914         },
13915         {
13916                 .name  = "CASE-INSENSITIVE-CREATE",
13917                 .fn    = run_case_insensitive_create,
13918         },
13919         {
13920                 .name  = "ASYNC-ECHO",
13921                 .fn    = run_async_echo,
13922         },
13923         {
13924                 .name  = "UID-REGRESSION-TEST",
13925                 .fn    = run_uid_regression_test,
13926         },
13927         {
13928                 .name  = "SHORTNAME-TEST",
13929                 .fn    = run_shortname_test,
13930         },
13931         {
13932                 .name  = "ADDRCHANGE",
13933                 .fn    = run_addrchange,
13934         },
13935 #if 1
13936         {
13937                 .name  = "OPENATTR",
13938                 .fn    = run_openattrtest,
13939         },
13940 #endif
13941         {
13942                 .name  = "XCOPY",
13943                 .fn    = run_xcopy,
13944         },
13945         {
13946                 .name  = "RENAME",
13947                 .fn    = run_rename,
13948         },
13949         {
13950                 .name  = "RENAME-ACCESS",
13951                 .fn    = run_rename_access,
13952         },
13953         {
13954                 .name  = "OWNER-RIGHTS",
13955                 .fn    = run_owner_rights,
13956         },
13957         {
13958                 .name  = "DELETE",
13959                 .fn    = run_deletetest,
13960         },
13961         {
13962                 .name  = "DELETE-PRINT",
13963                 .fn    = run_delete_print_test,
13964         },
13965         {
13966                 .name  = "WILDDELETE",
13967                 .fn    = run_wild_deletetest,
13968         },
13969         {
13970                 .name  = "DELETE-LN",
13971                 .fn    = run_deletetest_ln,
13972         },
13973         {
13974                 .name  = "PROPERTIES",
13975                 .fn    = run_properties,
13976         },
13977         {
13978                 .name  = "MANGLE",
13979                 .fn    = torture_mangle,
13980         },
13981         {
13982                 .name  = "MANGLE1",
13983                 .fn    = run_mangle1,
13984         },
13985         {
13986                 .name  = "MANGLE-ILLEGAL",
13987                 .fn    = run_mangle_illegal,
13988         },
13989         {
13990                 .name  = "W2K",
13991                 .fn    = run_w2ktest,
13992         },
13993         {
13994                 .name  = "TRANS2SCAN",
13995                 .fn    = torture_trans2_scan,
13996         },
13997         {
13998                 .name  = "NTTRANSSCAN",
13999                 .fn    = torture_nttrans_scan,
14000         },
14001         {
14002                 .name  = "UTABLE",
14003                 .fn    = torture_utable,
14004         },
14005         {
14006                 .name  = "CASETABLE",
14007                 .fn    = torture_casetable,
14008         },
14009         {
14010                 .name  = "ERRMAPEXTRACT",
14011                 .fn    = run_error_map_extract,
14012         },
14013         {
14014                 .name  = "PIPE_NUMBER",
14015                 .fn    = run_pipe_number,
14016         },
14017         {
14018                 .name  = "TCON2",
14019                 .fn    =  run_tcon2_test,
14020         },
14021         {
14022                 .name  = "IOCTL",
14023                 .fn    =  torture_ioctl_test,
14024         },
14025         {
14026                 .name  = "CHKPATH",
14027                 .fn    =  torture_chkpath_test,
14028         },
14029         {
14030                 .name  = "FDSESS",
14031                 .fn    = run_fdsesstest,
14032         },
14033         {
14034                 .name  = "EATEST",
14035                 .fn    = run_eatest,
14036         },
14037         {
14038                 .name  = "SESSSETUP_BENCH",
14039                 .fn    = run_sesssetup_bench,
14040         },
14041         {
14042                 .name  = "CHAIN1",
14043                 .fn    = run_chain1,
14044         },
14045         {
14046                 .name  = "CHAIN2",
14047                 .fn    = run_chain2,
14048         },
14049         {
14050                 .name  = "CHAIN3",
14051                 .fn    = run_chain3,
14052         },
14053         {
14054                 .name  = "WINDOWS-WRITE",
14055                 .fn    = run_windows_write,
14056         },
14057         {
14058                 .name  = "LARGE_READX",
14059                 .fn    = run_large_readx,
14060         },
14061         {
14062                 .name  = "NTTRANS-CREATE",
14063                 .fn    = run_nttrans_create,
14064         },
14065         {
14066                 .name  = "NTTRANS-FSCTL",
14067                 .fn    = run_nttrans_fsctl,
14068         },
14069         {
14070                 .name  = "CLI_ECHO",
14071                 .fn    = run_cli_echo,
14072         },
14073         {
14074                 .name  = "CLI_SPLICE",
14075                 .fn    = run_cli_splice,
14076         },
14077         {
14078                 .name  = "TLDAP",
14079                 .fn    = run_tldap,
14080         },
14081         {
14082                 .name  = "STREAMERROR",
14083                 .fn    = run_streamerror,
14084         },
14085         {
14086                 .name  = "NOTIFY-BENCH",
14087                 .fn    = run_notify_bench,
14088         },
14089         {
14090                 .name  = "NOTIFY-BENCH2",
14091                 .fn    = run_notify_bench2,
14092         },
14093         {
14094                 .name  = "NOTIFY-BENCH3",
14095                 .fn    = run_notify_bench3,
14096         },
14097         {
14098                 .name  = "BAD-NBT-SESSION",
14099                 .fn    = run_bad_nbt_session,
14100         },
14101         {
14102                 .name  = "IGN-BAD-NEGPROT",
14103                 .fn    = run_ign_bad_negprot,
14104         },
14105         {
14106                 .name  = "SMB-ANY-CONNECT",
14107                 .fn    = run_smb_any_connect,
14108         },
14109         {
14110                 .name  = "NOTIFY-ONLINE",
14111                 .fn    = run_notify_online,
14112         },
14113         {
14114                 .name  = "SMB2-BASIC",
14115                 .fn    = run_smb2_basic,
14116         },
14117         {
14118                 .name  = "SMB2-NEGPROT",
14119                 .fn    = run_smb2_negprot,
14120         },
14121         {
14122                 .name  = "SMB2-ANONYMOUS",
14123                 .fn    = run_smb2_anonymous,
14124         },
14125         {
14126                 .name  = "SMB2-SESSION-RECONNECT",
14127                 .fn    = run_smb2_session_reconnect,
14128         },
14129         {
14130                 .name  = "SMB2-TCON-DEPENDENCE",
14131                 .fn    = run_smb2_tcon_dependence,
14132         },
14133         {
14134                 .name  = "SMB2-MULTI-CHANNEL",
14135                 .fn    = run_smb2_multi_channel,
14136         },
14137         {
14138                 .name  = "SMB2-SESSION-REAUTH",
14139                 .fn    = run_smb2_session_reauth,
14140         },
14141         {
14142                 .name  = "SMB2-FTRUNCATE",
14143                 .fn    = run_smb2_ftruncate,
14144         },
14145         {
14146                 .name  = "SMB2-DIR-FSYNC",
14147                 .fn    = run_smb2_dir_fsync,
14148         },
14149         {
14150                 .name  = "CLEANUP1",
14151                 .fn    = run_cleanup1,
14152         },
14153         {
14154                 .name  = "CLEANUP2",
14155                 .fn    = run_cleanup2,
14156         },
14157         {
14158                 .name  = "CLEANUP3",
14159                 .fn    = run_cleanup3,
14160         },
14161         {
14162                 .name  = "CLEANUP4",
14163                 .fn    = run_cleanup4,
14164         },
14165         {
14166                 .name  = "OPLOCK-CANCEL",
14167                 .fn    = run_oplock_cancel,
14168         },
14169         {
14170                 .name  = "PIDHIGH",
14171                 .fn    = run_pidhigh,
14172         },
14173         {
14174                 .name  = "LOCAL-SUBSTITUTE",
14175                 .fn    = run_local_substitute,
14176         },
14177         {
14178                 .name  = "LOCAL-GENCACHE",
14179                 .fn    = run_local_gencache,
14180         },
14181         {
14182                 .name  = "LOCAL-DBWRAP-WATCH1",
14183                 .fn    = run_dbwrap_watch1,
14184         },
14185         {
14186                 .name  = "LOCAL-DBWRAP-WATCH2",
14187                 .fn    = run_dbwrap_watch2,
14188         },
14189         {
14190                 .name  = "LOCAL-DBWRAP-DO-LOCKED1",
14191                 .fn    = run_dbwrap_do_locked1,
14192         },
14193         {
14194                 .name  = "LOCAL-MESSAGING-READ1",
14195                 .fn    = run_messaging_read1,
14196         },
14197         {
14198                 .name  = "LOCAL-MESSAGING-READ2",
14199                 .fn    = run_messaging_read2,
14200         },
14201         {
14202                 .name  = "LOCAL-MESSAGING-READ3",
14203                 .fn    = run_messaging_read3,
14204         },
14205         {
14206                 .name  = "LOCAL-MESSAGING-READ4",
14207                 .fn    = run_messaging_read4,
14208         },
14209         {
14210                 .name  = "LOCAL-MESSAGING-FDPASS1",
14211                 .fn    = run_messaging_fdpass1,
14212         },
14213         {
14214                 .name  = "LOCAL-MESSAGING-FDPASS2",
14215                 .fn    = run_messaging_fdpass2,
14216         },
14217         {
14218                 .name  = "LOCAL-MESSAGING-FDPASS2a",
14219                 .fn    = run_messaging_fdpass2a,
14220         },
14221         {
14222                 .name  = "LOCAL-MESSAGING-FDPASS2b",
14223                 .fn    = run_messaging_fdpass2b,
14224         },
14225         {
14226                 .name  = "LOCAL-MESSAGING-SEND-ALL",
14227                 .fn    = run_messaging_send_all,
14228         },
14229         {
14230                 .name  = "LOCAL-BASE64",
14231                 .fn    = run_local_base64,
14232         },
14233         {
14234                 .name  = "LOCAL-RBTREE",
14235                 .fn    = run_local_rbtree,
14236         },
14237         {
14238                 .name  = "LOCAL-MEMCACHE",
14239                 .fn    = run_local_memcache,
14240         },
14241         {
14242                 .name  = "LOCAL-STREAM-NAME",
14243                 .fn    = run_local_stream_name,
14244         },
14245         {
14246                 .name  = "WBCLIENT-MULTI-PING",
14247                 .fn    = run_wbclient_multi_ping,
14248         },
14249         {
14250                 .name  = "LOCAL-string_to_sid",
14251                 .fn    = run_local_string_to_sid,
14252         },
14253         {
14254                 .name  = "LOCAL-sid_to_string",
14255                 .fn    = run_local_sid_to_string,
14256         },
14257         {
14258                 .name  = "LOCAL-binary_to_sid",
14259                 .fn    = run_local_binary_to_sid,
14260         },
14261         {
14262                 .name  = "LOCAL-DBTRANS",
14263                 .fn    = run_local_dbtrans,
14264         },
14265         {
14266                 .name  = "LOCAL-TEVENT-POLL",
14267                 .fn    = run_local_tevent_poll,
14268         },
14269         {
14270                 .name  = "LOCAL-CONVERT-STRING",
14271                 .fn    = run_local_convert_string,
14272         },
14273         {
14274                 .name  = "LOCAL-CONV-AUTH-INFO",
14275                 .fn    = run_local_conv_auth_info,
14276         },
14277         {
14278                 .name  = "LOCAL-hex_encode_buf",
14279                 .fn    = run_local_hex_encode_buf,
14280         },
14281         {
14282                 .name  = "LOCAL-IDMAP-TDB-COMMON",
14283                 .fn    = run_idmap_tdb_common_test,
14284         },
14285         {
14286                 .name  = "LOCAL-remove_duplicate_addrs2",
14287                 .fn    = run_local_remove_duplicate_addrs2,
14288         },
14289         {
14290                 .name  = "local-tdb-opener",
14291                 .fn    = run_local_tdb_opener,
14292         },
14293         {
14294                 .name  = "local-tdb-writer",
14295                 .fn    = run_local_tdb_writer,
14296         },
14297         {
14298                 .name  = "LOCAL-DBWRAP-CTDB",
14299                 .fn    = run_local_dbwrap_ctdb,
14300         },
14301         {
14302                 .name  = "LOCAL-BENCH-PTHREADPOOL",
14303                 .fn    = run_bench_pthreadpool,
14304         },
14305         {
14306                 .name  = "LOCAL-PTHREADPOOL-TEVENT",
14307                 .fn    = run_pthreadpool_tevent,
14308         },
14309         {
14310                 .name  = "LOCAL-G-LOCK1",
14311                 .fn    = run_g_lock1,
14312         },
14313         {
14314                 .name  = "LOCAL-G-LOCK2",
14315                 .fn    = run_g_lock2,
14316         },
14317         {
14318                 .name  = "LOCAL-G-LOCK3",
14319                 .fn    = run_g_lock3,
14320         },
14321         {
14322                 .name  = "LOCAL-G-LOCK4",
14323                 .fn    = run_g_lock4,
14324         },
14325         {
14326                 .name  = "LOCAL-G-LOCK5",
14327                 .fn    = run_g_lock5,
14328         },
14329         {
14330                 .name  = "LOCAL-G-LOCK6",
14331                 .fn    = run_g_lock6,
14332         },
14333         {
14334                 .name  = "LOCAL-G-LOCK-PING-PONG",
14335                 .fn    = run_g_lock_ping_pong,
14336         },
14337         {
14338                 .name  = "LOCAL-CANONICALIZE-PATH",
14339                 .fn    = run_local_canonicalize_path,
14340         },
14341         {
14342                 .name  = "LOCAL-NAMEMAP-CACHE1",
14343                 .fn    = run_local_namemap_cache1,
14344         },
14345         {
14346                 .name  = "LOCAL-IDMAP-CACHE1",
14347                 .fn    = run_local_idmap_cache1,
14348         },
14349         {
14350                 .name  = "qpathinfo-bufsize",
14351                 .fn    = run_qpathinfo_bufsize,
14352         },
14353         {
14354                 .name  = "hide-new-files-timeout",
14355                 .fn    = run_hidenewfiles,
14356         },
14357         {
14358                 .name = NULL,
14359         },
14360 };
14361
14362 /****************************************************************************
14363 run a specified test or "ALL"
14364 ****************************************************************************/
14365 static bool run_test(const char *name)
14366 {
14367         bool ret = True;
14368         bool result = True;
14369         bool found = False;
14370         int i;
14371         double t;
14372         if (strequal(name,"ALL")) {
14373                 for (i=0;torture_ops[i].name;i++) {
14374                         run_test(torture_ops[i].name);
14375                 }
14376                 found = True;
14377         }
14378
14379         for (i=0;torture_ops[i].name;i++) {
14380                 fstr_sprintf(randomfname, "\\XX%x", 
14381                          (unsigned)random());
14382
14383                 if (strequal(name, torture_ops[i].name)) {
14384                         found = True;
14385                         printf("Running %s\n", name);
14386                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
14387                                 t = create_procs(torture_ops[i].fn, &result);
14388                                 if (!result) { 
14389                                         ret = False;
14390                                         printf("TEST %s FAILED!\n", name);
14391                                 }
14392                         } else {
14393                                 struct timeval start;
14394                                 start = timeval_current();
14395                                 if (!torture_ops[i].fn(0)) {
14396                                         ret = False;
14397                                         printf("TEST %s FAILED!\n", name);
14398                                 }
14399                                 t = timeval_elapsed(&start);
14400                         }
14401                         printf("%s took %g secs\n\n", name, t);
14402                 }
14403         }
14404
14405         if (!found) {
14406                 printf("Did not find a test named %s\n", name);
14407                 ret = False;
14408         }
14409
14410         return ret;
14411 }
14412
14413
14414 static void usage(void)
14415 {
14416         int i;
14417
14418         printf("WARNING samba4 test suite is much more complete nowadays.\n");
14419         printf("Please use samba4 torture.\n\n");
14420
14421         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
14422
14423         printf("\t-d debuglevel\n");
14424         printf("\t-U user%%pass\n");
14425         printf("\t-k                    use kerberos\n");
14426         printf("\t-N numprocs\n");
14427         printf("\t-n my_netbios_name\n");
14428         printf("\t-W workgroup\n");
14429         printf("\t-o num_operations\n");
14430         printf("\t-O socket_options\n");
14431         printf("\t-m maximum protocol\n");
14432         printf("\t-L use oplocks\n");
14433         printf("\t-c CLIENT.TXT         specify client load file for NBENCH\n");
14434         printf("\t-A showall\n");
14435         printf("\t-p port\n");
14436         printf("\t-s seed\n");
14437         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
14438         printf("\t-f filename           filename to test\n");
14439         printf("\t-e                    encrypt\n");
14440         printf("\n\n");
14441
14442         printf("tests are:");
14443         for (i=0;torture_ops[i].name;i++) {
14444                 printf(" %s", torture_ops[i].name);
14445         }
14446         printf("\n");
14447
14448         printf("default test is ALL\n");
14449
14450         exit(1);
14451 }
14452
14453 /****************************************************************************
14454   main program
14455 ****************************************************************************/
14456  int main(int argc,char *argv[])
14457 {
14458         int opt, i;
14459         char *p;
14460         int gotuser = 0;
14461         int gotpass = 0;
14462         bool correct = True;
14463         TALLOC_CTX *frame = talloc_stackframe();
14464         int seed = time(NULL);
14465
14466 #ifdef HAVE_SETBUFFER
14467         setbuffer(stdout, NULL, 0);
14468 #endif
14469
14470         setup_logging("smbtorture", DEBUG_STDOUT);
14471
14472         smb_init_locale();
14473         fault_setup();
14474
14475         if (is_default_dyn_CONFIGFILE()) {
14476                 if(getenv("SMB_CONF_PATH")) {
14477                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
14478                 }
14479         }
14480         lp_load_global(get_dyn_CONFIGFILE());
14481         load_interfaces();
14482
14483         if (argc < 2) {
14484                 usage();
14485         }
14486
14487         for(p = argv[1]; *p; p++)
14488           if(*p == '\\')
14489             *p = '/';
14490
14491         if (strncmp(argv[1], "//", 2)) {
14492                 usage();
14493         }
14494
14495         fstrcpy(host, &argv[1][2]);
14496         p = strchr_m(&host[2],'/');
14497         if (!p) {
14498                 usage();
14499         }
14500         *p = 0;
14501         fstrcpy(share, p+1);
14502
14503         fstrcpy(myname, get_myname(talloc_tos()));
14504         if (!*myname) {
14505                 fprintf(stderr, "Failed to get my hostname.\n");
14506                 return 1;
14507         }
14508
14509         if (*username == 0 && getenv("LOGNAME")) {
14510           fstrcpy(username,getenv("LOGNAME"));
14511         }
14512
14513         argc--;
14514         argv++;
14515
14516         fstrcpy(workgroup, lp_workgroup());
14517
14518         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
14519                != EOF) {
14520                 switch (opt) {
14521                 case 'p':
14522                         port_to_use = atoi(optarg);
14523                         break;
14524                 case 's':
14525                         seed = atoi(optarg);
14526                         break;
14527                 case 'W':
14528                         fstrcpy(workgroup,optarg);
14529                         break;
14530                 case 'm':
14531                         lp_set_cmdline("client max protocol", optarg);
14532                         break;
14533                 case 'N':
14534                         torture_nprocs = atoi(optarg);
14535                         break;
14536                 case 'o':
14537                         torture_numops = atoi(optarg);
14538                         break;
14539                 case 'd':
14540                         lp_set_cmdline("log level", optarg);
14541                         break;
14542                 case 'O':
14543                         sockops = optarg;
14544                         break;
14545                 case 'L':
14546                         use_oplocks = True;
14547                         break;
14548                 case 'l':
14549                         local_path = optarg;
14550                         break;
14551                 case 'A':
14552                         torture_showall = True;
14553                         break;
14554                 case 'n':
14555                         fstrcpy(myname, optarg);
14556                         break;
14557                 case 'c':
14558                         client_txt = optarg;
14559                         break;
14560                 case 'e':
14561                         do_encrypt = true;
14562                         break;
14563                 case 'k':
14564 #ifdef HAVE_KRB5
14565                         use_kerberos = True;
14566 #else
14567                         d_printf("No kerberos support compiled in\n");
14568                         exit(1);
14569 #endif
14570                         break;
14571                 case 'U':
14572                         gotuser = 1;
14573                         fstrcpy(username,optarg);
14574                         p = strchr_m(username,'%');
14575                         if (p) {
14576                                 *p = 0;
14577                                 fstrcpy(password, p+1);
14578                                 gotpass = 1;
14579                         }
14580                         break;
14581                 case 'b':
14582                         fstrcpy(multishare_conn_fname, optarg);
14583                         use_multishare_conn = True;
14584                         break;
14585                 case 'B':
14586                         torture_blocksize = atoi(optarg);
14587                         break;
14588                 case 'f':
14589                         test_filename = SMB_STRDUP(optarg);
14590                         break;
14591                 default:
14592                         printf("Unknown option %c (%d)\n", (char)opt, opt);
14593                         usage();
14594                 }
14595         }
14596
14597         d_printf("using seed %d\n", seed);
14598
14599         srandom(seed);
14600
14601         if(use_kerberos && !gotuser) gotpass = True;
14602
14603         while (!gotpass) {
14604                 char pwd[256] = {0};
14605                 int rc;
14606
14607                 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
14608                 if (rc == 0) {
14609                         fstrcpy(password, pwd);
14610                         gotpass = 1;
14611                 }
14612         }
14613
14614         printf("host=%s share=%s user=%s myname=%s\n", 
14615                host, share, username, myname);
14616
14617         torture_creds = cli_session_creds_init(frame,
14618                                                username,
14619                                                workgroup,
14620                                                NULL, /* realm */
14621                                                password,
14622                                                use_kerberos,
14623                                                false, /* fallback_after_kerberos */
14624                                                false, /* use_ccache */
14625                                                false); /* password_is_nt_hash */
14626         if (torture_creds == NULL) {
14627                 d_printf("cli_session_creds_init() failed.\n");
14628                 exit(1);
14629         }
14630
14631         if (argc == optind) {
14632                 correct = run_test("ALL");
14633         } else {
14634                 for (i=optind;i<argc;i++) {
14635                         if (!run_test(argv[i])) {
14636                                 correct = False;
14637                         }
14638                 }
14639         }
14640
14641         TALLOC_FREE(frame);
14642
14643         if (correct) {
14644                 return(0);
14645         } else {
14646                 return(1);
14647         }
14648 }