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