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