torture: Add local-g-lock-ping-pong
[ambi/samba-autobuild/.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 static bool check_attributes(struct cli_state *cli,
3166                                 const char *fname,
3167                                 uint16_t expected_attrs)
3168 {
3169         uint16_t attrs = 0;
3170         NTSTATUS status = cli_getatr(cli,
3171                                 fname,
3172                                 &attrs,
3173                                 NULL,
3174                                 NULL);
3175         if (!NT_STATUS_IS_OK(status)) {
3176                 printf("cli_getatr failed with %s\n",
3177                         nt_errstr(status));
3178                 return false;
3179         }
3180         if (attrs != expected_attrs) {
3181                 printf("Attributes incorrect 0x%x, should be 0x%x\n",
3182                         (unsigned int)attrs,
3183                         (unsigned int)expected_attrs);
3184                 return false;
3185         }
3186         return true;
3187 }
3188
3189 /*
3190   This checks how the getatr calls works
3191 */
3192 static bool run_attrtest(int dummy)
3193 {
3194         struct cli_state *cli;
3195         uint16_t fnum;
3196         time_t t, t2;
3197         const char *fname = "\\attrib123456789.tst";
3198         bool correct = True;
3199         NTSTATUS status;
3200
3201         printf("starting attrib test\n");
3202
3203         if (!torture_open_connection(&cli, 0)) {
3204                 return False;
3205         }
3206
3207         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3208         cli_openx(cli, fname, 
3209                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3210         cli_close(cli, fnum);
3211
3212         status = cli_getatr(cli, fname, NULL, NULL, &t);
3213         if (!NT_STATUS_IS_OK(status)) {
3214                 printf("getatr failed (%s)\n", nt_errstr(status));
3215                 correct = False;
3216         }
3217
3218         if (abs(t - time(NULL)) > 60*60*24*10) {
3219                 printf("ERROR: SMBgetatr bug. time is %s",
3220                        ctime(&t));
3221                 t = time(NULL);
3222                 correct = True;
3223         }
3224
3225         t2 = t-60*60*24; /* 1 day ago */
3226
3227         status = cli_setatr(cli, fname, 0, t2);
3228         if (!NT_STATUS_IS_OK(status)) {
3229                 printf("setatr failed (%s)\n", nt_errstr(status));
3230                 correct = True;
3231         }
3232
3233         status = cli_getatr(cli, fname, NULL, NULL, &t);
3234         if (!NT_STATUS_IS_OK(status)) {
3235                 printf("getatr failed (%s)\n", nt_errstr(status));
3236                 correct = True;
3237         }
3238
3239         if (t != t2) {
3240                 printf("ERROR: getatr/setatr bug. times are\n%s",
3241                        ctime(&t));
3242                 printf("%s", ctime(&t2));
3243                 correct = True;
3244         }
3245
3246         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3247
3248         /* Check cli_setpathinfo_basic() */
3249         /* Re-create the file. */
3250         status = cli_openx(cli, fname,
3251                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3252         if (!NT_STATUS_IS_OK(status)) {
3253                 printf("Failed to recreate %s (%s)\n",
3254                         fname, nt_errstr(status));
3255                 correct = false;
3256         }
3257         cli_close(cli, fnum);
3258
3259         status = cli_setpathinfo_basic(cli,
3260                                         fname,
3261                                         0, /* create */
3262                                         0, /* access */
3263                                         0, /* write */
3264                                         0, /* change */
3265                                         FILE_ATTRIBUTE_SYSTEM |
3266                                         FILE_ATTRIBUTE_HIDDEN |
3267                                         FILE_ATTRIBUTE_READONLY);
3268         if (!NT_STATUS_IS_OK(status)) {
3269                 printf("cli_setpathinfo_basic failed with %s\n",
3270                         nt_errstr(status));
3271                 correct = false;
3272         }
3273
3274         /* Check attributes are correct. */
3275         correct = check_attributes(cli,
3276                         fname,
3277                         FILE_ATTRIBUTE_SYSTEM |
3278                         FILE_ATTRIBUTE_HIDDEN |
3279                         FILE_ATTRIBUTE_READONLY);
3280         if (correct == false) {
3281                 goto out;
3282         }
3283
3284         /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
3285         status = cli_setpathinfo_basic(cli,
3286                                         fname,
3287                                         0, /* create */
3288                                         0, /* access */
3289                                         0, /* write */
3290                                         0, /* change */
3291                                         FILE_ATTRIBUTE_NORMAL);
3292         if (!NT_STATUS_IS_OK(status)) {
3293                 printf("cli_setpathinfo_basic failed with %s\n",
3294                         nt_errstr(status));
3295                 correct = false;
3296         }
3297
3298         /* Check attributes are correct. */
3299         correct = check_attributes(cli,
3300                         fname,
3301                         FILE_ATTRIBUTE_SYSTEM |
3302                         FILE_ATTRIBUTE_HIDDEN |
3303                         FILE_ATTRIBUTE_READONLY);
3304         if (correct == false) {
3305                 goto out;
3306         }
3307
3308         /* Setting to (uint16_t)-1 should also be ignored. */
3309         status = cli_setpathinfo_basic(cli,
3310                                         fname,
3311                                         0, /* create */
3312                                         0, /* access */
3313                                         0, /* write */
3314                                         0, /* change */
3315                                         (uint16_t)-1);
3316         if (!NT_STATUS_IS_OK(status)) {
3317                 printf("cli_setpathinfo_basic failed with %s\n",
3318                         nt_errstr(status));
3319                 correct = false;
3320         }
3321
3322         /* Check attributes are correct. */
3323         correct = check_attributes(cli,
3324                         fname,
3325                         FILE_ATTRIBUTE_SYSTEM |
3326                         FILE_ATTRIBUTE_HIDDEN |
3327                         FILE_ATTRIBUTE_READONLY);
3328         if (correct == false) {
3329                 goto out;
3330         }
3331
3332         /* Setting to 0 should clear them all. */
3333         status = cli_setpathinfo_basic(cli,
3334                                         fname,
3335                                         0, /* create */
3336                                         0, /* access */
3337                                         0, /* write */
3338                                         0, /* change */
3339                                         0);
3340         if (!NT_STATUS_IS_OK(status)) {
3341                 printf("cli_setpathinfo_basic failed with %s\n",
3342                         nt_errstr(status));
3343                 correct = false;
3344         }
3345
3346         /* Check attributes are correct. */
3347         correct = check_attributes(cli,
3348                         fname,
3349                         FILE_ATTRIBUTE_NORMAL);
3350         if (correct == false) {
3351                 goto out;
3352         }
3353
3354   out:
3355
3356         cli_unlink(cli,
3357                 fname,
3358                 FILE_ATTRIBUTE_SYSTEM |
3359                 FILE_ATTRIBUTE_HIDDEN|
3360                 FILE_ATTRIBUTE_READONLY);
3361
3362         if (!torture_close_connection(cli)) {
3363                 correct = False;
3364         }
3365
3366         printf("attrib test finished\n");
3367
3368         return correct;
3369 }
3370
3371
3372 /*
3373   This checks a couple of trans2 calls
3374 */
3375 static bool run_trans2test(int dummy)
3376 {
3377         struct cli_state *cli;
3378         uint16_t fnum;
3379         off_t size;
3380         time_t c_time, a_time, m_time;
3381         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3382         const char *fname = "\\trans2.tst";
3383         const char *dname = "\\trans2";
3384         const char *fname2 = "\\trans2\\trans2.tst";
3385         char *pname;
3386         bool correct = True;
3387         NTSTATUS status;
3388         uint32_t fs_attr;
3389
3390         printf("starting trans2 test\n");
3391
3392         if (!torture_open_connection(&cli, 0)) {
3393                 return False;
3394         }
3395
3396         status = cli_get_fs_attr_info(cli, &fs_attr);
3397         if (!NT_STATUS_IS_OK(status)) {
3398                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3399                        nt_errstr(status));
3400                 correct = false;
3401         }
3402
3403         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3404         cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3405         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3406                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3407         if (!NT_STATUS_IS_OK(status)) {
3408                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3409                 correct = False;
3410         }
3411
3412         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3413         if (!NT_STATUS_IS_OK(status)) {
3414                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3415                 correct = False;
3416         }
3417         else if (strcmp(pname, fname)) {
3418                 printf("qfilename gave different name? [%s] [%s]\n",
3419                        fname, pname);
3420                 correct = False;
3421         }
3422
3423         cli_close(cli, fnum);
3424
3425         sleep(2);
3426
3427         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3428         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3429                           &fnum);
3430         if (!NT_STATUS_IS_OK(status)) {
3431                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3432                 return False;
3433         }
3434         cli_close(cli, fnum);
3435
3436         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3437                                 NULL);
3438         if (!NT_STATUS_IS_OK(status)) {
3439                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3440                 correct = False;
3441         } else {
3442                 time_t t = time(NULL);
3443
3444                 if (c_time != m_time) {
3445                         printf("create time=%s", ctime(&c_time));
3446                         printf("modify time=%s", ctime(&m_time));
3447                         printf("This system appears to have sticky create times\n");
3448                 }
3449                 if ((abs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
3450                         printf("access time=%s", ctime(&a_time));
3451                         printf("This system appears to set a midnight access time\n");
3452                         correct = False;
3453                 }
3454
3455                 if (abs(m_time - t) > 60*60*24*7) {
3456                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3457                         correct = False;
3458                 }
3459         }
3460
3461
3462         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3463         cli_openx(cli, fname, 
3464                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3465         cli_close(cli, fnum);
3466         status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3467                                 &m_time_ts, &size, NULL, NULL);
3468         if (!NT_STATUS_IS_OK(status)) {
3469                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3470                 correct = False;
3471         } else {
3472                 if (w_time_ts.tv_sec < 60*60*24*2) {
3473                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
3474                         printf("This system appears to set a initial 0 write time\n");
3475                         correct = False;
3476                 }
3477         }
3478
3479         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3480
3481
3482         /* check if the server updates the directory modification time
3483            when creating a new file */
3484         status = cli_mkdir(cli, dname);
3485         if (!NT_STATUS_IS_OK(status)) {
3486                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3487                 correct = False;
3488         }
3489         sleep(3);
3490         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3491                                 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3492         if (!NT_STATUS_IS_OK(status)) {
3493                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3494                 correct = False;
3495         }
3496
3497         cli_openx(cli, fname2, 
3498                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3499         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3500         cli_close(cli, fnum);
3501         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3502                                 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3503         if (!NT_STATUS_IS_OK(status)) {
3504                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3505                 correct = False;
3506         } else {
3507                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3508                     == 0) {
3509                         printf("This system does not update directory modification times\n");
3510                         correct = False;
3511                 }
3512         }
3513         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3514         cli_rmdir(cli, dname);
3515
3516         if (!torture_close_connection(cli)) {
3517                 correct = False;
3518         }
3519
3520         printf("trans2 test finished\n");
3521
3522         return correct;
3523 }
3524
3525 /*
3526   This checks new W2K calls.
3527 */
3528
3529 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3530 {
3531         uint8_t *buf = NULL;
3532         uint32_t len;
3533         NTSTATUS status;
3534
3535         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3536                                CLI_BUFFER_SIZE, NULL, &buf, &len);
3537         if (!NT_STATUS_IS_OK(status)) {
3538                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3539                        nt_errstr(status));
3540         } else {
3541                 printf("qfileinfo: level %d, len = %u\n", level, len);
3542                 dump_data(0, (uint8_t *)buf, len);
3543                 printf("\n");
3544         }
3545         TALLOC_FREE(buf);
3546         return status;
3547 }
3548
3549 static bool run_w2ktest(int dummy)
3550 {
3551         struct cli_state *cli;
3552         uint16_t fnum;
3553         const char *fname = "\\w2ktest\\w2k.tst";
3554         int level;
3555         bool correct = True;
3556
3557         printf("starting w2k test\n");
3558
3559         if (!torture_open_connection(&cli, 0)) {
3560                 return False;
3561         }
3562
3563         cli_openx(cli, fname, 
3564                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
3565
3566         for (level = 1004; level < 1040; level++) {
3567                 new_trans(cli, fnum, level);
3568         }
3569
3570         cli_close(cli, fnum);
3571
3572         if (!torture_close_connection(cli)) {
3573                 correct = False;
3574         }
3575
3576         printf("w2k test finished\n");
3577
3578         return correct;
3579 }
3580
3581
3582 /*
3583   this is a harness for some oplock tests
3584  */
3585 static bool run_oplock1(int dummy)
3586 {
3587         struct cli_state *cli1;
3588         const char *fname = "\\lockt1.lck";
3589         uint16_t fnum1;
3590         bool correct = True;
3591         NTSTATUS status;
3592
3593         printf("starting oplock test 1\n");
3594
3595         if (!torture_open_connection(&cli1, 0)) {
3596                 return False;
3597         }
3598
3599         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3600
3601         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3602
3603         cli1->use_oplocks = True;
3604
3605         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3606                           &fnum1);
3607         if (!NT_STATUS_IS_OK(status)) {
3608                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3609                 return False;
3610         }
3611
3612         cli1->use_oplocks = False;
3613
3614         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3615         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3616
3617         status = cli_close(cli1, fnum1);
3618         if (!NT_STATUS_IS_OK(status)) {
3619                 printf("close2 failed (%s)\n", nt_errstr(status));
3620                 return False;
3621         }
3622
3623         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3624         if (!NT_STATUS_IS_OK(status)) {
3625                 printf("unlink failed (%s)\n", nt_errstr(status));
3626                 return False;
3627         }
3628
3629         if (!torture_close_connection(cli1)) {
3630                 correct = False;
3631         }
3632
3633         printf("finished oplock test 1\n");
3634
3635         return correct;
3636 }
3637
3638 static bool run_oplock2(int dummy)
3639 {
3640         struct cli_state *cli1, *cli2;
3641         const char *fname = "\\lockt2.lck";
3642         uint16_t fnum1, fnum2;
3643         int saved_use_oplocks = use_oplocks;
3644         char buf[4];
3645         bool correct = True;
3646         volatile bool *shared_correct;
3647         size_t nread;
3648         NTSTATUS status;
3649
3650         shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
3651         *shared_correct = True;
3652
3653         use_level_II_oplocks = True;
3654         use_oplocks = True;
3655
3656         printf("starting oplock test 2\n");
3657
3658         if (!torture_open_connection(&cli1, 0)) {
3659                 use_level_II_oplocks = False;
3660                 use_oplocks = saved_use_oplocks;
3661                 return False;
3662         }
3663
3664         if (!torture_open_connection(&cli2, 1)) {
3665                 use_level_II_oplocks = False;
3666                 use_oplocks = saved_use_oplocks;
3667                 return False;
3668         }
3669
3670         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3671
3672         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3673         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3674
3675         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3676                           &fnum1);
3677         if (!NT_STATUS_IS_OK(status)) {
3678                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3679                 return False;
3680         }
3681
3682         /* Don't need the globals any more. */
3683         use_level_II_oplocks = False;
3684         use_oplocks = saved_use_oplocks;
3685
3686         if (fork() == 0) {
3687                 /* Child code */
3688                 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3689                 if (!NT_STATUS_IS_OK(status)) {
3690                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3691                         *shared_correct = False;
3692                         exit(0);
3693                 }
3694
3695                 sleep(2);
3696
3697                 status = cli_close(cli2, fnum2);
3698                 if (!NT_STATUS_IS_OK(status)) {
3699                         printf("close2 failed (%s)\n", nt_errstr(status));
3700                         *shared_correct = False;
3701                 }
3702
3703                 exit(0);
3704         }
3705
3706         sleep(2);
3707
3708         /* Ensure cli1 processes the break. Empty file should always return 0
3709          * bytes.  */
3710         status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
3711         if (!NT_STATUS_IS_OK(status)) {
3712                 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
3713                 correct = false;
3714         } else if (nread != 0) {
3715                 printf("read on empty fnum1 failed. recv %ld expected %d\n",
3716                       (unsigned long)nread, 0);
3717                 correct = false;
3718         }
3719
3720         /* Should now be at level II. */
3721         /* Test if sending a write locks causes a break to none. */
3722         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3723         if (!NT_STATUS_IS_OK(status)) {
3724                 printf("lock failed (%s)\n", nt_errstr(status));
3725                 correct = False;
3726         }
3727
3728         cli_unlock(cli1, fnum1, 0, 4);
3729
3730         sleep(2);
3731
3732         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3733         if (!NT_STATUS_IS_OK(status)) {
3734                 printf("lock failed (%s)\n", nt_errstr(status));
3735                 correct = False;
3736         }
3737
3738         cli_unlock(cli1, fnum1, 0, 4);
3739
3740         sleep(2);
3741
3742         cli_read(cli1, fnum1, buf, 0, 4, NULL);
3743
3744         status = cli_close(cli1, fnum1);
3745         if (!NT_STATUS_IS_OK(status)) {
3746                 printf("close1 failed (%s)\n", nt_errstr(status));
3747                 correct = False;
3748         }
3749
3750         sleep(4);
3751
3752         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3753         if (!NT_STATUS_IS_OK(status)) {
3754                 printf("unlink failed (%s)\n", nt_errstr(status));
3755                 correct = False;
3756         }
3757
3758         if (!torture_close_connection(cli1)) {
3759                 correct = False;
3760         }
3761
3762         if (!*shared_correct) {
3763                 correct = False;
3764         }
3765
3766         printf("finished oplock test 2\n");
3767
3768         return correct;
3769 }
3770
3771 struct oplock4_state {
3772         struct tevent_context *ev;
3773         struct cli_state *cli;
3774         bool *got_break;
3775         uint16_t *fnum2;
3776 };
3777
3778 static void oplock4_got_break(struct tevent_req *req);
3779 static void oplock4_got_open(struct tevent_req *req);
3780
3781 static bool run_oplock4(int dummy)
3782 {
3783         struct tevent_context *ev;
3784         struct cli_state *cli1, *cli2;
3785         struct tevent_req *oplock_req, *open_req;
3786         const char *fname = "\\lockt4.lck";
3787         const char *fname_ln = "\\lockt4_ln.lck";
3788         uint16_t fnum1, fnum2;
3789         int saved_use_oplocks = use_oplocks;
3790         NTSTATUS status;
3791         bool correct = true;
3792
3793         bool got_break;
3794
3795         struct oplock4_state *state;
3796
3797         printf("starting oplock test 4\n");
3798
3799         if (!torture_open_connection(&cli1, 0)) {
3800                 use_level_II_oplocks = false;
3801                 use_oplocks = saved_use_oplocks;
3802                 return false;
3803         }
3804
3805         if (!torture_open_connection(&cli2, 1)) {
3806                 use_level_II_oplocks = false;
3807                 use_oplocks = saved_use_oplocks;
3808                 return false;
3809         }
3810
3811         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3812         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3813
3814         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3815         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3816
3817         /* Create the file. */
3818         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3819                           &fnum1);
3820         if (!NT_STATUS_IS_OK(status)) {
3821                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3822                 return false;
3823         }
3824
3825         status = cli_close(cli1, fnum1);
3826         if (!NT_STATUS_IS_OK(status)) {
3827                 printf("close1 failed (%s)\n", nt_errstr(status));
3828                 return false;
3829         }
3830
3831         /* Now create a hardlink. */
3832         status = cli_nt_hardlink(cli1, fname, fname_ln);
3833         if (!NT_STATUS_IS_OK(status)) {
3834                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3835                 return false;
3836         }
3837
3838         /* Prove that opening hardlinks cause deny modes to conflict. */
3839         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3840         if (!NT_STATUS_IS_OK(status)) {
3841                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3842                 return false;
3843         }
3844
3845         status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3846         if (NT_STATUS_IS_OK(status)) {
3847                 printf("open of %s succeeded - should fail with sharing violation.\n",
3848                         fname_ln);
3849                 return false;
3850         }
3851
3852         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3853                 printf("open of %s should fail with sharing violation. Got %s\n",
3854                         fname_ln, nt_errstr(status));
3855                 return false;
3856         }
3857
3858         status = cli_close(cli1, fnum1);
3859         if (!NT_STATUS_IS_OK(status)) {
3860                 printf("close1 failed (%s)\n", nt_errstr(status));
3861                 return false;
3862         }
3863
3864         cli1->use_oplocks = true;
3865         cli2->use_oplocks = true;
3866
3867         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3868         if (!NT_STATUS_IS_OK(status)) {
3869                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3870                 return false;
3871         }
3872
3873         ev = samba_tevent_context_init(talloc_tos());
3874         if (ev == NULL) {
3875                 printf("tevent_context_init failed\n");
3876                 return false;
3877         }
3878
3879         state = talloc(ev, struct oplock4_state);
3880         if (state == NULL) {
3881                 printf("talloc failed\n");
3882                 return false;
3883         }
3884         state->ev = ev;
3885         state->cli = cli1;
3886         state->got_break = &got_break;
3887         state->fnum2 = &fnum2;
3888
3889         oplock_req = cli_smb_oplock_break_waiter_send(
3890                 talloc_tos(), ev, cli1);
3891         if (oplock_req == NULL) {
3892                 printf("cli_smb_oplock_break_waiter_send failed\n");
3893                 return false;
3894         }
3895         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3896
3897         open_req = cli_openx_send(
3898                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3899         if (open_req == NULL) {
3900                 printf("cli_openx_send failed\n");
3901                 return false;
3902         }
3903         tevent_req_set_callback(open_req, oplock4_got_open, state);
3904
3905         got_break = false;
3906         fnum2 = 0xffff;
3907
3908         while (!got_break || fnum2 == 0xffff) {
3909                 int ret;
3910                 ret = tevent_loop_once(ev);
3911                 if (ret == -1) {
3912                         printf("tevent_loop_once failed: %s\n",
3913                                strerror(errno));
3914                         return false;
3915                 }
3916         }
3917
3918         status = cli_close(cli2, fnum2);
3919         if (!NT_STATUS_IS_OK(status)) {
3920                 printf("close2 failed (%s)\n", nt_errstr(status));
3921                 correct = false;
3922         }
3923
3924         status = cli_close(cli1, fnum1);
3925         if (!NT_STATUS_IS_OK(status)) {
3926                 printf("close1 failed (%s)\n", nt_errstr(status));
3927                 correct = false;
3928         }
3929
3930         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3931         if (!NT_STATUS_IS_OK(status)) {
3932                 printf("unlink failed (%s)\n", nt_errstr(status));
3933                 correct = false;
3934         }
3935
3936         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3937         if (!NT_STATUS_IS_OK(status)) {
3938                 printf("unlink failed (%s)\n", nt_errstr(status));
3939                 correct = false;
3940         }
3941
3942         if (!torture_close_connection(cli1)) {
3943                 correct = false;
3944         }
3945
3946         if (!got_break) {
3947                 correct = false;
3948         }
3949
3950         printf("finished oplock test 4\n");
3951
3952         return correct;
3953 }
3954
3955 static void oplock4_got_break(struct tevent_req *req)
3956 {
3957         struct oplock4_state *state = tevent_req_callback_data(
3958                 req, struct oplock4_state);
3959         uint16_t fnum;
3960         uint8_t level;
3961         NTSTATUS status;
3962
3963         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3964         TALLOC_FREE(req);
3965         if (!NT_STATUS_IS_OK(status)) {
3966                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3967                        nt_errstr(status));
3968                 return;
3969         }
3970         *state->got_break = true;
3971
3972         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3973                                   NO_OPLOCK);
3974         if (req == NULL) {
3975                 printf("cli_oplock_ack_send failed\n");
3976                 return;
3977         }
3978 }
3979
3980 static void oplock4_got_open(struct tevent_req *req)
3981 {
3982         struct oplock4_state *state = tevent_req_callback_data(
3983                 req, struct oplock4_state);
3984         NTSTATUS status;
3985
3986         status = cli_openx_recv(req, state->fnum2);
3987         if (!NT_STATUS_IS_OK(status)) {
3988                 printf("cli_openx_recv returned %s\n", nt_errstr(status));
3989                 *state->fnum2 = 0xffff;
3990         }
3991 }
3992
3993 /*
3994   Test delete on close semantics.
3995  */
3996 static bool run_deletetest(int dummy)
3997 {
3998         struct cli_state *cli1 = NULL;
3999         struct cli_state *cli2 = NULL;
4000         const char *fname = "\\delete.file";
4001         uint16_t fnum1 = (uint16_t)-1;
4002         uint16_t fnum2 = (uint16_t)-1;
4003         bool correct = false;
4004         NTSTATUS status;
4005
4006         printf("starting delete test\n");
4007
4008         if (!torture_open_connection(&cli1, 0)) {
4009                 return False;
4010         }
4011
4012         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4013
4014         /* Test 1 - this should delete the file on close. */
4015
4016         cli_setatr(cli1, fname, 0, 0);
4017         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4018
4019         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
4020                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4021                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4022         if (!NT_STATUS_IS_OK(status)) {
4023                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
4024                 goto fail;
4025         }
4026
4027         status = cli_close(cli1, fnum1);
4028         if (!NT_STATUS_IS_OK(status)) {
4029                 printf("[1] close failed (%s)\n", nt_errstr(status));
4030                 goto fail;
4031         }
4032
4033         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4034         if (NT_STATUS_IS_OK(status)) {
4035                 printf("[1] open of %s succeeded (should fail)\n", fname);
4036                 goto fail;
4037         }
4038
4039         printf("first delete on close test succeeded.\n");
4040
4041         /* Test 2 - this should delete the file on close. */
4042
4043         cli_setatr(cli1, fname, 0, 0);
4044         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4045
4046         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
4047                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4048                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4049         if (!NT_STATUS_IS_OK(status)) {
4050                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
4051                 goto fail;
4052         }
4053
4054         status = cli_nt_delete_on_close(cli1, fnum1, true);
4055         if (!NT_STATUS_IS_OK(status)) {
4056                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
4057                 goto fail;
4058         }
4059
4060         status = cli_close(cli1, fnum1);
4061         if (!NT_STATUS_IS_OK(status)) {
4062                 printf("[2] close failed (%s)\n", nt_errstr(status));
4063                 goto fail;
4064         }
4065
4066         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4067         if (NT_STATUS_IS_OK(status)) {
4068                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
4069                 status = cli_close(cli1, fnum1);
4070                 if (!NT_STATUS_IS_OK(status)) {
4071                         printf("[2] close failed (%s)\n", nt_errstr(status));
4072                 }
4073                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4074                 goto fail;
4075         }
4076
4077         printf("second delete on close test succeeded.\n");
4078
4079         /* Test 3 - ... */
4080         cli_setatr(cli1, fname, 0, 0);
4081         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4082
4083         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
4084                               FILE_ATTRIBUTE_NORMAL,
4085                               FILE_SHARE_READ|FILE_SHARE_WRITE,
4086                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4087         if (!NT_STATUS_IS_OK(status)) {
4088                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
4089                 goto fail;
4090         }
4091
4092         /* This should fail with a sharing violation - open for delete is only compatible
4093            with SHARE_DELETE. */
4094
4095         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4096                               FILE_ATTRIBUTE_NORMAL,
4097                               FILE_SHARE_READ|FILE_SHARE_WRITE,
4098                               FILE_OPEN, 0, 0, &fnum2, NULL);
4099         if (NT_STATUS_IS_OK(status)) {
4100                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
4101                 goto fail;
4102         }
4103
4104         /* This should succeed. */
4105         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4106                              FILE_ATTRIBUTE_NORMAL,
4107                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4108                              FILE_OPEN, 0, 0, &fnum2, NULL);
4109         if (!NT_STATUS_IS_OK(status)) {
4110                 printf("[3] open  - 3 of %s failed (%s)\n", fname, nt_errstr(status));
4111                 goto fail;
4112         }
4113
4114         status = cli_nt_delete_on_close(cli1, fnum1, true);
4115         if (!NT_STATUS_IS_OK(status)) {
4116                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
4117                 goto fail;
4118         }
4119
4120         status = cli_close(cli1, fnum1);
4121         if (!NT_STATUS_IS_OK(status)) {
4122                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
4123                 goto fail;
4124         }
4125
4126         status = cli_close(cli1, fnum2);
4127         if (!NT_STATUS_IS_OK(status)) {
4128                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
4129                 goto fail;
4130         }
4131
4132         /* This should fail - file should no longer be there. */
4133
4134         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4135         if (NT_STATUS_IS_OK(status)) {
4136                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
4137                 status = cli_close(cli1, fnum1);
4138                 if (!NT_STATUS_IS_OK(status)) {
4139                         printf("[3] close failed (%s)\n", nt_errstr(status));
4140                 }
4141                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4142                 goto fail;
4143         }
4144
4145         printf("third delete on close test succeeded.\n");
4146
4147         /* Test 4 ... */
4148         cli_setatr(cli1, fname, 0, 0);
4149         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4150
4151         status = cli_ntcreate(cli1, fname, 0,
4152                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4153                               FILE_ATTRIBUTE_NORMAL,
4154                               FILE_SHARE_READ|FILE_SHARE_WRITE,
4155                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4156         if (!NT_STATUS_IS_OK(status)) {
4157                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4158                 goto fail;
4159         }
4160
4161         /* This should succeed. */
4162         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4163                              FILE_ATTRIBUTE_NORMAL,
4164                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4165                              FILE_OPEN, 0, 0, &fnum2, NULL);
4166         if (!NT_STATUS_IS_OK(status)) {
4167                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4168                 goto fail;
4169         }
4170
4171         status = cli_close(cli1, fnum2);
4172         if (!NT_STATUS_IS_OK(status)) {
4173                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4174                 goto fail;
4175         }
4176
4177         status = cli_nt_delete_on_close(cli1, fnum1, true);
4178         if (!NT_STATUS_IS_OK(status)) {
4179                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4180                 goto fail;
4181         }
4182
4183         /* This should fail - no more opens once delete on close set. */
4184         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4185                               FILE_ATTRIBUTE_NORMAL,
4186                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4187                               FILE_OPEN, 0, 0, &fnum2, NULL);
4188         if (NT_STATUS_IS_OK(status)) {
4189                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
4190                 goto fail;
4191         }
4192
4193         status = cli_close(cli1, fnum1);
4194         if (!NT_STATUS_IS_OK(status)) {
4195                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4196                 goto fail;
4197         }
4198
4199         printf("fourth delete on close test succeeded.\n");
4200
4201         /* Test 5 ... */
4202         cli_setatr(cli1, fname, 0, 0);
4203         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4204
4205         status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4206         if (!NT_STATUS_IS_OK(status)) {
4207                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4208                 goto fail;
4209         }
4210
4211         /* This should fail - only allowed on NT opens with DELETE access. */
4212
4213         status = cli_nt_delete_on_close(cli1, fnum1, true);
4214         if (NT_STATUS_IS_OK(status)) {
4215                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4216                 goto fail;
4217         }
4218
4219         status = cli_close(cli1, fnum1);
4220         if (!NT_STATUS_IS_OK(status)) {
4221                 printf("[5] close failed (%s)\n", nt_errstr(status));
4222                 goto fail;
4223         }
4224
4225         printf("fifth delete on close test succeeded.\n");
4226
4227         /* Test 6 ... */
4228         cli_setatr(cli1, fname, 0, 0);
4229         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4230
4231         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4232                              FILE_ATTRIBUTE_NORMAL,
4233                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4234                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4235         if (!NT_STATUS_IS_OK(status)) {
4236                 printf("[6] open of %s failed (%s)\n", fname,
4237                        nt_errstr(status));
4238                 goto fail;
4239         }
4240
4241         /* This should fail - only allowed on NT opens with DELETE access. */
4242
4243         status = cli_nt_delete_on_close(cli1, fnum1, true);
4244         if (NT_STATUS_IS_OK(status)) {
4245                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4246                 goto fail;
4247         }
4248
4249         status = cli_close(cli1, fnum1);
4250         if (!NT_STATUS_IS_OK(status)) {
4251                 printf("[6] close failed (%s)\n", nt_errstr(status));
4252                 goto fail;
4253         }
4254
4255         printf("sixth delete on close test succeeded.\n");
4256
4257         /* Test 7 ... */
4258         cli_setatr(cli1, fname, 0, 0);
4259         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4260
4261         status = cli_ntcreate(cli1, fname, 0,
4262                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4263                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4264                               0, 0, &fnum1, NULL);
4265         if (!NT_STATUS_IS_OK(status)) {
4266                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4267                 goto fail;
4268         }
4269
4270         status = cli_nt_delete_on_close(cli1, fnum1, true);
4271         if (!NT_STATUS_IS_OK(status)) {
4272                 printf("[7] setting delete_on_close on file failed !\n");
4273                 goto fail;
4274         }
4275
4276         status = cli_nt_delete_on_close(cli1, fnum1, false);
4277         if (!NT_STATUS_IS_OK(status)) {
4278                 printf("[7] unsetting delete_on_close on file failed !\n");
4279                 goto fail;
4280         }
4281
4282         status = cli_close(cli1, fnum1);
4283         if (!NT_STATUS_IS_OK(status)) {
4284                 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
4285                 goto fail;
4286         }
4287
4288         /* This next open should succeed - we reset the flag. */
4289         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4290         if (!NT_STATUS_IS_OK(status)) {
4291                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4292                 goto fail;
4293         }
4294
4295         status = cli_close(cli1, fnum1);
4296         if (!NT_STATUS_IS_OK(status)) {
4297                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4298                 goto fail;
4299         }
4300
4301         printf("seventh delete on close test succeeded.\n");
4302
4303         /* Test 8 ... */
4304         cli_setatr(cli1, fname, 0, 0);
4305         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4306
4307         if (!torture_open_connection(&cli2, 1)) {
4308                 printf("[8] failed to open second connection.\n");
4309                 goto fail;
4310         }
4311
4312         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4313
4314         status = cli_ntcreate(cli1, fname, 0,
4315                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4316                              FILE_ATTRIBUTE_NORMAL,
4317                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4318                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4319         if (!NT_STATUS_IS_OK(status)) {
4320                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4321                 goto fail;
4322         }
4323
4324         status = cli_ntcreate(cli2, fname, 0,
4325                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4326                              FILE_ATTRIBUTE_NORMAL,
4327                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4328                              FILE_OPEN, 0, 0, &fnum2, NULL);
4329         if (!NT_STATUS_IS_OK(status)) {
4330                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4331                 goto fail;
4332         }
4333
4334         status = cli_nt_delete_on_close(cli1, fnum1, true);
4335         if (!NT_STATUS_IS_OK(status)) {
4336                 printf("[8] setting delete_on_close on file failed !\n");
4337                 goto fail;
4338         }
4339
4340         status = cli_close(cli1, fnum1);
4341         if (!NT_STATUS_IS_OK(status)) {
4342                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4343                 goto fail;
4344         }
4345
4346         status = cli_close(cli2, fnum2);
4347         if (!NT_STATUS_IS_OK(status)) {
4348                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4349                 goto fail;
4350         }
4351
4352         /* This should fail.. */
4353         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4354         if (NT_STATUS_IS_OK(status)) {
4355                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4356                 goto fail;
4357         }
4358
4359         printf("eighth delete on close test succeeded.\n");
4360
4361         /* Test 9 ... */
4362
4363         /* This should fail - we need to set DELETE_ACCESS. */
4364         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4365                               FILE_ATTRIBUTE_NORMAL,
4366                               FILE_SHARE_NONE,
4367                               FILE_OVERWRITE_IF,
4368                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4369         if (NT_STATUS_IS_OK(status)) {
4370                 printf("[9] open of %s succeeded should have failed!\n", fname);
4371                 goto fail;
4372         }
4373
4374         printf("ninth delete on close test succeeded.\n");
4375
4376         /* Test 10 ... */
4377
4378         status = cli_ntcreate(cli1, fname, 0,
4379                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4380                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4381                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4382                              0, &fnum1, NULL);
4383         if (!NT_STATUS_IS_OK(status)) {
4384                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4385                 goto fail;
4386         }
4387
4388         /* This should delete the file. */
4389         status = cli_close(cli1, fnum1);
4390         if (!NT_STATUS_IS_OK(status)) {
4391                 printf("[10] close failed (%s)\n", nt_errstr(status));
4392                 goto fail;
4393         }
4394
4395         /* This should fail.. */
4396         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4397         if (NT_STATUS_IS_OK(status)) {
4398                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4399                 goto fail;
4400         }
4401
4402         printf("tenth delete on close test succeeded.\n");
4403
4404         /* Test 11 ... */
4405
4406         cli_setatr(cli1, fname, 0, 0);
4407         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4408
4409         /* Can we open a read-only file with delete access? */
4410
4411         /* Create a readonly file. */
4412         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4413                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4414                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4415         if (!NT_STATUS_IS_OK(status)) {
4416                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4417                 goto fail;
4418         }
4419
4420         status = cli_close(cli1, fnum1);
4421         if (!NT_STATUS_IS_OK(status)) {
4422                 printf("[11] close failed (%s)\n", nt_errstr(status));
4423                 goto fail;
4424         }
4425
4426         /* Now try open for delete access. */
4427         status = cli_ntcreate(cli1, fname, 0,
4428                              FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4429                              0,
4430                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4431                              FILE_OPEN, 0, 0, &fnum1, NULL);
4432         if (!NT_STATUS_IS_OK(status)) {
4433                 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
4434                 goto fail;
4435         }
4436
4437         cli_close(cli1, fnum1);
4438
4439         printf("eleventh delete on close test succeeded.\n");
4440
4441         /*
4442          * Test 12
4443          * like test 4 but with initial delete on close
4444          */
4445
4446         cli_setatr(cli1, fname, 0, 0);
4447         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4448
4449         status = cli_ntcreate(cli1, fname, 0,
4450                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4451                               FILE_ATTRIBUTE_NORMAL,
4452                               FILE_SHARE_READ|FILE_SHARE_WRITE,
4453                               FILE_OVERWRITE_IF,
4454                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4455         if (!NT_STATUS_IS_OK(status)) {
4456                 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4457                 goto fail;
4458         }
4459
4460         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4461                               FILE_ATTRIBUTE_NORMAL,
4462                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4463                               FILE_OPEN, 0, 0, &fnum2, NULL);
4464         if (!NT_STATUS_IS_OK(status)) {
4465                 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
4466                 goto fail;
4467         }
4468
4469         status = cli_close(cli1, fnum2);
4470         if (!NT_STATUS_IS_OK(status)) {
4471                 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
4472                 goto fail;
4473         }
4474
4475         status = cli_nt_delete_on_close(cli1, fnum1, true);
4476         if (!NT_STATUS_IS_OK(status)) {
4477                 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
4478                 goto fail;
4479         }
4480
4481         /* This should fail - no more opens once delete on close set. */
4482         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4483                               FILE_ATTRIBUTE_NORMAL,
4484                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4485                               FILE_OPEN, 0, 0, &fnum2, NULL);
4486         if (NT_STATUS_IS_OK(status)) {
4487                 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
4488                 goto fail;
4489         }
4490
4491         status = cli_nt_delete_on_close(cli1, fnum1, false);
4492         if (!NT_STATUS_IS_OK(status)) {
4493                 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
4494                 goto fail;
4495         }
4496
4497         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4498                               FILE_ATTRIBUTE_NORMAL,
4499                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4500                               FILE_OPEN, 0, 0, &fnum2, NULL);
4501         if (!NT_STATUS_IS_OK(status)) {
4502                 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
4503                 goto fail;
4504         }
4505
4506         status = cli_close(cli1, fnum2);
4507         if (!NT_STATUS_IS_OK(status)) {
4508                 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
4509                 goto fail;
4510         }
4511
4512         status = cli_close(cli1, fnum1);
4513         if (!NT_STATUS_IS_OK(status)) {
4514                 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
4515                 goto fail;
4516         }
4517
4518         /*
4519          * setting delete on close on the handle does
4520          * not unset the initial delete on close...
4521          */
4522         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4523                               FILE_ATTRIBUTE_NORMAL,
4524                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4525                               FILE_OPEN, 0, 0, &fnum2, NULL);
4526         if (NT_STATUS_IS_OK(status)) {
4527                 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
4528                 goto fail;
4529         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4530                 printf("ntcreate returned %s, expected "
4531                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
4532                        nt_errstr(status));
4533                 goto fail;
4534         }
4535
4536         printf("twelfth delete on close test succeeded.\n");
4537
4538
4539         printf("finished delete test\n");
4540
4541         correct = true;
4542
4543   fail:
4544         /* FIXME: This will crash if we aborted before cli2 got
4545          * intialized, because these functions don't handle
4546          * uninitialized connections. */
4547
4548         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4549         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4550         cli_setatr(cli1, fname, 0, 0);
4551         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4552
4553         if (cli1 && !torture_close_connection(cli1)) {
4554                 correct = False;
4555         }
4556         if (cli2 && !torture_close_connection(cli2)) {
4557                 correct = False;
4558         }
4559         return correct;
4560 }
4561
4562
4563 /*
4564   Test wildcard delete.
4565  */
4566 static bool run_wild_deletetest(int dummy)
4567 {
4568         struct cli_state *cli = NULL;
4569         const char *dname = "\\WTEST";
4570         const char *fname = "\\WTEST\\A";
4571         const char *wunlink_name = "\\WTEST\\*";
4572         uint16_t fnum1 = (uint16_t)-1;
4573         bool correct = false;
4574         NTSTATUS status;
4575
4576         printf("starting wildcard delete test\n");
4577
4578         if (!torture_open_connection(&cli, 0)) {
4579                 return false;
4580         }
4581
4582         smbXcli_conn_set_sockopt(cli->conn, sockops);
4583
4584         cli_unlink(cli, fname, 0);
4585         cli_rmdir(cli, dname);
4586         status = cli_mkdir(cli, dname);
4587         if (!NT_STATUS_IS_OK(status)) {
4588                 printf("mkdir of %s failed %s!\n", dname, nt_errstr(status));
4589                 goto fail;
4590         }
4591         status = cli_openx(cli, fname, O_CREAT|O_RDONLY, DENY_NONE, &fnum1);
4592         if (!NT_STATUS_IS_OK(status)) {
4593                 printf("open of %s failed %s!\n", fname, nt_errstr(status));
4594                 goto fail;
4595         }
4596         status = cli_close(cli, fnum1);
4597         fnum1 = -1;
4598
4599         /*
4600          * Note the unlink attribute-type of zero. This should
4601          * map into FILE_ATTRIBUTE_NORMAL at the server even
4602          * on a wildcard delete.
4603          */
4604
4605         status = cli_unlink(cli, wunlink_name, 0);
4606         if (!NT_STATUS_IS_OK(status)) {
4607                 printf("unlink of %s failed %s!\n",
4608                         wunlink_name, nt_errstr(status));
4609                 goto fail;
4610         }
4611
4612         printf("finished wildcard delete test\n");
4613
4614         correct = true;
4615
4616   fail:
4617
4618         if (fnum1 != (uint16_t)-1) cli_close(cli, fnum1);
4619         cli_unlink(cli, fname, 0);
4620         cli_rmdir(cli, dname);
4621
4622         if (cli && !torture_close_connection(cli)) {
4623                 correct = false;
4624         }
4625         return correct;
4626 }
4627
4628 static bool run_deletetest_ln(int dummy)
4629 {
4630         struct cli_state *cli;
4631         const char *fname = "\\delete1";
4632         const char *fname_ln = "\\delete1_ln";
4633         uint16_t fnum;
4634         uint16_t fnum1;
4635         NTSTATUS status;
4636         bool correct = true;
4637         time_t t;
4638
4639         printf("starting deletetest-ln\n");
4640
4641         if (!torture_open_connection(&cli, 0)) {
4642                 return false;
4643         }
4644
4645         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4646         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4647
4648         smbXcli_conn_set_sockopt(cli->conn, sockops);
4649
4650         /* Create the file. */
4651         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4652         if (!NT_STATUS_IS_OK(status)) {
4653                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4654                 return false;
4655         }
4656
4657         status = cli_close(cli, fnum);
4658         if (!NT_STATUS_IS_OK(status)) {
4659                 printf("close1 failed (%s)\n", nt_errstr(status));
4660                 return false;
4661         }
4662
4663         /* Now create a hardlink. */
4664         status = cli_nt_hardlink(cli, fname, fname_ln);
4665         if (!NT_STATUS_IS_OK(status)) {
4666                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4667                 return false;
4668         }
4669
4670         /* Open the original file. */
4671         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4672                         FILE_ATTRIBUTE_NORMAL,
4673                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4674                         FILE_OPEN_IF, 0, 0, &fnum, NULL);
4675         if (!NT_STATUS_IS_OK(status)) {
4676                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4677                 return false;
4678         }
4679
4680         /* Unlink the hard link path. */
4681         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4682                         FILE_ATTRIBUTE_NORMAL,
4683                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4684                         FILE_OPEN_IF, 0, 0, &fnum1, NULL);
4685         if (!NT_STATUS_IS_OK(status)) {
4686                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4687                 return false;
4688         }
4689         status = cli_nt_delete_on_close(cli, fnum1, true);
4690         if (!NT_STATUS_IS_OK(status)) {
4691                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4692                         __location__, fname_ln, nt_errstr(status));
4693                 return false;
4694         }
4695
4696         status = cli_close(cli, fnum1);
4697         if (!NT_STATUS_IS_OK(status)) {
4698                 printf("close %s failed (%s)\n",
4699                         fname_ln, nt_errstr(status));
4700                 return false;
4701         }
4702
4703         status = cli_close(cli, fnum);
4704         if (!NT_STATUS_IS_OK(status)) {
4705                 printf("close %s failed (%s)\n",
4706                         fname, nt_errstr(status));
4707                 return false;
4708         }
4709
4710         /* Ensure the original file is still there. */
4711         status = cli_getatr(cli, fname, NULL, NULL, &t);
4712         if (!NT_STATUS_IS_OK(status)) {
4713                 printf("%s getatr on file %s failed (%s)\n",
4714                         __location__,
4715                         fname,
4716                         nt_errstr(status));
4717                 correct = False;
4718         }
4719
4720         /* Ensure the link path is gone. */
4721         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4722         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4723                 printf("%s, getatr for file %s returned wrong error code %s "
4724                         "- should have been deleted\n",
4725                         __location__,
4726                         fname_ln, nt_errstr(status));
4727                 correct = False;
4728         }
4729
4730         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4731         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4732
4733         if (!torture_close_connection(cli)) {
4734                 correct = false;
4735         }
4736
4737         printf("finished deletetest-ln\n");
4738
4739         return correct;
4740 }
4741
4742 /*
4743   print out server properties
4744  */
4745 static bool run_properties(int dummy)
4746 {
4747         struct cli_state *cli;
4748         bool correct = True;
4749
4750         printf("starting properties test\n");
4751
4752         ZERO_STRUCT(cli);
4753
4754         if (!torture_open_connection(&cli, 0)) {
4755                 return False;
4756         }
4757
4758         smbXcli_conn_set_sockopt(cli->conn, sockops);
4759
4760         d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
4761
4762         if (!torture_close_connection(cli)) {
4763                 correct = False;
4764         }
4765
4766         return correct;
4767 }
4768
4769
4770
4771 /* FIRST_DESIRED_ACCESS   0xf019f */
4772 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4773                                FILE_READ_EA|                           /* 0xf */ \
4774                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
4775                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
4776                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
4777                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
4778 /* SECOND_DESIRED_ACCESS  0xe0080 */
4779 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4780                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4781                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
4782
4783 #if 0
4784 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4785                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4786                                FILE_READ_DATA|\
4787                                WRITE_OWNER_ACCESS                      /* */
4788 #endif
4789
4790 /*
4791   Test ntcreate calls made by xcopy
4792  */
4793 static bool run_xcopy(int dummy)
4794 {
4795         static struct cli_state *cli1;
4796         const char *fname = "\\test.txt";
4797         bool correct = True;
4798         uint16_t fnum1, fnum2;
4799         NTSTATUS status;
4800
4801         printf("starting xcopy test\n");
4802
4803         if (!torture_open_connection(&cli1, 0)) {
4804                 return False;
4805         }
4806
4807         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4808                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4809                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
4810         if (!NT_STATUS_IS_OK(status)) {
4811                 printf("First open failed - %s\n", nt_errstr(status));
4812                 return False;
4813         }
4814
4815         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4816                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4817                              FILE_OPEN, 0x200000, 0, &fnum2, NULL);
4818         if (!NT_STATUS_IS_OK(status)) {
4819                 printf("second open failed - %s\n", nt_errstr(status));
4820                 return False;
4821         }
4822
4823         if (!torture_close_connection(cli1)) {
4824                 correct = False;
4825         }
4826
4827         return correct;
4828 }
4829
4830 /*
4831   Test rename on files open with share delete and no share delete.
4832  */
4833 static bool run_rename(int dummy)
4834 {
4835         static struct cli_state *cli1;
4836         const char *fname = "\\test.txt";
4837         const char *fname1 = "\\test1.txt";
4838         bool correct = True;
4839         uint16_t fnum1;
4840         uint16_t attr;
4841         NTSTATUS status;
4842
4843         printf("starting rename test\n");
4844
4845         if (!torture_open_connection(&cli1, 0)) {
4846                 return False;
4847         }
4848
4849         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4850         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4851
4852         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4853                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4854                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4855         if (!NT_STATUS_IS_OK(status)) {
4856                 printf("First open failed - %s\n", nt_errstr(status));
4857                 return False;
4858         }
4859
4860         status = cli_rename(cli1, fname, fname1, false);
4861         if (!NT_STATUS_IS_OK(status)) {
4862                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4863         } else {
4864                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4865                 correct = False;
4866         }
4867
4868         status = cli_close(cli1, fnum1);
4869         if (!NT_STATUS_IS_OK(status)) {
4870                 printf("close - 1 failed (%s)\n", nt_errstr(status));
4871                 return False;
4872         }
4873
4874         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4875         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4876         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4877 #if 0
4878                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
4879 #else
4880                               FILE_SHARE_DELETE|FILE_SHARE_READ,
4881 #endif
4882                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4883         if (!NT_STATUS_IS_OK(status)) {
4884                 printf("Second open failed - %s\n", nt_errstr(status));
4885                 return False;
4886         }
4887
4888         status = cli_rename(cli1, fname, fname1, false);
4889         if (!NT_STATUS_IS_OK(status)) {
4890                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4891                 correct = False;
4892         } else {
4893                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4894         }
4895
4896         status = cli_close(cli1, fnum1);
4897         if (!NT_STATUS_IS_OK(status)) {
4898                 printf("close - 2 failed (%s)\n", nt_errstr(status));
4899                 return False;
4900         }
4901
4902         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4903         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4904
4905         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4906                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4907                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4908         if (!NT_STATUS_IS_OK(status)) {
4909                 printf("Third open failed - %s\n", nt_errstr(status));
4910                 return False;
4911         }
4912
4913
4914 #if 0
4915   {
4916         uint16_t fnum2;
4917
4918         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4919                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
4920                 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4921                 return False;
4922         }
4923         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4924                 printf("[8] setting delete_on_close on file failed !\n");
4925                 return False;
4926         }
4927
4928         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4929                 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4930                 return False;
4931         }
4932   }
4933 #endif
4934
4935         status = cli_rename(cli1, fname, fname1, false);
4936         if (!NT_STATUS_IS_OK(status)) {
4937                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4938                 correct = False;
4939         } else {
4940                 printf("Third rename succeeded (SHARE_NONE)\n");
4941         }
4942
4943         status = cli_close(cli1, fnum1);
4944         if (!NT_STATUS_IS_OK(status)) {
4945                 printf("close - 3 failed (%s)\n", nt_errstr(status));
4946                 return False;
4947         }
4948
4949         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4950         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4951
4952         /*----*/
4953
4954         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4955                               FILE_ATTRIBUTE_NORMAL,
4956                               FILE_SHARE_READ | FILE_SHARE_WRITE,
4957                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4958         if (!NT_STATUS_IS_OK(status)) {
4959                 printf("Fourth open failed - %s\n", nt_errstr(status));
4960                 return False;
4961         }
4962
4963         status = cli_rename(cli1, fname, fname1, false);
4964         if (!NT_STATUS_IS_OK(status)) {
4965                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4966         } else {
4967                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4968                 correct = False;
4969         }
4970
4971         status = cli_close(cli1, fnum1);
4972         if (!NT_STATUS_IS_OK(status)) {
4973                 printf("close - 4 failed (%s)\n", nt_errstr(status));
4974                 return False;
4975         }
4976
4977         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4978         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4979
4980         /*--*/
4981
4982         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4983                          FILE_ATTRIBUTE_NORMAL,
4984                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4985                          FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4986         if (!NT_STATUS_IS_OK(status)) {
4987                 printf("Fifth open failed - %s\n", nt_errstr(status));
4988                 return False;
4989         }
4990
4991         status = cli_rename(cli1, fname, fname1, false);
4992         if (!NT_STATUS_IS_OK(status)) {
4993                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4994                 correct = False;
4995         } else {
4996                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4997         }
4998
4999         /*
5000          * Now check if the first name still exists ...
5001          */
5002
5003         /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
5004                                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
5005                                    FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
5006           printf("Opening original file after rename of open file fails: %s\n",
5007               cli_errstr(cli1));
5008         }
5009         else {
5010           printf("Opening original file after rename of open file works ...\n");
5011           (void)cli_close(cli1, fnum2);
5012           } */
5013
5014         /*--*/
5015         status = cli_close(cli1, fnum1);
5016         if (!NT_STATUS_IS_OK(status)) {
5017                 printf("close - 5 failed (%s)\n", nt_errstr(status));
5018                 return False;
5019         }
5020
5021         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
5022         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
5023         if (!NT_STATUS_IS_OK(status)) {
5024                 printf("getatr on file %s failed - %s ! \n",
5025                         fname1, nt_errstr(status));
5026                 correct = False;
5027         } else {
5028                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
5029                         printf("Renamed file %s has wrong attr 0x%x "
5030                                 "(should be 0x%x)\n",
5031                                 fname1,
5032                                 attr,
5033                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
5034                         correct = False;
5035                 } else {
5036                         printf("Renamed file %s has archive bit set\n", fname1);
5037                 }
5038         }
5039
5040         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5041         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5042
5043         if (!torture_close_connection(cli1)) {
5044                 correct = False;
5045         }
5046
5047         return correct;
5048 }
5049
5050 /*
5051   Test rename into a directory with an ACL denying it.
5052  */
5053 static bool run_rename_access(int dummy)
5054 {
5055         static struct cli_state *cli = NULL;
5056         static struct cli_state *posix_cli = NULL;
5057         const char *src = "test.txt";
5058         const char *dname = "dir";
5059         const char *dst = "dir\\test.txt";
5060         const char *dsrc = "test.dir";
5061         const char *ddst = "dir\\test.dir";
5062         uint16_t fnum = (uint16_t)-1;
5063         struct security_descriptor *sd = NULL;
5064         struct security_descriptor *newsd = NULL;
5065         NTSTATUS status;
5066         TALLOC_CTX *frame = NULL;
5067
5068         frame = talloc_stackframe();
5069         printf("starting rename access test\n");
5070
5071         /* Windows connection. */
5072         if (!torture_open_connection(&cli, 0)) {
5073                 goto fail;
5074         }
5075
5076         smbXcli_conn_set_sockopt(cli->conn, sockops);
5077
5078         /* Posix connection. */
5079         if (!torture_open_connection(&posix_cli, 0)) {
5080                 goto fail;
5081         }
5082
5083         smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
5084
5085         status = torture_setup_unix_extensions(posix_cli);
5086         if (!NT_STATUS_IS_OK(status)) {
5087                 goto fail;
5088         }
5089
5090         /* Start with a clean slate. */
5091         cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5092         cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5093         cli_rmdir(cli, dsrc);
5094         cli_rmdir(cli, ddst);
5095         cli_rmdir(cli, dname);
5096
5097         /*
5098          * Setup the destination directory with a DENY ACE to
5099          * prevent new files within it.
5100          */
5101         status = cli_ntcreate(cli,
5102                                 dname,
5103                                 0,
5104                                 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
5105                                         WRITE_DAC_ACCESS|FILE_READ_DATA|
5106                                         WRITE_OWNER_ACCESS,
5107                                 FILE_ATTRIBUTE_DIRECTORY,
5108                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
5109                                 FILE_CREATE,
5110                                 FILE_DIRECTORY_FILE,
5111                                 0,
5112                                 &fnum,
5113                                 NULL);
5114         if (!NT_STATUS_IS_OK(status)) {
5115                 printf("Create of %s - %s\n", dname, nt_errstr(status));
5116                 goto fail;
5117         }
5118
5119         status = cli_query_secdesc(cli,
5120                                 fnum,
5121                                 frame,
5122                                 &sd);
5123         if (!NT_STATUS_IS_OK(status)) {
5124                 printf("cli_query_secdesc failed for %s (%s)\n",
5125                         dname, nt_errstr(status));
5126                 goto fail;
5127         }
5128
5129         newsd = security_descriptor_dacl_create(frame,
5130                                         0,
5131                                         NULL,
5132                                         NULL,
5133                                         SID_WORLD,
5134                                         SEC_ACE_TYPE_ACCESS_DENIED,
5135                                         SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
5136                                         0,
5137                                         NULL);
5138         if (newsd == NULL) {
5139                 goto fail;
5140         }
5141         sd->dacl = security_acl_concatenate(frame,
5142                                         newsd->dacl,
5143                                         sd->dacl);
5144         if (sd->dacl == NULL) {
5145                 goto fail;
5146         }
5147         status = cli_set_secdesc(cli, fnum, sd);
5148         if (!NT_STATUS_IS_OK(status)) {
5149                 printf("cli_set_secdesc failed for %s (%s)\n",
5150                         dname, nt_errstr(status));
5151                 goto fail;
5152         }
5153         status = cli_close(cli, fnum);
5154         if (!NT_STATUS_IS_OK(status)) {
5155                 printf("close failed for %s (%s)\n",
5156                         dname, nt_errstr(status));
5157                 goto fail;
5158         }
5159         /* Now go around the back and chmod to 777 via POSIX. */
5160         status = cli_posix_chmod(posix_cli, dname, 0777);
5161         if (!NT_STATUS_IS_OK(status)) {
5162                 printf("cli_posix_chmod failed for %s (%s)\n",
5163                         dname, nt_errstr(status));
5164                 goto fail;
5165         }
5166
5167         /* Check we can't create a file within dname via Windows. */
5168         status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5169         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5170                 cli_close(posix_cli, fnum);
5171                 printf("Create of %s should be ACCESS denied, was %s\n",
5172                         dst, nt_errstr(status));
5173                 goto fail;
5174         }
5175
5176         /* Make the sample file/directory. */
5177         status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5178         if (!NT_STATUS_IS_OK(status)) {
5179                 printf("open of %s failed (%s)\n", src, nt_errstr(status));
5180                 goto fail;
5181         }
5182         status = cli_close(cli, fnum);
5183         if (!NT_STATUS_IS_OK(status)) {
5184                 printf("cli_close failed (%s)\n", nt_errstr(status));
5185                 goto fail;
5186         }
5187
5188         status = cli_mkdir(cli, dsrc);
5189         if (!NT_STATUS_IS_OK(status)) {
5190                 printf("cli_mkdir of %s failed (%s)\n",
5191                         dsrc, nt_errstr(status));
5192                 goto fail;
5193         }
5194
5195         /*
5196          * OK - renames of the new file and directory into the
5197          * dst directory should fail.
5198          */
5199
5200         status = cli_rename(cli, src, dst, false);
5201         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5202                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
5203                         src, dst, nt_errstr(status));
5204                 goto fail;
5205         }
5206         status = cli_rename(cli, dsrc, ddst, false);
5207         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5208                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
5209                         src, dst, nt_errstr(status));
5210                 goto fail;
5211         }
5212
5213         TALLOC_FREE(frame);
5214         return true;
5215
5216   fail:
5217
5218         if (posix_cli) {
5219                 torture_close_connection(posix_cli);
5220         }
5221
5222         if (cli) {
5223                 if (fnum != (uint64_t)-1) {
5224                         cli_close(cli, fnum);
5225                 }
5226                 cli_unlink(cli, src,
5227                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5228                 cli_unlink(cli, dst,
5229                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5230                 cli_rmdir(cli, dsrc);
5231                 cli_rmdir(cli, ddst);
5232                 cli_rmdir(cli, dname);
5233
5234                 torture_close_connection(cli);
5235         }
5236
5237         TALLOC_FREE(frame);
5238         return false;
5239 }
5240
5241 /*
5242   Test owner rights ACE.
5243  */
5244 static bool run_owner_rights(int dummy)
5245 {
5246         static struct cli_state *cli = NULL;
5247         const char *fname = "owner_rights.txt";
5248         uint16_t fnum = (uint16_t)-1;
5249         struct security_descriptor *sd = NULL;
5250         struct security_descriptor *newsd = NULL;
5251         NTSTATUS status;
5252         TALLOC_CTX *frame = NULL;
5253
5254         frame = talloc_stackframe();
5255         printf("starting owner rights test\n");
5256
5257         /* Windows connection. */
5258         if (!torture_open_connection(&cli, 0)) {
5259                 goto fail;
5260         }
5261
5262         smbXcli_conn_set_sockopt(cli->conn, sockops);
5263
5264         /* Start with a clean slate. */
5265         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5266
5267         /* Create the test file. */
5268         /* Now try and open for read and write-dac. */
5269         status = cli_ntcreate(cli,
5270                                 fname,
5271                                 0,
5272                                 GENERIC_ALL_ACCESS,
5273                                 FILE_ATTRIBUTE_NORMAL,
5274                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5275                                         FILE_SHARE_DELETE,
5276                                 FILE_CREATE,
5277                                 0,
5278                                 0,
5279                                 &fnum,
5280                                 NULL);
5281         if (!NT_STATUS_IS_OK(status)) {
5282                 printf("Create of %s - %s\n", fname, nt_errstr(status));
5283                 goto fail;
5284         }
5285
5286         /* Get the original SD. */
5287         status = cli_query_secdesc(cli,
5288                                 fnum,
5289                                 frame,
5290                                 &sd);
5291         if (!NT_STATUS_IS_OK(status)) {
5292                 printf("cli_query_secdesc failed for %s (%s)\n",
5293                         fname, nt_errstr(status));
5294                 goto fail;
5295         }
5296
5297         /*
5298          * Add an "owner-rights" ACE denying WRITE_DATA,
5299          * and an "owner-rights" ACE allowing READ_DATA.
5300          */
5301
5302         newsd = security_descriptor_dacl_create(frame,
5303                                         0,
5304                                         NULL,
5305                                         NULL,
5306                                         SID_OWNER_RIGHTS,
5307                                         SEC_ACE_TYPE_ACCESS_DENIED,
5308                                         FILE_WRITE_DATA,
5309                                         0,
5310                                         SID_OWNER_RIGHTS,
5311                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
5312                                         FILE_READ_DATA,
5313                                         0,
5314                                         NULL);
5315         if (newsd == NULL) {
5316                 goto fail;
5317         }
5318         sd->dacl = security_acl_concatenate(frame,
5319                                         newsd->dacl,
5320                                         sd->dacl);
5321         if (sd->dacl == NULL) {
5322                 goto fail;
5323         }
5324         status = cli_set_secdesc(cli, fnum, sd);
5325         if (!NT_STATUS_IS_OK(status)) {
5326                 printf("cli_set_secdesc failed for %s (%s)\n",
5327                         fname, nt_errstr(status));
5328                 goto fail;
5329         }
5330         status = cli_close(cli, fnum);
5331         if (!NT_STATUS_IS_OK(status)) {
5332                 printf("close failed for %s (%s)\n",
5333                         fname, nt_errstr(status));
5334                 goto fail;
5335         }
5336         fnum = (uint16_t)-1;
5337
5338         /* Try and open for FILE_WRITE_DATA */
5339         status = cli_ntcreate(cli,
5340                                 fname,
5341                                 0,
5342                                 FILE_WRITE_DATA,
5343                                 FILE_ATTRIBUTE_NORMAL,
5344                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5345                                         FILE_SHARE_DELETE,
5346                                 FILE_OPEN,
5347                                 0,
5348                                 0,
5349                                 &fnum,
5350                                 NULL);
5351         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5352                 printf("Open of %s - %s\n", fname, nt_errstr(status));
5353                 goto fail;
5354         }
5355
5356         /* Now try and open for FILE_READ_DATA */
5357         status = cli_ntcreate(cli,
5358                                 fname,
5359                                 0,
5360                                 FILE_READ_DATA,
5361                                 FILE_ATTRIBUTE_NORMAL,
5362                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5363                                         FILE_SHARE_DELETE,
5364                                 FILE_OPEN,
5365                                 0,
5366                                 0,
5367                                 &fnum,
5368                                 NULL);
5369         if (!NT_STATUS_IS_OK(status)) {
5370                 printf("Open of %s - %s\n", fname, nt_errstr(status));
5371                 goto fail;
5372         }
5373
5374         status = cli_close(cli, fnum);
5375         if (!NT_STATUS_IS_OK(status)) {
5376                 printf("close failed for %s (%s)\n",
5377                         fname, nt_errstr(status));
5378                 goto fail;
5379         }
5380
5381         /* Restore clean slate. */
5382         TALLOC_FREE(sd);
5383         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5384
5385         /* Create the test file. */
5386         status = cli_ntcreate(cli,
5387                                 fname,
5388                                 0,
5389                                 GENERIC_ALL_ACCESS,
5390                                 FILE_ATTRIBUTE_NORMAL,
5391                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5392                                         FILE_SHARE_DELETE,
5393                                 FILE_CREATE,
5394                                 0,
5395                                 0,
5396                                 &fnum,
5397                                 NULL);
5398         if (!NT_STATUS_IS_OK(status)) {
5399                 printf("Create of %s - %s\n", fname, nt_errstr(status));
5400                 goto fail;
5401         }
5402
5403         /* Get the original SD. */
5404         status = cli_query_secdesc(cli,
5405                                 fnum,
5406                                 frame,
5407                                 &sd);
5408         if (!NT_STATUS_IS_OK(status)) {
5409                 printf("cli_query_secdesc failed for %s (%s)\n",
5410                         fname, nt_errstr(status));
5411                 goto fail;
5412         }
5413
5414         /*
5415          * Add an "owner-rights ACE denying WRITE_DATA,
5416          * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
5417          */
5418
5419         newsd = security_descriptor_dacl_create(frame,
5420                                         0,
5421                                         NULL,
5422                                         NULL,
5423                                         SID_OWNER_RIGHTS,
5424                                         SEC_ACE_TYPE_ACCESS_DENIED,
5425                                         FILE_WRITE_DATA,
5426                                         0,
5427                                         SID_OWNER_RIGHTS,
5428                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
5429                                         FILE_READ_DATA|FILE_WRITE_DATA,
5430                                         0,
5431                                         NULL);
5432         if (newsd == NULL) {
5433                 goto fail;
5434         }
5435         sd->dacl = security_acl_concatenate(frame,
5436                                         newsd->dacl,
5437                                         sd->dacl);
5438         if (sd->dacl == NULL) {
5439                 goto fail;
5440         }
5441         status = cli_set_secdesc(cli, fnum, sd);
5442         if (!NT_STATUS_IS_OK(status)) {
5443                 printf("cli_set_secdesc failed for %s (%s)\n",
5444                         fname, nt_errstr(status));
5445                 goto fail;
5446         }
5447         status = cli_close(cli, fnum);
5448         if (!NT_STATUS_IS_OK(status)) {
5449                 printf("close failed for %s (%s)\n",
5450                         fname, nt_errstr(status));
5451                 goto fail;
5452         }
5453         fnum = (uint16_t)-1;
5454
5455         /* Try and open for FILE_WRITE_DATA */
5456         status = cli_ntcreate(cli,
5457                                 fname,
5458                                 0,
5459                                 FILE_WRITE_DATA,
5460                                 FILE_ATTRIBUTE_NORMAL,
5461                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5462                                         FILE_SHARE_DELETE,
5463                                 FILE_OPEN,
5464                                 0,
5465                                 0,
5466                                 &fnum,
5467                                 NULL);
5468         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5469                 printf("Open of %s - %s\n", fname, nt_errstr(status));
5470                 goto fail;
5471         }
5472
5473         /* Now try and open for FILE_READ_DATA */
5474         status = cli_ntcreate(cli,
5475                                 fname,
5476                                 0,
5477                                 FILE_READ_DATA,
5478                                 FILE_ATTRIBUTE_NORMAL,
5479                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5480                                         FILE_SHARE_DELETE,
5481                                 FILE_OPEN,
5482                                 0,
5483                                 0,
5484                                 &fnum,
5485                                 NULL);
5486         if (!NT_STATUS_IS_OK(status)) {
5487                 printf("Open of %s - %s\n", fname, nt_errstr(status));
5488                 goto fail;
5489         }
5490
5491         status = cli_close(cli, fnum);
5492         if (!NT_STATUS_IS_OK(status)) {
5493                 printf("close failed for %s (%s)\n",
5494                         fname, nt_errstr(status));
5495                 goto fail;
5496         }
5497
5498         /* Restore clean slate. */
5499         TALLOC_FREE(sd);
5500         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5501
5502
5503         /* Create the test file. */
5504         status = cli_ntcreate(cli,
5505                                 fname,
5506                                 0,
5507                                 GENERIC_ALL_ACCESS,
5508                                 FILE_ATTRIBUTE_NORMAL,
5509                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5510                                         FILE_SHARE_DELETE,
5511                                 FILE_CREATE,
5512                                 0,
5513                                 0,
5514                                 &fnum,
5515                                 NULL);
5516         if (!NT_STATUS_IS_OK(status)) {
5517                 printf("Create of %s - %s\n", fname, nt_errstr(status));
5518                 goto fail;
5519         }
5520
5521         /* Get the original SD. */
5522         status = cli_query_secdesc(cli,
5523                                 fnum,
5524                                 frame,
5525                                 &sd);
5526         if (!NT_STATUS_IS_OK(status)) {
5527                 printf("cli_query_secdesc failed for %s (%s)\n",
5528                         fname, nt_errstr(status));
5529                 goto fail;
5530         }
5531
5532         /*
5533          * Add an "authenticated users" ACE allowing READ_DATA,
5534          * add an "owner-rights" denying READ_DATA,
5535          * and an "authenticated users" ACE allowing WRITE_DATA.
5536          */
5537
5538         newsd = security_descriptor_dacl_create(frame,
5539                                         0,
5540                                         NULL,
5541                                         NULL,
5542                                         SID_NT_AUTHENTICATED_USERS,
5543                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
5544                                         FILE_READ_DATA,
5545                                         0,
5546                                         SID_OWNER_RIGHTS,
5547                                         SEC_ACE_TYPE_ACCESS_DENIED,
5548                                         FILE_READ_DATA,
5549                                         0,
5550                                         SID_NT_AUTHENTICATED_USERS,
5551                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
5552                                         FILE_WRITE_DATA,
5553                                         0,
5554                                         NULL);
5555         if (newsd == NULL) {
5556                 printf("newsd == NULL\n");
5557                 goto fail;
5558         }
5559         sd->dacl = security_acl_concatenate(frame,
5560                                         newsd->dacl,
5561                                         sd->dacl);
5562         if (sd->dacl == NULL) {
5563                 printf("sd->dacl == NULL\n");
5564                 goto fail;
5565         }
5566         status = cli_set_secdesc(cli, fnum, sd);
5567         if (!NT_STATUS_IS_OK(status)) {
5568                 printf("cli_set_secdesc failed for %s (%s)\n",
5569                         fname, nt_errstr(status));
5570                 goto fail;
5571         }
5572         status = cli_close(cli, fnum);
5573         if (!NT_STATUS_IS_OK(status)) {
5574                 printf("close failed for %s (%s)\n",
5575                         fname, nt_errstr(status));
5576                 goto fail;
5577         }
5578         fnum = (uint16_t)-1;
5579
5580         /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
5581         status = cli_ntcreate(cli,
5582                                 fname,
5583                                 0,
5584                                 FILE_READ_DATA|FILE_WRITE_DATA,
5585                                 FILE_ATTRIBUTE_NORMAL,
5586                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5587                                         FILE_SHARE_DELETE,
5588                                 FILE_OPEN,
5589                                 0,
5590                                 0,
5591                                 &fnum,
5592                                 NULL);
5593         if (!NT_STATUS_IS_OK(status)) {
5594                 printf("Open of %s - %s\n", fname, nt_errstr(status));
5595                 goto fail;
5596         }
5597
5598         status = cli_close(cli, fnum);
5599         if (!NT_STATUS_IS_OK(status)) {
5600                 printf("close failed for %s (%s)\n",
5601                         fname, nt_errstr(status));
5602                 goto fail;
5603         }
5604
5605         cli_unlink(cli, fname,
5606                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5607
5608         TALLOC_FREE(frame);
5609         return true;
5610
5611   fail:
5612
5613         if (cli) {
5614                 if (fnum != (uint16_t)-1) {
5615                         cli_close(cli, fnum);
5616                 }
5617                 cli_unlink(cli, fname,
5618                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5619                 torture_close_connection(cli);
5620         }
5621
5622         TALLOC_FREE(frame);
5623         return false;
5624 }
5625
5626 static bool run_pipe_number(int dummy)
5627 {
5628         struct cli_state *cli1;
5629         const char *pipe_name = "\\SPOOLSS";
5630         uint16_t fnum;
5631         int num_pipes = 0;
5632         NTSTATUS status;
5633
5634         printf("starting pipenumber test\n");
5635         if (!torture_open_connection(&cli1, 0)) {
5636                 return False;
5637         }
5638
5639         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5640         while(1) {
5641                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
5642                                       FILE_ATTRIBUTE_NORMAL,
5643                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
5644                                       FILE_OPEN_IF, 0, 0, &fnum, NULL);
5645                 if (!NT_STATUS_IS_OK(status)) {
5646                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
5647                         break;
5648                 }
5649                 num_pipes++;
5650                 printf("\r%6d", num_pipes);
5651         }
5652
5653         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
5654         torture_close_connection(cli1);
5655         return True;
5656 }
5657
5658 /*
5659   Test open mode returns on read-only files.
5660  */
5661 static bool run_opentest(int dummy)
5662 {
5663         static struct cli_state *cli1;
5664         static struct cli_state *cli2;
5665         const char *fname = "\\readonly.file";
5666         uint16_t fnum1, fnum2;
5667         char buf[20];
5668         off_t fsize;
5669         bool correct = True;
5670         char *tmp_path;
5671         NTSTATUS status;
5672
5673         printf("starting open test\n");
5674
5675         if (!torture_open_connection(&cli1, 0)) {
5676                 return False;
5677         }
5678
5679         cli_setatr(cli1, fname, 0, 0);
5680         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5681
5682         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5683
5684         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
5685         if (!NT_STATUS_IS_OK(status)) {
5686                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5687                 return False;
5688         }
5689
5690         status = cli_close(cli1, fnum1);
5691         if (!NT_STATUS_IS_OK(status)) {
5692                 printf("close2 failed (%s)\n", nt_errstr(status));
5693                 return False;
5694         }
5695
5696         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
5697         if (!NT_STATUS_IS_OK(status)) {
5698                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
5699                 return False;
5700         }
5701
5702         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
5703         if (!NT_STATUS_IS_OK(status)) {
5704                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5705                 return False;
5706         }
5707
5708         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
5709         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
5710
5711         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
5712                         NT_STATUS_ACCESS_DENIED)) {
5713                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
5714         }
5715
5716         printf("finished open test 1\n");
5717
5718         cli_close(cli1, fnum1);
5719
5720         /* Now try not readonly and ensure ERRbadshare is returned. */
5721
5722         cli_setatr(cli1, fname, 0, 0);
5723
5724         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
5725         if (!NT_STATUS_IS_OK(status)) {
5726                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5727                 return False;
5728         }
5729
5730         /* This will fail - but the error should be ERRshare. */
5731         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
5732
5733         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
5734                         NT_STATUS_SHARING_VIOLATION)) {
5735                 printf("correct error code ERRDOS/ERRbadshare returned\n");
5736         }
5737
5738         status = cli_close(cli1, fnum1);
5739         if (!NT_STATUS_IS_OK(status)) {
5740                 printf("close2 failed (%s)\n", nt_errstr(status));
5741                 return False;
5742         }
5743
5744         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5745
5746         printf("finished open test 2\n");
5747
5748         /* Test truncate open disposition on file opened for read. */
5749         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
5750         if (!NT_STATUS_IS_OK(status)) {
5751                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
5752                 return False;
5753         }
5754
5755         /* write 20 bytes. */
5756
5757         memset(buf, '\0', 20);
5758
5759         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
5760         if (!NT_STATUS_IS_OK(status)) {
5761                 printf("write failed (%s)\n", nt_errstr(status));
5762                 correct = False;
5763         }
5764
5765         status = cli_close(cli1, fnum1);
5766         if (!NT_STATUS_IS_OK(status)) {
5767                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
5768                 return False;
5769         }
5770
5771         /* Ensure size == 20. */
5772         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5773         if (!NT_STATUS_IS_OK(status)) {
5774                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5775                 return False;
5776         }
5777
5778         if (fsize != 20) {
5779                 printf("(3) file size != 20\n");
5780                 return False;
5781         }
5782
5783         /* Now test if we can truncate a file opened for readonly. */
5784         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
5785         if (!NT_STATUS_IS_OK(status)) {
5786                 printf("(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("close2 failed (%s)\n", nt_errstr(status));
5793                 return False;
5794         }
5795
5796         /* Ensure size == 0. */
5797         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5798         if (!NT_STATUS_IS_OK(status)) {
5799                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5800                 return False;
5801         }
5802
5803         if (fsize != 0) {
5804                 printf("(3) file size != 0\n");
5805                 return False;
5806         }
5807         printf("finished open test 3\n");
5808
5809         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5810
5811         printf("Do ctemp tests\n");
5812         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
5813         if (!NT_STATUS_IS_OK(status)) {
5814                 printf("ctemp failed (%s)\n", nt_errstr(status));
5815                 return False;
5816         }
5817
5818         printf("ctemp gave path %s\n", tmp_path);
5819         status = cli_close(cli1, fnum1);
5820         if (!NT_STATUS_IS_OK(status)) {
5821                 printf("close of temp failed (%s)\n", nt_errstr(status));
5822         }
5823
5824         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5825         if (!NT_STATUS_IS_OK(status)) {
5826                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
5827         }
5828
5829         /* Test the non-io opens... */
5830
5831         if (!torture_open_connection(&cli2, 1)) {
5832                 return False;
5833         }
5834
5835         cli_setatr(cli2, fname, 0, 0);
5836         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5837
5838         smbXcli_conn_set_sockopt(cli2->conn, sockops);
5839
5840         printf("TEST #1 testing 2 non-io opens (no delete)\n");
5841         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5842                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5843                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5844         if (!NT_STATUS_IS_OK(status)) {
5845                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5846                 return False;
5847         }
5848
5849         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5850                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5851                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5852         if (!NT_STATUS_IS_OK(status)) {
5853                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5854                 return False;
5855         }
5856
5857         status = cli_close(cli1, fnum1);
5858         if (!NT_STATUS_IS_OK(status)) {
5859                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5860                 return False;
5861         }
5862
5863         status = cli_close(cli2, fnum2);
5864         if (!NT_STATUS_IS_OK(status)) {
5865                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5866                 return False;
5867         }
5868
5869         printf("non-io open test #1 passed.\n");
5870
5871         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5872
5873         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5874
5875         status = cli_ntcreate(cli1, fname, 0,
5876                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
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 #2 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_NONE,
5886                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5887         if (!NT_STATUS_IS_OK(status)) {
5888                 printf("TEST #2 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 #2 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 #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5901                 return False;
5902         }
5903
5904         printf("non-io open test #2 passed.\n");
5905
5906         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5907
5908         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5909
5910         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
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 #3 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, FILE_SHARE_NONE,
5921                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5922         if (!NT_STATUS_IS_OK(status)) {
5923                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5924                 return False;
5925         }
5926
5927         status = cli_close(cli1, fnum1);
5928         if (!NT_STATUS_IS_OK(status)) {
5929                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5930                 return False;
5931         }
5932
5933         status = cli_close(cli2, fnum2);
5934         if (!NT_STATUS_IS_OK(status)) {
5935                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5936                 return False;
5937         }
5938
5939         printf("non-io open test #3 passed.\n");
5940
5941         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5942
5943         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5944
5945         status = cli_ntcreate(cli1, fname, 0,
5946                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5947                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5948                                FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5949         if (!NT_STATUS_IS_OK(status)) {
5950                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5951                 return False;
5952         }
5953
5954         status = cli_ntcreate(cli2, fname, 0,
5955                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5956                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5957                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5958         if (NT_STATUS_IS_OK(status)) {
5959                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5960                 return False;
5961         }
5962
5963         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5964
5965         status = cli_close(cli1, fnum1);
5966         if (!NT_STATUS_IS_OK(status)) {
5967                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5968                 return False;
5969         }
5970
5971         printf("non-io open test #4 passed.\n");
5972
5973         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5974
5975         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5976
5977         status = cli_ntcreate(cli1, fname, 0,
5978                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5979                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5980                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5981         if (!NT_STATUS_IS_OK(status)) {
5982                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5983                 return False;
5984         }
5985
5986         status = cli_ntcreate(cli2, fname, 0,
5987                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5988                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5989                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5990         if (!NT_STATUS_IS_OK(status)) {
5991                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5992                 return False;
5993         }
5994
5995         status = cli_close(cli1, fnum1);
5996         if (!NT_STATUS_IS_OK(status)) {
5997                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5998                 return False;
5999         }
6000
6001         status = cli_close(cli2, fnum2);
6002         if (!NT_STATUS_IS_OK(status)) {
6003                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
6004                 return False;
6005         }
6006
6007         printf("non-io open test #5 passed.\n");
6008
6009         printf("TEST #6 testing 1 non-io open, one io open\n");
6010
6011         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6012
6013         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
6014                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6015                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6016         if (!NT_STATUS_IS_OK(status)) {
6017                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
6018                 return False;
6019         }
6020
6021         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
6022                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6023                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
6024         if (!NT_STATUS_IS_OK(status)) {
6025                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
6026                 return False;
6027         }
6028
6029         status = cli_close(cli1, fnum1);
6030         if (!NT_STATUS_IS_OK(status)) {
6031                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
6032                 return False;
6033         }
6034
6035         status = cli_close(cli2, fnum2);
6036         if (!NT_STATUS_IS_OK(status)) {
6037                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
6038                 return False;
6039         }
6040
6041         printf("non-io open test #6 passed.\n");
6042
6043         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
6044
6045         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6046
6047         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
6048                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6049                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6050         if (!NT_STATUS_IS_OK(status)) {
6051                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
6052                 return False;
6053         }
6054
6055         status = cli_ntcreate(cli2, fname, 0,
6056                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
6057                               FILE_ATTRIBUTE_NORMAL,
6058                               FILE_SHARE_READ|FILE_SHARE_DELETE,
6059                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
6060         if (NT_STATUS_IS_OK(status)) {
6061                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
6062                 return False;
6063         }
6064
6065         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
6066
6067         status = cli_close(cli1, fnum1);
6068         if (!NT_STATUS_IS_OK(status)) {
6069                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
6070                 return False;
6071         }
6072
6073         printf("non-io open test #7 passed.\n");
6074
6075         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6076
6077         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
6078         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
6079                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6080                                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6081         if (!NT_STATUS_IS_OK(status)) {
6082                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
6083                 correct = false;
6084                 goto out;
6085         }
6086
6087         /* Write to ensure we have to update the file time. */
6088         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
6089                               NULL);
6090         if (!NT_STATUS_IS_OK(status)) {
6091                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
6092                 correct = false;
6093                 goto out;
6094         }
6095
6096         status = cli_close(cli1, fnum1);
6097         if (!NT_STATUS_IS_OK(status)) {
6098                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
6099                 correct = false;
6100         }
6101
6102   out:
6103
6104         if (!torture_close_connection(cli1)) {
6105                 correct = False;
6106         }
6107         if (!torture_close_connection(cli2)) {
6108                 correct = False;
6109         }
6110
6111         return correct;
6112 }
6113
6114 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
6115 {
6116         uint16_t major, minor;
6117         uint32_t caplow, caphigh;
6118         NTSTATUS status;
6119
6120         if (!SERVER_HAS_UNIX_CIFS(cli)) {
6121                 printf("Server doesn't support UNIX CIFS extensions.\n");
6122                 return NT_STATUS_NOT_SUPPORTED;
6123         }
6124
6125         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
6126                                              &caphigh);
6127         if (!NT_STATUS_IS_OK(status)) {
6128                 printf("Server didn't return UNIX CIFS extensions: %s\n",
6129                        nt_errstr(status));
6130                 return status;
6131         }
6132
6133         status = cli_set_unix_extensions_capabilities(cli, major, minor,
6134                                                       caplow, caphigh);
6135         if (!NT_STATUS_IS_OK(status)) {
6136                 printf("Server doesn't support setting UNIX CIFS extensions: "
6137                        "%s.\n", nt_errstr(status));
6138                 return status;
6139         }
6140
6141         return NT_STATUS_OK;
6142 }
6143
6144 /*
6145   Test POSIX open /mkdir calls.
6146  */
6147 static bool run_simple_posix_open_test(int dummy)
6148 {
6149         static struct cli_state *cli1;
6150         const char *fname = "posix:file";
6151         const char *hname = "posix:hlink";
6152         const char *sname = "posix:symlink";
6153         const char *dname = "posix:dir";
6154         char buf[10];
6155         char namebuf[11];
6156         uint16_t fnum1 = (uint16_t)-1;
6157         SMB_STRUCT_STAT sbuf;
6158         bool correct = false;
6159         NTSTATUS status;
6160         size_t nread;
6161         const char *fname_windows = "windows_file";
6162         uint16_t fnum2 = (uint16_t)-1;
6163
6164         printf("Starting simple POSIX open test\n");
6165
6166         if (!torture_open_connection(&cli1, 0)) {
6167                 return false;
6168         }
6169
6170         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6171
6172         status = torture_setup_unix_extensions(cli1);
6173         if (!NT_STATUS_IS_OK(status)) {
6174                 return false;
6175         }
6176
6177         cli_setatr(cli1, fname, 0, 0);
6178         cli_posix_unlink(cli1, fname);
6179         cli_setatr(cli1, dname, 0, 0);
6180         cli_posix_rmdir(cli1, dname);
6181         cli_setatr(cli1, hname, 0, 0);
6182         cli_posix_unlink(cli1, hname);
6183         cli_setatr(cli1, sname, 0, 0);
6184         cli_posix_unlink(cli1, sname);
6185         cli_setatr(cli1, fname_windows, 0, 0);
6186         cli_posix_unlink(cli1, fname_windows);
6187
6188         /* Create a directory. */
6189         status = cli_posix_mkdir(cli1, dname, 0777);
6190         if (!NT_STATUS_IS_OK(status)) {
6191                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
6192                 goto out;
6193         }
6194
6195         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
6196                                 0600, &fnum1);
6197         if (!NT_STATUS_IS_OK(status)) {
6198                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6199                 goto out;
6200         }
6201
6202         /* Test ftruncate - set file size. */
6203         status = cli_ftruncate(cli1, fnum1, 1000);
6204         if (!NT_STATUS_IS_OK(status)) {
6205                 printf("ftruncate failed (%s)\n", nt_errstr(status));
6206                 goto out;
6207         }
6208
6209         /* Ensure st_size == 1000 */
6210         status = cli_posix_stat(cli1, fname, &sbuf);
6211         if (!NT_STATUS_IS_OK(status)) {
6212                 printf("stat failed (%s)\n", nt_errstr(status));
6213                 goto out;
6214         }
6215
6216         if (sbuf.st_ex_size != 1000) {
6217                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
6218                 goto out;
6219         }
6220
6221         /* Ensure st_mode == 0600 */
6222         if ((sbuf.st_ex_mode & 07777) != 0600) {
6223                 printf("posix_open - bad permissions 0%o != 0600\n",
6224                                 (unsigned int)(sbuf.st_ex_mode & 07777));
6225                 goto out;
6226         }
6227
6228         /* Test ftruncate - set file size back to zero. */
6229         status = cli_ftruncate(cli1, fnum1, 0);
6230         if (!NT_STATUS_IS_OK(status)) {
6231                 printf("ftruncate failed (%s)\n", nt_errstr(status));
6232                 goto out;
6233         }
6234
6235         status = cli_close(cli1, fnum1);
6236         if (!NT_STATUS_IS_OK(status)) {
6237                 printf("close failed (%s)\n", nt_errstr(status));
6238                 goto out;
6239         }
6240
6241         /* Now open the file again for read only. */
6242         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
6243         if (!NT_STATUS_IS_OK(status)) {
6244                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
6245                 goto out;
6246         }
6247
6248         /* Now unlink while open. */
6249         status = cli_posix_unlink(cli1, fname);
6250         if (!NT_STATUS_IS_OK(status)) {
6251                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
6252                 goto out;
6253         }
6254
6255         status = cli_close(cli1, fnum1);
6256         if (!NT_STATUS_IS_OK(status)) {
6257                 printf("close(2) failed (%s)\n", nt_errstr(status));
6258                 goto out;
6259         }
6260
6261         /* Ensure the file has gone. */
6262         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
6263         if (NT_STATUS_IS_OK(status)) {
6264                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
6265                 goto out;
6266         }
6267
6268         /* Create again to test open with O_TRUNC. */
6269         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
6270         if (!NT_STATUS_IS_OK(status)) {
6271                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6272                 goto out;
6273         }
6274
6275         /* Test ftruncate - set file size. */
6276         status = cli_ftruncate(cli1, fnum1, 1000);
6277         if (!NT_STATUS_IS_OK(status)) {
6278                 printf("ftruncate failed (%s)\n", nt_errstr(status));
6279                 goto out;
6280         }
6281
6282         /* Ensure st_size == 1000 */
6283         status = cli_posix_stat(cli1, fname, &sbuf);
6284         if (!NT_STATUS_IS_OK(status)) {
6285                 printf("stat failed (%s)\n", nt_errstr(status));
6286                 goto out;
6287         }
6288
6289         if (sbuf.st_ex_size != 1000) {
6290                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
6291                 goto out;
6292         }
6293
6294         status = cli_close(cli1, fnum1);
6295         if (!NT_STATUS_IS_OK(status)) {
6296                 printf("close(2) failed (%s)\n", nt_errstr(status));
6297                 goto out;
6298         }
6299
6300         /* Re-open with O_TRUNC. */
6301         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
6302         if (!NT_STATUS_IS_OK(status)) {
6303                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6304                 goto out;
6305         }
6306
6307         /* Ensure st_size == 0 */
6308         status = cli_posix_stat(cli1, fname, &sbuf);
6309         if (!NT_STATUS_IS_OK(status)) {
6310                 printf("stat failed (%s)\n", nt_errstr(status));
6311                 goto out;
6312         }
6313
6314         if (sbuf.st_ex_size != 0) {
6315                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
6316                 goto out;
6317         }
6318
6319         status = cli_close(cli1, fnum1);
6320         if (!NT_STATUS_IS_OK(status)) {
6321                 printf("close failed (%s)\n", nt_errstr(status));
6322                 goto out;
6323         }
6324
6325         status = cli_posix_unlink(cli1, fname);
6326         if (!NT_STATUS_IS_OK(status)) {
6327                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
6328                 goto out;
6329         }
6330
6331         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
6332         if (!NT_STATUS_IS_OK(status)) {
6333                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
6334                         dname, nt_errstr(status));
6335                 goto out;
6336         }
6337
6338         cli_close(cli1, fnum1);
6339
6340         /* What happens when we try and POSIX open a directory for write ? */
6341         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
6342         if (NT_STATUS_IS_OK(status)) {
6343                 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
6344                 goto out;
6345         } else {
6346                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
6347                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
6348                         goto out;
6349                 }
6350         }
6351
6352         /* Create the file. */
6353         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
6354                                 0600, &fnum1);
6355         if (!NT_STATUS_IS_OK(status)) {
6356                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6357                 goto out;
6358         }
6359
6360         /* Write some data into it. */
6361         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
6362                               NULL);
6363         if (!NT_STATUS_IS_OK(status)) {
6364                 printf("cli_write failed: %s\n", nt_errstr(status));
6365                 goto out;
6366         }
6367
6368         cli_close(cli1, fnum1);
6369
6370         /* Now create a hardlink. */
6371         status = cli_posix_hardlink(cli1, fname, hname);
6372         if (!NT_STATUS_IS_OK(status)) {
6373                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
6374                 goto out;
6375         }
6376
6377         /* Now create a symlink. */
6378         status = cli_posix_symlink(cli1, fname, sname);
6379         if (!NT_STATUS_IS_OK(status)) {
6380                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
6381                 goto out;
6382         }
6383
6384         /* Open the hardlink for read. */
6385         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
6386         if (!NT_STATUS_IS_OK(status)) {
6387                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
6388                 goto out;
6389         }
6390
6391         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
6392         if (!NT_STATUS_IS_OK(status)) {
6393                 printf("POSIX read of %s failed (%s)\n", hname,
6394                        nt_errstr(status));
6395                 goto out;
6396         } else if (nread != 10) {
6397                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
6398                        hname, (unsigned long)nread, 10);
6399                 goto out;
6400         }
6401
6402         if (memcmp(buf, "TEST DATA\n", 10)) {
6403                 printf("invalid data read from hardlink\n");
6404                 goto out;
6405         }
6406
6407         /* Do a POSIX lock/unlock. */
6408         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
6409         if (!NT_STATUS_IS_OK(status)) {
6410                 printf("POSIX lock failed %s\n", nt_errstr(status));
6411                 goto out;
6412         }
6413
6414         /* Punch a hole in the locked area. */
6415         status = cli_posix_unlock(cli1, fnum1, 10, 80);
6416         if (!NT_STATUS_IS_OK(status)) {
6417                 printf("POSIX unlock failed %s\n", nt_errstr(status));
6418                 goto out;
6419         }
6420
6421         cli_close(cli1, fnum1);
6422
6423         /* Open the symlink for read - this should fail. A POSIX
6424            client should not be doing opens on a symlink. */
6425         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
6426         if (NT_STATUS_IS_OK(status)) {
6427                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
6428                 goto out;
6429         } else {
6430                 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
6431                                 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
6432                         printf("POSIX open of %s should have failed "
6433                                 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
6434                                 "failed with %s instead.\n",
6435                                 sname, nt_errstr(status));
6436                         goto out;
6437                 }
6438         }
6439
6440         status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
6441         if (!NT_STATUS_IS_OK(status)) {
6442                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
6443                 goto out;
6444         }
6445
6446         if (strcmp(namebuf, fname) != 0) {
6447                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
6448                         sname, fname, namebuf);
6449                 goto out;
6450         }
6451
6452         status = cli_posix_rmdir(cli1, dname);
6453         if (!NT_STATUS_IS_OK(status)) {
6454                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
6455                 goto out;
6456         }
6457
6458         /* Check directory opens with a specific permission. */
6459         status = cli_posix_mkdir(cli1, dname, 0700);
6460         if (!NT_STATUS_IS_OK(status)) {
6461                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
6462                 goto out;
6463         }
6464
6465         /* Ensure st_mode == 0700 */
6466         status = cli_posix_stat(cli1, dname, &sbuf);
6467         if (!NT_STATUS_IS_OK(status)) {
6468                 printf("stat failed (%s)\n", nt_errstr(status));
6469                 goto out;
6470         }
6471
6472         if ((sbuf.st_ex_mode & 07777) != 0700) {
6473                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
6474                                 (unsigned int)(sbuf.st_ex_mode & 07777));
6475                 goto out;
6476         }
6477
6478         /*
6479          * Now create a Windows file, and attempt a POSIX unlink.
6480          * This should fail with a sharing violation but due to:
6481          *
6482          * [Bug 9571] Unlink after open causes smbd to panic
6483          *
6484          * ensure we've fixed the lock ordering violation.
6485          */
6486
6487         status = cli_ntcreate(cli1, fname_windows, 0,
6488                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
6489                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6490                         FILE_CREATE,
6491                         0x0, 0x0, &fnum2, NULL);
6492         if (!NT_STATUS_IS_OK(status)) {
6493                 printf("Windows create of %s failed (%s)\n", fname_windows,
6494                         nt_errstr(status));
6495                 goto out;
6496         }
6497
6498         /* Now try posix_unlink. */
6499         status = cli_posix_unlink(cli1, fname_windows);
6500         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6501                 printf("POSIX unlink of %s should fail "
6502                         "with NT_STATUS_SHARING_VIOLATION "
6503                         "got %s instead !\n",
6504                         fname_windows,
6505                         nt_errstr(status));
6506                 goto out;
6507         }
6508
6509         cli_close(cli1, fnum2);
6510
6511         printf("Simple POSIX open test passed\n");
6512         correct = true;
6513
6514   out:
6515
6516         if (fnum1 != (uint16_t)-1) {
6517                 cli_close(cli1, fnum1);
6518                 fnum1 = (uint16_t)-1;
6519         }
6520
6521         if (fnum2 != (uint16_t)-1) {
6522                 cli_close(cli1, fnum2);
6523                 fnum2 = (uint16_t)-1;
6524         }
6525
6526         cli_setatr(cli1, sname, 0, 0);
6527         cli_posix_unlink(cli1, sname);
6528         cli_setatr(cli1, hname, 0, 0);
6529         cli_posix_unlink(cli1, hname);
6530         cli_setatr(cli1, fname, 0, 0);
6531         cli_posix_unlink(cli1, fname);
6532         cli_setatr(cli1, dname, 0, 0);
6533         cli_posix_rmdir(cli1, dname);
6534         cli_setatr(cli1, fname_windows, 0, 0);
6535         cli_posix_unlink(cli1, fname_windows);
6536
6537         if (!torture_close_connection(cli1)) {
6538                 correct = false;
6539         }
6540
6541         return correct;
6542 }
6543
6544 /*
6545   Test POSIX and Windows ACLs are rejected on symlinks.
6546  */
6547 static bool run_acl_symlink_test(int dummy)
6548 {
6549         static struct cli_state *cli;
6550         const char *fname = "posix_file";
6551         const char *sname = "posix_symlink";
6552         uint16_t fnum = (uint16_t)-1;
6553         bool correct = false;
6554         NTSTATUS status;
6555         char *posix_acl = NULL;
6556         size_t posix_acl_len = 0;
6557         char *posix_acl_sym = NULL;
6558         size_t posix_acl_len_sym = 0;
6559         struct security_descriptor *sd = NULL;
6560         struct security_descriptor *sd_sym = NULL;
6561         TALLOC_CTX *frame = NULL;
6562
6563         frame = talloc_stackframe();
6564
6565         printf("Starting acl symlink test\n");
6566
6567         if (!torture_open_connection(&cli, 0)) {
6568                 TALLOC_FREE(frame);
6569                 return false;
6570         }
6571
6572         smbXcli_conn_set_sockopt(cli->conn, sockops);
6573
6574         status = torture_setup_unix_extensions(cli);
6575         if (!NT_STATUS_IS_OK(status)) {
6576                 TALLOC_FREE(frame);
6577                 return false;
6578         }
6579
6580         cli_setatr(cli, fname, 0, 0);
6581         cli_posix_unlink(cli, fname);
6582         cli_setatr(cli, sname, 0, 0);
6583         cli_posix_unlink(cli, sname);
6584
6585         status = cli_ntcreate(cli,
6586                         fname,
6587                         0,
6588                         READ_CONTROL_ACCESS,
6589                         0,
6590                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6591                         FILE_CREATE,
6592                         0x0,
6593                         0x0,
6594                         &fnum,
6595                         NULL);
6596
6597         if (!NT_STATUS_IS_OK(status)) {
6598                 printf("cli_ntcreate of %s failed (%s)\n",
6599                         fname,
6600                         nt_errstr(status));
6601                 goto out;
6602         }
6603
6604         /* Get the Windows ACL on the file. */
6605         status = cli_query_secdesc(cli,
6606                                 fnum,
6607                                 frame,
6608                                 &sd);
6609         if (!NT_STATUS_IS_OK(status)) {
6610                 printf("cli_query_secdesc failed (%s)\n",
6611                         nt_errstr(status));
6612                 goto out;
6613         }
6614
6615         /* Get the POSIX ACL on the file. */
6616         status = cli_posix_getacl(cli,
6617                                 fname,
6618                                 frame,
6619                                 &posix_acl_len,
6620                                 &posix_acl);
6621
6622         if (!NT_STATUS_IS_OK(status)) {
6623                 printf("cli_posix_getacl failed (%s)\n",
6624                         nt_errstr(status));
6625                 goto out;
6626         }
6627
6628         status = cli_close(cli, fnum);
6629         if (!NT_STATUS_IS_OK(status)) {
6630                 printf("close failed (%s)\n", nt_errstr(status));
6631                 goto out;
6632         }
6633         fnum = (uint16_t)-1;
6634
6635         /* Now create a symlink. */
6636         status = cli_posix_symlink(cli, fname, sname);
6637         if (!NT_STATUS_IS_OK(status)) {
6638                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
6639                         sname,
6640                         fname,
6641                         nt_errstr(status));
6642                 goto out;
6643         }
6644
6645         /* Open a handle on the symlink. */
6646         status = cli_ntcreate(cli,
6647                         sname,
6648                         0,
6649                         READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
6650                         0,
6651                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6652                         FILE_OPEN,
6653                         0x0,
6654                         0x0,
6655                         &fnum,
6656                         NULL);
6657
6658         if (!NT_STATUS_IS_OK(status)) {
6659                 printf("cli_posix_open of %s failed (%s)\n",
6660                         sname,
6661                         nt_errstr(status));
6662                 goto out;
6663         }
6664
6665         /* Get the Windows ACL on the symlink handle. Should fail */
6666         status = cli_query_secdesc(cli,
6667                                 fnum,
6668                                 frame,
6669                                 &sd_sym);
6670
6671         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6672                 printf("cli_query_secdesc on a symlink gave %s. "
6673                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6674                         nt_errstr(status));
6675                 goto out;
6676         }
6677
6678         /* Get the POSIX ACL on the symlink pathname. Should fail. */
6679         status = cli_posix_getacl(cli,
6680                                 sname,
6681                                 frame,
6682                                 &posix_acl_len_sym,
6683                                 &posix_acl_sym);
6684
6685         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6686                 printf("cli_posix_getacl on a symlink gave %s. "
6687                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6688                         nt_errstr(status));
6689                 goto out;
6690         }
6691
6692         /* Set the Windows ACL on the symlink handle. Should fail */
6693         status = cli_set_security_descriptor(cli,
6694                                 fnum,
6695                                 SECINFO_DACL,
6696                                 sd);
6697
6698         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6699                 printf("cli_query_secdesc on a symlink gave %s. "
6700                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6701                         nt_errstr(status));
6702                 goto out;
6703         }
6704
6705         /* Set the POSIX ACL on the symlink pathname. Should fail. */
6706         status = cli_posix_setacl(cli,
6707                                 sname,
6708                                 posix_acl,
6709                                 posix_acl_len);
6710
6711         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6712                 printf("cli_posix_getacl on a symlink gave %s. "
6713                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6714                         nt_errstr(status));
6715                 goto out;
6716         }
6717
6718         printf("ACL symlink test passed\n");
6719         correct = true;
6720
6721   out:
6722
6723         if (fnum != (uint16_t)-1) {
6724                 cli_close(cli, fnum);
6725                 fnum = (uint16_t)-1;
6726         }
6727
6728         cli_setatr(cli, sname, 0, 0);
6729         cli_posix_unlink(cli, sname);
6730         cli_setatr(cli, fname, 0, 0);
6731         cli_posix_unlink(cli, fname);
6732
6733         if (!torture_close_connection(cli)) {
6734                 correct = false;
6735         }
6736
6737         TALLOC_FREE(frame);
6738         return correct;
6739 }
6740
6741 /*
6742   Test POSIX can delete a file containing streams.
6743  */
6744 static bool run_posix_stream_delete(int dummy)
6745 {
6746         struct cli_state *cli1 = NULL;
6747         struct cli_state *cli2 = NULL;
6748         const char *fname = "streamfile";
6749         const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
6750         uint16_t fnum1 = (uint16_t)-1;
6751         bool correct = false;
6752         NTSTATUS status;
6753         TALLOC_CTX *frame = NULL;
6754
6755         frame = talloc_stackframe();
6756
6757         printf("Starting POSIX stream delete test\n");
6758
6759         if (!torture_open_connection(&cli1, 0) ||
6760                         !torture_open_connection(&cli2, 1)) {
6761                 TALLOC_FREE(frame);
6762                 return false;
6763         }
6764
6765         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6766         smbXcli_conn_set_sockopt(cli2->conn, sockops);
6767
6768         status = torture_setup_unix_extensions(cli2);
6769         if (!NT_STATUS_IS_OK(status)) {
6770                 goto out;
6771         }
6772
6773         cli_setatr(cli1, fname, 0, 0);
6774         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6775
6776         /* Create the file. */
6777         status = cli_ntcreate(cli1,
6778                         fname,
6779                         0,
6780                         READ_CONTROL_ACCESS,
6781                         0,
6782                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6783                         FILE_CREATE,
6784                         0x0,
6785                         0x0,
6786                         &fnum1,
6787                         NULL);
6788
6789         if (!NT_STATUS_IS_OK(status)) {
6790                 printf("cli_ntcreate of %s failed (%s)\n",
6791                         fname,
6792                         nt_errstr(status));
6793                 goto out;
6794         }
6795
6796         status = cli_close(cli1, fnum1);
6797         if (!NT_STATUS_IS_OK(status)) {
6798                 printf("cli_close of %s failed (%s)\n",
6799                         fname,
6800                         nt_errstr(status));
6801                 goto out;
6802         }
6803         fnum1 = (uint16_t)-1;
6804
6805         /* Now create the stream. */
6806         status = cli_ntcreate(cli1,
6807                         stream_fname,
6808                         0,
6809                         FILE_WRITE_DATA,
6810                         0,
6811                         FILE_SHARE_READ|FILE_SHARE_WRITE,
6812                         FILE_CREATE,
6813                         0x0,
6814                         0x0,
6815                         &fnum1,
6816                         NULL);
6817
6818         if (!NT_STATUS_IS_OK(status)) {
6819                 printf("cli_ntcreate of %s failed (%s)\n",
6820                         stream_fname,
6821                         nt_errstr(status));
6822                 goto out;
6823         }
6824
6825         /* Leave the stream handle open... */
6826
6827         /* POSIX unlink should fail. */
6828         status = cli_posix_unlink(cli2, fname);
6829         if (NT_STATUS_IS_OK(status)) {
6830                 printf("cli_posix_unlink of %s succeeded, should have failed\n",
6831                         fname);
6832                 goto out;
6833         }
6834
6835         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6836                 printf("cli_posix_unlink of %s failed with (%s) "
6837                         "should have been NT_STATUS_SHARING_VIOLATION\n",
6838                         fname,
6839                         nt_errstr(status));
6840                 goto out;
6841         }
6842
6843         /* Close the stream handle. */
6844         status = cli_close(cli1, fnum1);
6845         if (!NT_STATUS_IS_OK(status)) {
6846                 printf("cli_close of %s failed (%s)\n",
6847                         stream_fname,
6848                         nt_errstr(status));
6849                 goto out;
6850         }
6851         fnum1 = (uint16_t)-1;
6852
6853         /* POSIX unlink after stream handle closed should succeed. */
6854         status = cli_posix_unlink(cli2, fname);
6855         if (!NT_STATUS_IS_OK(status)) {
6856                 printf("cli_posix_unlink of %s failed (%s)\n",
6857                         fname,
6858                         nt_errstr(status));
6859                 goto out;
6860         }
6861
6862         printf("POSIX stream delete test passed\n");
6863         correct = true;
6864
6865   out:
6866
6867         if (fnum1 != (uint16_t)-1) {
6868                 cli_close(cli1, fnum1);
6869                 fnum1 = (uint16_t)-1;
6870         }
6871
6872         cli_setatr(cli1, fname, 0, 0);
6873         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6874
6875         if (!torture_close_connection(cli1)) {
6876                 correct = false;
6877         }
6878         if (!torture_close_connection(cli2)) {
6879                 correct = false;
6880         }
6881
6882         TALLOC_FREE(frame);
6883         return correct;
6884 }
6885
6886 /*
6887   Test setting EA's are rejected on symlinks.
6888  */
6889 static bool run_ea_symlink_test(int dummy)
6890 {
6891         static struct cli_state *cli;
6892         const char *fname = "posix_file_ea";
6893         const char *sname = "posix_symlink_ea";
6894         const char *ea_name = "testea_name";
6895         const char *ea_value = "testea_value";
6896         uint16_t fnum = (uint16_t)-1;
6897         bool correct = false;
6898         NTSTATUS status;
6899         size_t i, num_eas;
6900         struct ea_struct *eas = NULL;
6901         TALLOC_CTX *frame = NULL;
6902
6903         frame = talloc_stackframe();
6904
6905         printf("Starting EA symlink test\n");
6906
6907         if (!torture_open_connection(&cli, 0)) {
6908                 TALLOC_FREE(frame);
6909                 return false;
6910         }
6911
6912         smbXcli_conn_set_sockopt(cli->conn, sockops);
6913
6914         status = torture_setup_unix_extensions(cli);
6915         if (!NT_STATUS_IS_OK(status)) {
6916                 TALLOC_FREE(frame);
6917                 return false;
6918         }
6919
6920         cli_setatr(cli, fname, 0, 0);
6921         cli_posix_unlink(cli, fname);
6922         cli_setatr(cli, sname, 0, 0);
6923         cli_posix_unlink(cli, sname);
6924
6925         status = cli_ntcreate(cli,
6926                         fname,
6927                         0,
6928                         READ_CONTROL_ACCESS,
6929                         0,
6930                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6931                         FILE_CREATE,
6932                         0x0,
6933                         0x0,
6934                         &fnum,
6935                         NULL);
6936
6937         if (!NT_STATUS_IS_OK(status)) {
6938                 printf("cli_ntcreate of %s failed (%s)\n",
6939                         fname,
6940                         nt_errstr(status));
6941                 goto out;
6942         }
6943
6944         status = cli_close(cli, fnum);
6945         if (!NT_STATUS_IS_OK(status)) {
6946                 printf("close failed (%s)\n",
6947                         nt_errstr(status));
6948                 goto out;
6949         }
6950         fnum = (uint16_t)-1;
6951
6952         /* Set an EA on the path. */
6953         status = cli_set_ea_path(cli,
6954                                 fname,
6955                                 ea_name,
6956                                 ea_value,
6957                                 strlen(ea_value)+1);
6958
6959         if (!NT_STATUS_IS_OK(status)) {
6960                 printf("cli_set_ea_path failed (%s)\n",
6961                         nt_errstr(status));
6962                 goto out;
6963         }
6964
6965         /* Now create a symlink. */
6966         status = cli_posix_symlink(cli, fname, sname);
6967         if (!NT_STATUS_IS_OK(status)) {
6968                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
6969                         sname,
6970                         fname,
6971                         nt_errstr(status));
6972                 goto out;
6973         }
6974
6975         /* Get the EA list on the path. Should return value set. */
6976         status = cli_get_ea_list_path(cli,
6977                                 fname,
6978                                 frame,
6979                                 &num_eas,
6980                                 &eas);
6981
6982         if (!NT_STATUS_IS_OK(status)) {
6983                 printf("cli_get_ea_list_path failed (%s)\n",
6984                         nt_errstr(status));
6985                 goto out;
6986         }
6987
6988         /* Ensure the EA we set is there. */
6989         for (i=0; i<num_eas; i++) {
6990                 if (strcmp(eas[i].name, ea_name) == 0 &&
6991                                 eas[i].value.length == strlen(ea_value)+1 &&
6992                                 memcmp(eas[i].value.data,
6993                                         ea_value,
6994                                         eas[i].value.length) == 0) {
6995                         break;
6996                 }
6997         }
6998
6999         if (i == num_eas) {
7000                 printf("Didn't find EA on pathname %s\n",
7001                         fname);
7002                 goto out;
7003         }
7004
7005         num_eas = 0;
7006         TALLOC_FREE(eas);
7007
7008         /* Get the EA list on the symlink. Should return empty list. */
7009         status = cli_get_ea_list_path(cli,
7010                                 sname,
7011                                 frame,
7012                                 &num_eas,
7013                                 &eas);
7014
7015         if (!NT_STATUS_IS_OK(status)) {
7016                 printf("cli_get_ea_list_path failed (%s)\n",
7017                         nt_errstr(status));
7018                 goto out;
7019         }
7020
7021         if (num_eas != 0) {
7022                 printf("cli_get_ea_list_path failed (%s)\n",
7023                         nt_errstr(status));
7024                 goto out;
7025         }
7026
7027         /* Set an EA on the symlink. Should fail. */
7028         status = cli_set_ea_path(cli,
7029                                 sname,
7030                                 ea_name,
7031                                 ea_value,
7032                                 strlen(ea_value)+1);
7033
7034         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7035                 printf("cli_set_ea_path on a symlink gave %s. "
7036                         "Should be NT_STATUS_ACCESS_DENIED.\n",
7037                         nt_errstr(status));
7038                 goto out;
7039         }
7040
7041         printf("EA symlink test passed\n");
7042         correct = true;
7043
7044   out:
7045
7046         if (fnum != (uint16_t)-1) {
7047                 cli_close(cli, fnum);
7048                 fnum = (uint16_t)-1;
7049         }
7050
7051         cli_setatr(cli, sname, 0, 0);
7052         cli_posix_unlink(cli, sname);
7053         cli_setatr(cli, fname, 0, 0);
7054         cli_posix_unlink(cli, fname);
7055
7056         if (!torture_close_connection(cli)) {
7057                 correct = false;
7058         }
7059
7060         TALLOC_FREE(frame);
7061         return correct;
7062 }
7063
7064 /*
7065   Test POSIX locks are OFD-locks.
7066  */
7067 static bool run_posix_ofd_lock_test(int dummy)
7068 {
7069         static struct cli_state *cli;
7070         const char *fname = "posix_file";
7071         uint16_t fnum1 = (uint16_t)-1;
7072         uint16_t fnum2 = (uint16_t)-1;
7073         bool correct = false;
7074         NTSTATUS status;
7075         TALLOC_CTX *frame = NULL;
7076
7077         frame = talloc_stackframe();
7078
7079         printf("Starting POSIX ofd-lock test\n");
7080
7081         if (!torture_open_connection(&cli, 0)) {
7082                 TALLOC_FREE(frame);
7083                 return false;
7084         }
7085
7086         smbXcli_conn_set_sockopt(cli->conn, sockops);
7087
7088         status = torture_setup_unix_extensions(cli);
7089         if (!NT_STATUS_IS_OK(status)) {
7090                 TALLOC_FREE(frame);
7091                 return false;
7092         }
7093
7094         cli_setatr(cli, fname, 0, 0);
7095         cli_posix_unlink(cli, fname);
7096
7097         /* Open the file twice. */
7098         status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
7099                                 0600, &fnum1);
7100         if (!NT_STATUS_IS_OK(status)) {
7101                 printf("First POSIX open of %s failed\n", fname);
7102                 goto out;
7103         }
7104
7105         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
7106         if (!NT_STATUS_IS_OK(status)) {
7107                 printf("First POSIX open of %s failed\n", fname);
7108                 goto out;
7109         }
7110
7111         /* Set a 0-50 lock on fnum1. */
7112         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
7113         if (!NT_STATUS_IS_OK(status)) {
7114                 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
7115                 goto out;
7116         }
7117
7118         /* Set a 60-100 lock on fnum2. */
7119         status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
7120         if (!NT_STATUS_IS_OK(status)) {
7121                 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
7122                 goto out;
7123         }
7124
7125         /* close fnum1 - 0-50 lock should go away. */
7126         status = cli_close(cli, fnum1);
7127         if (!NT_STATUS_IS_OK(status)) {
7128                 printf("close failed (%s)\n",
7129                         nt_errstr(status));
7130                 goto out;
7131         }
7132         fnum1 = (uint16_t)-1;
7133
7134         /* Change the lock context. */
7135         cli_setpid(cli, cli_getpid(cli) + 1);
7136
7137         /* Re-open fnum1. */
7138         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
7139         if (!NT_STATUS_IS_OK(status)) {
7140                 printf("Third POSIX open of %s failed\n", fname);
7141                 goto out;
7142         }
7143
7144         /* 60-100 lock should still be there. */
7145         status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
7146         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
7147                 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
7148                 goto out;
7149         }
7150
7151         /* 0-50 lock should be gone. */
7152         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
7153         if (!NT_STATUS_IS_OK(status)) {
7154                 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
7155                 goto out;
7156         }
7157
7158         printf("POSIX OFD lock test passed\n");
7159         correct = true;
7160
7161   out:
7162
7163         if (fnum1 != (uint16_t)-1) {
7164                 cli_close(cli, fnum1);
7165                 fnum1 = (uint16_t)-1;
7166         }
7167         if (fnum2 != (uint16_t)-1) {
7168                 cli_close(cli, fnum2);
7169                 fnum2 = (uint16_t)-1;
7170         }
7171
7172         cli_setatr(cli, fname, 0, 0);
7173         cli_posix_unlink(cli, fname);
7174
7175         if (!torture_close_connection(cli)) {
7176                 correct = false;
7177         }
7178
7179         TALLOC_FREE(frame);
7180         return correct;
7181 }
7182
7183 static uint32_t open_attrs_table[] = {
7184                 FILE_ATTRIBUTE_NORMAL,
7185                 FILE_ATTRIBUTE_ARCHIVE,
7186                 FILE_ATTRIBUTE_READONLY,
7187                 FILE_ATTRIBUTE_HIDDEN,
7188                 FILE_ATTRIBUTE_SYSTEM,
7189
7190                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
7191                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
7192                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
7193                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
7194                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
7195                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
7196
7197                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
7198                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
7199                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
7200                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
7201 };
7202
7203 struct trunc_open_results {
7204         unsigned int num;
7205         uint32_t init_attr;
7206         uint32_t trunc_attr;
7207         uint32_t result_attr;
7208 };
7209
7210 static struct trunc_open_results attr_results[] = {
7211         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
7212         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
7213         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
7214         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
7215         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
7216         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
7217         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7218         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7219         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
7220         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7221         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7222         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
7223         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7224         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7225         { 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 },
7226         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7227         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7228         { 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 },
7229         { 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 },
7230         { 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 },
7231         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7232         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7233         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
7234         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7235         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7236         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
7237 };
7238
7239 static bool run_openattrtest(int dummy)
7240 {
7241         static struct cli_state *cli1;
7242         const char *fname = "\\openattr.file";
7243         uint16_t fnum1;
7244         bool correct = True;
7245         uint16_t attr;
7246         unsigned int i, j, k, l;
7247         NTSTATUS status;
7248
7249         printf("starting open attr test\n");
7250
7251         if (!torture_open_connection(&cli1, 0)) {
7252                 return False;
7253         }
7254
7255         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7256
7257         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
7258                 cli_setatr(cli1, fname, 0, 0);
7259                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7260
7261                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
7262                                        open_attrs_table[i], FILE_SHARE_NONE,
7263                                        FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7264                 if (!NT_STATUS_IS_OK(status)) {
7265                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
7266                         return False;
7267                 }
7268
7269                 status = cli_close(cli1, fnum1);
7270                 if (!NT_STATUS_IS_OK(status)) {
7271                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
7272                         return False;
7273                 }
7274
7275                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
7276                         status = cli_ntcreate(cli1, fname, 0,
7277                                               FILE_READ_DATA|FILE_WRITE_DATA,
7278                                               open_attrs_table[j],
7279                                               FILE_SHARE_NONE, FILE_OVERWRITE,
7280                                               0, 0, &fnum1, NULL);
7281                         if (!NT_STATUS_IS_OK(status)) {
7282                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
7283                                         if (attr_results[l].num == k) {
7284                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
7285                                                                 k, open_attrs_table[i],
7286                                                                 open_attrs_table[j],
7287                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
7288                                                 correct = False;
7289                                         }
7290                                 }
7291
7292                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7293                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
7294                                                         k, open_attrs_table[i], open_attrs_table[j],
7295                                                         nt_errstr(status));
7296                                         correct = False;
7297                                 }
7298 #if 0
7299                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
7300 #endif
7301                                 k++;
7302                                 continue;
7303                         }
7304
7305                         status = cli_close(cli1, fnum1);
7306                         if (!NT_STATUS_IS_OK(status)) {
7307                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
7308                                 return False;
7309                         }
7310
7311                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
7312                         if (!NT_STATUS_IS_OK(status)) {
7313                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
7314                                 return False;
7315                         }
7316
7317 #if 0
7318                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
7319                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
7320 #endif
7321
7322                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
7323                                 if (attr_results[l].num == k) {
7324                                         if (attr != attr_results[l].result_attr ||
7325                                                         open_attrs_table[i] != attr_results[l].init_attr ||
7326                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
7327                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
7328                                                 open_attrs_table[i],
7329                                                 open_attrs_table[j],
7330                                                 (unsigned int)attr,
7331                                                 attr_results[l].result_attr);
7332                                                 correct = False;
7333                                         }
7334                                         break;
7335                                 }
7336                         }
7337                         k++;
7338                 }
7339         }
7340
7341         cli_setatr(cli1, fname, 0, 0);
7342         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7343
7344         printf("open attr test %s.\n", correct ? "passed" : "failed");
7345
7346         if (!torture_close_connection(cli1)) {
7347                 correct = False;
7348         }
7349         return correct;
7350 }
7351
7352 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
7353                     const char *name, void *state)
7354 {
7355         int *matched = (int *)state;
7356         if (matched != NULL) {
7357                 *matched += 1;
7358         }
7359         return NT_STATUS_OK;
7360 }
7361
7362 /*
7363   test directory listing speed
7364  */
7365 static bool run_dirtest(int dummy)
7366 {
7367         int i;
7368         static struct cli_state *cli;
7369         uint16_t fnum;
7370         struct timeval core_start;
7371         bool correct = True;
7372         int matched;
7373
7374         printf("starting directory test\n");
7375
7376         if (!torture_open_connection(&cli, 0)) {
7377                 return False;
7378         }
7379
7380         smbXcli_conn_set_sockopt(cli->conn, sockops);
7381
7382         srandom(0);
7383         for (i=0;i<torture_numops;i++) {
7384                 fstring fname;
7385                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
7386                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
7387                         fprintf(stderr,"Failed to open %s\n", fname);
7388                         return False;
7389                 }
7390                 cli_close(cli, fnum);
7391         }
7392
7393         core_start = timeval_current();
7394
7395         matched = 0;
7396         cli_list(cli, "a*.*", 0, list_fn, &matched);
7397         printf("Matched %d\n", matched);
7398
7399         matched = 0;
7400         cli_list(cli, "b*.*", 0, list_fn, &matched);
7401         printf("Matched %d\n", matched);
7402
7403         matched = 0;
7404         cli_list(cli, "xyzabc", 0, list_fn, &matched);
7405         printf("Matched %d\n", matched);
7406
7407         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
7408
7409         srandom(0);
7410         for (i=0;i<torture_numops;i++) {
7411                 fstring fname;
7412                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
7413                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7414         }
7415
7416         if (!torture_close_connection(cli)) {
7417                 correct = False;
7418         }
7419
7420         printf("finished dirtest\n");
7421
7422         return correct;
7423 }
7424
7425 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
7426                    void *state)
7427 {
7428         struct cli_state *pcli = (struct cli_state *)state;
7429         fstring fname;
7430         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
7431
7432         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7433                 return NT_STATUS_OK;
7434
7435         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7436                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
7437                         printf("del_fn: failed to rmdir %s\n,", fname );
7438         } else {
7439                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
7440                         printf("del_fn: failed to unlink %s\n,", fname );
7441         }
7442         return NT_STATUS_OK;
7443 }
7444
7445
7446 /*
7447   sees what IOCTLs are supported
7448  */
7449 bool torture_ioctl_test(int dummy)
7450 {
7451         static struct cli_state *cli;
7452         uint16_t device, function;
7453         uint16_t fnum;
7454         const char *fname = "\\ioctl.dat";
7455         DATA_BLOB blob;
7456         NTSTATUS status;
7457
7458         if (!torture_open_connection(&cli, 0)) {
7459                 return False;
7460         }
7461
7462         printf("starting ioctl test\n");
7463
7464         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7465
7466         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7467         if (!NT_STATUS_IS_OK(status)) {
7468                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7469                 return False;
7470         }
7471
7472         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
7473         printf("ioctl device info: %s\n", nt_errstr(status));
7474
7475         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
7476         printf("ioctl job info: %s\n", nt_errstr(status));
7477
7478         for (device=0;device<0x100;device++) {
7479                 printf("ioctl test with device = 0x%x\n", device);
7480                 for (function=0;function<0x100;function++) {
7481                         uint32_t code = (device<<16) | function;
7482
7483                         status = cli_raw_ioctl(cli, fnum, code, &blob);
7484
7485                         if (NT_STATUS_IS_OK(status)) {
7486                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
7487                                        (int)blob.length);
7488                                 data_blob_free(&blob);
7489                         }
7490                 }
7491         }
7492
7493         if (!torture_close_connection(cli)) {
7494                 return False;
7495         }
7496
7497         return True;
7498 }
7499
7500
7501 /*
7502   tries varients of chkpath
7503  */
7504 bool torture_chkpath_test(int dummy)
7505 {
7506         static struct cli_state *cli;
7507         uint16_t fnum;
7508         bool ret;
7509         NTSTATUS status;
7510
7511         if (!torture_open_connection(&cli, 0)) {
7512                 return False;
7513         }
7514
7515         printf("starting chkpath test\n");
7516
7517         /* cleanup from an old run */
7518         cli_rmdir(cli, "\\chkpath.dir\\dir2");
7519         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7520         cli_rmdir(cli, "\\chkpath.dir");
7521
7522         status = cli_mkdir(cli, "\\chkpath.dir");
7523         if (!NT_STATUS_IS_OK(status)) {
7524                 printf("mkdir1 failed : %s\n", nt_errstr(status));
7525                 return False;
7526         }
7527
7528         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
7529         if (!NT_STATUS_IS_OK(status)) {
7530                 printf("mkdir2 failed : %s\n", nt_errstr(status));
7531                 return False;
7532         }
7533
7534         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
7535                           DENY_NONE, &fnum);
7536         if (!NT_STATUS_IS_OK(status)) {
7537                 printf("open1 failed (%s)\n", nt_errstr(status));
7538                 return False;
7539         }
7540         cli_close(cli, fnum);
7541
7542         status = cli_chkpath(cli, "\\chkpath.dir");
7543         if (!NT_STATUS_IS_OK(status)) {
7544                 printf("chkpath1 failed: %s\n", nt_errstr(status));
7545                 ret = False;
7546         }
7547
7548         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
7549         if (!NT_STATUS_IS_OK(status)) {
7550                 printf("chkpath2 failed: %s\n", nt_errstr(status));
7551                 ret = False;
7552         }
7553
7554         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
7555         if (!NT_STATUS_IS_OK(status)) {
7556                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
7557                                   NT_STATUS_NOT_A_DIRECTORY);
7558         } else {
7559                 printf("* chkpath on a file should fail\n");
7560                 ret = False;
7561         }
7562
7563         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
7564         if (!NT_STATUS_IS_OK(status)) {
7565                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
7566                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
7567         } else {
7568                 printf("* chkpath on a non existent file should fail\n");
7569                 ret = False;
7570         }
7571
7572         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
7573         if (!NT_STATUS_IS_OK(status)) {
7574                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
7575                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
7576         } else {
7577                 printf("* chkpath on a non existent component should fail\n");
7578                 ret = False;
7579         }
7580
7581         cli_rmdir(cli, "\\chkpath.dir\\dir2");
7582         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7583         cli_rmdir(cli, "\\chkpath.dir");
7584
7585         if (!torture_close_connection(cli)) {
7586                 return False;
7587         }
7588
7589         return ret;
7590 }
7591
7592 static bool run_eatest(int dummy)
7593 {
7594         static struct cli_state *cli;
7595         const char *fname = "\\eatest.txt";
7596         bool correct = True;
7597         uint16_t fnum;
7598         int i;
7599         size_t num_eas;
7600         struct ea_struct *ea_list = NULL;
7601         TALLOC_CTX *mem_ctx = talloc_init("eatest");
7602         NTSTATUS status;
7603
7604         printf("starting eatest\n");
7605
7606         if (!torture_open_connection(&cli, 0)) {
7607                 talloc_destroy(mem_ctx);
7608                 return False;
7609         }
7610
7611         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7612
7613         status = cli_ntcreate(cli, fname, 0,
7614                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
7615                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
7616                               0x4044, 0, &fnum, NULL);
7617         if (!NT_STATUS_IS_OK(status)) {
7618                 printf("open failed - %s\n", nt_errstr(status));
7619                 talloc_destroy(mem_ctx);
7620                 return False;
7621         }
7622
7623         for (i = 0; i < 10; i++) {
7624                 fstring ea_name, ea_val;
7625
7626                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
7627                 memset(ea_val, (char)i+1, i+1);
7628                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
7629                 if (!NT_STATUS_IS_OK(status)) {
7630                         printf("ea_set of name %s failed - %s\n", ea_name,
7631                                nt_errstr(status));
7632                         talloc_destroy(mem_ctx);
7633                         return False;
7634                 }
7635         }
7636
7637         cli_close(cli, fnum);
7638         for (i = 0; i < 10; i++) {
7639                 fstring ea_name, ea_val;
7640
7641                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
7642                 memset(ea_val, (char)i+1, i+1);
7643                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
7644                 if (!NT_STATUS_IS_OK(status)) {
7645                         printf("ea_set of name %s failed - %s\n", ea_name,
7646                                nt_errstr(status));
7647                         talloc_destroy(mem_ctx);
7648                         return False;
7649                 }
7650         }
7651
7652         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
7653         if (!NT_STATUS_IS_OK(status)) {
7654                 printf("ea_get list failed - %s\n", nt_errstr(status));
7655                 correct = False;
7656         }
7657
7658         printf("num_eas = %d\n", (int)num_eas);
7659
7660         if (num_eas != 20) {
7661                 printf("Should be 20 EA's stored... failing.\n");
7662                 correct = False;
7663         }
7664
7665         for (i = 0; i < num_eas; i++) {
7666                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
7667                 dump_data(0, ea_list[i].value.data,
7668                           ea_list[i].value.length);
7669         }
7670
7671         /* Setting EA's to zero length deletes them. Test this */
7672         printf("Now deleting all EA's - case indepenent....\n");
7673
7674 #if 1
7675         cli_set_ea_path(cli, fname, "", "", 0);
7676 #else
7677         for (i = 0; i < 20; i++) {
7678                 fstring ea_name;
7679                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
7680                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
7681                 if (!NT_STATUS_IS_OK(status)) {
7682                         printf("ea_set of name %s failed - %s\n", ea_name,
7683                                nt_errstr(status));
7684                         talloc_destroy(mem_ctx);
7685                         return False;
7686                 }
7687         }
7688 #endif
7689
7690         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
7691         if (!NT_STATUS_IS_OK(status)) {
7692                 printf("ea_get list failed - %s\n", nt_errstr(status));
7693                 correct = False;
7694         }
7695
7696         printf("num_eas = %d\n", (int)num_eas);
7697         for (i = 0; i < num_eas; i++) {
7698                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
7699                 dump_data(0, ea_list[i].value.data,
7700                           ea_list[i].value.length);
7701         }
7702
7703         if (num_eas != 0) {
7704                 printf("deleting EA's failed.\n");
7705                 correct = False;
7706         }
7707
7708         /* Try and delete a non existent EA. */
7709         status = cli_set_ea_path(cli, fname, "foo", "", 0);
7710         if (!NT_STATUS_IS_OK(status)) {
7711                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
7712                        nt_errstr(status));
7713                 correct = False;
7714         }
7715
7716         talloc_destroy(mem_ctx);
7717         if (!torture_close_connection(cli)) {
7718                 correct = False;
7719         }
7720
7721         return correct;
7722 }
7723
7724 static bool run_dirtest1(int dummy)
7725 {
7726         int i;
7727         static struct cli_state *cli;
7728         uint16_t fnum;
7729         int num_seen;
7730         bool correct = True;
7731
7732         printf("starting directory test\n");
7733
7734         if (!torture_open_connection(&cli, 0)) {
7735                 return False;
7736         }
7737
7738         smbXcli_conn_set_sockopt(cli->conn, sockops);
7739
7740         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
7741         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
7742         cli_rmdir(cli, "\\LISTDIR");
7743         cli_mkdir(cli, "\\LISTDIR");
7744
7745         /* Create 1000 files and 1000 directories. */
7746         for (i=0;i<1000;i++) {
7747                 fstring fname;
7748                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
7749                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
7750                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
7751                                    0, 0, &fnum, NULL))) {
7752                         fprintf(stderr,"Failed to open %s\n", fname);
7753                         return False;
7754                 }
7755                 cli_close(cli, fnum);
7756         }
7757         for (i=0;i<1000;i++) {
7758                 fstring fname;
7759                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
7760                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
7761                         fprintf(stderr,"Failed to open %s\n", fname);
7762                         return False;
7763                 }
7764         }
7765
7766         /* Now ensure that doing an old list sees both files and directories. */
7767         num_seen = 0;
7768         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7769         printf("num_seen = %d\n", num_seen );
7770         /* We should see 100 files + 1000 directories + . and .. */
7771         if (num_seen != 2002)
7772                 correct = False;
7773
7774         /* Ensure if we have the "must have" bits we only see the
7775          * relevent entries.
7776          */
7777         num_seen = 0;
7778         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7779         printf("num_seen = %d\n", num_seen );
7780         if (num_seen != 1002)
7781                 correct = False;
7782
7783         num_seen = 0;
7784         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7785         printf("num_seen = %d\n", num_seen );
7786         if (num_seen != 1000)
7787                 correct = False;
7788
7789         /* Delete everything. */
7790         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
7791         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
7792         cli_rmdir(cli, "\\LISTDIR");
7793
7794 #if 0
7795         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
7796         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
7797         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
7798 #endif
7799
7800         if (!torture_close_connection(cli)) {
7801                 correct = False;
7802         }
7803
7804         printf("finished dirtest1\n");
7805
7806         return correct;
7807 }
7808
7809 static bool run_error_map_extract(int dummy) {
7810
7811         static struct cli_state *c_dos;
7812         static struct cli_state *c_nt;
7813         NTSTATUS status;
7814
7815         uint32_t error;
7816
7817         uint32_t errnum;
7818         uint8_t errclass;
7819
7820         NTSTATUS nt_status;
7821
7822         fstring user;
7823
7824         /* NT-Error connection */
7825
7826         disable_spnego = true;
7827         if (!(c_nt = open_nbt_connection())) {
7828                 disable_spnego = false;
7829                 return False;
7830         }
7831         disable_spnego = false;
7832
7833         status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
7834                                  PROTOCOL_NT1);
7835
7836         if (!NT_STATUS_IS_OK(status)) {
7837                 printf("%s rejected the NT-error negprot (%s)\n", host,
7838                        nt_errstr(status));
7839                 cli_shutdown(c_nt);
7840                 return False;
7841         }
7842
7843         status = cli_session_setup_anon(c_nt);
7844         if (!NT_STATUS_IS_OK(status)) {
7845                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
7846                 return False;
7847         }
7848
7849         /* DOS-Error connection */
7850
7851         disable_spnego = true;
7852         force_dos_errors = true;
7853         if (!(c_dos = open_nbt_connection())) {
7854                 disable_spnego = false;
7855                 force_dos_errors = false;
7856                 return False;
7857         }
7858         disable_spnego = false;
7859         force_dos_errors = false;
7860
7861         status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
7862                                  PROTOCOL_NT1);
7863         if (!NT_STATUS_IS_OK(status)) {
7864                 printf("%s rejected the DOS-error negprot (%s)\n", host,
7865                        nt_errstr(status));
7866                 cli_shutdown(c_dos);
7867                 return False;
7868         }
7869
7870         status = cli_session_setup_anon(c_dos);
7871         if (!NT_STATUS_IS_OK(status)) {
7872                 printf("%s rejected the DOS-error initial session setup (%s)\n",
7873                         host, nt_errstr(status));
7874                 return False;
7875         }
7876
7877         c_nt->map_dos_errors = false;
7878         c_dos->map_dos_errors = false;
7879
7880         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
7881                 struct cli_credentials *user_creds = NULL;
7882
7883                 fstr_sprintf(user, "%X", error);
7884
7885                 user_creds = cli_session_creds_init(talloc_tos(),
7886                                                     user,
7887                                                     workgroup,
7888                                                     NULL, /* realm */
7889                                                     password,
7890                                                     false, /* use_kerberos */
7891                                                     false, /* fallback_after_kerberos */
7892                                                     false, /* use_ccache */
7893                                                     false); /* password_is_nt_hash */
7894                 if (user_creds == NULL) {
7895                         printf("cli_session_creds_init(%s) failed\n", user);
7896                         return false;
7897                 }
7898
7899                 status = cli_session_setup_creds(c_nt, user_creds);
7900                 if (NT_STATUS_IS_OK(status)) {
7901                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
7902                 }
7903
7904                 /* Case #1: 32-bit NT errors */
7905                 if (!NT_STATUS_IS_DOS(status)) {
7906                         nt_status = status;
7907                 } else {
7908                         printf("/** Dos error on NT connection! (%s) */\n", 
7909                                nt_errstr(status));
7910                         nt_status = NT_STATUS(0xc0000000);
7911                 }
7912
7913                 status = cli_session_setup_creds(c_dos, user_creds);
7914                 if (NT_STATUS_IS_OK(status)) {
7915                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
7916                 }
7917
7918                 /* Case #1: 32-bit NT errors */
7919                 if (NT_STATUS_IS_DOS(status)) {
7920                         printf("/** NT error on DOS connection! (%s) */\n", 
7921                                nt_errstr(status));
7922                         errnum = errclass = 0;
7923                 } else {
7924                         errclass = NT_STATUS_DOS_CLASS(status);
7925                         errnum = NT_STATUS_DOS_CODE(status);
7926                 }
7927
7928                 if (NT_STATUS_V(nt_status) != error) { 
7929                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
7930                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
7931                                get_nt_error_c_code(talloc_tos(), nt_status));
7932                 }
7933
7934                 printf("\t{%s,\t%s,\t%s},\n", 
7935                        smb_dos_err_class(errclass), 
7936                        smb_dos_err_name(errclass, errnum), 
7937                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
7938
7939                 TALLOC_FREE(user_creds);
7940         }
7941         return True;
7942 }
7943
7944 static bool run_sesssetup_bench(int dummy)
7945 {
7946         static struct cli_state *c;
7947         const char *fname = "\\file.dat";
7948         uint16_t fnum;
7949         NTSTATUS status;
7950         int i;
7951
7952         if (!torture_open_connection(&c, 0)) {
7953                 return false;
7954         }
7955
7956         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7957                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7958                               FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
7959         if (!NT_STATUS_IS_OK(status)) {
7960                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7961                 return false;
7962         }
7963
7964         for (i=0; i<torture_numops; i++) {
7965                 status = cli_session_setup_creds(c, torture_creds);
7966                 if (!NT_STATUS_IS_OK(status)) {
7967                         d_printf("(%s) cli_session_setup_creds failed: %s\n",
7968                                  __location__, nt_errstr(status));
7969                         return false;
7970                 }
7971
7972                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
7973
7974                 status = cli_ulogoff(c);
7975                 if (!NT_STATUS_IS_OK(status)) {
7976                         d_printf("(%s) cli_ulogoff failed: %s\n",
7977                                  __location__, nt_errstr(status));
7978                         return false;
7979                 }
7980         }
7981
7982         return true;
7983 }
7984
7985 static bool subst_test(const char *str, const char *user, const char *domain,
7986                        uid_t uid, gid_t gid, const char *expected)
7987 {
7988         char *subst;
7989         bool result = true;
7990
7991         subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
7992
7993         if (strcmp(subst, expected) != 0) {
7994                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
7995                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
7996                        expected);
7997                 result = false;
7998         }
7999
8000         TALLOC_FREE(subst);
8001         return result;
8002 }
8003
8004 static void chain1_open_completion(struct tevent_req *req)
8005 {
8006         uint16_t fnum;
8007         NTSTATUS status;
8008         status = cli_openx_recv(req, &fnum);
8009         TALLOC_FREE(req);
8010
8011         d_printf("cli_openx_recv returned %s: %d\n",
8012                  nt_errstr(status),
8013                  NT_STATUS_IS_OK(status) ? fnum : -1);
8014 }
8015
8016 static void chain1_write_completion(struct tevent_req *req)
8017 {
8018         size_t written;
8019         NTSTATUS status;
8020         status = cli_write_andx_recv(req, &written);
8021         TALLOC_FREE(req);
8022
8023         d_printf("cli_write_andx_recv returned %s: %d\n",
8024                  nt_errstr(status),
8025                  NT_STATUS_IS_OK(status) ? (int)written : -1);
8026 }
8027
8028 static void chain1_close_completion(struct tevent_req *req)
8029 {
8030         NTSTATUS status;
8031         bool *done = (bool *)tevent_req_callback_data_void(req);
8032
8033         status = cli_close_recv(req);
8034         *done = true;
8035
8036         TALLOC_FREE(req);
8037
8038         d_printf("cli_close returned %s\n", nt_errstr(status));
8039 }
8040
8041 static bool run_chain1(int dummy)
8042 {
8043         struct cli_state *cli1;
8044         struct tevent_context *evt = samba_tevent_context_init(NULL);
8045         struct tevent_req *reqs[3], *smbreqs[3];
8046         bool done = false;
8047         const char *str = "foobar";
8048         NTSTATUS status;
8049
8050         printf("starting chain1 test\n");
8051         if (!torture_open_connection(&cli1, 0)) {
8052                 return False;
8053         }
8054
8055         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8056
8057         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, "\\test",
8058                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
8059         if (reqs[0] == NULL) return false;
8060         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
8061
8062
8063         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
8064                                         (const uint8_t *)str, 0, strlen(str)+1,
8065                                         smbreqs, 1, &smbreqs[1]);
8066         if (reqs[1] == NULL) return false;
8067         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
8068
8069         reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
8070         if (reqs[2] == NULL) return false;
8071         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
8072
8073         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
8074         if (!NT_STATUS_IS_OK(status)) {
8075                 return false;
8076         }
8077
8078         while (!done) {
8079                 tevent_loop_once(evt);
8080         }
8081
8082         torture_close_connection(cli1);
8083         return True;
8084 }
8085
8086 static void chain2_sesssetup_completion(struct tevent_req *req)
8087 {
8088         NTSTATUS status;
8089         status = cli_session_setup_guest_recv(req);
8090         d_printf("sesssetup returned %s\n", nt_errstr(status));
8091 }
8092
8093 static void chain2_tcon_completion(struct tevent_req *req)
8094 {
8095         bool *done = (bool *)tevent_req_callback_data_void(req);
8096         NTSTATUS status;
8097         status = cli_tcon_andx_recv(req);
8098         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
8099         *done = true;
8100 }
8101
8102 static bool run_chain2(int dummy)
8103 {
8104         struct cli_state *cli1;
8105         struct tevent_context *evt = samba_tevent_context_init(NULL);
8106         struct tevent_req *reqs[2], *smbreqs[2];
8107         bool done = false;
8108         NTSTATUS status;
8109         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
8110
8111         printf("starting chain2 test\n");
8112         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
8113                                       port_to_use, SMB_SIGNING_DEFAULT, flags);
8114         if (!NT_STATUS_IS_OK(status)) {
8115                 return False;
8116         }
8117
8118         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8119
8120         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
8121                                                  &smbreqs[0]);
8122         if (reqs[0] == NULL) return false;
8123         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
8124
8125         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
8126                                        "?????", NULL, 0, &smbreqs[1]);
8127         if (reqs[1] == NULL) return false;
8128         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
8129
8130         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
8131         if (!NT_STATUS_IS_OK(status)) {
8132                 return false;
8133         }
8134
8135         while (!done) {
8136                 tevent_loop_once(evt);
8137         }
8138
8139         torture_close_connection(cli1);
8140         return True;
8141 }
8142
8143
8144 struct torture_createdel_state {
8145         struct tevent_context *ev;
8146         struct cli_state *cli;
8147 };
8148
8149 static void torture_createdel_created(struct tevent_req *subreq);
8150 static void torture_createdel_closed(struct tevent_req *subreq);
8151
8152 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
8153                                                  struct tevent_context *ev,
8154                                                  struct cli_state *cli,
8155                                                  const char *name)
8156 {
8157         struct tevent_req *req, *subreq;
8158         struct torture_createdel_state *state;
8159
8160         req = tevent_req_create(mem_ctx, &state,
8161                                 struct torture_createdel_state);
8162         if (req == NULL) {
8163                 return NULL;
8164         }
8165         state->ev = ev;
8166         state->cli = cli;
8167
8168         subreq = cli_ntcreate_send(
8169                 state, ev, cli, name, 0,
8170                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
8171                 FILE_ATTRIBUTE_NORMAL,
8172                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8173                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
8174
8175         if (tevent_req_nomem(subreq, req)) {
8176                 return tevent_req_post(req, ev);
8177         }
8178         tevent_req_set_callback(subreq, torture_createdel_created, req);
8179         return req;
8180 }
8181
8182 static void torture_createdel_created(struct tevent_req *subreq)
8183 {
8184         struct tevent_req *req = tevent_req_callback_data(
8185                 subreq, struct tevent_req);
8186         struct torture_createdel_state *state = tevent_req_data(
8187                 req, struct torture_createdel_state);
8188         NTSTATUS status;
8189         uint16_t fnum;
8190
8191         status = cli_ntcreate_recv(subreq, &fnum, NULL);
8192         TALLOC_FREE(subreq);
8193         if (tevent_req_nterror(req, status)) {
8194                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
8195                            nt_errstr(status)));
8196                 return;
8197         }
8198
8199         subreq = cli_close_send(state, state->ev, state->cli, fnum);
8200         if (tevent_req_nomem(subreq, req)) {
8201                 return;
8202         }
8203         tevent_req_set_callback(subreq, torture_createdel_closed, req);
8204 }
8205
8206 static void torture_createdel_closed(struct tevent_req *subreq)
8207 {
8208         struct tevent_req *req = tevent_req_callback_data(
8209                 subreq, struct tevent_req);
8210         NTSTATUS status;
8211
8212         status = cli_close_recv(subreq);
8213         if (tevent_req_nterror(req, status)) {
8214                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
8215                 return;
8216         }
8217         tevent_req_done(req);
8218 }
8219
8220 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
8221 {
8222         return tevent_req_simple_recv_ntstatus(req);
8223 }
8224
8225 struct torture_createdels_state {
8226         struct tevent_context *ev;
8227         struct cli_state *cli;
8228         const char *base_name;
8229         int sent;
8230         int received;
8231         int num_files;
8232         struct tevent_req **reqs;
8233 };
8234
8235 static void torture_createdels_done(struct tevent_req *subreq);
8236
8237 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
8238                                                   struct tevent_context *ev,
8239                                                   struct cli_state *cli,
8240                                                   const char *base_name,
8241                                                   int num_parallel,
8242                                                   int num_files)
8243 {
8244         struct tevent_req *req;
8245         struct torture_createdels_state *state;
8246         int i;
8247
8248         req = tevent_req_create(mem_ctx, &state,
8249                                 struct torture_createdels_state);
8250         if (req == NULL) {
8251                 return NULL;
8252         }
8253         state->ev = ev;
8254         state->cli = cli;
8255         state->base_name = talloc_strdup(state, base_name);
8256         if (tevent_req_nomem(state->base_name, req)) {
8257                 return tevent_req_post(req, ev);
8258         }
8259         state->num_files = MAX(num_parallel, num_files);
8260         state->sent = 0;
8261         state->received = 0;
8262
8263         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
8264         if (tevent_req_nomem(state->reqs, req)) {
8265                 return tevent_req_post(req, ev);
8266         }
8267
8268         for (i=0; i<num_parallel; i++) {
8269                 char *name;
8270
8271                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
8272                                        state->sent);
8273                 if (tevent_req_nomem(name, req)) {
8274                         return tevent_req_post(req, ev);
8275                 }
8276                 state->reqs[i] = torture_createdel_send(
8277                         state->reqs, state->ev, state->cli, name);
8278                 if (tevent_req_nomem(state->reqs[i], req)) {
8279                         return tevent_req_post(req, ev);
8280                 }
8281                 name = talloc_move(state->reqs[i], &name);
8282                 tevent_req_set_callback(state->reqs[i],
8283                                         torture_createdels_done, req);
8284                 state->sent += 1;
8285         }
8286         return req;
8287 }
8288
8289 static void torture_createdels_done(struct tevent_req *subreq)
8290 {
8291         struct tevent_req *req = tevent_req_callback_data(
8292                 subreq, struct tevent_req);
8293         struct torture_createdels_state *state = tevent_req_data(
8294                 req, struct torture_createdels_state);
8295         size_t num_parallel = talloc_array_length(state->reqs);
8296         NTSTATUS status;
8297         char *name;
8298         int i;
8299
8300         status = torture_createdel_recv(subreq);
8301         if (!NT_STATUS_IS_OK(status)){
8302                 DEBUG(10, ("torture_createdel_recv returned %s\n",
8303                            nt_errstr(status)));
8304                 TALLOC_FREE(subreq);
8305                 tevent_req_nterror(req, status);
8306                 return;
8307         }
8308
8309         for (i=0; i<num_parallel; i++) {
8310                 if (subreq == state->reqs[i]) {
8311                         break;
8312                 }
8313         }
8314         if (i == num_parallel) {
8315                 DEBUG(10, ("received something we did not send\n"));
8316                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
8317                 return;
8318         }
8319         TALLOC_FREE(state->reqs[i]);
8320
8321         if (state->sent >= state->num_files) {
8322                 tevent_req_done(req);
8323                 return;
8324         }
8325
8326         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
8327                                state->sent);
8328         if (tevent_req_nomem(name, req)) {
8329                 return;
8330         }
8331         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
8332                                                 state->cli, name);
8333         if (tevent_req_nomem(state->reqs[i], req)) {
8334                 return;
8335         }
8336         name = talloc_move(state->reqs[i], &name);
8337         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
8338         state->sent += 1;
8339 }
8340
8341 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
8342 {
8343         return tevent_req_simple_recv_ntstatus(req);
8344 }
8345
8346 struct swallow_notify_state {
8347         struct tevent_context *ev;
8348         struct cli_state *cli;
8349         uint16_t fnum;
8350         uint32_t completion_filter;
8351         bool recursive;
8352         bool (*fn)(uint32_t action, const char *name, void *priv);
8353         void *priv;
8354 };
8355
8356 static void swallow_notify_done(struct tevent_req *subreq);
8357
8358 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
8359                                               struct tevent_context *ev,
8360                                               struct cli_state *cli,
8361                                               uint16_t fnum,
8362                                               uint32_t completion_filter,
8363                                               bool recursive,
8364                                               bool (*fn)(uint32_t action,
8365                                                          const char *name,
8366                                                          void *priv),
8367                                               void *priv)
8368 {
8369         struct tevent_req *req, *subreq;
8370         struct swallow_notify_state *state;
8371
8372         req = tevent_req_create(mem_ctx, &state,
8373                                 struct swallow_notify_state);
8374         if (req == NULL) {
8375                 return NULL;
8376         }
8377         state->ev = ev;
8378         state->cli = cli;
8379         state->fnum = fnum;
8380         state->completion_filter = completion_filter;
8381         state->recursive = recursive;
8382         state->fn = fn;
8383         state->priv = priv;
8384
8385         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
8386                                  0xffff, state->completion_filter,
8387                                  state->recursive);
8388         if (tevent_req_nomem(subreq, req)) {
8389                 return tevent_req_post(req, ev);
8390         }
8391         tevent_req_set_callback(subreq, swallow_notify_done, req);
8392         return req;
8393 }
8394
8395 static void swallow_notify_done(struct tevent_req *subreq)
8396 {
8397         struct tevent_req *req = tevent_req_callback_data(
8398                 subreq, struct tevent_req);
8399         struct swallow_notify_state *state = tevent_req_data(
8400                 req, struct swallow_notify_state);
8401         NTSTATUS status;
8402         uint32_t i, num_changes;
8403         struct notify_change *changes;
8404
8405         status = cli_notify_recv(subreq, state, &num_changes, &changes);
8406         TALLOC_FREE(subreq);
8407         if (!NT_STATUS_IS_OK(status)) {
8408                 DEBUG(10, ("cli_notify_recv returned %s\n",
8409                            nt_errstr(status)));
8410                 tevent_req_nterror(req, status);
8411                 return;
8412         }
8413
8414         for (i=0; i<num_changes; i++) {
8415                 state->fn(changes[i].action, changes[i].name, state->priv);
8416         }
8417         TALLOC_FREE(changes);
8418
8419         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
8420                                  0xffff, state->completion_filter,
8421                                  state->recursive);
8422         if (tevent_req_nomem(subreq, req)) {
8423                 return;
8424         }
8425         tevent_req_set_callback(subreq, swallow_notify_done, req);
8426 }
8427
8428 static bool print_notifies(uint32_t action, const char *name, void *priv)
8429 {
8430         if (DEBUGLEVEL > 5) {
8431                 d_printf("%d %s\n", (int)action, name);
8432         }
8433         return true;
8434 }
8435
8436 static void notify_bench_done(struct tevent_req *req)
8437 {
8438         int *num_finished = (int *)tevent_req_callback_data_void(req);
8439         *num_finished += 1;
8440 }
8441
8442 static bool run_notify_bench(int dummy)
8443 {
8444         const char *dname = "\\notify-bench";
8445         struct tevent_context *ev;
8446         NTSTATUS status;
8447         uint16_t dnum;
8448         struct tevent_req *req1;
8449         struct tevent_req *req2 = NULL;
8450         int i, num_unc_names;
8451         int num_finished = 0;
8452
8453         printf("starting notify-bench test\n");
8454
8455         if (use_multishare_conn) {
8456                 char **unc_list;
8457                 unc_list = file_lines_load(multishare_conn_fname,
8458                                            &num_unc_names, 0, NULL);
8459                 if (!unc_list || num_unc_names <= 0) {
8460                         d_printf("Failed to load unc names list from '%s'\n",
8461                                  multishare_conn_fname);
8462                         return false;
8463                 }
8464                 TALLOC_FREE(unc_list);
8465         } else {
8466                 num_unc_names = 1;
8467         }
8468
8469         ev = samba_tevent_context_init(talloc_tos());
8470         if (ev == NULL) {
8471                 d_printf("tevent_context_init failed\n");
8472                 return false;
8473         }
8474
8475         for (i=0; i<num_unc_names; i++) {
8476                 struct cli_state *cli;
8477                 char *base_fname;
8478
8479                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
8480                                              dname, i);
8481                 if (base_fname == NULL) {
8482                         return false;
8483                 }
8484
8485                 if (!torture_open_connection(&cli, i)) {
8486                         return false;
8487                 }
8488
8489                 status = cli_ntcreate(cli, dname, 0,
8490                                       MAXIMUM_ALLOWED_ACCESS,
8491                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
8492                                       FILE_SHARE_DELETE,
8493                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
8494                                       &dnum, NULL);
8495
8496                 if (!NT_STATUS_IS_OK(status)) {
8497                         d_printf("Could not create %s: %s\n", dname,
8498                                  nt_errstr(status));
8499                         return false;
8500                 }
8501
8502                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
8503                                            FILE_NOTIFY_CHANGE_FILE_NAME |
8504                                            FILE_NOTIFY_CHANGE_DIR_NAME |
8505                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
8506                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
8507                                            false, print_notifies, NULL);
8508                 if (req1 == NULL) {
8509                         d_printf("Could not create notify request\n");
8510                         return false;
8511                 }
8512
8513                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
8514                                                base_fname, 10, torture_numops);
8515                 if (req2 == NULL) {
8516                         d_printf("Could not create createdels request\n");
8517                         return false;
8518                 }
8519                 TALLOC_FREE(base_fname);
8520
8521                 tevent_req_set_callback(req2, notify_bench_done,
8522                                         &num_finished);
8523         }
8524
8525         while (num_finished < num_unc_names) {
8526                 int ret;
8527                 ret = tevent_loop_once(ev);
8528                 if (ret != 0) {
8529                         d_printf("tevent_loop_once failed\n");
8530                         return false;
8531                 }
8532         }
8533
8534         if (!tevent_req_poll(req2, ev)) {
8535                 d_printf("tevent_req_poll failed\n");
8536         }
8537
8538         status = torture_createdels_recv(req2);
8539         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
8540
8541         return true;
8542 }
8543
8544 static bool run_mangle1(int dummy)
8545 {
8546         struct cli_state *cli;
8547         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
8548         uint16_t fnum;
8549         fstring alt_name;
8550         NTSTATUS status;
8551         time_t change_time, access_time, write_time;
8552         off_t size;
8553         uint16_t mode;
8554
8555         printf("starting mangle1 test\n");
8556         if (!torture_open_connection(&cli, 0)) {
8557                 return False;
8558         }
8559
8560         smbXcli_conn_set_sockopt(cli->conn, sockops);
8561
8562         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8563                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8564                               0, 0, &fnum, NULL);
8565         if (!NT_STATUS_IS_OK(status)) {
8566                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8567                 return false;
8568         }
8569         cli_close(cli, fnum);
8570
8571         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
8572         if (!NT_STATUS_IS_OK(status)) {
8573                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
8574                          nt_errstr(status));
8575                 return false;
8576         }
8577         d_printf("alt_name: %s\n", alt_name);
8578
8579         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
8580         if (!NT_STATUS_IS_OK(status)) {
8581                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
8582                          nt_errstr(status));
8583                 return false;
8584         }
8585         cli_close(cli, fnum);
8586
8587         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
8588                                 &write_time, &size, &mode);
8589         if (!NT_STATUS_IS_OK(status)) {
8590                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
8591                          nt_errstr(status));
8592                 return false;
8593         }
8594
8595         return true;
8596 }
8597
8598 static NTSTATUS mangle_illegal_list_shortname_fn(const char *mntpoint,
8599                                                  struct file_info *f,
8600                                                  const char *mask,
8601                                                  void *state)
8602 {
8603         if (f->short_name == NULL) {
8604                 return NT_STATUS_OK;
8605         }
8606
8607         if (strlen(f->short_name) == 0) {
8608                 return NT_STATUS_OK;
8609         }
8610
8611         printf("unexpected shortname: %s\n", f->short_name);
8612
8613         return NT_STATUS_OBJECT_NAME_INVALID;
8614 }
8615
8616 static NTSTATUS mangle_illegal_list_name_fn(const char *mntpoint,
8617                                             struct file_info *f,
8618                                             const char *mask,
8619                                             void *state)
8620 {
8621         char *name = state;
8622
8623         printf("name: %s\n", f->name);
8624         fstrcpy(name, f->name);
8625         return NT_STATUS_OK;
8626 }
8627
8628 static bool run_mangle_illegal(int dummy)
8629 {
8630         struct cli_state *cli = NULL;
8631         struct cli_state *cli_posix = NULL;
8632         const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
8633         const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
8634         char *mangled_path = NULL;
8635         uint16_t fnum;
8636         fstring name;
8637         fstring alt_name;
8638         NTSTATUS status;
8639
8640         printf("starting mangle-illegal test\n");
8641
8642         if (!torture_open_connection(&cli, 0)) {
8643                 return False;
8644         }
8645
8646         smbXcli_conn_set_sockopt(cli->conn, sockops);
8647
8648         if (!torture_open_connection(&cli_posix, 0)) {
8649                 return false;
8650         }
8651
8652         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
8653
8654         status = torture_setup_unix_extensions(cli_posix);
8655         if (!NT_STATUS_IS_OK(status)) {
8656                 return false;
8657         }
8658
8659         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
8660         status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
8661         if (!NT_STATUS_IS_OK(status)) {
8662                 printf("mkdir1 failed : %s\n", nt_errstr(status));
8663                 return False;
8664         }
8665
8666         /*
8667          * Create a file with illegal NTFS characters and test that we
8668          * get a usable mangled name
8669          */
8670
8671         cli_setatr(cli_posix, illegal_fname, 0, 0);
8672         cli_posix_unlink(cli_posix, illegal_fname);
8673
8674         status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
8675                                 0600, &fnum);
8676         if (!NT_STATUS_IS_OK(status)) {
8677                 printf("POSIX create of %s failed (%s)\n",
8678                        illegal_fname, nt_errstr(status));
8679                 return false;
8680         }
8681
8682         status = cli_close(cli_posix, fnum);
8683         if (!NT_STATUS_IS_OK(status)) {
8684                 printf("close failed (%s)\n", nt_errstr(status));
8685                 return false;
8686         }
8687
8688         status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
8689         if (!NT_STATUS_IS_OK(status)) {
8690                 d_printf("cli_list failed: %s\n", nt_errstr(status));
8691                 return false;
8692         }
8693
8694         mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
8695         if (mangled_path == NULL) {
8696                 return false;
8697         }
8698
8699         status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
8700         if (!NT_STATUS_IS_OK(status)) {
8701                 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
8702                 TALLOC_FREE(mangled_path);
8703                 return false;
8704         }
8705         TALLOC_FREE(mangled_path);
8706         cli_close(cli, fnum);
8707
8708         cli_setatr(cli_posix, illegal_fname, 0, 0);
8709         cli_posix_unlink(cli_posix, illegal_fname);
8710
8711         /*
8712          * Create a file with a long name and check that we got *no* short name.
8713          */
8714
8715         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8716                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8717                               0, 0, &fnum, NULL);
8718         if (!NT_STATUS_IS_OK(status)) {
8719                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8720                 return false;
8721         }
8722         cli_close(cli, fnum);
8723
8724         status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
8725         if (!NT_STATUS_IS_OK(status)) {
8726                 d_printf("cli_list failed\n");
8727                 return false;
8728         }
8729
8730         cli_unlink(cli, fname, 0);
8731         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
8732
8733         if (!torture_close_connection(cli_posix)) {
8734                 return false;
8735         }
8736
8737         if (!torture_close_connection(cli)) {
8738                 return false;
8739         }
8740
8741         return true;
8742 }
8743
8744 static size_t null_source(uint8_t *buf, size_t n, void *priv)
8745 {
8746         size_t *to_pull = (size_t *)priv;
8747         size_t thistime = *to_pull;
8748
8749         thistime = MIN(thistime, n);
8750         if (thistime == 0) {
8751                 return 0;
8752         }
8753
8754         memset(buf, 0, thistime);
8755         *to_pull -= thistime;
8756         return thistime;
8757 }
8758
8759 static bool run_windows_write(int dummy)
8760 {
8761         struct cli_state *cli1;
8762         uint16_t fnum;
8763         int i;
8764         bool ret = false;
8765         const char *fname = "\\writetest.txt";
8766         struct timeval start_time;
8767         double seconds;
8768         double kbytes;
8769         NTSTATUS status;
8770
8771         printf("starting windows_write test\n");
8772         if (!torture_open_connection(&cli1, 0)) {
8773                 return False;
8774         }
8775
8776         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
8777         if (!NT_STATUS_IS_OK(status)) {
8778                 printf("open failed (%s)\n", nt_errstr(status));
8779                 return False;
8780         }
8781
8782         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8783
8784         start_time = timeval_current();
8785
8786         for (i=0; i<torture_numops; i++) {
8787                 uint8_t c = 0;
8788                 off_t start = i * torture_blocksize;
8789                 size_t to_pull = torture_blocksize - 1;
8790
8791                 status = cli_writeall(cli1, fnum, 0, &c,
8792                                       start + torture_blocksize - 1, 1, NULL);
8793                 if (!NT_STATUS_IS_OK(status)) {
8794                         printf("cli_write failed: %s\n", nt_errstr(status));
8795                         goto fail;
8796                 }
8797
8798                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
8799                                   null_source, &to_pull);
8800                 if (!NT_STATUS_IS_OK(status)) {
8801                         printf("cli_push returned: %s\n", nt_errstr(status));
8802                         goto fail;
8803                 }
8804         }
8805
8806         seconds = timeval_elapsed(&start_time);
8807         kbytes = (double)torture_blocksize * torture_numops;
8808         kbytes /= 1024;
8809
8810         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
8811                (double)seconds, (int)(kbytes/seconds));
8812
8813         ret = true;
8814  fail:
8815         cli_close(cli1, fnum);
8816         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8817         torture_close_connection(cli1);
8818         return ret;
8819 }
8820
8821 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
8822 {
8823         size_t max_pdu = 0x1FFFF;
8824
8825         if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
8826                 max_pdu = 0xFFFFFF;
8827         }
8828
8829         if (smb1cli_conn_signing_is_active(cli->conn)) {
8830                 max_pdu = 0x1FFFF;
8831         }
8832
8833         if (smb1cli_conn_encryption_on(cli->conn)) {
8834                 max_pdu = CLI_BUFFER_SIZE;
8835         }
8836
8837         if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
8838                 len_requested &= 0xFFFF;
8839         }
8840
8841         return MIN(len_requested,
8842                    max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
8843 }
8844
8845 static bool check_read_call(struct cli_state *cli,
8846                             uint16_t fnum,
8847                             uint8_t *buf,
8848                             size_t len_requested)
8849 {
8850         NTSTATUS status;
8851         struct tevent_req *subreq = NULL;
8852         ssize_t len_read = 0;
8853         size_t len_expected = 0;
8854         struct tevent_context *ev = NULL;
8855
8856         ev = samba_tevent_context_init(talloc_tos());
8857         if (ev == NULL) {
8858                 return false;
8859         }
8860
8861         subreq = cli_read_andx_send(talloc_tos(),
8862                                     ev,
8863                                     cli,
8864                                     fnum,
8865                                     0,
8866                                     len_requested);
8867
8868         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
8869                 return false;
8870         }
8871
8872         status = cli_read_andx_recv(subreq, &len_read, &buf);
8873         if (!NT_STATUS_IS_OK(status)) {
8874                 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
8875                 return false;
8876         }
8877
8878         TALLOC_FREE(subreq);
8879         TALLOC_FREE(ev);
8880
8881         len_expected = calc_expected_return(cli, len_requested);
8882
8883         if (len_expected > 0x10000 && len_read == 0x10000) {
8884                 /* Windows servers only return a max of 0x10000,
8885                    doesn't matter if you set CAP_LARGE_READX in
8886                    the client sessionsetupX call or not. */
8887                 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
8888                         (unsigned int)len_requested);
8889         } else if (len_read != len_expected) {
8890                 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
8891                         (unsigned int)len_requested,
8892                         (unsigned int)len_read,
8893                         (unsigned int)len_expected);
8894                 return false;
8895         } else {
8896                 d_printf("Correct read reply.\n");
8897         }
8898
8899         return true;
8900 }
8901
8902 /* Test large readX variants. */
8903 static bool large_readx_tests(struct cli_state *cli,
8904                                 uint16_t fnum,
8905                                 uint8_t *buf)
8906 {
8907         /* A read of 0xFFFF0001 should *always* return 1 byte. */
8908         if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
8909                 return false;
8910         }
8911         /* A read of 0x10000 should return 0x10000 bytes. */
8912         if (check_read_call(cli, fnum, buf,    0x10000) == false) {
8913                 return false;
8914         }
8915         /* A read of 0x10000 should return 0x10001 bytes. */
8916         if (check_read_call(cli, fnum, buf,    0x10001) == false) {
8917                 return false;
8918         }
8919         /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
8920            the requested number of bytes. */
8921         if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
8922                 return false;
8923         }
8924         /* A read of 1MB should return 1MB bytes (on Samba). */
8925         if (check_read_call(cli, fnum, buf,   0x100000) == false) {
8926                 return false;
8927         }
8928
8929         if (check_read_call(cli, fnum, buf,    0x20001) == false) {
8930                 return false;
8931         }
8932         if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
8933                 return false;
8934         }
8935         if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
8936                 return false;
8937         }
8938         return true;
8939 }
8940
8941 static bool run_large_readx(int dummy)
8942 {
8943         uint8_t *buf = NULL;
8944         struct cli_state *cli1 = NULL;
8945         struct cli_state *cli2 = NULL;
8946         bool correct = false;
8947         const char *fname = "\\large_readx.dat";
8948         NTSTATUS status;
8949         uint16_t fnum1 = UINT16_MAX;
8950         uint32_t normal_caps = 0;
8951         size_t file_size = 20*1024*1024;
8952         TALLOC_CTX *frame = talloc_stackframe();
8953         size_t i;
8954         struct {
8955                 const char *name;
8956                 enum smb_signing_setting signing_setting;
8957                 enum protocol_types protocol;
8958         } runs[] = {
8959                 {
8960                         .name = "NT1",
8961                         .signing_setting = SMB_SIGNING_IF_REQUIRED,
8962                         .protocol = PROTOCOL_NT1,
8963                 },{
8964                         .name = "NT1 - SIGNING_REQUIRED",
8965                         .signing_setting = SMB_SIGNING_REQUIRED,
8966                         .protocol = PROTOCOL_NT1,
8967                 },
8968         };
8969
8970         printf("starting large_readx test\n");
8971
8972         if (!torture_open_connection(&cli1, 0)) {
8973                 goto out;
8974         }
8975
8976         normal_caps = smb1cli_conn_capabilities(cli1->conn);
8977
8978         if (!(normal_caps & CAP_LARGE_READX)) {
8979                 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
8980                         (unsigned int)normal_caps);
8981                 goto out;
8982         }
8983
8984         /* Create a file of size 4MB. */
8985         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
8986                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8987                         0, 0, &fnum1, NULL);
8988
8989         if (!NT_STATUS_IS_OK(status)) {
8990                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8991                 goto out;
8992         }
8993
8994         /* Write file_size bytes. */
8995         buf = talloc_zero_array(frame, uint8_t, file_size);
8996         if (buf == NULL) {
8997                 goto out;
8998         }
8999
9000         status = cli_writeall(cli1,
9001                               fnum1,
9002                               0,
9003                               buf,
9004                               0,
9005                               file_size,
9006                               NULL);
9007         if (!NT_STATUS_IS_OK(status)) {
9008                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
9009                 goto out;
9010         }
9011
9012         status = cli_close(cli1, fnum1);
9013         if (!NT_STATUS_IS_OK(status)) {
9014                 d_printf("cli_close failed: %s\n", nt_errstr(status));
9015                 goto out;
9016         }
9017
9018         fnum1 = UINT16_MAX;
9019
9020         for (i=0; i < ARRAY_SIZE(runs); i++) {
9021                 enum smb_signing_setting saved_signing_setting = signing_state;
9022                 uint16_t fnum2 = -1;
9023
9024                 if (do_encrypt &&
9025                     (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
9026                 {
9027                         d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
9028                         continue;
9029                 }
9030
9031                 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
9032
9033                 signing_state = runs[i].signing_setting;
9034                 cli2 = open_nbt_connection();
9035                 signing_state = saved_signing_setting;
9036                 if (cli2 == NULL) {
9037                         goto out;
9038                 }
9039
9040                 status = smbXcli_negprot(cli2->conn,
9041                                          cli2->timeout,
9042                                          runs[i].protocol,
9043                                          runs[i].protocol);
9044                 if (!NT_STATUS_IS_OK(status)) {
9045                         goto out;
9046                 }
9047
9048                 status = cli_session_setup_creds(cli2, torture_creds);
9049                 if (!NT_STATUS_IS_OK(status)) {
9050                         goto out;
9051                 }
9052
9053                 status = cli_tree_connect(cli2,
9054                                         share,
9055                                         "?????",
9056                                         password);
9057                 if (!NT_STATUS_IS_OK(status)) {
9058                         goto out;
9059                 }
9060
9061                 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
9062
9063                 normal_caps = smb1cli_conn_capabilities(cli2->conn);
9064
9065                 if (!(normal_caps & CAP_LARGE_READX)) {
9066                         d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
9067                                 (unsigned int)normal_caps);
9068                         goto out;
9069                 }
9070
9071                 if (do_encrypt) {
9072                         if (force_cli_encryption(cli2, share) == false) {
9073                                 goto out;
9074                         }
9075                 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
9076                         uint16_t major, minor;
9077                         uint32_t caplow, caphigh;
9078
9079                         status = cli_unix_extensions_version(cli2,
9080                                                              &major, &minor,
9081                                                              &caplow, &caphigh);
9082                         if (!NT_STATUS_IS_OK(status)) {
9083                                 goto out;
9084                         }
9085                 }
9086
9087                 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
9088                                 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
9089                                 0, 0, &fnum2, NULL);
9090                 if (!NT_STATUS_IS_OK(status)) {
9091                         d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
9092                         goto out;
9093                 }
9094
9095                 /* All reads must return less than file_size bytes. */
9096                 if (!large_readx_tests(cli2, fnum2, buf)) {
9097                         goto out;
9098                 }
9099
9100                 status = cli_close(cli2, fnum2);
9101                 if (!NT_STATUS_IS_OK(status)) {
9102                         d_printf("cli_close failed: %s\n", nt_errstr(status));
9103                         goto out;
9104                 }
9105                 fnum2 = -1;
9106
9107                 if (!torture_close_connection(cli2)) {
9108                         goto out;
9109                 }
9110                 cli2 = NULL;
9111         }
9112
9113         correct = true;
9114         printf("Success on large_readx test\n");
9115
9116   out:
9117
9118         if (cli2) {
9119                 if (!torture_close_connection(cli2)) {
9120                         correct = false;
9121                 }
9122         }
9123
9124         if (cli1) {
9125                 if (fnum1 != UINT16_MAX) {
9126                         status = cli_close(cli1, fnum1);
9127                         if (!NT_STATUS_IS_OK(status)) {
9128                                 d_printf("cli_close failed: %s\n", nt_errstr(status));
9129                         }
9130                         fnum1 = UINT16_MAX;
9131                 }
9132
9133                 status = cli_unlink(cli1, fname,
9134                                     FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9135                 if (!NT_STATUS_IS_OK(status)) {
9136                         printf("unlink failed (%s)\n", nt_errstr(status));
9137                 }
9138
9139                 if (!torture_close_connection(cli1)) {
9140                         correct = false;
9141                 }
9142         }
9143
9144         TALLOC_FREE(frame);
9145
9146         printf("finished large_readx test\n");
9147         return correct;
9148 }
9149
9150 static bool run_cli_echo(int dummy)
9151 {
9152         struct cli_state *cli;
9153         NTSTATUS status;
9154
9155         printf("starting cli_echo test\n");
9156         if (!torture_open_connection(&cli, 0)) {
9157                 return false;
9158         }
9159         smbXcli_conn_set_sockopt(cli->conn, sockops);
9160
9161         status = cli_echo(cli, 5, data_blob_const("hello", 5));
9162
9163         d_printf("cli_echo returned %s\n", nt_errstr(status));
9164
9165         torture_close_connection(cli);
9166         return NT_STATUS_IS_OK(status);
9167 }
9168
9169 static bool run_uid_regression_test(int dummy)
9170 {
9171         static struct cli_state *cli;
9172         int16_t old_vuid;
9173         int32_t old_cnum;
9174         bool correct = True;
9175         struct smbXcli_tcon *orig_tcon = NULL;
9176         NTSTATUS status;
9177
9178         printf("starting uid regression test\n");
9179
9180         if (!torture_open_connection(&cli, 0)) {
9181                 return False;
9182         }
9183
9184         smbXcli_conn_set_sockopt(cli->conn, sockops);
9185
9186         /* Ok - now save then logoff our current user. */
9187         old_vuid = cli_state_get_uid(cli);
9188
9189         status = cli_ulogoff(cli);
9190         if (!NT_STATUS_IS_OK(status)) {
9191                 d_printf("(%s) cli_ulogoff failed: %s\n",
9192                          __location__, nt_errstr(status));
9193                 correct = false;
9194                 goto out;
9195         }
9196
9197         cli_state_set_uid(cli, old_vuid);
9198
9199         /* Try an operation. */
9200         status = cli_mkdir(cli, "\\uid_reg_test");
9201         if (NT_STATUS_IS_OK(status)) {
9202                 d_printf("(%s) cli_mkdir succeeded\n",
9203                          __location__);
9204                 correct = false;
9205                 goto out;
9206         } else {
9207                 /* Should be bad uid. */
9208                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
9209                                  NT_STATUS_USER_SESSION_DELETED)) {
9210                         correct = false;
9211                         goto out;
9212                 }
9213         }
9214
9215         old_cnum = cli_state_get_tid(cli);
9216         orig_tcon = cli_state_save_tcon(cli);
9217         if (orig_tcon == NULL) {
9218                 correct = false;
9219                 goto out;
9220         }
9221
9222         /* Now try a SMBtdis with the invald vuid set to zero. */
9223         cli_state_set_uid(cli, 0);
9224
9225         /* This should succeed. */
9226         status = cli_tdis(cli);
9227
9228         if (NT_STATUS_IS_OK(status)) {
9229                 d_printf("First tdis with invalid vuid should succeed.\n");
9230         } else {
9231                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
9232                 correct = false;
9233                 cli_state_restore_tcon(cli, orig_tcon);
9234                 goto out;
9235         }
9236
9237         cli_state_restore_tcon(cli, orig_tcon);
9238         cli_state_set_uid(cli, old_vuid);
9239         cli_state_set_tid(cli, old_cnum);
9240
9241         /* This should fail. */
9242         status = cli_tdis(cli);
9243         if (NT_STATUS_IS_OK(status)) {
9244                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
9245                 correct = false;
9246                 goto out;
9247         } else {
9248                 /* Should be bad tid. */
9249                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
9250                                 NT_STATUS_NETWORK_NAME_DELETED)) {
9251                         correct = false;
9252                         goto out;
9253                 }
9254         }
9255
9256         cli_rmdir(cli, "\\uid_reg_test");
9257
9258   out:
9259
9260         cli_shutdown(cli);
9261         return correct;
9262 }
9263
9264
9265 static const char *illegal_chars = "*\\/?<>|\":";
9266 static char force_shortname_chars[] = " +,.[];=\177";
9267
9268 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
9269                              const char *mask, void *state)
9270 {
9271         struct cli_state *pcli = (struct cli_state *)state;
9272         fstring fname;
9273         NTSTATUS status = NT_STATUS_OK;
9274
9275         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
9276
9277         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9278                 return NT_STATUS_OK;
9279
9280         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
9281                 status = cli_rmdir(pcli, fname);
9282                 if (!NT_STATUS_IS_OK(status)) {
9283                         printf("del_fn: failed to rmdir %s\n,", fname );
9284                 }
9285         } else {
9286                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9287                 if (!NT_STATUS_IS_OK(status)) {
9288                         printf("del_fn: failed to unlink %s\n,", fname );
9289                 }
9290         }
9291         return status;
9292 }
9293
9294 struct sn_state {
9295         int matched;
9296         int i;
9297         bool val;
9298 };
9299
9300 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
9301                               const char *name, void *state)
9302 {
9303         struct sn_state *s = (struct sn_state  *)state;
9304         int i = s->i;
9305
9306 #if 0
9307         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
9308                 i, finfo->name, finfo->short_name);
9309 #endif
9310
9311         if (strchr(force_shortname_chars, i)) {
9312                 if (!finfo->short_name) {
9313                         /* Shortname not created when it should be. */
9314                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
9315                                 __location__, finfo->name, i);
9316                         s->val = true;
9317                 }
9318         } else if (finfo->short_name){
9319                 /* Shortname created when it should not be. */
9320                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
9321                         __location__, finfo->short_name, finfo->name);
9322                 s->val = true;
9323         }
9324         s->matched += 1;
9325         return NT_STATUS_OK;
9326 }
9327
9328 static bool run_shortname_test(int dummy)
9329 {
9330         static struct cli_state *cli;
9331         bool correct = True;
9332         int i;
9333         struct sn_state s;
9334         char fname[40];
9335         NTSTATUS status;
9336
9337         printf("starting shortname test\n");
9338
9339         if (!torture_open_connection(&cli, 0)) {
9340                 return False;
9341         }
9342
9343         smbXcli_conn_set_sockopt(cli->conn, sockops);
9344
9345         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
9346         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
9347         cli_rmdir(cli, "\\shortname");
9348
9349         status = cli_mkdir(cli, "\\shortname");
9350         if (!NT_STATUS_IS_OK(status)) {
9351                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
9352                         __location__, nt_errstr(status));
9353                 correct = false;
9354                 goto out;
9355         }
9356
9357         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
9358                 correct = false;
9359                 goto out;
9360         }
9361         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
9362                 correct = false;
9363                 goto out;
9364         }
9365
9366         s.val = false;
9367
9368         for (i = 32; i < 128; i++) {
9369                 uint16_t fnum = (uint16_t)-1;
9370
9371                 s.i = i;
9372
9373                 if (strchr(illegal_chars, i)) {
9374                         continue;
9375                 }
9376                 fname[15] = i;
9377
9378                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
9379                                    FILE_SHARE_READ|FILE_SHARE_WRITE,
9380                                    FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
9381                 if (!NT_STATUS_IS_OK(status)) {
9382                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
9383                                 __location__, fname, nt_errstr(status));
9384                         correct = false;
9385                         goto out;
9386                 }
9387                 cli_close(cli, fnum);
9388
9389                 s.matched = 0;
9390                 status = cli_list(cli, "\\shortname\\test*.*", 0,
9391                                   shortname_list_fn, &s);
9392                 if (s.matched != 1) {
9393                         d_printf("(%s) failed to list %s: %s\n",
9394                                 __location__, fname, nt_errstr(status));
9395                         correct = false;
9396                         goto out;
9397                 }
9398
9399                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9400                 if (!NT_STATUS_IS_OK(status)) {
9401                         d_printf("(%s) failed to delete %s: %s\n",
9402                                 __location__, fname, nt_errstr(status));
9403                         correct = false;
9404                         goto out;
9405                 }
9406
9407                 if (s.val) {
9408                         correct = false;
9409                         goto out;
9410                 }
9411         }
9412
9413   out:
9414
9415         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
9416         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
9417         cli_rmdir(cli, "\\shortname");
9418         torture_close_connection(cli);
9419         return correct;
9420 }
9421
9422 static void pagedsearch_cb(struct tevent_req *req)
9423 {
9424         TLDAPRC rc;
9425         struct tldap_message *msg;
9426         char *dn;
9427
9428         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
9429         if (!TLDAP_RC_IS_SUCCESS(rc)) {
9430                 d_printf("tldap_search_paged_recv failed: %s\n",
9431                          tldap_rc2string(rc));
9432                 return;
9433         }
9434         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
9435                 TALLOC_FREE(msg);
9436                 return;
9437         }
9438         if (!tldap_entry_dn(msg, &dn)) {
9439                 d_printf("tldap_entry_dn failed\n");
9440                 return;
9441         }
9442         d_printf("%s\n", dn);
9443         TALLOC_FREE(msg);
9444 }
9445
9446 static bool run_tldap(int dummy)
9447 {
9448         struct tldap_context *ld;
9449         int fd;
9450         TLDAPRC rc;
9451         NTSTATUS status;
9452         struct sockaddr_storage addr;
9453         struct tevent_context *ev;
9454         struct tevent_req *req;
9455         char *basedn;
9456         const char *filter;
9457
9458         if (!resolve_name(host, &addr, 0, false)) {
9459                 d_printf("could not find host %s\n", host);
9460                 return false;
9461         }
9462         status = open_socket_out(&addr, 389, 9999, &fd);
9463         if (!NT_STATUS_IS_OK(status)) {
9464                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
9465                 return false;
9466         }
9467
9468         ld = tldap_context_create(talloc_tos(), fd);
9469         if (ld == NULL) {
9470                 close(fd);
9471                 d_printf("tldap_context_create failed\n");
9472                 return false;
9473         }
9474
9475         rc = tldap_fetch_rootdse(ld);
9476         if (!TLDAP_RC_IS_SUCCESS(rc)) {
9477                 d_printf("tldap_fetch_rootdse failed: %s\n",
9478                          tldap_errstr(talloc_tos(), ld, rc));
9479                 return false;
9480         }
9481
9482         basedn = tldap_talloc_single_attribute(
9483                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
9484         if (basedn == NULL) {
9485                 d_printf("no defaultNamingContext\n");
9486                 return false;
9487         }
9488         d_printf("defaultNamingContext: %s\n", basedn);
9489
9490         ev = samba_tevent_context_init(talloc_tos());
9491         if (ev == NULL) {
9492                 d_printf("tevent_context_init failed\n");
9493                 return false;
9494         }
9495
9496         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
9497                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
9498                                       NULL, 0, 0,
9499                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
9500         if (req == NULL) {
9501                 d_printf("tldap_search_paged_send failed\n");
9502                 return false;
9503         }
9504         tevent_req_set_callback(req, pagedsearch_cb, NULL);
9505
9506         tevent_req_poll(req, ev);
9507
9508         TALLOC_FREE(req);
9509
9510         /* test search filters against rootDSE */
9511         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
9512                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
9513
9514         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
9515                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
9516                           talloc_tos(), NULL);
9517         if (!TLDAP_RC_IS_SUCCESS(rc)) {
9518                 d_printf("tldap_search with complex filter failed: %s\n",
9519                          tldap_errstr(talloc_tos(), ld, rc));
9520                 return false;
9521         }
9522
9523         TALLOC_FREE(ld);
9524         return true;
9525 }
9526
9527 /* Torture test to ensure no regression of :
9528 https://bugzilla.samba.org/show_bug.cgi?id=7084
9529 */
9530
9531 static bool run_dir_createtime(int dummy)
9532 {
9533         struct cli_state *cli;
9534         const char *dname = "\\testdir";
9535         const char *fname = "\\testdir\\testfile";
9536         NTSTATUS status;
9537         struct timespec create_time;
9538         struct timespec create_time1;
9539         uint16_t fnum;
9540         bool ret = false;
9541
9542         if (!torture_open_connection(&cli, 0)) {
9543                 return false;
9544         }
9545
9546         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9547         cli_rmdir(cli, dname);
9548
9549         status = cli_mkdir(cli, dname);
9550         if (!NT_STATUS_IS_OK(status)) {
9551                 printf("mkdir failed: %s\n", nt_errstr(status));
9552                 goto out;
9553         }
9554
9555         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
9556                                 NULL, NULL, NULL);
9557         if (!NT_STATUS_IS_OK(status)) {
9558                 printf("cli_qpathinfo2 returned %s\n",
9559                        nt_errstr(status));
9560                 goto out;
9561         }
9562
9563         /* Sleep 3 seconds, then create a file. */
9564         sleep(3);
9565
9566         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
9567                          DENY_NONE, &fnum);
9568         if (!NT_STATUS_IS_OK(status)) {
9569                 printf("cli_openx failed: %s\n", nt_errstr(status));
9570                 goto out;
9571         }
9572
9573         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
9574                                 NULL, NULL, NULL);
9575         if (!NT_STATUS_IS_OK(status)) {
9576                 printf("cli_qpathinfo2 (2) returned %s\n",
9577                        nt_errstr(status));
9578                 goto out;
9579         }
9580
9581         if (timespec_compare(&create_time1, &create_time)) {
9582                 printf("run_dir_createtime: create time was updated (error)\n");
9583         } else {
9584                 printf("run_dir_createtime: create time was not updated (correct)\n");
9585                 ret = true;
9586         }
9587
9588   out:
9589
9590         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9591         cli_rmdir(cli, dname);
9592         if (!torture_close_connection(cli)) {
9593                 ret = false;
9594         }
9595         return ret;
9596 }
9597
9598
9599 static bool run_streamerror(int dummy)
9600 {
9601         struct cli_state *cli;
9602         const char *dname = "\\testdir";
9603         const char *streamname =
9604                 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
9605         NTSTATUS status;
9606         time_t change_time, access_time, write_time;
9607         off_t size;
9608         uint16_t mode, fnum;
9609         bool ret = true;
9610
9611         if (!torture_open_connection(&cli, 0)) {
9612                 return false;
9613         }
9614
9615         cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9616         cli_rmdir(cli, dname);
9617
9618         status = cli_mkdir(cli, dname);
9619         if (!NT_STATUS_IS_OK(status)) {
9620                 printf("mkdir failed: %s\n", nt_errstr(status));
9621                 return false;
9622         }
9623
9624         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
9625                                 &write_time, &size, &mode);
9626         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
9627                 printf("pathinfo returned %s, expected "
9628                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
9629                        nt_errstr(status));
9630                 ret = false;
9631         }
9632
9633         status = cli_ntcreate(cli, streamname, 0x16,
9634                               FILE_READ_DATA|FILE_READ_EA|
9635                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
9636                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
9637                               FILE_OPEN, 0, 0, &fnum, NULL);
9638
9639         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
9640                 printf("ntcreate returned %s, expected "
9641                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
9642                        nt_errstr(status));
9643                 ret = false;
9644         }
9645
9646
9647         cli_rmdir(cli, dname);
9648         return ret;
9649 }
9650
9651 struct pidtest_state {
9652         bool success;
9653         uint16_t vwv[1];
9654         DATA_BLOB data;
9655 };
9656
9657 static void pid_echo_done(struct tevent_req *subreq);
9658
9659 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
9660                         struct tevent_context *ev,
9661                         struct cli_state *cli)
9662 {
9663         struct tevent_req *req, *subreq;
9664         struct pidtest_state *state;
9665
9666         req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
9667         if (req == NULL) {
9668                 return NULL;
9669         }
9670
9671         SSVAL(state->vwv, 0, 1);
9672         state->data = data_blob_const("hello", 5);
9673
9674         subreq = smb1cli_req_send(state,
9675                                 ev,
9676                                 cli->conn,
9677                                 SMBecho,
9678                                 0, 0, /* *_flags */
9679                                 0, 0, /* *_flags2 */
9680                                 cli->timeout,
9681                                 0xDEADBEEF, /* pid */
9682                                 NULL, /* tcon */
9683                                 NULL, /* session */
9684                                 ARRAY_SIZE(state->vwv), state->vwv,
9685                                 state->data.length, state->data.data);
9686
9687         if (tevent_req_nomem(subreq, req)) {
9688                 return tevent_req_post(req, ev);
9689         }
9690         tevent_req_set_callback(subreq, pid_echo_done, req);
9691         return req;
9692 }
9693
9694 static void pid_echo_done(struct tevent_req *subreq)
9695 {
9696         struct tevent_req *req = tevent_req_callback_data(
9697                 subreq, struct tevent_req);
9698         struct pidtest_state *state = tevent_req_data(
9699                 req, struct pidtest_state);
9700         NTSTATUS status;
9701         uint32_t num_bytes;
9702         uint8_t *bytes = NULL;
9703         struct iovec *recv_iov = NULL;
9704         uint8_t *phdr = NULL;
9705         uint16_t pidlow = 0;
9706         uint16_t pidhigh = 0;
9707         struct smb1cli_req_expected_response expected[] = {
9708         {
9709                 .status = NT_STATUS_OK,
9710                 .wct    = 1,
9711         },
9712         };
9713
9714         status = smb1cli_req_recv(subreq, state,
9715                                 &recv_iov,
9716                                 &phdr,
9717                                 NULL, /* pwct */
9718                                 NULL, /* pvwv */
9719                                 NULL, /* pvwv_offset */
9720                                 &num_bytes,
9721                                 &bytes,
9722                                 NULL, /* pbytes_offset */
9723                                 NULL, /* pinbuf */
9724                                 expected, ARRAY_SIZE(expected));
9725
9726         TALLOC_FREE(subreq);
9727
9728         if (!NT_STATUS_IS_OK(status)) {
9729                 tevent_req_nterror(req, status);
9730                 return;
9731         }
9732
9733         if (num_bytes != state->data.length) {
9734                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9735                 return;
9736         }
9737
9738         if (memcmp(bytes, state->data.data, num_bytes) != 0) {
9739                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9740                 return;
9741         }
9742
9743         /* Check pid low/high == DEADBEEF */
9744         pidlow = SVAL(phdr, HDR_PID);
9745         if (pidlow != 0xBEEF){
9746                 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
9747                         (unsigned int)pidlow);
9748                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9749                 return;
9750         }
9751         pidhigh = SVAL(phdr, HDR_PIDHIGH);
9752         if (pidhigh != 0xDEAD){
9753                 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
9754                         (unsigned int)pidhigh);
9755                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9756                 return;
9757         }
9758
9759         tevent_req_done(req);
9760 }
9761
9762 static NTSTATUS pid_echo_recv(struct tevent_req *req)
9763 {
9764         return tevent_req_simple_recv_ntstatus(req);
9765 }
9766
9767 static bool run_pidhigh(int dummy)
9768 {
9769         bool success = false;
9770         struct cli_state *cli = NULL;
9771         NTSTATUS status;
9772         struct tevent_context *ev = NULL;
9773         struct tevent_req *req = NULL;
9774         TALLOC_CTX *frame = talloc_stackframe();
9775
9776         printf("starting pid high test\n");
9777         if (!torture_open_connection(&cli, 0)) {
9778                 return false;
9779         }
9780         smbXcli_conn_set_sockopt(cli->conn, sockops);
9781
9782         ev = samba_tevent_context_init(frame);
9783         if (ev == NULL) {
9784                 goto fail;
9785         }
9786
9787         req = pid_echo_send(frame, ev, cli);
9788         if (req == NULL) {
9789                 goto fail;
9790         }
9791
9792         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
9793                 goto fail;
9794         }
9795
9796         status = pid_echo_recv(req);
9797         if (NT_STATUS_IS_OK(status)) {
9798                 printf("pid high test ok\n");
9799                 success = true;
9800         }
9801
9802  fail:
9803
9804         TALLOC_FREE(frame);
9805         torture_close_connection(cli);
9806         return success;
9807 }
9808
9809 /*
9810   Test Windows open on a bad POSIX symlink.
9811  */
9812 static bool run_symlink_open_test(int dummy)
9813 {
9814         static struct cli_state *cli;
9815         const char *fname = "non_existant_file";
9816         const char *sname = "dangling_symlink";
9817         uint16_t fnum = (uint16_t)-1;
9818         bool correct = false;
9819         NTSTATUS status;
9820         TALLOC_CTX *frame = NULL;
9821
9822         frame = talloc_stackframe();
9823
9824         printf("Starting Windows bad symlink open test\n");
9825
9826         if (!torture_open_connection(&cli, 0)) {
9827                 TALLOC_FREE(frame);
9828                 return false;
9829         }
9830
9831         smbXcli_conn_set_sockopt(cli->conn, sockops);
9832
9833         status = torture_setup_unix_extensions(cli);
9834         if (!NT_STATUS_IS_OK(status)) {
9835                 TALLOC_FREE(frame);
9836                 return false;
9837         }
9838
9839         /* Ensure nothing exists. */
9840         cli_setatr(cli, fname, 0, 0);
9841         cli_posix_unlink(cli, fname);
9842         cli_setatr(cli, sname, 0, 0);
9843         cli_posix_unlink(cli, sname);
9844
9845         /* Create a symlink pointing nowhere. */
9846         status = cli_posix_symlink(cli, fname, sname);
9847         if (!NT_STATUS_IS_OK(status)) {
9848                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
9849                         sname,
9850                         fname,
9851                         nt_errstr(status));
9852                 goto out;
9853         }
9854
9855         /* Now ensure that a Windows open doesn't hang. */
9856         status = cli_ntcreate(cli,
9857                         sname,
9858                         0,
9859                         FILE_READ_DATA|FILE_WRITE_DATA,
9860                         0,
9861                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9862                         FILE_OPEN_IF,
9863                         0x0,
9864                         0x0,
9865                         &fnum,
9866                         NULL);
9867
9868         /*
9869          * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
9870          * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
9871          * we use O_NOFOLLOW on the server or not.
9872          */
9873         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
9874             NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
9875         {
9876                 correct = true;
9877         } else {
9878                 printf("cli_ntcreate of %s returned %s - should return"
9879                                 " either (%s) or (%s)\n",
9880                         sname,
9881                         nt_errstr(status),
9882                         nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
9883                         nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
9884                 goto out;
9885         }
9886
9887         correct = true;
9888
9889   out:
9890
9891         if (fnum != (uint16_t)-1) {
9892                 cli_close(cli, fnum);
9893                 fnum = (uint16_t)-1;
9894         }
9895
9896         cli_setatr(cli, sname, 0, 0);
9897         cli_posix_unlink(cli, sname);
9898         cli_setatr(cli, fname, 0, 0);
9899         cli_posix_unlink(cli, fname);
9900
9901         if (!torture_close_connection(cli)) {
9902                 correct = false;
9903         }
9904
9905         TALLOC_FREE(frame);
9906         return correct;
9907 }
9908
9909 static bool run_local_substitute(int dummy)
9910 {
9911         bool ok = true;
9912
9913         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
9914         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
9915         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
9916         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
9917         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
9918         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
9919         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
9920         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
9921
9922         /* Different captialization rules in sub_basic... */
9923
9924         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
9925                        "blaDOM") == 0);
9926
9927         return ok;
9928 }
9929
9930 static bool run_local_base64(int dummy)
9931 {
9932         int i;
9933         bool ret = true;
9934
9935         for (i=1; i<2000; i++) {
9936                 DATA_BLOB blob1, blob2;
9937                 char *b64;
9938
9939                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
9940                 blob1.length = i;
9941                 generate_random_buffer(blob1.data, blob1.length);
9942
9943                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
9944                 if (b64 == NULL) {
9945                         d_fprintf(stderr, "base64_encode_data_blob failed "
9946                                   "for %d bytes\n", i);
9947                         ret = false;
9948                 }
9949                 blob2 = base64_decode_data_blob(b64);
9950                 TALLOC_FREE(b64);
9951
9952                 if (data_blob_cmp(&blob1, &blob2)) {
9953                         d_fprintf(stderr, "data_blob_cmp failed for %d "
9954                                   "bytes\n", i);
9955                         ret = false;
9956                 }
9957                 TALLOC_FREE(blob1.data);
9958                 data_blob_free(&blob2);
9959         }
9960         return ret;
9961 }
9962
9963 static void parse_fn(time_t timeout, DATA_BLOB blob, void *private_data)
9964 {
9965         return;
9966 }
9967
9968 static bool run_local_gencache(int dummy)
9969 {
9970         char *val;
9971         time_t tm;
9972         DATA_BLOB blob;
9973         char v;
9974         struct memcache *mem;
9975         int i;
9976
9977         mem = memcache_init(NULL, 0);
9978         if (mem == NULL) {
9979                 d_printf("%s: memcache_init failed\n", __location__);
9980                 return false;
9981         }
9982         memcache_set_global(mem);
9983
9984         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
9985                 d_printf("%s: gencache_set() failed\n", __location__);
9986                 return False;
9987         }
9988
9989         if (!gencache_get("foo", NULL, NULL, NULL)) {
9990                 d_printf("%s: gencache_get() failed\n", __location__);
9991                 return False;
9992         }
9993
9994         for (i=0; i<1000000; i++) {
9995                 gencache_parse("foo", parse_fn, NULL);
9996         }
9997
9998         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
9999                 d_printf("%s: gencache_get() failed\n", __location__);
10000                 return False;
10001         }
10002         TALLOC_FREE(val);
10003
10004         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
10005                 d_printf("%s: gencache_get() failed\n", __location__);
10006                 return False;
10007         }
10008
10009         if (strcmp(val, "bar") != 0) {
10010                 d_printf("%s: gencache_get() returned %s, expected %s\n",
10011                          __location__, val, "bar");
10012                 TALLOC_FREE(val);
10013                 return False;
10014         }
10015
10016         TALLOC_FREE(val);
10017
10018         if (!gencache_del("foo")) {
10019                 d_printf("%s: gencache_del() failed\n", __location__);
10020                 return False;
10021         }
10022         if (gencache_del("foo")) {
10023                 d_printf("%s: second gencache_del() succeeded\n",
10024                          __location__);
10025                 return False;
10026         }
10027
10028         if (gencache_get("foo", talloc_tos(), &val, &tm)) {
10029                 d_printf("%s: gencache_get() on deleted entry "
10030                          "succeeded\n", __location__);
10031                 return False;
10032         }
10033
10034         blob = data_blob_string_const_null("bar");
10035         tm = time(NULL) + 60;
10036
10037         if (!gencache_set_data_blob("foo", &blob, tm)) {
10038                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
10039                 return False;
10040         }
10041
10042         if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
10043                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
10044                 return False;
10045         }
10046
10047         if (strcmp((const char *)blob.data, "bar") != 0) {
10048                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
10049                          __location__, (const char *)blob.data, "bar");
10050                 data_blob_free(&blob);
10051                 return False;
10052         }
10053
10054         data_blob_free(&blob);
10055
10056         if (!gencache_del("foo")) {
10057                 d_printf("%s: gencache_del() failed\n", __location__);
10058                 return False;
10059         }
10060         if (gencache_del("foo")) {
10061                 d_printf("%s: second gencache_del() succeeded\n",
10062                          __location__);
10063                 return False;
10064         }
10065
10066         if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
10067                 d_printf("%s: gencache_get_data_blob() on deleted entry "
10068                          "succeeded\n", __location__);
10069                 return False;
10070         }
10071
10072         v = 1;
10073         blob.data = (uint8_t *)&v;
10074         blob.length = sizeof(v);
10075
10076         if (!gencache_set_data_blob("blob", &blob, tm)) {
10077                 d_printf("%s: gencache_set_data_blob() failed\n",
10078                          __location__);
10079                 return false;
10080         }
10081         if (gencache_get("blob", talloc_tos(), &val, &tm)) {
10082                 d_printf("%s: gencache_get succeeded\n", __location__);
10083                 return false;
10084         }
10085
10086         return True;
10087 }
10088
10089 static bool rbt_testval(struct db_context *db, const char *key,
10090                         const char *value)
10091 {
10092         struct db_record *rec;
10093         TDB_DATA data = string_tdb_data(value);
10094         bool ret = false;
10095         NTSTATUS status;
10096         TDB_DATA dbvalue;
10097
10098         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
10099         if (rec == NULL) {
10100                 d_fprintf(stderr, "fetch_locked failed\n");
10101                 goto done;
10102         }
10103         status = dbwrap_record_store(rec, data, 0);
10104         if (!NT_STATUS_IS_OK(status)) {
10105                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
10106                 goto done;
10107         }
10108         TALLOC_FREE(rec);
10109
10110         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
10111         if (rec == NULL) {
10112                 d_fprintf(stderr, "second fetch_locked failed\n");
10113                 goto done;
10114         }
10115
10116         dbvalue = dbwrap_record_get_value(rec);
10117         if ((dbvalue.dsize != data.dsize)
10118             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
10119                 d_fprintf(stderr, "Got wrong data back\n");
10120                 goto done;
10121         }
10122
10123         ret = true;
10124  done:
10125         TALLOC_FREE(rec);
10126         return ret;
10127 }
10128
10129 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
10130 {
10131         int *count2 = (int *)private_data;
10132         (*count2)++;
10133         return 0;
10134 }
10135
10136 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
10137 {
10138         int *count2 = (int *)private_data;
10139         (*count2)++;
10140         dbwrap_record_delete(rec);
10141         return 0;
10142 }
10143
10144 static bool run_local_rbtree(int dummy)
10145 {
10146         struct db_context *db;
10147         bool ret = false;
10148         int i;
10149         NTSTATUS status;
10150         int count = 0;
10151         int count2 = 0;
10152
10153         db = db_open_rbt(NULL);
10154
10155         if (db == NULL) {
10156                 d_fprintf(stderr, "db_open_rbt failed\n");
10157                 return false;
10158         }
10159
10160         for (i=0; i<1000; i++) {
10161                 char *key, *value;
10162
10163                 if (asprintf(&key, "key%ld", random()) == -1) {
10164                         goto done;
10165                 }
10166                 if (asprintf(&value, "value%ld", random()) == -1) {
10167                         SAFE_FREE(key);
10168                         goto done;
10169                 }
10170
10171                 if (!rbt_testval(db, key, value)) {
10172                         SAFE_FREE(key);
10173                         SAFE_FREE(value);
10174                         goto done;
10175                 }
10176
10177                 SAFE_FREE(value);
10178                 if (asprintf(&value, "value%ld", random()) == -1) {
10179                         SAFE_FREE(key);
10180                         goto done;
10181                 }
10182
10183                 if (!rbt_testval(db, key, value)) {
10184                         SAFE_FREE(key);
10185                         SAFE_FREE(value);
10186                         goto done;
10187                 }
10188
10189                 SAFE_FREE(key);
10190                 SAFE_FREE(value);
10191         }
10192
10193         ret = true;
10194         count = 0; count2 = 0;
10195         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
10196                                       &count2, &count);
10197         printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10198         if ((count != count2) || (count != 1000)) {
10199                 ret = false;
10200         }
10201         count = 0; count2 = 0;
10202         status = dbwrap_traverse(db, local_rbtree_traverse_delete,
10203                                  &count2, &count);
10204         printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10205         if ((count != count2) || (count != 1000)) {
10206                 ret = false;
10207         }
10208         count = 0; count2 = 0;
10209         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
10210                                       &count2, &count);
10211         printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10212         if ((count != count2) || (count != 0)) {
10213                 ret = false;
10214         }
10215
10216  done:
10217         TALLOC_FREE(db);
10218         return ret;
10219 }
10220
10221
10222 /*
10223   local test for character set functions
10224
10225   This is a very simple test for the functionality in convert_string_error()
10226  */
10227 static bool run_local_convert_string(int dummy)
10228 {
10229         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
10230         const char *test_strings[2] = { "March", "M\303\244rz" };
10231         char dst[7];
10232         int i;
10233
10234         for (i=0; i<2; i++) {
10235                 const char *str = test_strings[i];
10236                 int len = strlen(str);
10237                 size_t converted_size;
10238                 bool ret;
10239
10240                 memset(dst, 'X', sizeof(dst));
10241
10242                 /* first try with real source length */
10243                 ret = convert_string_error(CH_UNIX, CH_UTF8,
10244                                            str, len,
10245                                            dst, sizeof(dst),
10246                                            &converted_size);
10247                 if (ret != true) {
10248                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
10249                         goto failed;
10250                 }
10251
10252                 if (converted_size != len) {
10253                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
10254                                   str, len, (int)converted_size);
10255                         goto failed;
10256                 }
10257
10258                 if (strncmp(str, dst, converted_size) != 0) {
10259                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
10260                         goto failed;
10261                 }
10262
10263                 if (strlen(str) != converted_size) {
10264                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
10265                                   (int)strlen(str), (int)converted_size);
10266                         goto failed;
10267                 }
10268
10269                 if (dst[converted_size] != 'X') {
10270                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
10271                         goto failed;
10272                 }
10273
10274                 /* now with srclen==-1, this causes the nul to be
10275                  * converted too */
10276                 ret = convert_string_error(CH_UNIX, CH_UTF8,
10277                                            str, -1,
10278                                            dst, sizeof(dst),
10279                                            &converted_size);
10280                 if (ret != true) {
10281                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
10282                         goto failed;
10283                 }
10284
10285                 if (converted_size != len+1) {
10286                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
10287                                   str, len, (int)converted_size);
10288                         goto failed;
10289                 }
10290
10291                 if (strncmp(str, dst, converted_size) != 0) {
10292                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
10293                         goto failed;
10294                 }
10295
10296                 if (len+1 != converted_size) {
10297                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
10298                                   len+1, (int)converted_size);
10299                         goto failed;
10300                 }
10301
10302                 if (dst[converted_size] != 'X') {
10303                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
10304                         goto failed;
10305                 }
10306
10307         }
10308
10309
10310         TALLOC_FREE(tmp_ctx);
10311         return true;
10312 failed:
10313         TALLOC_FREE(tmp_ctx);
10314         return false;
10315 }
10316
10317
10318 struct talloc_dict_test {
10319         int content;
10320 };
10321
10322 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
10323 {
10324         int *count = (int *)priv;
10325         *count += 1;
10326         return 0;
10327 }
10328
10329 static bool run_local_talloc_dict(int dummy)
10330 {
10331         struct talloc_dict *dict;
10332         struct talloc_dict_test *t;
10333         int key, count, res;
10334         bool ok;
10335
10336         dict = talloc_dict_init(talloc_tos());
10337         if (dict == NULL) {
10338                 return false;
10339         }
10340
10341         t = talloc(talloc_tos(), struct talloc_dict_test);
10342         if (t == NULL) {
10343                 return false;
10344         }
10345
10346         key = 1;
10347         t->content = 1;
10348         ok = talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), &t);
10349         if (!ok) {
10350                 return false;
10351         }
10352
10353         count = 0;
10354         res = talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count);
10355         if (res == -1) {
10356                 return false;
10357         }
10358
10359         if (count != 1) {
10360                 return false;
10361         }
10362
10363         if (count != res) {
10364                 return false;
10365         }
10366
10367         TALLOC_FREE(dict);
10368
10369         return true;
10370 }
10371
10372 static bool run_local_string_to_sid(int dummy) {
10373         struct dom_sid sid;
10374
10375         if (string_to_sid(&sid, "S--1-5-32-545")) {
10376                 printf("allowing S--1-5-32-545\n");
10377                 return false;
10378         }
10379         if (string_to_sid(&sid, "S-1-5-32-+545")) {
10380                 printf("allowing S-1-5-32-+545\n");
10381                 return false;
10382         }
10383         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")) {
10384                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
10385                 return false;
10386         }
10387         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
10388                 printf("allowing S-1-5-32-545-abc\n");
10389                 return false;
10390         }
10391         if (string_to_sid(&sid, "S-300-5-32-545")) {
10392                 printf("allowing S-300-5-32-545\n");
10393                 return false;
10394         }
10395         if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
10396                 printf("allowing S-1-0xfffffffffffffe-32-545\n");
10397                 return false;
10398         }
10399         if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
10400                 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
10401                 return false;
10402         }
10403         if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
10404                 printf("could not parse S-1-0xfffffffffffe-32-545\n");
10405                 return false;
10406         }
10407         if (!string_to_sid(&sid, "S-1-5-32-545")) {
10408                 printf("could not parse S-1-5-32-545\n");
10409                 return false;
10410         }
10411         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
10412                 printf("mis-parsed S-1-5-32-545 as %s\n",
10413                        sid_string_tos(&sid));
10414                 return false;
10415         }
10416         return true;
10417 }
10418
10419 static bool sid_to_string_test(const char *expected) {
10420         char *str;
10421         bool res = true;
10422         struct dom_sid sid;
10423
10424         if (!string_to_sid(&sid, expected)) {
10425                 printf("could not parse %s\n", expected);
10426                 return false;
10427         }
10428
10429         str = dom_sid_string(NULL, &sid);
10430         if (strcmp(str, expected)) {
10431                 printf("Comparison failed (%s != %s)\n", str, expected);
10432                 res = false;
10433         }
10434         TALLOC_FREE(str);
10435         return res;
10436 }
10437
10438 static bool run_local_sid_to_string(int dummy) {
10439         if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
10440                 return false;
10441         if (!sid_to_string_test("S-1-545"))
10442                 return false;
10443         if (!sid_to_string_test("S-255-3840-1-1-1-1"))
10444                 return false;
10445         return true;
10446 }
10447
10448 static bool run_local_binary_to_sid(int dummy) {
10449         struct dom_sid *sid = talloc(NULL, struct dom_sid);
10450         static const uint8_t good_binary_sid[] = {
10451                 0x1, /* revision number */
10452                 15, /* num auths */
10453                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10454                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10455                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10456                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10457                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10458                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10459                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10460                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10461                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10462                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10463                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10464                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10465                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10466                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10467                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10468                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10469         };
10470
10471         static const uint8_t long_binary_sid[] = {
10472                 0x1, /* revision number */
10473                 15, /* num auths */
10474                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10475                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10476                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10477                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10478                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10479                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10480                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10481                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10482                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10483                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10484                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10485                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10486                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10487                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10488                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10489                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10490                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
10491                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
10492                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
10493         };
10494
10495         static const uint8_t long_binary_sid2[] = {
10496                 0x1, /* revision number */
10497                 32, /* num auths */
10498                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10499                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10500                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10501                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10502                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10503                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10504                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10505                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10506                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10507                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10508                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10509                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10510                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10511                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10512                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10513                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10514                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
10515                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
10516                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
10517                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
10518                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
10519                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
10520                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
10521                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
10522                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
10523                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
10524                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
10525                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
10526                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
10527                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
10528                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
10529                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
10530                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
10531         };
10532
10533         if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
10534                 return false;
10535         }
10536         if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
10537                 return false;
10538         }
10539         if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
10540                 return false;
10541         }
10542         return true;
10543 }
10544
10545 /* Split a path name into filename and stream name components. Canonicalise
10546  * such that an implicit $DATA token is always explicit.
10547  *
10548  * The "specification" of this function can be found in the
10549  * run_local_stream_name() function in torture.c, I've tried those
10550  * combinations against a W2k3 server.
10551  */
10552
10553 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
10554                                        char **pbase, char **pstream)
10555 {
10556         char *base = NULL;
10557         char *stream = NULL;
10558         char *sname; /* stream name */
10559         const char *stype; /* stream type */
10560
10561         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
10562
10563         sname = strchr_m(fname, ':');
10564
10565         if (sname == NULL) {
10566                 if (pbase != NULL) {
10567                         base = talloc_strdup(mem_ctx, fname);
10568                         NT_STATUS_HAVE_NO_MEMORY(base);
10569                 }
10570                 goto done;
10571         }
10572
10573         if (pbase != NULL) {
10574                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
10575                 NT_STATUS_HAVE_NO_MEMORY(base);
10576         }
10577
10578         sname += 1;
10579
10580         stype = strchr_m(sname, ':');
10581
10582         if (stype == NULL) {
10583                 sname = talloc_strdup(mem_ctx, sname);
10584                 stype = "$DATA";
10585         }
10586         else {
10587                 if (strcasecmp_m(stype, ":$DATA") != 0) {
10588                         /*
10589                          * If there is an explicit stream type, so far we only
10590                          * allow $DATA. Is there anything else allowed? -- vl
10591                          */
10592                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
10593                         TALLOC_FREE(base);
10594                         return NT_STATUS_OBJECT_NAME_INVALID;
10595                 }
10596                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
10597                 stype += 1;
10598         }
10599
10600         if (sname == NULL) {
10601                 TALLOC_FREE(base);
10602                 return NT_STATUS_NO_MEMORY;
10603         }
10604
10605         if (sname[0] == '\0') {
10606                 /*
10607                  * no stream name, so no stream
10608                  */
10609                 goto done;
10610         }
10611
10612         if (pstream != NULL) {
10613                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
10614                 if (stream == NULL) {
10615                         TALLOC_FREE(sname);
10616                         TALLOC_FREE(base);
10617                         return NT_STATUS_NO_MEMORY;
10618                 }
10619                 /*
10620                  * upper-case the type field
10621                  */
10622                 (void)strupper_m(strchr_m(stream, ':')+1);
10623         }
10624
10625  done:
10626         if (pbase != NULL) {
10627                 *pbase = base;
10628         }
10629         if (pstream != NULL) {
10630                 *pstream = stream;
10631         }
10632         return NT_STATUS_OK;
10633 }
10634
10635 static bool test_stream_name(const char *fname, const char *expected_base,
10636                              const char *expected_stream,
10637                              NTSTATUS expected_status)
10638 {
10639         NTSTATUS status;
10640         char *base = NULL;
10641         char *stream = NULL;
10642
10643         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
10644         if (!NT_STATUS_EQUAL(status, expected_status)) {
10645                 goto error;
10646         }
10647
10648         if (!NT_STATUS_IS_OK(status)) {
10649                 return true;
10650         }
10651
10652         if (base == NULL) goto error;
10653
10654         if (strcmp(expected_base, base) != 0) goto error;
10655
10656         if ((expected_stream != NULL) && (stream == NULL)) goto error;
10657         if ((expected_stream == NULL) && (stream != NULL)) goto error;
10658
10659         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
10660                 goto error;
10661
10662         TALLOC_FREE(base);
10663         TALLOC_FREE(stream);
10664         return true;
10665
10666  error:
10667         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
10668                   fname, expected_base ? expected_base : "<NULL>",
10669                   expected_stream ? expected_stream : "<NULL>",
10670                   nt_errstr(expected_status));
10671         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
10672                   base ? base : "<NULL>", stream ? stream : "<NULL>",
10673                   nt_errstr(status));
10674         TALLOC_FREE(base);
10675         TALLOC_FREE(stream);
10676         return false;
10677 }
10678
10679 static bool run_local_stream_name(int dummy)
10680 {
10681         bool ret = true;
10682
10683         ret &= test_stream_name(
10684                 "bla", "bla", NULL, NT_STATUS_OK);
10685         ret &= test_stream_name(
10686                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
10687         ret &= test_stream_name(
10688                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
10689         ret &= test_stream_name(
10690                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
10691         ret &= test_stream_name(
10692                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
10693         ret &= test_stream_name(
10694                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
10695         ret &= test_stream_name(
10696                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
10697         ret &= test_stream_name(
10698                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
10699
10700         return ret;
10701 }
10702
10703 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
10704 {
10705         if (a.length != b.length) {
10706                 printf("a.length=%d != b.length=%d\n",
10707                        (int)a.length, (int)b.length);
10708                 return false;
10709         }
10710         if (memcmp(a.data, b.data, a.length) != 0) {
10711                 printf("a.data and b.data differ\n");
10712                 return false;
10713         }
10714         return true;
10715 }
10716
10717 static bool run_local_memcache(int dummy)
10718 {
10719         struct memcache *cache;
10720         DATA_BLOB k1, k2, k3;
10721         DATA_BLOB d1, d3;
10722         DATA_BLOB v1, v3;
10723
10724         TALLOC_CTX *mem_ctx;
10725         char *ptr1 = NULL;
10726         char *ptr2 = NULL;
10727
10728         char *str1, *str2;
10729         size_t size1, size2;
10730         bool ret = false;
10731
10732         mem_ctx = talloc_init("foo");
10733         if (mem_ctx == NULL) {
10734                 return false;
10735         }
10736
10737         /* STAT_CACHE TESTS */
10738
10739         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
10740
10741         if (cache == NULL) {
10742                 printf("memcache_init failed\n");
10743                 return false;
10744         }
10745
10746         d1 = data_blob_const("d1", 2);
10747         d3 = data_blob_const("d3", 2);
10748
10749         k1 = data_blob_const("d1", 2);
10750         k2 = data_blob_const("d2", 2);
10751         k3 = data_blob_const("d3", 2);
10752
10753         memcache_add(cache, STAT_CACHE, k1, d1);
10754
10755         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
10756                 printf("could not find k1\n");
10757                 return false;
10758         }
10759         if (!data_blob_equal(d1, v1)) {
10760                 return false;
10761         }
10762
10763         memcache_add(cache, STAT_CACHE, k1, d3);
10764
10765         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
10766                 printf("could not find replaced k1\n");
10767                 return false;
10768         }
10769         if (!data_blob_equal(d3, v3)) {
10770                 return false;
10771         }
10772
10773         TALLOC_FREE(cache);
10774
10775         /* GETWD_CACHE TESTS */
10776         str1 = talloc_strdup(mem_ctx, "string1");
10777         if (str1 == NULL) {
10778                 return false;
10779         }
10780         ptr2 = str1; /* Keep an alias for comparison. */
10781
10782         str2 = talloc_strdup(mem_ctx, "string2");
10783         if (str2 == NULL) {
10784                 return false;
10785         }
10786
10787         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
10788         if (cache == NULL) {
10789                 printf("memcache_init failed\n");
10790                 return false;
10791         }
10792
10793         memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
10794         /* str1 == NULL now. */
10795         ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
10796         if (ptr1 == NULL) {
10797                 printf("could not find k2\n");
10798                 return false;
10799         }
10800         if (ptr1 != ptr2) {
10801                 printf("fetch of k2 got wrong string\n");
10802                 return false;
10803         }
10804
10805         /* Add a blob to ensure k2 gets purged. */
10806         d3 = data_blob_talloc_zero(mem_ctx, 180);
10807         memcache_add(cache, STAT_CACHE, k3, d3);
10808
10809         ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
10810         if (ptr2 != NULL) {
10811                 printf("Did find k2, should have been purged\n");
10812                 return false;
10813         }
10814
10815         TALLOC_FREE(cache);
10816         TALLOC_FREE(mem_ctx);
10817
10818         mem_ctx = talloc_init("foo");
10819         if (mem_ctx == NULL) {
10820                 return false;
10821         }
10822
10823         cache = memcache_init(NULL, 0);
10824         if (cache == NULL) {
10825                 return false;
10826         }
10827
10828         str1 = talloc_strdup(mem_ctx, "string1");
10829         if (str1 == NULL) {
10830                 return false;
10831         }
10832         str2 = talloc_strdup(mem_ctx, "string2");
10833         if (str2 == NULL) {
10834                 return false;
10835         }
10836         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
10837                             data_blob_string_const("torture"), &str1);
10838         size1 = talloc_total_size(cache);
10839
10840         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
10841                             data_blob_string_const("torture"), &str2);
10842         size2 = talloc_total_size(cache);
10843
10844         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
10845
10846         if (size2 > size1) {
10847                 printf("memcache leaks memory!\n");
10848                 goto fail;
10849         }
10850
10851         ret = true;
10852  fail:
10853         TALLOC_FREE(cache);
10854         return ret;
10855 }
10856
10857 static void wbclient_done(struct tevent_req *req)
10858 {
10859         wbcErr wbc_err;
10860         struct winbindd_response *wb_resp;
10861         int *i = (int *)tevent_req_callback_data_void(req);
10862
10863         wbc_err = wb_trans_recv(req, req, &wb_resp);
10864         TALLOC_FREE(req);
10865         *i += 1;
10866         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
10867 }
10868
10869 static bool run_wbclient_multi_ping(int dummy)
10870 {
10871         struct tevent_context *ev;
10872         struct wb_context **wb_ctx;
10873         struct winbindd_request wb_req;
10874         bool result = false;
10875         int i, j;
10876
10877         BlockSignals(True, SIGPIPE);
10878
10879         ev = tevent_context_init(talloc_tos());
10880         if (ev == NULL) {
10881                 goto fail;
10882         }
10883
10884         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
10885         if (wb_ctx == NULL) {
10886                 goto fail;
10887         }
10888
10889         ZERO_STRUCT(wb_req);
10890         wb_req.cmd = WINBINDD_PING;
10891
10892         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
10893
10894         for (i=0; i<torture_nprocs; i++) {
10895                 wb_ctx[i] = wb_context_init(ev, NULL);
10896                 if (wb_ctx[i] == NULL) {
10897                         goto fail;
10898                 }
10899                 for (j=0; j<torture_numops; j++) {
10900                         struct tevent_req *req;
10901                         req = wb_trans_send(ev, ev, wb_ctx[i],
10902                                             (j % 2) == 0, &wb_req);
10903                         if (req == NULL) {
10904                                 goto fail;
10905                         }
10906                         tevent_req_set_callback(req, wbclient_done, &i);
10907                 }
10908         }
10909
10910         i = 0;
10911
10912         while (i < torture_nprocs * torture_numops) {
10913                 tevent_loop_once(ev);
10914         }
10915
10916         result = true;
10917  fail:
10918         TALLOC_FREE(ev);
10919         return result;
10920 }
10921
10922 static void getaddrinfo_finished(struct tevent_req *req)
10923 {
10924         char *name = (char *)tevent_req_callback_data_void(req);
10925         struct addrinfo *ainfo;
10926         int res;
10927
10928         res = getaddrinfo_recv(req, &ainfo);
10929         if (res != 0) {
10930                 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
10931                 return;
10932         }
10933         d_printf("gai(%s) succeeded\n", name);
10934         freeaddrinfo(ainfo);
10935 }
10936
10937 static bool run_getaddrinfo_send(int dummy)
10938 {
10939         TALLOC_CTX *frame = talloc_stackframe();
10940         struct fncall_context *ctx;
10941         struct tevent_context *ev;
10942         bool result = false;
10943         const char *names[4] = { "www.samba.org", "notfound.samba.org",
10944                                  "www.slashdot.org", "heise.de" };
10945         struct tevent_req *reqs[4];
10946         int i;
10947
10948         ev = samba_tevent_context_init(frame);
10949         if (ev == NULL) {
10950                 goto fail;
10951         }
10952
10953         ctx = fncall_context_init(frame, 4);
10954
10955         for (i=0; i<ARRAY_SIZE(names); i++) {
10956                 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
10957                                            NULL);
10958                 if (reqs[i] == NULL) {
10959                         goto fail;
10960                 }
10961                 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
10962                                         discard_const_p(void, names[i]));
10963         }
10964
10965         for (i=0; i<ARRAY_SIZE(reqs); i++) {
10966                 tevent_loop_once(ev);
10967         }
10968
10969         result = true;
10970 fail:
10971         TALLOC_FREE(frame);
10972         return result;
10973 }
10974
10975 static bool dbtrans_inc(struct db_context *db)
10976 {
10977         struct db_record *rec;
10978         uint32_t val;
10979         bool ret = false;
10980         NTSTATUS status;
10981         TDB_DATA value;
10982
10983         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
10984         if (rec == NULL) {
10985                 printf(__location__ "fetch_lock failed\n");
10986                 return false;
10987         }
10988
10989         value = dbwrap_record_get_value(rec);
10990
10991         if (value.dsize != sizeof(uint32_t)) {
10992                 printf(__location__ "value.dsize = %d\n",
10993                        (int)value.dsize);
10994                 goto fail;
10995         }
10996
10997         memcpy(&val, value.dptr, sizeof(val));
10998         val += 1;
10999
11000         status = dbwrap_record_store(
11001                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
11002         if (!NT_STATUS_IS_OK(status)) {
11003                 printf(__location__ "store failed: %s\n",
11004                        nt_errstr(status));
11005                 goto fail;
11006         }
11007
11008         ret = true;
11009 fail:
11010         TALLOC_FREE(rec);
11011         return ret;
11012 }
11013
11014 static bool run_local_dbtrans(int dummy)
11015 {
11016         struct db_context *db;
11017         struct db_record *rec;
11018         NTSTATUS status;
11019         uint32_t initial;
11020         int res;
11021         TDB_DATA value;
11022
11023         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
11024                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
11025                      DBWRAP_FLAG_NONE);
11026         if (db == NULL) {
11027                 printf("Could not open transtest.db\n");
11028                 return false;
11029         }
11030
11031         res = dbwrap_transaction_start(db);
11032         if (res != 0) {
11033                 printf(__location__ "transaction_start failed\n");
11034                 return false;
11035         }
11036
11037         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
11038         if (rec == NULL) {
11039                 printf(__location__ "fetch_lock failed\n");
11040                 return false;
11041         }
11042
11043         value = dbwrap_record_get_value(rec);
11044
11045         if (value.dptr == NULL) {
11046                 initial = 0;
11047                 status = dbwrap_record_store(
11048                         rec, make_tdb_data((uint8_t *)&initial,
11049                                            sizeof(initial)),
11050                         0);
11051                 if (!NT_STATUS_IS_OK(status)) {
11052                         printf(__location__ "store returned %s\n",
11053                                nt_errstr(status));
11054                         return false;
11055                 }
11056         }
11057
11058         TALLOC_FREE(rec);
11059
11060         res = dbwrap_transaction_commit(db);
11061         if (res != 0) {
11062                 printf(__location__ "transaction_commit failed\n");
11063                 return false;
11064         }
11065
11066         while (true) {
11067                 uint32_t val, val2;
11068                 int i;
11069
11070                 res = dbwrap_transaction_start(db);
11071                 if (res != 0) {
11072                         printf(__location__ "transaction_start failed\n");
11073                         break;
11074                 }
11075
11076                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
11077                 if (!NT_STATUS_IS_OK(status)) {
11078                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
11079                                nt_errstr(status));
11080                         break;
11081                 }
11082
11083                 for (i=0; i<10; i++) {
11084                         if (!dbtrans_inc(db)) {
11085                                 return false;
11086                         }
11087                 }
11088
11089                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
11090                 if (!NT_STATUS_IS_OK(status)) {
11091                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
11092                                nt_errstr(status));
11093                         break;
11094                 }
11095
11096                 if (val2 != val + 10) {
11097                         printf(__location__ "val=%d, val2=%d\n",
11098                                (int)val, (int)val2);
11099                         break;
11100                 }
11101
11102                 printf("val2=%d\r", val2);
11103
11104                 res = dbwrap_transaction_commit(db);
11105                 if (res != 0) {
11106                         printf(__location__ "transaction_commit failed\n");
11107                         break;
11108                 }
11109         }
11110
11111         TALLOC_FREE(db);
11112         return true;
11113 }
11114
11115 /*
11116  * Just a dummy test to be run under a debugger. There's no real way
11117  * to inspect the tevent_select specific function from outside of
11118  * tevent_select.c.
11119  */
11120
11121 static bool run_local_tevent_select(int dummy)
11122 {
11123         struct tevent_context *ev;
11124         struct tevent_fd *fd1, *fd2;
11125         bool result = false;
11126
11127         ev = tevent_context_init_byname(NULL, "select");
11128         if (ev == NULL) {
11129                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
11130                 goto fail;
11131         }
11132
11133         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
11134         if (fd1 == NULL) {
11135                 d_fprintf(stderr, "tevent_add_fd failed\n");
11136                 goto fail;
11137         }
11138         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
11139         if (fd2 == NULL) {
11140                 d_fprintf(stderr, "tevent_add_fd failed\n");
11141                 goto fail;
11142         }
11143         TALLOC_FREE(fd2);
11144
11145         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
11146         if (fd2 == NULL) {
11147                 d_fprintf(stderr, "tevent_add_fd failed\n");
11148                 goto fail;
11149         }
11150
11151         result = true;
11152 fail:
11153         TALLOC_FREE(ev);
11154         return result;
11155 }
11156
11157 static bool run_local_hex_encode_buf(int dummy)
11158 {
11159         char buf[17];
11160         uint8_t src[8];
11161         int i;
11162
11163         for (i=0; i<sizeof(src); i++) {
11164                 src[i] = i;
11165         }
11166         hex_encode_buf(buf, src, sizeof(src));
11167         if (strcmp(buf, "0001020304050607") != 0) {
11168                 return false;
11169         }
11170         hex_encode_buf(buf, NULL, 0);
11171         if (buf[0] != '\0') {
11172                 return false;
11173         }
11174         return true;
11175 }
11176
11177 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
11178         "0.0.0.0",
11179         "::0",
11180         "1.2.3.1",
11181         "0.0.0.0",
11182         "0.0.0.0",
11183         "1.2.3.2",
11184         "1.2.3.3",
11185         "1.2.3.4",
11186         "1.2.3.5",
11187         "::0",
11188         "1.2.3.6",
11189         "1.2.3.7",
11190         "::0",
11191         "::0",
11192         "::0",
11193         "1.2.3.8",
11194         "1.2.3.9",
11195         "1.2.3.10",
11196         "1.2.3.11",
11197         "1.2.3.12",
11198         "1.2.3.13",
11199         "1001:1111:1111:1000:0:1111:1111:1111",
11200         "1.2.3.1",
11201         "1.2.3.2",
11202         "1.2.3.3",
11203         "1.2.3.12",
11204         "::0",
11205         "::0"
11206 };
11207
11208 static const char *remove_duplicate_addrs2_test_strings_result[] = {
11209         "1.2.3.1",
11210         "1.2.3.2",
11211         "1.2.3.3",
11212         "1.2.3.4",
11213         "1.2.3.5",
11214         "1.2.3.6",
11215         "1.2.3.7",
11216         "1.2.3.8",
11217         "1.2.3.9",
11218         "1.2.3.10",
11219         "1.2.3.11",
11220         "1.2.3.12",
11221         "1.2.3.13",
11222         "1001:1111:1111:1000:0:1111:1111:1111"
11223 };
11224
11225 static bool run_local_remove_duplicate_addrs2(int dummy)
11226 {
11227         struct ip_service test_vector[28];
11228         int count, i;
11229
11230         /* Construct the sockaddr_storage test vector. */
11231         for (i = 0; i < 28; i++) {
11232                 struct addrinfo hints;
11233                 struct addrinfo *res = NULL;
11234                 int ret;
11235
11236                 memset(&hints, '\0', sizeof(hints));
11237                 hints.ai_flags = AI_NUMERICHOST;
11238                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
11239                                 NULL,
11240                                 &hints,
11241                                 &res);
11242                 if (ret) {
11243                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
11244                                 remove_duplicate_addrs2_test_strings_vector[i]);
11245                         return false;
11246                 }
11247                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
11248                 memcpy(&test_vector[i].ss,
11249                         res->ai_addr,
11250                         res->ai_addrlen);
11251                 freeaddrinfo(res);
11252         }
11253
11254         count = remove_duplicate_addrs2(test_vector, i);
11255
11256         if (count != 14) {
11257                 fprintf(stderr, "count wrong (%d) should be 14\n",
11258                         count);
11259                 return false;
11260         }
11261
11262         for (i = 0; i < count; i++) {
11263                 char addr[INET6_ADDRSTRLEN];
11264
11265                 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
11266
11267                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
11268                         fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
11269                                 i,
11270                                 addr,
11271                                 remove_duplicate_addrs2_test_strings_result[i]);
11272                         return false;
11273                 }
11274         }
11275
11276         printf("run_local_remove_duplicate_addrs2: success\n");
11277         return true;
11278 }
11279
11280 static bool run_local_tdb_opener(int dummy)
11281 {
11282         TDB_CONTEXT *t;
11283         unsigned v = 0;
11284
11285         while (1) {
11286                 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
11287                              O_RDWR|O_CREAT, 0755);
11288                 if (t == NULL) {
11289                         perror("tdb_open failed");
11290                         return false;
11291                 }
11292                 tdb_close(t);
11293
11294                 v += 1;
11295                 printf("\r%u", v);
11296         }
11297         return true;
11298 }
11299
11300 static bool run_local_tdb_writer(int dummy)
11301 {
11302         TDB_CONTEXT *t;
11303         unsigned v = 0;
11304         TDB_DATA val;
11305
11306         t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
11307         if (t == 0) {
11308                 perror("tdb_open failed");
11309                 return 1;
11310         }
11311
11312         val.dptr = (uint8_t *)&v;
11313         val.dsize = sizeof(v);
11314
11315         while (1) {
11316                 TDB_DATA data;
11317                 int ret;
11318
11319                 ret = tdb_store(t, val, val, 0);
11320                 if (ret != 0) {
11321                         printf("%s\n", tdb_errorstr(t));
11322                 }
11323                 v += 1;
11324                 printf("\r%u", v);
11325
11326                 data = tdb_fetch(t, val);
11327                 if (data.dptr != NULL) {
11328                         SAFE_FREE(data.dptr);
11329                 }
11330         }
11331         return true;
11332 }
11333
11334 static bool run_local_canonicalize_path(int dummy)
11335 {
11336         const char *src[] = {
11337                         "/foo/..",
11338                         "/..",
11339                         "/foo/bar/../baz",
11340                         "/foo/././",
11341                         "/../foo",
11342                         ".././././",
11343                         ".././././../../../boo",
11344                         "./..",
11345                         NULL
11346                         };
11347         const char *dst[] = {
11348                         "/",
11349                         "/",
11350                         "/foo/baz",
11351                         "/foo",
11352                         "/foo",
11353                         "/",
11354                         "/boo",
11355                         "/",
11356                         NULL
11357                         };
11358         unsigned int i;
11359
11360         for (i = 0; src[i] != NULL; i++) {
11361                 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
11362                 if (d == NULL) {
11363                         perror("talloc fail\n");
11364                         return false;
11365                 }
11366                 if (strcmp(d, dst[i]) != 0) {
11367                         d_fprintf(stderr,
11368                                 "canonicalize missmatch %s -> %s != %s",
11369                                 src[i], d, dst[i]);
11370                         return false;
11371                 }
11372                 talloc_free(d);
11373         }
11374         return true;
11375 }
11376
11377 static bool run_ign_bad_negprot(int dummy)
11378 {
11379         struct tevent_context *ev;
11380         struct tevent_req *req;
11381         struct smbXcli_conn *conn;
11382         struct sockaddr_storage ss;
11383         NTSTATUS status;
11384         int fd;
11385         bool ok;
11386
11387         printf("starting ignore bad negprot\n");
11388
11389         ok = resolve_name(host, &ss, 0x20, true);
11390         if (!ok) {
11391                 d_fprintf(stderr, "Could not resolve name %s\n", host);
11392                 return false;
11393         }
11394
11395         status = open_socket_out(&ss, 445, 10000, &fd);
11396         if (!NT_STATUS_IS_OK(status)) {
11397                 d_fprintf(stderr, "open_socket_out failed: %s\n",
11398                           nt_errstr(status));
11399                 return false;
11400         }
11401
11402         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
11403                                    NULL, 0);
11404         if (conn == NULL) {
11405                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
11406                 return false;
11407         }
11408
11409         status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
11410         if (NT_STATUS_IS_OK(status)) {
11411                 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
11412                 return false;
11413         }
11414
11415         ev = samba_tevent_context_init(talloc_tos());
11416         if (ev == NULL) {
11417                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
11418                 return false;
11419         }
11420
11421         req = smb1cli_session_setup_nt1_send(
11422                 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
11423                 data_blob_null, data_blob_null, 0x40,
11424                 "Windows 2000 2195", "Windows 2000 5.0");
11425         if (req == NULL) {
11426                 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
11427                 return false;
11428         }
11429
11430         ok = tevent_req_poll_ntstatus(req, ev, &status);
11431         if (!ok) {
11432                 d_fprintf(stderr, "tevent_req_poll failed\n");
11433                 return false;
11434         }
11435
11436         status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
11437                                                 NULL, NULL);
11438         if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
11439                 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
11440                           "%s, expected NT_STATUS_CONNECTION_RESET\n",
11441                           nt_errstr(status));
11442                 return false;
11443         }
11444
11445         TALLOC_FREE(conn);
11446
11447         printf("starting ignore bad negprot\n");
11448
11449         return true;
11450 }
11451
11452 static double create_procs(bool (*fn)(int), bool *result)
11453 {
11454         int i, status;
11455         volatile pid_t *child_status;
11456         volatile bool *child_status_out;
11457         int synccount;
11458         int tries = 8;
11459         struct timeval start;
11460
11461         synccount = 0;
11462
11463         child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
11464         if (!child_status) {
11465                 printf("Failed to setup shared memory\n");
11466                 return -1;
11467         }
11468
11469         child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
11470         if (!child_status_out) {
11471                 printf("Failed to setup result status shared memory\n");
11472                 return -1;
11473         }
11474
11475         for (i = 0; i < torture_nprocs; i++) {
11476                 child_status[i] = 0;
11477                 child_status_out[i] = True;
11478         }
11479
11480         start = timeval_current();
11481
11482         for (i=0;i<torture_nprocs;i++) {
11483                 procnum = i;
11484                 if (fork() == 0) {
11485                         pid_t mypid = getpid();
11486                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
11487
11488                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
11489
11490                         while (1) {
11491                                 if (torture_open_connection(&current_cli, i)) break;
11492                                 if (tries-- == 0) {
11493                                         printf("pid %d failed to start\n", (int)getpid());
11494                                         _exit(1);
11495                                 }
11496                                 smb_msleep(10); 
11497                         }
11498
11499                         child_status[i] = getpid();
11500
11501                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
11502
11503                         child_status_out[i] = fn(i);
11504                         _exit(0);
11505                 }
11506         }
11507
11508         do {
11509                 synccount = 0;
11510                 for (i=0;i<torture_nprocs;i++) {
11511                         if (child_status[i]) synccount++;
11512                 }
11513                 if (synccount == torture_nprocs) break;
11514                 smb_msleep(10);
11515         } while (timeval_elapsed(&start) < 30);
11516
11517         if (synccount != torture_nprocs) {
11518                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
11519                 *result = False;
11520                 return timeval_elapsed(&start);
11521         }
11522
11523         /* start the client load */
11524         start = timeval_current();
11525
11526         for (i=0;i<torture_nprocs;i++) {
11527                 child_status[i] = 0;
11528         }
11529
11530         printf("%d clients started\n", torture_nprocs);
11531
11532         for (i=0;i<torture_nprocs;i++) {
11533                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
11534         }
11535
11536         printf("\n");
11537
11538         for (i=0;i<torture_nprocs;i++) {
11539                 if (!child_status_out[i]) {
11540                         *result = False;
11541                 }
11542         }
11543         return timeval_elapsed(&start);
11544 }
11545
11546 #define FLAG_MULTIPROC 1
11547
11548 static struct {
11549         const char *name;
11550         bool (*fn)(int);
11551         unsigned flags;
11552 } torture_ops[] = {
11553         {"FDPASS", run_fdpasstest, 0},
11554         {"LOCK1",  run_locktest1,  0},
11555         {"LOCK2",  run_locktest2,  0},
11556         {"LOCK3",  run_locktest3,  0},
11557         {"LOCK4",  run_locktest4,  0},
11558         {"LOCK5",  run_locktest5,  0},
11559         {"LOCK6",  run_locktest6,  0},
11560         {"LOCK7",  run_locktest7,  0},
11561         {"LOCK8",  run_locktest8,  0},
11562         {"LOCK9",  run_locktest9,  0},
11563         {"UNLINK", run_unlinktest, 0},
11564         {"BROWSE", run_browsetest, 0},
11565         {"ATTR",   run_attrtest,   0},
11566         {"TRANS2", run_trans2test, 0},
11567         {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
11568         {"TORTURE",run_torture,    FLAG_MULTIPROC},
11569         {"RANDOMIPC", run_randomipc, 0},
11570         {"NEGNOWAIT", run_negprot_nowait, 0},
11571         {"NBENCH",  run_nbench, 0},
11572         {"NBENCH2", run_nbench2, 0},
11573         {"OPLOCK1",  run_oplock1, 0},
11574         {"OPLOCK2",  run_oplock2, 0},
11575         {"OPLOCK4",  run_oplock4, 0},
11576         {"DIR",  run_dirtest, 0},
11577         {"DIR1",  run_dirtest1, 0},
11578         {"DIR-CREATETIME",  run_dir_createtime, 0},
11579         {"DENY1",  torture_denytest1, 0},
11580         {"DENY2",  torture_denytest2, 0},
11581         {"TCON",  run_tcon_test, 0},
11582         {"TCONDEV",  run_tcon_devtype_test, 0},
11583         {"RW1",  run_readwritetest, 0},
11584         {"RW2",  run_readwritemulti, FLAG_MULTIPROC},
11585         {"RW3",  run_readwritelarge, 0},
11586         {"RW-SIGNING",  run_readwritelarge_signtest, 0},
11587         {"OPEN", run_opentest, 0},
11588         {"POSIX", run_simple_posix_open_test, 0},
11589         {"POSIX-APPEND", run_posix_append, 0},
11590         {"POSIX-SYMLINK-ACL", run_acl_symlink_test, 0},
11591         {"POSIX-SYMLINK-EA", run_ea_symlink_test, 0},
11592         {"POSIX-STREAM-DELETE", run_posix_stream_delete, 0},
11593         {"POSIX-OFD-LOCK", run_posix_ofd_lock_test, 0},
11594         {"WINDOWS-BAD-SYMLINK", run_symlink_open_test, 0},
11595         {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
11596         {"ASYNC-ECHO", run_async_echo, 0},
11597         { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
11598         { "SHORTNAME-TEST", run_shortname_test, 0},
11599         { "ADDRCHANGE", run_addrchange, 0},
11600 #if 1
11601         {"OPENATTR", run_openattrtest, 0},
11602 #endif
11603         {"XCOPY", run_xcopy, 0},
11604         {"RENAME", run_rename, 0},
11605         {"RENAME-ACCESS", run_rename_access, 0},
11606         {"OWNER-RIGHTS", run_owner_rights, 0},
11607         {"DELETE", run_deletetest, 0},
11608         {"WILDDELETE", run_wild_deletetest, 0},
11609         {"DELETE-LN", run_deletetest_ln, 0},
11610         {"PROPERTIES", run_properties, 0},
11611         {"MANGLE", torture_mangle, 0},
11612         {"MANGLE1", run_mangle1, 0},
11613         {"MANGLE-ILLEGAL", run_mangle_illegal, 0},
11614         {"W2K", run_w2ktest, 0},
11615         {"TRANS2SCAN", torture_trans2_scan, 0},
11616         {"NTTRANSSCAN", torture_nttrans_scan, 0},
11617         {"UTABLE", torture_utable, 0},
11618         {"CASETABLE", torture_casetable, 0},
11619         {"ERRMAPEXTRACT", run_error_map_extract, 0},
11620         {"PIPE_NUMBER", run_pipe_number, 0},
11621         {"TCON2",  run_tcon2_test, 0},
11622         {"IOCTL",  torture_ioctl_test, 0},
11623         {"CHKPATH",  torture_chkpath_test, 0},
11624         {"FDSESS", run_fdsesstest, 0},
11625         { "EATEST", run_eatest, 0},
11626         { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
11627         { "CHAIN1", run_chain1, 0},
11628         { "CHAIN2", run_chain2, 0},
11629         { "CHAIN3", run_chain3, 0},
11630         { "WINDOWS-WRITE", run_windows_write, 0},
11631         { "LARGE_READX", run_large_readx, 0},
11632         { "NTTRANS-CREATE", run_nttrans_create, 0},
11633         { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
11634         { "CLI_ECHO", run_cli_echo, 0},
11635         { "GETADDRINFO", run_getaddrinfo_send, 0},
11636         { "TLDAP", run_tldap },
11637         { "STREAMERROR", run_streamerror },
11638         { "NOTIFY-BENCH", run_notify_bench },
11639         { "NOTIFY-BENCH2", run_notify_bench2 },
11640         { "NOTIFY-BENCH3", run_notify_bench3 },
11641         { "BAD-NBT-SESSION", run_bad_nbt_session },
11642         { "IGN-BAD-NEGPROT", run_ign_bad_negprot },
11643         { "SMB-ANY-CONNECT", run_smb_any_connect },
11644         { "NOTIFY-ONLINE", run_notify_online },
11645         { "SMB2-BASIC", run_smb2_basic },
11646         { "SMB2-NEGPROT", run_smb2_negprot },
11647         { "SMB2-SESSION-RECONNECT", run_smb2_session_reconnect },
11648         { "SMB2-TCON-DEPENDENCE", run_smb2_tcon_dependence },
11649         { "SMB2-MULTI-CHANNEL", run_smb2_multi_channel },
11650         { "SMB2-SESSION-REAUTH", run_smb2_session_reauth },
11651         { "SMB2-FTRUNCATE", run_smb2_ftruncate },
11652         { "CLEANUP1", run_cleanup1 },
11653         { "CLEANUP2", run_cleanup2 },
11654         { "CLEANUP3", run_cleanup3 },
11655         { "CLEANUP4", run_cleanup4 },
11656         { "OPLOCK-CANCEL", run_oplock_cancel },
11657         { "PIDHIGH", run_pidhigh },
11658         { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
11659         { "LOCAL-GENCACHE", run_local_gencache, 0},
11660         { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
11661         { "LOCAL-DBWRAP-WATCH1", run_dbwrap_watch1, 0 },
11662         { "LOCAL-DBWRAP-WATCH2", run_dbwrap_watch2, 0 },
11663         { "LOCAL-MESSAGING-READ1", run_messaging_read1, 0 },
11664         { "LOCAL-MESSAGING-READ2", run_messaging_read2, 0 },
11665         { "LOCAL-MESSAGING-READ3", run_messaging_read3, 0 },
11666         { "LOCAL-MESSAGING-READ4", run_messaging_read4, 0 },
11667         { "LOCAL-MESSAGING-FDPASS1", run_messaging_fdpass1, 0 },
11668         { "LOCAL-MESSAGING-FDPASS2", run_messaging_fdpass2, 0 },
11669         { "LOCAL-MESSAGING-FDPASS2a", run_messaging_fdpass2a, 0 },
11670         { "LOCAL-MESSAGING-FDPASS2b", run_messaging_fdpass2b, 0 },
11671         { "LOCAL-BASE64", run_local_base64, 0},
11672         { "LOCAL-RBTREE", run_local_rbtree, 0},
11673         { "LOCAL-MEMCACHE", run_local_memcache, 0},
11674         { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
11675         { "WBCLIENT-MULTI-PING", run_wbclient_multi_ping, 0},
11676         { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
11677         { "LOCAL-sid_to_string", run_local_sid_to_string, 0},
11678         { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
11679         { "LOCAL-DBTRANS", run_local_dbtrans, 0},
11680         { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
11681         { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
11682         { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
11683         { "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0},
11684         { "LOCAL-IDMAP-TDB-COMMON", run_idmap_tdb_common_test, 0},
11685         { "LOCAL-remove_duplicate_addrs2", run_local_remove_duplicate_addrs2, 0},
11686         { "local-tdb-opener", run_local_tdb_opener, 0 },
11687         { "local-tdb-writer", run_local_tdb_writer, 0 },
11688         { "LOCAL-DBWRAP-CTDB", run_local_dbwrap_ctdb, 0 },
11689         { "LOCAL-BENCH-PTHREADPOOL", run_bench_pthreadpool, 0 },
11690         { "LOCAL-PTHREADPOOL-TEVENT", run_pthreadpool_tevent, 0 },
11691         { "LOCAL-G-LOCK1", run_g_lock1, 0 },
11692         { "LOCAL-G-LOCK2", run_g_lock2, 0 },
11693         { "LOCAL-G-LOCK3", run_g_lock3, 0 },
11694         { "LOCAL-G-LOCK4", run_g_lock4, 0 },
11695         { "LOCAL-G-LOCK5", run_g_lock5, 0 },
11696         { "LOCAL-G-LOCK-PING-PONG", run_g_lock_ping_pong, 0 },
11697         { "LOCAL-CANONICALIZE-PATH", run_local_canonicalize_path, 0 },
11698         { "qpathinfo-bufsize", run_qpathinfo_bufsize, 0 },
11699         {NULL, NULL, 0}};
11700
11701 /*
11702  * dummy function to satisfy linker dependency
11703  */
11704 struct tevent_context *winbind_event_context(void);
11705 struct tevent_context *winbind_event_context(void)
11706 {
11707         return NULL;
11708 }
11709
11710 /****************************************************************************
11711 run a specified test or "ALL"
11712 ****************************************************************************/
11713 static bool run_test(const char *name)
11714 {
11715         bool ret = True;
11716         bool result = True;
11717         bool found = False;
11718         int i;
11719         double t;
11720         if (strequal(name,"ALL")) {
11721                 for (i=0;torture_ops[i].name;i++) {
11722                         run_test(torture_ops[i].name);
11723                 }
11724                 found = True;
11725         }
11726
11727         for (i=0;torture_ops[i].name;i++) {
11728                 fstr_sprintf(randomfname, "\\XX%x", 
11729                          (unsigned)random());
11730
11731                 if (strequal(name, torture_ops[i].name)) {
11732                         found = True;
11733                         printf("Running %s\n", name);
11734                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
11735                                 t = create_procs(torture_ops[i].fn, &result);
11736                                 if (!result) { 
11737                                         ret = False;
11738                                         printf("TEST %s FAILED!\n", name);
11739                                 }
11740                         } else {
11741                                 struct timeval start;
11742                                 start = timeval_current();
11743                                 if (!torture_ops[i].fn(0)) {
11744                                         ret = False;
11745                                         printf("TEST %s FAILED!\n", name);
11746                                 }
11747                                 t = timeval_elapsed(&start);
11748                         }
11749                         printf("%s took %g secs\n\n", name, t);
11750                 }
11751         }
11752
11753         if (!found) {
11754                 printf("Did not find a test named %s\n", name);
11755                 ret = False;
11756         }
11757
11758         return ret;
11759 }
11760
11761
11762 static void usage(void)
11763 {
11764         int i;
11765
11766         printf("WARNING samba4 test suite is much more complete nowadays.\n");
11767         printf("Please use samba4 torture.\n\n");
11768
11769         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
11770
11771         printf("\t-d debuglevel\n");
11772         printf("\t-U user%%pass\n");
11773         printf("\t-k                    use kerberos\n");
11774         printf("\t-N numprocs\n");
11775         printf("\t-n my_netbios_name\n");
11776         printf("\t-W workgroup\n");
11777         printf("\t-o num_operations\n");
11778         printf("\t-O socket_options\n");
11779         printf("\t-m maximum protocol\n");
11780         printf("\t-L use oplocks\n");
11781         printf("\t-c CLIENT.TXT         specify client load file for NBENCH\n");
11782         printf("\t-A showall\n");
11783         printf("\t-p port\n");
11784         printf("\t-s seed\n");
11785         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
11786         printf("\t-f filename           filename to test\n");
11787         printf("\t-e                    encrypt\n");
11788         printf("\n\n");
11789
11790         printf("tests are:");
11791         for (i=0;torture_ops[i].name;i++) {
11792                 printf(" %s", torture_ops[i].name);
11793         }
11794         printf("\n");
11795
11796         printf("default test is ALL\n");
11797
11798         exit(1);
11799 }
11800
11801 /****************************************************************************
11802   main program
11803 ****************************************************************************/
11804  int main(int argc,char *argv[])
11805 {
11806         int opt, i;
11807         char *p;
11808         int gotuser = 0;
11809         int gotpass = 0;
11810         bool correct = True;
11811         TALLOC_CTX *frame = talloc_stackframe();
11812         int seed = time(NULL);
11813
11814 #ifdef HAVE_SETBUFFER
11815         setbuffer(stdout, NULL, 0);
11816 #endif
11817
11818         setup_logging("smbtorture", DEBUG_STDOUT);
11819
11820         smb_init_locale();
11821         fault_setup();
11822
11823         if (is_default_dyn_CONFIGFILE()) {
11824                 if(getenv("SMB_CONF_PATH")) {
11825                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
11826                 }
11827         }
11828         lp_load_global(get_dyn_CONFIGFILE());
11829         load_interfaces();
11830
11831         if (argc < 2) {
11832                 usage();
11833         }
11834
11835         for(p = argv[1]; *p; p++)
11836           if(*p == '\\')
11837             *p = '/';
11838
11839         if (strncmp(argv[1], "//", 2)) {
11840                 usage();
11841         }
11842
11843         fstrcpy(host, &argv[1][2]);
11844         p = strchr_m(&host[2],'/');
11845         if (!p) {
11846                 usage();
11847         }
11848         *p = 0;
11849         fstrcpy(share, p+1);
11850
11851         fstrcpy(myname, get_myname(talloc_tos()));
11852         if (!*myname) {
11853                 fprintf(stderr, "Failed to get my hostname.\n");
11854                 return 1;
11855         }
11856
11857         if (*username == 0 && getenv("LOGNAME")) {
11858           fstrcpy(username,getenv("LOGNAME"));
11859         }
11860
11861         argc--;
11862         argv++;
11863
11864         fstrcpy(workgroup, lp_workgroup());
11865
11866         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
11867                != EOF) {
11868                 switch (opt) {
11869                 case 'p':
11870                         port_to_use = atoi(optarg);
11871                         break;
11872                 case 's':
11873                         seed = atoi(optarg);
11874                         break;
11875                 case 'W':
11876                         fstrcpy(workgroup,optarg);
11877                         break;
11878                 case 'm':
11879                         lp_set_cmdline("client max protocol", optarg);
11880                         break;
11881                 case 'N':
11882                         torture_nprocs = atoi(optarg);
11883                         break;
11884                 case 'o':
11885                         torture_numops = atoi(optarg);
11886                         break;
11887                 case 'd':
11888                         lp_set_cmdline("log level", optarg);
11889                         break;
11890                 case 'O':
11891                         sockops = optarg;
11892                         break;
11893                 case 'L':
11894                         use_oplocks = True;
11895                         break;
11896                 case 'l':
11897                         local_path = optarg;
11898                         break;
11899                 case 'A':
11900                         torture_showall = True;
11901                         break;
11902                 case 'n':
11903                         fstrcpy(myname, optarg);
11904                         break;
11905                 case 'c':
11906                         client_txt = optarg;
11907                         break;
11908                 case 'e':
11909                         do_encrypt = true;
11910                         break;
11911                 case 'k':
11912 #ifdef HAVE_KRB5
11913                         use_kerberos = True;
11914 #else
11915                         d_printf("No kerberos support compiled in\n");
11916                         exit(1);
11917 #endif
11918                         break;
11919                 case 'U':
11920                         gotuser = 1;
11921                         fstrcpy(username,optarg);
11922                         p = strchr_m(username,'%');
11923                         if (p) {
11924                                 *p = 0;
11925                                 fstrcpy(password, p+1);
11926                                 gotpass = 1;
11927                         }
11928                         break;
11929                 case 'b':
11930                         fstrcpy(multishare_conn_fname, optarg);
11931                         use_multishare_conn = True;
11932                         break;
11933                 case 'B':
11934                         torture_blocksize = atoi(optarg);
11935                         break;
11936                 case 'f':
11937                         test_filename = SMB_STRDUP(optarg);
11938                         break;
11939                 default:
11940                         printf("Unknown option %c (%d)\n", (char)opt, opt);
11941                         usage();
11942                 }
11943         }
11944
11945         d_printf("using seed %d\n", seed);
11946
11947         srandom(seed);
11948
11949         if(use_kerberos && !gotuser) gotpass = True;
11950
11951         while (!gotpass) {
11952                 char pwd[256] = {0};
11953                 int rc;
11954
11955                 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
11956                 if (rc == 0) {
11957                         fstrcpy(password, pwd);
11958                         gotpass = 1;
11959                 }
11960         }
11961
11962         printf("host=%s share=%s user=%s myname=%s\n", 
11963                host, share, username, myname);
11964
11965         torture_creds = cli_session_creds_init(frame,
11966                                                username,
11967                                                workgroup,
11968                                                NULL, /* realm */
11969                                                password,
11970                                                use_kerberos,
11971                                                false, /* fallback_after_kerberos */
11972                                                false, /* use_ccache */
11973                                                false); /* password_is_nt_hash */
11974         if (torture_creds == NULL) {
11975                 d_printf("cli_session_creds_init() failed.\n");
11976                 exit(1);
11977         }
11978
11979         if (argc == optind) {
11980                 correct = run_test("ALL");
11981         } else {
11982                 for (i=optind;i<argc;i++) {
11983                         if (!run_test(argv[i])) {
11984                                 correct = False;
11985                         }
11986                 }
11987         }
11988
11989         TALLOC_FREE(frame);
11990
11991         if (correct) {
11992                 return(0);
11993         } else {
11994                 return(1);
11995         }
11996 }