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