s3:torture: add torture_open_connection_flags()
[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 "wbc_async.h"
24 #include "torture/proto.h"
25 #include "libcli/security/security.h"
26 #include "tldap.h"
27 #include "tldap_util.h"
28 #include "../librpc/gen_ndr/svcctl.h"
29 #include "../lib/util/memcache.h"
30 #include "nsswitch/winbind_client.h"
31 #include "dbwrap/dbwrap.h"
32 #include "dbwrap/dbwrap_open.h"
33 #include "dbwrap/dbwrap_rbt.h"
34 #include "talloc_dict.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
47 extern char *optarg;
48 extern int optind;
49
50 fstring host, workgroup, share, password, username, myname;
51 struct cli_credentials *torture_creds;
52 static const char *sockops="TCP_NODELAY";
53 int torture_nprocs=1;
54 static int port_to_use=0;
55 int torture_numops=100;
56 int torture_blocksize=1024*1024;
57 static int procnum; /* records process count number when forking */
58 static struct cli_state *current_cli;
59 static fstring randomfname;
60 static bool use_oplocks;
61 static bool use_level_II_oplocks;
62 static const char *client_txt = "client_oplocks.txt";
63 static bool disable_spnego;
64 static bool use_kerberos;
65 static bool force_dos_errors;
66 static fstring multishare_conn_fname;
67 static bool use_multishare_conn = False;
68 static bool do_encrypt;
69 static const char *local_path = NULL;
70 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
71 char *test_filename;
72
73 bool torture_showall = False;
74
75 static double create_procs(bool (*fn)(int), bool *result);
76
77 /********************************************************************
78  Ensure a connection is encrypted.
79 ********************************************************************/
80
81 static bool force_cli_encryption(struct cli_state *c,
82                         const char *sharename)
83 {
84         uint16_t major, minor;
85         uint32_t caplow, caphigh;
86         NTSTATUS status;
87
88         if (!SERVER_HAS_UNIX_CIFS(c)) {
89                 d_printf("Encryption required and "
90                         "server that doesn't support "
91                         "UNIX extensions - failing connect\n");
92                         return false;
93         }
94
95         status = cli_unix_extensions_version(c, &major, &minor, &caplow,
96                                              &caphigh);
97         if (!NT_STATUS_IS_OK(status)) {
98                 d_printf("Encryption required and "
99                         "can't get UNIX CIFS extensions "
100                         "version from server: %s\n", nt_errstr(status));
101                 return false;
102         }
103
104         if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
105                 d_printf("Encryption required and "
106                         "share %s doesn't support "
107                         "encryption.\n", sharename);
108                 return false;
109         }
110
111         status = cli_smb1_setup_encryption(c, torture_creds);
112         if (!NT_STATUS_IS_OK(status)) {
113                 d_printf("Encryption required and "
114                         "setup failed with error %s.\n",
115                         nt_errstr(status));
116                 return false;
117         }
118
119         return true;
120 }
121
122
123 static struct cli_state *open_nbt_connection(void)
124 {
125         struct cli_state *c;
126         NTSTATUS status;
127         int flags = 0;
128
129         if (disable_spnego) {
130                 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
131         }
132
133         if (use_oplocks) {
134                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
135         }
136
137         if (use_level_II_oplocks) {
138                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
139         }
140
141         if (use_kerberos) {
142                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
143         }
144
145         if (force_dos_errors) {
146                 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
147         }
148
149         status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
150                                 signing_state, flags, &c);
151         if (!NT_STATUS_IS_OK(status)) {
152                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
153                 return NULL;
154         }
155
156         cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
157
158         return c;
159 }
160
161 /****************************************************************************
162  Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
163 ****************************************************************************/
164
165 static bool cli_bad_session_request(int fd,
166                          struct nmb_name *calling, struct nmb_name *called)
167 {
168         TALLOC_CTX *frame;
169         uint8_t len_buf[4];
170         struct iovec iov[3];
171         ssize_t len;
172         uint8_t *inbuf;
173         int err;
174         bool ret = false;
175         uint8_t message_type;
176         uint8_t error;
177         struct tevent_context *ev;
178         struct tevent_req *req;
179
180         frame = talloc_stackframe();
181
182         iov[0].iov_base = len_buf;
183         iov[0].iov_len  = sizeof(len_buf);
184
185         /* put in the destination name */
186
187         iov[1].iov_base = name_mangle(talloc_tos(), called->name,
188                                       called->name_type);
189         if (iov[1].iov_base == NULL) {
190                 goto fail;
191         }
192         iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
193                                   talloc_get_size(iov[1].iov_base));
194
195         /* and my name */
196
197         iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
198                                       calling->name_type);
199         if (iov[2].iov_base == NULL) {
200                 goto fail;
201         }
202         iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
203                                   talloc_get_size(iov[2].iov_base));
204
205         /* Deliberately corrupt the name len (first byte) */
206         *((uint8_t *)iov[2].iov_base) = 100;
207
208         /* send a session request (RFC 1002) */
209         /* setup the packet length
210          * Remove four bytes from the length count, since the length
211          * field in the NBT Session Service header counts the number
212          * of bytes which follow.  The cli_send_smb() function knows
213          * about this and accounts for those four bytes.
214          * CRH.
215          */
216
217         _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
218         SCVAL(len_buf,0,0x81);
219
220         len = write_data_iov(fd, iov, 3);
221         if (len == -1) {
222                 goto fail;
223         }
224
225         ev = samba_tevent_context_init(frame);
226         if (ev == NULL) {
227                 goto fail;
228         }
229         req = read_smb_send(frame, ev, fd);
230         if (req == NULL) {
231                 goto fail;
232         }
233         if (!tevent_req_poll(req, ev)) {
234                 goto fail;
235         }
236         len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
237         if (len == -1) {
238                 errno = err;
239                 goto fail;
240         }
241         TALLOC_FREE(ev);
242
243         message_type = CVAL(inbuf, 0);
244         if (message_type != 0x83) {
245                 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
246                           message_type);
247                 goto fail;
248         }
249
250         if (smb_len(inbuf) != 1) {
251                 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
252                           (int)smb_len(inbuf));
253                 goto fail;
254         }
255
256         error = CVAL(inbuf, 4);
257         if (error !=  0x82) {
258                 d_fprintf(stderr, "Expected error 0x82, got %d\n",
259                           (int)error);
260                 goto fail;
261         }
262
263         ret = true;
264 fail:
265         TALLOC_FREE(frame);
266         return ret;
267 }
268
269 /* Insert a NULL at the first separator of the given path and return a pointer
270  * to the remainder of the string.
271  */
272 static char *
273 terminate_path_at_separator(char * path)
274 {
275         char * p;
276
277         if (!path) {
278                 return NULL;
279         }
280
281         if ((p = strchr_m(path, '/'))) {
282                 *p = '\0';
283                 return p + 1;
284         }
285
286         if ((p = strchr_m(path, '\\'))) {
287                 *p = '\0';
288                 return p + 1;
289         }
290
291         /* No separator. */
292         return NULL;
293 }
294
295 /*
296   parse a //server/share type UNC name
297 */
298 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
299                       char **hostname, char **sharename)
300 {
301         char *p;
302
303         *hostname = *sharename = NULL;
304
305         if (strncmp(unc_name, "\\\\", 2) &&
306             strncmp(unc_name, "//", 2)) {
307                 return False;
308         }
309
310         *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
311         p = terminate_path_at_separator(*hostname);
312
313         if (p && *p) {
314                 *sharename = talloc_strdup(mem_ctx, p);
315                 terminate_path_at_separator(*sharename);
316         }
317
318         if (*hostname && *sharename) {
319                 return True;
320         }
321
322         TALLOC_FREE(*hostname);
323         TALLOC_FREE(*sharename);
324         return False;
325 }
326
327 static bool torture_open_connection_share(struct cli_state **c,
328                                    const char *hostname, 
329                                    const char *sharename,
330                                    int flags)
331 {
332         NTSTATUS status;
333
334         status = cli_full_connection_creds(c,
335                                            myname,
336                                            hostname,
337                                            NULL, /* dest_ss */
338                                            port_to_use,
339                                            sharename,
340                                            "?????",
341                                            torture_creds,
342                                            flags,
343                                            signing_state);
344         if (!NT_STATUS_IS_OK(status)) {
345                 printf("failed to open share connection: //%s/%s port:%d - %s\n",
346                         hostname, sharename, port_to_use, nt_errstr(status));
347                 return False;
348         }
349
350         cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
351
352         if (do_encrypt) {
353                 return force_cli_encryption(*c,
354                                         sharename);
355         }
356         return True;
357 }
358
359 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
360 {
361         char **unc_list = NULL;
362         int num_unc_names = 0;
363         bool result;
364
365         if (use_multishare_conn==True) {
366                 char *h, *s;
367                 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
368                 if (!unc_list || num_unc_names <= 0) {
369                         printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
370                         exit(1);
371                 }
372
373                 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
374                                       NULL, &h, &s)) {
375                         printf("Failed to parse UNC name %s\n",
376                                unc_list[conn_index % num_unc_names]);
377                         TALLOC_FREE(unc_list);
378                         exit(1);
379                 }
380
381                 result = torture_open_connection_share(c, h, s, flags);
382
383                 /* h, s were copied earlier */
384                 TALLOC_FREE(unc_list);
385                 return result;
386         }
387
388         return torture_open_connection_share(c, host, share, flags);
389 }
390
391 bool torture_open_connection(struct cli_state **c, int conn_index)
392 {
393         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
394
395         if (use_oplocks) {
396                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
397         }
398         if (use_level_II_oplocks) {
399                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
400         }
401
402         return torture_open_connection_flags(c, conn_index, flags);
403 }
404
405 bool torture_init_connection(struct cli_state **pcli)
406 {
407         struct cli_state *cli;
408
409         cli = open_nbt_connection();
410         if (cli == NULL) {
411                 return false;
412         }
413
414         *pcli = cli;
415         return true;
416 }
417
418 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
419 {
420         uint16_t old_vuid = cli_state_get_uid(cli);
421         NTSTATUS status;
422         bool ret;
423
424         cli_state_set_uid(cli, 0);
425         status = cli_session_setup_creds(cli, torture_creds);
426         ret = NT_STATUS_IS_OK(status);
427         *new_vuid = cli_state_get_uid(cli);
428         cli_state_set_uid(cli, old_vuid);
429         return ret;
430 }
431
432
433 bool torture_close_connection(struct cli_state *c)
434 {
435         bool ret = True;
436         NTSTATUS status;
437
438         status = cli_tdis(c);
439         if (!NT_STATUS_IS_OK(status)) {
440                 printf("tdis failed (%s)\n", nt_errstr(status));
441                 ret = False;
442         }
443
444         cli_shutdown(c);
445
446         return ret;
447 }
448
449
450 /* check if the server produced the expected dos or nt error code */
451 static bool check_both_error(int line, NTSTATUS status,
452                              uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
453 {
454         if (NT_STATUS_IS_DOS(status)) {
455                 uint8_t cclass;
456                 uint32_t num;
457
458                 /* Check DOS error */
459                 cclass = NT_STATUS_DOS_CLASS(status);
460                 num = NT_STATUS_DOS_CODE(status);
461
462                 if (eclass != cclass || ecode != num) {
463                         printf("unexpected error code class=%d code=%d\n",
464                                (int)cclass, (int)num);
465                         printf(" expected %d/%d %s (line=%d)\n",
466                                (int)eclass, (int)ecode, nt_errstr(nterr), line);
467                         return false;
468                 }
469         } else {
470                 /* Check NT error */
471                 if (!NT_STATUS_EQUAL(nterr, status)) {
472                         printf("unexpected error code %s\n",
473                                 nt_errstr(status));
474                         printf(" expected %s (line=%d)\n",
475                                 nt_errstr(nterr), line);
476                         return false;
477                 }
478         }
479
480         return true;
481 }
482
483
484 /* check if the server produced the expected error code */
485 static bool check_error(int line, NTSTATUS status,
486                         uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
487 {
488         if (NT_STATUS_IS_DOS(status)) {
489                 uint8_t cclass;
490                 uint32_t num;
491
492                 /* Check DOS error */
493
494                 cclass = NT_STATUS_DOS_CLASS(status);
495                 num = NT_STATUS_DOS_CODE(status);
496
497                 if (eclass != cclass || ecode != num) {
498                         printf("unexpected error code class=%d code=%d\n", 
499                                (int)cclass, (int)num);
500                         printf(" expected %d/%d %s (line=%d)\n", 
501                                (int)eclass, (int)ecode, nt_errstr(nterr),
502                                line);
503                         return False;
504                 }
505
506         } else {
507                 /* Check NT error */
508
509                 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
510                         printf("unexpected error code %s\n",
511                                nt_errstr(status));
512                         printf(" expected %s (line=%d)\n", nt_errstr(nterr),
513                                line);
514                         return False;
515                 }
516         }
517
518         return True;
519 }
520
521
522 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
523 {
524         NTSTATUS status;
525
526         status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
527
528         while (!NT_STATUS_IS_OK(status)) {
529                 if (!check_both_error(__LINE__, status, ERRDOS,
530                                       ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
531                         return false;
532                 }
533
534                 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
535         }
536
537         return true;
538 }
539
540
541 static bool rw_torture(struct cli_state *c)
542 {
543         const char *lockfname = "\\torture.lck";
544         fstring fname;
545         uint16_t fnum;
546         uint16_t fnum2;
547         pid_t pid2, pid = getpid();
548         int i, j;
549         char buf[1024];
550         bool correct = True;
551         size_t nread = 0;
552         NTSTATUS status;
553
554         memset(buf, '\0', sizeof(buf));
555
556         status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
557                          DENY_NONE, &fnum2);
558         if (!NT_STATUS_IS_OK(status)) {
559                 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
560         }
561         if (!NT_STATUS_IS_OK(status)) {
562                 printf("open of %s failed (%s)\n",
563                        lockfname, nt_errstr(status));
564                 return False;
565         }
566
567         for (i=0;i<torture_numops;i++) {
568                 unsigned n = (unsigned)sys_random()%10;
569
570                 if (i % 10 == 0) {
571                         printf("%d\r", i); fflush(stdout);
572                 }
573                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
574
575                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
576                         return False;
577                 }
578
579                 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
580                                   DENY_ALL, &fnum);
581                 if (!NT_STATUS_IS_OK(status)) {
582                         printf("open failed (%s)\n", nt_errstr(status));
583                         correct = False;
584                         break;
585                 }
586
587                 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
588                                       sizeof(pid), NULL);
589                 if (!NT_STATUS_IS_OK(status)) {
590                         printf("write failed (%s)\n", nt_errstr(status));
591                         correct = False;
592                 }
593
594                 for (j=0;j<50;j++) {
595                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
596                                               sizeof(pid)+(j*sizeof(buf)),
597                                               sizeof(buf), NULL);
598                         if (!NT_STATUS_IS_OK(status)) {
599                                 printf("write failed (%s)\n",
600                                        nt_errstr(status));
601                                 correct = False;
602                         }
603                 }
604
605                 pid2 = 0;
606
607                 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
608                                   &nread);
609                 if (!NT_STATUS_IS_OK(status)) {
610                         printf("read failed (%s)\n", nt_errstr(status));
611                         correct = false;
612                 } else if (nread != sizeof(pid)) {
613                         printf("read/write compare failed: "
614                                "recv %ld req %ld\n", (unsigned long)nread,
615                                (unsigned long)sizeof(pid));
616                         correct = false;
617                 }
618
619                 if (pid2 != pid) {
620                         printf("data corruption!\n");
621                         correct = False;
622                 }
623
624                 status = cli_close(c, fnum);
625                 if (!NT_STATUS_IS_OK(status)) {
626                         printf("close failed (%s)\n", nt_errstr(status));
627                         correct = False;
628                 }
629
630                 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
631                 if (!NT_STATUS_IS_OK(status)) {
632                         printf("unlink failed (%s)\n", nt_errstr(status));
633                         correct = False;
634                 }
635
636                 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
637                 if (!NT_STATUS_IS_OK(status)) {
638                         printf("unlock failed (%s)\n", nt_errstr(status));
639                         correct = False;
640                 }
641         }
642
643         cli_close(c, fnum2);
644         cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
645
646         printf("%d\n", i);
647
648         return correct;
649 }
650
651 static bool run_torture(int dummy)
652 {
653         struct cli_state *cli;
654         bool ret;
655
656         cli = current_cli;
657
658         smbXcli_conn_set_sockopt(cli->conn, sockops);
659
660         ret = rw_torture(cli);
661
662         if (!torture_close_connection(cli)) {
663                 ret = False;
664         }
665
666         return ret;
667 }
668
669 static bool rw_torture3(struct cli_state *c, char *lockfname)
670 {
671         uint16_t fnum = (uint16_t)-1;
672         unsigned int i = 0;
673         char buf[131072];
674         char buf_rd[131072];
675         unsigned count;
676         unsigned countprev = 0;
677         size_t sent = 0;
678         bool correct = True;
679         NTSTATUS status = NT_STATUS_OK;
680
681         srandom(1);
682         for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
683         {
684                 SIVAL(buf, i, sys_random());
685         }
686
687         if (procnum == 0)
688         {
689                 status = cli_unlink(
690                         c, lockfname,
691                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
692                 if (!NT_STATUS_IS_OK(status)) {
693                         printf("unlink failed (%s) (normal, this file should "
694                                "not exist)\n", nt_errstr(status));
695                 }
696
697                 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
698                                   DENY_NONE, &fnum);
699                 if (!NT_STATUS_IS_OK(status)) {
700                         printf("first open read/write of %s failed (%s)\n",
701                                         lockfname, nt_errstr(status));
702                         return False;
703                 }
704         }
705         else
706         {
707                 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
708                 {
709                         status = cli_openx(c, lockfname, O_RDONLY, 
710                                          DENY_NONE, &fnum);
711                         if (NT_STATUS_IS_OK(status)) {
712                                 break;
713                         }
714                         smb_msleep(10);
715                 }
716                 if (!NT_STATUS_IS_OK(status)) {
717                         printf("second open read-only of %s failed (%s)\n",
718                                         lockfname, nt_errstr(status));
719                         return False;
720                 }
721         }
722
723         i = 0;
724         for (count = 0; count < sizeof(buf); count += sent)
725         {
726                 if (count >= countprev) {
727                         printf("%d %8d\r", i, count);
728                         fflush(stdout);
729                         i++;
730                         countprev += (sizeof(buf) / 20);
731                 }
732
733                 if (procnum == 0)
734                 {
735                         sent = ((unsigned)sys_random()%(20))+ 1;
736                         if (sent > sizeof(buf) - count)
737                         {
738                                 sent = sizeof(buf) - count;
739                         }
740
741                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
742                                               count, sent, NULL);
743                         if (!NT_STATUS_IS_OK(status)) {
744                                 printf("write failed (%s)\n",
745                                        nt_errstr(status));
746                                 correct = False;
747                         }
748                 }
749                 else
750                 {
751                         status = cli_read(c, fnum, buf_rd+count, count,
752                                           sizeof(buf)-count, &sent);
753                         if(!NT_STATUS_IS_OK(status)) {
754                                 printf("read failed offset:%d size:%ld (%s)\n",
755                                        count, (unsigned long)sizeof(buf)-count,
756                                        nt_errstr(status));
757                                 correct = False;
758                                 sent = 0;
759                         } else if (sent > 0) {
760                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
761                                 {
762                                         printf("read/write compare failed\n");
763                                         printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
764                                         correct = False;
765                                         break;
766                                 }
767                         }
768                 }
769
770         }
771
772         status = cli_close(c, fnum);
773         if (!NT_STATUS_IS_OK(status)) {
774                 printf("close failed (%s)\n", nt_errstr(status));
775                 correct = False;
776         }
777
778         return correct;
779 }
780
781 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
782 {
783         const char *lockfname = "\\torture2.lck";
784         uint16_t fnum1;
785         uint16_t fnum2;
786         int i;
787         char buf[131072];
788         char buf_rd[131072];
789         bool correct = True;
790         size_t bytes_read;
791         NTSTATUS status;
792
793         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
794         if (!NT_STATUS_IS_OK(status)) {
795                 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
796         }
797
798         status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
799                           DENY_NONE, &fnum1);
800         if (!NT_STATUS_IS_OK(status)) {
801                 printf("first open read/write of %s failed (%s)\n",
802                                 lockfname, nt_errstr(status));
803                 return False;
804         }
805
806         status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
807         if (!NT_STATUS_IS_OK(status)) {
808                 printf("second open read-only of %s failed (%s)\n",
809                                 lockfname, nt_errstr(status));
810                 cli_close(c1, fnum1);
811                 return False;
812         }
813
814         for (i = 0; i < torture_numops; i++)
815         {
816                 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
817                 if (i % 10 == 0) {
818                         printf("%d\r", i); fflush(stdout);
819                 }
820
821                 generate_random_buffer((unsigned char *)buf, buf_size);
822
823                 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
824                                       buf_size, NULL);
825                 if (!NT_STATUS_IS_OK(status)) {
826                         printf("write failed (%s)\n", nt_errstr(status));
827                         correct = False;
828                         break;
829                 }
830
831                 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
832                 if(!NT_STATUS_IS_OK(status)) {
833                         printf("read failed (%s)\n", nt_errstr(status));
834                         correct = false;
835                         break;
836                 } else if (bytes_read != buf_size) {
837                         printf("read failed\n");
838                         printf("read %ld, expected %ld\n",
839                                (unsigned long)bytes_read,
840                                (unsigned long)buf_size); 
841                         correct = False;
842                         break;
843                 }
844
845                 if (memcmp(buf_rd, buf, buf_size) != 0)
846                 {
847                         printf("read/write compare failed\n");
848                         correct = False;
849                         break;
850                 }
851         }
852
853         status = cli_close(c2, fnum2);
854         if (!NT_STATUS_IS_OK(status)) {
855                 printf("close failed (%s)\n", nt_errstr(status));
856                 correct = False;
857         }
858
859         status = cli_close(c1, fnum1);
860         if (!NT_STATUS_IS_OK(status)) {
861                 printf("close failed (%s)\n", nt_errstr(status));
862                 correct = False;
863         }
864
865         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
866         if (!NT_STATUS_IS_OK(status)) {
867                 printf("unlink failed (%s)\n", nt_errstr(status));
868                 correct = False;
869         }
870
871         return correct;
872 }
873
874 static bool run_readwritetest(int dummy)
875 {
876         struct cli_state *cli1, *cli2;
877         bool test1, test2 = False;
878
879         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
880                 return False;
881         }
882         smbXcli_conn_set_sockopt(cli1->conn, sockops);
883         smbXcli_conn_set_sockopt(cli2->conn, sockops);
884
885         printf("starting readwritetest\n");
886
887         test1 = rw_torture2(cli1, cli2);
888         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
889
890         if (test1) {
891                 test2 = rw_torture2(cli1, cli1);
892                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
893         }
894
895         if (!torture_close_connection(cli1)) {
896                 test1 = False;
897         }
898
899         if (!torture_close_connection(cli2)) {
900                 test2 = False;
901         }
902
903         return (test1 && test2);
904 }
905
906 static bool run_readwritemulti(int dummy)
907 {
908         struct cli_state *cli;
909         bool test;
910
911         cli = current_cli;
912
913         smbXcli_conn_set_sockopt(cli->conn, sockops);
914
915         printf("run_readwritemulti: fname %s\n", randomfname);
916         test = rw_torture3(cli, randomfname);
917
918         if (!torture_close_connection(cli)) {
919                 test = False;
920         }
921
922         return test;
923 }
924
925 static bool run_readwritelarge_internal(void)
926 {
927         static struct cli_state *cli1;
928         uint16_t fnum1;
929         const char *lockfname = "\\large.dat";
930         off_t fsize;
931         char buf[126*1024];
932         bool correct = True;
933         NTSTATUS status;
934
935         if (!torture_open_connection(&cli1, 0)) {
936                 return False;
937         }
938         smbXcli_conn_set_sockopt(cli1->conn, sockops);
939         memset(buf,'\0',sizeof(buf));
940
941         printf("starting readwritelarge_internal\n");
942
943         cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
944
945         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
946                           DENY_NONE, &fnum1);
947         if (!NT_STATUS_IS_OK(status)) {
948                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
949                 return False;
950         }
951
952         cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
953
954         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
955                                      NULL, NULL, NULL);
956         if (!NT_STATUS_IS_OK(status)) {
957                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
958                 correct = False;
959         }
960
961         if (fsize == sizeof(buf))
962                 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
963                        (unsigned long)fsize);
964         else {
965                 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
966                        (unsigned long)fsize);
967                 correct = False;
968         }
969
970         status = cli_close(cli1, fnum1);
971         if (!NT_STATUS_IS_OK(status)) {
972                 printf("close failed (%s)\n", nt_errstr(status));
973                 correct = False;
974         }
975
976         status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
977         if (!NT_STATUS_IS_OK(status)) {
978                 printf("unlink failed (%s)\n", nt_errstr(status));
979                 correct = False;
980         }
981
982         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
983                           DENY_NONE, &fnum1);
984         if (!NT_STATUS_IS_OK(status)) {
985                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
986                 return False;
987         }
988
989         cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
990
991         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
992                                      NULL, NULL, NULL);
993         if (!NT_STATUS_IS_OK(status)) {
994                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
995                 correct = False;
996         }
997
998         if (fsize == sizeof(buf))
999                 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1000                        (unsigned long)fsize);
1001         else {
1002                 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1003                        (unsigned long)fsize);
1004                 correct = False;
1005         }
1006
1007 #if 0
1008         /* ToDo - set allocation. JRA */
1009         if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1010                 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1011                 return False;
1012         }
1013         if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1014                                  NULL, NULL)) {
1015                 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1016                 correct = False;
1017         }
1018         if (fsize != 0)
1019                 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1020 #endif
1021
1022         status = cli_close(cli1, fnum1);
1023         if (!NT_STATUS_IS_OK(status)) {
1024                 printf("close failed (%s)\n", nt_errstr(status));
1025                 correct = False;
1026         }
1027
1028         if (!torture_close_connection(cli1)) {
1029                 correct = False;
1030         }
1031         return correct;
1032 }
1033
1034 static bool run_readwritelarge(int dummy)
1035 {
1036         return run_readwritelarge_internal();
1037 }
1038
1039 static bool run_readwritelarge_signtest(int dummy)
1040 {
1041         bool ret;
1042         signing_state = SMB_SIGNING_REQUIRED;
1043         ret = run_readwritelarge_internal();
1044         signing_state = SMB_SIGNING_DEFAULT;
1045         return ret;
1046 }
1047
1048 int line_count = 0;
1049 int nbio_id;
1050
1051 #define ival(s) strtol(s, NULL, 0)
1052
1053 /* run a test that simulates an approximate netbench client load */
1054 static bool run_netbench(int client)
1055 {
1056         struct cli_state *cli;
1057         int i;
1058         char line[1024];
1059         char cname[20];
1060         FILE *f;
1061         const char *params[20];
1062         bool correct = True;
1063
1064         cli = current_cli;
1065
1066         nbio_id = client;
1067
1068         smbXcli_conn_set_sockopt(cli->conn, sockops);
1069
1070         nb_setup(cli);
1071
1072         slprintf(cname,sizeof(cname)-1, "client%d", client);
1073
1074         f = fopen(client_txt, "r");
1075
1076         if (!f) {
1077                 perror(client_txt);
1078                 return False;
1079         }
1080
1081         while (fgets(line, sizeof(line)-1, f)) {
1082                 char *saveptr;
1083                 line_count++;
1084
1085                 line[strlen(line)-1] = 0;
1086
1087                 /* printf("[%d] %s\n", line_count, line); */
1088
1089                 all_string_sub(line,"client1", cname, sizeof(line));
1090
1091                 /* parse the command parameters */
1092                 params[0] = strtok_r(line, " ", &saveptr);
1093                 i = 0;
1094                 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1095
1096                 params[i] = "";
1097
1098                 if (i < 2) continue;
1099
1100                 if (!strncmp(params[0],"SMB", 3)) {
1101                         printf("ERROR: You are using a dbench 1 load file\n");
1102                         exit(1);
1103                 }
1104
1105                 if (!strcmp(params[0],"NTCreateX")) {
1106                         nb_createx(params[1], ival(params[2]), ival(params[3]), 
1107                                    ival(params[4]));
1108                 } else if (!strcmp(params[0],"Close")) {
1109                         nb_close(ival(params[1]));
1110                 } else if (!strcmp(params[0],"Rename")) {
1111                         nb_rename(params[1], params[2]);
1112                 } else if (!strcmp(params[0],"Unlink")) {
1113                         nb_unlink(params[1]);
1114                 } else if (!strcmp(params[0],"Deltree")) {
1115                         nb_deltree(params[1]);
1116                 } else if (!strcmp(params[0],"Rmdir")) {
1117                         nb_rmdir(params[1]);
1118                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1119                         nb_qpathinfo(params[1]);
1120                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1121                         nb_qfileinfo(ival(params[1]));
1122                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1123                         nb_qfsinfo(ival(params[1]));
1124                 } else if (!strcmp(params[0],"FIND_FIRST")) {
1125                         nb_findfirst(params[1]);
1126                 } else if (!strcmp(params[0],"WriteX")) {
1127                         nb_writex(ival(params[1]), 
1128                                   ival(params[2]), ival(params[3]), ival(params[4]));
1129                 } else if (!strcmp(params[0],"ReadX")) {
1130                         nb_readx(ival(params[1]), 
1131                                   ival(params[2]), ival(params[3]), ival(params[4]));
1132                 } else if (!strcmp(params[0],"Flush")) {
1133                         nb_flush(ival(params[1]));
1134                 } else {
1135                         printf("Unknown operation %s\n", params[0]);
1136                         exit(1);
1137                 }
1138         }
1139         fclose(f);
1140
1141         nb_cleanup();
1142
1143         if (!torture_close_connection(cli)) {
1144                 correct = False;
1145         }
1146
1147         return correct;
1148 }
1149
1150
1151 /* run a test that simulates an approximate netbench client load */
1152 static bool run_nbench(int dummy)
1153 {
1154         double t;
1155         bool correct = True;
1156
1157         nbio_shmem(torture_nprocs);
1158
1159         nbio_id = -1;
1160
1161         signal(SIGALRM, nb_alarm);
1162         alarm(1);
1163         t = create_procs(run_netbench, &correct);
1164         alarm(0);
1165
1166         printf("\nThroughput %g MB/sec\n", 
1167                1.0e-6 * nbio_total() / t);
1168         return correct;
1169 }
1170
1171
1172 /*
1173   This test checks for two things:
1174
1175   1) correct support for retaining locks over a close (ie. the server
1176      must not use posix semantics)
1177   2) support for lock timeouts
1178  */
1179 static bool run_locktest1(int dummy)
1180 {
1181         struct cli_state *cli1, *cli2;
1182         const char *fname = "\\lockt1.lck";
1183         uint16_t fnum1, fnum2, fnum3;
1184         time_t t1, t2;
1185         unsigned lock_timeout;
1186         NTSTATUS status;
1187
1188         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1189                 return False;
1190         }
1191         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1192         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1193
1194         printf("starting locktest1\n");
1195
1196         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1197
1198         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1199                           &fnum1);
1200         if (!NT_STATUS_IS_OK(status)) {
1201                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1202                 return False;
1203         }
1204
1205         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1206         if (!NT_STATUS_IS_OK(status)) {
1207                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1208                 return False;
1209         }
1210
1211         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1212         if (!NT_STATUS_IS_OK(status)) {
1213                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1214                 return False;
1215         }
1216
1217         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1218         if (!NT_STATUS_IS_OK(status)) {
1219                 printf("lock1 failed (%s)\n", nt_errstr(status));
1220                 return false;
1221         }
1222
1223         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1224         if (NT_STATUS_IS_OK(status)) {
1225                 printf("lock2 succeeded! This is a locking bug\n");
1226                 return false;
1227         } else {
1228                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1229                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1230                         return false;
1231                 }
1232         }
1233
1234         lock_timeout = (1 + (random() % 20));
1235         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1236         t1 = time(NULL);
1237         status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1238         if (NT_STATUS_IS_OK(status)) {
1239                 printf("lock3 succeeded! This is a locking bug\n");
1240                 return false;
1241         } else {
1242                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1243                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1244                         return false;
1245                 }
1246         }
1247         t2 = time(NULL);
1248
1249         if (ABS(t2 - t1) < lock_timeout-1) {
1250                 printf("error: This server appears not to support timed lock requests\n");
1251         }
1252
1253         printf("server slept for %u seconds for a %u second timeout\n",
1254                (unsigned int)(t2-t1), lock_timeout);
1255
1256         status = cli_close(cli1, fnum2);
1257         if (!NT_STATUS_IS_OK(status)) {
1258                 printf("close1 failed (%s)\n", nt_errstr(status));
1259                 return False;
1260         }
1261
1262         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1263         if (NT_STATUS_IS_OK(status)) {
1264                 printf("lock4 succeeded! This is a locking bug\n");
1265                 return false;
1266         } else {
1267                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1268                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1269                         return false;
1270                 }
1271         }
1272
1273         status = cli_close(cli1, fnum1);
1274         if (!NT_STATUS_IS_OK(status)) {
1275                 printf("close2 failed (%s)\n", nt_errstr(status));
1276                 return False;
1277         }
1278
1279         status = cli_close(cli2, fnum3);
1280         if (!NT_STATUS_IS_OK(status)) {
1281                 printf("close3 failed (%s)\n", nt_errstr(status));
1282                 return False;
1283         }
1284
1285         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1286         if (!NT_STATUS_IS_OK(status)) {
1287                 printf("unlink failed (%s)\n", nt_errstr(status));
1288                 return False;
1289         }
1290
1291
1292         if (!torture_close_connection(cli1)) {
1293                 return False;
1294         }
1295
1296         if (!torture_close_connection(cli2)) {
1297                 return False;
1298         }
1299
1300         printf("Passed locktest1\n");
1301         return True;
1302 }
1303
1304 /*
1305   this checks to see if a secondary tconx can use open files from an
1306   earlier tconx
1307  */
1308 static bool run_tcon_test(int dummy)
1309 {
1310         static struct cli_state *cli;
1311         const char *fname = "\\tcontest.tmp";
1312         uint16_t fnum1;
1313         uint32_t cnum1, cnum2, cnum3;
1314         struct smbXcli_tcon *orig_tcon = NULL;
1315         uint16_t vuid1, vuid2;
1316         char buf[4];
1317         bool ret = True;
1318         NTSTATUS status;
1319
1320         memset(buf, '\0', sizeof(buf));
1321
1322         if (!torture_open_connection(&cli, 0)) {
1323                 return False;
1324         }
1325         smbXcli_conn_set_sockopt(cli->conn, sockops);
1326
1327         printf("starting tcontest\n");
1328
1329         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1330
1331         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1332         if (!NT_STATUS_IS_OK(status)) {
1333                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1334                 return False;
1335         }
1336
1337         cnum1 = cli_state_get_tid(cli);
1338         vuid1 = cli_state_get_uid(cli);
1339
1340         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1341         if (!NT_STATUS_IS_OK(status)) {
1342                 printf("initial write failed (%s)", nt_errstr(status));
1343                 return False;
1344         }
1345
1346         orig_tcon = cli_state_save_tcon(cli);
1347         if (orig_tcon == NULL) {
1348                 return false;
1349         }
1350
1351         status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1352         if (!NT_STATUS_IS_OK(status)) {
1353                 printf("%s refused 2nd tree connect (%s)\n", host,
1354                        nt_errstr(status));
1355                 cli_shutdown(cli);
1356                 return False;
1357         }
1358
1359         cnum2 = cli_state_get_tid(cli);
1360         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1361         vuid2 = cli_state_get_uid(cli) + 1;
1362
1363         /* try a write with the wrong tid */
1364         cli_state_set_tid(cli, cnum2);
1365
1366         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1367         if (NT_STATUS_IS_OK(status)) {
1368                 printf("* server allows write with wrong TID\n");
1369                 ret = False;
1370         } else {
1371                 printf("server fails write with wrong TID : %s\n",
1372                        nt_errstr(status));
1373         }
1374
1375
1376         /* try a write with an invalid tid */
1377         cli_state_set_tid(cli, cnum3);
1378
1379         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1380         if (NT_STATUS_IS_OK(status)) {
1381                 printf("* server allows write with invalid TID\n");
1382                 ret = False;
1383         } else {
1384                 printf("server fails write with invalid TID : %s\n",
1385                        nt_errstr(status));
1386         }
1387
1388         /* try a write with an invalid vuid */
1389         cli_state_set_uid(cli, vuid2);
1390         cli_state_set_tid(cli, cnum1);
1391
1392         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1393         if (NT_STATUS_IS_OK(status)) {
1394                 printf("* server allows write with invalid VUID\n");
1395                 ret = False;
1396         } else {
1397                 printf("server fails write with invalid VUID : %s\n",
1398                        nt_errstr(status));
1399         }
1400
1401         cli_state_set_tid(cli, cnum1);
1402         cli_state_set_uid(cli, vuid1);
1403
1404         status = cli_close(cli, fnum1);
1405         if (!NT_STATUS_IS_OK(status)) {
1406                 printf("close failed (%s)\n", nt_errstr(status));
1407                 return False;
1408         }
1409
1410         cli_state_set_tid(cli, cnum2);
1411
1412         status = cli_tdis(cli);
1413         if (!NT_STATUS_IS_OK(status)) {
1414                 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1415                 return False;
1416         }
1417
1418         cli_state_restore_tcon(cli, orig_tcon);
1419
1420         cli_state_set_tid(cli, cnum1);
1421
1422         if (!torture_close_connection(cli)) {
1423                 return False;
1424         }
1425
1426         return ret;
1427 }
1428
1429
1430 /*
1431  checks for old style tcon support
1432  */
1433 static bool run_tcon2_test(int dummy)
1434 {
1435         static struct cli_state *cli;
1436         uint16_t cnum, max_xmit;
1437         char *service;
1438         NTSTATUS status;
1439
1440         if (!torture_open_connection(&cli, 0)) {
1441                 return False;
1442         }
1443         smbXcli_conn_set_sockopt(cli->conn, sockops);
1444
1445         printf("starting tcon2 test\n");
1446
1447         if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1448                 return false;
1449         }
1450
1451         status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1452
1453         SAFE_FREE(service);
1454
1455         if (!NT_STATUS_IS_OK(status)) {
1456                 printf("tcon2 failed : %s\n", nt_errstr(status));
1457         } else {
1458                 printf("tcon OK : max_xmit=%d cnum=%d\n",
1459                        (int)max_xmit, (int)cnum);
1460         }
1461
1462         if (!torture_close_connection(cli)) {
1463                 return False;
1464         }
1465
1466         printf("Passed tcon2 test\n");
1467         return True;
1468 }
1469
1470 static bool tcon_devtest(struct cli_state *cli,
1471                          const char *myshare, const char *devtype,
1472                          const char *return_devtype,
1473                          NTSTATUS expected_error)
1474 {
1475         NTSTATUS status;
1476         bool ret;
1477
1478         status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1479
1480         if (NT_STATUS_IS_OK(expected_error)) {
1481                 if (NT_STATUS_IS_OK(status)) {
1482                         if (strcmp(cli->dev, return_devtype) == 0) {
1483                                 ret = True;
1484                         } else { 
1485                                 printf("tconX to share %s with type %s "
1486                                        "succeeded but returned the wrong "
1487                                        "device type (got [%s] but should have got [%s])\n",
1488                                        myshare, devtype, cli->dev, return_devtype);
1489                                 ret = False;
1490                         }
1491                 } else {
1492                         printf("tconX to share %s with type %s "
1493                                "should have succeeded but failed\n",
1494                                myshare, devtype);
1495                         ret = False;
1496                 }
1497                 cli_tdis(cli);
1498         } else {
1499                 if (NT_STATUS_IS_OK(status)) {
1500                         printf("tconx to share %s with type %s "
1501                                "should have failed but succeeded\n",
1502                                myshare, devtype);
1503                         ret = False;
1504                 } else {
1505                         if (NT_STATUS_EQUAL(status, expected_error)) {
1506                                 ret = True;
1507                         } else {
1508                                 printf("Returned unexpected error\n");
1509                                 ret = False;
1510                         }
1511                 }
1512         }
1513         return ret;
1514 }
1515
1516 /*
1517  checks for correct tconX support
1518  */
1519 static bool run_tcon_devtype_test(int dummy)
1520 {
1521         static struct cli_state *cli1 = NULL;
1522         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1523         NTSTATUS status;
1524         bool ret = True;
1525
1526         status = cli_full_connection_creds(&cli1,
1527                                            myname,
1528                                            host,
1529                                            NULL, /* dest_ss */
1530                                            port_to_use,
1531                                            NULL, /* service */
1532                                            NULL, /* service_type */
1533                                            torture_creds,
1534                                            flags,
1535                                            signing_state);
1536
1537         if (!NT_STATUS_IS_OK(status)) {
1538                 printf("could not open connection\n");
1539                 return False;
1540         }
1541
1542         if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1543                 ret = False;
1544
1545         if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1546                 ret = False;
1547
1548         if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1549                 ret = False;
1550
1551         if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1552                 ret = False;
1553
1554         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1555                 ret = False;
1556
1557         if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1558                 ret = False;
1559
1560         if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1561                 ret = False;
1562
1563         if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1564                 ret = False;
1565
1566         if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1567                 ret = False;
1568
1569         if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1570                 ret = False;
1571
1572         cli_shutdown(cli1);
1573
1574         if (ret)
1575                 printf("Passed tcondevtest\n");
1576
1577         return ret;
1578 }
1579
1580
1581 /*
1582   This test checks that 
1583
1584   1) the server supports multiple locking contexts on the one SMB
1585   connection, distinguished by PID.  
1586
1587   2) the server correctly fails overlapping locks made by the same PID (this
1588      goes against POSIX behaviour, which is why it is tricky to implement)
1589
1590   3) the server denies unlock requests by an incorrect client PID
1591 */
1592 static bool run_locktest2(int dummy)
1593 {
1594         static struct cli_state *cli;
1595         const char *fname = "\\lockt2.lck";
1596         uint16_t fnum1, fnum2, fnum3;
1597         bool correct = True;
1598         NTSTATUS status;
1599
1600         if (!torture_open_connection(&cli, 0)) {
1601                 return False;
1602         }
1603
1604         smbXcli_conn_set_sockopt(cli->conn, sockops);
1605
1606         printf("starting locktest2\n");
1607
1608         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1609
1610         cli_setpid(cli, 1);
1611
1612         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1613         if (!NT_STATUS_IS_OK(status)) {
1614                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1615                 return False;
1616         }
1617
1618         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1619         if (!NT_STATUS_IS_OK(status)) {
1620                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1621                 return False;
1622         }
1623
1624         cli_setpid(cli, 2);
1625
1626         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1627         if (!NT_STATUS_IS_OK(status)) {
1628                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1629                 return False;
1630         }
1631
1632         cli_setpid(cli, 1);
1633
1634         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1635         if (!NT_STATUS_IS_OK(status)) {
1636                 printf("lock1 failed (%s)\n", nt_errstr(status));
1637                 return false;
1638         }
1639
1640         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1641         if (NT_STATUS_IS_OK(status)) {
1642                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1643                 correct = false;
1644         } else {
1645                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1646                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1647                         return false;
1648                 }
1649         }
1650
1651         status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1652         if (NT_STATUS_IS_OK(status)) {
1653                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1654                 correct = false;
1655         } else {
1656                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1657                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1658                         return false;
1659                 }
1660         }
1661
1662         status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1663         if (NT_STATUS_IS_OK(status)) {
1664                 printf("READ lock2 succeeded! This is a locking bug\n");
1665                 correct = false;
1666         } else {
1667                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1668                                  NT_STATUS_FILE_LOCK_CONFLICT)) {
1669                         return false;
1670                 }
1671         }
1672
1673         status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1674         if (!NT_STATUS_IS_OK(status)) {
1675                 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1676         }
1677         cli_setpid(cli, 2);
1678         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1679                 printf("unlock at 100 succeeded! This is a locking bug\n");
1680                 correct = False;
1681         }
1682
1683         status = cli_unlock(cli, fnum1, 0, 4);
1684         if (NT_STATUS_IS_OK(status)) {
1685                 printf("unlock1 succeeded! This is a locking bug\n");
1686                 correct = false;
1687         } else {
1688                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1689                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1690                         return false;
1691                 }
1692         }
1693
1694         status = cli_unlock(cli, fnum1, 0, 8);
1695         if (NT_STATUS_IS_OK(status)) {
1696                 printf("unlock2 succeeded! This is a locking bug\n");
1697                 correct = false;
1698         } else {
1699                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1700                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1701                         return false;
1702                 }
1703         }
1704
1705         status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1706         if (NT_STATUS_IS_OK(status)) {
1707                 printf("lock3 succeeded! This is a locking bug\n");
1708                 correct = false;
1709         } else {
1710                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1711                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1712                         return false;
1713                 }
1714         }
1715
1716         cli_setpid(cli, 1);
1717
1718         status = cli_close(cli, fnum1);
1719         if (!NT_STATUS_IS_OK(status)) {
1720                 printf("close1 failed (%s)\n", nt_errstr(status));
1721                 return False;
1722         }
1723
1724         status = cli_close(cli, fnum2);
1725         if (!NT_STATUS_IS_OK(status)) {
1726                 printf("close2 failed (%s)\n", nt_errstr(status));
1727                 return False;
1728         }
1729
1730         status = cli_close(cli, fnum3);
1731         if (!NT_STATUS_IS_OK(status)) {
1732                 printf("close3 failed (%s)\n", nt_errstr(status));
1733                 return False;
1734         }
1735
1736         if (!torture_close_connection(cli)) {
1737                 correct = False;
1738         }
1739
1740         printf("locktest2 finished\n");
1741
1742         return correct;
1743 }
1744
1745
1746 /*
1747   This test checks that 
1748
1749   1) the server supports the full offset range in lock requests
1750 */
1751 static bool run_locktest3(int dummy)
1752 {
1753         static struct cli_state *cli1, *cli2;
1754         const char *fname = "\\lockt3.lck";
1755         uint16_t fnum1, fnum2;
1756         int i;
1757         uint32_t offset;
1758         bool correct = True;
1759         NTSTATUS status;
1760
1761 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1762
1763         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1764                 return False;
1765         }
1766         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1767         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1768
1769         printf("starting locktest3\n");
1770
1771         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1772
1773         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1774                          &fnum1);
1775         if (!NT_STATUS_IS_OK(status)) {
1776                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1777                 return False;
1778         }
1779
1780         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1781         if (!NT_STATUS_IS_OK(status)) {
1782                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1783                 return False;
1784         }
1785
1786         for (offset=i=0;i<torture_numops;i++) {
1787                 NEXT_OFFSET;
1788
1789                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1790                 if (!NT_STATUS_IS_OK(status)) {
1791                         printf("lock1 %d failed (%s)\n", 
1792                                i,
1793                                nt_errstr(status));
1794                         return False;
1795                 }
1796
1797                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1798                 if (!NT_STATUS_IS_OK(status)) {
1799                         printf("lock2 %d failed (%s)\n", 
1800                                i,
1801                                nt_errstr(status));
1802                         return False;
1803                 }
1804         }
1805
1806         for (offset=i=0;i<torture_numops;i++) {
1807                 NEXT_OFFSET;
1808
1809                 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1810                 if (NT_STATUS_IS_OK(status)) {
1811                         printf("error: lock1 %d succeeded!\n", i);
1812                         return False;
1813                 }
1814
1815                 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1816                 if (NT_STATUS_IS_OK(status)) {
1817                         printf("error: lock2 %d succeeded!\n", i);
1818                         return False;
1819                 }
1820
1821                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1822                 if (NT_STATUS_IS_OK(status)) {
1823                         printf("error: lock3 %d succeeded!\n", i);
1824                         return False;
1825                 }
1826
1827                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1828                 if (NT_STATUS_IS_OK(status)) {
1829                         printf("error: lock4 %d succeeded!\n", i);
1830                         return False;
1831                 }
1832         }
1833
1834         for (offset=i=0;i<torture_numops;i++) {
1835                 NEXT_OFFSET;
1836
1837                 status = cli_unlock(cli1, fnum1, offset-1, 1);
1838                 if (!NT_STATUS_IS_OK(status)) {
1839                         printf("unlock1 %d failed (%s)\n", 
1840                                i,
1841                                nt_errstr(status));
1842                         return False;
1843                 }
1844
1845                 status = cli_unlock(cli2, fnum2, offset-2, 1);
1846                 if (!NT_STATUS_IS_OK(status)) {
1847                         printf("unlock2 %d failed (%s)\n", 
1848                                i,
1849                                nt_errstr(status));
1850                         return False;
1851                 }
1852         }
1853
1854         status = cli_close(cli1, fnum1);
1855         if (!NT_STATUS_IS_OK(status)) {
1856                 printf("close1 failed (%s)\n", nt_errstr(status));
1857                 return False;
1858         }
1859
1860         status = cli_close(cli2, fnum2);
1861         if (!NT_STATUS_IS_OK(status)) {
1862                 printf("close2 failed (%s)\n", nt_errstr(status));
1863                 return False;
1864         }
1865
1866         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1867         if (!NT_STATUS_IS_OK(status)) {
1868                 printf("unlink failed (%s)\n", nt_errstr(status));
1869                 return False;
1870         }
1871
1872         if (!torture_close_connection(cli1)) {
1873                 correct = False;
1874         }
1875
1876         if (!torture_close_connection(cli2)) {
1877                 correct = False;
1878         }
1879
1880         printf("finished locktest3\n");
1881
1882         return correct;
1883 }
1884
1885 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1886                            char *buf, off_t offset, size_t size,
1887                            size_t *nread, size_t expect)
1888 {
1889         NTSTATUS status;
1890         size_t l_nread;
1891
1892         status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1893
1894         if(!NT_STATUS_IS_OK(status)) {
1895                 return false;
1896         } else if (l_nread != expect) {
1897                 return false;
1898         }
1899
1900         if (nread) {
1901                 *nread = l_nread;
1902         }
1903
1904         return true;
1905 }
1906
1907 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1908         printf("** "); correct = False; \
1909         }
1910
1911 /*
1912   looks at overlapping locks
1913 */
1914 static bool run_locktest4(int dummy)
1915 {
1916         static struct cli_state *cli1, *cli2;
1917         const char *fname = "\\lockt4.lck";
1918         uint16_t fnum1, fnum2, f;
1919         bool ret;
1920         char buf[1000];
1921         bool correct = True;
1922         NTSTATUS status;
1923
1924         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1925                 return False;
1926         }
1927
1928         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1929         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1930
1931         printf("starting locktest4\n");
1932
1933         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1934
1935         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1936         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1937
1938         memset(buf, 0, sizeof(buf));
1939
1940         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1941                               NULL);
1942         if (!NT_STATUS_IS_OK(status)) {
1943                 printf("Failed to create file: %s\n", nt_errstr(status));
1944                 correct = False;
1945                 goto fail;
1946         }
1947
1948         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1949               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1950         EXPECTED(ret, False);
1951         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1952
1953         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1954               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1955         EXPECTED(ret, True);
1956         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1957
1958         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1959               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1960         EXPECTED(ret, False);
1961         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1962
1963         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1964               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1965         EXPECTED(ret, True);
1966         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1967
1968         ret = (cli_setpid(cli1, 1),
1969               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1970               (cli_setpid(cli1, 2),
1971               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1972         EXPECTED(ret, False);
1973         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1974
1975         ret = (cli_setpid(cli1, 1),
1976               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1977               (cli_setpid(cli1, 2),
1978               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1979         EXPECTED(ret, True);
1980         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1981
1982         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1983               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1984         EXPECTED(ret, True);
1985         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1986
1987         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1988               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1989         EXPECTED(ret, False);
1990         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1991
1992         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1993               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1994         EXPECTED(ret, False);
1995         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1996
1997         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1998               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
1999         EXPECTED(ret, True);
2000         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2001
2002         ret = (cli_setpid(cli1, 1),
2003              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2004              (cli_setpid(cli1, 2),
2005              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2006         EXPECTED(ret, False);
2007         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2008
2009         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2010               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2011               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2012         EXPECTED(ret, False);
2013         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2014
2015
2016         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2017               test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2018         EXPECTED(ret, False);
2019         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2020
2021         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2022         ret = NT_STATUS_IS_OK(status);
2023         if (ret) {
2024                 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2025                                       NULL);
2026                 ret = NT_STATUS_IS_OK(status);
2027         }
2028         EXPECTED(ret, False);
2029         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2030
2031
2032         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2033               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2034               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2035               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2036         EXPECTED(ret, True);
2037         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2038
2039
2040         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2041               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2042               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2043               test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2044               !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2045                                              150, 4, NULL))) &&
2046               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2047         EXPECTED(ret, True);
2048         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2049
2050         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2051               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2052               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2053                                            160, 4, NULL)) &&
2054               test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2055         EXPECTED(ret, True);
2056         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2057
2058         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2059               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2060               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2061                                            170, 4, NULL)) &&
2062               test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2063         EXPECTED(ret, True);
2064         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2065
2066         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2067               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2068               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2069               !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2070                                             190, 4, NULL)) &&
2071               test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2072         EXPECTED(ret, True);
2073         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2074
2075         cli_close(cli1, fnum1);
2076         cli_close(cli2, fnum2);
2077         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2078         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2079         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2080               NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2081               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2082               NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2083               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2084         cli_close(cli1, f);
2085         cli_close(cli1, fnum1);
2086         EXPECTED(ret, True);
2087         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2088
2089  fail:
2090         cli_close(cli1, fnum1);
2091         cli_close(cli2, fnum2);
2092         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2093         torture_close_connection(cli1);
2094         torture_close_connection(cli2);
2095
2096         printf("finished locktest4\n");
2097         return correct;
2098 }
2099
2100 /*
2101   looks at lock upgrade/downgrade.
2102 */
2103 static bool run_locktest5(int dummy)
2104 {
2105         static struct cli_state *cli1, *cli2;
2106         const char *fname = "\\lockt5.lck";
2107         uint16_t fnum1, fnum2, fnum3;
2108         bool ret;
2109         char buf[1000];
2110         bool correct = True;
2111         NTSTATUS status;
2112
2113         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2114                 return False;
2115         }
2116
2117         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2118         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2119
2120         printf("starting locktest5\n");
2121
2122         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2123
2124         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2125         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2126         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2127
2128         memset(buf, 0, sizeof(buf));
2129
2130         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2131                               NULL);
2132         if (!NT_STATUS_IS_OK(status)) {
2133                 printf("Failed to create file: %s\n", nt_errstr(status));
2134                 correct = False;
2135                 goto fail;
2136         }
2137
2138         /* Check for NT bug... */
2139         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2140               NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2141         cli_close(cli1, fnum1);
2142         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2143         status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2144         ret = NT_STATUS_IS_OK(status);
2145         EXPECTED(ret, True);
2146         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2147         cli_close(cli1, fnum1);
2148         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2149         cli_unlock(cli1, fnum3, 0, 1);
2150
2151         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2152               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2153         EXPECTED(ret, True);
2154         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2155
2156         status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2157         ret = NT_STATUS_IS_OK(status);
2158         EXPECTED(ret, False);
2159
2160         printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2161
2162         /* Unlock the process 2 lock. */
2163         cli_unlock(cli2, fnum2, 0, 4);
2164
2165         status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2166         ret = NT_STATUS_IS_OK(status);
2167         EXPECTED(ret, False);
2168
2169         printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2170
2171         /* Unlock the process 1 fnum3 lock. */
2172         cli_unlock(cli1, fnum3, 0, 4);
2173
2174         /* Stack 2 more locks here. */
2175         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2176               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2177
2178         EXPECTED(ret, True);
2179         printf("the same process %s stack read locks\n", ret?"can":"cannot");
2180
2181         /* Unlock the first process lock, then check this was the WRITE lock that was
2182                 removed. */
2183
2184         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2185               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2186
2187         EXPECTED(ret, True);
2188         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2189
2190         /* Unlock the process 2 lock. */
2191         cli_unlock(cli2, fnum2, 0, 4);
2192
2193         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2194
2195         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2196                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2197                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2198
2199         EXPECTED(ret, True);
2200         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
2201
2202         /* Ensure the next unlock fails. */
2203         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2204         EXPECTED(ret, False);
2205         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
2206
2207         /* Ensure connection 2 can get a write lock. */
2208         status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2209         ret = NT_STATUS_IS_OK(status);
2210         EXPECTED(ret, True);
2211
2212         printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2213
2214
2215  fail:
2216         cli_close(cli1, fnum1);
2217         cli_close(cli2, fnum2);
2218         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2219         if (!torture_close_connection(cli1)) {
2220                 correct = False;
2221         }
2222         if (!torture_close_connection(cli2)) {
2223                 correct = False;
2224         }
2225
2226         printf("finished locktest5\n");
2227
2228         return correct;
2229 }
2230
2231 /*
2232   tries the unusual lockingX locktype bits
2233 */
2234 static bool run_locktest6(int dummy)
2235 {
2236         static struct cli_state *cli;
2237         const char *fname[1] = { "\\lock6.txt" };
2238         int i;
2239         uint16_t fnum;
2240         NTSTATUS status;
2241
2242         if (!torture_open_connection(&cli, 0)) {
2243                 return False;
2244         }
2245
2246         smbXcli_conn_set_sockopt(cli->conn, sockops);
2247
2248         printf("starting locktest6\n");
2249
2250         for (i=0;i<1;i++) {
2251                 printf("Testing %s\n", fname[i]);
2252
2253                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2254
2255                 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2256                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2257                 cli_close(cli, fnum);
2258                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2259
2260                 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2261                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2262                 cli_close(cli, fnum);
2263                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2264
2265                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2266         }
2267
2268         torture_close_connection(cli);
2269
2270         printf("finished locktest6\n");
2271         return True;
2272 }
2273
2274 static bool run_locktest7(int dummy)
2275 {
2276         struct cli_state *cli1;
2277         const char *fname = "\\lockt7.lck";
2278         uint16_t fnum1;
2279         char buf[200];
2280         bool correct = False;
2281         size_t nread;
2282         NTSTATUS status;
2283
2284         if (!torture_open_connection(&cli1, 0)) {
2285                 return False;
2286         }
2287
2288         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2289
2290         printf("starting locktest7\n");
2291
2292         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2293
2294         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2295
2296         memset(buf, 0, sizeof(buf));
2297
2298         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2299                               NULL);
2300         if (!NT_STATUS_IS_OK(status)) {
2301                 printf("Failed to create file: %s\n", nt_errstr(status));
2302                 goto fail;
2303         }
2304
2305         cli_setpid(cli1, 1);
2306
2307         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2308         if (!NT_STATUS_IS_OK(status)) {
2309                 printf("Unable to apply read lock on range 130:4, "
2310                        "error was %s\n", nt_errstr(status));
2311                 goto fail;
2312         } else {
2313                 printf("pid1 successfully locked range 130:4 for READ\n");
2314         }
2315
2316         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2317         if (!NT_STATUS_IS_OK(status)) {
2318                 printf("pid1 unable to read the range 130:4, error was %s\n",
2319                       nt_errstr(status));
2320                 goto fail;
2321         } else if (nread != 4) {
2322                 printf("pid1 unable to read the range 130:4, "
2323                        "recv %ld req %d\n", (unsigned long)nread, 4);
2324                 goto fail;
2325         } else {
2326                 printf("pid1 successfully read the range 130:4\n");
2327         }
2328
2329         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2330         if (!NT_STATUS_IS_OK(status)) {
2331                 printf("pid1 unable to write to the range 130:4, error was "
2332                        "%s\n", nt_errstr(status));
2333                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2334                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2335                         goto fail;
2336                 }
2337         } else {
2338                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2339                 goto fail;
2340         }
2341
2342         cli_setpid(cli1, 2);
2343
2344         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2345         if (!NT_STATUS_IS_OK(status)) {
2346                 printf("pid2 unable to read the range 130:4, error was %s\n",
2347                       nt_errstr(status));
2348                 goto fail;
2349         } else if (nread != 4) {
2350                 printf("pid2 unable to read the range 130:4, "
2351                        "recv %ld req %d\n", (unsigned long)nread, 4);
2352                 goto fail;
2353         } else {
2354                 printf("pid2 successfully read the range 130:4\n");
2355         }
2356
2357         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2358         if (!NT_STATUS_IS_OK(status)) {
2359                 printf("pid2 unable to write to the range 130:4, error was "
2360                        "%s\n", nt_errstr(status));
2361                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2362                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2363                         goto fail;
2364                 }
2365         } else {
2366                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2367                 goto fail;
2368         }
2369
2370         cli_setpid(cli1, 1);
2371         cli_unlock(cli1, fnum1, 130, 4);
2372
2373         status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2374         if (!NT_STATUS_IS_OK(status)) {
2375                 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2376                 goto fail;
2377         } else {
2378                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2379         }
2380
2381         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2382         if (!NT_STATUS_IS_OK(status)) {
2383                 printf("pid1 unable to read the range 130:4, error was %s\n",
2384                       nt_errstr(status));
2385                 goto fail;
2386         } else if (nread != 4) {
2387                 printf("pid1 unable to read the range 130:4, "
2388                        "recv %ld req %d\n", (unsigned long)nread, 4);
2389                 goto fail;
2390         } else {
2391                 printf("pid1 successfully read the range 130:4\n");
2392         }
2393
2394         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2395         if (!NT_STATUS_IS_OK(status)) {
2396                 printf("pid1 unable to write to the range 130:4, error was "
2397                        "%s\n", nt_errstr(status));
2398                 goto fail;
2399         } else {
2400                 printf("pid1 successfully wrote to the range 130:4\n");
2401         }
2402
2403         cli_setpid(cli1, 2);
2404
2405         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2406         if (!NT_STATUS_IS_OK(status)) {
2407                 printf("pid2 unable to read the range 130:4, error was "
2408                        "%s\n", nt_errstr(status));
2409                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2410                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2411                         goto fail;
2412                 }
2413         } else {
2414                 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2415                        (unsigned long)nread);
2416                 goto fail;
2417         }
2418
2419         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2420         if (!NT_STATUS_IS_OK(status)) {
2421                 printf("pid2 unable to write to the range 130:4, error was "
2422                        "%s\n", nt_errstr(status));
2423                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2424                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2425                         goto fail;
2426                 }
2427         } else {
2428                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2429                 goto fail;
2430         }
2431
2432         cli_unlock(cli1, fnum1, 130, 0);
2433         correct = True;
2434
2435 fail:
2436         cli_close(cli1, fnum1);
2437         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2438         torture_close_connection(cli1);
2439
2440         printf("finished locktest7\n");
2441         return correct;
2442 }
2443
2444 /*
2445  * This demonstrates a problem with our use of GPFS share modes: A file
2446  * descriptor sitting in the pending close queue holding a GPFS share mode
2447  * blocks opening a file another time. Happens with Word 2007 temp files.
2448  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2449  * open is denied with NT_STATUS_SHARING_VIOLATION.
2450  */
2451
2452 static bool run_locktest8(int dummy)
2453 {
2454         struct cli_state *cli1;
2455         const char *fname = "\\lockt8.lck";
2456         uint16_t fnum1, fnum2;
2457         char buf[200];
2458         bool correct = False;
2459         NTSTATUS status;
2460
2461         if (!torture_open_connection(&cli1, 0)) {
2462                 return False;
2463         }
2464
2465         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2466
2467         printf("starting locktest8\n");
2468
2469         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2470
2471         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2472                           &fnum1);
2473         if (!NT_STATUS_IS_OK(status)) {
2474                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2475                 return false;
2476         }
2477
2478         memset(buf, 0, sizeof(buf));
2479
2480         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2481         if (!NT_STATUS_IS_OK(status)) {
2482                 d_fprintf(stderr, "cli_openx second time returned %s\n",
2483                           nt_errstr(status));
2484                 goto fail;
2485         }
2486
2487         status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2488         if (!NT_STATUS_IS_OK(status)) {
2489                 printf("Unable to apply read lock on range 1:1, error was "
2490                        "%s\n", nt_errstr(status));
2491                 goto fail;
2492         }
2493
2494         status = cli_close(cli1, fnum1);
2495         if (!NT_STATUS_IS_OK(status)) {
2496                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2497                 goto fail;
2498         }
2499
2500         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2501         if (!NT_STATUS_IS_OK(status)) {
2502                 d_fprintf(stderr, "cli_openx third time returned %s\n",
2503                           nt_errstr(status));
2504                 goto fail;
2505         }
2506
2507         correct = true;
2508
2509 fail:
2510         cli_close(cli1, fnum1);
2511         cli_close(cli1, fnum2);
2512         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2513         torture_close_connection(cli1);
2514
2515         printf("finished locktest8\n");
2516         return correct;
2517 }
2518
2519 /*
2520  * This test is designed to be run in conjunction with
2521  * external NFS or POSIX locks taken in the filesystem.
2522  * It checks that the smbd server will block until the
2523  * lock is released and then acquire it. JRA.
2524  */
2525
2526 static bool got_alarm;
2527 static struct cli_state *alarm_cli;
2528
2529 static void alarm_handler(int dummy)
2530 {
2531         got_alarm = True;
2532 }
2533
2534 static void alarm_handler_parent(int dummy)
2535 {
2536         smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_OK);
2537 }
2538
2539 static void do_local_lock(int read_fd, int write_fd)
2540 {
2541         int fd;
2542         char c = '\0';
2543         struct flock lock;
2544         const char *local_pathname = NULL;
2545         int ret;
2546
2547         local_pathname = talloc_asprintf(talloc_tos(),
2548                         "%s/lockt9.lck", local_path);
2549         if (!local_pathname) {
2550                 printf("child: alloc fail\n");
2551                 exit(1);
2552         }
2553
2554         unlink(local_pathname);
2555         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2556         if (fd == -1) {
2557                 printf("child: open of %s failed %s.\n",
2558                         local_pathname, strerror(errno));
2559                 exit(1);
2560         }
2561
2562         /* Now take a fcntl lock. */
2563         lock.l_type = F_WRLCK;
2564         lock.l_whence = SEEK_SET;
2565         lock.l_start = 0;
2566         lock.l_len = 4;
2567         lock.l_pid = getpid();
2568
2569         ret = fcntl(fd,F_SETLK,&lock);
2570         if (ret == -1) {
2571                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2572                         local_pathname, strerror(errno));
2573                 exit(1);
2574         } else {
2575                 printf("child: got lock 0:4 on file %s.\n",
2576                         local_pathname );
2577                 fflush(stdout);
2578         }
2579
2580         CatchSignal(SIGALRM, alarm_handler);
2581         alarm(5);
2582         /* Signal the parent. */
2583         if (write(write_fd, &c, 1) != 1) {
2584                 printf("child: start signal fail %s.\n",
2585                         strerror(errno));
2586                 exit(1);
2587         }
2588         alarm(0);
2589
2590         alarm(10);
2591         /* Wait for the parent to be ready. */
2592         if (read(read_fd, &c, 1) != 1) {
2593                 printf("child: reply signal fail %s.\n",
2594                         strerror(errno));
2595                 exit(1);
2596         }
2597         alarm(0);
2598
2599         sleep(5);
2600         close(fd);
2601         printf("child: released lock 0:4 on file %s.\n",
2602                 local_pathname );
2603         fflush(stdout);
2604         exit(0);
2605 }
2606
2607 static bool run_locktest9(int dummy)
2608 {
2609         struct cli_state *cli1;
2610         const char *fname = "\\lockt9.lck";
2611         uint16_t fnum;
2612         bool correct = False;
2613         int pipe_in[2], pipe_out[2];
2614         pid_t child_pid;
2615         char c = '\0';
2616         int ret;
2617         struct timeval start;
2618         double seconds;
2619         NTSTATUS status;
2620
2621         printf("starting locktest9\n");
2622
2623         if (local_path == NULL) {
2624                 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2625                 return false;
2626         }
2627
2628         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2629                 return false;
2630         }
2631
2632         child_pid = fork();
2633         if (child_pid == -1) {
2634                 return false;
2635         }
2636
2637         if (child_pid == 0) {
2638                 /* Child. */
2639                 do_local_lock(pipe_out[0], pipe_in[1]);
2640                 exit(0);
2641         }
2642
2643         close(pipe_out[0]);
2644         close(pipe_in[1]);
2645         pipe_out[0] = -1;
2646         pipe_in[1] = -1;
2647
2648         /* Parent. */
2649         ret = read(pipe_in[0], &c, 1);
2650         if (ret != 1) {
2651                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2652                         strerror(errno));
2653                 return false;
2654         }
2655
2656         if (!torture_open_connection(&cli1, 0)) {
2657                 return false;
2658         }
2659
2660         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2661
2662         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE,
2663                           &fnum);
2664         if (!NT_STATUS_IS_OK(status)) {
2665                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2666                 return false;
2667         }
2668
2669         /* Ensure the child has the lock. */
2670         status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2671         if (NT_STATUS_IS_OK(status)) {
2672                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2673                 goto fail;
2674         } else {
2675                 d_printf("Child has the lock.\n");
2676         }
2677
2678         /* Tell the child to wait 5 seconds then exit. */
2679         ret = write(pipe_out[1], &c, 1);
2680         if (ret != 1) {
2681                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2682                         strerror(errno));
2683                 goto fail;
2684         }
2685
2686         /* Wait 20 seconds for the lock. */
2687         alarm_cli = cli1;
2688         CatchSignal(SIGALRM, alarm_handler_parent);
2689         alarm(20);
2690
2691         start = timeval_current();
2692
2693         status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2694         if (!NT_STATUS_IS_OK(status)) {
2695                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2696                        "%s\n", nt_errstr(status));
2697                 goto fail_nofd;
2698         }
2699         alarm(0);
2700
2701         seconds = timeval_elapsed(&start);
2702
2703         printf("Parent got the lock after %.2f seconds.\n",
2704                 seconds);
2705
2706         status = cli_close(cli1, fnum);
2707         if (!NT_STATUS_IS_OK(status)) {
2708                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2709                 goto fail;
2710         }
2711
2712         correct = true;
2713
2714 fail:
2715         cli_close(cli1, fnum);
2716         torture_close_connection(cli1);
2717
2718 fail_nofd:
2719
2720         printf("finished locktest9\n");
2721         return correct;
2722 }
2723
2724 /*
2725 test whether fnums and tids open on one VC are available on another (a major
2726 security hole)
2727 */
2728 static bool run_fdpasstest(int dummy)
2729 {
2730         struct cli_state *cli1, *cli2;
2731         const char *fname = "\\fdpass.tst";
2732         uint16_t fnum1;
2733         char buf[1024];
2734         NTSTATUS status;
2735
2736         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2737                 return False;
2738         }
2739         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2740         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2741
2742         printf("starting fdpasstest\n");
2743
2744         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2745
2746         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2747                           &fnum1);
2748         if (!NT_STATUS_IS_OK(status)) {
2749                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2750                 return False;
2751         }
2752
2753         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2754                               13, NULL);
2755         if (!NT_STATUS_IS_OK(status)) {
2756                 printf("write failed (%s)\n", nt_errstr(status));
2757                 return False;
2758         }
2759
2760         cli_state_set_uid(cli2, cli_state_get_uid(cli1));
2761         cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2762         cli_setpid(cli2, cli_getpid(cli1));
2763
2764         if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
2765                 printf("read succeeded! nasty security hole [%s]\n", buf);
2766                 return false;
2767         }
2768
2769         cli_close(cli1, fnum1);
2770         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2771
2772         torture_close_connection(cli1);
2773         torture_close_connection(cli2);
2774
2775         printf("finished fdpasstest\n");
2776         return True;
2777 }
2778
2779 static bool run_fdsesstest(int dummy)
2780 {
2781         struct cli_state *cli;
2782         uint16_t new_vuid;
2783         uint16_t saved_vuid;
2784         uint32_t new_cnum;
2785         uint32_t saved_cnum;
2786         const char *fname = "\\fdsess.tst";
2787         const char *fname1 = "\\fdsess1.tst";
2788         uint16_t fnum1;
2789         uint16_t fnum2;
2790         char buf[1024];
2791         bool ret = True;
2792         NTSTATUS status;
2793
2794         if (!torture_open_connection(&cli, 0))
2795                 return False;
2796         smbXcli_conn_set_sockopt(cli->conn, sockops);
2797
2798         if (!torture_cli_session_setup2(cli, &new_vuid))
2799                 return False;
2800
2801         saved_cnum = cli_state_get_tid(cli);
2802         if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
2803                 return False;
2804         new_cnum = cli_state_get_tid(cli);
2805         cli_state_set_tid(cli, saved_cnum);
2806
2807         printf("starting fdsesstest\n");
2808
2809         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2810         cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2811
2812         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2813         if (!NT_STATUS_IS_OK(status)) {
2814                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2815                 return False;
2816         }
2817
2818         status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2819                               NULL);
2820         if (!NT_STATUS_IS_OK(status)) {
2821                 printf("write failed (%s)\n", nt_errstr(status));
2822                 return False;
2823         }
2824
2825         saved_vuid = cli_state_get_uid(cli);
2826         cli_state_set_uid(cli, new_vuid);
2827
2828         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2829                 printf("read succeeded with different vuid! "
2830                        "nasty security hole [%s]\n", buf);
2831                 ret = false;
2832         }
2833         /* Try to open a file with different vuid, samba cnum. */
2834         if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2835                 printf("create with different vuid, same cnum succeeded.\n");
2836                 cli_close(cli, fnum2);
2837                 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2838         } else {
2839                 printf("create with different vuid, same cnum failed.\n");
2840                 printf("This will cause problems with service clients.\n");
2841                 ret = False;
2842         }
2843
2844         cli_state_set_uid(cli, saved_vuid);
2845
2846         /* Try with same vuid, different cnum. */
2847         cli_state_set_tid(cli, new_cnum);
2848
2849         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2850                 printf("read succeeded with different cnum![%s]\n", buf);
2851                 ret = false;
2852         }
2853
2854         cli_state_set_tid(cli, saved_cnum);
2855         cli_close(cli, fnum1);
2856         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2857
2858         torture_close_connection(cli);
2859
2860         printf("finished fdsesstest\n");
2861         return ret;
2862 }
2863
2864 /*
2865   This test checks that 
2866
2867   1) the server does not allow an unlink on a file that is open
2868 */
2869 static bool run_unlinktest(int dummy)
2870 {
2871         struct cli_state *cli;
2872         const char *fname = "\\unlink.tst";
2873         uint16_t fnum;
2874         bool correct = True;
2875         NTSTATUS status;
2876
2877         if (!torture_open_connection(&cli, 0)) {
2878                 return False;
2879         }
2880
2881         smbXcli_conn_set_sockopt(cli->conn, sockops);
2882
2883         printf("starting unlink test\n");
2884
2885         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2886
2887         cli_setpid(cli, 1);
2888
2889         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2890         if (!NT_STATUS_IS_OK(status)) {
2891                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2892                 return False;
2893         }
2894
2895         status = cli_unlink(cli, fname,
2896                             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2897         if (NT_STATUS_IS_OK(status)) {
2898                 printf("error: server allowed unlink on an open file\n");
2899                 correct = False;
2900         } else {
2901                 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
2902                                       NT_STATUS_SHARING_VIOLATION);
2903         }
2904
2905         cli_close(cli, fnum);
2906         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2907
2908         if (!torture_close_connection(cli)) {
2909                 correct = False;
2910         }
2911
2912         printf("unlink test finished\n");
2913
2914         return correct;
2915 }
2916
2917
2918 /*
2919 test how many open files this server supports on the one socket
2920 */
2921 static bool run_maxfidtest(int dummy)
2922 {
2923         struct cli_state *cli;
2924         fstring fname;
2925         uint16_t fnums[0x11000];
2926         int i;
2927         int retries=4;
2928         bool correct = True;
2929         NTSTATUS status;
2930
2931         cli = current_cli;
2932
2933         if (retries <= 0) {
2934                 printf("failed to connect\n");
2935                 return False;
2936         }
2937
2938         smbXcli_conn_set_sockopt(cli->conn, sockops);
2939
2940         for (i=0; i<0x11000; i++) {
2941                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2942                 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2943                                   &fnums[i]);
2944                 if (!NT_STATUS_IS_OK(status)) {
2945                         printf("open of %s failed (%s)\n", 
2946                                fname, nt_errstr(status));
2947                         printf("maximum fnum is %d\n", i);
2948                         break;
2949                 }
2950                 printf("%6d\r", i);
2951         }
2952         printf("%6d\n", i);
2953         i--;
2954
2955         printf("cleaning up\n");
2956         for (;i>=0;i--) {
2957                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2958                 cli_close(cli, fnums[i]);
2959
2960                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2961                 if (!NT_STATUS_IS_OK(status)) {
2962                         printf("unlink of %s failed (%s)\n", 
2963                                fname, nt_errstr(status));
2964                         correct = False;
2965                 }
2966                 printf("%6d\r", i);
2967         }
2968         printf("%6d\n", 0);
2969
2970         printf("maxfid test finished\n");
2971         if (!torture_close_connection(cli)) {
2972                 correct = False;
2973         }
2974         return correct;
2975 }
2976
2977 /* generate a random buffer */
2978 static void rand_buf(char *buf, int len)
2979 {
2980         while (len--) {
2981                 *buf = (char)sys_random();
2982                 buf++;
2983         }
2984 }
2985
2986 /* send smb negprot commands, not reading the response */
2987 static bool run_negprot_nowait(int dummy)
2988 {
2989         struct tevent_context *ev;
2990         int i;
2991         struct cli_state *cli;
2992         bool correct = True;
2993
2994         printf("starting negprot nowait test\n");
2995
2996         ev = samba_tevent_context_init(talloc_tos());
2997         if (ev == NULL) {
2998                 return false;
2999         }
3000
3001         if (!(cli = open_nbt_connection())) {
3002                 TALLOC_FREE(ev);
3003                 return False;
3004         }
3005
3006         for (i=0;i<50000;i++) {
3007                 struct tevent_req *req;
3008
3009                 req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
3010                                            PROTOCOL_CORE, PROTOCOL_NT1, 0);
3011                 if (req == NULL) {
3012                         TALLOC_FREE(ev);
3013                         return false;
3014                 }
3015                 if (!tevent_req_poll(req, ev)) {
3016                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3017                                   strerror(errno));
3018                         TALLOC_FREE(ev);
3019                         return false;
3020                 }
3021                 TALLOC_FREE(req);
3022         }
3023
3024         if (torture_close_connection(cli)) {
3025                 correct = False;
3026         }
3027
3028         printf("finished negprot nowait test\n");
3029
3030         return correct;
3031 }
3032
3033 /* send smb negprot commands, not reading the response */
3034 static bool run_bad_nbt_session(int dummy)
3035 {
3036         struct nmb_name called, calling;
3037         struct sockaddr_storage ss;
3038         NTSTATUS status;
3039         int fd;
3040         bool ret;
3041
3042         printf("starting bad nbt session test\n");
3043
3044         make_nmb_name(&calling, myname, 0x0);
3045         make_nmb_name(&called , host, 0x20);
3046
3047         if (!resolve_name(host, &ss, 0x20, true)) {
3048                 d_fprintf(stderr, "Could not resolve name %s\n", host);
3049                 return false;
3050         }
3051
3052         status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3053         if (!NT_STATUS_IS_OK(status)) {
3054                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3055                           nt_errstr(status));
3056                 return false;
3057         }
3058
3059         ret = cli_bad_session_request(fd, &calling, &called);
3060         close(fd);
3061         if (!ret) {
3062                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3063                           nt_errstr(status));
3064                 return false;
3065         }
3066
3067         printf("finished bad nbt session test\n");
3068         return true;
3069 }
3070
3071 /* send random IPC commands */
3072 static bool run_randomipc(int dummy)
3073 {
3074         char *rparam = NULL;
3075         char *rdata = NULL;
3076         unsigned int rdrcnt,rprcnt;
3077         char param[1024];
3078         int api, param_len, i;
3079         struct cli_state *cli;
3080         bool correct = True;
3081         int count = 50000;
3082
3083         printf("starting random ipc test\n");
3084
3085         if (!torture_open_connection(&cli, 0)) {
3086                 return False;
3087         }
3088
3089         for (i=0;i<count;i++) {
3090                 api = sys_random() % 500;
3091                 param_len = (sys_random() % 64);
3092
3093                 rand_buf(param, param_len);
3094
3095                 SSVAL(param,0,api); 
3096
3097                 cli_api(cli, 
3098                         param, param_len, 8,  
3099                         NULL, 0, CLI_BUFFER_SIZE,
3100                         &rparam, &rprcnt,     
3101                         &rdata, &rdrcnt);
3102                 if (i % 100 == 0) {
3103                         printf("%d/%d\r", i,count);
3104                 }
3105         }
3106         printf("%d/%d\n", i, count);
3107
3108         if (!torture_close_connection(cli)) {
3109                 correct = False;
3110         }
3111
3112         SAFE_FREE(rparam);
3113         SAFE_FREE(rdata);
3114
3115         printf("finished random ipc test\n");
3116
3117         return correct;
3118 }
3119
3120
3121
3122 static void browse_callback(const char *sname, uint32_t stype,
3123                             const char *comment, void *state)
3124 {
3125         printf("\t%20.20s %08x %s\n", sname, stype, comment);
3126 }
3127
3128
3129
3130 /*
3131   This test checks the browse list code
3132
3133 */
3134 static bool run_browsetest(int dummy)
3135 {
3136         static struct cli_state *cli;
3137         bool correct = True;
3138
3139         printf("starting browse test\n");
3140
3141         if (!torture_open_connection(&cli, 0)) {
3142                 return False;
3143         }
3144
3145         printf("domain list:\n");
3146         cli_NetServerEnum(cli, cli->server_domain, 
3147                           SV_TYPE_DOMAIN_ENUM,
3148                           browse_callback, NULL);
3149
3150         printf("machine list:\n");
3151         cli_NetServerEnum(cli, cli->server_domain, 
3152                           SV_TYPE_ALL,
3153                           browse_callback, NULL);
3154
3155         if (!torture_close_connection(cli)) {
3156                 correct = False;
3157         }
3158
3159         printf("browse test finished\n");
3160
3161         return correct;
3162
3163 }
3164
3165
3166 /*
3167   This checks how the getatr calls works
3168 */
3169 static bool run_attrtest(int dummy)
3170 {
3171         struct cli_state *cli;
3172         uint16_t fnum;
3173         time_t t, t2;
3174         const char *fname = "\\attrib123456789.tst";
3175         bool correct = True;
3176         NTSTATUS status;
3177
3178         printf("starting attrib test\n");
3179
3180         if (!torture_open_connection(&cli, 0)) {
3181                 return False;
3182         }
3183
3184         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3185         cli_openx(cli, fname, 
3186                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3187         cli_close(cli, fnum);
3188
3189         status = cli_getatr(cli, fname, NULL, NULL, &t);
3190         if (!NT_STATUS_IS_OK(status)) {
3191                 printf("getatr failed (%s)\n", nt_errstr(status));
3192                 correct = False;
3193         }
3194
3195         if (abs(t - time(NULL)) > 60*60*24*10) {
3196                 printf("ERROR: SMBgetatr bug. time is %s",
3197                        ctime(&t));
3198                 t = time(NULL);
3199                 correct = True;
3200         }
3201
3202         t2 = t-60*60*24; /* 1 day ago */
3203
3204         status = cli_setatr(cli, fname, 0, t2);
3205         if (!NT_STATUS_IS_OK(status)) {
3206                 printf("setatr failed (%s)\n", nt_errstr(status));
3207                 correct = True;
3208         }
3209
3210         status = cli_getatr(cli, fname, NULL, NULL, &t);
3211         if (!NT_STATUS_IS_OK(status)) {
3212                 printf("getatr failed (%s)\n", nt_errstr(status));
3213                 correct = True;
3214         }
3215
3216         if (t != t2) {
3217                 printf("ERROR: getatr/setatr bug. times are\n%s",
3218                        ctime(&t));
3219                 printf("%s", ctime(&t2));
3220                 correct = True;
3221         }
3222
3223         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3224
3225         if (!torture_close_connection(cli)) {
3226                 correct = False;
3227         }
3228
3229         printf("attrib test finished\n");
3230
3231         return correct;
3232 }
3233
3234
3235 /*
3236   This checks a couple of trans2 calls
3237 */
3238 static bool run_trans2test(int dummy)
3239 {
3240         struct cli_state *cli;
3241         uint16_t fnum;
3242         off_t size;
3243         time_t c_time, a_time, m_time;
3244         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3245         const char *fname = "\\trans2.tst";
3246         const char *dname = "\\trans2";
3247         const char *fname2 = "\\trans2\\trans2.tst";
3248         char *pname;
3249         bool correct = True;
3250         NTSTATUS status;
3251         uint32_t fs_attr;
3252
3253         printf("starting trans2 test\n");
3254
3255         if (!torture_open_connection(&cli, 0)) {
3256                 return False;
3257         }
3258
3259         status = cli_get_fs_attr_info(cli, &fs_attr);
3260         if (!NT_STATUS_IS_OK(status)) {
3261                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3262                        nt_errstr(status));
3263                 correct = false;
3264         }
3265
3266         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3267         cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3268         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3269                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3270         if (!NT_STATUS_IS_OK(status)) {
3271                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3272                 correct = False;
3273         }
3274
3275         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3276         if (!NT_STATUS_IS_OK(status)) {
3277                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3278                 correct = False;
3279         }
3280         else if (strcmp(pname, fname)) {
3281                 printf("qfilename gave different name? [%s] [%s]\n",
3282                        fname, pname);
3283                 correct = False;
3284         }
3285
3286         cli_close(cli, fnum);
3287
3288         sleep(2);
3289
3290         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3291         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3292                           &fnum);
3293         if (!NT_STATUS_IS_OK(status)) {
3294                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3295                 return False;
3296         }
3297         cli_close(cli, fnum);
3298
3299         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3300                                 NULL);
3301         if (!NT_STATUS_IS_OK(status)) {
3302                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3303                 correct = False;
3304         } else {
3305                 time_t t = time(NULL);
3306
3307                 if (c_time != m_time) {
3308                         printf("create time=%s", ctime(&c_time));
3309                         printf("modify time=%s", ctime(&m_time));
3310                         printf("This system appears to have sticky create times\n");
3311                 }
3312                 if ((abs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
3313                         printf("access time=%s", ctime(&a_time));
3314                         printf("This system appears to set a midnight access time\n");
3315                         correct = False;
3316                 }
3317
3318                 if (abs(m_time - t) > 60*60*24*7) {
3319                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3320                         correct = False;
3321                 }
3322         }
3323
3324
3325         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3326         cli_openx(cli, fname, 
3327                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3328         cli_close(cli, fnum);
3329         status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3330                                 &m_time_ts, &size, NULL, NULL);
3331         if (!NT_STATUS_IS_OK(status)) {
3332                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3333                 correct = False;
3334         } else {
3335                 if (w_time_ts.tv_sec < 60*60*24*2) {
3336                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
3337                         printf("This system appears to set a initial 0 write time\n");
3338                         correct = False;
3339                 }
3340         }
3341
3342         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3343
3344
3345         /* check if the server updates the directory modification time
3346            when creating a new file */
3347         status = cli_mkdir(cli, dname);
3348         if (!NT_STATUS_IS_OK(status)) {
3349                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3350                 correct = False;
3351         }
3352         sleep(3);
3353         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3354                                 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3355         if (!NT_STATUS_IS_OK(status)) {
3356                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3357                 correct = False;
3358         }
3359
3360         cli_openx(cli, fname2, 
3361                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3362         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3363         cli_close(cli, fnum);
3364         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3365                                 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3366         if (!NT_STATUS_IS_OK(status)) {
3367                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3368                 correct = False;
3369         } else {
3370                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3371                     == 0) {
3372                         printf("This system does not update directory modification times\n");
3373                         correct = False;
3374                 }
3375         }
3376         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3377         cli_rmdir(cli, dname);
3378
3379         if (!torture_close_connection(cli)) {
3380                 correct = False;
3381         }
3382
3383         printf("trans2 test finished\n");
3384
3385         return correct;
3386 }
3387
3388 /*
3389   This checks new W2K calls.
3390 */
3391
3392 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3393 {
3394         uint8_t *buf = NULL;
3395         uint32_t len;
3396         NTSTATUS status;
3397
3398         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3399                                CLI_BUFFER_SIZE, NULL, &buf, &len);
3400         if (!NT_STATUS_IS_OK(status)) {
3401                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3402                        nt_errstr(status));
3403         } else {
3404                 printf("qfileinfo: level %d, len = %u\n", level, len);
3405                 dump_data(0, (uint8_t *)buf, len);
3406                 printf("\n");
3407         }
3408         TALLOC_FREE(buf);
3409         return status;
3410 }
3411
3412 static bool run_w2ktest(int dummy)
3413 {
3414         struct cli_state *cli;
3415         uint16_t fnum;
3416         const char *fname = "\\w2ktest\\w2k.tst";
3417         int level;
3418         bool correct = True;
3419
3420         printf("starting w2k test\n");
3421
3422         if (!torture_open_connection(&cli, 0)) {
3423                 return False;
3424         }
3425
3426         cli_openx(cli, fname, 
3427                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
3428
3429         for (level = 1004; level < 1040; level++) {
3430                 new_trans(cli, fnum, level);
3431         }
3432
3433         cli_close(cli, fnum);
3434
3435         if (!torture_close_connection(cli)) {
3436                 correct = False;
3437         }
3438
3439         printf("w2k test finished\n");
3440
3441         return correct;
3442 }
3443
3444
3445 /*
3446   this is a harness for some oplock tests
3447  */
3448 static bool run_oplock1(int dummy)
3449 {
3450         struct cli_state *cli1;
3451         const char *fname = "\\lockt1.lck";
3452         uint16_t fnum1;
3453         bool correct = True;
3454         NTSTATUS status;
3455
3456         printf("starting oplock test 1\n");
3457
3458         if (!torture_open_connection(&cli1, 0)) {
3459                 return False;
3460         }
3461
3462         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3463
3464         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3465
3466         cli1->use_oplocks = True;
3467
3468         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3469                           &fnum1);
3470         if (!NT_STATUS_IS_OK(status)) {
3471                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3472                 return False;
3473         }
3474
3475         cli1->use_oplocks = False;
3476
3477         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3478         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3479
3480         status = cli_close(cli1, fnum1);
3481         if (!NT_STATUS_IS_OK(status)) {
3482                 printf("close2 failed (%s)\n", nt_errstr(status));
3483                 return False;
3484         }
3485
3486         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3487         if (!NT_STATUS_IS_OK(status)) {
3488                 printf("unlink failed (%s)\n", nt_errstr(status));
3489                 return False;
3490         }
3491
3492         if (!torture_close_connection(cli1)) {
3493                 correct = False;
3494         }
3495
3496         printf("finished oplock test 1\n");
3497
3498         return correct;
3499 }
3500
3501 static bool run_oplock2(int dummy)
3502 {
3503         struct cli_state *cli1, *cli2;
3504         const char *fname = "\\lockt2.lck";
3505         uint16_t fnum1, fnum2;
3506         int saved_use_oplocks = use_oplocks;
3507         char buf[4];
3508         bool correct = True;
3509         volatile bool *shared_correct;
3510         size_t nread;
3511         NTSTATUS status;
3512
3513         shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
3514         *shared_correct = True;
3515
3516         use_level_II_oplocks = True;
3517         use_oplocks = True;
3518
3519         printf("starting oplock test 2\n");
3520
3521         if (!torture_open_connection(&cli1, 0)) {
3522                 use_level_II_oplocks = False;
3523                 use_oplocks = saved_use_oplocks;
3524                 return False;
3525         }
3526
3527         if (!torture_open_connection(&cli2, 1)) {
3528                 use_level_II_oplocks = False;
3529                 use_oplocks = saved_use_oplocks;
3530                 return False;
3531         }
3532
3533         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3534
3535         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3536         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3537
3538         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3539                           &fnum1);
3540         if (!NT_STATUS_IS_OK(status)) {
3541                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3542                 return False;
3543         }
3544
3545         /* Don't need the globals any more. */
3546         use_level_II_oplocks = False;
3547         use_oplocks = saved_use_oplocks;
3548
3549         if (fork() == 0) {
3550                 /* Child code */
3551                 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3552                 if (!NT_STATUS_IS_OK(status)) {
3553                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3554                         *shared_correct = False;
3555                         exit(0);
3556                 }
3557
3558                 sleep(2);
3559
3560                 status = cli_close(cli2, fnum2);
3561                 if (!NT_STATUS_IS_OK(status)) {
3562                         printf("close2 failed (%s)\n", nt_errstr(status));
3563                         *shared_correct = False;
3564                 }
3565
3566                 exit(0);
3567         }
3568
3569         sleep(2);
3570
3571         /* Ensure cli1 processes the break. Empty file should always return 0
3572          * bytes.  */
3573         status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
3574         if (!NT_STATUS_IS_OK(status)) {
3575                 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
3576                 correct = false;
3577         } else if (nread != 0) {
3578                 printf("read on empty fnum1 failed. recv %ld expected %d\n",
3579                       (unsigned long)nread, 0);
3580                 correct = false;
3581         }
3582
3583         /* Should now be at level II. */
3584         /* Test if sending a write locks causes a break to none. */
3585         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3586         if (!NT_STATUS_IS_OK(status)) {
3587                 printf("lock failed (%s)\n", nt_errstr(status));
3588                 correct = False;
3589         }
3590
3591         cli_unlock(cli1, fnum1, 0, 4);
3592
3593         sleep(2);
3594
3595         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3596         if (!NT_STATUS_IS_OK(status)) {
3597                 printf("lock failed (%s)\n", nt_errstr(status));
3598                 correct = False;
3599         }
3600
3601         cli_unlock(cli1, fnum1, 0, 4);
3602
3603         sleep(2);
3604
3605         cli_read(cli1, fnum1, buf, 0, 4, NULL);
3606
3607         status = cli_close(cli1, fnum1);
3608         if (!NT_STATUS_IS_OK(status)) {
3609                 printf("close1 failed (%s)\n", nt_errstr(status));
3610                 correct = False;
3611         }
3612
3613         sleep(4);
3614
3615         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3616         if (!NT_STATUS_IS_OK(status)) {
3617                 printf("unlink failed (%s)\n", nt_errstr(status));
3618                 correct = False;
3619         }
3620
3621         if (!torture_close_connection(cli1)) {
3622                 correct = False;
3623         }
3624
3625         if (!*shared_correct) {
3626                 correct = False;
3627         }
3628
3629         printf("finished oplock test 2\n");
3630
3631         return correct;
3632 }
3633
3634 struct oplock4_state {
3635         struct tevent_context *ev;
3636         struct cli_state *cli;
3637         bool *got_break;
3638         uint16_t *fnum2;
3639 };
3640
3641 static void oplock4_got_break(struct tevent_req *req);
3642 static void oplock4_got_open(struct tevent_req *req);
3643
3644 static bool run_oplock4(int dummy)
3645 {
3646         struct tevent_context *ev;
3647         struct cli_state *cli1, *cli2;
3648         struct tevent_req *oplock_req, *open_req;
3649         const char *fname = "\\lockt4.lck";
3650         const char *fname_ln = "\\lockt4_ln.lck";
3651         uint16_t fnum1, fnum2;
3652         int saved_use_oplocks = use_oplocks;
3653         NTSTATUS status;
3654         bool correct = true;
3655
3656         bool got_break;
3657
3658         struct oplock4_state *state;
3659
3660         printf("starting oplock test 4\n");
3661
3662         if (!torture_open_connection(&cli1, 0)) {
3663                 use_level_II_oplocks = false;
3664                 use_oplocks = saved_use_oplocks;
3665                 return false;
3666         }
3667
3668         if (!torture_open_connection(&cli2, 1)) {
3669                 use_level_II_oplocks = false;
3670                 use_oplocks = saved_use_oplocks;
3671                 return false;
3672         }
3673
3674         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3675         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3676
3677         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3678         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3679
3680         /* Create the file. */
3681         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3682                           &fnum1);
3683         if (!NT_STATUS_IS_OK(status)) {
3684                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3685                 return false;
3686         }
3687
3688         status = cli_close(cli1, fnum1);
3689         if (!NT_STATUS_IS_OK(status)) {
3690                 printf("close1 failed (%s)\n", nt_errstr(status));
3691                 return false;
3692         }
3693
3694         /* Now create a hardlink. */
3695         status = cli_nt_hardlink(cli1, fname, fname_ln);
3696         if (!NT_STATUS_IS_OK(status)) {
3697                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3698                 return false;
3699         }
3700
3701         /* Prove that opening hardlinks cause deny modes to conflict. */
3702         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3703         if (!NT_STATUS_IS_OK(status)) {
3704                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3705                 return false;
3706         }
3707
3708         status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3709         if (NT_STATUS_IS_OK(status)) {
3710                 printf("open of %s succeeded - should fail with sharing violation.\n",
3711                         fname_ln);
3712                 return false;
3713         }
3714
3715         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3716                 printf("open of %s should fail with sharing violation. Got %s\n",
3717                         fname_ln, nt_errstr(status));
3718                 return false;
3719         }
3720
3721         status = cli_close(cli1, fnum1);
3722         if (!NT_STATUS_IS_OK(status)) {
3723                 printf("close1 failed (%s)\n", nt_errstr(status));
3724                 return false;
3725         }
3726
3727         cli1->use_oplocks = true;
3728         cli2->use_oplocks = true;
3729
3730         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3731         if (!NT_STATUS_IS_OK(status)) {
3732                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3733                 return false;
3734         }
3735
3736         ev = samba_tevent_context_init(talloc_tos());
3737         if (ev == NULL) {
3738                 printf("tevent_context_init failed\n");
3739                 return false;
3740         }
3741
3742         state = talloc(ev, struct oplock4_state);
3743         if (state == NULL) {
3744                 printf("talloc failed\n");
3745                 return false;
3746         }
3747         state->ev = ev;
3748         state->cli = cli1;
3749         state->got_break = &got_break;
3750         state->fnum2 = &fnum2;
3751
3752         oplock_req = cli_smb_oplock_break_waiter_send(
3753                 talloc_tos(), ev, cli1);
3754         if (oplock_req == NULL) {
3755                 printf("cli_smb_oplock_break_waiter_send failed\n");
3756                 return false;
3757         }
3758         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3759
3760         open_req = cli_openx_send(
3761                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3762         if (open_req == NULL) {
3763                 printf("cli_openx_send failed\n");
3764                 return false;
3765         }
3766         tevent_req_set_callback(open_req, oplock4_got_open, state);
3767
3768         got_break = false;
3769         fnum2 = 0xffff;
3770
3771         while (!got_break || fnum2 == 0xffff) {
3772                 int ret;
3773                 ret = tevent_loop_once(ev);
3774                 if (ret == -1) {
3775                         printf("tevent_loop_once failed: %s\n",
3776                                strerror(errno));
3777                         return false;
3778                 }
3779         }
3780
3781         status = cli_close(cli2, fnum2);
3782         if (!NT_STATUS_IS_OK(status)) {
3783                 printf("close2 failed (%s)\n", nt_errstr(status));
3784                 correct = false;
3785         }
3786
3787         status = cli_close(cli1, fnum1);
3788         if (!NT_STATUS_IS_OK(status)) {
3789                 printf("close1 failed (%s)\n", nt_errstr(status));
3790                 correct = false;
3791         }
3792
3793         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3794         if (!NT_STATUS_IS_OK(status)) {
3795                 printf("unlink failed (%s)\n", nt_errstr(status));
3796                 correct = false;
3797         }
3798
3799         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3800         if (!NT_STATUS_IS_OK(status)) {
3801                 printf("unlink failed (%s)\n", nt_errstr(status));
3802                 correct = false;
3803         }
3804
3805         if (!torture_close_connection(cli1)) {
3806                 correct = false;
3807         }
3808
3809         if (!got_break) {
3810                 correct = false;
3811         }
3812
3813         printf("finished oplock test 4\n");
3814
3815         return correct;
3816 }
3817
3818 static void oplock4_got_break(struct tevent_req *req)
3819 {
3820         struct oplock4_state *state = tevent_req_callback_data(
3821                 req, struct oplock4_state);
3822         uint16_t fnum;
3823         uint8_t level;
3824         NTSTATUS status;
3825
3826         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3827         TALLOC_FREE(req);
3828         if (!NT_STATUS_IS_OK(status)) {
3829                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3830                        nt_errstr(status));
3831                 return;
3832         }
3833         *state->got_break = true;
3834
3835         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3836                                   NO_OPLOCK);
3837         if (req == NULL) {
3838                 printf("cli_oplock_ack_send failed\n");
3839                 return;
3840         }
3841 }
3842
3843 static void oplock4_got_open(struct tevent_req *req)
3844 {
3845         struct oplock4_state *state = tevent_req_callback_data(
3846                 req, struct oplock4_state);
3847         NTSTATUS status;
3848
3849         status = cli_openx_recv(req, state->fnum2);
3850         if (!NT_STATUS_IS_OK(status)) {
3851                 printf("cli_openx_recv returned %s\n", nt_errstr(status));
3852                 *state->fnum2 = 0xffff;
3853         }
3854 }
3855
3856 /*
3857   Test delete on close semantics.
3858  */
3859 static bool run_deletetest(int dummy)
3860 {
3861         struct cli_state *cli1 = NULL;
3862         struct cli_state *cli2 = NULL;
3863         const char *fname = "\\delete.file";
3864         uint16_t fnum1 = (uint16_t)-1;
3865         uint16_t fnum2 = (uint16_t)-1;
3866         bool correct = false;
3867         NTSTATUS status;
3868
3869         printf("starting delete test\n");
3870
3871         if (!torture_open_connection(&cli1, 0)) {
3872                 return False;
3873         }
3874
3875         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3876
3877         /* Test 1 - this should delete the file on close. */
3878
3879         cli_setatr(cli1, fname, 0, 0);
3880         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3881
3882         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3883                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3884                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
3885         if (!NT_STATUS_IS_OK(status)) {
3886                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3887                 goto fail;
3888         }
3889
3890         status = cli_close(cli1, fnum1);
3891         if (!NT_STATUS_IS_OK(status)) {
3892                 printf("[1] close failed (%s)\n", nt_errstr(status));
3893                 goto fail;
3894         }
3895
3896         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3897         if (NT_STATUS_IS_OK(status)) {
3898                 printf("[1] open of %s succeeded (should fail)\n", fname);
3899                 goto fail;
3900         }
3901
3902         printf("first delete on close test succeeded.\n");
3903
3904         /* Test 2 - this should delete the file on close. */
3905
3906         cli_setatr(cli1, fname, 0, 0);
3907         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3908
3909         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3910                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3911                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
3912         if (!NT_STATUS_IS_OK(status)) {
3913                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3914                 goto fail;
3915         }
3916
3917         status = cli_nt_delete_on_close(cli1, fnum1, true);
3918         if (!NT_STATUS_IS_OK(status)) {
3919                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3920                 goto fail;
3921         }
3922
3923         status = cli_close(cli1, fnum1);
3924         if (!NT_STATUS_IS_OK(status)) {
3925                 printf("[2] close failed (%s)\n", nt_errstr(status));
3926                 goto fail;
3927         }
3928
3929         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
3930         if (NT_STATUS_IS_OK(status)) {
3931                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3932                 status = cli_close(cli1, fnum1);
3933                 if (!NT_STATUS_IS_OK(status)) {
3934                         printf("[2] close failed (%s)\n", nt_errstr(status));
3935                 }
3936                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3937                 goto fail;
3938         }
3939
3940         printf("second delete on close test succeeded.\n");
3941
3942         /* Test 3 - ... */
3943         cli_setatr(cli1, fname, 0, 0);
3944         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3945
3946         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3947                               FILE_ATTRIBUTE_NORMAL,
3948                               FILE_SHARE_READ|FILE_SHARE_WRITE,
3949                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
3950         if (!NT_STATUS_IS_OK(status)) {
3951                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
3952                 goto fail;
3953         }
3954
3955         /* This should fail with a sharing violation - open for delete is only compatible
3956            with SHARE_DELETE. */
3957
3958         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3959                               FILE_ATTRIBUTE_NORMAL,
3960                               FILE_SHARE_READ|FILE_SHARE_WRITE,
3961                               FILE_OPEN, 0, 0, &fnum2, NULL);
3962         if (NT_STATUS_IS_OK(status)) {
3963                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
3964                 goto fail;
3965         }
3966
3967         /* This should succeed. */
3968         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3969                              FILE_ATTRIBUTE_NORMAL,
3970                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3971                              FILE_OPEN, 0, 0, &fnum2, NULL);
3972         if (!NT_STATUS_IS_OK(status)) {
3973                 printf("[3] open  - 3 of %s failed (%s)\n", fname, nt_errstr(status));
3974                 goto fail;
3975         }
3976
3977         status = cli_nt_delete_on_close(cli1, fnum1, true);
3978         if (!NT_STATUS_IS_OK(status)) {
3979                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
3980                 goto fail;
3981         }
3982
3983         status = cli_close(cli1, fnum1);
3984         if (!NT_STATUS_IS_OK(status)) {
3985                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
3986                 goto fail;
3987         }
3988
3989         status = cli_close(cli1, fnum2);
3990         if (!NT_STATUS_IS_OK(status)) {
3991                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
3992                 goto fail;
3993         }
3994
3995         /* This should fail - file should no longer be there. */
3996
3997         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
3998         if (NT_STATUS_IS_OK(status)) {
3999                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
4000                 status = cli_close(cli1, fnum1);
4001                 if (!NT_STATUS_IS_OK(status)) {
4002                         printf("[3] close failed (%s)\n", nt_errstr(status));
4003                 }
4004                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4005                 goto fail;
4006         }
4007
4008         printf("third delete on close test succeeded.\n");
4009
4010         /* Test 4 ... */
4011         cli_setatr(cli1, fname, 0, 0);
4012         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4013
4014         status = cli_ntcreate(cli1, fname, 0,
4015                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4016                               FILE_ATTRIBUTE_NORMAL,
4017                               FILE_SHARE_READ|FILE_SHARE_WRITE,
4018                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4019         if (!NT_STATUS_IS_OK(status)) {
4020                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4021                 goto fail;
4022         }
4023
4024         /* This should succeed. */
4025         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4026                              FILE_ATTRIBUTE_NORMAL,
4027                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4028                              FILE_OPEN, 0, 0, &fnum2, NULL);
4029         if (!NT_STATUS_IS_OK(status)) {
4030                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4031                 goto fail;
4032         }
4033
4034         status = cli_close(cli1, fnum2);
4035         if (!NT_STATUS_IS_OK(status)) {
4036                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4037                 goto fail;
4038         }
4039
4040         status = cli_nt_delete_on_close(cli1, fnum1, true);
4041         if (!NT_STATUS_IS_OK(status)) {
4042                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4043                 goto fail;
4044         }
4045
4046         /* This should fail - no more opens once delete on close set. */
4047         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4048                               FILE_ATTRIBUTE_NORMAL,
4049                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4050                               FILE_OPEN, 0, 0, &fnum2, NULL);
4051         if (NT_STATUS_IS_OK(status)) {
4052                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
4053                 goto fail;
4054         }
4055
4056         status = cli_close(cli1, fnum1);
4057         if (!NT_STATUS_IS_OK(status)) {
4058                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4059                 goto fail;
4060         }
4061
4062         printf("fourth delete on close test succeeded.\n");
4063
4064         /* Test 5 ... */
4065         cli_setatr(cli1, fname, 0, 0);
4066         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4067
4068         status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4069         if (!NT_STATUS_IS_OK(status)) {
4070                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4071                 goto fail;
4072         }
4073
4074         /* This should fail - only allowed on NT opens with DELETE access. */
4075
4076         status = cli_nt_delete_on_close(cli1, fnum1, true);
4077         if (NT_STATUS_IS_OK(status)) {
4078                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4079                 goto fail;
4080         }
4081
4082         status = cli_close(cli1, fnum1);
4083         if (!NT_STATUS_IS_OK(status)) {
4084                 printf("[5] close failed (%s)\n", nt_errstr(status));
4085                 goto fail;
4086         }
4087
4088         printf("fifth delete on close test succeeded.\n");
4089
4090         /* Test 6 ... */
4091         cli_setatr(cli1, fname, 0, 0);
4092         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4093
4094         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4095                              FILE_ATTRIBUTE_NORMAL,
4096                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4097                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4098         if (!NT_STATUS_IS_OK(status)) {
4099                 printf("[6] open of %s failed (%s)\n", fname,
4100                        nt_errstr(status));
4101                 goto fail;
4102         }
4103
4104         /* This should fail - only allowed on NT opens with DELETE access. */
4105
4106         status = cli_nt_delete_on_close(cli1, fnum1, true);
4107         if (NT_STATUS_IS_OK(status)) {
4108                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4109                 goto fail;
4110         }
4111
4112         status = cli_close(cli1, fnum1);
4113         if (!NT_STATUS_IS_OK(status)) {
4114                 printf("[6] close failed (%s)\n", nt_errstr(status));
4115                 goto fail;
4116         }
4117
4118         printf("sixth delete on close test succeeded.\n");
4119
4120         /* Test 7 ... */
4121         cli_setatr(cli1, fname, 0, 0);
4122         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4123
4124         status = cli_ntcreate(cli1, fname, 0,
4125                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4126                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4127                               0, 0, &fnum1, NULL);
4128         if (!NT_STATUS_IS_OK(status)) {
4129                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4130                 goto fail;
4131         }
4132
4133         status = cli_nt_delete_on_close(cli1, fnum1, true);
4134         if (!NT_STATUS_IS_OK(status)) {
4135                 printf("[7] setting delete_on_close on file failed !\n");
4136                 goto fail;
4137         }
4138
4139         status = cli_nt_delete_on_close(cli1, fnum1, false);
4140         if (!NT_STATUS_IS_OK(status)) {
4141                 printf("[7] unsetting delete_on_close on file failed !\n");
4142                 goto fail;
4143         }
4144
4145         status = cli_close(cli1, fnum1);
4146         if (!NT_STATUS_IS_OK(status)) {
4147                 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
4148                 goto fail;
4149         }
4150
4151         /* This next open should succeed - we reset the flag. */
4152         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4153         if (!NT_STATUS_IS_OK(status)) {
4154                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4155                 goto fail;
4156         }
4157
4158         status = cli_close(cli1, fnum1);
4159         if (!NT_STATUS_IS_OK(status)) {
4160                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4161                 goto fail;
4162         }
4163
4164         printf("seventh delete on close test succeeded.\n");
4165
4166         /* Test 8 ... */
4167         cli_setatr(cli1, fname, 0, 0);
4168         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4169
4170         if (!torture_open_connection(&cli2, 1)) {
4171                 printf("[8] failed to open second connection.\n");
4172                 goto fail;
4173         }
4174
4175         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4176
4177         status = cli_ntcreate(cli1, fname, 0,
4178                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4179                              FILE_ATTRIBUTE_NORMAL,
4180                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4181                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4182         if (!NT_STATUS_IS_OK(status)) {
4183                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4184                 goto fail;
4185         }
4186
4187         status = cli_ntcreate(cli2, fname, 0,
4188                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4189                              FILE_ATTRIBUTE_NORMAL,
4190                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4191                              FILE_OPEN, 0, 0, &fnum2, NULL);
4192         if (!NT_STATUS_IS_OK(status)) {
4193                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4194                 goto fail;
4195         }
4196
4197         status = cli_nt_delete_on_close(cli1, fnum1, true);
4198         if (!NT_STATUS_IS_OK(status)) {
4199                 printf("[8] setting delete_on_close on file failed !\n");
4200                 goto fail;
4201         }
4202
4203         status = cli_close(cli1, fnum1);
4204         if (!NT_STATUS_IS_OK(status)) {
4205                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4206                 goto fail;
4207         }
4208
4209         status = cli_close(cli2, fnum2);
4210         if (!NT_STATUS_IS_OK(status)) {
4211                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4212                 goto fail;
4213         }
4214
4215         /* This should fail.. */
4216         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4217         if (NT_STATUS_IS_OK(status)) {
4218                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4219                 goto fail;
4220         }
4221
4222         printf("eighth delete on close test succeeded.\n");
4223
4224         /* Test 9 ... */
4225
4226         /* This should fail - we need to set DELETE_ACCESS. */
4227         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4228                               FILE_ATTRIBUTE_NORMAL,
4229                               FILE_SHARE_NONE,
4230                               FILE_OVERWRITE_IF,
4231                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4232         if (NT_STATUS_IS_OK(status)) {
4233                 printf("[9] open of %s succeeded should have failed!\n", fname);
4234                 goto fail;
4235         }
4236
4237         printf("ninth delete on close test succeeded.\n");
4238
4239         /* Test 10 ... */
4240
4241         status = cli_ntcreate(cli1, fname, 0,
4242                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4243                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4244                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4245                              0, &fnum1, NULL);
4246         if (!NT_STATUS_IS_OK(status)) {
4247                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4248                 goto fail;
4249         }
4250
4251         /* This should delete the file. */
4252         status = cli_close(cli1, fnum1);
4253         if (!NT_STATUS_IS_OK(status)) {
4254                 printf("[10] close failed (%s)\n", nt_errstr(status));
4255                 goto fail;
4256         }
4257
4258         /* This should fail.. */
4259         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4260         if (NT_STATUS_IS_OK(status)) {
4261                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4262                 goto fail;
4263         }
4264
4265         printf("tenth delete on close test succeeded.\n");
4266
4267         /* Test 11 ... */
4268
4269         cli_setatr(cli1, fname, 0, 0);
4270         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4271
4272         /* Can we open a read-only file with delete access? */
4273
4274         /* Create a readonly file. */
4275         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4276                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4277                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4278         if (!NT_STATUS_IS_OK(status)) {
4279                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4280                 goto fail;
4281         }
4282
4283         status = cli_close(cli1, fnum1);
4284         if (!NT_STATUS_IS_OK(status)) {
4285                 printf("[11] close failed (%s)\n", nt_errstr(status));
4286                 goto fail;
4287         }
4288
4289         /* Now try open for delete access. */
4290         status = cli_ntcreate(cli1, fname, 0,
4291                              FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4292                              0,
4293                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4294                              FILE_OPEN, 0, 0, &fnum1, NULL);
4295         if (!NT_STATUS_IS_OK(status)) {
4296                 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
4297                 goto fail;
4298         }
4299
4300         cli_close(cli1, fnum1);
4301
4302         printf("eleventh delete on close test succeeded.\n");
4303
4304         /*
4305          * Test 12
4306          * like test 4 but with initial delete on close
4307          */
4308
4309         cli_setatr(cli1, fname, 0, 0);
4310         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4311
4312         status = cli_ntcreate(cli1, fname, 0,
4313                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4314                               FILE_ATTRIBUTE_NORMAL,
4315                               FILE_SHARE_READ|FILE_SHARE_WRITE,
4316                               FILE_OVERWRITE_IF,
4317                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4318         if (!NT_STATUS_IS_OK(status)) {
4319                 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4320                 goto fail;
4321         }
4322
4323         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4324                               FILE_ATTRIBUTE_NORMAL,
4325                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4326                               FILE_OPEN, 0, 0, &fnum2, NULL);
4327         if (!NT_STATUS_IS_OK(status)) {
4328                 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
4329                 goto fail;
4330         }
4331
4332         status = cli_close(cli1, fnum2);
4333         if (!NT_STATUS_IS_OK(status)) {
4334                 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
4335                 goto fail;
4336         }
4337
4338         status = cli_nt_delete_on_close(cli1, fnum1, true);
4339         if (!NT_STATUS_IS_OK(status)) {
4340                 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
4341                 goto fail;
4342         }
4343
4344         /* This should fail - no more opens once delete on close set. */
4345         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4346                               FILE_ATTRIBUTE_NORMAL,
4347                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4348                               FILE_OPEN, 0, 0, &fnum2, NULL);
4349         if (NT_STATUS_IS_OK(status)) {
4350                 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
4351                 goto fail;
4352         }
4353
4354         status = cli_nt_delete_on_close(cli1, fnum1, false);
4355         if (!NT_STATUS_IS_OK(status)) {
4356                 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
4357                 goto fail;
4358         }
4359
4360         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4361                               FILE_ATTRIBUTE_NORMAL,
4362                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4363                               FILE_OPEN, 0, 0, &fnum2, NULL);
4364         if (!NT_STATUS_IS_OK(status)) {
4365                 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
4366                 goto fail;
4367         }
4368
4369         status = cli_close(cli1, fnum2);
4370         if (!NT_STATUS_IS_OK(status)) {
4371                 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
4372                 goto fail;
4373         }
4374
4375         status = cli_close(cli1, fnum1);
4376         if (!NT_STATUS_IS_OK(status)) {
4377                 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
4378                 goto fail;
4379         }
4380
4381         /*
4382          * setting delete on close on the handle does
4383          * not unset the initial delete on close...
4384          */
4385         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4386                               FILE_ATTRIBUTE_NORMAL,
4387                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4388                               FILE_OPEN, 0, 0, &fnum2, NULL);
4389         if (NT_STATUS_IS_OK(status)) {
4390                 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
4391                 goto fail;
4392         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4393                 printf("ntcreate returned %s, expected "
4394                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
4395                        nt_errstr(status));
4396                 goto fail;
4397         }
4398
4399         printf("twelfth delete on close test succeeded.\n");
4400
4401
4402         printf("finished delete test\n");
4403
4404         correct = true;
4405
4406   fail:
4407         /* FIXME: This will crash if we aborted before cli2 got
4408          * intialized, because these functions don't handle
4409          * uninitialized connections. */
4410
4411         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4412         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4413         cli_setatr(cli1, fname, 0, 0);
4414         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4415
4416         if (cli1 && !torture_close_connection(cli1)) {
4417                 correct = False;
4418         }
4419         if (cli2 && !torture_close_connection(cli2)) {
4420                 correct = False;
4421         }
4422         return correct;
4423 }
4424
4425
4426 /*
4427   Test wildcard delete.
4428  */
4429 static bool run_wild_deletetest(int dummy)
4430 {
4431         struct cli_state *cli = NULL;
4432         const char *dname = "\\WTEST";
4433         const char *fname = "\\WTEST\\A";
4434         const char *wunlink_name = "\\WTEST\\*";
4435         uint16_t fnum1 = (uint16_t)-1;
4436         bool correct = false;
4437         NTSTATUS status;
4438
4439         printf("starting wildcard delete test\n");
4440
4441         if (!torture_open_connection(&cli, 0)) {
4442                 return false;
4443         }
4444
4445         smbXcli_conn_set_sockopt(cli->conn, sockops);
4446
4447         cli_unlink(cli, fname, 0);
4448         cli_rmdir(cli, dname);
4449         status = cli_mkdir(cli, dname);
4450         if (!NT_STATUS_IS_OK(status)) {
4451                 printf("mkdir of %s failed %s!\n", dname, nt_errstr(status));
4452                 goto fail;
4453         }
4454         status = cli_openx(cli, fname, O_CREAT|O_RDONLY, DENY_NONE, &fnum1);
4455         if (!NT_STATUS_IS_OK(status)) {
4456                 printf("open of %s failed %s!\n", fname, nt_errstr(status));
4457                 goto fail;
4458         }
4459         status = cli_close(cli, fnum1);
4460         fnum1 = -1;
4461
4462         /*
4463          * Note the unlink attribute-type of zero. This should
4464          * map into FILE_ATTRIBUTE_NORMAL at the server even
4465          * on a wildcard delete.
4466          */
4467
4468         status = cli_unlink(cli, wunlink_name, 0);
4469         if (!NT_STATUS_IS_OK(status)) {
4470                 printf("unlink of %s failed %s!\n",
4471                         wunlink_name, nt_errstr(status));
4472                 goto fail;
4473         }
4474
4475         printf("finished wildcard delete test\n");
4476
4477         correct = true;
4478
4479   fail:
4480
4481         if (fnum1 != (uint16_t)-1) cli_close(cli, fnum1);
4482         cli_unlink(cli, fname, 0);
4483         cli_rmdir(cli, dname);
4484
4485         if (cli && !torture_close_connection(cli)) {
4486                 correct = false;
4487         }
4488         return correct;
4489 }
4490
4491 static bool run_deletetest_ln(int dummy)
4492 {
4493         struct cli_state *cli;
4494         const char *fname = "\\delete1";
4495         const char *fname_ln = "\\delete1_ln";
4496         uint16_t fnum;
4497         uint16_t fnum1;
4498         NTSTATUS status;
4499         bool correct = true;
4500         time_t t;
4501
4502         printf("starting deletetest-ln\n");
4503
4504         if (!torture_open_connection(&cli, 0)) {
4505                 return false;
4506         }
4507
4508         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4509         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4510
4511         smbXcli_conn_set_sockopt(cli->conn, sockops);
4512
4513         /* Create the file. */
4514         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4515         if (!NT_STATUS_IS_OK(status)) {
4516                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4517                 return false;
4518         }
4519
4520         status = cli_close(cli, fnum);
4521         if (!NT_STATUS_IS_OK(status)) {
4522                 printf("close1 failed (%s)\n", nt_errstr(status));
4523                 return false;
4524         }
4525
4526         /* Now create a hardlink. */
4527         status = cli_nt_hardlink(cli, fname, fname_ln);
4528         if (!NT_STATUS_IS_OK(status)) {
4529                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4530                 return false;
4531         }
4532
4533         /* Open the original file. */
4534         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4535                         FILE_ATTRIBUTE_NORMAL,
4536                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4537                         FILE_OPEN_IF, 0, 0, &fnum, NULL);
4538         if (!NT_STATUS_IS_OK(status)) {
4539                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4540                 return false;
4541         }
4542
4543         /* Unlink the hard link path. */
4544         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4545                         FILE_ATTRIBUTE_NORMAL,
4546                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4547                         FILE_OPEN_IF, 0, 0, &fnum1, NULL);
4548         if (!NT_STATUS_IS_OK(status)) {
4549                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4550                 return false;
4551         }
4552         status = cli_nt_delete_on_close(cli, fnum1, true);
4553         if (!NT_STATUS_IS_OK(status)) {
4554                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4555                         __location__, fname_ln, nt_errstr(status));
4556                 return false;
4557         }
4558
4559         status = cli_close(cli, fnum1);
4560         if (!NT_STATUS_IS_OK(status)) {
4561                 printf("close %s failed (%s)\n",
4562                         fname_ln, nt_errstr(status));
4563                 return false;
4564         }
4565
4566         status = cli_close(cli, fnum);
4567         if (!NT_STATUS_IS_OK(status)) {
4568                 printf("close %s failed (%s)\n",
4569                         fname, nt_errstr(status));
4570                 return false;
4571         }
4572
4573         /* Ensure the original file is still there. */
4574         status = cli_getatr(cli, fname, NULL, NULL, &t);
4575         if (!NT_STATUS_IS_OK(status)) {
4576                 printf("%s getatr on file %s failed (%s)\n",
4577                         __location__,
4578                         fname,
4579                         nt_errstr(status));
4580                 correct = False;
4581         }
4582
4583         /* Ensure the link path is gone. */
4584         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4585         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4586                 printf("%s, getatr for file %s returned wrong error code %s "
4587                         "- should have been deleted\n",
4588                         __location__,
4589                         fname_ln, nt_errstr(status));
4590                 correct = False;
4591         }
4592
4593         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4594         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4595
4596         if (!torture_close_connection(cli)) {
4597                 correct = false;
4598         }
4599
4600         printf("finished deletetest-ln\n");
4601
4602         return correct;
4603 }
4604
4605 /*
4606   print out server properties
4607  */
4608 static bool run_properties(int dummy)
4609 {
4610         struct cli_state *cli;
4611         bool correct = True;
4612
4613         printf("starting properties test\n");
4614
4615         ZERO_STRUCT(cli);
4616
4617         if (!torture_open_connection(&cli, 0)) {
4618                 return False;
4619         }
4620
4621         smbXcli_conn_set_sockopt(cli->conn, sockops);
4622
4623         d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
4624
4625         if (!torture_close_connection(cli)) {
4626                 correct = False;
4627         }
4628
4629         return correct;
4630 }
4631
4632
4633
4634 /* FIRST_DESIRED_ACCESS   0xf019f */
4635 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4636                                FILE_READ_EA|                           /* 0xf */ \
4637                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
4638                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
4639                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
4640                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
4641 /* SECOND_DESIRED_ACCESS  0xe0080 */
4642 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4643                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4644                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
4645
4646 #if 0
4647 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4648                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4649                                FILE_READ_DATA|\
4650                                WRITE_OWNER_ACCESS                      /* */
4651 #endif
4652
4653 /*
4654   Test ntcreate calls made by xcopy
4655  */
4656 static bool run_xcopy(int dummy)
4657 {
4658         static struct cli_state *cli1;
4659         const char *fname = "\\test.txt";
4660         bool correct = True;
4661         uint16_t fnum1, fnum2;
4662         NTSTATUS status;
4663
4664         printf("starting xcopy test\n");
4665
4666         if (!torture_open_connection(&cli1, 0)) {
4667                 return False;
4668         }
4669
4670         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4671                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4672                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
4673         if (!NT_STATUS_IS_OK(status)) {
4674                 printf("First open failed - %s\n", nt_errstr(status));
4675                 return False;
4676         }
4677
4678         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4679                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4680                              FILE_OPEN, 0x200000, 0, &fnum2, NULL);
4681         if (!NT_STATUS_IS_OK(status)) {
4682                 printf("second open failed - %s\n", nt_errstr(status));
4683                 return False;
4684         }
4685
4686         if (!torture_close_connection(cli1)) {
4687                 correct = False;
4688         }
4689
4690         return correct;
4691 }
4692
4693 /*
4694   Test rename on files open with share delete and no share delete.
4695  */
4696 static bool run_rename(int dummy)
4697 {
4698         static struct cli_state *cli1;
4699         const char *fname = "\\test.txt";
4700         const char *fname1 = "\\test1.txt";
4701         bool correct = True;
4702         uint16_t fnum1;
4703         uint16_t attr;
4704         NTSTATUS status;
4705
4706         printf("starting rename test\n");
4707
4708         if (!torture_open_connection(&cli1, 0)) {
4709                 return False;
4710         }
4711
4712         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4713         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4714
4715         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4716                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4717                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4718         if (!NT_STATUS_IS_OK(status)) {
4719                 printf("First open failed - %s\n", nt_errstr(status));
4720                 return False;
4721         }
4722
4723         status = cli_rename(cli1, fname, fname1, false);
4724         if (!NT_STATUS_IS_OK(status)) {
4725                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4726         } else {
4727                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4728                 correct = False;
4729         }
4730
4731         status = cli_close(cli1, fnum1);
4732         if (!NT_STATUS_IS_OK(status)) {
4733                 printf("close - 1 failed (%s)\n", nt_errstr(status));
4734                 return False;
4735         }
4736
4737         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4738         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4739         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4740 #if 0
4741                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
4742 #else
4743                               FILE_SHARE_DELETE|FILE_SHARE_READ,
4744 #endif
4745                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4746         if (!NT_STATUS_IS_OK(status)) {
4747                 printf("Second open failed - %s\n", nt_errstr(status));
4748                 return False;
4749         }
4750
4751         status = cli_rename(cli1, fname, fname1, false);
4752         if (!NT_STATUS_IS_OK(status)) {
4753                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4754                 correct = False;
4755         } else {
4756                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4757         }
4758
4759         status = cli_close(cli1, fnum1);
4760         if (!NT_STATUS_IS_OK(status)) {
4761                 printf("close - 2 failed (%s)\n", nt_errstr(status));
4762                 return False;
4763         }
4764
4765         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4766         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4767
4768         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4769                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4770                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4771         if (!NT_STATUS_IS_OK(status)) {
4772                 printf("Third open failed - %s\n", nt_errstr(status));
4773                 return False;
4774         }
4775
4776
4777 #if 0
4778   {
4779         uint16_t fnum2;
4780
4781         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4782                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
4783                 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4784                 return False;
4785         }
4786         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4787                 printf("[8] setting delete_on_close on file failed !\n");
4788                 return False;
4789         }
4790
4791         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4792                 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4793                 return False;
4794         }
4795   }
4796 #endif
4797
4798         status = cli_rename(cli1, fname, fname1, false);
4799         if (!NT_STATUS_IS_OK(status)) {
4800                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4801                 correct = False;
4802         } else {
4803                 printf("Third rename succeeded (SHARE_NONE)\n");
4804         }
4805
4806         status = cli_close(cli1, fnum1);
4807         if (!NT_STATUS_IS_OK(status)) {
4808                 printf("close - 3 failed (%s)\n", nt_errstr(status));
4809                 return False;
4810         }
4811
4812         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4813         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4814
4815         /*----*/
4816
4817         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4818                               FILE_ATTRIBUTE_NORMAL,
4819                               FILE_SHARE_READ | FILE_SHARE_WRITE,
4820                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4821         if (!NT_STATUS_IS_OK(status)) {
4822                 printf("Fourth open failed - %s\n", nt_errstr(status));
4823                 return False;
4824         }
4825
4826         status = cli_rename(cli1, fname, fname1, false);
4827         if (!NT_STATUS_IS_OK(status)) {
4828                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4829         } else {
4830                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4831                 correct = False;
4832         }
4833
4834         status = cli_close(cli1, fnum1);
4835         if (!NT_STATUS_IS_OK(status)) {
4836                 printf("close - 4 failed (%s)\n", nt_errstr(status));
4837                 return False;
4838         }
4839
4840         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4841         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4842
4843         /*--*/
4844
4845         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4846                          FILE_ATTRIBUTE_NORMAL,
4847                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4848                          FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4849         if (!NT_STATUS_IS_OK(status)) {
4850                 printf("Fifth open failed - %s\n", nt_errstr(status));
4851                 return False;
4852         }
4853
4854         status = cli_rename(cli1, fname, fname1, false);
4855         if (!NT_STATUS_IS_OK(status)) {
4856                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4857                 correct = False;
4858         } else {
4859                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4860         }
4861
4862         /*
4863          * Now check if the first name still exists ...
4864          */
4865
4866         /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4867                                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4868                                    FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
4869           printf("Opening original file after rename of open file fails: %s\n",
4870               cli_errstr(cli1));
4871         }
4872         else {
4873           printf("Opening original file after rename of open file works ...\n");
4874           (void)cli_close(cli1, fnum2);
4875           } */
4876
4877         /*--*/
4878         status = cli_close(cli1, fnum1);
4879         if (!NT_STATUS_IS_OK(status)) {
4880                 printf("close - 5 failed (%s)\n", nt_errstr(status));
4881                 return False;
4882         }
4883
4884         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4885         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4886         if (!NT_STATUS_IS_OK(status)) {
4887                 printf("getatr on file %s failed - %s ! \n",
4888                         fname1, nt_errstr(status));
4889                 correct = False;
4890         } else {
4891                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4892                         printf("Renamed file %s has wrong attr 0x%x "
4893                                 "(should be 0x%x)\n",
4894                                 fname1,
4895                                 attr,
4896                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4897                         correct = False;
4898                 } else {
4899                         printf("Renamed file %s has archive bit set\n", fname1);
4900                 }
4901         }
4902
4903         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4904         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4905
4906         if (!torture_close_connection(cli1)) {
4907                 correct = False;
4908         }
4909
4910         return correct;
4911 }
4912
4913 /*
4914   Test rename into a directory with an ACL denying it.
4915  */
4916 static bool run_rename_access(int dummy)
4917 {
4918         static struct cli_state *cli = NULL;
4919         static struct cli_state *posix_cli = NULL;
4920         const char *src = "test.txt";
4921         const char *dname = "dir";
4922         const char *dst = "dir\\test.txt";
4923         const char *dsrc = "test.dir";
4924         const char *ddst = "dir\\test.dir";
4925         uint16_t fnum = (uint16_t)-1;
4926         struct security_descriptor *sd = NULL;
4927         struct security_descriptor *newsd = NULL;
4928         NTSTATUS status;
4929         TALLOC_CTX *frame = NULL;
4930
4931         frame = talloc_stackframe();
4932         printf("starting rename access test\n");
4933
4934         /* Windows connection. */
4935         if (!torture_open_connection(&cli, 0)) {
4936                 goto fail;
4937         }
4938
4939         smbXcli_conn_set_sockopt(cli->conn, sockops);
4940
4941         /* Posix connection. */
4942         if (!torture_open_connection(&posix_cli, 0)) {
4943                 goto fail;
4944         }
4945
4946         smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
4947
4948         status = torture_setup_unix_extensions(posix_cli);
4949         if (!NT_STATUS_IS_OK(status)) {
4950                 goto fail;
4951         }
4952
4953         /* Start with a clean slate. */
4954         cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4955         cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4956         cli_rmdir(cli, dsrc);
4957         cli_rmdir(cli, ddst);
4958         cli_rmdir(cli, dname);
4959
4960         /*
4961          * Setup the destination directory with a DENY ACE to
4962          * prevent new files within it.
4963          */
4964         status = cli_ntcreate(cli,
4965                                 dname,
4966                                 0,
4967                                 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
4968                                         WRITE_DAC_ACCESS|FILE_READ_DATA|
4969                                         WRITE_OWNER_ACCESS,
4970                                 FILE_ATTRIBUTE_DIRECTORY,
4971                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
4972                                 FILE_CREATE,
4973                                 FILE_DIRECTORY_FILE,
4974                                 0,
4975                                 &fnum,
4976                                 NULL);
4977         if (!NT_STATUS_IS_OK(status)) {
4978                 printf("Create of %s - %s\n", dname, nt_errstr(status));
4979                 goto fail;
4980         }
4981
4982         status = cli_query_secdesc(cli,
4983                                 fnum,
4984                                 frame,
4985                                 &sd);
4986         if (!NT_STATUS_IS_OK(status)) {
4987                 printf("cli_query_secdesc failed for %s (%s)\n",
4988                         dname, nt_errstr(status));
4989                 goto fail;
4990         }
4991
4992         newsd = security_descriptor_dacl_create(frame,
4993                                         0,
4994                                         NULL,
4995                                         NULL,
4996                                         SID_WORLD,
4997                                         SEC_ACE_TYPE_ACCESS_DENIED,
4998                                         SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
4999                                         0,
5000                                         NULL);
5001         if (newsd == NULL) {
5002                 goto fail;
5003         }
5004         sd->dacl = security_acl_concatenate(frame,
5005                                         newsd->dacl,
5006                                         sd->dacl);
5007         if (sd->dacl == NULL) {
5008                 goto fail;
5009         }
5010         status = cli_set_secdesc(cli, fnum, sd);
5011         if (!NT_STATUS_IS_OK(status)) {
5012                 printf("cli_set_secdesc failed for %s (%s)\n",
5013                         dname, nt_errstr(status));
5014                 goto fail;
5015         }
5016         status = cli_close(cli, fnum);
5017         if (!NT_STATUS_IS_OK(status)) {
5018                 printf("close failed for %s (%s)\n",
5019                         dname, nt_errstr(status));
5020                 goto fail;
5021         }
5022         /* Now go around the back and chmod to 777 via POSIX. */
5023         status = cli_posix_chmod(posix_cli, dname, 0777);
5024         if (!NT_STATUS_IS_OK(status)) {
5025                 printf("cli_posix_chmod failed for %s (%s)\n",
5026                         dname, nt_errstr(status));
5027                 goto fail;
5028         }
5029
5030         /* Check we can't create a file within dname via Windows. */
5031         status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5032         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5033                 cli_close(posix_cli, fnum);
5034                 printf("Create of %s should be ACCESS denied, was %s\n",
5035                         dst, nt_errstr(status));
5036                 goto fail;
5037         }
5038
5039         /* Make the sample file/directory. */
5040         status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5041         if (!NT_STATUS_IS_OK(status)) {
5042                 printf("open of %s failed (%s)\n", src, nt_errstr(status));
5043                 goto fail;
5044         }
5045         status = cli_close(cli, fnum);
5046         if (!NT_STATUS_IS_OK(status)) {
5047                 printf("cli_close failed (%s)\n", nt_errstr(status));
5048                 goto fail;
5049         }
5050
5051         status = cli_mkdir(cli, dsrc);
5052         if (!NT_STATUS_IS_OK(status)) {
5053                 printf("cli_mkdir of %s failed (%s)\n",
5054                         dsrc, nt_errstr(status));
5055                 goto fail;
5056         }
5057
5058         /*
5059          * OK - renames of the new file and directory into the
5060          * dst directory should fail.
5061          */
5062
5063         status = cli_rename(cli, src, dst, false);
5064         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5065                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
5066                         src, dst, nt_errstr(status));
5067                 goto fail;
5068         }
5069         status = cli_rename(cli, dsrc, ddst, false);
5070         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5071                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
5072                         src, dst, nt_errstr(status));
5073                 goto fail;
5074         }
5075
5076         TALLOC_FREE(frame);
5077         return true;
5078
5079   fail:
5080
5081         if (posix_cli) {
5082                 torture_close_connection(posix_cli);
5083         }
5084
5085         if (cli) {
5086                 if (fnum != (uint64_t)-1) {
5087                         cli_close(cli, fnum);
5088                 }
5089                 cli_unlink(cli, src,
5090                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5091                 cli_unlink(cli, dst,
5092                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5093                 cli_rmdir(cli, dsrc);
5094                 cli_rmdir(cli, ddst);
5095                 cli_rmdir(cli, dname);
5096
5097                 torture_close_connection(cli);
5098         }
5099
5100         TALLOC_FREE(frame);
5101         return false;
5102 }
5103
5104 /*
5105   Test owner rights ACE.
5106  */
5107 static bool run_owner_rights(int dummy)
5108 {
5109         static struct cli_state *cli = NULL;
5110         const char *fname = "owner_rights.txt";
5111         uint16_t fnum = (uint16_t)-1;
5112         struct security_descriptor *sd = NULL;
5113         struct security_descriptor *newsd = NULL;
5114         NTSTATUS status;
5115         TALLOC_CTX *frame = NULL;
5116
5117         frame = talloc_stackframe();
5118         printf("starting owner rights test\n");
5119
5120         /* Windows connection. */
5121         if (!torture_open_connection(&cli, 0)) {
5122                 goto fail;
5123         }
5124
5125         smbXcli_conn_set_sockopt(cli->conn, sockops);
5126
5127         /* Start with a clean slate. */
5128         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5129
5130         /* Create the test file. */
5131         /* Now try and open for read and write-dac. */
5132         status = cli_ntcreate(cli,
5133                                 fname,
5134                                 0,
5135                                 GENERIC_ALL_ACCESS,
5136                                 FILE_ATTRIBUTE_NORMAL,
5137                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5138                                         FILE_SHARE_DELETE,
5139                                 FILE_CREATE,
5140                                 0,
5141                                 0,
5142                                 &fnum,
5143                                 NULL);
5144         if (!NT_STATUS_IS_OK(status)) {
5145                 printf("Create of %s - %s\n", fname, nt_errstr(status));
5146                 goto fail;
5147         }
5148
5149         /* Get the original SD. */
5150         status = cli_query_secdesc(cli,
5151                                 fnum,
5152                                 frame,
5153                                 &sd);
5154         if (!NT_STATUS_IS_OK(status)) {
5155                 printf("cli_query_secdesc failed for %s (%s)\n",
5156                         fname, nt_errstr(status));
5157                 goto fail;
5158         }
5159
5160         /*
5161          * Add an "owner-rights" ACE denying WRITE_DATA,
5162          * and an "owner-rights" ACE allowing READ_DATA.
5163          */
5164
5165         newsd = security_descriptor_dacl_create(frame,
5166                                         0,
5167                                         NULL,
5168                                         NULL,
5169                                         SID_OWNER_RIGHTS,
5170                                         SEC_ACE_TYPE_ACCESS_DENIED,
5171                                         FILE_WRITE_DATA,
5172                                         0,
5173                                         SID_OWNER_RIGHTS,
5174                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
5175                                         FILE_READ_DATA,
5176                                         0,
5177                                         NULL);
5178         if (newsd == NULL) {
5179                 goto fail;
5180         }
5181         sd->dacl = security_acl_concatenate(frame,
5182                                         newsd->dacl,
5183                                         sd->dacl);
5184         if (sd->dacl == NULL) {
5185                 goto fail;
5186         }
5187         status = cli_set_secdesc(cli, fnum, sd);
5188         if (!NT_STATUS_IS_OK(status)) {
5189                 printf("cli_set_secdesc failed for %s (%s)\n",
5190                         fname, nt_errstr(status));
5191                 goto fail;
5192         }
5193         status = cli_close(cli, fnum);
5194         if (!NT_STATUS_IS_OK(status)) {
5195                 printf("close failed for %s (%s)\n",
5196                         fname, nt_errstr(status));
5197                 goto fail;
5198         }
5199         fnum = (uint16_t)-1;
5200
5201         /* Try and open for FILE_WRITE_DATA */
5202         status = cli_ntcreate(cli,
5203                                 fname,
5204                                 0,
5205                                 FILE_WRITE_DATA,
5206                                 FILE_ATTRIBUTE_NORMAL,
5207                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5208                                         FILE_SHARE_DELETE,
5209                                 FILE_OPEN,
5210                                 0,
5211                                 0,
5212                                 &fnum,
5213                                 NULL);
5214         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5215                 printf("Open of %s - %s\n", fname, nt_errstr(status));
5216                 goto fail;
5217         }
5218
5219         /* Now try and open for FILE_READ_DATA */
5220         status = cli_ntcreate(cli,
5221                                 fname,
5222                                 0,
5223                                 FILE_READ_DATA,
5224                                 FILE_ATTRIBUTE_NORMAL,
5225                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5226                                         FILE_SHARE_DELETE,
5227                                 FILE_OPEN,
5228                                 0,
5229                                 0,
5230                                 &fnum,
5231                                 NULL);
5232         if (!NT_STATUS_IS_OK(status)) {
5233                 printf("Open of %s - %s\n", fname, nt_errstr(status));
5234                 goto fail;
5235         }
5236
5237         status = cli_close(cli, fnum);
5238         if (!NT_STATUS_IS_OK(status)) {
5239                 printf("close failed for %s (%s)\n",
5240                         fname, nt_errstr(status));
5241                 goto fail;
5242         }
5243
5244         /* Restore clean slate. */
5245         TALLOC_FREE(sd);
5246         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5247
5248         /* Create the test file. */
5249         status = cli_ntcreate(cli,
5250                                 fname,
5251                                 0,
5252                                 GENERIC_ALL_ACCESS,
5253                                 FILE_ATTRIBUTE_NORMAL,
5254                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5255                                         FILE_SHARE_DELETE,
5256                                 FILE_CREATE,
5257                                 0,
5258                                 0,
5259                                 &fnum,
5260                                 NULL);
5261         if (!NT_STATUS_IS_OK(status)) {
5262                 printf("Create of %s - %s\n", fname, nt_errstr(status));
5263                 goto fail;
5264         }
5265
5266         /* Get the original SD. */
5267         status = cli_query_secdesc(cli,
5268                                 fnum,
5269                                 frame,
5270                                 &sd);
5271         if (!NT_STATUS_IS_OK(status)) {
5272                 printf("cli_query_secdesc failed for %s (%s)\n",
5273                         fname, nt_errstr(status));
5274                 goto fail;
5275         }
5276
5277         /*
5278          * Add an "owner-rights ACE denying WRITE_DATA,
5279          * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
5280          */
5281
5282         newsd = security_descriptor_dacl_create(frame,
5283                                         0,
5284                                         NULL,
5285                                         NULL,
5286                                         SID_OWNER_RIGHTS,
5287                                         SEC_ACE_TYPE_ACCESS_DENIED,
5288                                         FILE_WRITE_DATA,
5289                                         0,
5290                                         SID_OWNER_RIGHTS,
5291                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
5292                                         FILE_READ_DATA|FILE_WRITE_DATA,
5293                                         0,
5294                                         NULL);
5295         if (newsd == NULL) {
5296                 goto fail;
5297         }
5298         sd->dacl = security_acl_concatenate(frame,
5299                                         newsd->dacl,
5300                                         sd->dacl);
5301         if (sd->dacl == NULL) {
5302                 goto fail;
5303         }
5304         status = cli_set_secdesc(cli, fnum, sd);
5305         if (!NT_STATUS_IS_OK(status)) {
5306                 printf("cli_set_secdesc failed for %s (%s)\n",
5307                         fname, nt_errstr(status));
5308                 goto fail;
5309         }
5310         status = cli_close(cli, fnum);
5311         if (!NT_STATUS_IS_OK(status)) {
5312                 printf("close failed for %s (%s)\n",
5313                         fname, nt_errstr(status));
5314                 goto fail;
5315         }
5316         fnum = (uint16_t)-1;
5317
5318         /* Try and open for FILE_WRITE_DATA */
5319         status = cli_ntcreate(cli,
5320                                 fname,
5321                                 0,
5322                                 FILE_WRITE_DATA,
5323                                 FILE_ATTRIBUTE_NORMAL,
5324                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5325                                         FILE_SHARE_DELETE,
5326                                 FILE_OPEN,
5327                                 0,
5328                                 0,
5329                                 &fnum,
5330                                 NULL);
5331         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5332                 printf("Open of %s - %s\n", fname, nt_errstr(status));
5333                 goto fail;
5334         }
5335
5336         /* Now try and open for FILE_READ_DATA */
5337         status = cli_ntcreate(cli,
5338                                 fname,
5339                                 0,
5340                                 FILE_READ_DATA,
5341                                 FILE_ATTRIBUTE_NORMAL,
5342                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5343                                         FILE_SHARE_DELETE,
5344                                 FILE_OPEN,
5345                                 0,
5346                                 0,
5347                                 &fnum,
5348                                 NULL);
5349         if (!NT_STATUS_IS_OK(status)) {
5350                 printf("Open of %s - %s\n", fname, nt_errstr(status));
5351                 goto fail;
5352         }
5353
5354         status = cli_close(cli, fnum);
5355         if (!NT_STATUS_IS_OK(status)) {
5356                 printf("close failed for %s (%s)\n",
5357                         fname, nt_errstr(status));
5358                 goto fail;
5359         }
5360
5361         /* Restore clean slate. */
5362         TALLOC_FREE(sd);
5363         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5364
5365
5366         /* Create the test file. */
5367         status = cli_ntcreate(cli,
5368                                 fname,
5369                                 0,
5370                                 GENERIC_ALL_ACCESS,
5371                                 FILE_ATTRIBUTE_NORMAL,
5372                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5373                                         FILE_SHARE_DELETE,
5374                                 FILE_CREATE,
5375                                 0,
5376                                 0,
5377                                 &fnum,
5378                                 NULL);
5379         if (!NT_STATUS_IS_OK(status)) {
5380                 printf("Create of %s - %s\n", fname, nt_errstr(status));
5381                 goto fail;
5382         }
5383
5384         /* Get the original SD. */
5385         status = cli_query_secdesc(cli,
5386                                 fnum,
5387                                 frame,
5388                                 &sd);
5389         if (!NT_STATUS_IS_OK(status)) {
5390                 printf("cli_query_secdesc failed for %s (%s)\n",
5391                         fname, nt_errstr(status));
5392                 goto fail;
5393         }
5394
5395         /*
5396          * Add an "authenticated users" ACE allowing READ_DATA,
5397          * add an "owner-rights" denying READ_DATA,
5398          * and an "authenticated users" ACE allowing WRITE_DATA.
5399          */
5400
5401         newsd = security_descriptor_dacl_create(frame,
5402                                         0,
5403                                         NULL,
5404                                         NULL,
5405                                         SID_NT_AUTHENTICATED_USERS,
5406                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
5407                                         FILE_READ_DATA,
5408                                         0,
5409                                         SID_OWNER_RIGHTS,
5410                                         SEC_ACE_TYPE_ACCESS_DENIED,
5411                                         FILE_READ_DATA,
5412                                         0,
5413                                         SID_NT_AUTHENTICATED_USERS,
5414                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
5415                                         FILE_WRITE_DATA,
5416                                         0,
5417                                         NULL);
5418         if (newsd == NULL) {
5419                 printf("newsd == NULL\n");
5420                 goto fail;
5421         }
5422         sd->dacl = security_acl_concatenate(frame,
5423                                         newsd->dacl,
5424                                         sd->dacl);
5425         if (sd->dacl == NULL) {
5426                 printf("sd->dacl == NULL\n");
5427                 goto fail;
5428         }
5429         status = cli_set_secdesc(cli, fnum, sd);
5430         if (!NT_STATUS_IS_OK(status)) {
5431                 printf("cli_set_secdesc failed for %s (%s)\n",
5432                         fname, nt_errstr(status));
5433                 goto fail;
5434         }
5435         status = cli_close(cli, fnum);
5436         if (!NT_STATUS_IS_OK(status)) {
5437                 printf("close failed for %s (%s)\n",
5438                         fname, nt_errstr(status));
5439                 goto fail;
5440         }
5441         fnum = (uint16_t)-1;
5442
5443         /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
5444         status = cli_ntcreate(cli,
5445                                 fname,
5446                                 0,
5447                                 FILE_READ_DATA|FILE_WRITE_DATA,
5448                                 FILE_ATTRIBUTE_NORMAL,
5449                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5450                                         FILE_SHARE_DELETE,
5451                                 FILE_OPEN,
5452                                 0,
5453                                 0,
5454                                 &fnum,
5455                                 NULL);
5456         if (!NT_STATUS_IS_OK(status)) {
5457                 printf("Open of %s - %s\n", fname, nt_errstr(status));
5458                 goto fail;
5459         }
5460
5461         status = cli_close(cli, fnum);
5462         if (!NT_STATUS_IS_OK(status)) {
5463                 printf("close failed for %s (%s)\n",
5464                         fname, nt_errstr(status));
5465                 goto fail;
5466         }
5467
5468         cli_unlink(cli, fname,
5469                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5470
5471         TALLOC_FREE(frame);
5472         return true;
5473
5474   fail:
5475
5476         if (cli) {
5477                 if (fnum != (uint16_t)-1) {
5478                         cli_close(cli, fnum);
5479                 }
5480                 cli_unlink(cli, fname,
5481                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5482                 torture_close_connection(cli);
5483         }
5484
5485         TALLOC_FREE(frame);
5486         return false;
5487 }
5488
5489 static bool run_pipe_number(int dummy)
5490 {
5491         struct cli_state *cli1;
5492         const char *pipe_name = "\\SPOOLSS";
5493         uint16_t fnum;
5494         int num_pipes = 0;
5495         NTSTATUS status;
5496
5497         printf("starting pipenumber test\n");
5498         if (!torture_open_connection(&cli1, 0)) {
5499                 return False;
5500         }
5501
5502         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5503         while(1) {
5504                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
5505                                       FILE_ATTRIBUTE_NORMAL,
5506                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
5507                                       FILE_OPEN_IF, 0, 0, &fnum, NULL);
5508                 if (!NT_STATUS_IS_OK(status)) {
5509                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
5510                         break;
5511                 }
5512                 num_pipes++;
5513                 printf("\r%6d", num_pipes);
5514         }
5515
5516         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
5517         torture_close_connection(cli1);
5518         return True;
5519 }
5520
5521 /*
5522   Test open mode returns on read-only files.
5523  */
5524 static bool run_opentest(int dummy)
5525 {
5526         static struct cli_state *cli1;
5527         static struct cli_state *cli2;
5528         const char *fname = "\\readonly.file";
5529         uint16_t fnum1, fnum2;
5530         char buf[20];
5531         off_t fsize;
5532         bool correct = True;
5533         char *tmp_path;
5534         NTSTATUS status;
5535
5536         printf("starting open test\n");
5537
5538         if (!torture_open_connection(&cli1, 0)) {
5539                 return False;
5540         }
5541
5542         cli_setatr(cli1, fname, 0, 0);
5543         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5544
5545         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5546
5547         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
5548         if (!NT_STATUS_IS_OK(status)) {
5549                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5550                 return False;
5551         }
5552
5553         status = cli_close(cli1, fnum1);
5554         if (!NT_STATUS_IS_OK(status)) {
5555                 printf("close2 failed (%s)\n", nt_errstr(status));
5556                 return False;
5557         }
5558
5559         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
5560         if (!NT_STATUS_IS_OK(status)) {
5561                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
5562                 return False;
5563         }
5564
5565         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
5566         if (!NT_STATUS_IS_OK(status)) {
5567                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5568                 return False;
5569         }
5570
5571         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
5572         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
5573
5574         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
5575                         NT_STATUS_ACCESS_DENIED)) {
5576                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
5577         }
5578
5579         printf("finished open test 1\n");
5580
5581         cli_close(cli1, fnum1);
5582
5583         /* Now try not readonly and ensure ERRbadshare is returned. */
5584
5585         cli_setatr(cli1, fname, 0, 0);
5586
5587         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
5588         if (!NT_STATUS_IS_OK(status)) {
5589                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5590                 return False;
5591         }
5592
5593         /* This will fail - but the error should be ERRshare. */
5594         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
5595
5596         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
5597                         NT_STATUS_SHARING_VIOLATION)) {
5598                 printf("correct error code ERRDOS/ERRbadshare returned\n");
5599         }
5600
5601         status = cli_close(cli1, fnum1);
5602         if (!NT_STATUS_IS_OK(status)) {
5603                 printf("close2 failed (%s)\n", nt_errstr(status));
5604                 return False;
5605         }
5606
5607         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5608
5609         printf("finished open test 2\n");
5610
5611         /* Test truncate open disposition on file opened for read. */
5612         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
5613         if (!NT_STATUS_IS_OK(status)) {
5614                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
5615                 return False;
5616         }
5617
5618         /* write 20 bytes. */
5619
5620         memset(buf, '\0', 20);
5621
5622         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
5623         if (!NT_STATUS_IS_OK(status)) {
5624                 printf("write failed (%s)\n", nt_errstr(status));
5625                 correct = False;
5626         }
5627
5628         status = cli_close(cli1, fnum1);
5629         if (!NT_STATUS_IS_OK(status)) {
5630                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
5631                 return False;
5632         }
5633
5634         /* Ensure size == 20. */
5635         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5636         if (!NT_STATUS_IS_OK(status)) {
5637                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5638                 return False;
5639         }
5640
5641         if (fsize != 20) {
5642                 printf("(3) file size != 20\n");
5643                 return False;
5644         }
5645
5646         /* Now test if we can truncate a file opened for readonly. */
5647         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
5648         if (!NT_STATUS_IS_OK(status)) {
5649                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
5650                 return False;
5651         }
5652
5653         status = cli_close(cli1, fnum1);
5654         if (!NT_STATUS_IS_OK(status)) {
5655                 printf("close2 failed (%s)\n", nt_errstr(status));
5656                 return False;
5657         }
5658
5659         /* Ensure size == 0. */
5660         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5661         if (!NT_STATUS_IS_OK(status)) {
5662                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5663                 return False;
5664         }
5665
5666         if (fsize != 0) {
5667                 printf("(3) file size != 0\n");
5668                 return False;
5669         }
5670         printf("finished open test 3\n");
5671
5672         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5673
5674         printf("Do ctemp tests\n");
5675         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
5676         if (!NT_STATUS_IS_OK(status)) {
5677                 printf("ctemp failed (%s)\n", nt_errstr(status));
5678                 return False;
5679         }
5680
5681         printf("ctemp gave path %s\n", tmp_path);
5682         status = cli_close(cli1, fnum1);
5683         if (!NT_STATUS_IS_OK(status)) {
5684                 printf("close of temp failed (%s)\n", nt_errstr(status));
5685         }
5686
5687         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5688         if (!NT_STATUS_IS_OK(status)) {
5689                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
5690         }
5691
5692         /* Test the non-io opens... */
5693
5694         if (!torture_open_connection(&cli2, 1)) {
5695                 return False;
5696         }
5697
5698         cli_setatr(cli2, fname, 0, 0);
5699         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5700
5701         smbXcli_conn_set_sockopt(cli2->conn, sockops);
5702
5703         printf("TEST #1 testing 2 non-io opens (no delete)\n");
5704         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5705                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5706                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5707         if (!NT_STATUS_IS_OK(status)) {
5708                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5709                 return False;
5710         }
5711
5712         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5713                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5714                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5715         if (!NT_STATUS_IS_OK(status)) {
5716                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5717                 return False;
5718         }
5719
5720         status = cli_close(cli1, fnum1);
5721         if (!NT_STATUS_IS_OK(status)) {
5722                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5723                 return False;
5724         }
5725
5726         status = cli_close(cli2, fnum2);
5727         if (!NT_STATUS_IS_OK(status)) {
5728                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5729                 return False;
5730         }
5731
5732         printf("non-io open test #1 passed.\n");
5733
5734         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5735
5736         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5737
5738         status = cli_ntcreate(cli1, fname, 0,
5739                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5740                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5741                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5742         if (!NT_STATUS_IS_OK(status)) {
5743                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5744                 return False;
5745         }
5746
5747         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5748                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5749                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5750         if (!NT_STATUS_IS_OK(status)) {
5751                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5752                 return False;
5753         }
5754
5755         status = cli_close(cli1, fnum1);
5756         if (!NT_STATUS_IS_OK(status)) {
5757                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5758                 return False;
5759         }
5760
5761         status = cli_close(cli2, fnum2);
5762         if (!NT_STATUS_IS_OK(status)) {
5763                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5764                 return False;
5765         }
5766
5767         printf("non-io open test #2 passed.\n");
5768
5769         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5770
5771         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5772
5773         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5774                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5775                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5776         if (!NT_STATUS_IS_OK(status)) {
5777                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5778                 return False;
5779         }
5780
5781         status = cli_ntcreate(cli2, fname, 0,
5782                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5783                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5784                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5785         if (!NT_STATUS_IS_OK(status)) {
5786                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5787                 return False;
5788         }
5789
5790         status = cli_close(cli1, fnum1);
5791         if (!NT_STATUS_IS_OK(status)) {
5792                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5793                 return False;
5794         }
5795
5796         status = cli_close(cli2, fnum2);
5797         if (!NT_STATUS_IS_OK(status)) {
5798                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5799                 return False;
5800         }
5801
5802         printf("non-io open test #3 passed.\n");
5803
5804         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5805
5806         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5807
5808         status = cli_ntcreate(cli1, fname, 0,
5809                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5810                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5811                                FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5812         if (!NT_STATUS_IS_OK(status)) {
5813                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5814                 return False;
5815         }
5816
5817         status = cli_ntcreate(cli2, fname, 0,
5818                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5819                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5820                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5821         if (NT_STATUS_IS_OK(status)) {
5822                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5823                 return False;
5824         }
5825
5826         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5827
5828         status = cli_close(cli1, fnum1);
5829         if (!NT_STATUS_IS_OK(status)) {
5830                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5831                 return False;
5832         }
5833
5834         printf("non-io open test #4 passed.\n");
5835
5836         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5837
5838         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5839
5840         status = cli_ntcreate(cli1, fname, 0,
5841                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5842                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5843                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5844         if (!NT_STATUS_IS_OK(status)) {
5845                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5846                 return False;
5847         }
5848
5849         status = cli_ntcreate(cli2, fname, 0,
5850                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5851                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5852                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5853         if (!NT_STATUS_IS_OK(status)) {
5854                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5855                 return False;
5856         }
5857
5858         status = cli_close(cli1, fnum1);
5859         if (!NT_STATUS_IS_OK(status)) {
5860                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5861                 return False;
5862         }
5863
5864         status = cli_close(cli2, fnum2);
5865         if (!NT_STATUS_IS_OK(status)) {
5866                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5867                 return False;
5868         }
5869
5870         printf("non-io open test #5 passed.\n");
5871
5872         printf("TEST #6 testing 1 non-io open, one io open\n");
5873
5874         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5875
5876         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5877                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5878                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5879         if (!NT_STATUS_IS_OK(status)) {
5880                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5881                 return False;
5882         }
5883
5884         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5885                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5886                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5887         if (!NT_STATUS_IS_OK(status)) {
5888                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5889                 return False;
5890         }
5891
5892         status = cli_close(cli1, fnum1);
5893         if (!NT_STATUS_IS_OK(status)) {
5894                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5895                 return False;
5896         }
5897
5898         status = cli_close(cli2, fnum2);
5899         if (!NT_STATUS_IS_OK(status)) {
5900                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5901                 return False;
5902         }
5903
5904         printf("non-io open test #6 passed.\n");
5905
5906         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5907
5908         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5909
5910         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5911                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5912                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5913         if (!NT_STATUS_IS_OK(status)) {
5914                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5915                 return False;
5916         }
5917
5918         status = cli_ntcreate(cli2, fname, 0,
5919                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5920                               FILE_ATTRIBUTE_NORMAL,
5921                               FILE_SHARE_READ|FILE_SHARE_DELETE,
5922                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5923         if (NT_STATUS_IS_OK(status)) {
5924                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5925                 return False;
5926         }
5927
5928         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5929
5930         status = cli_close(cli1, fnum1);
5931         if (!NT_STATUS_IS_OK(status)) {
5932                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5933                 return False;
5934         }
5935
5936         printf("non-io open test #7 passed.\n");
5937
5938         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5939
5940         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5941         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5942                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5943                                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5944         if (!NT_STATUS_IS_OK(status)) {
5945                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5946                 correct = false;
5947                 goto out;
5948         }
5949
5950         /* Write to ensure we have to update the file time. */
5951         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5952                               NULL);
5953         if (!NT_STATUS_IS_OK(status)) {
5954                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5955                 correct = false;
5956                 goto out;
5957         }
5958
5959         status = cli_close(cli1, fnum1);
5960         if (!NT_STATUS_IS_OK(status)) {
5961                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5962                 correct = false;
5963         }
5964
5965   out:
5966
5967         if (!torture_close_connection(cli1)) {
5968                 correct = False;
5969         }
5970         if (!torture_close_connection(cli2)) {
5971                 correct = False;
5972         }
5973
5974         return correct;
5975 }
5976
5977 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5978 {
5979         uint16_t major, minor;
5980         uint32_t caplow, caphigh;
5981         NTSTATUS status;
5982
5983         if (!SERVER_HAS_UNIX_CIFS(cli)) {
5984                 printf("Server doesn't support UNIX CIFS extensions.\n");
5985                 return NT_STATUS_NOT_SUPPORTED;
5986         }
5987
5988         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5989                                              &caphigh);
5990         if (!NT_STATUS_IS_OK(status)) {
5991                 printf("Server didn't return UNIX CIFS extensions: %s\n",
5992                        nt_errstr(status));
5993                 return status;
5994         }
5995
5996         status = cli_set_unix_extensions_capabilities(cli, major, minor,
5997                                                       caplow, caphigh);
5998         if (!NT_STATUS_IS_OK(status)) {
5999                 printf("Server doesn't support setting UNIX CIFS extensions: "
6000                        "%s.\n", nt_errstr(status));
6001                 return status;
6002         }
6003
6004         return NT_STATUS_OK;
6005 }
6006
6007 /*
6008   Test POSIX open /mkdir calls.
6009  */
6010 static bool run_simple_posix_open_test(int dummy)
6011 {
6012         static struct cli_state *cli1;
6013         const char *fname = "posix:file";
6014         const char *hname = "posix:hlink";
6015         const char *sname = "posix:symlink";
6016         const char *dname = "posix:dir";
6017         char buf[10];
6018         char namebuf[11];
6019         uint16_t fnum1 = (uint16_t)-1;
6020         SMB_STRUCT_STAT sbuf;
6021         bool correct = false;
6022         NTSTATUS status;
6023         size_t nread;
6024         const char *fname_windows = "windows_file";
6025         uint16_t fnum2 = (uint16_t)-1;
6026
6027         printf("Starting simple POSIX open test\n");
6028
6029         if (!torture_open_connection(&cli1, 0)) {
6030                 return false;
6031         }
6032
6033         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6034
6035         status = torture_setup_unix_extensions(cli1);
6036         if (!NT_STATUS_IS_OK(status)) {
6037                 return false;
6038         }
6039
6040         cli_setatr(cli1, fname, 0, 0);
6041         cli_posix_unlink(cli1, fname);
6042         cli_setatr(cli1, dname, 0, 0);
6043         cli_posix_rmdir(cli1, dname);
6044         cli_setatr(cli1, hname, 0, 0);
6045         cli_posix_unlink(cli1, hname);
6046         cli_setatr(cli1, sname, 0, 0);
6047         cli_posix_unlink(cli1, sname);
6048         cli_setatr(cli1, fname_windows, 0, 0);
6049         cli_posix_unlink(cli1, fname_windows);
6050
6051         /* Create a directory. */
6052         status = cli_posix_mkdir(cli1, dname, 0777);
6053         if (!NT_STATUS_IS_OK(status)) {
6054                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
6055                 goto out;
6056         }
6057
6058         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
6059                                 0600, &fnum1);
6060         if (!NT_STATUS_IS_OK(status)) {
6061                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6062                 goto out;
6063         }
6064
6065         /* Test ftruncate - set file size. */
6066         status = cli_ftruncate(cli1, fnum1, 1000);
6067         if (!NT_STATUS_IS_OK(status)) {
6068                 printf("ftruncate failed (%s)\n", nt_errstr(status));
6069                 goto out;
6070         }
6071
6072         /* Ensure st_size == 1000 */
6073         status = cli_posix_stat(cli1, fname, &sbuf);
6074         if (!NT_STATUS_IS_OK(status)) {
6075                 printf("stat failed (%s)\n", nt_errstr(status));
6076                 goto out;
6077         }
6078
6079         if (sbuf.st_ex_size != 1000) {
6080                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
6081                 goto out;
6082         }
6083
6084         /* Ensure st_mode == 0600 */
6085         if ((sbuf.st_ex_mode & 07777) != 0600) {
6086                 printf("posix_open - bad permissions 0%o != 0600\n",
6087                                 (unsigned int)(sbuf.st_ex_mode & 07777));
6088                 goto out;
6089         }
6090
6091         /* Test ftruncate - set file size back to zero. */
6092         status = cli_ftruncate(cli1, fnum1, 0);
6093         if (!NT_STATUS_IS_OK(status)) {
6094                 printf("ftruncate failed (%s)\n", nt_errstr(status));
6095                 goto out;
6096         }
6097
6098         status = cli_close(cli1, fnum1);
6099         if (!NT_STATUS_IS_OK(status)) {
6100                 printf("close failed (%s)\n", nt_errstr(status));
6101                 goto out;
6102         }
6103
6104         /* Now open the file again for read only. */
6105         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
6106         if (!NT_STATUS_IS_OK(status)) {
6107                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
6108                 goto out;
6109         }
6110
6111         /* Now unlink while open. */
6112         status = cli_posix_unlink(cli1, fname);
6113         if (!NT_STATUS_IS_OK(status)) {
6114                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
6115                 goto out;
6116         }
6117
6118         status = cli_close(cli1, fnum1);
6119         if (!NT_STATUS_IS_OK(status)) {
6120                 printf("close(2) failed (%s)\n", nt_errstr(status));
6121                 goto out;
6122         }
6123
6124         /* Ensure the file has gone. */
6125         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
6126         if (NT_STATUS_IS_OK(status)) {
6127                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
6128                 goto out;
6129         }
6130
6131         /* Create again to test open with O_TRUNC. */
6132         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
6133         if (!NT_STATUS_IS_OK(status)) {
6134                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6135                 goto out;
6136         }
6137
6138         /* Test ftruncate - set file size. */
6139         status = cli_ftruncate(cli1, fnum1, 1000);
6140         if (!NT_STATUS_IS_OK(status)) {
6141                 printf("ftruncate failed (%s)\n", nt_errstr(status));
6142                 goto out;
6143         }
6144
6145         /* Ensure st_size == 1000 */
6146         status = cli_posix_stat(cli1, fname, &sbuf);
6147         if (!NT_STATUS_IS_OK(status)) {
6148                 printf("stat failed (%s)\n", nt_errstr(status));
6149                 goto out;
6150         }
6151
6152         if (sbuf.st_ex_size != 1000) {
6153                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
6154                 goto out;
6155         }
6156
6157         status = cli_close(cli1, fnum1);
6158         if (!NT_STATUS_IS_OK(status)) {
6159                 printf("close(2) failed (%s)\n", nt_errstr(status));
6160                 goto out;
6161         }
6162
6163         /* Re-open with O_TRUNC. */
6164         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
6165         if (!NT_STATUS_IS_OK(status)) {
6166                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6167                 goto out;
6168         }
6169
6170         /* Ensure st_size == 0 */
6171         status = cli_posix_stat(cli1, fname, &sbuf);
6172         if (!NT_STATUS_IS_OK(status)) {
6173                 printf("stat failed (%s)\n", nt_errstr(status));
6174                 goto out;
6175         }
6176
6177         if (sbuf.st_ex_size != 0) {
6178                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
6179                 goto out;
6180         }
6181
6182         status = cli_close(cli1, fnum1);
6183         if (!NT_STATUS_IS_OK(status)) {
6184                 printf("close failed (%s)\n", nt_errstr(status));
6185                 goto out;
6186         }
6187
6188         status = cli_posix_unlink(cli1, fname);
6189         if (!NT_STATUS_IS_OK(status)) {
6190                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
6191                 goto out;
6192         }
6193
6194         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
6195         if (!NT_STATUS_IS_OK(status)) {
6196                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
6197                         dname, nt_errstr(status));
6198                 goto out;
6199         }
6200
6201         cli_close(cli1, fnum1);
6202
6203         /* What happens when we try and POSIX open a directory for write ? */
6204         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
6205         if (NT_STATUS_IS_OK(status)) {
6206                 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
6207                 goto out;
6208         } else {
6209                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
6210                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
6211                         goto out;
6212                 }
6213         }
6214
6215         /* Create the file. */
6216         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
6217                                 0600, &fnum1);
6218         if (!NT_STATUS_IS_OK(status)) {
6219                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6220                 goto out;
6221         }
6222
6223         /* Write some data into it. */
6224         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
6225                               NULL);
6226         if (!NT_STATUS_IS_OK(status)) {
6227                 printf("cli_write failed: %s\n", nt_errstr(status));
6228                 goto out;
6229         }
6230
6231         cli_close(cli1, fnum1);
6232
6233         /* Now create a hardlink. */
6234         status = cli_posix_hardlink(cli1, fname, hname);
6235         if (!NT_STATUS_IS_OK(status)) {
6236                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
6237                 goto out;
6238         }
6239
6240         /* Now create a symlink. */
6241         status = cli_posix_symlink(cli1, fname, sname);
6242         if (!NT_STATUS_IS_OK(status)) {
6243                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
6244                 goto out;
6245         }
6246
6247         /* Open the hardlink for read. */
6248         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
6249         if (!NT_STATUS_IS_OK(status)) {
6250                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
6251                 goto out;
6252         }
6253
6254         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
6255         if (!NT_STATUS_IS_OK(status)) {
6256                 printf("POSIX read of %s failed (%s)\n", hname,
6257                        nt_errstr(status));
6258                 goto out;
6259         } else if (nread != 10) {
6260                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
6261                        hname, (unsigned long)nread, 10);
6262                 goto out;
6263         }
6264
6265         if (memcmp(buf, "TEST DATA\n", 10)) {
6266                 printf("invalid data read from hardlink\n");
6267                 goto out;
6268         }
6269
6270         /* Do a POSIX lock/unlock. */
6271         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
6272         if (!NT_STATUS_IS_OK(status)) {
6273                 printf("POSIX lock failed %s\n", nt_errstr(status));
6274                 goto out;
6275         }
6276
6277         /* Punch a hole in the locked area. */
6278         status = cli_posix_unlock(cli1, fnum1, 10, 80);
6279         if (!NT_STATUS_IS_OK(status)) {
6280                 printf("POSIX unlock failed %s\n", nt_errstr(status));
6281                 goto out;
6282         }
6283
6284         cli_close(cli1, fnum1);
6285
6286         /* Open the symlink for read - this should fail. A POSIX
6287            client should not be doing opens on a symlink. */
6288         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
6289         if (NT_STATUS_IS_OK(status)) {
6290                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
6291                 goto out;
6292         } else {
6293                 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
6294                                 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
6295                         printf("POSIX open of %s should have failed "
6296                                 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
6297                                 "failed with %s instead.\n",
6298                                 sname, nt_errstr(status));
6299                         goto out;
6300                 }
6301         }
6302
6303         status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
6304         if (!NT_STATUS_IS_OK(status)) {
6305                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
6306                 goto out;
6307         }
6308
6309         if (strcmp(namebuf, fname) != 0) {
6310                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
6311                         sname, fname, namebuf);
6312                 goto out;
6313         }
6314
6315         status = cli_posix_rmdir(cli1, dname);
6316         if (!NT_STATUS_IS_OK(status)) {
6317                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
6318                 goto out;
6319         }
6320
6321         /* Check directory opens with a specific permission. */
6322         status = cli_posix_mkdir(cli1, dname, 0700);
6323         if (!NT_STATUS_IS_OK(status)) {
6324                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
6325                 goto out;
6326         }
6327
6328         /* Ensure st_mode == 0700 */
6329         status = cli_posix_stat(cli1, dname, &sbuf);
6330         if (!NT_STATUS_IS_OK(status)) {
6331                 printf("stat failed (%s)\n", nt_errstr(status));
6332                 goto out;
6333         }
6334
6335         if ((sbuf.st_ex_mode & 07777) != 0700) {
6336                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
6337                                 (unsigned int)(sbuf.st_ex_mode & 07777));
6338                 goto out;
6339         }
6340
6341         /*
6342          * Now create a Windows file, and attempt a POSIX unlink.
6343          * This should fail with a sharing violation but due to:
6344          *
6345          * [Bug 9571] Unlink after open causes smbd to panic
6346          *
6347          * ensure we've fixed the lock ordering violation.
6348          */
6349
6350         status = cli_ntcreate(cli1, fname_windows, 0,
6351                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
6352                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6353                         FILE_CREATE,
6354                         0x0, 0x0, &fnum2, NULL);
6355         if (!NT_STATUS_IS_OK(status)) {
6356                 printf("Windows create of %s failed (%s)\n", fname_windows,
6357                         nt_errstr(status));
6358                 goto out;
6359         }
6360
6361         /* Now try posix_unlink. */
6362         status = cli_posix_unlink(cli1, fname_windows);
6363         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6364                 printf("POSIX unlink of %s should fail "
6365                         "with NT_STATUS_SHARING_VIOLATION "
6366                         "got %s instead !\n",
6367                         fname_windows,
6368                         nt_errstr(status));
6369                 goto out;
6370         }
6371
6372         cli_close(cli1, fnum2);
6373
6374         printf("Simple POSIX open test passed\n");
6375         correct = true;
6376
6377   out:
6378
6379         if (fnum1 != (uint16_t)-1) {
6380                 cli_close(cli1, fnum1);
6381                 fnum1 = (uint16_t)-1;
6382         }
6383
6384         if (fnum2 != (uint16_t)-1) {
6385                 cli_close(cli1, fnum2);
6386                 fnum2 = (uint16_t)-1;
6387         }
6388
6389         cli_setatr(cli1, sname, 0, 0);
6390         cli_posix_unlink(cli1, sname);
6391         cli_setatr(cli1, hname, 0, 0);
6392         cli_posix_unlink(cli1, hname);
6393         cli_setatr(cli1, fname, 0, 0);
6394         cli_posix_unlink(cli1, fname);
6395         cli_setatr(cli1, dname, 0, 0);
6396         cli_posix_rmdir(cli1, dname);
6397         cli_setatr(cli1, fname_windows, 0, 0);
6398         cli_posix_unlink(cli1, fname_windows);
6399
6400         if (!torture_close_connection(cli1)) {
6401                 correct = false;
6402         }
6403
6404         return correct;
6405 }
6406
6407 /*
6408   Test POSIX and Windows ACLs are rejected on symlinks.
6409  */
6410 static bool run_acl_symlink_test(int dummy)
6411 {
6412         static struct cli_state *cli;
6413         const char *fname = "posix_file";
6414         const char *sname = "posix_symlink";
6415         uint16_t fnum = (uint16_t)-1;
6416         bool correct = false;
6417         NTSTATUS status;
6418         char *posix_acl = NULL;
6419         size_t posix_acl_len = 0;
6420         char *posix_acl_sym = NULL;
6421         size_t posix_acl_len_sym = 0;
6422         struct security_descriptor *sd = NULL;
6423         struct security_descriptor *sd_sym = NULL;
6424         TALLOC_CTX *frame = NULL;
6425
6426         frame = talloc_stackframe();
6427
6428         printf("Starting acl symlink test\n");
6429
6430         if (!torture_open_connection(&cli, 0)) {
6431                 TALLOC_FREE(frame);
6432                 return false;
6433         }
6434
6435         smbXcli_conn_set_sockopt(cli->conn, sockops);
6436
6437         status = torture_setup_unix_extensions(cli);
6438         if (!NT_STATUS_IS_OK(status)) {
6439                 TALLOC_FREE(frame);
6440                 return false;
6441         }
6442
6443         cli_setatr(cli, fname, 0, 0);
6444         cli_posix_unlink(cli, fname);
6445         cli_setatr(cli, sname, 0, 0);
6446         cli_posix_unlink(cli, sname);
6447
6448         status = cli_ntcreate(cli,
6449                         fname,
6450                         0,
6451                         READ_CONTROL_ACCESS,
6452                         0,
6453                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6454                         FILE_CREATE,
6455                         0x0,
6456                         0x0,
6457                         &fnum,
6458                         NULL);
6459
6460         if (!NT_STATUS_IS_OK(status)) {
6461                 printf("cli_ntcreate of %s failed (%s)\n",
6462                         fname,
6463                         nt_errstr(status));
6464                 goto out;
6465         }
6466
6467         /* Get the Windows ACL on the file. */
6468         status = cli_query_secdesc(cli,
6469                                 fnum,
6470                                 frame,
6471                                 &sd);
6472         if (!NT_STATUS_IS_OK(status)) {
6473                 printf("cli_query_secdesc failed (%s)\n",
6474                         nt_errstr(status));
6475                 goto out;
6476         }
6477
6478         /* Get the POSIX ACL on the file. */
6479         status = cli_posix_getacl(cli,
6480                                 fname,
6481                                 frame,
6482                                 &posix_acl_len,
6483                                 &posix_acl);
6484
6485         if (!NT_STATUS_IS_OK(status)) {
6486                 printf("cli_posix_getacl failed (%s)\n",
6487                         nt_errstr(status));
6488                 goto out;
6489         }
6490
6491         status = cli_close(cli, fnum);
6492         if (!NT_STATUS_IS_OK(status)) {
6493                 printf("close failed (%s)\n", nt_errstr(status));
6494                 goto out;
6495         }
6496         fnum = (uint16_t)-1;
6497
6498         /* Now create a symlink. */
6499         status = cli_posix_symlink(cli, fname, sname);
6500         if (!NT_STATUS_IS_OK(status)) {
6501                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
6502                         sname,
6503                         fname,
6504                         nt_errstr(status));
6505                 goto out;
6506         }
6507
6508         /* Open a handle on the symlink. */
6509         status = cli_ntcreate(cli,
6510                         sname,
6511                         0,
6512                         READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
6513                         0,
6514                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6515                         FILE_OPEN,
6516                         0x0,
6517                         0x0,
6518                         &fnum,
6519                         NULL);
6520
6521         if (!NT_STATUS_IS_OK(status)) {
6522                 printf("cli_posix_open of %s failed (%s)\n",
6523                         sname,
6524                         nt_errstr(status));
6525                 goto out;
6526         }
6527
6528         /* Get the Windows ACL on the symlink handle. Should fail */
6529         status = cli_query_secdesc(cli,
6530                                 fnum,
6531                                 frame,
6532                                 &sd_sym);
6533
6534         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6535                 printf("cli_query_secdesc on a symlink gave %s. "
6536                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6537                         nt_errstr(status));
6538                 goto out;
6539         }
6540
6541         /* Get the POSIX ACL on the symlink pathname. Should fail. */
6542         status = cli_posix_getacl(cli,
6543                                 sname,
6544                                 frame,
6545                                 &posix_acl_len_sym,
6546                                 &posix_acl_sym);
6547
6548         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6549                 printf("cli_posix_getacl on a symlink gave %s. "
6550                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6551                         nt_errstr(status));
6552                 goto out;
6553         }
6554
6555         /* Set the Windows ACL on the symlink handle. Should fail */
6556         status = cli_set_security_descriptor(cli,
6557                                 fnum,
6558                                 SECINFO_DACL,
6559                                 sd);
6560
6561         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6562                 printf("cli_query_secdesc on a symlink gave %s. "
6563                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6564                         nt_errstr(status));
6565                 goto out;
6566         }
6567
6568         /* Set the POSIX ACL on the symlink pathname. Should fail. */
6569         status = cli_posix_setacl(cli,
6570                                 sname,
6571                                 posix_acl,
6572                                 posix_acl_len);
6573
6574         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6575                 printf("cli_posix_getacl on a symlink gave %s. "
6576                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6577                         nt_errstr(status));
6578                 goto out;
6579         }
6580
6581         printf("ACL symlink test passed\n");
6582         correct = true;
6583
6584   out:
6585
6586         if (fnum != (uint16_t)-1) {
6587                 cli_close(cli, fnum);
6588                 fnum = (uint16_t)-1;
6589         }
6590
6591         cli_setatr(cli, sname, 0, 0);
6592         cli_posix_unlink(cli, sname);
6593         cli_setatr(cli, fname, 0, 0);
6594         cli_posix_unlink(cli, fname);
6595
6596         if (!torture_close_connection(cli)) {
6597                 correct = false;
6598         }
6599
6600         TALLOC_FREE(frame);
6601         return correct;
6602 }
6603
6604 /*
6605   Test POSIX can delete a file containing streams.
6606  */
6607 static bool run_posix_stream_delete(int dummy)
6608 {
6609         struct cli_state *cli1 = NULL;
6610         struct cli_state *cli2 = NULL;
6611         const char *fname = "streamfile";
6612         const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
6613         uint16_t fnum1 = (uint16_t)-1;
6614         bool correct = false;
6615         NTSTATUS status;
6616         TALLOC_CTX *frame = NULL;
6617
6618         frame = talloc_stackframe();
6619
6620         printf("Starting POSIX stream delete test\n");
6621
6622         if (!torture_open_connection(&cli1, 0) ||
6623                         !torture_open_connection(&cli2, 1)) {
6624                 TALLOC_FREE(frame);
6625                 return false;
6626         }
6627
6628         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6629         smbXcli_conn_set_sockopt(cli2->conn, sockops);
6630
6631         status = torture_setup_unix_extensions(cli2);
6632         if (!NT_STATUS_IS_OK(status)) {
6633                 goto out;
6634         }
6635
6636         cli_setatr(cli1, fname, 0, 0);
6637         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6638
6639         /* Create the file. */
6640         status = cli_ntcreate(cli1,
6641                         fname,
6642                         0,
6643                         READ_CONTROL_ACCESS,
6644                         0,
6645                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6646                         FILE_CREATE,
6647                         0x0,
6648                         0x0,
6649                         &fnum1,
6650                         NULL);
6651
6652         if (!NT_STATUS_IS_OK(status)) {
6653                 printf("cli_ntcreate of %s failed (%s)\n",
6654                         fname,
6655                         nt_errstr(status));
6656                 goto out;
6657         }
6658
6659         status = cli_close(cli1, fnum1);
6660         if (!NT_STATUS_IS_OK(status)) {
6661                 printf("cli_close of %s failed (%s)\n",
6662                         fname,
6663                         nt_errstr(status));
6664                 goto out;
6665         }
6666         fnum1 = (uint16_t)-1;
6667
6668         /* Now create the stream. */
6669         status = cli_ntcreate(cli1,
6670                         stream_fname,
6671                         0,
6672                         FILE_WRITE_DATA,
6673                         0,
6674                         FILE_SHARE_READ|FILE_SHARE_WRITE,
6675                         FILE_CREATE,
6676                         0x0,
6677                         0x0,
6678                         &fnum1,
6679                         NULL);
6680
6681         if (!NT_STATUS_IS_OK(status)) {
6682                 printf("cli_ntcreate of %s failed (%s)\n",
6683                         stream_fname,
6684                         nt_errstr(status));
6685                 goto out;
6686         }
6687
6688         /* Leave the stream handle open... */
6689
6690         /* POSIX unlink should fail. */
6691         status = cli_posix_unlink(cli2, fname);
6692         if (NT_STATUS_IS_OK(status)) {
6693                 printf("cli_posix_unlink of %s succeeded, should have failed\n",
6694                         fname);
6695                 goto out;
6696         }
6697
6698         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6699                 printf("cli_posix_unlink of %s failed with (%s) "
6700                         "should have been NT_STATUS_SHARING_VIOLATION\n",
6701                         fname,
6702                         nt_errstr(status));
6703                 goto out;
6704         }
6705
6706         /* Close the stream handle. */
6707         status = cli_close(cli1, fnum1);
6708         if (!NT_STATUS_IS_OK(status)) {
6709                 printf("cli_close of %s failed (%s)\n",
6710                         stream_fname,
6711                         nt_errstr(status));
6712                 goto out;
6713         }
6714         fnum1 = (uint16_t)-1;
6715
6716         /* POSIX unlink after stream handle closed should succeed. */
6717         status = cli_posix_unlink(cli2, fname);
6718         if (!NT_STATUS_IS_OK(status)) {
6719                 printf("cli_posix_unlink of %s failed (%s)\n",
6720                         fname,
6721                         nt_errstr(status));
6722                 goto out;
6723         }
6724
6725         printf("POSIX stream delete test passed\n");
6726         correct = true;
6727
6728   out:
6729
6730         if (fnum1 != (uint16_t)-1) {
6731                 cli_close(cli1, fnum1);
6732                 fnum1 = (uint16_t)-1;
6733         }
6734
6735         cli_setatr(cli1, fname, 0, 0);
6736         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6737
6738         if (!torture_close_connection(cli1)) {
6739                 correct = false;
6740         }
6741         if (!torture_close_connection(cli2)) {
6742                 correct = false;
6743         }
6744
6745         TALLOC_FREE(frame);
6746         return correct;
6747 }
6748
6749 /*
6750   Test setting EA's are rejected on symlinks.
6751  */
6752 static bool run_ea_symlink_test(int dummy)
6753 {
6754         static struct cli_state *cli;
6755         const char *fname = "posix_file_ea";
6756         const char *sname = "posix_symlink_ea";
6757         const char *ea_name = "testea_name";
6758         const char *ea_value = "testea_value";
6759         uint16_t fnum = (uint16_t)-1;
6760         bool correct = false;
6761         NTSTATUS status;
6762         size_t i, num_eas;
6763         struct ea_struct *eas = NULL;
6764         TALLOC_CTX *frame = NULL;
6765
6766         frame = talloc_stackframe();
6767
6768         printf("Starting EA symlink test\n");
6769
6770         if (!torture_open_connection(&cli, 0)) {
6771                 TALLOC_FREE(frame);
6772                 return false;
6773         }
6774
6775         smbXcli_conn_set_sockopt(cli->conn, sockops);
6776
6777         status = torture_setup_unix_extensions(cli);
6778         if (!NT_STATUS_IS_OK(status)) {
6779                 TALLOC_FREE(frame);
6780                 return false;
6781         }
6782
6783         cli_setatr(cli, fname, 0, 0);
6784         cli_posix_unlink(cli, fname);
6785         cli_setatr(cli, sname, 0, 0);
6786         cli_posix_unlink(cli, sname);
6787
6788         status = cli_ntcreate(cli,
6789                         fname,
6790                         0,
6791                         READ_CONTROL_ACCESS,
6792                         0,
6793                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6794                         FILE_CREATE,
6795                         0x0,
6796                         0x0,
6797                         &fnum,
6798                         NULL);
6799
6800         if (!NT_STATUS_IS_OK(status)) {
6801                 printf("cli_ntcreate of %s failed (%s)\n",
6802                         fname,
6803                         nt_errstr(status));
6804                 goto out;
6805         }
6806
6807         status = cli_close(cli, fnum);
6808         if (!NT_STATUS_IS_OK(status)) {
6809                 printf("close failed (%s)\n",
6810                         nt_errstr(status));
6811                 goto out;
6812         }
6813         fnum = (uint16_t)-1;
6814
6815         /* Set an EA on the path. */
6816         status = cli_set_ea_path(cli,
6817                                 fname,
6818                                 ea_name,
6819                                 ea_value,
6820                                 strlen(ea_value)+1);
6821
6822         if (!NT_STATUS_IS_OK(status)) {
6823                 printf("cli_set_ea_path failed (%s)\n",
6824                         nt_errstr(status));
6825                 goto out;
6826         }
6827
6828         /* Now create a symlink. */
6829         status = cli_posix_symlink(cli, fname, sname);
6830         if (!NT_STATUS_IS_OK(status)) {
6831                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
6832                         sname,
6833                         fname,
6834                         nt_errstr(status));
6835                 goto out;
6836         }
6837
6838         /* Get the EA list on the path. Should return value set. */
6839         status = cli_get_ea_list_path(cli,
6840                                 fname,
6841                                 frame,
6842                                 &num_eas,
6843                                 &eas);
6844
6845         if (!NT_STATUS_IS_OK(status)) {
6846                 printf("cli_get_ea_list_path failed (%s)\n",
6847                         nt_errstr(status));
6848                 goto out;
6849         }
6850
6851         /* Ensure the EA we set is there. */
6852         for (i=0; i<num_eas; i++) {
6853                 if (strcmp(eas[i].name, ea_name) == 0 &&
6854                                 eas[i].value.length == strlen(ea_value)+1 &&
6855                                 memcmp(eas[i].value.data,
6856                                         ea_value,
6857                                         eas[i].value.length) == 0) {
6858                         break;
6859                 }
6860         }
6861
6862         if (i == num_eas) {
6863                 printf("Didn't find EA on pathname %s\n",
6864                         fname);
6865                 goto out;
6866         }
6867
6868         num_eas = 0;
6869         TALLOC_FREE(eas);
6870
6871         /* Get the EA list on the symlink. Should return empty list. */
6872         status = cli_get_ea_list_path(cli,
6873                                 sname,
6874                                 frame,
6875                                 &num_eas,
6876                                 &eas);
6877
6878         if (!NT_STATUS_IS_OK(status)) {
6879                 printf("cli_get_ea_list_path failed (%s)\n",
6880                         nt_errstr(status));
6881                 goto out;
6882         }
6883
6884         if (num_eas != 0) {
6885                 printf("cli_get_ea_list_path failed (%s)\n",
6886                         nt_errstr(status));
6887                 goto out;
6888         }
6889
6890         /* Set an EA on the symlink. Should fail. */
6891         status = cli_set_ea_path(cli,
6892                                 sname,
6893                                 ea_name,
6894                                 ea_value,
6895                                 strlen(ea_value)+1);
6896
6897         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6898                 printf("cli_set_ea_path on a symlink gave %s. "
6899                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6900                         nt_errstr(status));
6901                 goto out;
6902         }
6903
6904         printf("EA symlink test passed\n");
6905         correct = true;
6906
6907   out:
6908
6909         if (fnum != (uint16_t)-1) {
6910                 cli_close(cli, fnum);
6911                 fnum = (uint16_t)-1;
6912         }
6913
6914         cli_setatr(cli, sname, 0, 0);
6915         cli_posix_unlink(cli, sname);
6916         cli_setatr(cli, fname, 0, 0);
6917         cli_posix_unlink(cli, fname);
6918
6919         if (!torture_close_connection(cli)) {
6920                 correct = false;
6921         }
6922
6923         TALLOC_FREE(frame);
6924         return correct;
6925 }
6926
6927 /*
6928   Test POSIX locks are OFD-locks.
6929  */
6930 static bool run_posix_ofd_lock_test(int dummy)
6931 {
6932         static struct cli_state *cli;
6933         const char *fname = "posix_file";
6934         uint16_t fnum1 = (uint16_t)-1;
6935         uint16_t fnum2 = (uint16_t)-1;
6936         bool correct = false;
6937         NTSTATUS status;
6938         TALLOC_CTX *frame = NULL;
6939
6940         frame = talloc_stackframe();
6941
6942         printf("Starting POSIX ofd-lock test\n");
6943
6944         if (!torture_open_connection(&cli, 0)) {
6945                 TALLOC_FREE(frame);
6946                 return false;
6947         }
6948
6949         smbXcli_conn_set_sockopt(cli->conn, sockops);
6950
6951         status = torture_setup_unix_extensions(cli);
6952         if (!NT_STATUS_IS_OK(status)) {
6953                 TALLOC_FREE(frame);
6954                 return false;
6955         }
6956
6957         cli_setatr(cli, fname, 0, 0);
6958         cli_posix_unlink(cli, fname);
6959
6960         /* Open the file twice. */
6961         status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
6962                                 0600, &fnum1);
6963         if (!NT_STATUS_IS_OK(status)) {
6964                 printf("First POSIX open of %s failed\n", fname);
6965                 goto out;
6966         }
6967
6968         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
6969         if (!NT_STATUS_IS_OK(status)) {
6970                 printf("First POSIX open of %s failed\n", fname);
6971                 goto out;
6972         }
6973
6974         /* Set a 0-50 lock on fnum1. */
6975         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
6976         if (!NT_STATUS_IS_OK(status)) {
6977                 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
6978                 goto out;
6979         }
6980
6981         /* Set a 60-100 lock on fnum2. */
6982         status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
6983         if (!NT_STATUS_IS_OK(status)) {
6984                 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
6985                 goto out;
6986         }
6987
6988         /* close fnum1 - 0-50 lock should go away. */
6989         status = cli_close(cli, fnum1);
6990         if (!NT_STATUS_IS_OK(status)) {
6991                 printf("close failed (%s)\n",
6992                         nt_errstr(status));
6993                 goto out;
6994         }
6995         fnum1 = (uint16_t)-1;
6996
6997         /* Change the lock context. */
6998         cli_setpid(cli, cli_getpid(cli) + 1);
6999
7000         /* Re-open fnum1. */
7001         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
7002         if (!NT_STATUS_IS_OK(status)) {
7003                 printf("Third POSIX open of %s failed\n", fname);
7004                 goto out;
7005         }
7006
7007         /* 60-100 lock should still be there. */
7008         status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
7009         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
7010                 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
7011                 goto out;
7012         }
7013
7014         /* 0-50 lock should be gone. */
7015         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
7016         if (!NT_STATUS_IS_OK(status)) {
7017                 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
7018                 goto out;
7019         }
7020
7021         printf("POSIX OFD lock test passed\n");
7022         correct = true;
7023
7024   out:
7025
7026         if (fnum1 != (uint16_t)-1) {
7027                 cli_close(cli, fnum1);
7028                 fnum1 = (uint16_t)-1;
7029         }
7030         if (fnum2 != (uint16_t)-1) {
7031                 cli_close(cli, fnum2);
7032                 fnum2 = (uint16_t)-1;
7033         }
7034
7035         cli_setatr(cli, fname, 0, 0);
7036         cli_posix_unlink(cli, fname);
7037
7038         if (!torture_close_connection(cli)) {
7039                 correct = false;
7040         }
7041
7042         TALLOC_FREE(frame);
7043         return correct;
7044 }
7045
7046 static uint32_t open_attrs_table[] = {
7047                 FILE_ATTRIBUTE_NORMAL,
7048                 FILE_ATTRIBUTE_ARCHIVE,
7049                 FILE_ATTRIBUTE_READONLY,
7050                 FILE_ATTRIBUTE_HIDDEN,
7051                 FILE_ATTRIBUTE_SYSTEM,
7052
7053                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
7054                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
7055                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
7056                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
7057                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
7058                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
7059
7060                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
7061                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
7062                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
7063                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
7064 };
7065
7066 struct trunc_open_results {
7067         unsigned int num;
7068         uint32_t init_attr;
7069         uint32_t trunc_attr;
7070         uint32_t result_attr;
7071 };
7072
7073 static struct trunc_open_results attr_results[] = {
7074         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
7075         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
7076         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
7077         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
7078         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
7079         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
7080         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7081         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7082         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
7083         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7084         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7085         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
7086         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7087         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7088         { 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 },
7089         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7090         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7091         { 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 },
7092         { 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 },
7093         { 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 },
7094         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7095         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7096         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
7097         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7098         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7099         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
7100 };
7101
7102 static bool run_openattrtest(int dummy)
7103 {
7104         static struct cli_state *cli1;
7105         const char *fname = "\\openattr.file";
7106         uint16_t fnum1;
7107         bool correct = True;
7108         uint16_t attr;
7109         unsigned int i, j, k, l;
7110         NTSTATUS status;
7111
7112         printf("starting open attr test\n");
7113
7114         if (!torture_open_connection(&cli1, 0)) {
7115                 return False;
7116         }
7117
7118         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7119
7120         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
7121                 cli_setatr(cli1, fname, 0, 0);
7122                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7123
7124                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
7125                                        open_attrs_table[i], FILE_SHARE_NONE,
7126                                        FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7127                 if (!NT_STATUS_IS_OK(status)) {
7128                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
7129                         return False;
7130                 }
7131
7132                 status = cli_close(cli1, fnum1);
7133                 if (!NT_STATUS_IS_OK(status)) {
7134                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
7135                         return False;
7136                 }
7137
7138                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
7139                         status = cli_ntcreate(cli1, fname, 0,
7140                                               FILE_READ_DATA|FILE_WRITE_DATA,
7141                                               open_attrs_table[j],
7142                                               FILE_SHARE_NONE, FILE_OVERWRITE,
7143                                               0, 0, &fnum1, NULL);
7144                         if (!NT_STATUS_IS_OK(status)) {
7145                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
7146                                         if (attr_results[l].num == k) {
7147                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
7148                                                                 k, open_attrs_table[i],
7149                                                                 open_attrs_table[j],
7150                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
7151                                                 correct = False;
7152                                         }
7153                                 }
7154
7155                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7156                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
7157                                                         k, open_attrs_table[i], open_attrs_table[j],
7158                                                         nt_errstr(status));
7159                                         correct = False;
7160                                 }
7161 #if 0
7162                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
7163 #endif
7164                                 k++;
7165                                 continue;
7166                         }
7167
7168                         status = cli_close(cli1, fnum1);
7169                         if (!NT_STATUS_IS_OK(status)) {
7170                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
7171                                 return False;
7172                         }
7173
7174                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
7175                         if (!NT_STATUS_IS_OK(status)) {
7176                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
7177                                 return False;
7178                         }
7179
7180 #if 0
7181                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
7182                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
7183 #endif
7184
7185                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
7186                                 if (attr_results[l].num == k) {
7187                                         if (attr != attr_results[l].result_attr ||
7188                                                         open_attrs_table[i] != attr_results[l].init_attr ||
7189                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
7190                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
7191                                                 open_attrs_table[i],
7192                                                 open_attrs_table[j],
7193                                                 (unsigned int)attr,
7194                                                 attr_results[l].result_attr);
7195                                                 correct = False;
7196                                         }
7197                                         break;
7198                                 }
7199                         }
7200                         k++;
7201                 }
7202         }
7203
7204         cli_setatr(cli1, fname, 0, 0);
7205         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7206
7207         printf("open attr test %s.\n", correct ? "passed" : "failed");
7208
7209         if (!torture_close_connection(cli1)) {
7210                 correct = False;
7211         }
7212         return correct;
7213 }
7214
7215 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
7216                     const char *name, void *state)
7217 {
7218         int *matched = (int *)state;
7219         if (matched != NULL) {
7220                 *matched += 1;
7221         }
7222         return NT_STATUS_OK;
7223 }
7224
7225 /*
7226   test directory listing speed
7227  */
7228 static bool run_dirtest(int dummy)
7229 {
7230         int i;
7231         static struct cli_state *cli;
7232         uint16_t fnum;
7233         struct timeval core_start;
7234         bool correct = True;
7235         int matched;
7236
7237         printf("starting directory test\n");
7238
7239         if (!torture_open_connection(&cli, 0)) {
7240                 return False;
7241         }
7242
7243         smbXcli_conn_set_sockopt(cli->conn, sockops);
7244
7245         srandom(0);
7246         for (i=0;i<torture_numops;i++) {
7247                 fstring fname;
7248                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
7249                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
7250                         fprintf(stderr,"Failed to open %s\n", fname);
7251                         return False;
7252                 }
7253                 cli_close(cli, fnum);
7254         }
7255
7256         core_start = timeval_current();
7257
7258         matched = 0;
7259         cli_list(cli, "a*.*", 0, list_fn, &matched);
7260         printf("Matched %d\n", matched);
7261
7262         matched = 0;
7263         cli_list(cli, "b*.*", 0, list_fn, &matched);
7264         printf("Matched %d\n", matched);
7265
7266         matched = 0;
7267         cli_list(cli, "xyzabc", 0, list_fn, &matched);
7268         printf("Matched %d\n", matched);
7269
7270         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
7271
7272         srandom(0);
7273         for (i=0;i<torture_numops;i++) {
7274                 fstring fname;
7275                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
7276                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7277         }
7278
7279         if (!torture_close_connection(cli)) {
7280                 correct = False;
7281         }
7282
7283         printf("finished dirtest\n");
7284
7285         return correct;
7286 }
7287
7288 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
7289                    void *state)
7290 {
7291         struct cli_state *pcli = (struct cli_state *)state;
7292         fstring fname;
7293         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
7294
7295         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7296                 return NT_STATUS_OK;
7297
7298         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7299                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
7300                         printf("del_fn: failed to rmdir %s\n,", fname );
7301         } else {
7302                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
7303                         printf("del_fn: failed to unlink %s\n,", fname );
7304         }
7305         return NT_STATUS_OK;
7306 }
7307
7308
7309 /*
7310   sees what IOCTLs are supported
7311  */
7312 bool torture_ioctl_test(int dummy)
7313 {
7314         static struct cli_state *cli;
7315         uint16_t device, function;
7316         uint16_t fnum;
7317         const char *fname = "\\ioctl.dat";
7318         DATA_BLOB blob;
7319         NTSTATUS status;
7320
7321         if (!torture_open_connection(&cli, 0)) {
7322                 return False;
7323         }
7324
7325         printf("starting ioctl test\n");
7326
7327         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7328
7329         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7330         if (!NT_STATUS_IS_OK(status)) {
7331                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7332                 return False;
7333         }
7334
7335         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
7336         printf("ioctl device info: %s\n", nt_errstr(status));
7337
7338         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
7339         printf("ioctl job info: %s\n", nt_errstr(status));
7340
7341         for (device=0;device<0x100;device++) {
7342                 printf("ioctl test with device = 0x%x\n", device);
7343                 for (function=0;function<0x100;function++) {
7344                         uint32_t code = (device<<16) | function;
7345
7346                         status = cli_raw_ioctl(cli, fnum, code, &blob);
7347
7348                         if (NT_STATUS_IS_OK(status)) {
7349                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
7350                                        (int)blob.length);
7351                                 data_blob_free(&blob);
7352                         }
7353                 }
7354         }
7355
7356         if (!torture_close_connection(cli)) {
7357                 return False;
7358         }
7359
7360         return True;
7361 }
7362
7363
7364 /*
7365   tries varients of chkpath
7366  */
7367 bool torture_chkpath_test(int dummy)
7368 {
7369         static struct cli_state *cli;
7370         uint16_t fnum;
7371         bool ret;
7372         NTSTATUS status;
7373
7374         if (!torture_open_connection(&cli, 0)) {
7375                 return False;
7376         }
7377
7378         printf("starting chkpath test\n");
7379
7380         /* cleanup from an old run */
7381         cli_rmdir(cli, "\\chkpath.dir\\dir2");
7382         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7383         cli_rmdir(cli, "\\chkpath.dir");
7384
7385         status = cli_mkdir(cli, "\\chkpath.dir");
7386         if (!NT_STATUS_IS_OK(status)) {
7387                 printf("mkdir1 failed : %s\n", nt_errstr(status));
7388                 return False;
7389         }
7390
7391         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
7392         if (!NT_STATUS_IS_OK(status)) {
7393                 printf("mkdir2 failed : %s\n", nt_errstr(status));
7394                 return False;
7395         }
7396
7397         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
7398                           DENY_NONE, &fnum);
7399         if (!NT_STATUS_IS_OK(status)) {
7400                 printf("open1 failed (%s)\n", nt_errstr(status));
7401                 return False;
7402         }
7403         cli_close(cli, fnum);
7404
7405         status = cli_chkpath(cli, "\\chkpath.dir");
7406         if (!NT_STATUS_IS_OK(status)) {
7407                 printf("chkpath1 failed: %s\n", nt_errstr(status));
7408                 ret = False;
7409         }
7410
7411         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
7412         if (!NT_STATUS_IS_OK(status)) {
7413                 printf("chkpath2 failed: %s\n", nt_errstr(status));
7414                 ret = False;
7415         }
7416
7417         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
7418         if (!NT_STATUS_IS_OK(status)) {
7419                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
7420                                   NT_STATUS_NOT_A_DIRECTORY);
7421         } else {
7422                 printf("* chkpath on a file should fail\n");
7423                 ret = False;
7424         }
7425
7426         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
7427         if (!NT_STATUS_IS_OK(status)) {
7428                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
7429                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
7430         } else {
7431                 printf("* chkpath on a non existent file should fail\n");
7432                 ret = False;
7433         }
7434
7435         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
7436         if (!NT_STATUS_IS_OK(status)) {
7437                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
7438                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
7439         } else {
7440                 printf("* chkpath on a non existent component should fail\n");
7441                 ret = False;
7442         }
7443
7444         cli_rmdir(cli, "\\chkpath.dir\\dir2");
7445         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7446         cli_rmdir(cli, "\\chkpath.dir");
7447
7448         if (!torture_close_connection(cli)) {
7449                 return False;
7450         }
7451
7452         return ret;
7453 }
7454
7455 static bool run_eatest(int dummy)
7456 {
7457         static struct cli_state *cli;
7458         const char *fname = "\\eatest.txt";
7459         bool correct = True;
7460         uint16_t fnum;
7461         int i;
7462         size_t num_eas;
7463         struct ea_struct *ea_list = NULL;
7464         TALLOC_CTX *mem_ctx = talloc_init("eatest");
7465         NTSTATUS status;
7466
7467         printf("starting eatest\n");
7468
7469         if (!torture_open_connection(&cli, 0)) {
7470                 talloc_destroy(mem_ctx);
7471                 return False;
7472         }
7473
7474         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7475
7476         status = cli_ntcreate(cli, fname, 0,
7477                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
7478                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
7479                               0x4044, 0, &fnum, NULL);
7480         if (!NT_STATUS_IS_OK(status)) {
7481                 printf("open failed - %s\n", nt_errstr(status));
7482                 talloc_destroy(mem_ctx);
7483                 return False;
7484         }
7485
7486         for (i = 0; i < 10; i++) {
7487                 fstring ea_name, ea_val;
7488
7489                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
7490                 memset(ea_val, (char)i+1, i+1);
7491                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
7492                 if (!NT_STATUS_IS_OK(status)) {
7493                         printf("ea_set of name %s failed - %s\n", ea_name,
7494                                nt_errstr(status));
7495                         talloc_destroy(mem_ctx);
7496                         return False;
7497                 }
7498         }
7499
7500         cli_close(cli, fnum);
7501         for (i = 0; i < 10; i++) {
7502                 fstring ea_name, ea_val;
7503
7504                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
7505                 memset(ea_val, (char)i+1, i+1);
7506                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
7507                 if (!NT_STATUS_IS_OK(status)) {
7508                         printf("ea_set of name %s failed - %s\n", ea_name,
7509                                nt_errstr(status));
7510                         talloc_destroy(mem_ctx);
7511                         return False;
7512                 }
7513         }
7514
7515         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
7516         if (!NT_STATUS_IS_OK(status)) {
7517                 printf("ea_get list failed - %s\n", nt_errstr(status));
7518                 correct = False;
7519         }
7520
7521         printf("num_eas = %d\n", (int)num_eas);
7522
7523         if (num_eas != 20) {
7524                 printf("Should be 20 EA's stored... failing.\n");
7525                 correct = False;
7526         }
7527
7528         for (i = 0; i < num_eas; i++) {
7529                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
7530                 dump_data(0, ea_list[i].value.data,
7531                           ea_list[i].value.length);
7532         }
7533
7534         /* Setting EA's to zero length deletes them. Test this */
7535         printf("Now deleting all EA's - case indepenent....\n");
7536
7537 #if 1
7538         cli_set_ea_path(cli, fname, "", "", 0);
7539 #else
7540         for (i = 0; i < 20; i++) {
7541                 fstring ea_name;
7542                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
7543                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
7544                 if (!NT_STATUS_IS_OK(status)) {
7545                         printf("ea_set of name %s failed - %s\n", ea_name,
7546                                nt_errstr(status));
7547                         talloc_destroy(mem_ctx);
7548                         return False;
7549                 }
7550         }
7551 #endif
7552
7553         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
7554         if (!NT_STATUS_IS_OK(status)) {
7555                 printf("ea_get list failed - %s\n", nt_errstr(status));
7556                 correct = False;
7557         }
7558
7559         printf("num_eas = %d\n", (int)num_eas);
7560         for (i = 0; i < num_eas; i++) {
7561                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
7562                 dump_data(0, ea_list[i].value.data,
7563                           ea_list[i].value.length);
7564         }
7565
7566         if (num_eas != 0) {
7567                 printf("deleting EA's failed.\n");
7568                 correct = False;
7569         }
7570
7571         /* Try and delete a non existent EA. */
7572         status = cli_set_ea_path(cli, fname, "foo", "", 0);
7573         if (!NT_STATUS_IS_OK(status)) {
7574                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
7575                        nt_errstr(status));
7576                 correct = False;
7577         }
7578
7579         talloc_destroy(mem_ctx);
7580         if (!torture_close_connection(cli)) {
7581                 correct = False;
7582         }
7583
7584         return correct;
7585 }
7586
7587 static bool run_dirtest1(int dummy)
7588 {
7589         int i;
7590         static struct cli_state *cli;
7591         uint16_t fnum;
7592         int num_seen;
7593         bool correct = True;
7594
7595         printf("starting directory test\n");
7596
7597         if (!torture_open_connection(&cli, 0)) {
7598                 return False;
7599         }
7600
7601         smbXcli_conn_set_sockopt(cli->conn, sockops);
7602
7603         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
7604         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
7605         cli_rmdir(cli, "\\LISTDIR");
7606         cli_mkdir(cli, "\\LISTDIR");
7607
7608         /* Create 1000 files and 1000 directories. */
7609         for (i=0;i<1000;i++) {
7610                 fstring fname;
7611                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
7612                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
7613                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
7614                                    0, 0, &fnum, NULL))) {
7615                         fprintf(stderr,"Failed to open %s\n", fname);
7616                         return False;
7617                 }
7618                 cli_close(cli, fnum);
7619         }
7620         for (i=0;i<1000;i++) {
7621                 fstring fname;
7622                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
7623                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
7624                         fprintf(stderr,"Failed to open %s\n", fname);
7625                         return False;
7626                 }
7627         }
7628
7629         /* Now ensure that doing an old list sees both files and directories. */
7630         num_seen = 0;
7631         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7632         printf("num_seen = %d\n", num_seen );
7633         /* We should see 100 files + 1000 directories + . and .. */
7634         if (num_seen != 2002)
7635                 correct = False;
7636
7637         /* Ensure if we have the "must have" bits we only see the
7638          * relevent entries.
7639          */
7640         num_seen = 0;
7641         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7642         printf("num_seen = %d\n", num_seen );
7643         if (num_seen != 1002)
7644                 correct = False;
7645
7646         num_seen = 0;
7647         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7648         printf("num_seen = %d\n", num_seen );
7649         if (num_seen != 1000)
7650                 correct = False;
7651
7652         /* Delete everything. */
7653         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
7654         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
7655         cli_rmdir(cli, "\\LISTDIR");
7656
7657 #if 0
7658         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
7659         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
7660         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
7661 #endif
7662
7663         if (!torture_close_connection(cli)) {
7664                 correct = False;
7665         }
7666
7667         printf("finished dirtest1\n");
7668
7669         return correct;
7670 }
7671
7672 static bool run_error_map_extract(int dummy) {
7673
7674         static struct cli_state *c_dos;
7675         static struct cli_state *c_nt;
7676         NTSTATUS status;
7677
7678         uint32_t error;
7679
7680         uint32_t errnum;
7681         uint8_t errclass;
7682
7683         NTSTATUS nt_status;
7684
7685         fstring user;
7686
7687         /* NT-Error connection */
7688
7689         disable_spnego = true;
7690         if (!(c_nt = open_nbt_connection())) {
7691                 disable_spnego = false;
7692                 return False;
7693         }
7694         disable_spnego = false;
7695
7696         status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
7697                                  PROTOCOL_NT1);
7698
7699         if (!NT_STATUS_IS_OK(status)) {
7700                 printf("%s rejected the NT-error negprot (%s)\n", host,
7701                        nt_errstr(status));
7702                 cli_shutdown(c_nt);
7703                 return False;
7704         }
7705
7706         status = cli_session_setup_anon(c_nt);
7707         if (!NT_STATUS_IS_OK(status)) {
7708                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
7709                 return False;
7710         }
7711
7712         /* DOS-Error connection */
7713
7714         disable_spnego = true;
7715         force_dos_errors = true;
7716         if (!(c_dos = open_nbt_connection())) {
7717                 disable_spnego = false;
7718                 force_dos_errors = false;
7719                 return False;
7720         }
7721         disable_spnego = false;
7722         force_dos_errors = false;
7723
7724         status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
7725                                  PROTOCOL_NT1);
7726         if (!NT_STATUS_IS_OK(status)) {
7727                 printf("%s rejected the DOS-error negprot (%s)\n", host,
7728                        nt_errstr(status));
7729                 cli_shutdown(c_dos);
7730                 return False;
7731         }
7732
7733         status = cli_session_setup_anon(c_dos);
7734         if (!NT_STATUS_IS_OK(status)) {
7735                 printf("%s rejected the DOS-error initial session setup (%s)\n",
7736                         host, nt_errstr(status));
7737                 return False;
7738         }
7739
7740         c_nt->map_dos_errors = false;
7741         c_dos->map_dos_errors = false;
7742
7743         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
7744                 struct cli_credentials *user_creds = NULL;
7745
7746                 fstr_sprintf(user, "%X", error);
7747
7748                 user_creds = cli_session_creds_init(talloc_tos(),
7749                                                     user,
7750                                                     workgroup,
7751                                                     NULL, /* realm */
7752                                                     password,
7753                                                     false, /* use_kerberos */
7754                                                     false, /* fallback_after_kerberos */
7755                                                     false, /* use_ccache */
7756                                                     false); /* password_is_nt_hash */
7757                 if (user_creds == NULL) {
7758                         printf("cli_session_creds_init(%s) failed\n", user);
7759                         return false;
7760                 }
7761
7762                 status = cli_session_setup_creds(c_nt, user_creds);
7763                 if (NT_STATUS_IS_OK(status)) {
7764                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
7765                 }
7766
7767                 /* Case #1: 32-bit NT errors */
7768                 if (!NT_STATUS_IS_DOS(status)) {
7769                         nt_status = status;
7770                 } else {
7771                         printf("/** Dos error on NT connection! (%s) */\n", 
7772                                nt_errstr(status));
7773                         nt_status = NT_STATUS(0xc0000000);
7774                 }
7775
7776                 status = cli_session_setup_creds(c_dos, user_creds);
7777                 if (NT_STATUS_IS_OK(status)) {
7778                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
7779                 }
7780
7781                 /* Case #1: 32-bit NT errors */
7782                 if (NT_STATUS_IS_DOS(status)) {
7783                         printf("/** NT error on DOS connection! (%s) */\n", 
7784                                nt_errstr(status));
7785                         errnum = errclass = 0;
7786                 } else {
7787                         errclass = NT_STATUS_DOS_CLASS(status);
7788                         errnum = NT_STATUS_DOS_CODE(status);
7789                 }
7790
7791                 if (NT_STATUS_V(nt_status) != error) { 
7792                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
7793                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
7794                                get_nt_error_c_code(talloc_tos(), nt_status));
7795                 }
7796
7797                 printf("\t{%s,\t%s,\t%s},\n", 
7798                        smb_dos_err_class(errclass), 
7799                        smb_dos_err_name(errclass, errnum), 
7800                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
7801
7802                 TALLOC_FREE(user_creds);
7803         }
7804         return True;
7805 }
7806
7807 static bool run_sesssetup_bench(int dummy)
7808 {
7809         static struct cli_state *c;
7810         const char *fname = "\\file.dat";
7811         uint16_t fnum;
7812         NTSTATUS status;
7813         int i;
7814
7815         if (!torture_open_connection(&c, 0)) {
7816                 return false;
7817         }
7818
7819         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7820                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7821                               FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
7822         if (!NT_STATUS_IS_OK(status)) {
7823                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7824                 return false;
7825         }
7826
7827         for (i=0; i<torture_numops; i++) {
7828                 status = cli_session_setup_creds(c, torture_creds);
7829                 if (!NT_STATUS_IS_OK(status)) {
7830                         d_printf("(%s) cli_session_setup_creds failed: %s\n",
7831                                  __location__, nt_errstr(status));
7832                         return false;
7833                 }
7834
7835                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
7836
7837                 status = cli_ulogoff(c);
7838                 if (!NT_STATUS_IS_OK(status)) {
7839                         d_printf("(%s) cli_ulogoff failed: %s\n",
7840                                  __location__, nt_errstr(status));
7841                         return false;
7842                 }
7843         }
7844
7845         return true;
7846 }
7847
7848 static bool subst_test(const char *str, const char *user, const char *domain,
7849                        uid_t uid, gid_t gid, const char *expected)
7850 {
7851         char *subst;
7852         bool result = true;
7853
7854         subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
7855
7856         if (strcmp(subst, expected) != 0) {
7857                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
7858                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
7859                        expected);
7860                 result = false;
7861         }
7862
7863         TALLOC_FREE(subst);
7864         return result;
7865 }
7866
7867 static void chain1_open_completion(struct tevent_req *req)
7868 {
7869         uint16_t fnum;
7870         NTSTATUS status;
7871         status = cli_openx_recv(req, &fnum);
7872         TALLOC_FREE(req);
7873
7874         d_printf("cli_openx_recv returned %s: %d\n",
7875                  nt_errstr(status),
7876                  NT_STATUS_IS_OK(status) ? fnum : -1);
7877 }
7878
7879 static void chain1_write_completion(struct tevent_req *req)
7880 {
7881         size_t written;
7882         NTSTATUS status;
7883         status = cli_write_andx_recv(req, &written);
7884         TALLOC_FREE(req);
7885
7886         d_printf("cli_write_andx_recv returned %s: %d\n",
7887                  nt_errstr(status),
7888                  NT_STATUS_IS_OK(status) ? (int)written : -1);
7889 }
7890
7891 static void chain1_close_completion(struct tevent_req *req)
7892 {
7893         NTSTATUS status;
7894         bool *done = (bool *)tevent_req_callback_data_void(req);
7895
7896         status = cli_close_recv(req);
7897         *done = true;
7898
7899         TALLOC_FREE(req);
7900
7901         d_printf("cli_close returned %s\n", nt_errstr(status));
7902 }
7903
7904 static bool run_chain1(int dummy)
7905 {
7906         struct cli_state *cli1;
7907         struct tevent_context *evt = samba_tevent_context_init(NULL);
7908         struct tevent_req *reqs[3], *smbreqs[3];
7909         bool done = false;
7910         const char *str = "foobar";
7911         NTSTATUS status;
7912
7913         printf("starting chain1 test\n");
7914         if (!torture_open_connection(&cli1, 0)) {
7915                 return False;
7916         }
7917
7918         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7919
7920         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, "\\test",
7921                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
7922         if (reqs[0] == NULL) return false;
7923         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
7924
7925
7926         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
7927                                         (const uint8_t *)str, 0, strlen(str)+1,
7928                                         smbreqs, 1, &smbreqs[1]);
7929         if (reqs[1] == NULL) return false;
7930         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
7931
7932         reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
7933         if (reqs[2] == NULL) return false;
7934         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
7935
7936         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
7937         if (!NT_STATUS_IS_OK(status)) {
7938                 return false;
7939         }
7940
7941         while (!done) {
7942                 tevent_loop_once(evt);
7943         }
7944
7945         torture_close_connection(cli1);
7946         return True;
7947 }
7948
7949 static void chain2_sesssetup_completion(struct tevent_req *req)
7950 {
7951         NTSTATUS status;
7952         status = cli_session_setup_guest_recv(req);
7953         d_printf("sesssetup returned %s\n", nt_errstr(status));
7954 }
7955
7956 static void chain2_tcon_completion(struct tevent_req *req)
7957 {
7958         bool *done = (bool *)tevent_req_callback_data_void(req);
7959         NTSTATUS status;
7960         status = cli_tcon_andx_recv(req);
7961         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
7962         *done = true;
7963 }
7964
7965 static bool run_chain2(int dummy)
7966 {
7967         struct cli_state *cli1;
7968         struct tevent_context *evt = samba_tevent_context_init(NULL);
7969         struct tevent_req *reqs[2], *smbreqs[2];
7970         bool done = false;
7971         NTSTATUS status;
7972         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
7973
7974         printf("starting chain2 test\n");
7975         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
7976                                       port_to_use, SMB_SIGNING_DEFAULT, flags);
7977         if (!NT_STATUS_IS_OK(status)) {
7978                 return False;
7979         }
7980
7981         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7982
7983         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
7984                                                  &smbreqs[0]);
7985         if (reqs[0] == NULL) return false;
7986         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
7987
7988         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
7989                                        "?????", NULL, 0, &smbreqs[1]);
7990         if (reqs[1] == NULL) return false;
7991         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
7992
7993         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
7994         if (!NT_STATUS_IS_OK(status)) {
7995                 return false;
7996         }
7997
7998         while (!done) {
7999                 tevent_loop_once(evt);
8000         }
8001
8002         torture_close_connection(cli1);
8003         return True;
8004 }
8005
8006
8007 struct torture_createdel_state {
8008         struct tevent_context *ev;
8009         struct cli_state *cli;
8010 };
8011
8012 static void torture_createdel_created(struct tevent_req *subreq);
8013 static void torture_createdel_closed(struct tevent_req *subreq);
8014
8015 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
8016                                                  struct tevent_context *ev,
8017                                                  struct cli_state *cli,
8018                                                  const char *name)
8019 {
8020         struct tevent_req *req, *subreq;
8021         struct torture_createdel_state *state;
8022
8023         req = tevent_req_create(mem_ctx, &state,
8024                                 struct torture_createdel_state);
8025         if (req == NULL) {
8026                 return NULL;
8027         }
8028         state->ev = ev;
8029         state->cli = cli;
8030
8031         subreq = cli_ntcreate_send(
8032                 state, ev, cli, name, 0,
8033                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
8034                 FILE_ATTRIBUTE_NORMAL,
8035                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8036                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
8037
8038         if (tevent_req_nomem(subreq, req)) {
8039                 return tevent_req_post(req, ev);
8040         }
8041         tevent_req_set_callback(subreq, torture_createdel_created, req);
8042         return req;
8043 }
8044
8045 static void torture_createdel_created(struct tevent_req *subreq)
8046 {
8047         struct tevent_req *req = tevent_req_callback_data(
8048                 subreq, struct tevent_req);
8049         struct torture_createdel_state *state = tevent_req_data(
8050                 req, struct torture_createdel_state);
8051         NTSTATUS status;
8052         uint16_t fnum;
8053
8054         status = cli_ntcreate_recv(subreq, &fnum, NULL);
8055         TALLOC_FREE(subreq);
8056         if (tevent_req_nterror(req, status)) {
8057                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
8058                            nt_errstr(status)));
8059                 return;
8060         }
8061
8062         subreq = cli_close_send(state, state->ev, state->cli, fnum);
8063         if (tevent_req_nomem(subreq, req)) {
8064                 return;
8065         }
8066         tevent_req_set_callback(subreq, torture_createdel_closed, req);
8067 }
8068
8069 static void torture_createdel_closed(struct tevent_req *subreq)
8070 {
8071         struct tevent_req *req = tevent_req_callback_data(
8072                 subreq, struct tevent_req);
8073         NTSTATUS status;
8074
8075         status = cli_close_recv(subreq);
8076         if (tevent_req_nterror(req, status)) {
8077                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
8078                 return;
8079         }
8080         tevent_req_done(req);
8081 }
8082
8083 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
8084 {
8085         return tevent_req_simple_recv_ntstatus(req);
8086 }
8087
8088 struct torture_createdels_state {
8089         struct tevent_context *ev;
8090         struct cli_state *cli;
8091         const char *base_name;
8092         int sent;
8093         int received;
8094         int num_files;
8095         struct tevent_req **reqs;
8096 };
8097
8098 static void torture_createdels_done(struct tevent_req *subreq);
8099
8100 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
8101                                                   struct tevent_context *ev,
8102                                                   struct cli_state *cli,
8103                                                   const char *base_name,
8104                                                   int num_parallel,
8105                                                   int num_files)
8106 {
8107         struct tevent_req *req;
8108         struct torture_createdels_state *state;
8109         int i;
8110
8111         req = tevent_req_create(mem_ctx, &state,
8112                                 struct torture_createdels_state);
8113         if (req == NULL) {
8114                 return NULL;
8115         }
8116         state->ev = ev;
8117         state->cli = cli;
8118         state->base_name = talloc_strdup(state, base_name);
8119         if (tevent_req_nomem(state->base_name, req)) {
8120                 return tevent_req_post(req, ev);
8121         }
8122         state->num_files = MAX(num_parallel, num_files);
8123         state->sent = 0;
8124         state->received = 0;
8125
8126         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
8127         if (tevent_req_nomem(state->reqs, req)) {
8128                 return tevent_req_post(req, ev);
8129         }
8130
8131         for (i=0; i<num_parallel; i++) {
8132                 char *name;
8133
8134                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
8135                                        state->sent);
8136                 if (tevent_req_nomem(name, req)) {
8137                         return tevent_req_post(req, ev);
8138                 }
8139                 state->reqs[i] = torture_createdel_send(
8140                         state->reqs, state->ev, state->cli, name);
8141                 if (tevent_req_nomem(state->reqs[i], req)) {
8142                         return tevent_req_post(req, ev);
8143                 }
8144                 name = talloc_move(state->reqs[i], &name);
8145                 tevent_req_set_callback(state->reqs[i],
8146                                         torture_createdels_done, req);
8147                 state->sent += 1;
8148         }
8149         return req;
8150 }
8151
8152 static void torture_createdels_done(struct tevent_req *subreq)
8153 {
8154         struct tevent_req *req = tevent_req_callback_data(
8155                 subreq, struct tevent_req);
8156         struct torture_createdels_state *state = tevent_req_data(
8157                 req, struct torture_createdels_state);
8158         size_t num_parallel = talloc_array_length(state->reqs);
8159         NTSTATUS status;
8160         char *name;
8161         int i;
8162
8163         status = torture_createdel_recv(subreq);
8164         if (!NT_STATUS_IS_OK(status)){
8165                 DEBUG(10, ("torture_createdel_recv returned %s\n",
8166                            nt_errstr(status)));
8167                 TALLOC_FREE(subreq);
8168                 tevent_req_nterror(req, status);
8169                 return;
8170         }
8171
8172         for (i=0; i<num_parallel; i++) {
8173                 if (subreq == state->reqs[i]) {
8174                         break;
8175                 }
8176         }
8177         if (i == num_parallel) {
8178                 DEBUG(10, ("received something we did not send\n"));
8179                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
8180                 return;
8181         }
8182         TALLOC_FREE(state->reqs[i]);
8183
8184         if (state->sent >= state->num_files) {
8185                 tevent_req_done(req);
8186                 return;
8187         }
8188
8189         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
8190                                state->sent);
8191         if (tevent_req_nomem(name, req)) {
8192                 return;
8193         }
8194         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
8195                                                 state->cli, name);
8196         if (tevent_req_nomem(state->reqs[i], req)) {
8197                 return;
8198         }
8199         name = talloc_move(state->reqs[i], &name);
8200         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
8201         state->sent += 1;
8202 }
8203
8204 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
8205 {
8206         return tevent_req_simple_recv_ntstatus(req);
8207 }
8208
8209 struct swallow_notify_state {
8210         struct tevent_context *ev;
8211         struct cli_state *cli;
8212         uint16_t fnum;
8213         uint32_t completion_filter;
8214         bool recursive;
8215         bool (*fn)(uint32_t action, const char *name, void *priv);
8216         void *priv;
8217 };
8218
8219 static void swallow_notify_done(struct tevent_req *subreq);
8220
8221 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
8222                                               struct tevent_context *ev,
8223                                               struct cli_state *cli,
8224                                               uint16_t fnum,
8225                                               uint32_t completion_filter,
8226                                               bool recursive,
8227                                               bool (*fn)(uint32_t action,
8228                                                          const char *name,
8229                                                          void *priv),
8230                                               void *priv)
8231 {
8232         struct tevent_req *req, *subreq;
8233         struct swallow_notify_state *state;
8234
8235         req = tevent_req_create(mem_ctx, &state,
8236                                 struct swallow_notify_state);
8237         if (req == NULL) {
8238                 return NULL;
8239         }
8240         state->ev = ev;
8241         state->cli = cli;
8242         state->fnum = fnum;
8243         state->completion_filter = completion_filter;
8244         state->recursive = recursive;
8245         state->fn = fn;
8246         state->priv = priv;
8247
8248         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
8249                                  0xffff, state->completion_filter,
8250                                  state->recursive);
8251         if (tevent_req_nomem(subreq, req)) {
8252                 return tevent_req_post(req, ev);
8253         }
8254         tevent_req_set_callback(subreq, swallow_notify_done, req);
8255         return req;
8256 }
8257
8258 static void swallow_notify_done(struct tevent_req *subreq)
8259 {
8260         struct tevent_req *req = tevent_req_callback_data(
8261                 subreq, struct tevent_req);
8262         struct swallow_notify_state *state = tevent_req_data(
8263                 req, struct swallow_notify_state);
8264         NTSTATUS status;
8265         uint32_t i, num_changes;
8266         struct notify_change *changes;
8267
8268         status = cli_notify_recv(subreq, state, &num_changes, &changes);
8269         TALLOC_FREE(subreq);
8270         if (!NT_STATUS_IS_OK(status)) {
8271                 DEBUG(10, ("cli_notify_recv returned %s\n",
8272                            nt_errstr(status)));
8273                 tevent_req_nterror(req, status);
8274                 return;
8275         }
8276
8277         for (i=0; i<num_changes; i++) {
8278                 state->fn(changes[i].action, changes[i].name, state->priv);
8279         }
8280         TALLOC_FREE(changes);
8281
8282         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
8283                                  0xffff, state->completion_filter,
8284                                  state->recursive);
8285         if (tevent_req_nomem(subreq, req)) {
8286                 return;
8287         }
8288         tevent_req_set_callback(subreq, swallow_notify_done, req);
8289 }
8290
8291 static bool print_notifies(uint32_t action, const char *name, void *priv)
8292 {
8293         if (DEBUGLEVEL > 5) {
8294                 d_printf("%d %s\n", (int)action, name);
8295         }
8296         return true;
8297 }
8298
8299 static void notify_bench_done(struct tevent_req *req)
8300 {
8301         int *num_finished = (int *)tevent_req_callback_data_void(req);
8302         *num_finished += 1;
8303 }
8304
8305 static bool run_notify_bench(int dummy)
8306 {
8307         const char *dname = "\\notify-bench";
8308         struct tevent_context *ev;
8309         NTSTATUS status;
8310         uint16_t dnum;
8311         struct tevent_req *req1;
8312         struct tevent_req *req2 = NULL;
8313         int i, num_unc_names;
8314         int num_finished = 0;
8315
8316         printf("starting notify-bench test\n");
8317
8318         if (use_multishare_conn) {
8319                 char **unc_list;
8320                 unc_list = file_lines_load(multishare_conn_fname,
8321                                            &num_unc_names, 0, NULL);
8322                 if (!unc_list || num_unc_names <= 0) {
8323                         d_printf("Failed to load unc names list from '%s'\n",
8324                                  multishare_conn_fname);
8325                         return false;
8326                 }
8327                 TALLOC_FREE(unc_list);
8328         } else {
8329                 num_unc_names = 1;
8330         }
8331
8332         ev = samba_tevent_context_init(talloc_tos());
8333         if (ev == NULL) {
8334                 d_printf("tevent_context_init failed\n");
8335                 return false;
8336         }
8337
8338         for (i=0; i<num_unc_names; i++) {
8339                 struct cli_state *cli;
8340                 char *base_fname;
8341
8342                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
8343                                              dname, i);
8344                 if (base_fname == NULL) {
8345                         return false;
8346                 }
8347
8348                 if (!torture_open_connection(&cli, i)) {
8349                         return false;
8350                 }
8351
8352                 status = cli_ntcreate(cli, dname, 0,
8353                                       MAXIMUM_ALLOWED_ACCESS,
8354                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
8355                                       FILE_SHARE_DELETE,
8356                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
8357                                       &dnum, NULL);
8358
8359                 if (!NT_STATUS_IS_OK(status)) {
8360                         d_printf("Could not create %s: %s\n", dname,
8361                                  nt_errstr(status));
8362                         return false;
8363                 }
8364
8365                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
8366                                            FILE_NOTIFY_CHANGE_FILE_NAME |
8367                                            FILE_NOTIFY_CHANGE_DIR_NAME |
8368                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
8369                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
8370                                            false, print_notifies, NULL);
8371                 if (req1 == NULL) {
8372                         d_printf("Could not create notify request\n");
8373                         return false;
8374                 }
8375
8376                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
8377                                                base_fname, 10, torture_numops);
8378                 if (req2 == NULL) {
8379                         d_printf("Could not create createdels request\n");
8380                         return false;
8381                 }
8382                 TALLOC_FREE(base_fname);
8383
8384                 tevent_req_set_callback(req2, notify_bench_done,
8385                                         &num_finished);
8386         }
8387
8388         while (num_finished < num_unc_names) {
8389                 int ret;
8390                 ret = tevent_loop_once(ev);
8391                 if (ret != 0) {
8392                         d_printf("tevent_loop_once failed\n");
8393                         return false;
8394                 }
8395         }
8396
8397         if (!tevent_req_poll(req2, ev)) {
8398                 d_printf("tevent_req_poll failed\n");
8399         }
8400
8401         status = torture_createdels_recv(req2);
8402         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
8403
8404         return true;
8405 }
8406
8407 static bool run_mangle1(int dummy)
8408 {
8409         struct cli_state *cli;
8410         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
8411         uint16_t fnum;
8412         fstring alt_name;
8413         NTSTATUS status;
8414         time_t change_time, access_time, write_time;
8415         off_t size;
8416         uint16_t mode;
8417
8418         printf("starting mangle1 test\n");
8419         if (!torture_open_connection(&cli, 0)) {
8420                 return False;
8421         }
8422
8423         smbXcli_conn_set_sockopt(cli->conn, sockops);
8424
8425         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8426                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8427                               0, 0, &fnum, NULL);
8428         if (!NT_STATUS_IS_OK(status)) {
8429                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8430                 return false;
8431         }
8432         cli_close(cli, fnum);
8433
8434         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
8435         if (!NT_STATUS_IS_OK(status)) {
8436                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
8437                          nt_errstr(status));
8438                 return false;
8439         }
8440         d_printf("alt_name: %s\n", alt_name);
8441
8442         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
8443         if (!NT_STATUS_IS_OK(status)) {
8444                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
8445                          nt_errstr(status));
8446                 return false;
8447         }
8448         cli_close(cli, fnum);
8449
8450         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
8451                                 &write_time, &size, &mode);
8452         if (!NT_STATUS_IS_OK(status)) {
8453                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
8454                          nt_errstr(status));
8455                 return false;
8456         }
8457
8458         return true;
8459 }
8460
8461 static NTSTATUS mangle_illegal_list_shortname_fn(const char *mntpoint,
8462                                                  struct file_info *f,
8463                                                  const char *mask,
8464                                                  void *state)
8465 {
8466         if (f->short_name == NULL) {
8467                 return NT_STATUS_OK;
8468         }
8469
8470         if (strlen(f->short_name) == 0) {
8471                 return NT_STATUS_OK;
8472         }
8473
8474         printf("unexpected shortname: %s\n", f->short_name);
8475
8476         return NT_STATUS_OBJECT_NAME_INVALID;
8477 }
8478
8479 static NTSTATUS mangle_illegal_list_name_fn(const char *mntpoint,
8480                                             struct file_info *f,
8481                                             const char *mask,
8482                                             void *state)
8483 {
8484         char *name = state;
8485
8486         printf("name: %s\n", f->name);
8487         fstrcpy(name, f->name);
8488         return NT_STATUS_OK;
8489 }
8490
8491 static bool run_mangle_illegal(int dummy)
8492 {
8493         struct cli_state *cli = NULL;
8494         struct cli_state *cli_posix = NULL;
8495         const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
8496         const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
8497         char *mangled_path = NULL;
8498         uint16_t fnum;
8499         fstring name;
8500         fstring alt_name;
8501         NTSTATUS status;
8502
8503         printf("starting mangle-illegal test\n");
8504
8505         if (!torture_open_connection(&cli, 0)) {
8506                 return False;
8507         }
8508
8509         smbXcli_conn_set_sockopt(cli->conn, sockops);
8510
8511         if (!torture_open_connection(&cli_posix, 0)) {
8512                 return false;
8513         }
8514
8515         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
8516
8517         status = torture_setup_unix_extensions(cli_posix);
8518         if (!NT_STATUS_IS_OK(status)) {
8519                 return false;
8520         }
8521
8522         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
8523         status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
8524         if (!NT_STATUS_IS_OK(status)) {
8525                 printf("mkdir1 failed : %s\n", nt_errstr(status));
8526                 return False;
8527         }
8528
8529         /*
8530          * Create a file with illegal NTFS characters and test that we
8531          * get a usable mangled name
8532          */
8533
8534         cli_setatr(cli_posix, illegal_fname, 0, 0);
8535         cli_posix_unlink(cli_posix, illegal_fname);
8536
8537         status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
8538                                 0600, &fnum);
8539         if (!NT_STATUS_IS_OK(status)) {
8540                 printf("POSIX create of %s failed (%s)\n",
8541                        illegal_fname, nt_errstr(status));
8542                 return false;
8543         }
8544
8545         status = cli_close(cli_posix, fnum);
8546         if (!NT_STATUS_IS_OK(status)) {
8547                 printf("close failed (%s)\n", nt_errstr(status));
8548                 return false;
8549         }
8550
8551         status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
8552         if (!NT_STATUS_IS_OK(status)) {
8553                 d_printf("cli_list failed: %s\n", nt_errstr(status));
8554                 return false;
8555         }
8556
8557         mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
8558         if (mangled_path == NULL) {
8559                 return false;
8560         }
8561
8562         status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
8563         if (!NT_STATUS_IS_OK(status)) {
8564                 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
8565                 TALLOC_FREE(mangled_path);
8566                 return false;
8567         }
8568         TALLOC_FREE(mangled_path);
8569         cli_close(cli, fnum);
8570
8571         cli_setatr(cli_posix, illegal_fname, 0, 0);
8572         cli_posix_unlink(cli_posix, illegal_fname);
8573
8574         /*
8575          * Create a file with a long name and check that we got *no* short name.
8576          */
8577
8578         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8579                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8580                               0, 0, &fnum, NULL);
8581         if (!NT_STATUS_IS_OK(status)) {
8582                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8583                 return false;
8584         }
8585         cli_close(cli, fnum);
8586
8587         status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
8588         if (!NT_STATUS_IS_OK(status)) {
8589                 d_printf("cli_list failed\n");
8590                 return false;
8591         }
8592
8593         cli_unlink(cli, fname, 0);
8594         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
8595
8596         if (!torture_close_connection(cli_posix)) {
8597                 return false;
8598         }
8599
8600         if (!torture_close_connection(cli)) {
8601                 return false;
8602         }
8603
8604         return true;
8605 }
8606
8607 static size_t null_source(uint8_t *buf, size_t n, void *priv)
8608 {
8609         size_t *to_pull = (size_t *)priv;
8610         size_t thistime = *to_pull;
8611
8612         thistime = MIN(thistime, n);
8613         if (thistime == 0) {
8614                 return 0;
8615         }
8616
8617         memset(buf, 0, thistime);
8618         *to_pull -= thistime;
8619         return thistime;
8620 }
8621
8622 static bool run_windows_write(int dummy)
8623 {
8624         struct cli_state *cli1;
8625         uint16_t fnum;
8626         int i;
8627         bool ret = false;
8628         const char *fname = "\\writetest.txt";
8629         struct timeval start_time;
8630         double seconds;
8631         double kbytes;
8632         NTSTATUS status;
8633
8634         printf("starting windows_write test\n");
8635         if (!torture_open_connection(&cli1, 0)) {
8636                 return False;
8637         }
8638
8639         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
8640         if (!NT_STATUS_IS_OK(status)) {
8641                 printf("open failed (%s)\n", nt_errstr(status));
8642                 return False;
8643         }
8644
8645         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8646
8647         start_time = timeval_current();
8648
8649         for (i=0; i<torture_numops; i++) {
8650                 uint8_t c = 0;
8651                 off_t start = i * torture_blocksize;
8652                 size_t to_pull = torture_blocksize - 1;
8653
8654                 status = cli_writeall(cli1, fnum, 0, &c,
8655                                       start + torture_blocksize - 1, 1, NULL);
8656                 if (!NT_STATUS_IS_OK(status)) {
8657                         printf("cli_write failed: %s\n", nt_errstr(status));
8658                         goto fail;
8659                 }
8660
8661                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
8662                                   null_source, &to_pull);
8663                 if (!NT_STATUS_IS_OK(status)) {
8664                         printf("cli_push returned: %s\n", nt_errstr(status));
8665                         goto fail;
8666                 }
8667         }
8668
8669         seconds = timeval_elapsed(&start_time);
8670         kbytes = (double)torture_blocksize * torture_numops;
8671         kbytes /= 1024;
8672
8673         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
8674                (double)seconds, (int)(kbytes/seconds));
8675
8676         ret = true;
8677  fail:
8678         cli_close(cli1, fnum);
8679         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8680         torture_close_connection(cli1);
8681         return ret;
8682 }
8683
8684 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
8685 {
8686         size_t max_pdu = 0x1FFFF;
8687
8688         if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
8689                 max_pdu = 0xFFFFFF;
8690         }
8691
8692         if (smb1cli_conn_signing_is_active(cli->conn)) {
8693                 max_pdu = 0x1FFFF;
8694         }
8695
8696         if (smb1cli_conn_encryption_on(cli->conn)) {
8697                 max_pdu = CLI_BUFFER_SIZE;
8698         }
8699
8700         if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
8701                 len_requested &= 0xFFFF;
8702         }
8703
8704         return MIN(len_requested,
8705                    max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
8706 }
8707
8708 static bool check_read_call(struct cli_state *cli,
8709                             uint16_t fnum,
8710                             uint8_t *buf,
8711                             size_t len_requested)
8712 {
8713         NTSTATUS status;
8714         struct tevent_req *subreq = NULL;
8715         ssize_t len_read = 0;
8716         size_t len_expected = 0;
8717         struct tevent_context *ev = NULL;
8718
8719         ev = samba_tevent_context_init(talloc_tos());
8720         if (ev == NULL) {
8721                 return false;
8722         }
8723
8724         subreq = cli_read_andx_send(talloc_tos(),
8725                                     ev,
8726                                     cli,
8727                                     fnum,
8728                                     0,
8729                                     len_requested);
8730
8731         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
8732                 return false;
8733         }
8734
8735         status = cli_read_andx_recv(subreq, &len_read, &buf);
8736         if (!NT_STATUS_IS_OK(status)) {
8737                 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
8738                 return false;
8739         }
8740
8741         TALLOC_FREE(subreq);
8742         TALLOC_FREE(ev);
8743
8744         len_expected = calc_expected_return(cli, len_requested);
8745
8746         if (len_expected > 0x10000 && len_read == 0x10000) {
8747                 /* Windows servers only return a max of 0x10000,
8748                    doesn't matter if you set CAP_LARGE_READX in
8749                    the client sessionsetupX call or not. */
8750                 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
8751                         (unsigned int)len_requested);
8752         } else if (len_read != len_expected) {
8753                 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
8754                         (unsigned int)len_requested,
8755                         (unsigned int)len_read,
8756                         (unsigned int)len_expected);
8757                 return false;
8758         } else {
8759                 d_printf("Correct read reply.\n");
8760         }
8761
8762         return true;
8763 }
8764
8765 /* Test large readX variants. */
8766 static bool large_readx_tests(struct cli_state *cli,
8767                                 uint16_t fnum,
8768                                 uint8_t *buf)
8769 {
8770         /* A read of 0xFFFF0001 should *always* return 1 byte. */
8771         if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
8772                 return false;
8773         }
8774         /* A read of 0x10000 should return 0x10000 bytes. */
8775         if (check_read_call(cli, fnum, buf,    0x10000) == false) {
8776                 return false;
8777         }
8778         /* A read of 0x10000 should return 0x10001 bytes. */
8779         if (check_read_call(cli, fnum, buf,    0x10001) == false) {
8780                 return false;
8781         }
8782         /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
8783            the requested number of bytes. */
8784         if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
8785                 return false;
8786         }
8787         /* A read of 1MB should return 1MB bytes (on Samba). */
8788         if (check_read_call(cli, fnum, buf,   0x100000) == false) {
8789                 return false;
8790         }
8791
8792         if (check_read_call(cli, fnum, buf,    0x20001) == false) {
8793                 return false;
8794         }
8795         if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
8796                 return false;
8797         }
8798         if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
8799                 return false;
8800         }
8801         return true;
8802 }
8803
8804 static bool run_large_readx(int dummy)
8805 {
8806         uint8_t *buf = NULL;
8807         struct cli_state *cli1 = NULL;
8808         struct cli_state *cli2 = NULL;
8809         bool correct = false;
8810         const char *fname = "\\large_readx.dat";
8811         NTSTATUS status;
8812         uint16_t fnum1 = UINT16_MAX;
8813         uint32_t normal_caps = 0;
8814         size_t file_size = 20*1024*1024;
8815         TALLOC_CTX *frame = talloc_stackframe();
8816         size_t i;
8817         struct {
8818                 const char *name;
8819                 enum smb_signing_setting signing_setting;
8820                 enum protocol_types protocol;
8821         } runs[] = {
8822                 {
8823                         .name = "NT1",
8824                         .signing_setting = SMB_SIGNING_IF_REQUIRED,
8825                         .protocol = PROTOCOL_NT1,
8826                 },{
8827                         .name = "NT1 - SIGNING_REQUIRED",
8828                         .signing_setting = SMB_SIGNING_REQUIRED,
8829                         .protocol = PROTOCOL_NT1,
8830                 },
8831         };
8832
8833         printf("starting large_readx test\n");
8834
8835         if (!torture_open_connection(&cli1, 0)) {
8836                 goto out;
8837         }
8838
8839         normal_caps = smb1cli_conn_capabilities(cli1->conn);
8840
8841         if (!(normal_caps & CAP_LARGE_READX)) {
8842                 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
8843                         (unsigned int)normal_caps);
8844                 goto out;
8845         }
8846
8847         /* Create a file of size 4MB. */
8848         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
8849                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8850                         0, 0, &fnum1, NULL);
8851
8852         if (!NT_STATUS_IS_OK(status)) {
8853                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8854                 goto out;
8855         }
8856
8857         /* Write file_size bytes. */
8858         buf = talloc_zero_array(frame, uint8_t, file_size);
8859         if (buf == NULL) {
8860                 goto out;
8861         }
8862
8863         status = cli_writeall(cli1,
8864                               fnum1,
8865                               0,
8866                               buf,
8867                               0,
8868                               file_size,
8869                               NULL);
8870         if (!NT_STATUS_IS_OK(status)) {
8871                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
8872                 goto out;
8873         }
8874
8875         status = cli_close(cli1, fnum1);
8876         if (!NT_STATUS_IS_OK(status)) {
8877                 d_printf("cli_close failed: %s\n", nt_errstr(status));
8878                 goto out;
8879         }
8880
8881         fnum1 = UINT16_MAX;
8882
8883         for (i=0; i < ARRAY_SIZE(runs); i++) {
8884                 enum smb_signing_setting saved_signing_setting = signing_state;
8885                 uint16_t fnum2 = -1;
8886
8887                 if (do_encrypt &&
8888                     (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
8889                 {
8890                         d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
8891                         continue;
8892                 }
8893
8894                 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
8895
8896                 signing_state = runs[i].signing_setting;
8897                 cli2 = open_nbt_connection();
8898                 signing_state = saved_signing_setting;
8899                 if (cli2 == NULL) {
8900                         goto out;
8901                 }
8902
8903                 status = smbXcli_negprot(cli2->conn,
8904                                          cli2->timeout,
8905                                          runs[i].protocol,
8906                                          runs[i].protocol);
8907                 if (!NT_STATUS_IS_OK(status)) {
8908                         goto out;
8909                 }
8910
8911                 status = cli_session_setup_creds(cli2, torture_creds);
8912                 if (!NT_STATUS_IS_OK(status)) {
8913                         goto out;
8914                 }
8915
8916                 status = cli_tree_connect(cli2,
8917                                         share,
8918                                         "?????",
8919                                         password);
8920                 if (!NT_STATUS_IS_OK(status)) {
8921                         goto out;
8922                 }
8923
8924                 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
8925
8926                 normal_caps = smb1cli_conn_capabilities(cli2->conn);
8927
8928                 if (!(normal_caps & CAP_LARGE_READX)) {
8929                         d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
8930                                 (unsigned int)normal_caps);
8931                         goto out;
8932                 }
8933
8934                 if (do_encrypt) {
8935                         if (force_cli_encryption(cli2, share) == false) {
8936                                 goto out;
8937                         }
8938                 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
8939                         uint16_t major, minor;
8940                         uint32_t caplow, caphigh;
8941
8942                         status = cli_unix_extensions_version(cli2,
8943                                                              &major, &minor,
8944                                                              &caplow, &caphigh);
8945                         if (!NT_STATUS_IS_OK(status)) {
8946                                 goto out;
8947                         }
8948                 }
8949
8950                 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
8951                                 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
8952                                 0, 0, &fnum2, NULL);
8953                 if (!NT_STATUS_IS_OK(status)) {
8954                         d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
8955                         goto out;
8956                 }
8957
8958                 /* All reads must return less than file_size bytes. */
8959                 if (!large_readx_tests(cli2, fnum2, buf)) {
8960                         goto out;
8961                 }
8962
8963                 status = cli_close(cli2, fnum2);
8964                 if (!NT_STATUS_IS_OK(status)) {
8965                         d_printf("cli_close failed: %s\n", nt_errstr(status));
8966                         goto out;
8967                 }
8968                 fnum2 = -1;
8969
8970                 if (!torture_close_connection(cli2)) {
8971                         goto out;
8972                 }
8973                 cli2 = NULL;
8974         }
8975
8976         correct = true;
8977         printf("Success on large_readx test\n");
8978
8979   out:
8980
8981         if (cli2) {
8982                 if (!torture_close_connection(cli2)) {
8983                         correct = false;
8984                 }
8985         }
8986
8987         if (cli1) {
8988                 if (fnum1 != UINT16_MAX) {
8989                         status = cli_close(cli1, fnum1);
8990                         if (!NT_STATUS_IS_OK(status)) {
8991                                 d_printf("cli_close failed: %s\n", nt_errstr(status));
8992                         }
8993                         fnum1 = UINT16_MAX;
8994                 }
8995
8996                 status = cli_unlink(cli1, fname,
8997                                     FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8998                 if (!NT_STATUS_IS_OK(status)) {
8999                         printf("unlink failed (%s)\n", nt_errstr(status));
9000                 }
9001
9002                 if (!torture_close_connection(cli1)) {
9003                         correct = false;
9004                 }
9005         }
9006
9007         TALLOC_FREE(frame);
9008
9009         printf("finished large_readx test\n");
9010         return correct;
9011 }
9012
9013 static bool run_cli_echo(int dummy)
9014 {
9015         struct cli_state *cli;
9016         NTSTATUS status;
9017
9018         printf("starting cli_echo test\n");
9019         if (!torture_open_connection(&cli, 0)) {
9020                 return false;
9021         }
9022         smbXcli_conn_set_sockopt(cli->conn, sockops);
9023
9024         status = cli_echo(cli, 5, data_blob_const("hello", 5));
9025
9026         d_printf("cli_echo returned %s\n", nt_errstr(status));
9027
9028         torture_close_connection(cli);
9029         return NT_STATUS_IS_OK(status);
9030 }
9031
9032 static bool run_uid_regression_test(int dummy)
9033 {
9034         static struct cli_state *cli;
9035         int16_t old_vuid;
9036         int32_t old_cnum;
9037         bool correct = True;
9038         struct smbXcli_tcon *orig_tcon = NULL;
9039         NTSTATUS status;
9040
9041         printf("starting uid regression test\n");
9042
9043         if (!torture_open_connection(&cli, 0)) {
9044                 return False;
9045         }
9046
9047         smbXcli_conn_set_sockopt(cli->conn, sockops);
9048
9049         /* Ok - now save then logoff our current user. */
9050         old_vuid = cli_state_get_uid(cli);
9051
9052         status = cli_ulogoff(cli);
9053         if (!NT_STATUS_IS_OK(status)) {
9054                 d_printf("(%s) cli_ulogoff failed: %s\n",
9055                          __location__, nt_errstr(status));
9056                 correct = false;
9057                 goto out;
9058         }
9059
9060         cli_state_set_uid(cli, old_vuid);
9061
9062         /* Try an operation. */
9063         status = cli_mkdir(cli, "\\uid_reg_test");
9064         if (NT_STATUS_IS_OK(status)) {
9065                 d_printf("(%s) cli_mkdir succeeded\n",
9066                          __location__);
9067                 correct = false;
9068                 goto out;
9069         } else {
9070                 /* Should be bad uid. */
9071                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
9072                                  NT_STATUS_USER_SESSION_DELETED)) {
9073                         correct = false;
9074                         goto out;
9075                 }
9076         }
9077
9078         old_cnum = cli_state_get_tid(cli);
9079         orig_tcon = cli_state_save_tcon(cli);
9080         if (orig_tcon == NULL) {
9081                 correct = false;
9082                 goto out;
9083         }
9084
9085         /* Now try a SMBtdis with the invald vuid set to zero. */
9086         cli_state_set_uid(cli, 0);
9087
9088         /* This should succeed. */
9089         status = cli_tdis(cli);
9090
9091         if (NT_STATUS_IS_OK(status)) {
9092                 d_printf("First tdis with invalid vuid should succeed.\n");
9093         } else {
9094                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
9095                 correct = false;
9096                 cli_state_restore_tcon(cli, orig_tcon);
9097                 goto out;
9098         }
9099
9100         cli_state_restore_tcon(cli, orig_tcon);
9101         cli_state_set_uid(cli, old_vuid);
9102         cli_state_set_tid(cli, old_cnum);
9103
9104         /* This should fail. */
9105         status = cli_tdis(cli);
9106         if (NT_STATUS_IS_OK(status)) {
9107                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
9108                 correct = false;
9109                 goto out;
9110         } else {
9111                 /* Should be bad tid. */
9112                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
9113                                 NT_STATUS_NETWORK_NAME_DELETED)) {
9114                         correct = false;
9115                         goto out;
9116                 }
9117         }
9118
9119         cli_rmdir(cli, "\\uid_reg_test");
9120
9121   out:
9122
9123         cli_shutdown(cli);
9124         return correct;
9125 }
9126
9127
9128 static const char *illegal_chars = "*\\/?<>|\":";
9129 static char force_shortname_chars[] = " +,.[];=\177";
9130
9131 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
9132                              const char *mask, void *state)
9133 {
9134         struct cli_state *pcli = (struct cli_state *)state;
9135         fstring fname;
9136         NTSTATUS status = NT_STATUS_OK;
9137
9138         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
9139
9140         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9141                 return NT_STATUS_OK;
9142
9143         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
9144                 status = cli_rmdir(pcli, fname);
9145                 if (!NT_STATUS_IS_OK(status)) {
9146                         printf("del_fn: failed to rmdir %s\n,", fname );
9147                 }
9148         } else {
9149                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9150                 if (!NT_STATUS_IS_OK(status)) {
9151                         printf("del_fn: failed to unlink %s\n,", fname );
9152                 }
9153         }
9154         return status;
9155 }
9156
9157 struct sn_state {
9158         int matched;
9159         int i;
9160         bool val;
9161 };
9162
9163 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
9164                               const char *name, void *state)
9165 {
9166         struct sn_state *s = (struct sn_state  *)state;
9167         int i = s->i;
9168
9169 #if 0
9170         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
9171                 i, finfo->name, finfo->short_name);
9172 #endif
9173
9174         if (strchr(force_shortname_chars, i)) {
9175                 if (!finfo->short_name) {
9176                         /* Shortname not created when it should be. */
9177                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
9178                                 __location__, finfo->name, i);
9179                         s->val = true;
9180                 }
9181         } else if (finfo->short_name){
9182                 /* Shortname created when it should not be. */
9183                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
9184                         __location__, finfo->short_name, finfo->name);
9185                 s->val = true;
9186         }
9187         s->matched += 1;
9188         return NT_STATUS_OK;
9189 }
9190
9191 static bool run_shortname_test(int dummy)
9192 {
9193         static struct cli_state *cli;
9194         bool correct = True;
9195         int i;
9196         struct sn_state s;
9197         char fname[40];
9198         NTSTATUS status;
9199
9200         printf("starting shortname test\n");
9201
9202         if (!torture_open_connection(&cli, 0)) {
9203                 return False;
9204         }
9205
9206         smbXcli_conn_set_sockopt(cli->conn, sockops);
9207
9208         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
9209         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
9210         cli_rmdir(cli, "\\shortname");
9211
9212         status = cli_mkdir(cli, "\\shortname");
9213         if (!NT_STATUS_IS_OK(status)) {
9214                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
9215                         __location__, nt_errstr(status));
9216                 correct = false;
9217                 goto out;
9218         }
9219
9220         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
9221                 correct = false;
9222                 goto out;
9223         }
9224         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
9225                 correct = false;
9226                 goto out;
9227         }
9228
9229         s.val = false;
9230
9231         for (i = 32; i < 128; i++) {
9232                 uint16_t fnum = (uint16_t)-1;
9233
9234                 s.i = i;
9235
9236                 if (strchr(illegal_chars, i)) {
9237                         continue;
9238                 }
9239                 fname[15] = i;
9240
9241                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
9242                                    FILE_SHARE_READ|FILE_SHARE_WRITE,
9243                                    FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
9244                 if (!NT_STATUS_IS_OK(status)) {
9245                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
9246                                 __location__, fname, nt_errstr(status));
9247                         correct = false;
9248                         goto out;
9249                 }
9250                 cli_close(cli, fnum);
9251
9252                 s.matched = 0;
9253                 status = cli_list(cli, "\\shortname\\test*.*", 0,
9254                                   shortname_list_fn, &s);
9255                 if (s.matched != 1) {
9256                         d_printf("(%s) failed to list %s: %s\n",
9257                                 __location__, fname, nt_errstr(status));
9258                         correct = false;
9259                         goto out;
9260                 }
9261
9262                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9263                 if (!NT_STATUS_IS_OK(status)) {
9264                         d_printf("(%s) failed to delete %s: %s\n",
9265                                 __location__, fname, nt_errstr(status));
9266                         correct = false;
9267                         goto out;
9268                 }
9269
9270                 if (s.val) {
9271                         correct = false;
9272                         goto out;
9273                 }
9274         }
9275
9276   out:
9277
9278         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
9279         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
9280         cli_rmdir(cli, "\\shortname");
9281         torture_close_connection(cli);
9282         return correct;
9283 }
9284
9285 static void pagedsearch_cb(struct tevent_req *req)
9286 {
9287         TLDAPRC rc;
9288         struct tldap_message *msg;
9289         char *dn;
9290
9291         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
9292         if (!TLDAP_RC_IS_SUCCESS(rc)) {
9293                 d_printf("tldap_search_paged_recv failed: %s\n",
9294                          tldap_rc2string(rc));
9295                 return;
9296         }
9297         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
9298                 TALLOC_FREE(msg);
9299                 return;
9300         }
9301         if (!tldap_entry_dn(msg, &dn)) {
9302                 d_printf("tldap_entry_dn failed\n");
9303                 return;
9304         }
9305         d_printf("%s\n", dn);
9306         TALLOC_FREE(msg);
9307 }
9308
9309 static bool run_tldap(int dummy)
9310 {
9311         struct tldap_context *ld;
9312         int fd;
9313         TLDAPRC rc;
9314         NTSTATUS status;
9315         struct sockaddr_storage addr;
9316         struct tevent_context *ev;
9317         struct tevent_req *req;
9318         char *basedn;
9319         const char *filter;
9320
9321         if (!resolve_name(host, &addr, 0, false)) {
9322                 d_printf("could not find host %s\n", host);
9323                 return false;
9324         }
9325         status = open_socket_out(&addr, 389, 9999, &fd);
9326         if (!NT_STATUS_IS_OK(status)) {
9327                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
9328                 return false;
9329         }
9330
9331         ld = tldap_context_create(talloc_tos(), fd);
9332         if (ld == NULL) {
9333                 close(fd);
9334                 d_printf("tldap_context_create failed\n");
9335                 return false;
9336         }
9337
9338         rc = tldap_fetch_rootdse(ld);
9339         if (!TLDAP_RC_IS_SUCCESS(rc)) {
9340                 d_printf("tldap_fetch_rootdse failed: %s\n",
9341                          tldap_errstr(talloc_tos(), ld, rc));
9342                 return false;
9343         }
9344
9345         basedn = tldap_talloc_single_attribute(
9346                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
9347         if (basedn == NULL) {
9348                 d_printf("no defaultNamingContext\n");
9349                 return false;
9350         }
9351         d_printf("defaultNamingContext: %s\n", basedn);
9352
9353         ev = samba_tevent_context_init(talloc_tos());
9354         if (ev == NULL) {
9355                 d_printf("tevent_context_init failed\n");
9356                 return false;
9357         }
9358
9359         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
9360                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
9361                                       NULL, 0, 0,
9362                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
9363         if (req == NULL) {
9364                 d_printf("tldap_search_paged_send failed\n");
9365                 return false;
9366         }
9367         tevent_req_set_callback(req, pagedsearch_cb, NULL);
9368
9369         tevent_req_poll(req, ev);
9370
9371         TALLOC_FREE(req);
9372
9373         /* test search filters against rootDSE */
9374         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
9375                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
9376
9377         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
9378                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
9379                           talloc_tos(), NULL);
9380         if (!TLDAP_RC_IS_SUCCESS(rc)) {
9381                 d_printf("tldap_search with complex filter failed: %s\n",
9382                          tldap_errstr(talloc_tos(), ld, rc));
9383                 return false;
9384         }
9385
9386         TALLOC_FREE(ld);
9387         return true;
9388 }
9389
9390 /* Torture test to ensure no regression of :
9391 https://bugzilla.samba.org/show_bug.cgi?id=7084
9392 */
9393
9394 static bool run_dir_createtime(int dummy)
9395 {
9396         struct cli_state *cli;
9397         const char *dname = "\\testdir";
9398         const char *fname = "\\testdir\\testfile";
9399         NTSTATUS status;
9400         struct timespec create_time;
9401         struct timespec create_time1;
9402         uint16_t fnum;
9403         bool ret = false;
9404
9405         if (!torture_open_connection(&cli, 0)) {
9406                 return false;
9407         }
9408
9409         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9410         cli_rmdir(cli, dname);
9411
9412         status = cli_mkdir(cli, dname);
9413         if (!NT_STATUS_IS_OK(status)) {
9414                 printf("mkdir failed: %s\n", nt_errstr(status));
9415                 goto out;
9416         }
9417
9418         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
9419                                 NULL, NULL, NULL);
9420         if (!NT_STATUS_IS_OK(status)) {
9421                 printf("cli_qpathinfo2 returned %s\n",
9422                        nt_errstr(status));
9423                 goto out;
9424         }
9425
9426         /* Sleep 3 seconds, then create a file. */
9427         sleep(3);
9428
9429         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
9430                          DENY_NONE, &fnum);
9431         if (!NT_STATUS_IS_OK(status)) {
9432                 printf("cli_openx failed: %s\n", nt_errstr(status));
9433                 goto out;
9434         }
9435
9436         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
9437                                 NULL, NULL, NULL);
9438         if (!NT_STATUS_IS_OK(status)) {
9439                 printf("cli_qpathinfo2 (2) returned %s\n",
9440                        nt_errstr(status));
9441                 goto out;
9442         }
9443
9444         if (timespec_compare(&create_time1, &create_time)) {
9445                 printf("run_dir_createtime: create time was updated (error)\n");
9446         } else {
9447                 printf("run_dir_createtime: create time was not updated (correct)\n");
9448                 ret = true;
9449         }
9450
9451   out:
9452
9453         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9454         cli_rmdir(cli, dname);
9455         if (!torture_close_connection(cli)) {
9456                 ret = false;
9457         }
9458         return ret;
9459 }
9460
9461
9462 static bool run_streamerror(int dummy)
9463 {
9464         struct cli_state *cli;
9465         const char *dname = "\\testdir";
9466         const char *streamname =
9467                 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
9468         NTSTATUS status;
9469         time_t change_time, access_time, write_time;
9470         off_t size;
9471         uint16_t mode, fnum;
9472         bool ret = true;
9473
9474         if (!torture_open_connection(&cli, 0)) {
9475                 return false;
9476         }
9477
9478         cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9479         cli_rmdir(cli, dname);
9480
9481         status = cli_mkdir(cli, dname);
9482         if (!NT_STATUS_IS_OK(status)) {
9483                 printf("mkdir failed: %s\n", nt_errstr(status));
9484                 return false;
9485         }
9486
9487         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
9488                                 &write_time, &size, &mode);
9489         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
9490                 printf("pathinfo returned %s, expected "
9491                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
9492                        nt_errstr(status));
9493                 ret = false;
9494         }
9495
9496         status = cli_ntcreate(cli, streamname, 0x16,
9497                               FILE_READ_DATA|FILE_READ_EA|
9498                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
9499                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
9500                               FILE_OPEN, 0, 0, &fnum, NULL);
9501
9502         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
9503                 printf("ntcreate returned %s, expected "
9504                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
9505                        nt_errstr(status));
9506                 ret = false;
9507         }
9508
9509
9510         cli_rmdir(cli, dname);
9511         return ret;
9512 }
9513
9514 struct pidtest_state {
9515         bool success;
9516         uint16_t vwv[1];
9517         DATA_BLOB data;
9518 };
9519
9520 static void pid_echo_done(struct tevent_req *subreq);
9521
9522 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
9523                         struct tevent_context *ev,
9524                         struct cli_state *cli)
9525 {
9526         struct tevent_req *req, *subreq;
9527         struct pidtest_state *state;
9528
9529         req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
9530         if (req == NULL) {
9531                 return NULL;
9532         }
9533
9534         SSVAL(state->vwv, 0, 1);
9535         state->data = data_blob_const("hello", 5);
9536
9537         subreq = smb1cli_req_send(state,
9538                                 ev,
9539                                 cli->conn,
9540                                 SMBecho,
9541                                 0, 0, /* *_flags */
9542                                 0, 0, /* *_flags2 */
9543                                 cli->timeout,
9544                                 0xDEADBEEF, /* pid */
9545                                 NULL, /* tcon */
9546                                 NULL, /* session */
9547                                 ARRAY_SIZE(state->vwv), state->vwv,
9548                                 state->data.length, state->data.data);
9549
9550         if (tevent_req_nomem(subreq, req)) {
9551                 return tevent_req_post(req, ev);
9552         }
9553         tevent_req_set_callback(subreq, pid_echo_done, req);
9554         return req;
9555 }
9556
9557 static void pid_echo_done(struct tevent_req *subreq)
9558 {
9559         struct tevent_req *req = tevent_req_callback_data(
9560                 subreq, struct tevent_req);
9561         struct pidtest_state *state = tevent_req_data(
9562                 req, struct pidtest_state);
9563         NTSTATUS status;
9564         uint32_t num_bytes;
9565         uint8_t *bytes = NULL;
9566         struct iovec *recv_iov = NULL;
9567         uint8_t *phdr = NULL;
9568         uint16_t pidlow = 0;
9569         uint16_t pidhigh = 0;
9570         struct smb1cli_req_expected_response expected[] = {
9571         {
9572                 .status = NT_STATUS_OK,
9573                 .wct    = 1,
9574         },
9575         };
9576
9577         status = smb1cli_req_recv(subreq, state,
9578                                 &recv_iov,
9579                                 &phdr,
9580                                 NULL, /* pwct */
9581                                 NULL, /* pvwv */
9582                                 NULL, /* pvwv_offset */
9583                                 &num_bytes,
9584                                 &bytes,
9585                                 NULL, /* pbytes_offset */
9586                                 NULL, /* pinbuf */
9587                                 expected, ARRAY_SIZE(expected));
9588
9589         TALLOC_FREE(subreq);
9590
9591         if (!NT_STATUS_IS_OK(status)) {
9592                 tevent_req_nterror(req, status);
9593                 return;
9594         }
9595
9596         if (num_bytes != state->data.length) {
9597                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9598                 return;
9599         }
9600
9601         if (memcmp(bytes, state->data.data, num_bytes) != 0) {
9602                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9603                 return;
9604         }
9605
9606         /* Check pid low/high == DEADBEEF */
9607         pidlow = SVAL(phdr, HDR_PID);
9608         if (pidlow != 0xBEEF){
9609                 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
9610                         (unsigned int)pidlow);
9611                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9612                 return;
9613         }
9614         pidhigh = SVAL(phdr, HDR_PIDHIGH);
9615         if (pidhigh != 0xDEAD){
9616                 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
9617                         (unsigned int)pidhigh);
9618                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9619                 return;
9620         }
9621
9622         tevent_req_done(req);
9623 }
9624
9625 static NTSTATUS pid_echo_recv(struct tevent_req *req)
9626 {
9627         return tevent_req_simple_recv_ntstatus(req);
9628 }
9629
9630 static bool run_pidhigh(int dummy)
9631 {
9632         bool success = false;
9633         struct cli_state *cli = NULL;
9634         NTSTATUS status;
9635         struct tevent_context *ev = NULL;
9636         struct tevent_req *req = NULL;
9637         TALLOC_CTX *frame = talloc_stackframe();
9638
9639         printf("starting pid high test\n");
9640         if (!torture_open_connection(&cli, 0)) {
9641                 return false;
9642         }
9643         smbXcli_conn_set_sockopt(cli->conn, sockops);
9644
9645         ev = samba_tevent_context_init(frame);
9646         if (ev == NULL) {
9647                 goto fail;
9648         }
9649
9650         req = pid_echo_send(frame, ev, cli);
9651         if (req == NULL) {
9652                 goto fail;
9653         }
9654
9655         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
9656                 goto fail;
9657         }
9658
9659         status = pid_echo_recv(req);
9660         if (NT_STATUS_IS_OK(status)) {
9661                 printf("pid high test ok\n");
9662                 success = true;
9663         }
9664
9665  fail:
9666
9667         TALLOC_FREE(frame);
9668         torture_close_connection(cli);
9669         return success;
9670 }
9671
9672 /*
9673   Test Windows open on a bad POSIX symlink.
9674  */
9675 static bool run_symlink_open_test(int dummy)
9676 {
9677         static struct cli_state *cli;
9678         const char *fname = "non_existant_file";
9679         const char *sname = "dangling_symlink";
9680         uint16_t fnum = (uint16_t)-1;
9681         bool correct = false;
9682         NTSTATUS status;
9683         TALLOC_CTX *frame = NULL;
9684
9685         frame = talloc_stackframe();
9686
9687         printf("Starting Windows bad symlink open test\n");
9688
9689         if (!torture_open_connection(&cli, 0)) {
9690                 TALLOC_FREE(frame);
9691                 return false;
9692         }
9693
9694         smbXcli_conn_set_sockopt(cli->conn, sockops);
9695
9696         status = torture_setup_unix_extensions(cli);
9697         if (!NT_STATUS_IS_OK(status)) {
9698                 TALLOC_FREE(frame);
9699                 return false;
9700         }
9701
9702         /* Ensure nothing exists. */
9703         cli_setatr(cli, fname, 0, 0);
9704         cli_posix_unlink(cli, fname);
9705         cli_setatr(cli, sname, 0, 0);
9706         cli_posix_unlink(cli, sname);
9707
9708         /* Create a symlink pointing nowhere. */
9709         status = cli_posix_symlink(cli, fname, sname);
9710         if (!NT_STATUS_IS_OK(status)) {
9711                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
9712                         sname,
9713                         fname,
9714                         nt_errstr(status));
9715                 goto out;
9716         }
9717
9718         /* Now ensure that a Windows open doesn't hang. */
9719         status = cli_ntcreate(cli,
9720                         sname,
9721                         0,
9722                         FILE_READ_DATA|FILE_WRITE_DATA,
9723                         0,
9724                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9725                         FILE_OPEN_IF,
9726                         0x0,
9727                         0x0,
9728                         &fnum,
9729                         NULL);
9730
9731         /*
9732          * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
9733          * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
9734          * we use O_NOFOLLOW on the server or not.
9735          */
9736         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
9737             NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
9738         {
9739                 correct = true;
9740         } else {
9741                 printf("cli_ntcreate of %s returned %s - should return"
9742                                 " either (%s) or (%s)\n",
9743                         sname,
9744                         nt_errstr(status),
9745                         nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
9746                         nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
9747                 goto out;
9748         }
9749
9750         correct = true;
9751
9752   out:
9753
9754         if (fnum != (uint16_t)-1) {
9755                 cli_close(cli, fnum);
9756                 fnum = (uint16_t)-1;
9757         }
9758
9759         cli_setatr(cli, sname, 0, 0);
9760         cli_posix_unlink(cli, sname);
9761         cli_setatr(cli, fname, 0, 0);
9762         cli_posix_unlink(cli, fname);
9763
9764         if (!torture_close_connection(cli)) {
9765                 correct = false;
9766         }
9767
9768         TALLOC_FREE(frame);
9769         return correct;
9770 }
9771
9772 static bool run_local_substitute(int dummy)
9773 {
9774         bool ok = true;
9775
9776         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
9777         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
9778         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
9779         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
9780         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
9781         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
9782         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
9783         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
9784
9785         /* Different captialization rules in sub_basic... */
9786
9787         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
9788                        "blaDOM") == 0);
9789
9790         return ok;
9791 }
9792
9793 static bool run_local_base64(int dummy)
9794 {
9795         int i;
9796         bool ret = true;
9797
9798         for (i=1; i<2000; i++) {
9799                 DATA_BLOB blob1, blob2;
9800                 char *b64;
9801
9802                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
9803                 blob1.length = i;
9804                 generate_random_buffer(blob1.data, blob1.length);
9805
9806                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
9807                 if (b64 == NULL) {
9808                         d_fprintf(stderr, "base64_encode_data_blob failed "
9809                                   "for %d bytes\n", i);
9810                         ret = false;
9811                 }
9812                 blob2 = base64_decode_data_blob(b64);
9813                 TALLOC_FREE(b64);
9814
9815                 if (data_blob_cmp(&blob1, &blob2)) {
9816                         d_fprintf(stderr, "data_blob_cmp failed for %d "
9817                                   "bytes\n", i);
9818                         ret = false;
9819                 }
9820                 TALLOC_FREE(blob1.data);
9821                 data_blob_free(&blob2);
9822         }
9823         return ret;
9824 }
9825
9826 static void parse_fn(time_t timeout, DATA_BLOB blob, void *private_data)
9827 {
9828         return;
9829 }
9830
9831 static bool run_local_gencache(int dummy)
9832 {
9833         char *val;
9834         time_t tm;
9835         DATA_BLOB blob;
9836         char v;
9837         struct memcache *mem;
9838         int i;
9839
9840         mem = memcache_init(NULL, 0);
9841         if (mem == NULL) {
9842                 d_printf("%s: memcache_init failed\n", __location__);
9843                 return false;
9844         }
9845         memcache_set_global(mem);
9846
9847         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
9848                 d_printf("%s: gencache_set() failed\n", __location__);
9849                 return False;
9850         }
9851
9852         if (!gencache_get("foo", NULL, NULL, NULL)) {
9853                 d_printf("%s: gencache_get() failed\n", __location__);
9854                 return False;
9855         }
9856
9857         for (i=0; i<1000000; i++) {
9858                 gencache_parse("foo", parse_fn, NULL);
9859         }
9860
9861         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
9862                 d_printf("%s: gencache_get() failed\n", __location__);
9863                 return False;
9864         }
9865         TALLOC_FREE(val);
9866
9867         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
9868                 d_printf("%s: gencache_get() failed\n", __location__);
9869                 return False;
9870         }
9871
9872         if (strcmp(val, "bar") != 0) {
9873                 d_printf("%s: gencache_get() returned %s, expected %s\n",
9874                          __location__, val, "bar");
9875                 TALLOC_FREE(val);
9876                 return False;
9877         }
9878
9879         TALLOC_FREE(val);
9880
9881         if (!gencache_del("foo")) {
9882                 d_printf("%s: gencache_del() failed\n", __location__);
9883                 return False;
9884         }
9885         if (gencache_del("foo")) {
9886                 d_printf("%s: second gencache_del() succeeded\n",
9887                          __location__);
9888                 return False;
9889         }
9890
9891         if (gencache_get("foo", talloc_tos(), &val, &tm)) {
9892                 d_printf("%s: gencache_get() on deleted entry "
9893                          "succeeded\n", __location__);
9894                 return False;
9895         }
9896
9897         blob = data_blob_string_const_null("bar");
9898         tm = time(NULL) + 60;
9899
9900         if (!gencache_set_data_blob("foo", &blob, tm)) {
9901                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
9902                 return False;
9903         }
9904
9905         if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
9906                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
9907                 return False;
9908         }
9909
9910         if (strcmp((const char *)blob.data, "bar") != 0) {
9911                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
9912                          __location__, (const char *)blob.data, "bar");
9913                 data_blob_free(&blob);
9914                 return False;
9915         }
9916
9917         data_blob_free(&blob);
9918
9919         if (!gencache_del("foo")) {
9920                 d_printf("%s: gencache_del() failed\n", __location__);
9921                 return False;
9922         }
9923         if (gencache_del("foo")) {
9924                 d_printf("%s: second gencache_del() succeeded\n",
9925                          __location__);
9926                 return False;
9927         }
9928
9929         if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
9930                 d_printf("%s: gencache_get_data_blob() on deleted entry "
9931                          "succeeded\n", __location__);
9932                 return False;
9933         }
9934
9935         v = 1;
9936         blob.data = (uint8_t *)&v;
9937         blob.length = sizeof(v);
9938
9939         if (!gencache_set_data_blob("blob", &blob, tm)) {
9940                 d_printf("%s: gencache_set_data_blob() failed\n",
9941                          __location__);
9942                 return false;
9943         }
9944         if (gencache_get("blob", talloc_tos(), &val, &tm)) {
9945                 d_printf("%s: gencache_get succeeded\n", __location__);
9946                 return false;
9947         }
9948
9949         return True;
9950 }
9951
9952 static bool rbt_testval(struct db_context *db, const char *key,
9953                         const char *value)
9954 {
9955         struct db_record *rec;
9956         TDB_DATA data = string_tdb_data(value);
9957         bool ret = false;
9958         NTSTATUS status;
9959         TDB_DATA dbvalue;
9960
9961         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
9962         if (rec == NULL) {
9963                 d_fprintf(stderr, "fetch_locked failed\n");
9964                 goto done;
9965         }
9966         status = dbwrap_record_store(rec, data, 0);
9967         if (!NT_STATUS_IS_OK(status)) {
9968                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
9969                 goto done;
9970         }
9971         TALLOC_FREE(rec);
9972
9973         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
9974         if (rec == NULL) {
9975                 d_fprintf(stderr, "second fetch_locked failed\n");
9976                 goto done;
9977         }
9978
9979         dbvalue = dbwrap_record_get_value(rec);
9980         if ((dbvalue.dsize != data.dsize)
9981             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
9982                 d_fprintf(stderr, "Got wrong data back\n");
9983                 goto done;
9984         }
9985
9986         ret = true;
9987  done:
9988         TALLOC_FREE(rec);
9989         return ret;
9990 }
9991
9992 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
9993 {
9994         int *count2 = (int *)private_data;
9995         (*count2)++;
9996         return 0;
9997 }
9998
9999 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
10000 {
10001         int *count2 = (int *)private_data;
10002         (*count2)++;
10003         dbwrap_record_delete(rec);
10004         return 0;
10005 }
10006
10007 static bool run_local_rbtree(int dummy)
10008 {
10009         struct db_context *db;
10010         bool ret = false;
10011         int i;
10012         NTSTATUS status;
10013         int count = 0;
10014         int count2 = 0;
10015
10016         db = db_open_rbt(NULL);
10017
10018         if (db == NULL) {
10019                 d_fprintf(stderr, "db_open_rbt failed\n");
10020                 return false;
10021         }
10022
10023         for (i=0; i<1000; i++) {
10024                 char *key, *value;
10025
10026                 if (asprintf(&key, "key%ld", random()) == -1) {
10027                         goto done;
10028                 }
10029                 if (asprintf(&value, "value%ld", random()) == -1) {
10030                         SAFE_FREE(key);
10031                         goto done;
10032                 }
10033
10034                 if (!rbt_testval(db, key, value)) {
10035                         SAFE_FREE(key);
10036                         SAFE_FREE(value);
10037                         goto done;
10038                 }
10039
10040                 SAFE_FREE(value);
10041                 if (asprintf(&value, "value%ld", random()) == -1) {
10042                         SAFE_FREE(key);
10043                         goto done;
10044                 }
10045
10046                 if (!rbt_testval(db, key, value)) {
10047                         SAFE_FREE(key);
10048                         SAFE_FREE(value);
10049                         goto done;
10050                 }
10051
10052                 SAFE_FREE(key);
10053                 SAFE_FREE(value);
10054         }
10055
10056         ret = true;
10057         count = 0; count2 = 0;
10058         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
10059                                       &count2, &count);
10060         printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10061         if ((count != count2) || (count != 1000)) {
10062                 ret = false;
10063         }
10064         count = 0; count2 = 0;
10065         status = dbwrap_traverse(db, local_rbtree_traverse_delete,
10066                                  &count2, &count);
10067         printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10068         if ((count != count2) || (count != 1000)) {
10069                 ret = false;
10070         }
10071         count = 0; count2 = 0;
10072         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
10073                                       &count2, &count);
10074         printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10075         if ((count != count2) || (count != 0)) {
10076                 ret = false;
10077         }
10078
10079  done:
10080         TALLOC_FREE(db);
10081         return ret;
10082 }
10083
10084
10085 /*
10086   local test for character set functions
10087
10088   This is a very simple test for the functionality in convert_string_error()
10089  */
10090 static bool run_local_convert_string(int dummy)
10091 {
10092         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
10093         const char *test_strings[2] = { "March", "M\303\244rz" };
10094         char dst[7];
10095         int i;
10096
10097         for (i=0; i<2; i++) {
10098                 const char *str = test_strings[i];
10099                 int len = strlen(str);
10100                 size_t converted_size;
10101                 bool ret;
10102
10103                 memset(dst, 'X', sizeof(dst));
10104
10105                 /* first try with real source length */
10106                 ret = convert_string_error(CH_UNIX, CH_UTF8,
10107                                            str, len,
10108                                            dst, sizeof(dst),
10109                                            &converted_size);
10110                 if (ret != true) {
10111                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
10112                         goto failed;
10113                 }
10114
10115                 if (converted_size != len) {
10116                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
10117                                   str, len, (int)converted_size);
10118                         goto failed;
10119                 }
10120
10121                 if (strncmp(str, dst, converted_size) != 0) {
10122                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
10123                         goto failed;
10124                 }
10125
10126                 if (strlen(str) != converted_size) {
10127                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
10128                                   (int)strlen(str), (int)converted_size);
10129                         goto failed;
10130                 }
10131
10132                 if (dst[converted_size] != 'X') {
10133                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
10134                         goto failed;
10135                 }
10136
10137                 /* now with srclen==-1, this causes the nul to be
10138                  * converted too */
10139                 ret = convert_string_error(CH_UNIX, CH_UTF8,
10140                                            str, -1,
10141                                            dst, sizeof(dst),
10142                                            &converted_size);
10143                 if (ret != true) {
10144                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
10145                         goto failed;
10146                 }
10147
10148                 if (converted_size != len+1) {
10149                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
10150                                   str, len, (int)converted_size);
10151                         goto failed;
10152                 }
10153
10154                 if (strncmp(str, dst, converted_size) != 0) {
10155                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
10156                         goto failed;
10157                 }
10158
10159                 if (len+1 != converted_size) {
10160                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
10161                                   len+1, (int)converted_size);
10162                         goto failed;
10163                 }
10164
10165                 if (dst[converted_size] != 'X') {
10166                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
10167                         goto failed;
10168                 }
10169
10170         }
10171
10172
10173         TALLOC_FREE(tmp_ctx);
10174         return true;
10175 failed:
10176         TALLOC_FREE(tmp_ctx);
10177         return false;
10178 }
10179
10180
10181 struct talloc_dict_test {
10182         int content;
10183 };
10184
10185 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
10186 {
10187         int *count = (int *)priv;
10188         *count += 1;
10189         return 0;
10190 }
10191
10192 static bool run_local_talloc_dict(int dummy)
10193 {
10194         struct talloc_dict *dict;
10195         struct talloc_dict_test *t;
10196         int key, count, res;
10197         bool ok;
10198
10199         dict = talloc_dict_init(talloc_tos());
10200         if (dict == NULL) {
10201                 return false;
10202         }
10203
10204         t = talloc(talloc_tos(), struct talloc_dict_test);
10205         if (t == NULL) {
10206                 return false;
10207         }
10208
10209         key = 1;
10210         t->content = 1;
10211         ok = talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), &t);
10212         if (!ok) {
10213                 return false;
10214         }
10215
10216         count = 0;
10217         res = talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count);
10218         if (res == -1) {
10219                 return false;
10220         }
10221
10222         if (count != 1) {
10223                 return false;
10224         }
10225
10226         if (count != res) {
10227                 return false;
10228         }
10229
10230         TALLOC_FREE(dict);
10231
10232         return true;
10233 }
10234
10235 static bool run_local_string_to_sid(int dummy) {
10236         struct dom_sid sid;
10237
10238         if (string_to_sid(&sid, "S--1-5-32-545")) {
10239                 printf("allowing S--1-5-32-545\n");
10240                 return false;
10241         }
10242         if (string_to_sid(&sid, "S-1-5-32-+545")) {
10243                 printf("allowing S-1-5-32-+545\n");
10244                 return false;
10245         }
10246         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")) {
10247                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
10248                 return false;
10249         }
10250         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
10251                 printf("allowing S-1-5-32-545-abc\n");
10252                 return false;
10253         }
10254         if (string_to_sid(&sid, "S-300-5-32-545")) {
10255                 printf("allowing S-300-5-32-545\n");
10256                 return false;
10257         }
10258         if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
10259                 printf("allowing S-1-0xfffffffffffffe-32-545\n");
10260                 return false;
10261         }
10262         if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
10263                 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
10264                 return false;
10265         }
10266         if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
10267                 printf("could not parse S-1-0xfffffffffffe-32-545\n");
10268                 return false;
10269         }
10270         if (!string_to_sid(&sid, "S-1-5-32-545")) {
10271                 printf("could not parse S-1-5-32-545\n");
10272                 return false;
10273         }
10274         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
10275                 printf("mis-parsed S-1-5-32-545 as %s\n",
10276                        sid_string_tos(&sid));
10277                 return false;
10278         }
10279         return true;
10280 }
10281
10282 static bool sid_to_string_test(const char *expected) {
10283         char *str;
10284         bool res = true;
10285         struct dom_sid sid;
10286
10287         if (!string_to_sid(&sid, expected)) {
10288                 printf("could not parse %s\n", expected);
10289                 return false;
10290         }
10291
10292         str = dom_sid_string(NULL, &sid);
10293         if (strcmp(str, expected)) {
10294                 printf("Comparison failed (%s != %s)\n", str, expected);
10295                 res = false;
10296         }
10297         TALLOC_FREE(str);
10298         return res;
10299 }
10300
10301 static bool run_local_sid_to_string(int dummy) {
10302         if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
10303                 return false;
10304         if (!sid_to_string_test("S-1-545"))
10305                 return false;
10306         if (!sid_to_string_test("S-255-3840-1-1-1-1"))
10307                 return false;
10308         return true;
10309 }
10310
10311 static bool run_local_binary_to_sid(int dummy) {
10312         struct dom_sid *sid = talloc(NULL, struct dom_sid);
10313         static const uint8_t good_binary_sid[] = {
10314                 0x1, /* revision number */
10315                 15, /* num auths */
10316                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10317                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10318                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10319                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10320                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10321                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10322                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10323                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10324                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10325                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10326                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10327                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10328                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10329                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10330                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10331                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10332         };
10333
10334         static const uint8_t long_binary_sid[] = {
10335                 0x1, /* revision number */
10336                 15, /* num auths */
10337                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10338                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10339                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10340                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10341                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10342                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10343                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10344                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10345                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10346                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10347                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10348                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10349                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10350                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10351                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10352                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10353                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
10354                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
10355                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
10356         };
10357
10358         static const uint8_t long_binary_sid2[] = {
10359                 0x1, /* revision number */
10360                 32, /* num auths */
10361                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10362                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10363                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10364                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10365                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10366                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10367                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10368                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10369                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10370                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10371                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10372                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10373                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10374                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10375                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10376                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10377                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
10378                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
10379                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
10380                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
10381                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
10382                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
10383                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
10384                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
10385                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
10386                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
10387                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
10388                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
10389                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
10390                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
10391                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
10392                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
10393                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
10394         };
10395
10396         if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
10397                 return false;
10398         }
10399         if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
10400                 return false;
10401         }
10402         if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
10403                 return false;
10404         }
10405         return true;
10406 }
10407
10408 /* Split a path name into filename and stream name components. Canonicalise
10409  * such that an implicit $DATA token is always explicit.
10410  *
10411  * The "specification" of this function can be found in the
10412  * run_local_stream_name() function in torture.c, I've tried those
10413  * combinations against a W2k3 server.
10414  */
10415
10416 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
10417                                        char **pbase, char **pstream)
10418 {
10419         char *base = NULL;
10420         char *stream = NULL;
10421         char *sname; /* stream name */
10422         const char *stype; /* stream type */
10423
10424         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
10425
10426         sname = strchr_m(fname, ':');
10427
10428         if (sname == NULL) {
10429                 if (pbase != NULL) {
10430                         base = talloc_strdup(mem_ctx, fname);
10431                         NT_STATUS_HAVE_NO_MEMORY(base);
10432                 }
10433                 goto done;
10434         }
10435
10436         if (pbase != NULL) {
10437                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
10438                 NT_STATUS_HAVE_NO_MEMORY(base);
10439         }
10440
10441         sname += 1;
10442
10443         stype = strchr_m(sname, ':');
10444
10445         if (stype == NULL) {
10446                 sname = talloc_strdup(mem_ctx, sname);
10447                 stype = "$DATA";
10448         }
10449         else {
10450                 if (strcasecmp_m(stype, ":$DATA") != 0) {
10451                         /*
10452                          * If there is an explicit stream type, so far we only
10453                          * allow $DATA. Is there anything else allowed? -- vl
10454                          */
10455                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
10456                         TALLOC_FREE(base);
10457                         return NT_STATUS_OBJECT_NAME_INVALID;
10458                 }
10459                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
10460                 stype += 1;
10461         }
10462
10463         if (sname == NULL) {
10464                 TALLOC_FREE(base);
10465                 return NT_STATUS_NO_MEMORY;
10466         }
10467
10468         if (sname[0] == '\0') {
10469                 /*
10470                  * no stream name, so no stream
10471                  */
10472                 goto done;
10473         }
10474
10475         if (pstream != NULL) {
10476                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
10477                 if (stream == NULL) {
10478                         TALLOC_FREE(sname);
10479                         TALLOC_FREE(base);
10480                         return NT_STATUS_NO_MEMORY;
10481                 }
10482                 /*
10483                  * upper-case the type field
10484                  */
10485                 (void)strupper_m(strchr_m(stream, ':')+1);
10486         }
10487
10488  done:
10489         if (pbase != NULL) {
10490                 *pbase = base;
10491         }
10492         if (pstream != NULL) {
10493                 *pstream = stream;
10494         }
10495         return NT_STATUS_OK;
10496 }
10497
10498 static bool test_stream_name(const char *fname, const char *expected_base,
10499                              const char *expected_stream,
10500                              NTSTATUS expected_status)
10501 {
10502         NTSTATUS status;
10503         char *base = NULL;
10504         char *stream = NULL;
10505
10506         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
10507         if (!NT_STATUS_EQUAL(status, expected_status)) {
10508                 goto error;
10509         }
10510
10511         if (!NT_STATUS_IS_OK(status)) {
10512                 return true;
10513         }
10514
10515         if (base == NULL) goto error;
10516
10517         if (strcmp(expected_base, base) != 0) goto error;
10518
10519         if ((expected_stream != NULL) && (stream == NULL)) goto error;
10520         if ((expected_stream == NULL) && (stream != NULL)) goto error;
10521
10522         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
10523                 goto error;
10524
10525         TALLOC_FREE(base);
10526         TALLOC_FREE(stream);
10527         return true;
10528
10529  error:
10530         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
10531                   fname, expected_base ? expected_base : "<NULL>",
10532                   expected_stream ? expected_stream : "<NULL>",
10533                   nt_errstr(expected_status));
10534         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
10535                   base ? base : "<NULL>", stream ? stream : "<NULL>",
10536                   nt_errstr(status));
10537         TALLOC_FREE(base);
10538         TALLOC_FREE(stream);
10539         return false;
10540 }
10541
10542 static bool run_local_stream_name(int dummy)
10543 {
10544         bool ret = true;
10545
10546         ret &= test_stream_name(
10547                 "bla", "bla", NULL, NT_STATUS_OK);
10548         ret &= test_stream_name(
10549                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
10550         ret &= test_stream_name(
10551                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
10552         ret &= test_stream_name(
10553                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
10554         ret &= test_stream_name(
10555                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
10556         ret &= test_stream_name(
10557                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
10558         ret &= test_stream_name(
10559                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
10560         ret &= test_stream_name(
10561                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
10562
10563         return ret;
10564 }
10565
10566 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
10567 {
10568         if (a.length != b.length) {
10569                 printf("a.length=%d != b.length=%d\n",
10570                        (int)a.length, (int)b.length);
10571                 return false;
10572         }
10573         if (memcmp(a.data, b.data, a.length) != 0) {
10574                 printf("a.data and b.data differ\n");
10575                 return false;
10576         }
10577         return true;
10578 }
10579
10580 static bool run_local_memcache(int dummy)
10581 {
10582         struct memcache *cache;
10583         DATA_BLOB k1, k2;
10584         DATA_BLOB d1, d2, d3;
10585         DATA_BLOB v1, v2, v3;
10586
10587         TALLOC_CTX *mem_ctx;
10588         char *str1, *str2;
10589         size_t size1, size2;
10590         bool ret = false;
10591
10592         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
10593
10594         if (cache == NULL) {
10595                 printf("memcache_init failed\n");
10596                 return false;
10597         }
10598
10599         d1 = data_blob_const("d1", 2);
10600         d2 = data_blob_const("d2", 2);
10601         d3 = data_blob_const("d3", 2);
10602
10603         k1 = data_blob_const("d1", 2);
10604         k2 = data_blob_const("d2", 2);
10605
10606         memcache_add(cache, STAT_CACHE, k1, d1);
10607         memcache_add(cache, GETWD_CACHE, k2, d2);
10608
10609         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
10610                 printf("could not find k1\n");
10611                 return false;
10612         }
10613         if (!data_blob_equal(d1, v1)) {
10614                 return false;
10615         }
10616
10617         if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
10618                 printf("could not find k2\n");
10619                 return false;
10620         }
10621         if (!data_blob_equal(d2, v2)) {
10622                 return false;
10623         }
10624
10625         memcache_add(cache, STAT_CACHE, k1, d3);
10626
10627         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
10628                 printf("could not find replaced k1\n");
10629                 return false;
10630         }
10631         if (!data_blob_equal(d3, v3)) {
10632                 return false;
10633         }
10634
10635         memcache_add(cache, GETWD_CACHE, k1, d1);
10636
10637         if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
10638                 printf("Did find k2, should have been purged\n");
10639                 return false;
10640         }
10641
10642         TALLOC_FREE(cache);
10643
10644         cache = memcache_init(NULL, 0);
10645
10646         mem_ctx = talloc_init("foo");
10647
10648         str1 = talloc_strdup(mem_ctx, "string1");
10649         str2 = talloc_strdup(mem_ctx, "string2");
10650
10651         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
10652                             data_blob_string_const("torture"), &str1);
10653         size1 = talloc_total_size(cache);
10654
10655         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
10656                             data_blob_string_const("torture"), &str2);
10657         size2 = talloc_total_size(cache);
10658
10659         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
10660
10661         if (size2 > size1) {
10662                 printf("memcache leaks memory!\n");
10663                 goto fail;
10664         }
10665
10666         ret = true;
10667  fail:
10668         TALLOC_FREE(cache);
10669         return ret;
10670 }
10671
10672 static void wbclient_done(struct tevent_req *req)
10673 {
10674         wbcErr wbc_err;
10675         struct winbindd_response *wb_resp;
10676         int *i = (int *)tevent_req_callback_data_void(req);
10677
10678         wbc_err = wb_trans_recv(req, req, &wb_resp);
10679         TALLOC_FREE(req);
10680         *i += 1;
10681         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
10682 }
10683
10684 static bool run_wbclient_multi_ping(int dummy)
10685 {
10686         struct tevent_context *ev;
10687         struct wb_context **wb_ctx;
10688         struct winbindd_request wb_req;
10689         bool result = false;
10690         int i, j;
10691
10692         BlockSignals(True, SIGPIPE);
10693
10694         ev = tevent_context_init(talloc_tos());
10695         if (ev == NULL) {
10696                 goto fail;
10697         }
10698
10699         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
10700         if (wb_ctx == NULL) {
10701                 goto fail;
10702         }
10703
10704         ZERO_STRUCT(wb_req);
10705         wb_req.cmd = WINBINDD_PING;
10706
10707         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
10708
10709         for (i=0; i<torture_nprocs; i++) {
10710                 wb_ctx[i] = wb_context_init(ev, NULL);
10711                 if (wb_ctx[i] == NULL) {
10712                         goto fail;
10713                 }
10714                 for (j=0; j<torture_numops; j++) {
10715                         struct tevent_req *req;
10716                         req = wb_trans_send(ev, ev, wb_ctx[i],
10717                                             (j % 2) == 0, &wb_req);
10718                         if (req == NULL) {
10719                                 goto fail;
10720                         }
10721                         tevent_req_set_callback(req, wbclient_done, &i);
10722                 }
10723         }
10724
10725         i = 0;
10726
10727         while (i < torture_nprocs * torture_numops) {
10728                 tevent_loop_once(ev);
10729         }
10730
10731         result = true;
10732  fail:
10733         TALLOC_FREE(ev);
10734         return result;
10735 }
10736
10737 static void getaddrinfo_finished(struct tevent_req *req)
10738 {
10739         char *name = (char *)tevent_req_callback_data_void(req);
10740         struct addrinfo *ainfo;
10741         int res;
10742
10743         res = getaddrinfo_recv(req, &ainfo);
10744         if (res != 0) {
10745                 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
10746                 return;
10747         }
10748         d_printf("gai(%s) succeeded\n", name);
10749         freeaddrinfo(ainfo);
10750 }
10751
10752 static bool run_getaddrinfo_send(int dummy)
10753 {
10754         TALLOC_CTX *frame = talloc_stackframe();
10755         struct fncall_context *ctx;
10756         struct tevent_context *ev;
10757         bool result = false;
10758         const char *names[4] = { "www.samba.org", "notfound.samba.org",
10759                                  "www.slashdot.org", "heise.de" };
10760         struct tevent_req *reqs[4];
10761         int i;
10762
10763         ev = samba_tevent_context_init(frame);
10764         if (ev == NULL) {
10765                 goto fail;
10766         }
10767
10768         ctx = fncall_context_init(frame, 4);
10769
10770         for (i=0; i<ARRAY_SIZE(names); i++) {
10771                 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
10772                                            NULL);
10773                 if (reqs[i] == NULL) {
10774                         goto fail;
10775                 }
10776                 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
10777                                         discard_const_p(void, names[i]));
10778         }
10779
10780         for (i=0; i<ARRAY_SIZE(reqs); i++) {
10781                 tevent_loop_once(ev);
10782         }
10783
10784         result = true;
10785 fail:
10786         TALLOC_FREE(frame);
10787         return result;
10788 }
10789
10790 static bool dbtrans_inc(struct db_context *db)
10791 {
10792         struct db_record *rec;
10793         uint32_t val;
10794         bool ret = false;
10795         NTSTATUS status;
10796         TDB_DATA value;
10797
10798         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
10799         if (rec == NULL) {
10800                 printf(__location__ "fetch_lock failed\n");
10801                 return false;
10802         }
10803
10804         value = dbwrap_record_get_value(rec);
10805
10806         if (value.dsize != sizeof(uint32_t)) {
10807                 printf(__location__ "value.dsize = %d\n",
10808                        (int)value.dsize);
10809                 goto fail;
10810         }
10811
10812         memcpy(&val, value.dptr, sizeof(val));
10813         val += 1;
10814
10815         status = dbwrap_record_store(
10816                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
10817         if (!NT_STATUS_IS_OK(status)) {
10818                 printf(__location__ "store failed: %s\n",
10819                        nt_errstr(status));
10820                 goto fail;
10821         }
10822
10823         ret = true;
10824 fail:
10825         TALLOC_FREE(rec);
10826         return ret;
10827 }
10828
10829 static bool run_local_dbtrans(int dummy)
10830 {
10831         struct db_context *db;
10832         struct db_record *rec;
10833         NTSTATUS status;
10834         uint32_t initial;
10835         int res;
10836         TDB_DATA value;
10837
10838         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
10839                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
10840                      DBWRAP_FLAG_NONE);
10841         if (db == NULL) {
10842                 printf("Could not open transtest.db\n");
10843                 return false;
10844         }
10845
10846         res = dbwrap_transaction_start(db);
10847         if (res != 0) {
10848                 printf(__location__ "transaction_start failed\n");
10849                 return false;
10850         }
10851
10852         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
10853         if (rec == NULL) {
10854                 printf(__location__ "fetch_lock failed\n");
10855                 return false;
10856         }
10857
10858         value = dbwrap_record_get_value(rec);
10859
10860         if (value.dptr == NULL) {
10861                 initial = 0;
10862                 status = dbwrap_record_store(
10863                         rec, make_tdb_data((uint8_t *)&initial,
10864                                            sizeof(initial)),
10865                         0);
10866                 if (!NT_STATUS_IS_OK(status)) {
10867                         printf(__location__ "store returned %s\n",
10868                                nt_errstr(status));
10869                         return false;
10870                 }
10871         }
10872
10873         TALLOC_FREE(rec);
10874
10875         res = dbwrap_transaction_commit(db);
10876         if (res != 0) {
10877                 printf(__location__ "transaction_commit failed\n");
10878                 return false;
10879         }
10880
10881         while (true) {
10882                 uint32_t val, val2;
10883                 int i;
10884
10885                 res = dbwrap_transaction_start(db);
10886                 if (res != 0) {
10887                         printf(__location__ "transaction_start failed\n");
10888                         break;
10889                 }
10890
10891                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
10892                 if (!NT_STATUS_IS_OK(status)) {
10893                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
10894                                nt_errstr(status));
10895                         break;
10896                 }
10897
10898                 for (i=0; i<10; i++) {
10899                         if (!dbtrans_inc(db)) {
10900                                 return false;
10901                         }
10902                 }
10903
10904                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
10905                 if (!NT_STATUS_IS_OK(status)) {
10906                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
10907                                nt_errstr(status));
10908                         break;
10909                 }
10910
10911                 if (val2 != val + 10) {
10912                         printf(__location__ "val=%d, val2=%d\n",
10913                                (int)val, (int)val2);
10914                         break;
10915                 }
10916
10917                 printf("val2=%d\r", val2);
10918
10919                 res = dbwrap_transaction_commit(db);
10920                 if (res != 0) {
10921                         printf(__location__ "transaction_commit failed\n");
10922                         break;
10923                 }
10924         }
10925
10926         TALLOC_FREE(db);
10927         return true;
10928 }
10929
10930 /*
10931  * Just a dummy test to be run under a debugger. There's no real way
10932  * to inspect the tevent_select specific function from outside of
10933  * tevent_select.c.
10934  */
10935
10936 static bool run_local_tevent_select(int dummy)
10937 {
10938         struct tevent_context *ev;
10939         struct tevent_fd *fd1, *fd2;
10940         bool result = false;
10941
10942         ev = tevent_context_init_byname(NULL, "select");
10943         if (ev == NULL) {
10944                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
10945                 goto fail;
10946         }
10947
10948         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
10949         if (fd1 == NULL) {
10950                 d_fprintf(stderr, "tevent_add_fd failed\n");
10951                 goto fail;
10952         }
10953         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
10954         if (fd2 == NULL) {
10955                 d_fprintf(stderr, "tevent_add_fd failed\n");
10956                 goto fail;
10957         }
10958         TALLOC_FREE(fd2);
10959
10960         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
10961         if (fd2 == NULL) {
10962                 d_fprintf(stderr, "tevent_add_fd failed\n");
10963                 goto fail;
10964         }
10965
10966         result = true;
10967 fail:
10968         TALLOC_FREE(ev);
10969         return result;
10970 }
10971
10972 static bool run_local_hex_encode_buf(int dummy)
10973 {
10974         char buf[17];
10975         uint8_t src[8];
10976         int i;
10977
10978         for (i=0; i<sizeof(src); i++) {
10979                 src[i] = i;
10980         }
10981         hex_encode_buf(buf, src, sizeof(src));
10982         if (strcmp(buf, "0001020304050607") != 0) {
10983                 return false;
10984         }
10985         hex_encode_buf(buf, NULL, 0);
10986         if (buf[0] != '\0') {
10987                 return false;
10988         }
10989         return true;
10990 }
10991
10992 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
10993         "0.0.0.0",
10994         "::0",
10995         "1.2.3.1",
10996         "0.0.0.0",
10997         "0.0.0.0",
10998         "1.2.3.2",
10999         "1.2.3.3",
11000         "1.2.3.4",
11001         "1.2.3.5",
11002         "::0",
11003         "1.2.3.6",
11004         "1.2.3.7",
11005         "::0",
11006         "::0",
11007         "::0",
11008         "1.2.3.8",
11009         "1.2.3.9",
11010         "1.2.3.10",
11011         "1.2.3.11",
11012         "1.2.3.12",
11013         "1.2.3.13",
11014         "1001:1111:1111:1000:0:1111:1111:1111",
11015         "1.2.3.1",
11016         "1.2.3.2",
11017         "1.2.3.3",
11018         "1.2.3.12",
11019         "::0",
11020         "::0"
11021 };
11022
11023 static const char *remove_duplicate_addrs2_test_strings_result[] = {
11024         "1.2.3.1",
11025         "1.2.3.2",
11026         "1.2.3.3",
11027         "1.2.3.4",
11028         "1.2.3.5",
11029         "1.2.3.6",
11030         "1.2.3.7",
11031         "1.2.3.8",
11032         "1.2.3.9",
11033         "1.2.3.10",
11034         "1.2.3.11",
11035         "1.2.3.12",
11036         "1.2.3.13",
11037         "1001:1111:1111:1000:0:1111:1111:1111"
11038 };
11039
11040 static bool run_local_remove_duplicate_addrs2(int dummy)
11041 {
11042         struct ip_service test_vector[28];
11043         int count, i;
11044
11045         /* Construct the sockaddr_storage test vector. */
11046         for (i = 0; i < 28; i++) {
11047                 struct addrinfo hints;
11048                 struct addrinfo *res = NULL;
11049                 int ret;
11050
11051                 memset(&hints, '\0', sizeof(hints));
11052                 hints.ai_flags = AI_NUMERICHOST;
11053                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
11054                                 NULL,
11055                                 &hints,
11056                                 &res);
11057                 if (ret) {
11058                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
11059                                 remove_duplicate_addrs2_test_strings_vector[i]);
11060                         return false;
11061                 }
11062                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
11063                 memcpy(&test_vector[i].ss,
11064                         res->ai_addr,
11065                         res->ai_addrlen);
11066                 freeaddrinfo(res);
11067         }
11068
11069         count = remove_duplicate_addrs2(test_vector, i);
11070
11071         if (count != 14) {
11072                 fprintf(stderr, "count wrong (%d) should be 14\n",
11073                         count);
11074                 return false;
11075         }
11076
11077         for (i = 0; i < count; i++) {
11078                 char addr[INET6_ADDRSTRLEN];
11079
11080                 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
11081
11082                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
11083                         fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
11084                                 i,
11085                                 addr,
11086                                 remove_duplicate_addrs2_test_strings_result[i]);
11087                         return false;
11088                 }
11089         }
11090
11091         printf("run_local_remove_duplicate_addrs2: success\n");
11092         return true;
11093 }
11094
11095 static bool run_local_tdb_opener(int dummy)
11096 {
11097         TDB_CONTEXT *t;
11098         unsigned v = 0;
11099
11100         while (1) {
11101                 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
11102                              O_RDWR|O_CREAT, 0755);
11103                 if (t == NULL) {
11104                         perror("tdb_open failed");
11105                         return false;
11106                 }
11107                 tdb_close(t);
11108
11109                 v += 1;
11110                 printf("\r%u", v);
11111         }
11112         return true;
11113 }
11114
11115 static bool run_local_tdb_writer(int dummy)
11116 {
11117         TDB_CONTEXT *t;
11118         unsigned v = 0;
11119         TDB_DATA val;
11120
11121         t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
11122         if (t == 0) {
11123                 perror("tdb_open failed");
11124                 return 1;
11125         }
11126
11127         val.dptr = (uint8_t *)&v;
11128         val.dsize = sizeof(v);
11129
11130         while (1) {
11131                 TDB_DATA data;
11132                 int ret;
11133
11134                 ret = tdb_store(t, val, val, 0);
11135                 if (ret != 0) {
11136                         printf("%s\n", tdb_errorstr(t));
11137                 }
11138                 v += 1;
11139                 printf("\r%u", v);
11140
11141                 data = tdb_fetch(t, val);
11142                 if (data.dptr != NULL) {
11143                         SAFE_FREE(data.dptr);
11144                 }
11145         }
11146         return true;
11147 }
11148
11149 static bool run_local_canonicalize_path(int dummy)
11150 {
11151         const char *src[] = {
11152                         "/foo/..",
11153                         "/..",
11154                         "/foo/bar/../baz",
11155                         "/foo/././",
11156                         "/../foo",
11157                         ".././././",
11158                         ".././././../../../boo",
11159                         "./..",
11160                         NULL
11161                         };
11162         const char *dst[] = {
11163                         "/",
11164                         "/",
11165                         "/foo/baz",
11166                         "/foo",
11167                         "/foo",
11168                         "/",
11169                         "/boo",
11170                         "/",
11171                         NULL
11172                         };
11173         unsigned int i;
11174
11175         for (i = 0; src[i] != NULL; i++) {
11176                 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
11177                 if (d == NULL) {
11178                         perror("talloc fail\n");
11179                         return false;
11180                 }
11181                 if (strcmp(d, dst[i]) != 0) {
11182                         d_fprintf(stderr,
11183                                 "canonicalize missmatch %s -> %s != %s",
11184                                 src[i], d, dst[i]);
11185                         return false;
11186                 }
11187                 talloc_free(d);
11188         }
11189         return true;
11190 }
11191
11192 static bool run_ign_bad_negprot(int dummy)
11193 {
11194         struct tevent_context *ev;
11195         struct tevent_req *req;
11196         struct smbXcli_conn *conn;
11197         struct sockaddr_storage ss;
11198         NTSTATUS status;
11199         int fd;
11200         bool ok;
11201
11202         printf("starting ignore bad negprot\n");
11203
11204         ok = resolve_name(host, &ss, 0x20, true);
11205         if (!ok) {
11206                 d_fprintf(stderr, "Could not resolve name %s\n", host);
11207                 return false;
11208         }
11209
11210         status = open_socket_out(&ss, 445, 10000, &fd);
11211         if (!NT_STATUS_IS_OK(status)) {
11212                 d_fprintf(stderr, "open_socket_out failed: %s\n",
11213                           nt_errstr(status));
11214                 return false;
11215         }
11216
11217         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
11218                                    NULL, 0);
11219         if (conn == NULL) {
11220                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
11221                 return false;
11222         }
11223
11224         status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
11225         if (NT_STATUS_IS_OK(status)) {
11226                 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
11227                 return false;
11228         }
11229
11230         ev = samba_tevent_context_init(talloc_tos());
11231         if (ev == NULL) {
11232                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
11233                 return false;
11234         }
11235
11236         req = smb1cli_session_setup_nt1_send(
11237                 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
11238                 data_blob_null, data_blob_null, 0x40,
11239                 "Windows 2000 2195", "Windows 2000 5.0");
11240         if (req == NULL) {
11241                 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
11242                 return false;
11243         }
11244
11245         ok = tevent_req_poll_ntstatus(req, ev, &status);
11246         if (!ok) {
11247                 d_fprintf(stderr, "tevent_req_poll failed\n");
11248                 return false;
11249         }
11250
11251         status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
11252                                                 NULL, NULL);
11253         if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
11254                 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
11255                           "%s, expected NT_STATUS_CONNECTION_RESET\n",
11256                           nt_errstr(status));
11257                 return false;
11258         }
11259
11260         TALLOC_FREE(conn);
11261
11262         printf("starting ignore bad negprot\n");
11263
11264         return true;
11265 }
11266
11267 static double create_procs(bool (*fn)(int), bool *result)
11268 {
11269         int i, status;
11270         volatile pid_t *child_status;
11271         volatile bool *child_status_out;
11272         int synccount;
11273         int tries = 8;
11274         struct timeval start;
11275
11276         synccount = 0;
11277
11278         child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
11279         if (!child_status) {
11280                 printf("Failed to setup shared memory\n");
11281                 return -1;
11282         }
11283
11284         child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
11285         if (!child_status_out) {
11286                 printf("Failed to setup result status shared memory\n");
11287                 return -1;
11288         }
11289
11290         for (i = 0; i < torture_nprocs; i++) {
11291                 child_status[i] = 0;
11292                 child_status_out[i] = True;
11293         }
11294
11295         start = timeval_current();
11296
11297         for (i=0;i<torture_nprocs;i++) {
11298                 procnum = i;
11299                 if (fork() == 0) {
11300                         pid_t mypid = getpid();
11301                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
11302
11303                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
11304
11305                         while (1) {
11306                                 if (torture_open_connection(&current_cli, i)) break;
11307                                 if (tries-- == 0) {
11308                                         printf("pid %d failed to start\n", (int)getpid());
11309                                         _exit(1);
11310                                 }
11311                                 smb_msleep(10); 
11312                         }
11313
11314                         child_status[i] = getpid();
11315
11316                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
11317
11318                         child_status_out[i] = fn(i);
11319                         _exit(0);
11320                 }
11321         }
11322
11323         do {
11324                 synccount = 0;
11325                 for (i=0;i<torture_nprocs;i++) {
11326                         if (child_status[i]) synccount++;
11327                 }
11328                 if (synccount == torture_nprocs) break;
11329                 smb_msleep(10);
11330         } while (timeval_elapsed(&start) < 30);
11331
11332         if (synccount != torture_nprocs) {
11333                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
11334                 *result = False;
11335                 return timeval_elapsed(&start);
11336         }
11337
11338         /* start the client load */
11339         start = timeval_current();
11340
11341         for (i=0;i<torture_nprocs;i++) {
11342                 child_status[i] = 0;
11343         }
11344
11345         printf("%d clients started\n", torture_nprocs);
11346
11347         for (i=0;i<torture_nprocs;i++) {
11348                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
11349         }
11350
11351         printf("\n");
11352
11353         for (i=0;i<torture_nprocs;i++) {
11354                 if (!child_status_out[i]) {
11355                         *result = False;
11356                 }
11357         }
11358         return timeval_elapsed(&start);
11359 }
11360
11361 #define FLAG_MULTIPROC 1
11362
11363 static struct {
11364         const char *name;
11365         bool (*fn)(int);
11366         unsigned flags;
11367 } torture_ops[] = {
11368         {"FDPASS", run_fdpasstest, 0},
11369         {"LOCK1",  run_locktest1,  0},
11370         {"LOCK2",  run_locktest2,  0},
11371         {"LOCK3",  run_locktest3,  0},
11372         {"LOCK4",  run_locktest4,  0},
11373         {"LOCK5",  run_locktest5,  0},
11374         {"LOCK6",  run_locktest6,  0},
11375         {"LOCK7",  run_locktest7,  0},
11376         {"LOCK8",  run_locktest8,  0},
11377         {"LOCK9",  run_locktest9,  0},
11378         {"UNLINK", run_unlinktest, 0},
11379         {"BROWSE", run_browsetest, 0},
11380         {"ATTR",   run_attrtest,   0},
11381         {"TRANS2", run_trans2test, 0},
11382         {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
11383         {"TORTURE",run_torture,    FLAG_MULTIPROC},
11384         {"RANDOMIPC", run_randomipc, 0},
11385         {"NEGNOWAIT", run_negprot_nowait, 0},
11386         {"NBENCH",  run_nbench, 0},
11387         {"NBENCH2", run_nbench2, 0},
11388         {"OPLOCK1",  run_oplock1, 0},
11389         {"OPLOCK2",  run_oplock2, 0},
11390         {"OPLOCK4",  run_oplock4, 0},
11391         {"DIR",  run_dirtest, 0},
11392         {"DIR1",  run_dirtest1, 0},
11393         {"DIR-CREATETIME",  run_dir_createtime, 0},
11394         {"DENY1",  torture_denytest1, 0},
11395         {"DENY2",  torture_denytest2, 0},
11396         {"TCON",  run_tcon_test, 0},
11397         {"TCONDEV",  run_tcon_devtype_test, 0},
11398         {"RW1",  run_readwritetest, 0},
11399         {"RW2",  run_readwritemulti, FLAG_MULTIPROC},
11400         {"RW3",  run_readwritelarge, 0},
11401         {"RW-SIGNING",  run_readwritelarge_signtest, 0},
11402         {"OPEN", run_opentest, 0},
11403         {"POSIX", run_simple_posix_open_test, 0},
11404         {"POSIX-APPEND", run_posix_append, 0},
11405         {"POSIX-SYMLINK-ACL", run_acl_symlink_test, 0},
11406         {"POSIX-SYMLINK-EA", run_ea_symlink_test, 0},
11407         {"POSIX-STREAM-DELETE", run_posix_stream_delete, 0},
11408         {"POSIX-OFD-LOCK", run_posix_ofd_lock_test, 0},
11409         {"WINDOWS-BAD-SYMLINK", run_symlink_open_test, 0},
11410         {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
11411         {"ASYNC-ECHO", run_async_echo, 0},
11412         { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
11413         { "SHORTNAME-TEST", run_shortname_test, 0},
11414         { "ADDRCHANGE", run_addrchange, 0},
11415 #if 1
11416         {"OPENATTR", run_openattrtest, 0},
11417 #endif
11418         {"XCOPY", run_xcopy, 0},
11419         {"RENAME", run_rename, 0},
11420         {"RENAME-ACCESS", run_rename_access, 0},
11421         {"OWNER-RIGHTS", run_owner_rights, 0},
11422         {"DELETE", run_deletetest, 0},
11423         {"WILDDELETE", run_wild_deletetest, 0},
11424         {"DELETE-LN", run_deletetest_ln, 0},
11425         {"PROPERTIES", run_properties, 0},
11426         {"MANGLE", torture_mangle, 0},
11427         {"MANGLE1", run_mangle1, 0},
11428         {"MANGLE-ILLEGAL", run_mangle_illegal, 0},
11429         {"W2K", run_w2ktest, 0},
11430         {"TRANS2SCAN", torture_trans2_scan, 0},
11431         {"NTTRANSSCAN", torture_nttrans_scan, 0},
11432         {"UTABLE", torture_utable, 0},
11433         {"CASETABLE", torture_casetable, 0},
11434         {"ERRMAPEXTRACT", run_error_map_extract, 0},
11435         {"PIPE_NUMBER", run_pipe_number, 0},
11436         {"TCON2",  run_tcon2_test, 0},
11437         {"IOCTL",  torture_ioctl_test, 0},
11438         {"CHKPATH",  torture_chkpath_test, 0},
11439         {"FDSESS", run_fdsesstest, 0},
11440         { "EATEST", run_eatest, 0},
11441         { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
11442         { "CHAIN1", run_chain1, 0},
11443         { "CHAIN2", run_chain2, 0},
11444         { "CHAIN3", run_chain3, 0},
11445         { "WINDOWS-WRITE", run_windows_write, 0},
11446         { "LARGE_READX", run_large_readx, 0},
11447         { "NTTRANS-CREATE", run_nttrans_create, 0},
11448         { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
11449         { "CLI_ECHO", run_cli_echo, 0},
11450         { "GETADDRINFO", run_getaddrinfo_send, 0},
11451         { "TLDAP", run_tldap },
11452         { "STREAMERROR", run_streamerror },
11453         { "NOTIFY-BENCH", run_notify_bench },
11454         { "NOTIFY-BENCH2", run_notify_bench2 },
11455         { "NOTIFY-BENCH3", run_notify_bench3 },
11456         { "BAD-NBT-SESSION", run_bad_nbt_session },
11457         { "IGN-BAD-NEGPROT", run_ign_bad_negprot },
11458         { "SMB-ANY-CONNECT", run_smb_any_connect },
11459         { "NOTIFY-ONLINE", run_notify_online },
11460         { "SMB2-BASIC", run_smb2_basic },
11461         { "SMB2-NEGPROT", run_smb2_negprot },
11462         { "SMB2-SESSION-RECONNECT", run_smb2_session_reconnect },
11463         { "SMB2-TCON-DEPENDENCE", run_smb2_tcon_dependence },
11464         { "SMB2-MULTI-CHANNEL", run_smb2_multi_channel },
11465         { "SMB2-SESSION-REAUTH", run_smb2_session_reauth },
11466         { "SMB2-FTRUNCATE", run_smb2_ftruncate },
11467         { "CLEANUP1", run_cleanup1 },
11468         { "CLEANUP2", run_cleanup2 },
11469         { "CLEANUP3", run_cleanup3 },
11470         { "CLEANUP4", run_cleanup4 },
11471         { "OPLOCK-CANCEL", run_oplock_cancel },
11472         { "PIDHIGH", run_pidhigh },
11473         { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
11474         { "LOCAL-GENCACHE", run_local_gencache, 0},
11475         { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
11476         { "LOCAL-DBWRAP-WATCH1", run_dbwrap_watch1, 0 },
11477         { "LOCAL-DBWRAP-WATCH2", run_dbwrap_watch2, 0 },
11478         { "LOCAL-MESSAGING-READ1", run_messaging_read1, 0 },
11479         { "LOCAL-MESSAGING-READ2", run_messaging_read2, 0 },
11480         { "LOCAL-MESSAGING-READ3", run_messaging_read3, 0 },
11481         { "LOCAL-MESSAGING-READ4", run_messaging_read4, 0 },
11482         { "LOCAL-MESSAGING-FDPASS1", run_messaging_fdpass1, 0 },
11483         { "LOCAL-MESSAGING-FDPASS2", run_messaging_fdpass2, 0 },
11484         { "LOCAL-MESSAGING-FDPASS2a", run_messaging_fdpass2a, 0 },
11485         { "LOCAL-MESSAGING-FDPASS2b", run_messaging_fdpass2b, 0 },
11486         { "LOCAL-BASE64", run_local_base64, 0},
11487         { "LOCAL-RBTREE", run_local_rbtree, 0},
11488         { "LOCAL-MEMCACHE", run_local_memcache, 0},
11489         { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
11490         { "WBCLIENT-MULTI-PING", run_wbclient_multi_ping, 0},
11491         { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
11492         { "LOCAL-sid_to_string", run_local_sid_to_string, 0},
11493         { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
11494         { "LOCAL-DBTRANS", run_local_dbtrans, 0},
11495         { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
11496         { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
11497         { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
11498         { "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0},
11499         { "LOCAL-IDMAP-TDB-COMMON", run_idmap_tdb_common_test, 0},
11500         { "LOCAL-remove_duplicate_addrs2", run_local_remove_duplicate_addrs2, 0},
11501         { "local-tdb-opener", run_local_tdb_opener, 0 },
11502         { "local-tdb-writer", run_local_tdb_writer, 0 },
11503         { "LOCAL-DBWRAP-CTDB", run_local_dbwrap_ctdb, 0 },
11504         { "LOCAL-BENCH-PTHREADPOOL", run_bench_pthreadpool, 0 },
11505         { "LOCAL-PTHREADPOOL-TEVENT", run_pthreadpool_tevent, 0 },
11506         { "LOCAL-G-LOCK1", run_g_lock1, 0 },
11507         { "LOCAL-G-LOCK2", run_g_lock2, 0 },
11508         { "LOCAL-G-LOCK3", run_g_lock3, 0 },
11509         { "LOCAL-G-LOCK4", run_g_lock4, 0 },
11510         { "LOCAL-G-LOCK5", run_g_lock5, 0 },
11511         { "LOCAL-CANONICALIZE-PATH", run_local_canonicalize_path, 0 },
11512         { "qpathinfo-bufsize", run_qpathinfo_bufsize, 0 },
11513         {NULL, NULL, 0}};
11514
11515 /*
11516  * dummy function to satisfy linker dependency
11517  */
11518 struct tevent_context *winbind_event_context(void);
11519 struct tevent_context *winbind_event_context(void)
11520 {
11521         return NULL;
11522 }
11523
11524 /****************************************************************************
11525 run a specified test or "ALL"
11526 ****************************************************************************/
11527 static bool run_test(const char *name)
11528 {
11529         bool ret = True;
11530         bool result = True;
11531         bool found = False;
11532         int i;
11533         double t;
11534         if (strequal(name,"ALL")) {
11535                 for (i=0;torture_ops[i].name;i++) {
11536                         run_test(torture_ops[i].name);
11537                 }
11538                 found = True;
11539         }
11540
11541         for (i=0;torture_ops[i].name;i++) {
11542                 fstr_sprintf(randomfname, "\\XX%x", 
11543                          (unsigned)random());
11544
11545                 if (strequal(name, torture_ops[i].name)) {
11546                         found = True;
11547                         printf("Running %s\n", name);
11548                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
11549                                 t = create_procs(torture_ops[i].fn, &result);
11550                                 if (!result) { 
11551                                         ret = False;
11552                                         printf("TEST %s FAILED!\n", name);
11553                                 }
11554                         } else {
11555                                 struct timeval start;
11556                                 start = timeval_current();
11557                                 if (!torture_ops[i].fn(0)) {
11558                                         ret = False;
11559                                         printf("TEST %s FAILED!\n", name);
11560                                 }
11561                                 t = timeval_elapsed(&start);
11562                         }
11563                         printf("%s took %g secs\n\n", name, t);
11564                 }
11565         }
11566
11567         if (!found) {
11568                 printf("Did not find a test named %s\n", name);
11569                 ret = False;
11570         }
11571
11572         return ret;
11573 }
11574
11575
11576 static void usage(void)
11577 {
11578         int i;
11579
11580         printf("WARNING samba4 test suite is much more complete nowadays.\n");
11581         printf("Please use samba4 torture.\n\n");
11582
11583         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
11584
11585         printf("\t-d debuglevel\n");
11586         printf("\t-U user%%pass\n");
11587         printf("\t-k                    use kerberos\n");
11588         printf("\t-N numprocs\n");
11589         printf("\t-n my_netbios_name\n");
11590         printf("\t-W workgroup\n");
11591         printf("\t-o num_operations\n");
11592         printf("\t-O socket_options\n");
11593         printf("\t-m maximum protocol\n");
11594         printf("\t-L use oplocks\n");
11595         printf("\t-c CLIENT.TXT         specify client load file for NBENCH\n");
11596         printf("\t-A showall\n");
11597         printf("\t-p port\n");
11598         printf("\t-s seed\n");
11599         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
11600         printf("\t-f filename           filename to test\n");
11601         printf("\t-e                    encrypt\n");
11602         printf("\n\n");
11603
11604         printf("tests are:");
11605         for (i=0;torture_ops[i].name;i++) {
11606                 printf(" %s", torture_ops[i].name);
11607         }
11608         printf("\n");
11609
11610         printf("default test is ALL\n");
11611
11612         exit(1);
11613 }
11614
11615 /****************************************************************************
11616   main program
11617 ****************************************************************************/
11618  int main(int argc,char *argv[])
11619 {
11620         int opt, i;
11621         char *p;
11622         int gotuser = 0;
11623         int gotpass = 0;
11624         bool correct = True;
11625         TALLOC_CTX *frame = talloc_stackframe();
11626         int seed = time(NULL);
11627
11628 #ifdef HAVE_SETBUFFER
11629         setbuffer(stdout, NULL, 0);
11630 #endif
11631
11632         setup_logging("smbtorture", DEBUG_STDOUT);
11633
11634         smb_init_locale();
11635         fault_setup();
11636
11637         if (is_default_dyn_CONFIGFILE()) {
11638                 if(getenv("SMB_CONF_PATH")) {
11639                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
11640                 }
11641         }
11642         lp_load_global(get_dyn_CONFIGFILE());
11643         load_interfaces();
11644
11645         if (argc < 2) {
11646                 usage();
11647         }
11648
11649         for(p = argv[1]; *p; p++)
11650           if(*p == '\\')
11651             *p = '/';
11652
11653         if (strncmp(argv[1], "//", 2)) {
11654                 usage();
11655         }
11656
11657         fstrcpy(host, &argv[1][2]);
11658         p = strchr_m(&host[2],'/');
11659         if (!p) {
11660                 usage();
11661         }
11662         *p = 0;
11663         fstrcpy(share, p+1);
11664
11665         fstrcpy(myname, get_myname(talloc_tos()));
11666         if (!*myname) {
11667                 fprintf(stderr, "Failed to get my hostname.\n");
11668                 return 1;
11669         }
11670
11671         if (*username == 0 && getenv("LOGNAME")) {
11672           fstrcpy(username,getenv("LOGNAME"));
11673         }
11674
11675         argc--;
11676         argv++;
11677
11678         fstrcpy(workgroup, lp_workgroup());
11679
11680         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
11681                != EOF) {
11682                 switch (opt) {
11683                 case 'p':
11684                         port_to_use = atoi(optarg);
11685                         break;
11686                 case 's':
11687                         seed = atoi(optarg);
11688                         break;
11689                 case 'W':
11690                         fstrcpy(workgroup,optarg);
11691                         break;
11692                 case 'm':
11693                         lp_set_cmdline("client max protocol", optarg);
11694                         break;
11695                 case 'N':
11696                         torture_nprocs = atoi(optarg);
11697                         break;
11698                 case 'o':
11699                         torture_numops = atoi(optarg);
11700                         break;
11701                 case 'd':
11702                         lp_set_cmdline("log level", optarg);
11703                         break;
11704                 case 'O':
11705                         sockops = optarg;
11706                         break;
11707                 case 'L':
11708                         use_oplocks = True;
11709                         break;
11710                 case 'l':
11711                         local_path = optarg;
11712                         break;
11713                 case 'A':
11714                         torture_showall = True;
11715                         break;
11716                 case 'n':
11717                         fstrcpy(myname, optarg);
11718                         break;
11719                 case 'c':
11720                         client_txt = optarg;
11721                         break;
11722                 case 'e':
11723                         do_encrypt = true;
11724                         break;
11725                 case 'k':
11726 #ifdef HAVE_KRB5
11727                         use_kerberos = True;
11728 #else
11729                         d_printf("No kerberos support compiled in\n");
11730                         exit(1);
11731 #endif
11732                         break;
11733                 case 'U':
11734                         gotuser = 1;
11735                         fstrcpy(username,optarg);
11736                         p = strchr_m(username,'%');
11737                         if (p) {
11738                                 *p = 0;
11739                                 fstrcpy(password, p+1);
11740                                 gotpass = 1;
11741                         }
11742                         break;
11743                 case 'b':
11744                         fstrcpy(multishare_conn_fname, optarg);
11745                         use_multishare_conn = True;
11746                         break;
11747                 case 'B':
11748                         torture_blocksize = atoi(optarg);
11749                         break;
11750                 case 'f':
11751                         test_filename = SMB_STRDUP(optarg);
11752                         break;
11753                 default:
11754                         printf("Unknown option %c (%d)\n", (char)opt, opt);
11755                         usage();
11756                 }
11757         }
11758
11759         d_printf("using seed %d\n", seed);
11760
11761         srandom(seed);
11762
11763         if(use_kerberos && !gotuser) gotpass = True;
11764
11765         while (!gotpass) {
11766                 char pwd[256] = {0};
11767                 int rc;
11768
11769                 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
11770                 if (rc == 0) {
11771                         fstrcpy(password, pwd);
11772                         gotpass = 1;
11773                 }
11774         }
11775
11776         printf("host=%s share=%s user=%s myname=%s\n", 
11777                host, share, username, myname);
11778
11779         torture_creds = cli_session_creds_init(frame,
11780                                                username,
11781                                                workgroup,
11782                                                NULL, /* realm */
11783                                                password,
11784                                                use_kerberos,
11785                                                false, /* fallback_after_kerberos */
11786                                                false, /* use_ccache */
11787                                                false); /* password_is_nt_hash */
11788         if (torture_creds == NULL) {
11789                 d_printf("cli_session_creds_init() failed.\n");
11790                 exit(1);
11791         }
11792
11793         if (argc == optind) {
11794                 correct = run_test("ALL");
11795         } else {
11796                 for (i=optind;i<argc;i++) {
11797                         if (!run_test(argv[i])) {
11798                                 correct = False;
11799                         }
11800                 }
11801         }
11802
11803         TALLOC_FREE(frame);
11804
11805         if (correct) {
11806                 return(0);
11807         } else {
11808                 return(1);
11809         }
11810 }