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