s4:kdc: Implement KDC plugin hardware authentication policy
[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 "tldap_gensec_bind.h"
30 #include "tldap_tls_connect.h"
31 #include "../librpc/gen_ndr/svcctl.h"
32 #include "../lib/util/memcache.h"
33 #include "nsswitch/winbind_client.h"
34 #include "dbwrap/dbwrap.h"
35 #include "dbwrap/dbwrap_open.h"
36 #include "dbwrap/dbwrap_rbt.h"
37 #include "async_smb.h"
38 #include "libsmb/libsmb.h"
39 #include "libsmb/clirap.h"
40 #include "trans2.h"
41 #include "libsmb/nmblib.h"
42 #include "../lib/util/tevent_ntstatus.h"
43 #include "util_tdb.h"
44 #include "../libcli/smb/read_smb.h"
45 #include "../libcli/smb/smbXcli_base.h"
46 #include "lib/util/sys_rw_data.h"
47 #include "lib/util/base64.h"
48 #include "lib/util/time.h"
49 #include "lib/gencache.h"
50 #include "lib/util/sys_rw.h"
51 #include "lib/util/asn1.h"
52 #include "lib/util/util_file.h"
53 #include "lib/param/param.h"
54 #include "auth/gensec/gensec.h"
55 #include "lib/util/string_wrappers.h"
56 #include "source3/lib/substitute.h"
57 #include "ads.h"
58
59 #include <gnutls/gnutls.h>
60 #include <gnutls/crypto.h>
61
62 extern char *optarg;
63 extern int optind;
64
65 fstring host, workgroup, share, password, username, myname;
66 struct cli_credentials *torture_creds;
67 static const char *sockops="TCP_NODELAY";
68 int torture_nprocs=1;
69 static int port_to_use=0;
70 int torture_numops=100;
71 int torture_blocksize=1024*1024;
72 static int procnum; /* records process count number when forking */
73 static struct cli_state *current_cli;
74 static fstring randomfname;
75 static bool use_oplocks;
76 static bool use_level_II_oplocks;
77 static const char *client_txt = "client_oplocks.txt";
78 static bool disable_spnego;
79 static bool use_kerberos;
80 static bool force_dos_errors;
81 static fstring multishare_conn_fname;
82 static bool use_multishare_conn = False;
83 static bool do_encrypt;
84 static const char *local_path = NULL;
85 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
86 char *test_filename;
87
88 bool torture_showall = False;
89
90 static double create_procs(bool (*fn)(int), bool *result);
91
92 /********************************************************************
93  Ensure a connection is encrypted.
94 ********************************************************************/
95
96 static bool force_cli_encryption(struct cli_state *c,
97                         const char *sharename)
98 {
99         uint16_t major, minor;
100         uint32_t caplow, caphigh;
101         NTSTATUS status;
102
103         if (!SERVER_HAS_UNIX_CIFS(c)) {
104                 d_printf("Encryption required and "
105                         "server that doesn't support "
106                         "UNIX extensions - failing connect\n");
107                         return false;
108         }
109
110         status = cli_unix_extensions_version(c, &major, &minor, &caplow,
111                                              &caphigh);
112         if (!NT_STATUS_IS_OK(status)) {
113                 d_printf("Encryption required and "
114                         "can't get UNIX CIFS extensions "
115                         "version from server: %s\n", nt_errstr(status));
116                 return false;
117         }
118
119         if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
120                 d_printf("Encryption required and "
121                         "share %s doesn't support "
122                         "encryption.\n", sharename);
123                 return false;
124         }
125
126         status = cli_smb1_setup_encryption(c, torture_creds);
127         if (!NT_STATUS_IS_OK(status)) {
128                 d_printf("Encryption required and "
129                         "setup failed with error %s.\n",
130                         nt_errstr(status));
131                 return false;
132         }
133
134         return true;
135 }
136
137
138 static struct cli_state *open_nbt_connection(void)
139 {
140         struct cli_state *c;
141         NTSTATUS status;
142         int flags = 0;
143
144         if (disable_spnego) {
145                 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
146         }
147
148         if (use_oplocks) {
149                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
150         }
151
152         if (use_level_II_oplocks) {
153                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
154         }
155
156         if (force_dos_errors) {
157                 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
158         }
159
160         status = cli_connect_nb(NULL,
161                                 host,
162                                 NULL,
163                                 port_to_use,
164                                 0x20,
165                                 myname,
166                                 signing_state,
167                                 flags,
168                                 &c);
169         if (!NT_STATUS_IS_OK(status)) {
170                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
171                 return NULL;
172         }
173
174         cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
175
176         return c;
177 }
178
179 /****************************************************************************
180  Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
181 ****************************************************************************/
182
183 static bool cli_bad_session_request(int fd,
184                          struct nmb_name *calling, struct nmb_name *called)
185 {
186         TALLOC_CTX *frame;
187         uint8_t len_buf[4];
188         struct iovec iov[3];
189         ssize_t len;
190         uint8_t *inbuf;
191         int err;
192         bool ret = false;
193         uint8_t message_type;
194         uint8_t error;
195         struct tevent_context *ev;
196         struct tevent_req *req;
197
198         frame = talloc_stackframe();
199
200         iov[0].iov_base = len_buf;
201         iov[0].iov_len  = sizeof(len_buf);
202
203         /* put in the destination name */
204
205         iov[1].iov_base = name_mangle(talloc_tos(), called->name,
206                                       called->name_type);
207         if (iov[1].iov_base == NULL) {
208                 goto fail;
209         }
210         iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
211                                   talloc_get_size(iov[1].iov_base));
212
213         /* and my name */
214
215         iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
216                                       calling->name_type);
217         if (iov[2].iov_base == NULL) {
218                 goto fail;
219         }
220         iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
221                                   talloc_get_size(iov[2].iov_base));
222
223         /* Deliberately corrupt the name len (first byte) */
224         *((uint8_t *)iov[2].iov_base) = 100;
225
226         /* send a session request (RFC 1002) */
227         /* setup the packet length
228          * Remove four bytes from the length count, since the length
229          * field in the NBT Session Service header counts the number
230          * of bytes which follow.  The cli_send_smb() function knows
231          * about this and accounts for those four bytes.
232          * CRH.
233          */
234
235         _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
236         SCVAL(len_buf,0,0x81);
237
238         len = write_data_iov(fd, iov, 3);
239         if (len == -1) {
240                 goto fail;
241         }
242
243         ev = samba_tevent_context_init(frame);
244         if (ev == NULL) {
245                 goto fail;
246         }
247         req = read_smb_send(frame, ev, fd);
248         if (req == NULL) {
249                 goto fail;
250         }
251         if (!tevent_req_poll(req, ev)) {
252                 goto fail;
253         }
254         len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
255         if (len == -1) {
256                 errno = err;
257                 goto fail;
258         }
259         TALLOC_FREE(ev);
260
261         message_type = CVAL(inbuf, 0);
262         if (message_type != 0x83) {
263                 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
264                           message_type);
265                 goto fail;
266         }
267
268         if (smb_len(inbuf) != 1) {
269                 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
270                           (int)smb_len(inbuf));
271                 goto fail;
272         }
273
274         error = CVAL(inbuf, 4);
275         if (error !=  0x82) {
276                 d_fprintf(stderr, "Expected error 0x82, got %d\n",
277                           (int)error);
278                 goto fail;
279         }
280
281         ret = true;
282 fail:
283         TALLOC_FREE(frame);
284         return ret;
285 }
286
287 /* Insert a NULL at the first separator of the given path and return a pointer
288  * to the remainder of the string.
289  */
290 static char *
291 terminate_path_at_separator(char * path)
292 {
293         char * p;
294
295         if (!path) {
296                 return NULL;
297         }
298
299         if ((p = strchr_m(path, '/'))) {
300                 *p = '\0';
301                 return p + 1;
302         }
303
304         if ((p = strchr_m(path, '\\'))) {
305                 *p = '\0';
306                 return p + 1;
307         }
308
309         /* No separator. */
310         return NULL;
311 }
312
313 /*
314   parse a //server/share type UNC name
315 */
316 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
317                       char **hostname, char **sharename)
318 {
319         char *p;
320
321         *hostname = *sharename = NULL;
322
323         if (strncmp(unc_name, "\\\\", 2) &&
324             strncmp(unc_name, "//", 2)) {
325                 return False;
326         }
327
328         *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
329         p = terminate_path_at_separator(*hostname);
330
331         if (p && *p) {
332                 *sharename = talloc_strdup(mem_ctx, p);
333                 terminate_path_at_separator(*sharename);
334         }
335
336         if (*hostname && *sharename) {
337                 return True;
338         }
339
340         TALLOC_FREE(*hostname);
341         TALLOC_FREE(*sharename);
342         return False;
343 }
344
345 static bool torture_open_connection_share(struct cli_state **c,
346                                    const char *hostname,
347                                    const char *sharename,
348                                    int flags)
349 {
350         NTSTATUS status;
351
352         status = cli_full_connection_creds(NULL,
353                                            c,
354                                            myname,
355                                            hostname,
356                                            NULL, /* dest_ss */
357                                            port_to_use,
358                                            sharename,
359                                            "?????",
360                                            torture_creds,
361                                            flags);
362         if (!NT_STATUS_IS_OK(status)) {
363                 printf("failed to open share connection: //%s/%s port:%d - %s\n",
364                         hostname, sharename, port_to_use, nt_errstr(status));
365                 return False;
366         }
367
368         cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
369
370         if (do_encrypt) {
371                 return force_cli_encryption(*c,
372                                         sharename);
373         }
374         return True;
375 }
376
377 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
378 {
379         char **unc_list = NULL;
380         int num_unc_names = 0;
381         bool result;
382
383         if (use_multishare_conn==True) {
384                 char *h, *s;
385                 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
386                 if (!unc_list || num_unc_names <= 0) {
387                         printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
388                         exit(1);
389                 }
390
391                 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
392                                       NULL, &h, &s)) {
393                         printf("Failed to parse UNC name %s\n",
394                                unc_list[conn_index % num_unc_names]);
395                         TALLOC_FREE(unc_list);
396                         exit(1);
397                 }
398
399                 result = torture_open_connection_share(c, h, s, flags);
400
401                 /* h, s were copied earlier */
402                 TALLOC_FREE(unc_list);
403                 return result;
404         }
405
406         return torture_open_connection_share(c, host, share, flags);
407 }
408
409 bool torture_open_connection(struct cli_state **c, int conn_index)
410 {
411         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
412
413         if (use_oplocks) {
414                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
415         }
416         if (use_level_II_oplocks) {
417                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
418         }
419
420         return torture_open_connection_flags(c, conn_index, flags);
421 }
422
423 bool torture_init_connection(struct cli_state **pcli)
424 {
425         struct cli_state *cli;
426
427         cli = open_nbt_connection();
428         if (cli == NULL) {
429                 return false;
430         }
431
432         *pcli = cli;
433         return true;
434 }
435
436 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
437 {
438         uint16_t old_vuid = cli_state_get_uid(cli);
439         NTSTATUS status;
440         bool ret;
441
442         cli_state_set_uid(cli, 0);
443         status = cli_session_setup_creds(cli, torture_creds);
444         ret = NT_STATUS_IS_OK(status);
445         *new_vuid = cli_state_get_uid(cli);
446         cli_state_set_uid(cli, old_vuid);
447         return ret;
448 }
449
450
451 bool torture_close_connection(struct cli_state *c)
452 {
453         bool ret = True;
454         NTSTATUS status;
455
456         status = cli_tdis(c);
457         if (!NT_STATUS_IS_OK(status)) {
458                 printf("tdis failed (%s)\n", nt_errstr(status));
459                 ret = False;
460         }
461
462         cli_shutdown(c);
463
464         return ret;
465 }
466
467 void torture_conn_set_sockopt(struct cli_state *cli)
468 {
469         smbXcli_conn_set_sockopt(cli->conn, sockops);
470 }
471
472 static NTSTATUS torture_delete_fn(struct file_info *finfo,
473                                   const char *pattern,
474                                   void *state)
475 {
476         NTSTATUS status;
477         char *filename = NULL;
478         char *dirname = NULL;
479         char *p = NULL;
480         TALLOC_CTX *frame = talloc_stackframe();
481         struct cli_state *cli = (struct cli_state *)state;
482
483         if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
484                 TALLOC_FREE(frame);
485                 return NT_STATUS_OK;
486         }
487
488         dirname = talloc_strdup(frame, pattern);
489         if (dirname == NULL) {
490                 TALLOC_FREE(frame);
491                 return NT_STATUS_NO_MEMORY;
492         }
493         p = strrchr_m(dirname, '\\');
494         if (p != NULL) {
495                 /* Remove the terminating '\' */
496                 *p = '\0';
497         }
498         if (dirname[0] != '\0') {
499                 filename = talloc_asprintf(frame,
500                                            "%s\\%s",
501                                            dirname,
502                                            finfo->name);
503         } else {
504                 filename = talloc_asprintf(frame,
505                                            "%s",
506                                            finfo->name);
507         }
508         if (filename == NULL) {
509                 TALLOC_FREE(frame);
510                 return NT_STATUS_NO_MEMORY;
511         }
512         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
513                 char *subdirname = talloc_asprintf(frame,
514                                                    "%s\\*",
515                                                    filename);
516                 if (subdirname == NULL) {
517                         TALLOC_FREE(frame);
518                         return NT_STATUS_NO_MEMORY;
519                 }
520                 status = cli_list(cli,
521                                   subdirname,
522                                   FILE_ATTRIBUTE_DIRECTORY |
523                                           FILE_ATTRIBUTE_HIDDEN |
524                                           FILE_ATTRIBUTE_SYSTEM,
525                                   torture_delete_fn,
526                                   cli);
527                 if (!NT_STATUS_IS_OK(status)) {
528                         printf("torture_delete_fn: cli_list "
529                                 "of %s failed (%s)\n",
530                                 subdirname,
531                                 nt_errstr(status));
532                         TALLOC_FREE(frame);
533                         return status;
534                 }
535                 status = cli_rmdir(cli, filename);
536         } else {
537                 status = cli_unlink(cli,
538                                     filename,
539                                     FILE_ATTRIBUTE_SYSTEM |
540                                         FILE_ATTRIBUTE_HIDDEN);
541         }
542         if (!NT_STATUS_IS_OK(status)) {
543                 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
544                         printf("torture_delete_fn: cli_rmdir"
545                                 " of %s failed (%s)\n",
546                                 filename,
547                                 nt_errstr(status));
548                 } else {
549                         printf("torture_delete_fn: cli_unlink"
550                                 " of %s failed (%s)\n",
551                                 filename,
552                                 nt_errstr(status));
553                 }
554         }
555         TALLOC_FREE(frame);
556         return status;
557 }
558
559 void torture_deltree(struct cli_state *cli, const char *dname)
560 {
561         char *mask = NULL;
562         NTSTATUS status;
563
564         /* It might be a file */
565         (void)cli_unlink(cli,
566                          dname,
567                          FILE_ATTRIBUTE_SYSTEM |
568                                 FILE_ATTRIBUTE_HIDDEN);
569
570         mask = talloc_asprintf(cli,
571                                "%s\\*",
572                                dname);
573         if (mask == NULL) {
574                 printf("torture_deltree: talloc_asprintf failed\n");
575                 return;
576         }
577
578         status = cli_list(cli,
579                         mask,
580                         FILE_ATTRIBUTE_DIRECTORY |
581                                 FILE_ATTRIBUTE_HIDDEN|
582                                 FILE_ATTRIBUTE_SYSTEM,
583                         torture_delete_fn,
584                         cli);
585         if (!NT_STATUS_IS_OK(status)) {
586                 printf("torture_deltree: cli_list of %s failed (%s)\n",
587                         mask,
588                         nt_errstr(status));
589         }
590         TALLOC_FREE(mask);
591         status = cli_rmdir(cli, dname);
592         if (!NT_STATUS_IS_OK(status)) {
593                 printf("torture_deltree: cli_rmdir of %s failed (%s)\n",
594                         dname,
595                         nt_errstr(status));
596         }
597 }
598
599 /* check if the server produced the expected dos or nt error code */
600 static bool check_both_error(int line, NTSTATUS status,
601                              uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
602 {
603         if (NT_STATUS_IS_DOS(status)) {
604                 uint8_t cclass;
605                 uint32_t num;
606
607                 /* Check DOS error */
608                 cclass = NT_STATUS_DOS_CLASS(status);
609                 num = NT_STATUS_DOS_CODE(status);
610
611                 if (eclass != cclass || ecode != num) {
612                         printf("unexpected error code class=%d code=%d\n",
613                                (int)cclass, (int)num);
614                         printf(" expected %d/%d %s (line=%d)\n",
615                                (int)eclass, (int)ecode, nt_errstr(nterr), line);
616                         return false;
617                 }
618         } else {
619                 /* Check NT error */
620                 if (!NT_STATUS_EQUAL(nterr, status)) {
621                         printf("unexpected error code %s\n",
622                                 nt_errstr(status));
623                         printf(" expected %s (line=%d)\n",
624                                 nt_errstr(nterr), line);
625                         return false;
626                 }
627         }
628
629         return true;
630 }
631
632
633 /* check if the server produced the expected error code */
634 static bool check_error(int line, NTSTATUS status,
635                         uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
636 {
637         if (NT_STATUS_IS_DOS(status)) {
638                 uint8_t cclass;
639                 uint32_t num;
640
641                 /* Check DOS error */
642
643                 cclass = NT_STATUS_DOS_CLASS(status);
644                 num = NT_STATUS_DOS_CODE(status);
645
646                 if (eclass != cclass || ecode != num) {
647                         printf("unexpected error code class=%d code=%d\n",
648                                (int)cclass, (int)num);
649                         printf(" expected %d/%d %s (line=%d)\n",
650                                (int)eclass, (int)ecode, nt_errstr(nterr),
651                                line);
652                         return False;
653                 }
654
655         } else {
656                 /* Check NT error */
657
658                 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
659                         printf("unexpected error code %s\n",
660                                nt_errstr(status));
661                         printf(" expected %s (line=%d)\n", nt_errstr(nterr),
662                                line);
663                         return False;
664                 }
665         }
666
667         return True;
668 }
669
670 NTSTATUS cli_qpathinfo1(struct cli_state *cli,
671                         const char *fname,
672                         time_t *change_time,
673                         time_t *access_time,
674                         time_t *write_time,
675                         off_t *size,
676                         uint32_t *pattr)
677 {
678         int timezone = smb1cli_conn_server_time_zone(cli->conn);
679         time_t (*date_fn)(const void *buf, int serverzone) = NULL;
680         uint8_t *rdata = NULL;
681         uint32_t num_rdata;
682         NTSTATUS status;
683
684         status = cli_qpathinfo(talloc_tos(),
685                                cli,
686                                fname,
687                                SMB_INFO_STANDARD,
688                                22,
689                                CLI_BUFFER_SIZE,
690                                &rdata,
691                                &num_rdata);
692         if (!NT_STATUS_IS_OK(status)) {
693                 return status;
694         }
695         if (cli->win95) {
696                 date_fn = make_unix_date;
697         } else {
698                 date_fn = make_unix_date2;
699         }
700
701         if (change_time) {
702                 *change_time = date_fn(rdata + 0, timezone);
703         }
704         if (access_time) {
705                 *access_time = date_fn(rdata + 4, timezone);
706         }
707         if (write_time) {
708                 *write_time = date_fn(rdata + 8, timezone);
709         }
710         if (size) {
711                 *size = PULL_LE_U32(rdata, 12);
712         }
713         if (pattr) {
714                 *pattr = PULL_LE_U16(rdata, l1_attrFile);
715         }
716         return NT_STATUS_OK;
717 }
718
719 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
720 {
721         NTSTATUS status;
722
723         status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
724
725         while (!NT_STATUS_IS_OK(status)) {
726                 if (!check_both_error(__LINE__, status, ERRDOS,
727                                       ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
728                         return false;
729                 }
730
731                 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
732         }
733
734         return true;
735 }
736
737
738 static bool rw_torture(struct cli_state *c)
739 {
740         const char *lockfname = "\\torture.lck";
741         fstring fname;
742         uint16_t fnum;
743         uint16_t fnum2;
744         pid_t pid2, pid = getpid();
745         int i, j;
746         char buf[1024];
747         bool correct = True;
748         size_t nread = 0;
749         NTSTATUS status;
750
751         memset(buf, '\0', sizeof(buf));
752
753         status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
754                          DENY_NONE, &fnum2);
755         if (!NT_STATUS_IS_OK(status)) {
756                 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
757         }
758         if (!NT_STATUS_IS_OK(status)) {
759                 printf("open of %s failed (%s)\n",
760                        lockfname, nt_errstr(status));
761                 return False;
762         }
763
764         for (i=0;i<torture_numops;i++) {
765                 unsigned n = (unsigned)sys_random()%10;
766
767                 if (i % 10 == 0) {
768                         printf("%d\r", i); fflush(stdout);
769                 }
770                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
771
772                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
773                         return False;
774                 }
775
776                 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
777                                   DENY_ALL, &fnum);
778                 if (!NT_STATUS_IS_OK(status)) {
779                         printf("open failed (%s)\n", nt_errstr(status));
780                         correct = False;
781                         break;
782                 }
783
784                 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
785                                       sizeof(pid), NULL);
786                 if (!NT_STATUS_IS_OK(status)) {
787                         printf("write failed (%s)\n", nt_errstr(status));
788                         correct = False;
789                 }
790
791                 for (j=0;j<50;j++) {
792                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
793                                               sizeof(pid)+(j*sizeof(buf)),
794                                               sizeof(buf), NULL);
795                         if (!NT_STATUS_IS_OK(status)) {
796                                 printf("write failed (%s)\n",
797                                        nt_errstr(status));
798                                 correct = False;
799                         }
800                 }
801
802                 pid2 = 0;
803
804                 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
805                                   &nread);
806                 if (!NT_STATUS_IS_OK(status)) {
807                         printf("read failed (%s)\n", nt_errstr(status));
808                         correct = false;
809                 } else if (nread != sizeof(pid)) {
810                         printf("read/write compare failed: "
811                                "recv %ld req %ld\n", (unsigned long)nread,
812                                (unsigned long)sizeof(pid));
813                         correct = false;
814                 }
815
816                 if (pid2 != pid) {
817                         printf("data corruption!\n");
818                         correct = False;
819                 }
820
821                 status = cli_close(c, fnum);
822                 if (!NT_STATUS_IS_OK(status)) {
823                         printf("close failed (%s)\n", nt_errstr(status));
824                         correct = False;
825                 }
826
827                 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
828                 if (!NT_STATUS_IS_OK(status)) {
829                         printf("unlink failed (%s)\n", nt_errstr(status));
830                         correct = False;
831                 }
832
833                 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
834                 if (!NT_STATUS_IS_OK(status)) {
835                         printf("unlock failed (%s)\n", nt_errstr(status));
836                         correct = False;
837                 }
838         }
839
840         cli_close(c, fnum2);
841         cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
842
843         printf("%d\n", i);
844
845         return correct;
846 }
847
848 static bool run_torture(int dummy)
849 {
850         struct cli_state *cli;
851         bool ret;
852
853         cli = current_cli;
854
855         smbXcli_conn_set_sockopt(cli->conn, sockops);
856
857         ret = rw_torture(cli);
858
859         if (!torture_close_connection(cli)) {
860                 ret = False;
861         }
862
863         return ret;
864 }
865
866 static bool rw_torture3(struct cli_state *c, char *lockfname)
867 {
868         uint16_t fnum = (uint16_t)-1;
869         unsigned int i = 0;
870         char buf[131072];
871         char buf_rd[131072];
872         unsigned count;
873         unsigned countprev = 0;
874         size_t sent = 0;
875         bool correct = True;
876         NTSTATUS status = NT_STATUS_OK;
877
878         srandom(1);
879         for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
880         {
881                 SIVAL(buf, i, sys_random());
882         }
883
884         if (procnum == 0)
885         {
886                 status = cli_unlink(
887                         c, lockfname,
888                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
889                 if (!NT_STATUS_IS_OK(status)) {
890                         printf("unlink failed (%s) (normal, this file should "
891                                "not exist)\n", nt_errstr(status));
892                 }
893
894                 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
895                                   DENY_NONE, &fnum);
896                 if (!NT_STATUS_IS_OK(status)) {
897                         printf("first open read/write of %s failed (%s)\n",
898                                         lockfname, nt_errstr(status));
899                         return False;
900                 }
901         }
902         else
903         {
904                 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
905                 {
906                         status = cli_openx(c, lockfname, O_RDONLY,
907                                          DENY_NONE, &fnum);
908                         if (NT_STATUS_IS_OK(status)) {
909                                 break;
910                         }
911                         smb_msleep(10);
912                 }
913                 if (!NT_STATUS_IS_OK(status)) {
914                         printf("second open read-only of %s failed (%s)\n",
915                                         lockfname, nt_errstr(status));
916                         return False;
917                 }
918         }
919
920         i = 0;
921         for (count = 0; count < sizeof(buf); count += sent)
922         {
923                 if (count >= countprev) {
924                         printf("%d %8d\r", i, count);
925                         fflush(stdout);
926                         i++;
927                         countprev += (sizeof(buf) / 20);
928                 }
929
930                 if (procnum == 0)
931                 {
932                         sent = ((unsigned)sys_random()%(20))+ 1;
933                         if (sent > sizeof(buf) - count)
934                         {
935                                 sent = sizeof(buf) - count;
936                         }
937
938                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
939                                               count, sent, NULL);
940                         if (!NT_STATUS_IS_OK(status)) {
941                                 printf("write failed (%s)\n",
942                                        nt_errstr(status));
943                                 correct = False;
944                         }
945                 }
946                 else
947                 {
948                         status = cli_read(c, fnum, buf_rd+count, count,
949                                           sizeof(buf)-count, &sent);
950                         if(!NT_STATUS_IS_OK(status)) {
951                                 printf("read failed offset:%d size:%ld (%s)\n",
952                                        count, (unsigned long)sizeof(buf)-count,
953                                        nt_errstr(status));
954                                 correct = False;
955                                 sent = 0;
956                         } else if (sent > 0) {
957                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
958                                 {
959                                         printf("read/write compare failed\n");
960                                         printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
961                                         correct = False;
962                                         break;
963                                 }
964                         }
965                 }
966
967         }
968
969         status = cli_close(c, fnum);
970         if (!NT_STATUS_IS_OK(status)) {
971                 printf("close failed (%s)\n", nt_errstr(status));
972                 correct = False;
973         }
974
975         return correct;
976 }
977
978 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
979 {
980         const char *lockfname = "\\torture2.lck";
981         uint16_t fnum1;
982         uint16_t fnum2;
983         int i;
984         char buf[131072];
985         char buf_rd[131072];
986         bool correct = True;
987         size_t bytes_read;
988         NTSTATUS status;
989
990         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
991         if (!NT_STATUS_IS_OK(status)) {
992                 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
993         }
994
995         status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
996                           DENY_NONE, &fnum1);
997         if (!NT_STATUS_IS_OK(status)) {
998                 printf("first open read/write of %s failed (%s)\n",
999                                 lockfname, nt_errstr(status));
1000                 return False;
1001         }
1002
1003         status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
1004         if (!NT_STATUS_IS_OK(status)) {
1005                 printf("second open read-only of %s failed (%s)\n",
1006                                 lockfname, nt_errstr(status));
1007                 cli_close(c1, fnum1);
1008                 return False;
1009         }
1010
1011         for (i = 0; i < torture_numops; i++)
1012         {
1013                 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
1014                 if (i % 10 == 0) {
1015                         printf("%d\r", i); fflush(stdout);
1016                 }
1017
1018                 generate_random_buffer((unsigned char *)buf, buf_size);
1019
1020                 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
1021                                       buf_size, NULL);
1022                 if (!NT_STATUS_IS_OK(status)) {
1023                         printf("write failed (%s)\n", nt_errstr(status));
1024                         correct = False;
1025                         break;
1026                 }
1027
1028                 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
1029                 if(!NT_STATUS_IS_OK(status)) {
1030                         printf("read failed (%s)\n", nt_errstr(status));
1031                         correct = false;
1032                         break;
1033                 } else if (bytes_read != buf_size) {
1034                         printf("read failed\n");
1035                         printf("read %ld, expected %ld\n",
1036                                (unsigned long)bytes_read,
1037                                (unsigned long)buf_size);
1038                         correct = False;
1039                         break;
1040                 }
1041
1042                 if (memcmp(buf_rd, buf, buf_size) != 0)
1043                 {
1044                         printf("read/write compare failed\n");
1045                         correct = False;
1046                         break;
1047                 }
1048         }
1049
1050         status = cli_close(c2, fnum2);
1051         if (!NT_STATUS_IS_OK(status)) {
1052                 printf("close failed (%s)\n", nt_errstr(status));
1053                 correct = False;
1054         }
1055
1056         status = cli_close(c1, fnum1);
1057         if (!NT_STATUS_IS_OK(status)) {
1058                 printf("close failed (%s)\n", nt_errstr(status));
1059                 correct = False;
1060         }
1061
1062         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1063         if (!NT_STATUS_IS_OK(status)) {
1064                 printf("unlink failed (%s)\n", nt_errstr(status));
1065                 correct = False;
1066         }
1067
1068         return correct;
1069 }
1070
1071 static bool run_readwritetest(int dummy)
1072 {
1073         struct cli_state *cli1, *cli2;
1074         bool test1, test2 = False;
1075
1076         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1077                 return False;
1078         }
1079         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1080         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1081
1082         printf("starting readwritetest\n");
1083
1084         test1 = rw_torture2(cli1, cli2);
1085         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
1086
1087         if (test1) {
1088                 test2 = rw_torture2(cli1, cli1);
1089                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
1090         }
1091
1092         if (!torture_close_connection(cli1)) {
1093                 test1 = False;
1094         }
1095
1096         if (!torture_close_connection(cli2)) {
1097                 test2 = False;
1098         }
1099
1100         return (test1 && test2);
1101 }
1102
1103 static bool run_readwritemulti(int dummy)
1104 {
1105         struct cli_state *cli;
1106         bool test;
1107
1108         cli = current_cli;
1109
1110         smbXcli_conn_set_sockopt(cli->conn, sockops);
1111
1112         printf("run_readwritemulti: fname %s\n", randomfname);
1113         test = rw_torture3(cli, randomfname);
1114
1115         if (!torture_close_connection(cli)) {
1116                 test = False;
1117         }
1118
1119         return test;
1120 }
1121
1122 static bool run_readwritelarge_internal(void)
1123 {
1124         static struct cli_state *cli1;
1125         uint16_t fnum1;
1126         const char *lockfname = "\\large.dat";
1127         off_t fsize;
1128         char buf[126*1024];
1129         bool correct = True;
1130         NTSTATUS status;
1131
1132         if (!torture_open_connection(&cli1, 0)) {
1133                 return False;
1134         }
1135         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1136         memset(buf,'\0',sizeof(buf));
1137
1138         printf("starting readwritelarge_internal\n");
1139
1140         cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1141
1142         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1143                           DENY_NONE, &fnum1);
1144         if (!NT_STATUS_IS_OK(status)) {
1145                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1146                 return False;
1147         }
1148
1149         cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1150
1151         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1152                                      NULL, NULL, NULL);
1153         if (!NT_STATUS_IS_OK(status)) {
1154                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1155                 correct = False;
1156         }
1157
1158         if (fsize == sizeof(buf))
1159                 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1160                        (unsigned long)fsize);
1161         else {
1162                 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1163                        (unsigned long)fsize);
1164                 correct = False;
1165         }
1166
1167         status = cli_close(cli1, fnum1);
1168         if (!NT_STATUS_IS_OK(status)) {
1169                 printf("close failed (%s)\n", nt_errstr(status));
1170                 correct = False;
1171         }
1172
1173         status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1174         if (!NT_STATUS_IS_OK(status)) {
1175                 printf("unlink failed (%s)\n", nt_errstr(status));
1176                 correct = False;
1177         }
1178
1179         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1180                           DENY_NONE, &fnum1);
1181         if (!NT_STATUS_IS_OK(status)) {
1182                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1183                 return False;
1184         }
1185
1186         cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1187
1188         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1189                                      NULL, NULL, NULL);
1190         if (!NT_STATUS_IS_OK(status)) {
1191                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1192                 correct = False;
1193         }
1194
1195         if (fsize == sizeof(buf))
1196                 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1197                        (unsigned long)fsize);
1198         else {
1199                 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1200                        (unsigned long)fsize);
1201                 correct = False;
1202         }
1203
1204         status = cli_close(cli1, fnum1);
1205         if (!NT_STATUS_IS_OK(status)) {
1206                 printf("close failed (%s)\n", nt_errstr(status));
1207                 correct = False;
1208         }
1209
1210         if (!torture_close_connection(cli1)) {
1211                 correct = False;
1212         }
1213         return correct;
1214 }
1215
1216 static bool run_readwritelarge(int dummy)
1217 {
1218         return run_readwritelarge_internal();
1219 }
1220
1221 static bool run_readwritelarge_signtest(int dummy)
1222 {
1223         bool ret;
1224         signing_state = SMB_SIGNING_REQUIRED;
1225         ret = run_readwritelarge_internal();
1226         signing_state = SMB_SIGNING_DEFAULT;
1227         return ret;
1228 }
1229
1230 int line_count = 0;
1231 int nbio_id;
1232
1233 #define ival(s) strtol(s, NULL, 0)
1234
1235 /* run a test that simulates an approximate netbench client load */
1236 static bool run_netbench(int client)
1237 {
1238         struct cli_state *cli;
1239         int i;
1240         char line[1024];
1241         char cname[20];
1242         FILE *f;
1243         const char *params[20];
1244         bool correct = True;
1245
1246         cli = current_cli;
1247
1248         nbio_id = client;
1249
1250         smbXcli_conn_set_sockopt(cli->conn, sockops);
1251
1252         nb_setup(cli);
1253
1254         slprintf(cname,sizeof(cname)-1, "client%d", client);
1255
1256         f = fopen(client_txt, "r");
1257
1258         if (!f) {
1259                 perror(client_txt);
1260                 return False;
1261         }
1262
1263         while (fgets(line, sizeof(line)-1, f)) {
1264                 char *saveptr;
1265                 line_count++;
1266
1267                 line[strlen(line)-1] = 0;
1268
1269                 /* printf("[%d] %s\n", line_count, line); */
1270
1271                 all_string_sub(line,"client1", cname, sizeof(line));
1272
1273                 /* parse the command parameters */
1274                 params[0] = strtok_r(line, " ", &saveptr);
1275                 i = 0;
1276                 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1277
1278                 params[i] = "";
1279
1280                 if (i < 2) continue;
1281
1282                 if (!strncmp(params[0],"SMB", 3)) {
1283                         printf("ERROR: You are using a dbench 1 load file\n");
1284                         exit(1);
1285                 }
1286
1287                 if (!strcmp(params[0],"NTCreateX")) {
1288                         nb_createx(params[1], ival(params[2]), ival(params[3]),
1289                                    ival(params[4]));
1290                 } else if (!strcmp(params[0],"Close")) {
1291                         nb_close(ival(params[1]));
1292                 } else if (!strcmp(params[0],"Rename")) {
1293                         nb_rename(params[1], params[2]);
1294                 } else if (!strcmp(params[0],"Unlink")) {
1295                         nb_unlink(params[1]);
1296                 } else if (!strcmp(params[0],"Deltree")) {
1297                         nb_deltree(params[1]);
1298                 } else if (!strcmp(params[0],"Rmdir")) {
1299                         nb_rmdir(params[1]);
1300                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1301                         nb_qpathinfo(params[1]);
1302                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1303                         nb_qfileinfo(ival(params[1]));
1304                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1305                         nb_qfsinfo(ival(params[1]));
1306                 } else if (!strcmp(params[0],"FIND_FIRST")) {
1307                         nb_findfirst(params[1]);
1308                 } else if (!strcmp(params[0],"WriteX")) {
1309                         nb_writex(ival(params[1]),
1310                                   ival(params[2]), ival(params[3]), ival(params[4]));
1311                 } else if (!strcmp(params[0],"ReadX")) {
1312                         nb_readx(ival(params[1]),
1313                                   ival(params[2]), ival(params[3]), ival(params[4]));
1314                 } else if (!strcmp(params[0],"Flush")) {
1315                         nb_flush(ival(params[1]));
1316                 } else {
1317                         printf("Unknown operation %s\n", params[0]);
1318                         exit(1);
1319                 }
1320         }
1321         fclose(f);
1322
1323         nb_cleanup();
1324
1325         if (!torture_close_connection(cli)) {
1326                 correct = False;
1327         }
1328
1329         return correct;
1330 }
1331
1332
1333 /* run a test that simulates an approximate netbench client load */
1334 static bool run_nbench(int dummy)
1335 {
1336         double t;
1337         bool correct = True;
1338
1339         nbio_shmem(torture_nprocs);
1340
1341         nbio_id = -1;
1342
1343         signal(SIGALRM, nb_alarm);
1344         alarm(1);
1345         t = create_procs(run_netbench, &correct);
1346         alarm(0);
1347
1348         printf("\nThroughput %g MB/sec\n",
1349                1.0e-6 * nbio_total() / t);
1350         return correct;
1351 }
1352
1353
1354 /*
1355   This test checks for two things:
1356
1357   1) correct support for retaining locks over a close (ie. the server
1358      must not use posix semantics)
1359   2) support for lock timeouts
1360  */
1361 static bool run_locktest1(int dummy)
1362 {
1363         struct cli_state *cli1, *cli2;
1364         const char *fname = "\\lockt1.lck";
1365         uint16_t fnum1, fnum2, fnum3;
1366         time_t t1, t2;
1367         unsigned lock_timeout;
1368         NTSTATUS status;
1369
1370         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1371                 return False;
1372         }
1373         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1374         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1375
1376         printf("starting locktest1\n");
1377
1378         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1379
1380         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1381                           &fnum1);
1382         if (!NT_STATUS_IS_OK(status)) {
1383                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1384                 return False;
1385         }
1386
1387         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1388         if (!NT_STATUS_IS_OK(status)) {
1389                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1390                 return False;
1391         }
1392
1393         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1394         if (!NT_STATUS_IS_OK(status)) {
1395                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1396                 return False;
1397         }
1398
1399         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1400         if (!NT_STATUS_IS_OK(status)) {
1401                 printf("lock1 failed (%s)\n", nt_errstr(status));
1402                 return false;
1403         }
1404
1405         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1406         if (NT_STATUS_IS_OK(status)) {
1407                 printf("lock2 succeeded! This is a locking bug\n");
1408                 return false;
1409         } else {
1410                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1411                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1412                         return false;
1413                 }
1414         }
1415
1416         lock_timeout = (1 + (random() % 20));
1417         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1418         t1 = time(NULL);
1419         status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1420         if (NT_STATUS_IS_OK(status)) {
1421                 printf("lock3 succeeded! This is a locking bug\n");
1422                 return false;
1423         } else {
1424                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1425                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1426                         return false;
1427                 }
1428         }
1429         t2 = time(NULL);
1430
1431         if (ABS(t2 - t1) < lock_timeout-1) {
1432                 printf("error: This server appears not to support timed lock requests\n");
1433         }
1434
1435         printf("server slept for %u seconds for a %u second timeout\n",
1436                (unsigned int)(t2-t1), lock_timeout);
1437
1438         status = cli_close(cli1, fnum2);
1439         if (!NT_STATUS_IS_OK(status)) {
1440                 printf("close1 failed (%s)\n", nt_errstr(status));
1441                 return False;
1442         }
1443
1444         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1445         if (NT_STATUS_IS_OK(status)) {
1446                 printf("lock4 succeeded! This is a locking bug\n");
1447                 return false;
1448         } else {
1449                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1450                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1451                         return false;
1452                 }
1453         }
1454
1455         status = cli_close(cli1, fnum1);
1456         if (!NT_STATUS_IS_OK(status)) {
1457                 printf("close2 failed (%s)\n", nt_errstr(status));
1458                 return False;
1459         }
1460
1461         status = cli_close(cli2, fnum3);
1462         if (!NT_STATUS_IS_OK(status)) {
1463                 printf("close3 failed (%s)\n", nt_errstr(status));
1464                 return False;
1465         }
1466
1467         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1468         if (!NT_STATUS_IS_OK(status)) {
1469                 printf("unlink failed (%s)\n", nt_errstr(status));
1470                 return False;
1471         }
1472
1473
1474         if (!torture_close_connection(cli1)) {
1475                 return False;
1476         }
1477
1478         if (!torture_close_connection(cli2)) {
1479                 return False;
1480         }
1481
1482         printf("Passed locktest1\n");
1483         return True;
1484 }
1485
1486 /*
1487   this checks to see if a secondary tconx can use open files from an
1488   earlier tconx
1489  */
1490 static bool run_tcon_test(int dummy)
1491 {
1492         static struct cli_state *cli;
1493         const char *fname = "\\tcontest.tmp";
1494         uint16_t fnum1;
1495         uint32_t cnum1, cnum2, cnum3;
1496         struct smbXcli_tcon *orig_tcon = NULL;
1497         char *orig_share = NULL;
1498         uint16_t vuid1, vuid2;
1499         char buf[4];
1500         bool ret = True;
1501         NTSTATUS status;
1502
1503         memset(buf, '\0', sizeof(buf));
1504
1505         if (!torture_open_connection(&cli, 0)) {
1506                 return False;
1507         }
1508         smbXcli_conn_set_sockopt(cli->conn, sockops);
1509
1510         printf("starting tcontest\n");
1511
1512         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1513
1514         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1515         if (!NT_STATUS_IS_OK(status)) {
1516                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1517                 return False;
1518         }
1519
1520         cnum1 = cli_state_get_tid(cli);
1521         vuid1 = cli_state_get_uid(cli);
1522
1523         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1524         if (!NT_STATUS_IS_OK(status)) {
1525                 printf("initial write failed (%s)", nt_errstr(status));
1526                 return False;
1527         }
1528
1529         cli_state_save_tcon_share(cli, &orig_tcon, &orig_share);
1530
1531         status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1532         if (!NT_STATUS_IS_OK(status)) {
1533                 printf("%s refused 2nd tree connect (%s)\n", host,
1534                        nt_errstr(status));
1535                 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1536                 cli_shutdown(cli);
1537                 return False;
1538         }
1539
1540         cnum2 = cli_state_get_tid(cli);
1541         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1542         vuid2 = cli_state_get_uid(cli) + 1;
1543
1544         /* try a write with the wrong tid */
1545         cli_state_set_tid(cli, cnum2);
1546
1547         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1548         if (NT_STATUS_IS_OK(status)) {
1549                 printf("* server allows write with wrong TID\n");
1550                 ret = False;
1551         } else {
1552                 printf("server fails write with wrong TID : %s\n",
1553                        nt_errstr(status));
1554         }
1555
1556
1557         /* try a write with an invalid tid */
1558         cli_state_set_tid(cli, cnum3);
1559
1560         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1561         if (NT_STATUS_IS_OK(status)) {
1562                 printf("* server allows write with invalid TID\n");
1563                 ret = False;
1564         } else {
1565                 printf("server fails write with invalid TID : %s\n",
1566                        nt_errstr(status));
1567         }
1568
1569         /* try a write with an invalid vuid */
1570         cli_state_set_uid(cli, vuid2);
1571         cli_state_set_tid(cli, cnum1);
1572
1573         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1574         if (NT_STATUS_IS_OK(status)) {
1575                 printf("* server allows write with invalid VUID\n");
1576                 ret = False;
1577         } else {
1578                 printf("server fails write with invalid VUID : %s\n",
1579                        nt_errstr(status));
1580         }
1581
1582         cli_state_set_tid(cli, cnum1);
1583         cli_state_set_uid(cli, vuid1);
1584
1585         status = cli_close(cli, fnum1);
1586         if (!NT_STATUS_IS_OK(status)) {
1587                 printf("close failed (%s)\n", nt_errstr(status));
1588                 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1589                 cli_shutdown(cli);
1590                 return False;
1591         }
1592
1593         cli_state_set_tid(cli, cnum2);
1594
1595         status = cli_tdis(cli);
1596         if (!NT_STATUS_IS_OK(status)) {
1597                 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1598                 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1599                 cli_shutdown(cli);
1600                 return False;
1601         }
1602
1603         cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1604
1605         cli_state_set_tid(cli, cnum1);
1606
1607         if (!torture_close_connection(cli)) {
1608                 return False;
1609         }
1610
1611         return ret;
1612 }
1613
1614
1615 /*
1616  checks for old style tcon support
1617  */
1618 static bool run_tcon2_test(int dummy)
1619 {
1620         static struct cli_state *cli;
1621         uint16_t cnum, max_xmit;
1622         char *service;
1623         NTSTATUS status;
1624
1625         if (!torture_open_connection(&cli, 0)) {
1626                 return False;
1627         }
1628         smbXcli_conn_set_sockopt(cli->conn, sockops);
1629
1630         printf("starting tcon2 test\n");
1631
1632         if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1633                 return false;
1634         }
1635
1636         status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1637
1638         SAFE_FREE(service);
1639
1640         if (!NT_STATUS_IS_OK(status)) {
1641                 printf("tcon2 failed : %s\n", nt_errstr(status));
1642         } else {
1643                 printf("tcon OK : max_xmit=%d cnum=%d\n",
1644                        (int)max_xmit, (int)cnum);
1645         }
1646
1647         if (!torture_close_connection(cli)) {
1648                 return False;
1649         }
1650
1651         printf("Passed tcon2 test\n");
1652         return True;
1653 }
1654
1655 static bool tcon_devtest(struct cli_state *cli,
1656                          const char *myshare, const char *devtype,
1657                          const char *return_devtype,
1658                          NTSTATUS expected_error)
1659 {
1660         NTSTATUS status;
1661         bool ret;
1662
1663         status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1664
1665         if (NT_STATUS_IS_OK(expected_error)) {
1666                 if (NT_STATUS_IS_OK(status)) {
1667                         if (return_devtype != NULL &&
1668                             strequal(cli->dev, return_devtype)) {
1669                                 ret = True;
1670                         } else {
1671                                 printf("tconX to share %s with type %s "
1672                                        "succeeded but returned the wrong "
1673                                        "device type (got [%s] but should have got [%s])\n",
1674                                        myshare, devtype, cli->dev, return_devtype);
1675                                 ret = False;
1676                         }
1677                 } else {
1678                         printf("tconX to share %s with type %s "
1679                                "should have succeeded but failed\n",
1680                                myshare, devtype);
1681                         ret = False;
1682                 }
1683                 cli_tdis(cli);
1684         } else {
1685                 if (NT_STATUS_IS_OK(status)) {
1686                         printf("tconx to share %s with type %s "
1687                                "should have failed but succeeded\n",
1688                                myshare, devtype);
1689                         ret = False;
1690                 } else {
1691                         if (NT_STATUS_EQUAL(status, expected_error)) {
1692                                 ret = True;
1693                         } else {
1694                                 printf("Returned unexpected error\n");
1695                                 ret = False;
1696                         }
1697                 }
1698         }
1699         return ret;
1700 }
1701
1702 /*
1703  checks for correct tconX support
1704  */
1705 static bool run_tcon_devtype_test(int dummy)
1706 {
1707         static struct cli_state *cli1 = NULL;
1708         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1709         NTSTATUS status;
1710         bool ret = True;
1711
1712         status = cli_full_connection_creds(NULL,
1713                                            &cli1,
1714                                            myname,
1715                                            host,
1716                                            NULL, /* dest_ss */
1717                                            port_to_use,
1718                                            NULL, /* service */
1719                                            NULL, /* service_type */
1720                                            torture_creds,
1721                                            flags);
1722
1723         if (!NT_STATUS_IS_OK(status)) {
1724                 printf("could not open connection\n");
1725                 return False;
1726         }
1727
1728         if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1729                 ret = False;
1730
1731         if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1732                 ret = False;
1733
1734         if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1735                 ret = False;
1736
1737         if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1738                 ret = False;
1739
1740         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1741                 ret = False;
1742
1743         if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1744                 ret = False;
1745
1746         if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1747                 ret = False;
1748
1749         if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1750                 ret = False;
1751
1752         if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1753                 ret = False;
1754
1755         if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1756                 ret = False;
1757
1758         cli_shutdown(cli1);
1759
1760         if (ret)
1761                 printf("Passed tcondevtest\n");
1762
1763         return ret;
1764 }
1765
1766
1767 /*
1768   This test checks that
1769
1770   1) the server supports multiple locking contexts on the one SMB
1771   connection, distinguished by PID.
1772
1773   2) the server correctly fails overlapping locks made by the same PID (this
1774      goes against POSIX behaviour, which is why it is tricky to implement)
1775
1776   3) the server denies unlock requests by an incorrect client PID
1777 */
1778 static bool run_locktest2(int dummy)
1779 {
1780         static struct cli_state *cli;
1781         const char *fname = "\\lockt2.lck";
1782         uint16_t fnum1, fnum2, fnum3;
1783         bool correct = True;
1784         NTSTATUS status;
1785
1786         if (!torture_open_connection(&cli, 0)) {
1787                 return False;
1788         }
1789
1790         smbXcli_conn_set_sockopt(cli->conn, sockops);
1791
1792         printf("starting locktest2\n");
1793
1794         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1795
1796         cli_setpid(cli, 1);
1797
1798         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1799         if (!NT_STATUS_IS_OK(status)) {
1800                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1801                 return False;
1802         }
1803
1804         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1805         if (!NT_STATUS_IS_OK(status)) {
1806                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1807                 return False;
1808         }
1809
1810         cli_setpid(cli, 2);
1811
1812         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1813         if (!NT_STATUS_IS_OK(status)) {
1814                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1815                 return False;
1816         }
1817
1818         cli_setpid(cli, 1);
1819
1820         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1821         if (!NT_STATUS_IS_OK(status)) {
1822                 printf("lock1 failed (%s)\n", nt_errstr(status));
1823                 return false;
1824         }
1825
1826         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1827         if (NT_STATUS_IS_OK(status)) {
1828                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1829                 correct = false;
1830         } else {
1831                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1832                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1833                         return false;
1834                 }
1835         }
1836
1837         status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1838         if (NT_STATUS_IS_OK(status)) {
1839                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1840                 correct = false;
1841         } else {
1842                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1843                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1844                         return false;
1845                 }
1846         }
1847
1848         status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1849         if (NT_STATUS_IS_OK(status)) {
1850                 printf("READ lock2 succeeded! This is a locking bug\n");
1851                 correct = false;
1852         } else {
1853                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1854                                  NT_STATUS_FILE_LOCK_CONFLICT)) {
1855                         return false;
1856                 }
1857         }
1858
1859         status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1860         if (!NT_STATUS_IS_OK(status)) {
1861                 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1862         }
1863         cli_setpid(cli, 2);
1864         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1865                 printf("unlock at 100 succeeded! This is a locking bug\n");
1866                 correct = False;
1867         }
1868
1869         status = cli_unlock(cli, fnum1, 0, 4);
1870         if (NT_STATUS_IS_OK(status)) {
1871                 printf("unlock1 succeeded! This is a locking bug\n");
1872                 correct = false;
1873         } else {
1874                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1875                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1876                         return false;
1877                 }
1878         }
1879
1880         status = cli_unlock(cli, fnum1, 0, 8);
1881         if (NT_STATUS_IS_OK(status)) {
1882                 printf("unlock2 succeeded! This is a locking bug\n");
1883                 correct = false;
1884         } else {
1885                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1886                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1887                         return false;
1888                 }
1889         }
1890
1891         status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1892         if (NT_STATUS_IS_OK(status)) {
1893                 printf("lock3 succeeded! This is a locking bug\n");
1894                 correct = false;
1895         } else {
1896                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1897                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1898                         return false;
1899                 }
1900         }
1901
1902         cli_setpid(cli, 1);
1903
1904         status = cli_close(cli, fnum1);
1905         if (!NT_STATUS_IS_OK(status)) {
1906                 printf("close1 failed (%s)\n", nt_errstr(status));
1907                 return False;
1908         }
1909
1910         status = cli_close(cli, fnum2);
1911         if (!NT_STATUS_IS_OK(status)) {
1912                 printf("close2 failed (%s)\n", nt_errstr(status));
1913                 return False;
1914         }
1915
1916         status = cli_close(cli, fnum3);
1917         if (!NT_STATUS_IS_OK(status)) {
1918                 printf("close3 failed (%s)\n", nt_errstr(status));
1919                 return False;
1920         }
1921
1922         if (!torture_close_connection(cli)) {
1923                 correct = False;
1924         }
1925
1926         printf("locktest2 finished\n");
1927
1928         return correct;
1929 }
1930
1931
1932 /*
1933   This test checks that
1934
1935   1) the server supports the full offset range in lock requests
1936 */
1937 static bool run_locktest3(int dummy)
1938 {
1939         static struct cli_state *cli1, *cli2;
1940         const char *fname = "\\lockt3.lck";
1941         uint16_t fnum1, fnum2;
1942         int i;
1943         uint32_t offset;
1944         bool correct = True;
1945         NTSTATUS status;
1946
1947 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1948
1949         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1950                 return False;
1951         }
1952         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1953         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1954
1955         printf("starting locktest3\n");
1956
1957         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1958
1959         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1960                          &fnum1);
1961         if (!NT_STATUS_IS_OK(status)) {
1962                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1963                 return False;
1964         }
1965
1966         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1967         if (!NT_STATUS_IS_OK(status)) {
1968                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1969                 return False;
1970         }
1971
1972         for (offset=i=0;i<torture_numops;i++) {
1973                 NEXT_OFFSET;
1974
1975                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1976                 if (!NT_STATUS_IS_OK(status)) {
1977                         printf("lock1 %d failed (%s)\n",
1978                                i,
1979                                nt_errstr(status));
1980                         return False;
1981                 }
1982
1983                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1984                 if (!NT_STATUS_IS_OK(status)) {
1985                         printf("lock2 %d failed (%s)\n",
1986                                i,
1987                                nt_errstr(status));
1988                         return False;
1989                 }
1990         }
1991
1992         for (offset=i=0;i<torture_numops;i++) {
1993                 NEXT_OFFSET;
1994
1995                 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1996                 if (NT_STATUS_IS_OK(status)) {
1997                         printf("error: lock1 %d succeeded!\n", i);
1998                         return False;
1999                 }
2000
2001                 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
2002                 if (NT_STATUS_IS_OK(status)) {
2003                         printf("error: lock2 %d succeeded!\n", i);
2004                         return False;
2005                 }
2006
2007                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
2008                 if (NT_STATUS_IS_OK(status)) {
2009                         printf("error: lock3 %d succeeded!\n", i);
2010                         return False;
2011                 }
2012
2013                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
2014                 if (NT_STATUS_IS_OK(status)) {
2015                         printf("error: lock4 %d succeeded!\n", i);
2016                         return False;
2017                 }
2018         }
2019
2020         for (offset=i=0;i<torture_numops;i++) {
2021                 NEXT_OFFSET;
2022
2023                 status = cli_unlock(cli1, fnum1, offset-1, 1);
2024                 if (!NT_STATUS_IS_OK(status)) {
2025                         printf("unlock1 %d failed (%s)\n",
2026                                i,
2027                                nt_errstr(status));
2028                         return False;
2029                 }
2030
2031                 status = cli_unlock(cli2, fnum2, offset-2, 1);
2032                 if (!NT_STATUS_IS_OK(status)) {
2033                         printf("unlock2 %d failed (%s)\n",
2034                                i,
2035                                nt_errstr(status));
2036                         return False;
2037                 }
2038         }
2039
2040         status = cli_close(cli1, fnum1);
2041         if (!NT_STATUS_IS_OK(status)) {
2042                 printf("close1 failed (%s)\n", nt_errstr(status));
2043                 return False;
2044         }
2045
2046         status = cli_close(cli2, fnum2);
2047         if (!NT_STATUS_IS_OK(status)) {
2048                 printf("close2 failed (%s)\n", nt_errstr(status));
2049                 return False;
2050         }
2051
2052         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2053         if (!NT_STATUS_IS_OK(status)) {
2054                 printf("unlink failed (%s)\n", nt_errstr(status));
2055                 return False;
2056         }
2057
2058         if (!torture_close_connection(cli1)) {
2059                 correct = False;
2060         }
2061
2062         if (!torture_close_connection(cli2)) {
2063                 correct = False;
2064         }
2065
2066         printf("finished locktest3\n");
2067
2068         return correct;
2069 }
2070
2071 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
2072                            char *buf, off_t offset, size_t size,
2073                            size_t *nread, size_t expect)
2074 {
2075         NTSTATUS status;
2076         size_t l_nread;
2077
2078         status = cli_read(cli, fnum, buf, offset, size, &l_nread);
2079
2080         if(!NT_STATUS_IS_OK(status)) {
2081                 return false;
2082         } else if (l_nread != expect) {
2083                 return false;
2084         }
2085
2086         if (nread) {
2087                 *nread = l_nread;
2088         }
2089
2090         return true;
2091 }
2092
2093 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2094         printf("** "); correct = False; \
2095         }
2096
2097 /*
2098   looks at overlapping locks
2099 */
2100 static bool run_locktest4(int dummy)
2101 {
2102         static struct cli_state *cli1, *cli2;
2103         const char *fname = "\\lockt4.lck";
2104         uint16_t fnum1, fnum2, f;
2105         bool ret;
2106         char buf[1000];
2107         bool correct = True;
2108         NTSTATUS status;
2109
2110         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2111                 return False;
2112         }
2113
2114         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2115         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2116
2117         printf("starting locktest4\n");
2118
2119         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2120
2121         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2122         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2123
2124         memset(buf, 0, sizeof(buf));
2125
2126         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2127                               NULL);
2128         if (!NT_STATUS_IS_OK(status)) {
2129                 printf("Failed to create file: %s\n", nt_errstr(status));
2130                 correct = False;
2131                 goto fail;
2132         }
2133
2134         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2135               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
2136         EXPECTED(ret, False);
2137         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2138
2139         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2140               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2141         EXPECTED(ret, True);
2142         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2143
2144         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2145               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2146         EXPECTED(ret, False);
2147         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2148
2149         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2150               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2151         EXPECTED(ret, True);
2152         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2153
2154         ret = (cli_setpid(cli1, 1),
2155               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2156               (cli_setpid(cli1, 2),
2157               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2158         EXPECTED(ret, False);
2159         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2160
2161         ret = (cli_setpid(cli1, 1),
2162               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2163               (cli_setpid(cli1, 2),
2164               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2165         EXPECTED(ret, True);
2166         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2167
2168         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2169               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2170         EXPECTED(ret, True);
2171         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2172
2173         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2174               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2175         EXPECTED(ret, False);
2176         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2177
2178         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2179               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2180         EXPECTED(ret, False);
2181         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2182
2183         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2184               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2185         EXPECTED(ret, True);
2186         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2187
2188         ret = (cli_setpid(cli1, 1),
2189              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2190              (cli_setpid(cli1, 2),
2191              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2192         EXPECTED(ret, False);
2193         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2194
2195         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2196               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2197               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2198         EXPECTED(ret, False);
2199         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2200
2201
2202         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2203               test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2204         EXPECTED(ret, False);
2205         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2206
2207         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2208         ret = NT_STATUS_IS_OK(status);
2209         if (ret) {
2210                 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2211                                       NULL);
2212                 ret = NT_STATUS_IS_OK(status);
2213         }
2214         EXPECTED(ret, False);
2215         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2216
2217
2218         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2219               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2220               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2221               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2222         EXPECTED(ret, True);
2223         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2224
2225
2226         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2227               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2228               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2229               test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2230               !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2231                                              150, 4, NULL))) &&
2232               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2233         EXPECTED(ret, True);
2234         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2235
2236         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2237               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2238               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2239                                            160, 4, NULL)) &&
2240               test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2241         EXPECTED(ret, True);
2242         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2243
2244         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2245               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2246               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2247                                            170, 4, NULL)) &&
2248               test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2249         EXPECTED(ret, True);
2250         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2251
2252         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2253               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2254               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2255               !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2256                                             190, 4, NULL)) &&
2257               test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2258         EXPECTED(ret, True);
2259         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2260
2261         cli_close(cli1, fnum1);
2262         cli_close(cli2, fnum2);
2263         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2264         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2265         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2266               NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2267               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2268               NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2269               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2270         cli_close(cli1, f);
2271         cli_close(cli1, fnum1);
2272         EXPECTED(ret, True);
2273         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2274
2275  fail:
2276         cli_close(cli1, fnum1);
2277         cli_close(cli2, fnum2);
2278         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2279         torture_close_connection(cli1);
2280         torture_close_connection(cli2);
2281
2282         printf("finished locktest4\n");
2283         return correct;
2284 }
2285
2286 /*
2287   looks at lock upgrade/downgrade.
2288 */
2289 static bool run_locktest5(int dummy)
2290 {
2291         static struct cli_state *cli1, *cli2;
2292         const char *fname = "\\lockt5.lck";
2293         uint16_t fnum1, fnum2, fnum3;
2294         bool ret;
2295         char buf[1000];
2296         bool correct = True;
2297         NTSTATUS status;
2298
2299         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2300                 return False;
2301         }
2302
2303         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2304         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2305
2306         printf("starting locktest5\n");
2307
2308         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2309
2310         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2311         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2312         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2313
2314         memset(buf, 0, sizeof(buf));
2315
2316         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2317                               NULL);
2318         if (!NT_STATUS_IS_OK(status)) {
2319                 printf("Failed to create file: %s\n", nt_errstr(status));
2320                 correct = False;
2321                 goto fail;
2322         }
2323
2324         /* Check for NT bug... */
2325         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2326               NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2327         cli_close(cli1, fnum1);
2328         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2329         status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2330         ret = NT_STATUS_IS_OK(status);
2331         EXPECTED(ret, True);
2332         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2333         cli_close(cli1, fnum1);
2334         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2335         cli_unlock(cli1, fnum3, 0, 1);
2336
2337         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2338               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2339         EXPECTED(ret, True);
2340         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2341
2342         status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2343         ret = NT_STATUS_IS_OK(status);
2344         EXPECTED(ret, False);
2345
2346         printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2347
2348         /* Unlock the process 2 lock. */
2349         cli_unlock(cli2, fnum2, 0, 4);
2350
2351         status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2352         ret = NT_STATUS_IS_OK(status);
2353         EXPECTED(ret, False);
2354
2355         printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2356
2357         /* Unlock the process 1 fnum3 lock. */
2358         cli_unlock(cli1, fnum3, 0, 4);
2359
2360         /* Stack 2 more locks here. */
2361         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2362               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2363
2364         EXPECTED(ret, True);
2365         printf("the same process %s stack read locks\n", ret?"can":"cannot");
2366
2367         /* Unlock the first process lock, then check this was the WRITE lock that was
2368                 removed. */
2369
2370         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2371               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2372
2373         EXPECTED(ret, True);
2374         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2375
2376         /* Unlock the process 2 lock. */
2377         cli_unlock(cli2, fnum2, 0, 4);
2378
2379         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2380
2381         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2382                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2383                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2384
2385         EXPECTED(ret, True);
2386         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2387
2388         /* Ensure the next unlock fails. */
2389         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2390         EXPECTED(ret, False);
2391         printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2392
2393         /* Ensure connection 2 can get a write lock. */
2394         status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2395         ret = NT_STATUS_IS_OK(status);
2396         EXPECTED(ret, True);
2397
2398         printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2399
2400
2401  fail:
2402         cli_close(cli1, fnum1);
2403         cli_close(cli2, fnum2);
2404         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2405         if (!torture_close_connection(cli1)) {
2406                 correct = False;
2407         }
2408         if (!torture_close_connection(cli2)) {
2409                 correct = False;
2410         }
2411
2412         printf("finished locktest5\n");
2413
2414         return correct;
2415 }
2416
2417 /*
2418   tries the unusual lockingX locktype bits
2419 */
2420 static bool run_locktest6(int dummy)
2421 {
2422         static struct cli_state *cli;
2423         const char *fname[1] = { "\\lock6.txt" };
2424         int i;
2425         uint16_t fnum;
2426         NTSTATUS status;
2427
2428         if (!torture_open_connection(&cli, 0)) {
2429                 return False;
2430         }
2431
2432         smbXcli_conn_set_sockopt(cli->conn, sockops);
2433
2434         printf("starting locktest6\n");
2435
2436         for (i=0;i<1;i++) {
2437                 printf("Testing %s\n", fname[i]);
2438
2439                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2440
2441                 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2442                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2443                 cli_close(cli, fnum);
2444                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2445
2446                 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2447                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2448                 cli_close(cli, fnum);
2449                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2450
2451                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2452         }
2453
2454         torture_close_connection(cli);
2455
2456         printf("finished locktest6\n");
2457         return True;
2458 }
2459
2460 static bool run_locktest7(int dummy)
2461 {
2462         struct cli_state *cli1;
2463         const char *fname = "\\lockt7.lck";
2464         uint16_t fnum1;
2465         char buf[200];
2466         bool correct = False;
2467         size_t nread;
2468         NTSTATUS status;
2469
2470         if (!torture_open_connection(&cli1, 0)) {
2471                 return False;
2472         }
2473
2474         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2475
2476         printf("starting locktest7\n");
2477
2478         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2479
2480         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2481
2482         memset(buf, 0, sizeof(buf));
2483
2484         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2485                               NULL);
2486         if (!NT_STATUS_IS_OK(status)) {
2487                 printf("Failed to create file: %s\n", nt_errstr(status));
2488                 goto fail;
2489         }
2490
2491         cli_setpid(cli1, 1);
2492
2493         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2494         if (!NT_STATUS_IS_OK(status)) {
2495                 printf("Unable to apply read lock on range 130:4, "
2496                        "error was %s\n", nt_errstr(status));
2497                 goto fail;
2498         } else {
2499                 printf("pid1 successfully locked range 130:4 for READ\n");
2500         }
2501
2502         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2503         if (!NT_STATUS_IS_OK(status)) {
2504                 printf("pid1 unable to read the range 130:4, error was %s\n",
2505                       nt_errstr(status));
2506                 goto fail;
2507         } else if (nread != 4) {
2508                 printf("pid1 unable to read the range 130:4, "
2509                        "recv %ld req %d\n", (unsigned long)nread, 4);
2510                 goto fail;
2511         } else {
2512                 printf("pid1 successfully read the range 130:4\n");
2513         }
2514
2515         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2516         if (!NT_STATUS_IS_OK(status)) {
2517                 printf("pid1 unable to write to the range 130:4, error was "
2518                        "%s\n", nt_errstr(status));
2519                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2520                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2521                         goto fail;
2522                 }
2523         } else {
2524                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2525                 goto fail;
2526         }
2527
2528         cli_setpid(cli1, 2);
2529
2530         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2531         if (!NT_STATUS_IS_OK(status)) {
2532                 printf("pid2 unable to read the range 130:4, error was %s\n",
2533                       nt_errstr(status));
2534                 goto fail;
2535         } else if (nread != 4) {
2536                 printf("pid2 unable to read the range 130:4, "
2537                        "recv %ld req %d\n", (unsigned long)nread, 4);
2538                 goto fail;
2539         } else {
2540                 printf("pid2 successfully read the range 130:4\n");
2541         }
2542
2543         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2544         if (!NT_STATUS_IS_OK(status)) {
2545                 printf("pid2 unable to write to the range 130:4, error was "
2546                        "%s\n", nt_errstr(status));
2547                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2548                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2549                         goto fail;
2550                 }
2551         } else {
2552                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2553                 goto fail;
2554         }
2555
2556         cli_setpid(cli1, 1);
2557         cli_unlock(cli1, fnum1, 130, 4);
2558
2559         status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2560         if (!NT_STATUS_IS_OK(status)) {
2561                 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2562                 goto fail;
2563         } else {
2564                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2565         }
2566
2567         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2568         if (!NT_STATUS_IS_OK(status)) {
2569                 printf("pid1 unable to read the range 130:4, error was %s\n",
2570                       nt_errstr(status));
2571                 goto fail;
2572         } else if (nread != 4) {
2573                 printf("pid1 unable to read the range 130:4, "
2574                        "recv %ld req %d\n", (unsigned long)nread, 4);
2575                 goto fail;
2576         } else {
2577                 printf("pid1 successfully read the range 130:4\n");
2578         }
2579
2580         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2581         if (!NT_STATUS_IS_OK(status)) {
2582                 printf("pid1 unable to write to the range 130:4, error was "
2583                        "%s\n", nt_errstr(status));
2584                 goto fail;
2585         } else {
2586                 printf("pid1 successfully wrote to the range 130:4\n");
2587         }
2588
2589         cli_setpid(cli1, 2);
2590
2591         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2592         if (!NT_STATUS_IS_OK(status)) {
2593                 printf("pid2 unable to read the range 130:4, error was "
2594                        "%s\n", nt_errstr(status));
2595                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2596                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2597                         goto fail;
2598                 }
2599         } else {
2600                 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2601                        (unsigned long)nread);
2602                 goto fail;
2603         }
2604
2605         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2606         if (!NT_STATUS_IS_OK(status)) {
2607                 printf("pid2 unable to write to the range 130:4, error was "
2608                        "%s\n", nt_errstr(status));
2609                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2610                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2611                         goto fail;
2612                 }
2613         } else {
2614                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2615                 goto fail;
2616         }
2617
2618         cli_unlock(cli1, fnum1, 130, 0);
2619         correct = True;
2620
2621 fail:
2622         cli_close(cli1, fnum1);
2623         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2624         torture_close_connection(cli1);
2625
2626         printf("finished locktest7\n");
2627         return correct;
2628 }
2629
2630 /*
2631  * This demonstrates a problem with our use of GPFS share modes: A file
2632  * descriptor sitting in the pending close queue holding a GPFS share mode
2633  * blocks opening a file another time. Happens with Word 2007 temp files.
2634  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2635  * open is denied with NT_STATUS_SHARING_VIOLATION.
2636  */
2637
2638 static bool run_locktest8(int dummy)
2639 {
2640         struct cli_state *cli1;
2641         const char *fname = "\\lockt8.lck";
2642         uint16_t fnum1, fnum2;
2643         char buf[200];
2644         bool correct = False;
2645         NTSTATUS status;
2646
2647         if (!torture_open_connection(&cli1, 0)) {
2648                 return False;
2649         }
2650
2651         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2652
2653         printf("starting locktest8\n");
2654
2655         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2656
2657         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2658                           &fnum1);
2659         if (!NT_STATUS_IS_OK(status)) {
2660                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2661                 return false;
2662         }
2663
2664         memset(buf, 0, sizeof(buf));
2665
2666         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2667         if (!NT_STATUS_IS_OK(status)) {
2668                 d_fprintf(stderr, "cli_openx second time returned %s\n",
2669                           nt_errstr(status));
2670                 goto fail;
2671         }
2672
2673         status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2674         if (!NT_STATUS_IS_OK(status)) {
2675                 printf("Unable to apply read lock on range 1:1, error was "
2676                        "%s\n", nt_errstr(status));
2677                 goto fail;
2678         }
2679
2680         status = cli_close(cli1, fnum1);
2681         if (!NT_STATUS_IS_OK(status)) {
2682                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2683                 goto fail;
2684         }
2685
2686         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2687         if (!NT_STATUS_IS_OK(status)) {
2688                 d_fprintf(stderr, "cli_openx third time returned %s\n",
2689                           nt_errstr(status));
2690                 goto fail;
2691         }
2692
2693         correct = true;
2694
2695 fail:
2696         cli_close(cli1, fnum1);
2697         cli_close(cli1, fnum2);
2698         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2699         torture_close_connection(cli1);
2700
2701         printf("finished locktest8\n");
2702         return correct;
2703 }
2704
2705 /*
2706  * This test is designed to be run in conjunction with
2707  * external NFS or POSIX locks taken in the filesystem.
2708  * It checks that the smbd server will block until the
2709  * lock is released and then acquire it. JRA.
2710  */
2711
2712 static bool got_alarm;
2713 static struct cli_state *alarm_cli;
2714
2715 static void alarm_handler(int dummy)
2716 {
2717         got_alarm = True;
2718 }
2719
2720 static void alarm_handler_parent(int dummy)
2721 {
2722         smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2723 }
2724
2725 static void do_local_lock(const char *fname, int read_fd, int write_fd)
2726 {
2727         int fd;
2728         char c = '\0';
2729         struct flock lock;
2730         const char *local_pathname = NULL;
2731         int ret;
2732
2733         local_pathname = talloc_asprintf(talloc_tos(),
2734                         "%s/%s", local_path, fname);
2735         if (!local_pathname) {
2736                 printf("child: alloc fail\n");
2737                 exit(1);
2738         }
2739
2740         unlink(local_pathname);
2741         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2742         if (fd == -1) {
2743                 printf("child: open of %s failed %s.\n",
2744                         local_pathname, strerror(errno));
2745                 exit(1);
2746         }
2747
2748         /* Now take a fcntl lock. */
2749         lock.l_type = F_WRLCK;
2750         lock.l_whence = SEEK_SET;
2751         lock.l_start = 0;
2752         lock.l_len = 4;
2753         lock.l_pid = getpid();
2754
2755         ret = fcntl(fd,F_SETLK,&lock);
2756         if (ret == -1) {
2757                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2758                         local_pathname, strerror(errno));
2759                 exit(1);
2760         } else {
2761                 printf("child: got lock 0:4 on file %s.\n",
2762                         local_pathname );
2763                 fflush(stdout);
2764         }
2765
2766         CatchSignal(SIGALRM, alarm_handler);
2767         alarm(5);
2768         /* Signal the parent. */
2769         if (write(write_fd, &c, 1) != 1) {
2770                 printf("child: start signal fail %s.\n",
2771                         strerror(errno));
2772                 exit(1);
2773         }
2774         alarm(0);
2775
2776         alarm(10);
2777         /* Wait for the parent to be ready. */
2778         if (read(read_fd, &c, 1) != 1) {
2779                 printf("child: reply signal fail %s.\n",
2780                         strerror(errno));
2781                 exit(1);
2782         }
2783         alarm(0);
2784
2785         sleep(5);
2786         close(fd);
2787         printf("child: released lock 0:4 on file %s.\n",
2788                 local_pathname );
2789         fflush(stdout);
2790         exit(0);
2791 }
2792
2793 static bool _run_locktest9X(const char *fname, int timeout)
2794 {
2795         struct cli_state *cli1;
2796         char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2797         uint16_t fnum;
2798         bool correct = False;
2799         int pipe_in[2], pipe_out[2];
2800         pid_t child_pid;
2801         char c = '\0';
2802         int ret;
2803         struct timeval start;
2804         double seconds;
2805         NTSTATUS status;
2806
2807         printf("starting locktest9X: %s\n", fname);
2808
2809         if (local_path == NULL) {
2810                 d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2811                 return false;
2812         }
2813
2814         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2815                 return false;
2816         }
2817
2818         child_pid = fork();
2819         if (child_pid == -1) {
2820                 return false;
2821         }
2822
2823         if (child_pid == 0) {
2824                 /* Child. */
2825                 do_local_lock(fname, pipe_out[0], pipe_in[1]);
2826                 exit(0);
2827         }
2828
2829         close(pipe_out[0]);
2830         close(pipe_in[1]);
2831         pipe_out[0] = -1;
2832         pipe_in[1] = -1;
2833
2834         /* Parent. */
2835         ret = read(pipe_in[0], &c, 1);
2836         if (ret != 1) {
2837                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2838                         strerror(errno));
2839                 return false;
2840         }
2841
2842         if (!torture_open_connection(&cli1, 0)) {
2843                 return false;
2844         }
2845
2846         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2847
2848         status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2849                           &fnum);
2850         if (!NT_STATUS_IS_OK(status)) {
2851                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2852                 return false;
2853         }
2854
2855         /* Ensure the child has the lock. */
2856         status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2857         if (NT_STATUS_IS_OK(status)) {
2858                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2859                 goto fail;
2860         } else {
2861                 d_printf("Child has the lock.\n");
2862         }
2863
2864         /* Tell the child to wait 5 seconds then exit. */
2865         ret = write(pipe_out[1], &c, 1);
2866         if (ret != 1) {
2867                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2868                         strerror(errno));
2869                 goto fail;
2870         }
2871
2872         /* Wait 20 seconds for the lock. */
2873         alarm_cli = cli1;
2874         CatchSignal(SIGALRM, alarm_handler_parent);
2875         alarm(20);
2876
2877         start = timeval_current();
2878
2879         status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2880         if (!NT_STATUS_IS_OK(status)) {
2881                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2882                        "%s\n", nt_errstr(status));
2883                 goto fail_nofd;
2884         }
2885         alarm(0);
2886
2887         seconds = timeval_elapsed(&start);
2888
2889         printf("Parent got the lock after %.2f seconds.\n",
2890                 seconds);
2891
2892         status = cli_close(cli1, fnum);
2893         if (!NT_STATUS_IS_OK(status)) {
2894                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2895                 goto fail;
2896         }
2897
2898         correct = true;
2899
2900 fail:
2901         cli_close(cli1, fnum);
2902         torture_close_connection(cli1);
2903
2904 fail_nofd:
2905
2906         printf("finished locktest9X: %s\n", fname);
2907         return correct;
2908 }
2909
2910 static bool run_locktest9a(int dummy)
2911 {
2912         return _run_locktest9X("lock9a.dat", -1);
2913 }
2914
2915 static bool run_locktest9b(int dummy)
2916 {
2917         return _run_locktest9X("lock9b.dat", 10000);
2918 }
2919
2920 struct locktest10_state {
2921         bool ok;
2922         bool done;
2923 };
2924
2925 static void locktest10_lockingx_done(struct tevent_req *subreq);
2926 static void locktest10_read_andx_done(struct tevent_req *subreq);
2927
2928 static bool run_locktest10(int dummy)
2929 {
2930         struct tevent_context *ev = NULL;
2931         struct cli_state *cli1 = NULL;
2932         struct cli_state *cli2 = NULL;
2933         struct smb1_lock_element lck = { 0 };
2934         struct tevent_req *reqs[2] = { NULL };
2935         struct tevent_req *smbreqs[2] = { NULL };
2936         const char fname[] = "\\lockt10.lck";
2937         uint16_t fnum1, fnum2;
2938         bool ret = false;
2939         bool ok;
2940         uint8_t data = 1;
2941         struct locktest10_state state = { .ok = true };
2942         NTSTATUS status;
2943
2944         printf("starting locktest10\n");
2945
2946         ev = samba_tevent_context_init(NULL);
2947         if (ev == NULL) {
2948                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2949                 goto done;
2950         }
2951
2952         ok = torture_open_connection(&cli1, 0);
2953         if (!ok) {
2954                 goto done;
2955         }
2956         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2957
2958         ok = torture_open_connection(&cli2, 1);
2959         if (!ok) {
2960                 goto done;
2961         }
2962         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2963
2964         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2965         if (!NT_STATUS_IS_OK(status)) {
2966                 d_fprintf(stderr,
2967                           "cli_openx failed: %s\n",
2968                           nt_errstr(status));
2969                 goto done;
2970         }
2971
2972         status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2973         if (!NT_STATUS_IS_OK(status)) {
2974                 d_fprintf(stderr,
2975                           "cli_writeall failed: %s\n",
2976                           nt_errstr(status));
2977                 goto done;
2978         }
2979
2980         status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2981         if (!NT_STATUS_IS_OK(status)) {
2982                 d_fprintf(stderr,
2983                           "cli_openx failed: %s\n",
2984                           nt_errstr(status));
2985                 goto done;
2986         }
2987
2988         status = cli_locktype(
2989                 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2990         if (!NT_STATUS_IS_OK(status)) {
2991                 d_fprintf(stderr,
2992                           "cli_locktype failed: %s\n",
2993                           nt_errstr(status));
2994                 goto done;
2995         }
2996
2997         lck = (struct smb1_lock_element) {
2998                 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2999         };
3000
3001         reqs[0] = cli_lockingx_create(
3002                 ev,                             /* mem_ctx */
3003                 ev,                             /* tevent_context */
3004                 cli1,                           /* cli */
3005                 fnum1,                          /* fnum */
3006                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3007                 0,                              /* newoplocklevel */
3008                 1,                              /* timeout */
3009                 0,                              /* num_unlocks */
3010                 NULL,                           /* unlocks */
3011                 1,                              /* num_locks */
3012                 &lck,                           /* locks */
3013                 &smbreqs[0]);                   /* psmbreq */
3014         if (reqs[0] == NULL) {
3015                 d_fprintf(stderr, "cli_lockingx_create failed\n");
3016                 goto done;
3017         }
3018         tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
3019
3020         reqs[1] = cli_read_andx_create(
3021                 ev,             /* mem_ctx */
3022                 ev,             /* ev */
3023                 cli1,           /* cli */
3024                 fnum1,          /* fnum */
3025                 0,              /* offset */
3026                 1,              /* size */
3027                 &smbreqs[1]);   /* psmbreq */
3028         if (reqs[1] == NULL) {
3029                 d_fprintf(stderr, "cli_read_andx_create failed\n");
3030                 goto done;
3031         }
3032         tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
3033
3034         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
3035         if (!NT_STATUS_IS_OK(status)) {
3036                 d_fprintf(stderr,
3037                           "smb1cli_req_chain_submit failed: %s\n",
3038                           nt_errstr(status));
3039                 goto done;
3040         }
3041
3042         while (!state.done) {
3043                 tevent_loop_once(ev);
3044         }
3045
3046         torture_close_connection(cli1);
3047
3048         if (state.ok) {
3049                 ret = true;
3050         }
3051 done:
3052         return ret;
3053 }
3054
3055 static void locktest10_lockingx_done(struct tevent_req *subreq)
3056 {
3057         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3058         NTSTATUS status;
3059
3060         status = cli_lockingx_recv(subreq);
3061         TALLOC_FREE(subreq);
3062
3063         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3064                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3065                 state->ok = false;
3066         }
3067 }
3068
3069 static void locktest10_read_andx_done(struct tevent_req *subreq)
3070 {
3071         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3072         ssize_t received = -1;
3073         uint8_t *rcvbuf = NULL;
3074         NTSTATUS status;
3075
3076         status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3077
3078         if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
3079                 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
3080                 state->ok = false;
3081         }
3082
3083         state->done = true;
3084         TALLOC_FREE(subreq);
3085 }
3086
3087 static bool run_locktest11(int dummy)
3088 {
3089         struct cli_state *cli1;
3090         const char *fname = "\\lockt11.lck";
3091         NTSTATUS status;
3092         uint16_t fnum;
3093         bool ret = false;
3094
3095         if (!torture_open_connection(&cli1, 0)) {
3096                 return false;
3097         }
3098
3099         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3100
3101         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3102
3103         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
3104         if (!NT_STATUS_IS_OK(status)) {
3105                 d_fprintf(stderr,
3106                           "cli_openx returned %s\n",
3107                           nt_errstr(status));
3108                 return false;
3109         }
3110
3111         /*
3112          * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3113          * returns NT_STATUS_OK
3114          */
3115
3116         status = cli_lockingx(
3117                 cli1,                           /* cli */
3118                 fnum,                           /* fnum */
3119                 LOCKING_ANDX_CANCEL_LOCK,       /* typeoflock */
3120                 0,                              /* newoplocklevel */
3121                 0,                              /* timeout */
3122                 0,                              /* num_unlocks */
3123                 NULL,                           /* unlocks */
3124                 0,                              /* num_locks */
3125                 NULL);                          /* locks */
3126
3127         if (!NT_STATUS_IS_OK(status)) {
3128                 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
3129                 goto fail;
3130         }
3131
3132         ret = true;
3133 fail:
3134         cli_close(cli1, fnum);
3135         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3136
3137         return ret;
3138 }
3139
3140 struct deferred_close_state {
3141         struct tevent_context *ev;
3142         struct cli_state *cli;
3143         uint16_t fnum;
3144 };
3145
3146 static void deferred_close_waited(struct tevent_req *subreq);
3147 static void deferred_close_done(struct tevent_req *subreq);
3148
3149 static struct tevent_req *deferred_close_send(
3150         TALLOC_CTX *mem_ctx,
3151         struct tevent_context *ev,
3152         int wait_secs,
3153         struct cli_state *cli,
3154         uint16_t fnum)
3155 {
3156         struct tevent_req *req = NULL, *subreq = NULL;
3157         struct deferred_close_state *state = NULL;
3158         struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
3159
3160         req = tevent_req_create(
3161                 mem_ctx, &state, struct deferred_close_state);
3162         if (req == NULL) {
3163                 return NULL;
3164         }
3165         state->ev = ev;
3166         state->cli = cli;
3167         state->fnum = fnum;
3168
3169         subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
3170         if (tevent_req_nomem(subreq, req)) {
3171                 return tevent_req_post(req, ev);
3172         }
3173         tevent_req_set_callback(subreq, deferred_close_waited, req);
3174         return req;
3175 }
3176
3177 static void deferred_close_waited(struct tevent_req *subreq)
3178 {
3179         struct tevent_req *req = tevent_req_callback_data(
3180                 subreq, struct tevent_req);
3181         struct deferred_close_state *state = tevent_req_data(
3182                 req, struct deferred_close_state);
3183         bool ok;
3184
3185         ok = tevent_wakeup_recv(subreq);
3186         TALLOC_FREE(subreq);
3187         if (!ok) {
3188                 tevent_req_oom(req);
3189                 return;
3190         }
3191
3192         subreq = cli_close_send(state, state->ev, state->cli, state->fnum, 0);
3193         if (tevent_req_nomem(subreq, req)) {
3194                 return;
3195         }
3196         tevent_req_set_callback(subreq, deferred_close_done, req);
3197 }
3198
3199 static void deferred_close_done(struct tevent_req *subreq)
3200 {
3201         NTSTATUS status = cli_close_recv(subreq);
3202         tevent_req_simple_finish_ntstatus(subreq, status);
3203 }
3204
3205 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3206 {
3207         return tevent_req_simple_recv_ntstatus(req);
3208 }
3209
3210 struct lockread_state {
3211         struct smb1_lock_element lck;
3212         struct tevent_req *reqs[2];
3213         struct tevent_req *smbreqs[2];
3214         NTSTATUS lock_status;
3215         NTSTATUS read_status;
3216         uint8_t *readbuf;
3217 };
3218
3219 static void lockread_lockingx_done(struct tevent_req *subreq);
3220 static void lockread_read_andx_done(struct tevent_req *subreq);
3221
3222 static struct tevent_req *lockread_send(
3223         TALLOC_CTX *mem_ctx,
3224         struct tevent_context *ev,
3225         struct cli_state *cli,
3226         uint16_t fnum)
3227 {
3228         struct tevent_req *req = NULL;
3229         struct lockread_state *state = NULL;
3230         NTSTATUS status;
3231
3232         req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3233         if (req == NULL) {
3234                 return NULL;
3235         }
3236
3237         state->lck = (struct smb1_lock_element) {
3238                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3239         };
3240
3241         state->reqs[0] = cli_lockingx_create(
3242                 ev,                             /* mem_ctx */
3243                 ev,                             /* tevent_context */
3244                 cli,                            /* cli */
3245                 fnum,                           /* fnum */
3246                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3247                 0,                              /* newoplocklevel */
3248                 10000,                          /* timeout */
3249                 0,                              /* num_unlocks */
3250                 NULL,                           /* unlocks */
3251                 1,                              /* num_locks */
3252                 &state->lck,                    /* locks */
3253                 &state->smbreqs[0]);            /* psmbreq */
3254         if (tevent_req_nomem(state->reqs[0], req)) {
3255                 return tevent_req_post(req, ev);
3256         }
3257         tevent_req_set_callback(
3258                 state->reqs[0], lockread_lockingx_done, req);
3259
3260         state->reqs[1] = cli_read_andx_create(
3261                 ev,             /* mem_ctx */
3262                 ev,             /* ev */
3263                 cli,            /* cli */
3264                 fnum,           /* fnum */
3265                 0,              /* offset */
3266                 1,              /* size */
3267                 &state->smbreqs[1]);    /* psmbreq */
3268         if (tevent_req_nomem(state->reqs[1], req)) {
3269                 return tevent_req_post(req, ev);
3270         }
3271         tevent_req_set_callback(
3272                 state->reqs[1], lockread_read_andx_done, req);
3273
3274         status = smb1cli_req_chain_submit(state->smbreqs, 2);
3275         if (tevent_req_nterror(req, status)) {
3276                 return tevent_req_post(req, ev);
3277         }
3278         return req;
3279 }
3280
3281 static void lockread_lockingx_done(struct tevent_req *subreq)
3282 {
3283         struct tevent_req *req = tevent_req_callback_data(
3284                 subreq, struct tevent_req);
3285         struct lockread_state *state = tevent_req_data(
3286                 req, struct lockread_state);
3287         state->lock_status = cli_lockingx_recv(subreq);
3288         TALLOC_FREE(subreq);
3289         d_fprintf(stderr,
3290                   "lockingx returned %s\n",
3291                   nt_errstr(state->lock_status));
3292 }
3293
3294 static void lockread_read_andx_done(struct tevent_req *subreq)
3295 {
3296         struct tevent_req *req = tevent_req_callback_data(
3297                 subreq, struct tevent_req);
3298         struct lockread_state *state = tevent_req_data(
3299                 req, struct lockread_state);
3300         ssize_t received = -1;
3301         uint8_t *rcvbuf = NULL;
3302
3303         state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3304
3305         d_fprintf(stderr,
3306                   "read returned %s\n",
3307                   nt_errstr(state->read_status));
3308
3309         if (!NT_STATUS_IS_OK(state->read_status)) {
3310                 TALLOC_FREE(subreq);
3311                 tevent_req_done(req);
3312                 return;
3313         }
3314
3315         if (received > 0) {
3316                 state->readbuf = talloc_memdup(state, rcvbuf, received);
3317                 TALLOC_FREE(subreq);
3318                 if (tevent_req_nomem(state->readbuf, req)) {
3319                         return;
3320                 }
3321         }
3322         TALLOC_FREE(subreq);
3323         tevent_req_done(req);
3324 }
3325
3326 static NTSTATUS lockread_recv(
3327         struct tevent_req *req,
3328         NTSTATUS *lock_status,
3329         NTSTATUS *read_status,
3330         TALLOC_CTX *mem_ctx,
3331         uint8_t **read_buf)
3332 {
3333         struct lockread_state *state = tevent_req_data(
3334                 req, struct lockread_state);
3335         NTSTATUS status;
3336
3337         if (tevent_req_is_nterror(req, &status)) {
3338                 return status;
3339         }
3340
3341         *lock_status = state->lock_status;
3342         *read_status = state->read_status;
3343         if (state->readbuf != NULL) {
3344                 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3345         } else {
3346                 *read_buf = NULL;
3347         }
3348
3349         return NT_STATUS_OK;
3350 }
3351
3352 struct lock12_state {
3353         uint8_t dummy;
3354 };
3355
3356 static void lock12_closed(struct tevent_req *subreq);
3357 static void lock12_read(struct tevent_req *subreq);
3358
3359 static struct tevent_req *lock12_send(
3360         TALLOC_CTX *mem_ctx,
3361         struct tevent_context *ev,
3362         struct cli_state *cli,
3363         uint16_t fnum1,
3364         uint16_t fnum2)
3365 {
3366         struct tevent_req *req = NULL, *subreq = NULL;
3367         struct lock12_state *state = NULL;
3368
3369         req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3370         if (req == NULL) {
3371                 return NULL;
3372         }
3373
3374         subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3375         if (tevent_req_nomem(subreq, req)) {
3376                 return tevent_req_post(req, ev);
3377         }
3378         tevent_req_set_callback(subreq, lock12_closed, req);
3379
3380         subreq = lockread_send(state, ev, cli, fnum2);
3381         if (tevent_req_nomem(subreq, req)) {
3382                 return tevent_req_post(req, ev);
3383         }
3384         tevent_req_set_callback(subreq, lock12_read, req);
3385
3386         return req;
3387 }
3388
3389 static void lock12_closed(struct tevent_req *subreq)
3390 {
3391         struct tevent_req *req = tevent_req_callback_data(
3392                 subreq, struct tevent_req);
3393         NTSTATUS status;
3394
3395         status = deferred_close_recv(subreq);
3396         TALLOC_FREE(subreq);
3397         DBG_DEBUG("close returned %s\n", nt_errstr(status));
3398         if (tevent_req_nterror(req, status)) {
3399                 return;
3400         }
3401 }
3402
3403 static void lock12_read(struct tevent_req *subreq)
3404 {
3405         struct tevent_req *req = tevent_req_callback_data(
3406                 subreq, struct tevent_req);
3407         struct lock12_state *state = tevent_req_data(
3408                 req, struct lock12_state);
3409         NTSTATUS status, lock_status, read_status;
3410         uint8_t *buf = NULL;
3411
3412         status = lockread_recv(
3413                 subreq, &lock_status, &read_status, state, &buf);
3414         TALLOC_FREE(subreq);
3415         if (tevent_req_nterror(req, status) ||
3416             tevent_req_nterror(req, lock_status) ||
3417             tevent_req_nterror(req, read_status)) {
3418                 return;
3419         }
3420         tevent_req_done(req);
3421 }
3422
3423 static NTSTATUS lock12_recv(struct tevent_req *req)
3424
3425 {
3426         NTSTATUS status;
3427
3428         if (tevent_req_is_nterror(req, &status)) {
3429                 return status;
3430         }
3431         return NT_STATUS_OK;
3432 }
3433
3434 static bool run_locktest12(int dummy)
3435 {
3436         struct tevent_context *ev = NULL;
3437         struct tevent_req *req = NULL;
3438         struct cli_state *cli = NULL;
3439         const char fname[] = "\\lockt12.lck";
3440         uint16_t fnum1, fnum2;
3441         bool ret = false;
3442         bool ok;
3443         uint8_t data = 1;
3444         NTSTATUS status;
3445
3446         printf("starting locktest12\n");
3447
3448         ev = samba_tevent_context_init(NULL);
3449         if (ev == NULL) {
3450                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3451                 goto done;
3452         }
3453
3454         ok = torture_open_connection(&cli, 0);
3455         if (!ok) {
3456                 goto done;
3457         }
3458         smbXcli_conn_set_sockopt(cli->conn, sockops);
3459
3460         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3461         if (!NT_STATUS_IS_OK(status)) {
3462                 d_fprintf(stderr,
3463                           "cli_openx failed: %s\n",
3464                           nt_errstr(status));
3465                 goto done;
3466         }
3467
3468         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3469         if (!NT_STATUS_IS_OK(status)) {
3470                 d_fprintf(stderr,
3471                           "cli_openx failed: %s\n",
3472                           nt_errstr(status));
3473                 goto done;
3474         }
3475
3476         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3477         if (!NT_STATUS_IS_OK(status)) {
3478                 d_fprintf(stderr,
3479                           "cli_writeall failed: %s\n",
3480                           nt_errstr(status));
3481                 goto done;
3482         }
3483
3484         status = cli_locktype(
3485                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3486         if (!NT_STATUS_IS_OK(status)) {
3487                 d_fprintf(stderr,
3488                           "cli_locktype failed: %s\n",
3489                           nt_errstr(status));
3490                 goto done;
3491         }
3492
3493         req = lock12_send(ev, ev, cli, fnum1, fnum2);
3494         if (req == NULL) {
3495                 d_fprintf(stderr, "lock12_send failed\n");
3496                 goto done;
3497         }
3498
3499         ok = tevent_req_poll_ntstatus(req, ev, &status);
3500         if (!ok) {
3501                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3502                 goto done;
3503         }
3504
3505         if (!NT_STATUS_IS_OK(status)) {
3506                 d_fprintf(stderr,
3507                           "tevent_req_poll_ntstatus returned %s\n",
3508                           nt_errstr(status));
3509                 goto done;
3510         }
3511
3512         status = lock12_recv(req);
3513         if (!NT_STATUS_IS_OK(status)) {
3514                 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3515                 goto done;
3516         }
3517
3518         ret = true;
3519 done:
3520         if (cli != NULL) {
3521                 torture_close_connection(cli);
3522         }
3523         return ret;
3524 }
3525
3526 struct lock_ntcancel_state {
3527         struct timeval start;
3528         struct smb1_lock_element lck;
3529         struct tevent_req *subreq;
3530 };
3531
3532 static void lock_ntcancel_waited(struct tevent_req *subreq);
3533 static void lock_ntcancel_done(struct tevent_req *subreq);
3534
3535 static struct tevent_req *lock_ntcancel_send(
3536         TALLOC_CTX *mem_ctx,
3537         struct tevent_context *ev,
3538         struct cli_state *cli,
3539         uint16_t fnum)
3540 {
3541         struct tevent_req *req = NULL, *subreq = NULL;
3542         struct lock_ntcancel_state *state = NULL;
3543
3544         req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3545         if (req == NULL) {
3546                 return NULL;
3547         }
3548         state->lck = (struct smb1_lock_element) {
3549                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3550         };
3551         state->start = timeval_current();
3552
3553         state->subreq = cli_lockingx_send(
3554                 state,                          /* mem_ctx */
3555                 ev,                             /* tevent_context */
3556                 cli,                            /* cli */
3557                 fnum,                           /* fnum */
3558                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3559                 0,                              /* newoplocklevel */
3560                 10000,                          /* timeout */
3561                 0,                              /* num_unlocks */
3562                 NULL,                           /* unlocks */
3563                 1,                              /* num_locks */
3564                 &state->lck);                   /* locks */
3565         if (tevent_req_nomem(state->subreq, req)) {
3566                 return tevent_req_post(req, ev);
3567         }
3568         tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3569
3570         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3571         if (tevent_req_nomem(subreq, req)) {
3572                 return tevent_req_post(req, ev);
3573         }
3574         tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3575         return req;
3576 }
3577
3578 static void lock_ntcancel_waited(struct tevent_req *subreq)
3579 {
3580         struct tevent_req *req = tevent_req_callback_data(
3581                 subreq, struct tevent_req);
3582         struct lock_ntcancel_state *state = tevent_req_data(
3583                 req, struct lock_ntcancel_state);
3584         bool ok;
3585
3586         ok = tevent_wakeup_recv(subreq);
3587         TALLOC_FREE(subreq);
3588         if (!ok) {
3589                 tevent_req_oom(req);
3590                 return;
3591         }
3592
3593         ok = tevent_req_cancel(state->subreq);
3594         if (!ok) {
3595                 d_fprintf(stderr, "Could not cancel subreq\n");
3596                 tevent_req_oom(req);
3597                 return;
3598         }
3599 }
3600
3601 static void lock_ntcancel_done(struct tevent_req *subreq)
3602 {
3603         struct tevent_req *req = tevent_req_callback_data(
3604                 subreq, struct tevent_req);
3605         struct lock_ntcancel_state *state = tevent_req_data(
3606                 req, struct lock_ntcancel_state);
3607         NTSTATUS status;
3608         double elapsed;
3609
3610         status = cli_lockingx_recv(subreq);
3611         TALLOC_FREE(subreq);
3612
3613         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3614                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3615                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3616                 return;
3617         }
3618
3619         elapsed = timeval_elapsed(&state->start);
3620
3621         if (elapsed > 3) {
3622                 d_printf("cli_lockingx was too slow, cancel did not work\n");
3623                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3624                 return;
3625         }
3626
3627         tevent_req_done(req);
3628 }
3629
3630 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3631 {
3632         return tevent_req_simple_recv_ntstatus(req);
3633 }
3634
3635 static bool run_locktest13(int dummy)
3636 {
3637         struct tevent_context *ev = NULL;
3638         struct tevent_req *req = NULL;
3639         struct cli_state *cli = NULL;
3640         const char fname[] = "\\lockt13.lck";
3641         uint16_t fnum1, fnum2;
3642         bool ret = false;
3643         bool ok;
3644         uint8_t data = 1;
3645         NTSTATUS status;
3646
3647         printf("starting locktest13\n");
3648
3649         ev = samba_tevent_context_init(NULL);
3650         if (ev == NULL) {
3651                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3652                 goto done;
3653         }
3654
3655         ok = torture_open_connection(&cli, 0);
3656         if (!ok) {
3657                 goto done;
3658         }
3659         smbXcli_conn_set_sockopt(cli->conn, sockops);
3660
3661         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3662         if (!NT_STATUS_IS_OK(status)) {
3663                 d_fprintf(stderr,
3664                           "cli_openx failed: %s\n",
3665                           nt_errstr(status));
3666                 goto done;
3667         }
3668
3669         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3670         if (!NT_STATUS_IS_OK(status)) {
3671                 d_fprintf(stderr,
3672                           "cli_openx failed: %s\n",
3673                           nt_errstr(status));
3674                 goto done;
3675         }
3676
3677         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3678         if (!NT_STATUS_IS_OK(status)) {
3679                 d_fprintf(stderr,
3680                           "cli_writeall failed: %s\n",
3681                           nt_errstr(status));
3682                 goto done;
3683         }
3684
3685         status = cli_locktype(
3686                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3687         if (!NT_STATUS_IS_OK(status)) {
3688                 d_fprintf(stderr,
3689                           "cli_locktype failed: %s\n",
3690                           nt_errstr(status));
3691                 goto done;
3692         }
3693
3694         req = lock_ntcancel_send(ev, ev, cli, fnum2);
3695         if (req == NULL) {
3696                 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3697                 goto done;
3698         }
3699
3700         ok = tevent_req_poll_ntstatus(req, ev, &status);
3701         if (!ok) {
3702                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3703                 goto done;
3704         }
3705
3706         if (!NT_STATUS_IS_OK(status)) {
3707                 d_fprintf(stderr,
3708                           "tevent_req_poll_ntstatus returned %s\n",
3709                           nt_errstr(status));
3710                 goto done;
3711         }
3712
3713         status = lock_ntcancel_recv(req);
3714         if (!NT_STATUS_IS_OK(status)) {
3715                 d_fprintf(stderr,
3716                           "lock_ntcancel returned %s\n",
3717                           nt_errstr(status));
3718                 goto done;
3719         }
3720
3721         ret = true;
3722 done:
3723         if (cli != NULL) {
3724                 torture_close_connection(cli);
3725         }
3726         return ret;
3727 }
3728
3729 /*
3730 test whether fnums and tids open on one VC are available on another (a major
3731 security hole)
3732 */
3733 static bool run_fdpasstest(int dummy)
3734 {
3735         struct cli_state *cli1, *cli2;
3736         const char *fname = "\\fdpass.tst";
3737         uint16_t fnum1;
3738         char buf[1024];
3739         NTSTATUS status;
3740
3741         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3742                 return False;
3743         }
3744         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3745         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3746
3747         printf("starting fdpasstest\n");
3748
3749         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3750
3751         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3752                           &fnum1);
3753         if (!NT_STATUS_IS_OK(status)) {
3754                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3755                 return False;
3756         }
3757
3758         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3759                               13, NULL);
3760         if (!NT_STATUS_IS_OK(status)) {
3761                 printf("write failed (%s)\n", nt_errstr(status));
3762                 return False;
3763         }
3764
3765         cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3766         cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3767         cli_setpid(cli2, cli_getpid(cli1));
3768
3769         if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3770                 printf("read succeeded! nasty security hole [%s]\n", buf);
3771                 return false;
3772         }
3773
3774         cli_close(cli1, fnum1);
3775         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3776
3777         torture_close_connection(cli1);
3778         torture_close_connection(cli2);
3779
3780         printf("finished fdpasstest\n");
3781         return True;
3782 }
3783
3784 static bool run_fdsesstest(int dummy)
3785 {
3786         struct cli_state *cli;
3787         uint16_t new_vuid;
3788         uint16_t saved_vuid;
3789         uint32_t new_cnum;
3790         uint32_t saved_cnum;
3791         const char *fname = "\\fdsess.tst";
3792         const char *fname1 = "\\fdsess1.tst";
3793         uint16_t fnum1;
3794         uint16_t fnum2;
3795         char buf[1024];
3796         bool ret = True;
3797         NTSTATUS status;
3798
3799         if (!torture_open_connection(&cli, 0))
3800                 return False;
3801         smbXcli_conn_set_sockopt(cli->conn, sockops);
3802
3803         if (!torture_cli_session_setup2(cli, &new_vuid))
3804                 return False;
3805
3806         saved_cnum = cli_state_get_tid(cli);
3807         if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3808                 return False;
3809         new_cnum = cli_state_get_tid(cli);
3810         cli_state_set_tid(cli, saved_cnum);
3811
3812         printf("starting fdsesstest\n");
3813
3814         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3815         cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3816
3817         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3818         if (!NT_STATUS_IS_OK(status)) {
3819                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3820                 return False;
3821         }
3822
3823         status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3824                               NULL);
3825         if (!NT_STATUS_IS_OK(status)) {
3826                 printf("write failed (%s)\n", nt_errstr(status));
3827                 return False;
3828         }
3829
3830         saved_vuid = cli_state_get_uid(cli);
3831         cli_state_set_uid(cli, new_vuid);
3832
3833         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3834                 printf("read succeeded with different vuid! "
3835                        "nasty security hole [%s]\n", buf);
3836                 ret = false;
3837         }
3838         /* Try to open a file with different vuid, samba cnum. */
3839         if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3840                 printf("create with different vuid, same cnum succeeded.\n");
3841                 cli_close(cli, fnum2);
3842                 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3843         } else {
3844                 printf("create with different vuid, same cnum failed.\n");
3845                 printf("This will cause problems with service clients.\n");
3846                 ret = False;
3847         }
3848
3849         cli_state_set_uid(cli, saved_vuid);
3850
3851         /* Try with same vuid, different cnum. */
3852         cli_state_set_tid(cli, new_cnum);
3853
3854         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3855                 printf("read succeeded with different cnum![%s]\n", buf);
3856                 ret = false;
3857         }
3858
3859         cli_state_set_tid(cli, saved_cnum);
3860         cli_close(cli, fnum1);
3861         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3862
3863         torture_close_connection(cli);
3864
3865         printf("finished fdsesstest\n");
3866         return ret;
3867 }
3868
3869 /*
3870   This test checks that
3871
3872   1) the server does not allow an unlink on a file that is open
3873 */
3874 static bool run_unlinktest(int dummy)
3875 {
3876         struct cli_state *cli;
3877         const char *fname = "\\unlink.tst";
3878         uint16_t fnum;
3879         bool correct = True;
3880         NTSTATUS status;
3881
3882         if (!torture_open_connection(&cli, 0)) {
3883                 return False;
3884         }
3885
3886         smbXcli_conn_set_sockopt(cli->conn, sockops);
3887
3888         printf("starting unlink test\n");
3889
3890         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3891
3892         cli_setpid(cli, 1);
3893
3894         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3895         if (!NT_STATUS_IS_OK(status)) {
3896                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3897                 return False;
3898         }
3899
3900         status = cli_unlink(cli, fname,
3901                             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3902         if (NT_STATUS_IS_OK(status)) {
3903                 printf("error: server allowed unlink on an open file\n");
3904                 correct = False;
3905         } else {
3906                 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3907                                       NT_STATUS_SHARING_VIOLATION);
3908         }
3909
3910         cli_close(cli, fnum);
3911         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3912
3913         if (!torture_close_connection(cli)) {
3914                 correct = False;
3915         }
3916
3917         printf("unlink test finished\n");
3918
3919         return correct;
3920 }
3921
3922
3923 /*
3924 test how many open files this server supports on the one socket
3925 */
3926 static bool run_maxfidtest(int dummy)
3927 {
3928         struct cli_state *cli;
3929         fstring fname;
3930         uint16_t fnums[0x11000];
3931         int i;
3932         int retries=4;
3933         bool correct = True;
3934         NTSTATUS status;
3935
3936         cli = current_cli;
3937
3938         if (retries <= 0) {
3939                 printf("failed to connect\n");
3940                 return False;
3941         }
3942
3943         smbXcli_conn_set_sockopt(cli->conn, sockops);
3944
3945         for (i=0; i<0x11000; i++) {
3946                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3947                 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3948                                   &fnums[i]);
3949                 if (!NT_STATUS_IS_OK(status)) {
3950                         printf("open of %s failed (%s)\n",
3951                                fname, nt_errstr(status));
3952                         printf("maximum fnum is %d\n", i);
3953                         break;
3954                 }
3955                 printf("%6d\r", i);
3956         }
3957         printf("%6d\n", i);
3958         i--;
3959
3960         printf("cleaning up\n");
3961         for (;i>=0;i--) {
3962                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3963                 cli_close(cli, fnums[i]);
3964
3965                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3966                 if (!NT_STATUS_IS_OK(status)) {
3967                         printf("unlink of %s failed (%s)\n",
3968                                fname, nt_errstr(status));
3969                         correct = False;
3970                 }
3971                 printf("%6d\r", i);
3972         }
3973         printf("%6d\n", 0);
3974
3975         printf("maxfid test finished\n");
3976         if (!torture_close_connection(cli)) {
3977                 correct = False;
3978         }
3979         return correct;
3980 }
3981
3982 /* generate a random buffer */
3983 static void rand_buf(char *buf, int len)
3984 {
3985         while (len--) {
3986                 *buf = (char)sys_random();
3987                 buf++;
3988         }
3989 }
3990
3991 /* send smb negprot commands, not reading the response */
3992 static bool run_negprot_nowait(int dummy)
3993 {
3994         struct tevent_context *ev;
3995         int i;
3996         struct cli_state *cli;
3997         bool correct = True;
3998
3999         printf("starting negprot nowait test\n");
4000
4001         ev = samba_tevent_context_init(talloc_tos());
4002         if (ev == NULL) {
4003                 return false;
4004         }
4005
4006         if (!(cli = open_nbt_connection())) {
4007                 TALLOC_FREE(ev);
4008                 return False;
4009         }
4010
4011         for (i=0;i<50000;i++) {
4012                 struct tevent_req *req;
4013
4014                 req = smbXcli_negprot_send(
4015                         ev,
4016                         ev,
4017                         cli->conn,
4018                         cli->timeout,
4019                         PROTOCOL_CORE,
4020                         PROTOCOL_NT1,
4021                         0,
4022                         NULL);
4023                 if (req == NULL) {
4024                         TALLOC_FREE(ev);
4025                         return false;
4026                 }
4027                 if (!tevent_req_poll(req, ev)) {
4028                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
4029                                   strerror(errno));
4030                         TALLOC_FREE(ev);
4031                         return false;
4032                 }
4033                 TALLOC_FREE(req);
4034         }
4035
4036         if (torture_close_connection(cli)) {
4037                 correct = False;
4038         }
4039
4040         printf("finished negprot nowait test\n");
4041
4042         return correct;
4043 }
4044
4045 /* send smb negprot commands, not reading the response */
4046 static bool run_bad_nbt_session(int dummy)
4047 {
4048         struct nmb_name called, calling;
4049         struct sockaddr_storage ss;
4050         NTSTATUS status;
4051         int fd;
4052         bool ret;
4053
4054         printf("starting bad nbt session test\n");
4055
4056         make_nmb_name(&calling, myname, 0x0);
4057         make_nmb_name(&called , host, 0x20);
4058
4059         if (!resolve_name(host, &ss, 0x20, true)) {
4060                 d_fprintf(stderr, "Could not resolve name %s\n", host);
4061                 return false;
4062         }
4063
4064         status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4065         if (!NT_STATUS_IS_OK(status)) {
4066                 d_fprintf(stderr, "open_socket_out failed: %s\n",
4067                           nt_errstr(status));
4068                 return false;
4069         }
4070
4071         ret = cli_bad_session_request(fd, &calling, &called);
4072         close(fd);
4073         if (!ret) {
4074                 d_fprintf(stderr, "open_socket_out failed: %s\n",
4075                           nt_errstr(status));
4076                 return false;
4077         }
4078
4079         printf("finished bad nbt session test\n");
4080         return true;
4081 }
4082
4083 /* send random IPC commands */
4084 static bool run_randomipc(int dummy)
4085 {
4086         char *rparam = NULL;
4087         char *rdata = NULL;
4088         unsigned int rdrcnt,rprcnt;
4089         char param[1024];
4090         int api, param_len, i;
4091         struct cli_state *cli;
4092         bool correct = True;
4093         int count = 50000;
4094
4095         printf("starting random ipc test\n");
4096
4097         if (!torture_open_connection(&cli, 0)) {
4098                 return False;
4099         }
4100
4101         for (i=0;i<count;i++) {
4102                 api = sys_random() % 500;
4103                 param_len = (sys_random() % 64);
4104
4105                 rand_buf(param, param_len);
4106
4107                 SSVAL(param,0,api);
4108
4109                 cli_api(cli,
4110                         param, param_len, 8,
4111                         NULL, 0, CLI_BUFFER_SIZE,
4112                         &rparam, &rprcnt,
4113                         &rdata, &rdrcnt);
4114                 if (i % 100 == 0) {
4115                         printf("%d/%d\r", i,count);
4116                 }
4117         }
4118         printf("%d/%d\n", i, count);
4119
4120         if (!torture_close_connection(cli)) {
4121                 correct = False;
4122         }
4123
4124         SAFE_FREE(rparam);
4125         SAFE_FREE(rdata);
4126
4127         printf("finished random ipc test\n");
4128
4129         return correct;
4130 }
4131
4132
4133
4134 static void browse_callback(const char *sname, uint32_t stype,
4135                             const char *comment, void *state)
4136 {
4137         printf("\t%20.20s %08x %s\n", sname, stype, comment);
4138 }
4139
4140
4141
4142 /*
4143   This test checks the browse list code
4144
4145 */
4146 static bool run_browsetest(int dummy)
4147 {
4148         static struct cli_state *cli;
4149         bool correct = True;
4150
4151         printf("starting browse test\n");
4152
4153         if (!torture_open_connection(&cli, 0)) {
4154                 return False;
4155         }
4156
4157         printf("domain list:\n");
4158         cli_NetServerEnum(cli, cli->server_domain,
4159                           SV_TYPE_DOMAIN_ENUM,
4160                           browse_callback, NULL);
4161
4162         printf("machine list:\n");
4163         cli_NetServerEnum(cli, cli->server_domain,
4164                           SV_TYPE_ALL,
4165                           browse_callback, NULL);
4166
4167         if (!torture_close_connection(cli)) {
4168                 correct = False;
4169         }
4170
4171         printf("browse test finished\n");
4172
4173         return correct;
4174
4175 }
4176
4177 static bool check_attributes(struct cli_state *cli,
4178                                 const char *fname,
4179                                 uint32_t expected_attrs)
4180 {
4181         uint32_t attrs = 0;
4182         NTSTATUS status = cli_getatr(cli,
4183                                 fname,
4184                                 &attrs,
4185                                 NULL,
4186                                 NULL);
4187         if (!NT_STATUS_IS_OK(status)) {
4188                 printf("cli_getatr failed with %s\n",
4189                         nt_errstr(status));
4190                 return false;
4191         }
4192         if (attrs != expected_attrs) {
4193                 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4194                         (unsigned int)attrs,
4195                         (unsigned int)expected_attrs);
4196                 return false;
4197         }
4198         return true;
4199 }
4200
4201 /*
4202   This checks how the getatr calls works
4203 */
4204 static bool run_attrtest(int dummy)
4205 {
4206         struct cli_state *cli;
4207         uint16_t fnum;
4208         time_t t, t2;
4209         const char *fname = "\\attrib123456789.tst";
4210         bool correct = True;
4211         NTSTATUS status;
4212
4213         printf("starting attrib test\n");
4214
4215         if (!torture_open_connection(&cli, 0)) {
4216                 return False;
4217         }
4218
4219         /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4220         status = cli_unlink(cli, fname, 0x20000);
4221         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4222                 correct = false;
4223                 goto out;
4224         }
4225
4226         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4227         cli_openx(cli, fname,
4228                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4229         cli_close(cli, fnum);
4230
4231         status = cli_getatr(cli, fname, NULL, NULL, &t);
4232         if (!NT_STATUS_IS_OK(status)) {
4233                 printf("getatr failed (%s)\n", nt_errstr(status));
4234                 correct = False;
4235         }
4236
4237         if (labs(t - time(NULL)) > 60*60*24*10) {
4238                 printf("ERROR: SMBgetatr bug. time is %s",
4239                        ctime(&t));
4240                 t = time(NULL);
4241                 correct = True;
4242         }
4243
4244         t2 = t-60*60*24; /* 1 day ago */
4245
4246         /* Ensure we can't set with out-of-range (unknown) attribute. */
4247         status = cli_setatr(cli, fname, 0x20000, t2);
4248         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4249                 correct = false;
4250                 goto out;
4251         }
4252
4253         status = cli_setatr(cli, fname, 0, t2);
4254         if (!NT_STATUS_IS_OK(status)) {
4255                 printf("setatr failed (%s)\n", nt_errstr(status));
4256                 correct = True;
4257         }
4258
4259         status = cli_getatr(cli, fname, NULL, NULL, &t);
4260         if (!NT_STATUS_IS_OK(status)) {
4261                 printf("getatr failed (%s)\n", nt_errstr(status));
4262                 correct = True;
4263         }
4264
4265         if (t != t2) {
4266                 printf("ERROR: getatr/setatr bug. times are\n%s",
4267                        ctime(&t));
4268                 printf("%s", ctime(&t2));
4269                 correct = True;
4270         }
4271
4272         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4273
4274         /* Check cli_setpathinfo_ext() */
4275         /* Re-create the file. */
4276         status = cli_openx(cli, fname,
4277                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4278         if (!NT_STATUS_IS_OK(status)) {
4279                 printf("Failed to recreate %s (%s)\n",
4280                         fname, nt_errstr(status));
4281                 correct = false;
4282         }
4283         cli_close(cli, fnum);
4284
4285         status = cli_setpathinfo_ext(
4286                 cli,
4287                 fname,
4288                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4289                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4290                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4291                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4292                 FILE_ATTRIBUTE_SYSTEM |
4293                 FILE_ATTRIBUTE_HIDDEN |
4294                 FILE_ATTRIBUTE_READONLY);
4295         if (!NT_STATUS_IS_OK(status)) {
4296                 printf("cli_setpathinfo_ext failed with %s\n",
4297                         nt_errstr(status));
4298                 correct = false;
4299         }
4300
4301         /* Check attributes are correct. */
4302         correct = check_attributes(cli,
4303                         fname,
4304                         FILE_ATTRIBUTE_SYSTEM |
4305                         FILE_ATTRIBUTE_HIDDEN |
4306                         FILE_ATTRIBUTE_READONLY);
4307         if (correct == false) {
4308                 goto out;
4309         }
4310
4311         /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4312         status = cli_setpathinfo_ext(
4313                 cli,
4314                 fname,
4315                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4316                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4317                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4318                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4319                 FILE_ATTRIBUTE_NORMAL);
4320         if (!NT_STATUS_IS_OK(status)) {
4321                 printf("cli_setpathinfo_ext failed with %s\n",
4322                         nt_errstr(status));
4323                 correct = false;
4324         }
4325
4326         /* Check attributes are correct. */
4327         correct = check_attributes(cli,
4328                         fname,
4329                         FILE_ATTRIBUTE_SYSTEM |
4330                         FILE_ATTRIBUTE_HIDDEN |
4331                         FILE_ATTRIBUTE_READONLY);
4332         if (correct == false) {
4333                 goto out;
4334         }
4335
4336         /* Setting to (uint16_t)-1 should also be ignored. */
4337         status = cli_setpathinfo_ext(
4338                 cli,
4339                 fname,
4340                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4341                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4342                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4343                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4344                 (uint32_t)-1);
4345         if (!NT_STATUS_IS_OK(status)) {
4346                 printf("cli_setpathinfo_ext failed with %s\n",
4347                         nt_errstr(status));
4348                 correct = false;
4349         }
4350
4351         /* Check attributes are correct. */
4352         correct = check_attributes(cli,
4353                         fname,
4354                         FILE_ATTRIBUTE_SYSTEM |
4355                         FILE_ATTRIBUTE_HIDDEN |
4356                         FILE_ATTRIBUTE_READONLY);
4357         if (correct == false) {
4358                 goto out;
4359         }
4360
4361         /* Setting to 0 should clear them all. */
4362         status = cli_setpathinfo_ext(
4363                 cli,
4364                 fname,
4365                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4366                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4367                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4368                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4369                 0);
4370         if (!NT_STATUS_IS_OK(status)) {
4371                 printf("cli_setpathinfo_ext failed with %s\n",
4372                         nt_errstr(status));
4373                 correct = false;
4374         }
4375
4376         /* Check attributes are correct. */
4377         correct = check_attributes(cli,
4378                         fname,
4379                         FILE_ATTRIBUTE_NORMAL);
4380         if (correct == false) {
4381                 goto out;
4382         }
4383
4384   out:
4385
4386         cli_unlink(cli,
4387                 fname,
4388                 FILE_ATTRIBUTE_SYSTEM |
4389                 FILE_ATTRIBUTE_HIDDEN|
4390                 FILE_ATTRIBUTE_READONLY);
4391
4392         if (!torture_close_connection(cli)) {
4393                 correct = False;
4394         }
4395
4396         printf("attrib test finished\n");
4397
4398         return correct;
4399 }
4400
4401 static NTSTATUS cli_qfilename(
4402         struct cli_state *cli,
4403         uint16_t fnum,
4404         TALLOC_CTX *mem_ctx,
4405         char **_name)
4406 {
4407         uint16_t recv_flags2;
4408         uint8_t *rdata;
4409         uint32_t num_rdata;
4410         NTSTATUS status;
4411         char *name = NULL;
4412         uint32_t namelen;
4413
4414         status = cli_qfileinfo(talloc_tos(),
4415                                cli,
4416                                fnum,
4417                                FSCC_FILE_NAME_INFORMATION,
4418                                4,
4419                                CLI_BUFFER_SIZE,
4420                                &recv_flags2,
4421                                &rdata,
4422                                &num_rdata);
4423         if (!NT_STATUS_IS_OK(status)) {
4424                 return status;
4425         }
4426
4427         namelen = IVAL(rdata, 0);
4428         if (namelen > (num_rdata - 4)) {
4429                 TALLOC_FREE(rdata);
4430                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4431         }
4432
4433         pull_string_talloc(mem_ctx,
4434                            (const char *)rdata,
4435                            recv_flags2,
4436                            &name,
4437                            rdata + 4,
4438                            namelen,
4439                            STR_UNICODE);
4440         if (name == NULL) {
4441                 status = map_nt_error_from_unix(errno);
4442                 TALLOC_FREE(rdata);
4443                 return status;
4444         }
4445
4446         *_name = name;
4447         TALLOC_FREE(rdata);
4448         return NT_STATUS_OK;
4449 }
4450
4451 /*
4452   This checks a couple of trans2 calls
4453 */
4454 static bool run_trans2test(int dummy)
4455 {
4456         struct cli_state *cli;
4457         uint16_t fnum;
4458         off_t size;
4459         time_t c_time, a_time, m_time;
4460         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4461         const char *fname = "\\trans2.tst";
4462         const char *dname = "\\trans2";
4463         const char *fname2 = "\\trans2\\trans2.tst";
4464         char *pname = NULL;
4465         bool correct = True;
4466         NTSTATUS status;
4467         uint32_t fs_attr;
4468         uint64_t ino;
4469
4470         printf("starting trans2 test\n");
4471
4472         if (!torture_open_connection(&cli, 0)) {
4473                 return False;
4474         }
4475
4476         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4477                 /* Ensure ino is zero, SMB2 gets a real one. */
4478                 ino = 0;
4479         } else {
4480                 /* Ensure ino is -1, SMB1 never gets a real one. */
4481                 ino = (uint64_t)-1;
4482         }
4483
4484         status = cli_get_fs_attr_info(cli, &fs_attr);
4485         if (!NT_STATUS_IS_OK(status)) {
4486                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4487                        nt_errstr(status));
4488                 correct = false;
4489         }
4490
4491         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4492         cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4493         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4494                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4495         if (!NT_STATUS_IS_OK(status)) {
4496                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4497                 correct = False;
4498         }
4499
4500         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4501         if (!NT_STATUS_IS_OK(status)) {
4502                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4503                 correct = False;
4504         }
4505         else if (strcmp(pname, fname)) {
4506                 printf("qfilename gave different name? [%s] [%s]\n",
4507                        fname, pname);
4508                 correct = False;
4509         }
4510
4511         cli_close(cli, fnum);
4512
4513         sleep(2);
4514
4515         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4516         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4517                           &fnum);
4518         if (!NT_STATUS_IS_OK(status)) {
4519                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4520                 return False;
4521         }
4522         cli_close(cli, fnum);
4523
4524         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4525                                 NULL);
4526         if (!NT_STATUS_IS_OK(status)) {
4527                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4528                 correct = False;
4529         } else {
4530                 time_t t = time(NULL);
4531
4532                 if (c_time != m_time) {
4533                         printf("create time=%s", ctime(&c_time));
4534                         printf("modify time=%s", ctime(&m_time));
4535                         printf("This system appears to have sticky create times\n");
4536                 }
4537                 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4538                         printf("access time=%s", ctime(&a_time));
4539                         printf("This system appears to set a midnight access time\n");
4540                         correct = False;
4541                 }
4542
4543                 if (labs(m_time - t) > 60*60*24*7) {
4544                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4545                         correct = False;
4546                 }
4547         }
4548
4549
4550         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4551         cli_openx(cli, fname,
4552                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4553         cli_close(cli, fnum);
4554         status = cli_qpathinfo2(cli,
4555                                 fname,
4556                                 &c_time_ts,
4557                                 &a_time_ts,
4558                                 &w_time_ts,
4559                                 &m_time_ts,
4560                                 &size,
4561                                 NULL,
4562                                 &ino,
4563                                 NULL);
4564         if (!NT_STATUS_IS_OK(status)) {
4565                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4566                 correct = False;
4567         } else {
4568                 if (w_time_ts.tv_sec < 60*60*24*2) {
4569                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
4570                         printf("This system appears to set a initial 0 write time\n");
4571                         correct = False;
4572                 }
4573                 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4574                         /* SMB2 should always return an inode. */
4575                         if (ino == 0) {
4576                                 printf("SMB2 bad inode (0)\n");
4577                                 correct = false;
4578                         }
4579                 } else {
4580                         /* SMB1 must always return zero here. */
4581                         if (ino != 0) {
4582                                 printf("SMB1 bad inode (!0)\n");
4583                                 correct = false;
4584                         }
4585                 }
4586         }
4587
4588         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4589
4590
4591         /* check if the server updates the directory modification time
4592            when creating a new file */
4593         status = cli_mkdir(cli, dname);
4594         if (!NT_STATUS_IS_OK(status)) {
4595                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4596                 correct = False;
4597         }
4598         sleep(3);
4599         status = cli_qpathinfo2(cli,
4600                                 "\\trans2\\",
4601                                 &c_time_ts,
4602                                 &a_time_ts,
4603                                 &w_time_ts,
4604                                 &m_time_ts,
4605                                 &size,
4606                                 NULL,
4607                                 NULL,
4608                                 NULL);
4609         if (!NT_STATUS_IS_OK(status)) {
4610                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4611                 correct = False;
4612         }
4613
4614         cli_openx(cli, fname2,
4615                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4616         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4617         cli_close(cli, fnum);
4618         status = cli_qpathinfo2(cli,
4619                                 "\\trans2\\",
4620                                 &c_time_ts,
4621                                 &a_time_ts,
4622                                 &w_time_ts,
4623                                 &m_time2_ts,
4624                                 &size,
4625                                 NULL,
4626                                 NULL,
4627                                 NULL);
4628         if (!NT_STATUS_IS_OK(status)) {
4629                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4630                 correct = False;
4631         } else {
4632                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4633                     == 0) {
4634                         printf("This system does not update directory modification times\n");
4635                         correct = False;
4636                 }
4637         }
4638         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4639         cli_rmdir(cli, dname);
4640
4641         if (!torture_close_connection(cli)) {
4642                 correct = False;
4643         }
4644
4645         printf("trans2 test finished\n");
4646
4647         return correct;
4648 }
4649
4650 /*
4651   This checks new W2K calls.
4652 */
4653
4654 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4655 {
4656         uint8_t *buf = NULL;
4657         uint32_t len;
4658         NTSTATUS status;
4659
4660         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4661                                CLI_BUFFER_SIZE, NULL, &buf, &len);
4662         if (!NT_STATUS_IS_OK(status)) {
4663                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4664                        nt_errstr(status));
4665         } else {
4666                 printf("qfileinfo: level %d, len = %u\n", level, len);
4667                 dump_data(0, (uint8_t *)buf, len);
4668                 printf("\n");
4669         }
4670         TALLOC_FREE(buf);
4671         return status;
4672 }
4673
4674 static bool run_w2ktest(int dummy)
4675 {
4676         struct cli_state *cli;
4677         uint16_t fnum;
4678         const char *fname = "\\w2ktest\\w2k.tst";
4679         int level;
4680         bool correct = True;
4681
4682         printf("starting w2k test\n");
4683
4684         if (!torture_open_connection(&cli, 0)) {
4685                 return False;
4686         }
4687
4688         cli_openx(cli, fname,
4689                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
4690
4691         for (level = 1004; level < 1040; level++) {
4692                 new_trans(cli, fnum, level);
4693         }
4694
4695         cli_close(cli, fnum);
4696
4697         if (!torture_close_connection(cli)) {
4698                 correct = False;
4699         }
4700
4701         printf("w2k test finished\n");
4702
4703         return correct;
4704 }
4705
4706
4707 /*
4708   this is a harness for some oplock tests
4709  */
4710 static bool run_oplock1(int dummy)
4711 {
4712         struct cli_state *cli1;
4713         const char *fname = "\\lockt1.lck";
4714         uint16_t fnum1;
4715         bool correct = True;
4716         NTSTATUS status;
4717
4718         printf("starting oplock test 1\n");
4719
4720         if (!torture_open_connection(&cli1, 0)) {
4721                 return False;
4722         }
4723
4724         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4725
4726         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4727
4728         cli1->use_oplocks = True;
4729
4730         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4731                           &fnum1);
4732         if (!NT_STATUS_IS_OK(status)) {
4733                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4734                 return False;
4735         }
4736
4737         cli1->use_oplocks = False;
4738
4739         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4740         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4741
4742         status = cli_close(cli1, fnum1);
4743         if (!NT_STATUS_IS_OK(status)) {
4744                 printf("close2 failed (%s)\n", nt_errstr(status));
4745                 return False;
4746         }
4747
4748         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4749         if (!NT_STATUS_IS_OK(status)) {
4750                 printf("unlink failed (%s)\n", nt_errstr(status));
4751                 return False;
4752         }
4753
4754         if (!torture_close_connection(cli1)) {
4755                 correct = False;
4756         }
4757
4758         printf("finished oplock test 1\n");
4759
4760         return correct;
4761 }
4762
4763 static bool run_oplock2(int dummy)
4764 {
4765         struct cli_state *cli1, *cli2;
4766         const char *fname = "\\lockt2.lck";
4767         uint16_t fnum1, fnum2;
4768         int saved_use_oplocks = use_oplocks;
4769         char buf[4];
4770         bool correct = True;
4771         volatile bool *shared_correct;
4772         size_t nread;
4773         NTSTATUS status;
4774
4775         shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4776         *shared_correct = True;
4777
4778         use_level_II_oplocks = True;
4779         use_oplocks = True;
4780
4781         printf("starting oplock test 2\n");
4782
4783         if (!torture_open_connection(&cli1, 0)) {
4784                 use_level_II_oplocks = False;
4785                 use_oplocks = saved_use_oplocks;
4786                 return False;
4787         }
4788
4789         if (!torture_open_connection(&cli2, 1)) {
4790                 use_level_II_oplocks = False;
4791                 use_oplocks = saved_use_oplocks;
4792                 return False;
4793         }
4794
4795         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4796
4797         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4798         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4799
4800         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4801                           &fnum1);
4802         if (!NT_STATUS_IS_OK(status)) {
4803                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4804                 return False;
4805         }
4806
4807         /* Don't need the globals any more. */
4808         use_level_II_oplocks = False;
4809         use_oplocks = saved_use_oplocks;
4810
4811         if (fork() == 0) {
4812                 /* Child code */
4813                 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4814                 if (!NT_STATUS_IS_OK(status)) {
4815                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4816                         *shared_correct = False;
4817                         exit(0);
4818                 }
4819
4820                 sleep(2);
4821
4822                 status = cli_close(cli2, fnum2);
4823                 if (!NT_STATUS_IS_OK(status)) {
4824                         printf("close2 failed (%s)\n", nt_errstr(status));
4825                         *shared_correct = False;
4826                 }
4827
4828                 exit(0);
4829         }
4830
4831         sleep(2);
4832
4833         /* Ensure cli1 processes the break. Empty file should always return 0
4834          * bytes.  */
4835         status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4836         if (!NT_STATUS_IS_OK(status)) {
4837                 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4838                 correct = false;
4839         } else if (nread != 0) {
4840                 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4841                       (unsigned long)nread, 0);
4842                 correct = false;
4843         }
4844
4845         /* Should now be at level II. */
4846         /* Test if sending a write locks causes a break to none. */
4847         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4848         if (!NT_STATUS_IS_OK(status)) {
4849                 printf("lock failed (%s)\n", nt_errstr(status));
4850                 correct = False;
4851         }
4852
4853         cli_unlock(cli1, fnum1, 0, 4);
4854
4855         sleep(2);
4856
4857         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4858         if (!NT_STATUS_IS_OK(status)) {
4859                 printf("lock failed (%s)\n", nt_errstr(status));
4860                 correct = False;
4861         }
4862
4863         cli_unlock(cli1, fnum1, 0, 4);
4864
4865         sleep(2);
4866
4867         cli_read(cli1, fnum1, buf, 0, 4, NULL);
4868
4869         status = cli_close(cli1, fnum1);
4870         if (!NT_STATUS_IS_OK(status)) {
4871                 printf("close1 failed (%s)\n", nt_errstr(status));
4872                 correct = False;
4873         }
4874
4875         sleep(4);
4876
4877         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4878         if (!NT_STATUS_IS_OK(status)) {
4879                 printf("unlink failed (%s)\n", nt_errstr(status));
4880                 correct = False;
4881         }
4882
4883         if (!torture_close_connection(cli1)) {
4884                 correct = False;
4885         }
4886
4887         if (!*shared_correct) {
4888                 correct = False;
4889         }
4890
4891         printf("finished oplock test 2\n");
4892
4893         return correct;
4894 }
4895
4896 struct oplock4_state {
4897         struct tevent_context *ev;
4898         struct cli_state *cli;
4899         bool *got_break;
4900         uint16_t *fnum2;
4901 };
4902
4903 static void oplock4_got_break(struct tevent_req *req);
4904 static void oplock4_got_open(struct tevent_req *req);
4905
4906 static bool run_oplock4(int dummy)
4907 {
4908         struct tevent_context *ev;
4909         struct cli_state *cli1, *cli2;
4910         struct tevent_req *oplock_req, *open_req;
4911         const char *fname = "\\lockt4.lck";
4912         const char *fname_ln = "\\lockt4_ln.lck";
4913         uint16_t fnum1, fnum2;
4914         int saved_use_oplocks = use_oplocks;
4915         NTSTATUS status;
4916         bool correct = true;
4917
4918         bool got_break;
4919
4920         struct oplock4_state *state;
4921
4922         printf("starting oplock test 4\n");
4923
4924         if (!torture_open_connection(&cli1, 0)) {
4925                 use_level_II_oplocks = false;
4926                 use_oplocks = saved_use_oplocks;
4927                 return false;
4928         }
4929
4930         if (!torture_open_connection(&cli2, 1)) {
4931                 use_level_II_oplocks = false;
4932                 use_oplocks = saved_use_oplocks;
4933                 return false;
4934         }
4935
4936         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4937         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4938
4939         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4940         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4941
4942         /* Create the file. */
4943         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4944                           &fnum1);
4945         if (!NT_STATUS_IS_OK(status)) {
4946                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4947                 return false;
4948         }
4949
4950         status = cli_close(cli1, fnum1);
4951         if (!NT_STATUS_IS_OK(status)) {
4952                 printf("close1 failed (%s)\n", nt_errstr(status));
4953                 return false;
4954         }
4955
4956         /* Now create a hardlink. */
4957         status = cli_hardlink(cli1, fname, fname_ln);
4958         if (!NT_STATUS_IS_OK(status)) {
4959                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4960                 return false;
4961         }
4962
4963         /* Prove that opening hardlinks cause deny modes to conflict. */
4964         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4965         if (!NT_STATUS_IS_OK(status)) {
4966                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4967                 return false;
4968         }
4969
4970         status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4971         if (NT_STATUS_IS_OK(status)) {
4972                 printf("open of %s succeeded - should fail with sharing violation.\n",
4973                         fname_ln);
4974                 return false;
4975         }
4976
4977         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4978                 printf("open of %s should fail with sharing violation. Got %s\n",
4979                         fname_ln, nt_errstr(status));
4980                 return false;
4981         }
4982
4983         status = cli_close(cli1, fnum1);
4984         if (!NT_STATUS_IS_OK(status)) {
4985                 printf("close1 failed (%s)\n", nt_errstr(status));
4986                 return false;
4987         }
4988
4989         cli1->use_oplocks = true;
4990         cli2->use_oplocks = true;
4991
4992         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4993         if (!NT_STATUS_IS_OK(status)) {
4994                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4995                 return false;
4996         }
4997
4998         ev = samba_tevent_context_init(talloc_tos());
4999         if (ev == NULL) {
5000                 printf("tevent_context_init failed\n");
5001                 return false;
5002         }
5003
5004         state = talloc(ev, struct oplock4_state);
5005         if (state == NULL) {
5006                 printf("talloc failed\n");
5007                 return false;
5008         }
5009         state->ev = ev;
5010         state->cli = cli1;
5011         state->got_break = &got_break;
5012         state->fnum2 = &fnum2;
5013
5014         oplock_req = cli_smb_oplock_break_waiter_send(
5015                 talloc_tos(), ev, cli1);
5016         if (oplock_req == NULL) {
5017                 printf("cli_smb_oplock_break_waiter_send failed\n");
5018                 return false;
5019         }
5020         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
5021
5022         open_req = cli_openx_send(
5023                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
5024         if (open_req == NULL) {
5025                 printf("cli_openx_send failed\n");
5026                 return false;
5027         }
5028         tevent_req_set_callback(open_req, oplock4_got_open, state);
5029
5030         got_break = false;
5031         fnum2 = 0xffff;
5032
5033         while (!got_break || fnum2 == 0xffff) {
5034                 int ret;
5035                 ret = tevent_loop_once(ev);
5036                 if (ret == -1) {
5037                         printf("tevent_loop_once failed: %s\n",
5038                                strerror(errno));
5039                         return false;
5040                 }
5041         }
5042
5043         status = cli_close(cli2, fnum2);
5044         if (!NT_STATUS_IS_OK(status)) {
5045                 printf("close2 failed (%s)\n", nt_errstr(status));
5046                 correct = false;
5047         }
5048
5049         status = cli_close(cli1, fnum1);
5050         if (!NT_STATUS_IS_OK(status)) {
5051                 printf("close1 failed (%s)\n", nt_errstr(status));
5052                 correct = false;
5053         }
5054
5055         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5056         if (!NT_STATUS_IS_OK(status)) {
5057                 printf("unlink failed (%s)\n", nt_errstr(status));
5058                 correct = false;
5059         }
5060
5061         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5062         if (!NT_STATUS_IS_OK(status)) {
5063                 printf("unlink failed (%s)\n", nt_errstr(status));
5064                 correct = false;
5065         }
5066
5067         if (!torture_close_connection(cli1)) {
5068                 correct = false;
5069         }
5070
5071         if (!got_break) {
5072                 correct = false;
5073         }
5074
5075         printf("finished oplock test 4\n");
5076
5077         return correct;
5078 }
5079
5080 static void oplock4_got_break(struct tevent_req *req)
5081 {
5082         struct oplock4_state *state = tevent_req_callback_data(
5083                 req, struct oplock4_state);
5084         uint16_t fnum;
5085         uint8_t level;
5086         NTSTATUS status;
5087
5088         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
5089         TALLOC_FREE(req);
5090         if (!NT_STATUS_IS_OK(status)) {
5091                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5092                        nt_errstr(status));
5093                 return;
5094         }
5095         *state->got_break = true;
5096
5097         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5098                                   NO_OPLOCK);
5099         if (req == NULL) {
5100                 printf("cli_oplock_ack_send failed\n");
5101                 return;
5102         }
5103 }
5104
5105 static void oplock4_got_open(struct tevent_req *req)
5106 {
5107         struct oplock4_state *state = tevent_req_callback_data(
5108                 req, struct oplock4_state);
5109         NTSTATUS status;
5110
5111         status = cli_openx_recv(req, state->fnum2);
5112         if (!NT_STATUS_IS_OK(status)) {
5113                 printf("cli_openx_recv returned %s\n", nt_errstr(status));
5114                 *state->fnum2 = 0xffff;
5115         }
5116 }
5117
5118 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5119
5120 struct oplock5_state {
5121         int pipe_down_fd;
5122 };
5123
5124 /*
5125  * Async open the file that has a kernel oplock, do an echo to get
5126  * that 100% across, close the file to signal to the child fd that the
5127  * oplock can be dropped, wait for the open reply.
5128  */
5129
5130 static void oplock5_opened(struct tevent_req *subreq);
5131 static void oplock5_pong(struct tevent_req *subreq);
5132 static void oplock5_timedout(struct tevent_req *subreq);
5133
5134 static struct tevent_req *oplock5_send(
5135         TALLOC_CTX *mem_ctx,
5136         struct tevent_context *ev,
5137         struct cli_state *cli,
5138         const char *fname,
5139         int pipe_down_fd)
5140 {
5141         struct tevent_req *req = NULL, *subreq = NULL;
5142         struct oplock5_state *state = NULL;
5143         static uint8_t data = 0;
5144
5145         req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5146         if (req == NULL) {
5147                 return NULL;
5148         }
5149         state->pipe_down_fd = pipe_down_fd;
5150
5151         subreq = cli_ntcreate_send(
5152                 state,
5153                 ev,
5154                 cli,
5155                 fname,
5156                 0,                      /* CreatFlags */
5157                 SEC_FILE_READ_DATA,    /* DesiredAccess */
5158                 FILE_ATTRIBUTE_NORMAL,  /* FileAttributes */
5159                 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5160                 FILE_OPEN,               /* CreateDisposition */
5161                 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5162                 0,                       /* Impersonation */
5163                 0);                      /* SecurityFlags */
5164         if (tevent_req_nomem(subreq, req)) {
5165                 return tevent_req_post(req, ev);
5166         }
5167         tevent_req_set_callback(subreq, oplock5_opened, req);
5168
5169         subreq = cli_echo_send(
5170                 state,
5171                 ev,
5172                 cli,
5173                 1,
5174                 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5175         if (tevent_req_nomem(subreq, req)) {
5176                 return tevent_req_post(req, ev);
5177         }
5178         tevent_req_set_callback(subreq, oplock5_pong, req);
5179
5180         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5181         if (tevent_req_nomem(subreq, req)) {
5182                 return tevent_req_post(req, ev);
5183         }
5184         tevent_req_set_callback(subreq, oplock5_timedout, req);
5185
5186         return req;
5187 }
5188
5189 static void oplock5_opened(struct tevent_req *subreq)
5190 {
5191         struct tevent_req *req = tevent_req_callback_data(
5192                 subreq, struct tevent_req);
5193         NTSTATUS status;
5194         uint16_t fnum;
5195
5196         status = cli_ntcreate_recv(subreq, &fnum, NULL);
5197         TALLOC_FREE(subreq);
5198         if (tevent_req_nterror(req, status)) {
5199                 return;
5200         }
5201         tevent_req_done(req);
5202 }
5203
5204 static void oplock5_pong(struct tevent_req *subreq)
5205 {
5206         struct tevent_req *req = tevent_req_callback_data(
5207                 subreq, struct tevent_req);
5208         struct oplock5_state *state = tevent_req_data(
5209                 req, struct oplock5_state);
5210         NTSTATUS status;
5211
5212         status = cli_echo_recv(subreq);
5213         TALLOC_FREE(subreq);
5214         if (tevent_req_nterror(req, status)) {
5215                 return;
5216         }
5217
5218         close(state->pipe_down_fd);
5219 }
5220
5221 static void oplock5_timedout(struct tevent_req *subreq)
5222 {
5223         struct tevent_req *req = tevent_req_callback_data(
5224                 subreq, struct tevent_req);
5225         bool ok;
5226
5227         ok = tevent_wakeup_recv(subreq);
5228         TALLOC_FREE(subreq);
5229         if (!ok) {
5230                 tevent_req_oom(req);
5231                 return;
5232         }
5233         tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5234 }
5235
5236 static NTSTATUS oplock5_recv(struct tevent_req *req)
5237 {
5238         return tevent_req_simple_recv_ntstatus(req);
5239 }
5240
5241 static bool run_oplock5(int dummy)
5242 {
5243         struct tevent_context *ev = NULL;
5244         struct tevent_req *req = NULL;
5245         struct cli_state *cli = NULL;
5246         const char *fname = "oplock5.txt";
5247         int pipe_down[2], pipe_up[2];
5248         pid_t child_pid;
5249         uint8_t c = '\0';
5250         NTSTATUS status;
5251         int ret;
5252         bool ok;
5253
5254         printf("starting oplock5\n");
5255
5256         if (local_path == NULL) {
5257                 d_fprintf(stderr, "oplock5 must be given a local path via "
5258                           "-l <localpath>\n");
5259                 return false;
5260         }
5261
5262         ret = pipe(pipe_down);
5263         if (ret == -1) {
5264                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5265                 return false;
5266         }
5267         ret = pipe(pipe_up);
5268         if (ret == -1) {
5269                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5270                 return false;
5271         }
5272
5273         child_pid = fork();
5274         if (child_pid == -1) {
5275                 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5276                 return false;
5277         }
5278
5279         if (child_pid == 0) {
5280                 char *local_file = NULL;
5281                 int fd;
5282
5283                 close(pipe_down[1]);
5284                 close(pipe_up[0]);
5285
5286                 local_file = talloc_asprintf(
5287                         talloc_tos(), "%s/%s", local_path, fname);
5288                 if (local_file == 0) {
5289                         c = 1;
5290                         goto do_write;
5291                 }
5292                 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5293                 if (fd == -1) {
5294                         d_fprintf(stderr,
5295                                   "open(%s) in child failed: %s\n",
5296                                   local_file,
5297                                   strerror(errno));
5298                         c = 2;
5299                         goto do_write;
5300                 }
5301
5302                 signal(SIGIO, SIG_IGN);
5303
5304                 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5305                 if (ret == -1) {
5306                         d_fprintf(stderr,
5307                                   "SETLEASE in child failed: %s\n",
5308                                   strerror(errno));
5309                         c = 3;
5310                         goto do_write;
5311                 }
5312
5313         do_write:
5314                 ret = sys_write(pipe_up[1], &c, sizeof(c));
5315                 if (ret == -1) {
5316                         d_fprintf(stderr,
5317                                   "sys_write failed: %s\n",
5318                                   strerror(errno));
5319                         exit(4);
5320                 }
5321                 ret = sys_read(pipe_down[0], &c, sizeof(c));
5322                 if (ret == -1) {
5323                         d_fprintf(stderr,
5324                                   "sys_read failed: %s\n",
5325                                   strerror(errno));
5326                         exit(5);
5327                 }
5328                 exit(0);
5329         }
5330
5331         close(pipe_up[1]);
5332         close(pipe_down[0]);
5333
5334         ret = sys_read(pipe_up[0], &c, sizeof(c));
5335         if (ret != 1) {
5336                 d_fprintf(stderr,
5337                           "sys_read failed: %s\n",
5338                           strerror(errno));
5339                 return false;
5340         }
5341         if (c != 0) {
5342                 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5343                 return false;
5344         }
5345
5346         ok = torture_open_connection(&cli, 0);
5347         if (!ok) {
5348                 d_fprintf(stderr, "torture_open_connection failed\n");
5349                 return false;
5350         }
5351
5352         ev = samba_tevent_context_init(talloc_tos());
5353         if (ev == NULL) {
5354                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5355                 return false;
5356         }
5357
5358         req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5359         if (req == NULL) {
5360                 d_fprintf(stderr, "oplock5_send failed\n");
5361                 return false;
5362         }
5363
5364         ok = tevent_req_poll_ntstatus(req, ev, &status);
5365         if (!ok) {
5366                 d_fprintf(stderr,
5367                           "tevent_req_poll_ntstatus failed: %s\n",
5368                           nt_errstr(status));
5369                 return false;
5370         }
5371
5372         status = oplock5_recv(req);
5373         TALLOC_FREE(req);
5374         if (!NT_STATUS_IS_OK(status)) {
5375                 d_fprintf(stderr,
5376                           "oplock5 failed: %s\n",
5377                           nt_errstr(status));
5378                 return false;
5379         }
5380
5381         return true;
5382 }
5383
5384 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5385
5386 /*
5387   Test delete on close semantics.
5388  */
5389 static bool run_deletetest(int dummy)
5390 {
5391         struct cli_state *cli1 = NULL;
5392         struct cli_state *cli2 = NULL;
5393         const char *fname = "\\delete.file";
5394         uint16_t fnum1 = (uint16_t)-1;
5395         uint16_t fnum2 = (uint16_t)-1;
5396         bool correct = false;
5397         NTSTATUS status;
5398
5399         printf("starting delete test\n");
5400
5401         if (!torture_open_connection(&cli1, 0)) {
5402                 return False;
5403         }
5404
5405         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5406
5407         /* Test 1 - this should delete the file on close. */
5408
5409         cli_setatr(cli1, fname, 0, 0);
5410         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5411
5412         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5413                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5414                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5415         if (!NT_STATUS_IS_OK(status)) {
5416                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5417                 goto fail;
5418         }
5419
5420         status = cli_close(cli1, fnum1);
5421         if (!NT_STATUS_IS_OK(status)) {
5422                 printf("[1] close failed (%s)\n", nt_errstr(status));
5423                 goto fail;
5424         }
5425
5426         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5427         if (NT_STATUS_IS_OK(status)) {
5428                 printf("[1] open of %s succeeded (should fail)\n", fname);
5429                 goto fail;
5430         }
5431
5432         printf("first delete on close test succeeded.\n");
5433
5434         /* Test 2 - this should delete the file on close. */
5435
5436         cli_setatr(cli1, fname, 0, 0);
5437         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5438
5439         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5440                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5441                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5442         if (!NT_STATUS_IS_OK(status)) {
5443                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5444                 goto fail;
5445         }
5446
5447         status = cli_nt_delete_on_close(cli1, fnum1, true);
5448         if (!NT_STATUS_IS_OK(status)) {
5449                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5450                 goto fail;
5451         }
5452
5453         status = cli_close(cli1, fnum1);
5454         if (!NT_STATUS_IS_OK(status)) {
5455                 printf("[2] close failed (%s)\n", nt_errstr(status));
5456                 goto fail;
5457         }
5458
5459         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5460         if (NT_STATUS_IS_OK(status)) {
5461                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5462                 status = cli_close(cli1, fnum1);
5463                 if (!NT_STATUS_IS_OK(status)) {
5464                         printf("[2] close failed (%s)\n", nt_errstr(status));
5465                 }
5466                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5467                 goto fail;
5468         }
5469
5470         printf("second delete on close test succeeded.\n");
5471
5472         /* Test 3 - ... */
5473         cli_setatr(cli1, fname, 0, 0);
5474         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5475
5476         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5477                               FILE_ATTRIBUTE_NORMAL,
5478                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5479                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5480         if (!NT_STATUS_IS_OK(status)) {
5481                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5482                 goto fail;
5483         }
5484
5485         /* This should fail with a sharing violation - open for delete is only compatible
5486            with SHARE_DELETE. */
5487
5488         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5489                               FILE_ATTRIBUTE_NORMAL,
5490                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5491                               FILE_OPEN, 0, 0, &fnum2, NULL);
5492         if (NT_STATUS_IS_OK(status)) {
5493                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
5494                 goto fail;
5495         }
5496
5497         /* This should succeed. */
5498         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5499                              FILE_ATTRIBUTE_NORMAL,
5500                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5501                              FILE_OPEN, 0, 0, &fnum2, NULL);
5502         if (!NT_STATUS_IS_OK(status)) {
5503                 printf("[3] open  - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5504                 goto fail;
5505         }
5506
5507         status = cli_nt_delete_on_close(cli1, fnum1, true);
5508         if (!NT_STATUS_IS_OK(status)) {
5509                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5510                 goto fail;
5511         }
5512
5513         status = cli_close(cli1, fnum1);
5514         if (!NT_STATUS_IS_OK(status)) {
5515                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5516                 goto fail;
5517         }
5518
5519         status = cli_close(cli1, fnum2);
5520         if (!NT_STATUS_IS_OK(status)) {
5521                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5522                 goto fail;
5523         }
5524
5525         /* This should fail - file should no longer be there. */
5526
5527         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5528         if (NT_STATUS_IS_OK(status)) {
5529                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5530                 status = cli_close(cli1, fnum1);
5531                 if (!NT_STATUS_IS_OK(status)) {
5532                         printf("[3] close failed (%s)\n", nt_errstr(status));
5533                 }
5534                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5535                 goto fail;
5536         }
5537
5538         printf("third delete on close test succeeded.\n");
5539
5540         /* Test 4 ... */
5541         cli_setatr(cli1, fname, 0, 0);
5542         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5543
5544         status = cli_ntcreate(cli1, fname, 0,
5545                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5546                               FILE_ATTRIBUTE_NORMAL,
5547                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5548                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5549         if (!NT_STATUS_IS_OK(status)) {
5550                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5551                 goto fail;
5552         }
5553
5554         /* This should succeed. */
5555         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5556                              FILE_ATTRIBUTE_NORMAL,
5557                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5558                              FILE_OPEN, 0, 0, &fnum2, NULL);
5559         if (!NT_STATUS_IS_OK(status)) {
5560                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5561                 goto fail;
5562         }
5563
5564         status = cli_close(cli1, fnum2);
5565         if (!NT_STATUS_IS_OK(status)) {
5566                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5567                 goto fail;
5568         }
5569
5570         status = cli_nt_delete_on_close(cli1, fnum1, true);
5571         if (!NT_STATUS_IS_OK(status)) {
5572                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5573                 goto fail;
5574         }
5575
5576         /* This should fail - no more opens once delete on close set. */
5577         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5578                               FILE_ATTRIBUTE_NORMAL,
5579                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5580                               FILE_OPEN, 0, 0, &fnum2, NULL);
5581         if (NT_STATUS_IS_OK(status)) {
5582                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
5583                 goto fail;
5584         }
5585
5586         status = cli_close(cli1, fnum1);
5587         if (!NT_STATUS_IS_OK(status)) {
5588                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5589                 goto fail;
5590         }
5591
5592         printf("fourth delete on close test succeeded.\n");
5593
5594         /* Test 5 ... */
5595         cli_setatr(cli1, fname, 0, 0);
5596         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5597
5598         status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5599         if (!NT_STATUS_IS_OK(status)) {
5600                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5601                 goto fail;
5602         }
5603
5604         /* This should fail - only allowed on NT opens with DELETE access. */
5605
5606         status = cli_nt_delete_on_close(cli1, fnum1, true);
5607         if (NT_STATUS_IS_OK(status)) {
5608                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5609                 goto fail;
5610         }
5611
5612         status = cli_close(cli1, fnum1);
5613         if (!NT_STATUS_IS_OK(status)) {
5614                 printf("[5] close failed (%s)\n", nt_errstr(status));
5615                 goto fail;
5616         }
5617
5618         printf("fifth delete on close test succeeded.\n");
5619
5620         /* Test 6 ... */
5621         cli_setatr(cli1, fname, 0, 0);
5622         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5623
5624         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5625                              FILE_ATTRIBUTE_NORMAL,
5626                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5627                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5628         if (!NT_STATUS_IS_OK(status)) {
5629                 printf("[6] open of %s failed (%s)\n", fname,
5630                        nt_errstr(status));
5631                 goto fail;
5632         }
5633
5634         /* This should fail - only allowed on NT opens with DELETE access. */
5635
5636         status = cli_nt_delete_on_close(cli1, fnum1, true);
5637         if (NT_STATUS_IS_OK(status)) {
5638                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5639                 goto fail;
5640         }
5641
5642         status = cli_close(cli1, fnum1);
5643         if (!NT_STATUS_IS_OK(status)) {
5644                 printf("[6] close failed (%s)\n", nt_errstr(status));
5645                 goto fail;
5646         }
5647
5648         printf("sixth delete on close test succeeded.\n");
5649
5650         /* Test 7 ... */
5651         cli_setatr(cli1, fname, 0, 0);
5652         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5653
5654         status = cli_ntcreate(cli1, fname, 0,
5655                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5656                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5657                               0, 0, &fnum1, NULL);
5658         if (!NT_STATUS_IS_OK(status)) {
5659                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5660                 goto fail;
5661         }
5662
5663         status = cli_nt_delete_on_close(cli1, fnum1, true);
5664         if (!NT_STATUS_IS_OK(status)) {
5665                 printf("[7] setting delete_on_close on file failed !\n");
5666                 goto fail;
5667         }
5668
5669         status = cli_nt_delete_on_close(cli1, fnum1, false);
5670         if (!NT_STATUS_IS_OK(status)) {
5671                 printf("[7] unsetting delete_on_close on file failed !\n");
5672                 goto fail;
5673         }
5674
5675         status = cli_close(cli1, fnum1);
5676         if (!NT_STATUS_IS_OK(status)) {
5677                 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5678                 goto fail;
5679         }
5680
5681         /* This next open should succeed - we reset the flag. */
5682         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5683         if (!NT_STATUS_IS_OK(status)) {
5684                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5685                 goto fail;
5686         }
5687
5688         status = cli_close(cli1, fnum1);
5689         if (!NT_STATUS_IS_OK(status)) {
5690                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5691                 goto fail;
5692         }
5693
5694         printf("seventh delete on close test succeeded.\n");
5695
5696         /* Test 8 ... */
5697         cli_setatr(cli1, fname, 0, 0);
5698         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5699
5700         if (!torture_open_connection(&cli2, 1)) {
5701                 printf("[8] failed to open second connection.\n");
5702                 goto fail;
5703         }
5704
5705         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5706
5707         status = cli_ntcreate(cli1, fname, 0,
5708                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5709                              FILE_ATTRIBUTE_NORMAL,
5710                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5711                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5712         if (!NT_STATUS_IS_OK(status)) {
5713                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5714                 goto fail;
5715         }
5716
5717         status = cli_ntcreate(cli2, fname, 0,
5718                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5719                              FILE_ATTRIBUTE_NORMAL,
5720                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5721                              FILE_OPEN, 0, 0, &fnum2, NULL);
5722         if (!NT_STATUS_IS_OK(status)) {
5723                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5724                 goto fail;
5725         }
5726
5727         status = cli_nt_delete_on_close(cli1, fnum1, true);
5728         if (!NT_STATUS_IS_OK(status)) {
5729                 printf("[8] setting delete_on_close on file failed !\n");
5730                 goto fail;
5731         }
5732
5733         status = cli_close(cli1, fnum1);
5734         if (!NT_STATUS_IS_OK(status)) {
5735                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5736                 goto fail;
5737         }
5738
5739         status = cli_close(cli2, fnum2);
5740         if (!NT_STATUS_IS_OK(status)) {
5741                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5742                 goto fail;
5743         }
5744
5745         /* This should fail.. */
5746         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5747         if (NT_STATUS_IS_OK(status)) {
5748                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5749                 goto fail;
5750         }
5751
5752         printf("eighth delete on close test succeeded.\n");
5753
5754         /* Test 9 ... */
5755
5756         /* This should fail - we need to set DELETE_ACCESS. */
5757         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5758                               FILE_ATTRIBUTE_NORMAL,
5759                               FILE_SHARE_NONE,
5760                               FILE_OVERWRITE_IF,
5761                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5762         if (NT_STATUS_IS_OK(status)) {
5763                 printf("[9] open of %s succeeded should have failed!\n", fname);
5764                 goto fail;
5765         }
5766
5767         printf("ninth delete on close test succeeded.\n");
5768
5769         /* Test 10 ... */
5770
5771         status = cli_ntcreate(cli1, fname, 0,
5772                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5773                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5774                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5775                              0, &fnum1, NULL);
5776         if (!NT_STATUS_IS_OK(status)) {
5777                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5778                 goto fail;
5779         }
5780
5781         /* This should delete the file. */
5782         status = cli_close(cli1, fnum1);
5783         if (!NT_STATUS_IS_OK(status)) {
5784                 printf("[10] close failed (%s)\n", nt_errstr(status));
5785                 goto fail;
5786         }
5787
5788         /* This should fail.. */
5789         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5790         if (NT_STATUS_IS_OK(status)) {
5791                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5792                 goto fail;
5793         }
5794
5795         printf("tenth delete on close test succeeded.\n");
5796
5797         /* Test 11 ... */
5798
5799         cli_setatr(cli1, fname, 0, 0);
5800         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5801
5802         /* Can we open a read-only file with delete access? */
5803
5804         /* Create a readonly file. */
5805         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5806                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5807                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5808         if (!NT_STATUS_IS_OK(status)) {
5809                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5810                 goto fail;
5811         }
5812
5813         status = cli_close(cli1, fnum1);
5814         if (!NT_STATUS_IS_OK(status)) {
5815                 printf("[11] close failed (%s)\n", nt_errstr(status));
5816                 goto fail;
5817         }
5818
5819         /* Now try open for delete access. */
5820         status = cli_ntcreate(cli1, fname, 0,
5821                              FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5822                              0,
5823                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5824                              FILE_OPEN, 0, 0, &fnum1, NULL);
5825         if (!NT_STATUS_IS_OK(status)) {
5826                 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5827                 goto fail;
5828         }
5829
5830         cli_close(cli1, fnum1);
5831
5832         printf("eleventh delete on close test succeeded.\n");
5833
5834         /*
5835          * Test 12
5836          * like test 4 but with initial delete on close
5837          */
5838
5839         cli_setatr(cli1, fname, 0, 0);
5840         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5841
5842         status = cli_ntcreate(cli1, fname, 0,
5843                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5844                               FILE_ATTRIBUTE_NORMAL,
5845                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5846                               FILE_OVERWRITE_IF,
5847                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5848         if (!NT_STATUS_IS_OK(status)) {
5849                 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5850                 goto fail;
5851         }
5852
5853         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5854                               FILE_ATTRIBUTE_NORMAL,
5855                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5856                               FILE_OPEN, 0, 0, &fnum2, NULL);
5857         if (!NT_STATUS_IS_OK(status)) {
5858                 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5859                 goto fail;
5860         }
5861
5862         status = cli_close(cli1, fnum2);
5863         if (!NT_STATUS_IS_OK(status)) {
5864                 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5865                 goto fail;
5866         }
5867
5868         status = cli_nt_delete_on_close(cli1, fnum1, true);
5869         if (!NT_STATUS_IS_OK(status)) {
5870                 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5871                 goto fail;
5872         }
5873
5874         /* This should fail - no more opens once delete on close set. */
5875         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5876                               FILE_ATTRIBUTE_NORMAL,
5877                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5878                               FILE_OPEN, 0, 0, &fnum2, NULL);
5879         if (NT_STATUS_IS_OK(status)) {
5880                 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5881                 goto fail;
5882         }
5883
5884         status = cli_nt_delete_on_close(cli1, fnum1, false);
5885         if (!NT_STATUS_IS_OK(status)) {
5886                 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5887                 goto fail;
5888         }
5889
5890         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5891                               FILE_ATTRIBUTE_NORMAL,
5892                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5893                               FILE_OPEN, 0, 0, &fnum2, NULL);
5894         if (!NT_STATUS_IS_OK(status)) {
5895                 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5896                 goto fail;
5897         }
5898
5899         status = cli_close(cli1, fnum2);
5900         if (!NT_STATUS_IS_OK(status)) {
5901                 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5902                 goto fail;
5903         }
5904
5905         status = cli_close(cli1, fnum1);
5906         if (!NT_STATUS_IS_OK(status)) {
5907                 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5908                 goto fail;
5909         }
5910
5911         /*
5912          * setting delete on close on the handle does
5913          * not unset the initial delete on close...
5914          */
5915         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5916                               FILE_ATTRIBUTE_NORMAL,
5917                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5918                               FILE_OPEN, 0, 0, &fnum2, NULL);
5919         if (NT_STATUS_IS_OK(status)) {
5920                 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5921                 goto fail;
5922         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5923                 printf("ntcreate returned %s, expected "
5924                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5925                        nt_errstr(status));
5926                 goto fail;
5927         }
5928
5929         printf("twelfth delete on close test succeeded.\n");
5930
5931
5932         printf("finished delete test\n");
5933
5934         correct = true;
5935
5936   fail:
5937         /* FIXME: This will crash if we aborted before cli2 got
5938          * initialized, because these functions don't handle
5939          * uninitialized connections. */
5940
5941         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5942         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5943         cli_setatr(cli1, fname, 0, 0);
5944         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5945
5946         if (cli1 && !torture_close_connection(cli1)) {
5947                 correct = False;
5948         }
5949         if (cli2 && !torture_close_connection(cli2)) {
5950                 correct = False;
5951         }
5952         return correct;
5953 }
5954
5955 struct delete_stream_state {
5956         bool closed;
5957 };
5958
5959 static void delete_stream_unlinked(struct tevent_req *subreq);
5960 static void delete_stream_closed(struct tevent_req *subreq);
5961
5962 static struct tevent_req *delete_stream_send(
5963         TALLOC_CTX *mem_ctx,
5964         struct tevent_context *ev,
5965         struct cli_state *cli,
5966         const char *base_fname,
5967         uint16_t stream_fnum)
5968 {
5969         struct tevent_req *req = NULL, *subreq = NULL;
5970         struct delete_stream_state *state = NULL;
5971
5972         req = tevent_req_create(
5973                 mem_ctx, &state, struct delete_stream_state);
5974         if (req == NULL) {
5975                 return NULL;
5976         }
5977
5978         subreq = cli_unlink_send(
5979                 state,
5980                 ev,
5981                 cli,
5982                 base_fname,
5983                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5984         if (tevent_req_nomem(subreq, req)) {
5985                 return tevent_req_post(req, ev);
5986         }
5987         tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5988
5989         subreq = cli_close_send(state, ev, cli, stream_fnum, 0);
5990         if (tevent_req_nomem(subreq, req)) {
5991                 return tevent_req_post(req, ev);
5992         }
5993         tevent_req_set_callback(subreq, delete_stream_closed, req);
5994
5995         return req;
5996 }
5997
5998 static void delete_stream_unlinked(struct tevent_req *subreq)
5999 {
6000         struct tevent_req *req = tevent_req_callback_data(
6001                 subreq, struct tevent_req);
6002         struct delete_stream_state *state = tevent_req_data(
6003                 req, struct delete_stream_state);
6004         NTSTATUS status;
6005
6006         status = cli_unlink_recv(subreq);
6007         TALLOC_FREE(subreq);
6008         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6009                 printf("cli_unlink returned %s\n",
6010                        nt_errstr(status));
6011                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6012                 return;
6013         }
6014         if (!state->closed) {
6015                 /* close reply should have come in first */
6016                 printf("Not closed\n");
6017                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6018                 return;
6019         }
6020         tevent_req_done(req);
6021 }
6022
6023 static void delete_stream_closed(struct tevent_req *subreq)
6024 {
6025         struct tevent_req *req = tevent_req_callback_data(
6026                 subreq, struct tevent_req);
6027         struct delete_stream_state *state = tevent_req_data(
6028                 req, struct delete_stream_state);
6029         NTSTATUS status;
6030
6031         status = cli_close_recv(subreq);
6032         TALLOC_FREE(subreq);
6033         if (tevent_req_nterror(req, status)) {
6034                 return;
6035         }
6036         /* also waiting for the unlink to come back */
6037         state->closed = true;
6038 }
6039
6040 static NTSTATUS delete_stream_recv(struct tevent_req *req)
6041 {
6042         return tevent_req_simple_recv_ntstatus(req);
6043 }
6044
6045 static bool run_delete_stream(int dummy)
6046 {
6047         struct tevent_context *ev = NULL;
6048         struct tevent_req *req = NULL;
6049         struct cli_state *cli = NULL;
6050         const char fname[] = "delete_stream";
6051         const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
6052         uint16_t fnum1, fnum2;
6053         NTSTATUS status;
6054         bool ok;
6055
6056         printf("Starting stream delete test\n");
6057
6058         ok = torture_open_connection(&cli, 0);
6059         if (!ok) {
6060                 return false;
6061         }
6062
6063         cli_setatr(cli, fname, 0, 0);
6064         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6065
6066         /* Create the file. */
6067         status = cli_ntcreate(
6068                 cli,
6069                 fname,
6070                 0,
6071                 READ_CONTROL_ACCESS,
6072                 0,
6073                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6074                 FILE_CREATE,
6075                 0x0,
6076                 0x0,
6077                 &fnum1,
6078                 NULL);
6079         if (!NT_STATUS_IS_OK(status)) {
6080                 d_fprintf(stderr,
6081                           "cli_ntcreate of %s failed (%s)\n",
6082                           fname,
6083                           nt_errstr(status));
6084                 return false;
6085         }
6086         status = cli_close(cli, fnum1);
6087         if (!NT_STATUS_IS_OK(status)) {
6088                 d_fprintf(stderr,
6089                           "cli_close of %s failed (%s)\n",
6090                           fname,
6091                           nt_errstr(status));
6092                 return false;
6093         }
6094
6095         /* Now create the stream. */
6096         status = cli_ntcreate(
6097                 cli,
6098                 fname_stream,
6099                 0,
6100                 FILE_WRITE_DATA,
6101                 0,
6102                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6103                 FILE_CREATE,
6104                 0x0,
6105                 0x0,
6106                 &fnum1,
6107                 NULL);
6108
6109         if (!NT_STATUS_IS_OK(status)) {
6110                 d_fprintf(stderr,
6111                           "cli_ntcreate of %s failed (%s)\n",
6112                           fname_stream,
6113                           nt_errstr(status));
6114                 return false;
6115         }
6116
6117         /* open it a second time */
6118
6119         status = cli_ntcreate(
6120                 cli,
6121                 fname_stream,
6122                 0,
6123                 FILE_WRITE_DATA,
6124                 0,
6125                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6126                 FILE_OPEN,
6127                 0x0,
6128                 0x0,
6129                 &fnum2,
6130                 NULL);
6131
6132         if (!NT_STATUS_IS_OK(status)) {
6133                 d_fprintf(stderr,
6134                           "2nd cli_ntcreate of %s failed (%s)\n",
6135                           fname_stream,
6136                           nt_errstr(status));
6137                 return false;
6138         }
6139
6140         ev = samba_tevent_context_init(talloc_tos());
6141         if (ev == NULL) {
6142                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
6143                 return false;
6144         }
6145
6146         req = delete_stream_send(ev, ev, cli, fname, fnum1);
6147         if (req == NULL) {
6148                 d_fprintf(stderr, "delete_stream_send failed\n");
6149                 return false;
6150         }
6151
6152         ok = tevent_req_poll_ntstatus(req, ev, &status);
6153         if (!ok) {
6154                 d_fprintf(stderr,
6155                           "tevent_req_poll_ntstatus failed: %s\n",
6156                           nt_errstr(status));
6157                 return false;
6158         }
6159
6160         status = delete_stream_recv(req);
6161         TALLOC_FREE(req);
6162         if (!NT_STATUS_IS_OK(status)) {
6163                 d_fprintf(stderr,
6164                           "delete_stream failed: %s\n",
6165                           nt_errstr(status));
6166                 return false;
6167         }
6168
6169         status = cli_close(cli, fnum2);
6170         if (!NT_STATUS_IS_OK(status)) {
6171                 d_fprintf(stderr,
6172                           "close failed: %s\n",
6173                           nt_errstr(status));
6174                 return false;
6175         }
6176
6177         status = cli_unlink(
6178                 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6179         if (!NT_STATUS_IS_OK(status)) {
6180                 d_fprintf(stderr,
6181                           "unlink failed: %s\n",
6182                           nt_errstr(status));
6183                 return false;
6184         }
6185
6186         return true;
6187 }
6188
6189 /*
6190   Exercise delete on close semantics - use on the PRINT1 share in torture
6191   testing.
6192  */
6193 static bool run_delete_print_test(int dummy)
6194 {
6195         struct cli_state *cli1 = NULL;
6196         const char *fname = "print_delete.file";
6197         uint16_t fnum1 = (uint16_t)-1;
6198         bool correct = false;
6199         const char *buf = "print file data\n";
6200         NTSTATUS status;
6201
6202         printf("starting print delete test\n");
6203
6204         if (!torture_open_connection(&cli1, 0)) {
6205                 return false;
6206         }
6207
6208         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6209
6210         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6211                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6212                               0, 0, &fnum1, NULL);
6213         if (!NT_STATUS_IS_OK(status)) {
6214                 printf("open of %s failed (%s)\n",
6215                         fname,
6216                         nt_errstr(status));
6217                 goto fail;
6218         }
6219
6220         status = cli_writeall(cli1,
6221                         fnum1,
6222                         0,
6223                         (const uint8_t *)buf,
6224                         0, /* offset */
6225                         strlen(buf), /* size */
6226                         NULL);
6227         if (!NT_STATUS_IS_OK(status)) {
6228                 printf("writing print file data failed (%s)\n",
6229                         nt_errstr(status));
6230                 goto fail;
6231         }
6232
6233         status = cli_nt_delete_on_close(cli1, fnum1, true);
6234         if (!NT_STATUS_IS_OK(status)) {
6235                 printf("setting delete_on_close failed (%s)\n",
6236                         nt_errstr(status));
6237                 goto fail;
6238         }
6239
6240         status = cli_close(cli1, fnum1);
6241         if (!NT_STATUS_IS_OK(status)) {
6242                 printf("close failed (%s)\n", nt_errstr(status));
6243                 goto fail;
6244         }
6245
6246         printf("finished print delete test\n");
6247
6248         correct = true;
6249
6250   fail:
6251
6252         if (fnum1 != (uint16_t)-1) {
6253                 cli_close(cli1, fnum1);
6254         }
6255
6256         if (cli1 && !torture_close_connection(cli1)) {
6257                 correct = false;
6258         }
6259         return correct;
6260 }
6261
6262 static bool run_deletetest_ln(int dummy)
6263 {
6264         struct cli_state *cli;
6265         const char *fname = "\\delete1";
6266         const char *fname_ln = "\\delete1_ln";
6267         uint16_t fnum;
6268         uint16_t fnum1;
6269         NTSTATUS status;
6270         bool correct = true;
6271         time_t t;
6272
6273         printf("starting deletetest-ln\n");
6274
6275         if (!torture_open_connection(&cli, 0)) {
6276                 return false;
6277         }
6278
6279         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6280         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6281
6282         smbXcli_conn_set_sockopt(cli->conn, sockops);
6283
6284         /* Create the file. */
6285         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6286         if (!NT_STATUS_IS_OK(status)) {
6287                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6288                 return false;
6289         }
6290
6291         status = cli_close(cli, fnum);
6292         if (!NT_STATUS_IS_OK(status)) {
6293                 printf("close1 failed (%s)\n", nt_errstr(status));
6294                 return false;
6295         }
6296
6297         /* Now create a hardlink. */
6298         status = cli_hardlink(cli, fname, fname_ln);
6299         if (!NT_STATUS_IS_OK(status)) {
6300                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6301                 return false;
6302         }
6303
6304         /* Open the original file. */
6305         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6306                         FILE_ATTRIBUTE_NORMAL,
6307                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6308                         FILE_OPEN_IF, 0, 0, &fnum, NULL);
6309         if (!NT_STATUS_IS_OK(status)) {
6310                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6311                 return false;
6312         }
6313
6314         /* Unlink the hard link path. */
6315         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6316                         FILE_ATTRIBUTE_NORMAL,
6317                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6318                         FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6319         if (!NT_STATUS_IS_OK(status)) {
6320                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6321                 return false;
6322         }
6323         status = cli_nt_delete_on_close(cli, fnum1, true);
6324         if (!NT_STATUS_IS_OK(status)) {
6325                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6326                         __location__, fname_ln, nt_errstr(status));
6327                 return false;
6328         }
6329
6330         status = cli_close(cli, fnum1);
6331         if (!NT_STATUS_IS_OK(status)) {
6332                 printf("close %s failed (%s)\n",
6333                         fname_ln, nt_errstr(status));
6334                 return false;
6335         }
6336
6337         status = cli_close(cli, fnum);
6338         if (!NT_STATUS_IS_OK(status)) {
6339                 printf("close %s failed (%s)\n",
6340                         fname, nt_errstr(status));
6341                 return false;
6342         }
6343
6344         /* Ensure the original file is still there. */
6345         status = cli_getatr(cli, fname, NULL, NULL, &t);
6346         if (!NT_STATUS_IS_OK(status)) {
6347                 printf("%s getatr on file %s failed (%s)\n",
6348                         __location__,
6349                         fname,
6350                         nt_errstr(status));
6351                 correct = False;
6352         }
6353
6354         /* Ensure the link path is gone. */
6355         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6356         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6357                 printf("%s, getatr for file %s returned wrong error code %s "
6358                         "- should have been deleted\n",
6359                         __location__,
6360                         fname_ln, nt_errstr(status));
6361                 correct = False;
6362         }
6363
6364         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6365         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6366
6367         if (!torture_close_connection(cli)) {
6368                 correct = false;
6369         }
6370
6371         printf("finished deletetest-ln\n");
6372
6373         return correct;
6374 }
6375
6376 /*
6377   print out server properties
6378  */
6379 static bool run_properties(int dummy)
6380 {
6381         struct cli_state *cli;
6382         bool correct = True;
6383
6384         printf("starting properties test\n");
6385
6386         ZERO_STRUCT(cli);
6387
6388         if (!torture_open_connection(&cli, 0)) {
6389                 return False;
6390         }
6391
6392         smbXcli_conn_set_sockopt(cli->conn, sockops);
6393
6394         d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6395
6396         if (!torture_close_connection(cli)) {
6397                 correct = False;
6398         }
6399
6400         return correct;
6401 }
6402
6403
6404
6405 /* FIRST_DESIRED_ACCESS   0xf019f */
6406 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6407                                FILE_READ_EA|                           /* 0xf */ \
6408                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
6409                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
6410                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
6411                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
6412 /* SECOND_DESIRED_ACCESS  0xe0080 */
6413 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6414                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6415                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
6416
6417 #if 0
6418 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6419                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6420                                FILE_READ_DATA|\
6421                                WRITE_OWNER_ACCESS                      /* */
6422 #endif
6423
6424 /*
6425   Test ntcreate calls made by xcopy
6426  */
6427 static bool run_xcopy(int dummy)
6428 {
6429         static struct cli_state *cli1;
6430         const char *fname = "\\test.txt";
6431         bool correct = True;
6432         uint16_t fnum1, fnum2;
6433         NTSTATUS status;
6434
6435         printf("starting xcopy test\n");
6436
6437         if (!torture_open_connection(&cli1, 0)) {
6438                 return False;
6439         }
6440
6441         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6442                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6443                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6444         if (!NT_STATUS_IS_OK(status)) {
6445                 printf("First open failed - %s\n", nt_errstr(status));
6446                 return False;
6447         }
6448
6449         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6450                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6451                              FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6452         if (!NT_STATUS_IS_OK(status)) {
6453                 printf("second open failed - %s\n", nt_errstr(status));
6454                 return False;
6455         }
6456
6457         if (!torture_close_connection(cli1)) {
6458                 correct = False;
6459         }
6460
6461         return correct;
6462 }
6463
6464 /*
6465   Test rename on files open with share delete and no share delete.
6466  */
6467 static bool run_rename(int dummy)
6468 {
6469         static struct cli_state *cli1;
6470         const char *fname = "\\test.txt";
6471         const char *fname1 = "\\test1.txt";
6472         bool correct = True;
6473         uint16_t fnum1;
6474         uint32_t attr;
6475         NTSTATUS status;
6476
6477         printf("starting rename test\n");
6478
6479         if (!torture_open_connection(&cli1, 0)) {
6480                 return False;
6481         }
6482
6483         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6484         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6485
6486         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6487                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6488                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6489         if (!NT_STATUS_IS_OK(status)) {
6490                 printf("First open failed - %s\n", nt_errstr(status));
6491                 return False;
6492         }
6493
6494         status = cli_rename(cli1, fname, fname1, false);
6495         if (!NT_STATUS_IS_OK(status)) {
6496                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6497         } else {
6498                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6499                 correct = False;
6500         }
6501
6502         status = cli_close(cli1, fnum1);
6503         if (!NT_STATUS_IS_OK(status)) {
6504                 printf("close - 1 failed (%s)\n", nt_errstr(status));
6505                 return False;
6506         }
6507
6508         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6509         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6510         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6511 #if 0
6512                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
6513 #else
6514                               FILE_SHARE_DELETE|FILE_SHARE_READ,
6515 #endif
6516                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6517         if (!NT_STATUS_IS_OK(status)) {
6518                 printf("Second open failed - %s\n", nt_errstr(status));
6519                 return False;
6520         }
6521
6522         status = cli_rename(cli1, fname, fname1, false);
6523         if (!NT_STATUS_IS_OK(status)) {
6524                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6525                 correct = False;
6526         } else {
6527                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6528         }
6529
6530         status = cli_close(cli1, fnum1);
6531         if (!NT_STATUS_IS_OK(status)) {
6532                 printf("close - 2 failed (%s)\n", nt_errstr(status));
6533                 return False;
6534         }
6535
6536         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6537         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6538
6539         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6540                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6541                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6542         if (!NT_STATUS_IS_OK(status)) {
6543                 printf("Third open failed - %s\n", nt_errstr(status));
6544                 return False;
6545         }
6546
6547
6548         status = cli_rename(cli1, fname, fname1, false);
6549         if (!NT_STATUS_IS_OK(status)) {
6550                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6551                 correct = False;
6552         } else {
6553                 printf("Third rename succeeded (SHARE_NONE)\n");
6554         }
6555
6556         status = cli_close(cli1, fnum1);
6557         if (!NT_STATUS_IS_OK(status)) {
6558                 printf("close - 3 failed (%s)\n", nt_errstr(status));
6559                 return False;
6560         }
6561
6562         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6563         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6564
6565         /*----*/
6566
6567         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6568                               FILE_ATTRIBUTE_NORMAL,
6569                               FILE_SHARE_READ | FILE_SHARE_WRITE,
6570                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6571         if (!NT_STATUS_IS_OK(status)) {
6572                 printf("Fourth open failed - %s\n", nt_errstr(status));
6573                 return False;
6574         }
6575
6576         status = cli_rename(cli1, fname, fname1, false);
6577         if (!NT_STATUS_IS_OK(status)) {
6578                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6579         } else {
6580                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6581                 correct = False;
6582         }
6583
6584         status = cli_close(cli1, fnum1);
6585         if (!NT_STATUS_IS_OK(status)) {
6586                 printf("close - 4 failed (%s)\n", nt_errstr(status));
6587                 return False;
6588         }
6589
6590         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6591         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6592
6593         /*--*/
6594
6595         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6596                          FILE_ATTRIBUTE_NORMAL,
6597                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6598                          FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6599         if (!NT_STATUS_IS_OK(status)) {
6600                 printf("Fifth open failed - %s\n", nt_errstr(status));
6601                 return False;
6602         }
6603
6604         status = cli_rename(cli1, fname, fname1, false);
6605         if (!NT_STATUS_IS_OK(status)) {
6606                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6607                 correct = False;
6608         } else {
6609                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6610         }
6611
6612         /*--*/
6613         status = cli_close(cli1, fnum1);
6614         if (!NT_STATUS_IS_OK(status)) {
6615                 printf("close - 5 failed (%s)\n", nt_errstr(status));
6616                 return False;
6617         }
6618
6619         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6620         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6621         if (!NT_STATUS_IS_OK(status)) {
6622                 printf("getatr on file %s failed - %s ! \n",
6623                         fname1, nt_errstr(status));
6624                 correct = False;
6625         } else {
6626                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6627                         printf("Renamed file %s has wrong attr 0x%x "
6628                                 "(should be 0x%x)\n",
6629                                 fname1,
6630                                 attr,
6631                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6632                         correct = False;
6633                 } else {
6634                         printf("Renamed file %s has archive bit set\n", fname1);
6635                 }
6636         }
6637
6638         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6639         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6640
6641         if (!torture_close_connection(cli1)) {
6642                 correct = False;
6643         }
6644
6645         return correct;
6646 }
6647
6648 /*
6649   Test rename into a directory with an ACL denying it.
6650  */
6651 static bool run_rename_access(int dummy)
6652 {
6653         static struct cli_state *cli = NULL;
6654         static struct cli_state *posix_cli = NULL;
6655         const char *src = "test.txt";
6656         const char *dname = "dir";
6657         const char *dst = "dir\\test.txt";
6658         const char *dsrc = "test.dir";
6659         const char *ddst = "dir\\test.dir";
6660         uint16_t fnum = (uint16_t)-1;
6661         struct security_descriptor *sd = NULL;
6662         struct security_descriptor *newsd = NULL;
6663         NTSTATUS status;
6664         TALLOC_CTX *frame = NULL;
6665
6666         frame = talloc_stackframe();
6667         printf("starting rename access test\n");
6668
6669         /* Windows connection. */
6670         if (!torture_open_connection(&cli, 0)) {
6671                 goto fail;
6672         }
6673
6674         smbXcli_conn_set_sockopt(cli->conn, sockops);
6675
6676         /* Posix connection. */
6677         if (!torture_open_connection(&posix_cli, 0)) {
6678                 goto fail;
6679         }
6680
6681         smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6682
6683         status = torture_setup_unix_extensions(posix_cli);
6684         if (!NT_STATUS_IS_OK(status)) {
6685                 goto fail;
6686         }
6687
6688         /* Start with a clean slate. */
6689         cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6690         cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6691         cli_rmdir(cli, dsrc);
6692         cli_rmdir(cli, ddst);
6693         cli_rmdir(cli, dname);
6694
6695         /*
6696          * Setup the destination directory with a DENY ACE to
6697          * prevent new files within it.
6698          */
6699         status = cli_ntcreate(cli,
6700                                 dname,
6701                                 0,
6702                                 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6703                                         WRITE_DAC_ACCESS|FILE_READ_DATA|
6704                                         WRITE_OWNER_ACCESS,
6705                                 FILE_ATTRIBUTE_DIRECTORY,
6706                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6707                                 FILE_CREATE,
6708                                 FILE_DIRECTORY_FILE,
6709                                 0,
6710                                 &fnum,
6711                                 NULL);
6712         if (!NT_STATUS_IS_OK(status)) {
6713                 printf("Create of %s - %s\n", dname, nt_errstr(status));
6714                 goto fail;
6715         }
6716
6717         status = cli_query_secdesc(cli,
6718                                 fnum,
6719                                 frame,
6720                                 &sd);
6721         if (!NT_STATUS_IS_OK(status)) {
6722                 printf("cli_query_secdesc failed for %s (%s)\n",
6723                         dname, nt_errstr(status));
6724                 goto fail;
6725         }
6726
6727         newsd = security_descriptor_dacl_create(frame,
6728                                         0,
6729                                         NULL,
6730                                         NULL,
6731                                         SID_WORLD,
6732                                         SEC_ACE_TYPE_ACCESS_DENIED,
6733                                         SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6734                                         0,
6735                                         NULL);
6736         if (newsd == NULL) {
6737                 goto fail;
6738         }
6739         sd->dacl = security_acl_concatenate(frame,
6740                                         newsd->dacl,
6741                                         sd->dacl);
6742         if (sd->dacl == NULL) {
6743                 goto fail;
6744         }
6745         status = cli_set_secdesc(cli, fnum, sd);
6746         if (!NT_STATUS_IS_OK(status)) {
6747                 printf("cli_set_secdesc failed for %s (%s)\n",
6748                         dname, nt_errstr(status));
6749                 goto fail;
6750         }
6751         status = cli_close(cli, fnum);
6752         if (!NT_STATUS_IS_OK(status)) {
6753                 printf("close failed for %s (%s)\n",
6754                         dname, nt_errstr(status));
6755                 goto fail;
6756         }
6757         /* Now go around the back and chmod to 777 via POSIX. */
6758         status = cli_posix_chmod(posix_cli, dname, 0777);
6759         if (!NT_STATUS_IS_OK(status)) {
6760                 printf("cli_posix_chmod failed for %s (%s)\n",
6761                         dname, nt_errstr(status));
6762                 goto fail;
6763         }
6764
6765         /* Check we can't create a file within dname via Windows. */
6766         status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6767         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6768                 cli_close(posix_cli, fnum);
6769                 printf("Create of %s should be ACCESS denied, was %s\n",
6770                         dst, nt_errstr(status));
6771                 goto fail;
6772         }
6773
6774         /* Make the sample file/directory. */
6775         status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6776         if (!NT_STATUS_IS_OK(status)) {
6777                 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6778                 goto fail;
6779         }
6780         status = cli_close(cli, fnum);
6781         if (!NT_STATUS_IS_OK(status)) {
6782                 printf("cli_close failed (%s)\n", nt_errstr(status));
6783                 goto fail;
6784         }
6785
6786         status = cli_mkdir(cli, dsrc);
6787         if (!NT_STATUS_IS_OK(status)) {
6788                 printf("cli_mkdir of %s failed (%s)\n",
6789                         dsrc, nt_errstr(status));
6790                 goto fail;
6791         }
6792
6793         /*
6794          * OK - renames of the new file and directory into the
6795          * dst directory should fail.
6796          */
6797
6798         status = cli_rename(cli, src, dst, false);
6799         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6800                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6801                         src, dst, nt_errstr(status));
6802                 goto fail;
6803         }
6804         status = cli_rename(cli, dsrc, ddst, false);
6805         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6806                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6807                         src, dst, nt_errstr(status));
6808                 goto fail;
6809         }
6810
6811         TALLOC_FREE(frame);
6812         return true;
6813
6814   fail:
6815
6816         if (posix_cli) {
6817                 torture_close_connection(posix_cli);
6818         }
6819
6820         if (cli) {
6821                 if (fnum != (uint16_t)-1) {
6822                         cli_close(cli, fnum);
6823                 }
6824                 cli_unlink(cli, src,
6825                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6826                 cli_unlink(cli, dst,
6827                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6828                 cli_rmdir(cli, dsrc);
6829                 cli_rmdir(cli, ddst);
6830                 cli_rmdir(cli, dname);
6831
6832                 torture_close_connection(cli);
6833         }
6834
6835         TALLOC_FREE(frame);
6836         return false;
6837 }
6838
6839 /*
6840   Test owner rights ACE.
6841  */
6842 static bool run_owner_rights(int dummy)
6843 {
6844         static struct cli_state *cli = NULL;
6845         const char *fname = "owner_rights.txt";
6846         uint16_t fnum = (uint16_t)-1;
6847         struct security_descriptor *sd = NULL;
6848         struct security_descriptor *newsd = NULL;
6849         NTSTATUS status;
6850         TALLOC_CTX *frame = NULL;
6851
6852         frame = talloc_stackframe();
6853         printf("starting owner rights test\n");
6854
6855         /* Windows connection. */
6856         if (!torture_open_connection(&cli, 0)) {
6857                 goto fail;
6858         }
6859
6860         smbXcli_conn_set_sockopt(cli->conn, sockops);
6861
6862         /* Start with a clean slate. */
6863         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6864
6865         /* Create the test file. */
6866         /* Now try and open for read and write-dac. */
6867         status = cli_ntcreate(cli,
6868                                 fname,
6869                                 0,
6870                                 GENERIC_ALL_ACCESS,
6871                                 FILE_ATTRIBUTE_NORMAL,
6872                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6873                                         FILE_SHARE_DELETE,
6874                                 FILE_CREATE,
6875                                 0,
6876                                 0,
6877                                 &fnum,
6878                                 NULL);
6879         if (!NT_STATUS_IS_OK(status)) {
6880                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6881                 goto fail;
6882         }
6883
6884         /* Get the original SD. */
6885         status = cli_query_secdesc(cli,
6886                                 fnum,
6887                                 frame,
6888                                 &sd);
6889         if (!NT_STATUS_IS_OK(status)) {
6890                 printf("cli_query_secdesc failed for %s (%s)\n",
6891                         fname, nt_errstr(status));
6892                 goto fail;
6893         }
6894
6895         /*
6896          * Add an "owner-rights" ACE denying WRITE_DATA,
6897          * and an "owner-rights" ACE allowing READ_DATA.
6898          */
6899
6900         newsd = security_descriptor_dacl_create(frame,
6901                                         0,
6902                                         NULL,
6903                                         NULL,
6904                                         SID_OWNER_RIGHTS,
6905                                         SEC_ACE_TYPE_ACCESS_DENIED,
6906                                         FILE_WRITE_DATA,
6907                                         0,
6908                                         SID_OWNER_RIGHTS,
6909                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6910                                         FILE_READ_DATA,
6911                                         0,
6912                                         NULL);
6913         if (newsd == NULL) {
6914                 goto fail;
6915         }
6916         sd->dacl = security_acl_concatenate(frame,
6917                                         newsd->dacl,
6918                                         sd->dacl);
6919         if (sd->dacl == NULL) {
6920                 goto fail;
6921         }
6922         status = cli_set_secdesc(cli, fnum, sd);
6923         if (!NT_STATUS_IS_OK(status)) {
6924                 printf("cli_set_secdesc failed for %s (%s)\n",
6925                         fname, nt_errstr(status));
6926                 goto fail;
6927         }
6928         status = cli_close(cli, fnum);
6929         if (!NT_STATUS_IS_OK(status)) {
6930                 printf("close failed for %s (%s)\n",
6931                         fname, nt_errstr(status));
6932                 goto fail;
6933         }
6934         fnum = (uint16_t)-1;
6935
6936         /* Try and open for FILE_WRITE_DATA */
6937         status = cli_ntcreate(cli,
6938                                 fname,
6939                                 0,
6940                                 FILE_WRITE_DATA,
6941                                 FILE_ATTRIBUTE_NORMAL,
6942                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6943                                         FILE_SHARE_DELETE,
6944                                 FILE_OPEN,
6945                                 0,
6946                                 0,
6947                                 &fnum,
6948                                 NULL);
6949         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6950                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6951                 goto fail;
6952         }
6953
6954         /* Now try and open for FILE_READ_DATA */
6955         status = cli_ntcreate(cli,
6956                                 fname,
6957                                 0,
6958                                 FILE_READ_DATA,
6959                                 FILE_ATTRIBUTE_NORMAL,
6960                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6961                                         FILE_SHARE_DELETE,
6962                                 FILE_OPEN,
6963                                 0,
6964                                 0,
6965                                 &fnum,
6966                                 NULL);
6967         if (!NT_STATUS_IS_OK(status)) {
6968                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6969                 goto fail;
6970         }
6971
6972         status = cli_close(cli, fnum);
6973         if (!NT_STATUS_IS_OK(status)) {
6974                 printf("close failed for %s (%s)\n",
6975                         fname, nt_errstr(status));
6976                 goto fail;
6977         }
6978
6979         /* Restore clean slate. */
6980         TALLOC_FREE(sd);
6981         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6982
6983         /* Create the test file. */
6984         status = cli_ntcreate(cli,
6985                                 fname,
6986                                 0,
6987                                 GENERIC_ALL_ACCESS,
6988                                 FILE_ATTRIBUTE_NORMAL,
6989                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6990                                         FILE_SHARE_DELETE,
6991                                 FILE_CREATE,
6992                                 0,
6993                                 0,
6994                                 &fnum,
6995                                 NULL);
6996         if (!NT_STATUS_IS_OK(status)) {
6997                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6998                 goto fail;
6999         }
7000
7001         /* Get the original SD. */
7002         status = cli_query_secdesc(cli,
7003                                 fnum,
7004                                 frame,
7005                                 &sd);
7006         if (!NT_STATUS_IS_OK(status)) {
7007                 printf("cli_query_secdesc failed for %s (%s)\n",
7008                         fname, nt_errstr(status));
7009                 goto fail;
7010         }
7011
7012         /*
7013          * Add an "owner-rights ACE denying WRITE_DATA,
7014          * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
7015          */
7016
7017         newsd = security_descriptor_dacl_create(frame,
7018                                         0,
7019                                         NULL,
7020                                         NULL,
7021                                         SID_OWNER_RIGHTS,
7022                                         SEC_ACE_TYPE_ACCESS_DENIED,
7023                                         FILE_WRITE_DATA,
7024                                         0,
7025                                         SID_OWNER_RIGHTS,
7026                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7027                                         FILE_READ_DATA|FILE_WRITE_DATA,
7028                                         0,
7029                                         NULL);
7030         if (newsd == NULL) {
7031                 goto fail;
7032         }
7033         sd->dacl = security_acl_concatenate(frame,
7034                                         newsd->dacl,
7035                                         sd->dacl);
7036         if (sd->dacl == NULL) {
7037                 goto fail;
7038         }
7039         status = cli_set_secdesc(cli, fnum, sd);
7040         if (!NT_STATUS_IS_OK(status)) {
7041                 printf("cli_set_secdesc failed for %s (%s)\n",
7042                         fname, nt_errstr(status));
7043                 goto fail;
7044         }
7045         status = cli_close(cli, fnum);
7046         if (!NT_STATUS_IS_OK(status)) {
7047                 printf("close failed for %s (%s)\n",
7048                         fname, nt_errstr(status));
7049                 goto fail;
7050         }
7051         fnum = (uint16_t)-1;
7052
7053         /* Try and open for FILE_WRITE_DATA */
7054         status = cli_ntcreate(cli,
7055                                 fname,
7056                                 0,
7057                                 FILE_WRITE_DATA,
7058                                 FILE_ATTRIBUTE_NORMAL,
7059                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7060                                         FILE_SHARE_DELETE,
7061                                 FILE_OPEN,
7062                                 0,
7063                                 0,
7064                                 &fnum,
7065                                 NULL);
7066         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7067                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7068                 goto fail;
7069         }
7070
7071         /* Now try and open for FILE_READ_DATA */
7072         status = cli_ntcreate(cli,
7073                                 fname,
7074                                 0,
7075                                 FILE_READ_DATA,
7076                                 FILE_ATTRIBUTE_NORMAL,
7077                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7078                                         FILE_SHARE_DELETE,
7079                                 FILE_OPEN,
7080                                 0,
7081                                 0,
7082                                 &fnum,
7083                                 NULL);
7084         if (!NT_STATUS_IS_OK(status)) {
7085                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7086                 goto fail;
7087         }
7088
7089         status = cli_close(cli, fnum);
7090         if (!NT_STATUS_IS_OK(status)) {
7091                 printf("close failed for %s (%s)\n",
7092                         fname, nt_errstr(status));
7093                 goto fail;
7094         }
7095
7096         /* Restore clean slate. */
7097         TALLOC_FREE(sd);
7098         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7099
7100
7101         /* Create the test file. */
7102         status = cli_ntcreate(cli,
7103                                 fname,
7104                                 0,
7105                                 GENERIC_ALL_ACCESS,
7106                                 FILE_ATTRIBUTE_NORMAL,
7107                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7108                                         FILE_SHARE_DELETE,
7109                                 FILE_CREATE,
7110                                 0,
7111                                 0,
7112                                 &fnum,
7113                                 NULL);
7114         if (!NT_STATUS_IS_OK(status)) {
7115                 printf("Create of %s - %s\n", fname, nt_errstr(status));
7116                 goto fail;
7117         }
7118
7119         /* Get the original SD. */
7120         status = cli_query_secdesc(cli,
7121                                 fnum,
7122                                 frame,
7123                                 &sd);
7124         if (!NT_STATUS_IS_OK(status)) {
7125                 printf("cli_query_secdesc failed for %s (%s)\n",
7126                         fname, nt_errstr(status));
7127                 goto fail;
7128         }
7129
7130         /*
7131          * Add an "authenticated users" ACE allowing READ_DATA,
7132          * add an "owner-rights" denying READ_DATA,
7133          * and an "authenticated users" ACE allowing WRITE_DATA.
7134          */
7135
7136         newsd = security_descriptor_dacl_create(frame,
7137                                         0,
7138                                         NULL,
7139                                         NULL,
7140                                         SID_NT_AUTHENTICATED_USERS,
7141                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7142                                         FILE_READ_DATA,
7143                                         0,
7144                                         SID_OWNER_RIGHTS,
7145                                         SEC_ACE_TYPE_ACCESS_DENIED,
7146                                         FILE_READ_DATA,
7147                                         0,
7148                                         SID_NT_AUTHENTICATED_USERS,
7149                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7150                                         FILE_WRITE_DATA,
7151                                         0,
7152                                         NULL);
7153         if (newsd == NULL) {
7154                 printf("newsd == NULL\n");
7155                 goto fail;
7156         }
7157         sd->dacl = security_acl_concatenate(frame,
7158                                         newsd->dacl,
7159                                         sd->dacl);
7160         if (sd->dacl == NULL) {
7161                 printf("sd->dacl == NULL\n");
7162                 goto fail;
7163         }
7164         status = cli_set_secdesc(cli, fnum, sd);
7165         if (!NT_STATUS_IS_OK(status)) {
7166                 printf("cli_set_secdesc failed for %s (%s)\n",
7167                         fname, nt_errstr(status));
7168                 goto fail;
7169         }
7170         status = cli_close(cli, fnum);
7171         if (!NT_STATUS_IS_OK(status)) {
7172                 printf("close failed for %s (%s)\n",
7173                         fname, nt_errstr(status));
7174                 goto fail;
7175         }
7176         fnum = (uint16_t)-1;
7177
7178         /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7179         status = cli_ntcreate(cli,
7180                                 fname,
7181                                 0,
7182                                 FILE_READ_DATA|FILE_WRITE_DATA,
7183                                 FILE_ATTRIBUTE_NORMAL,
7184                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7185                                         FILE_SHARE_DELETE,
7186                                 FILE_OPEN,
7187                                 0,
7188                                 0,
7189                                 &fnum,
7190                                 NULL);
7191         if (!NT_STATUS_IS_OK(status)) {
7192                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7193                 goto fail;
7194         }
7195
7196         status = cli_close(cli, fnum);
7197         if (!NT_STATUS_IS_OK(status)) {
7198                 printf("close failed for %s (%s)\n",
7199                         fname, nt_errstr(status));
7200                 goto fail;
7201         }
7202
7203         cli_unlink(cli, fname,
7204                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7205
7206         TALLOC_FREE(frame);
7207         return true;
7208
7209   fail:
7210
7211         if (cli) {
7212                 if (fnum != (uint16_t)-1) {
7213                         cli_close(cli, fnum);
7214                 }
7215                 cli_unlink(cli, fname,
7216                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7217                 torture_close_connection(cli);
7218         }
7219
7220         TALLOC_FREE(frame);
7221         return false;
7222 }
7223
7224 /*
7225  * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7226  * Note this test only works with a user with SeSecurityPrivilege set.
7227  *
7228  * NB. This is also tested in samba3.base.createx_access
7229  * but this makes it very explicit what we're looking for.
7230  */
7231 static bool run_smb1_system_security(int dummy)
7232 {
7233         static struct cli_state *cli = NULL;
7234         const char *fname = "system_security.txt";
7235         uint16_t fnum = (uint16_t)-1;
7236         NTSTATUS status;
7237         TALLOC_CTX *frame = NULL;
7238
7239         frame = talloc_stackframe();
7240         printf("starting smb1 system security test\n");
7241
7242         /* SMB1 connection - torture_open_connection() forces this. */
7243         if (!torture_open_connection(&cli, 0)) {
7244                 goto fail;
7245         }
7246
7247         smbXcli_conn_set_sockopt(cli->conn, sockops);
7248
7249         /* Start with a clean slate. */
7250         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7251
7252         /* Create the test file. */
7253         status = cli_ntcreate(cli,
7254                                 fname,
7255                                 0,
7256                                 GENERIC_ALL_ACCESS,
7257                                 FILE_ATTRIBUTE_NORMAL,
7258                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7259                                         FILE_SHARE_DELETE,
7260                                 FILE_CREATE,
7261                                 0,
7262                                 0,
7263                                 &fnum,
7264                                 NULL);
7265         if (!NT_STATUS_IS_OK(status)) {
7266                 printf("Create of %s - %s\n", fname, nt_errstr(status));
7267                 goto fail;
7268         }
7269
7270         status = cli_close(cli, fnum);
7271
7272         /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7273         /*
7274          * On SMB1 this succeeds - SMB2 it fails,
7275          * see the SMB2-SACL test.
7276          */
7277         status = cli_ntcreate(cli,
7278                                 fname,
7279                                 0,
7280                                 SEC_FLAG_SYSTEM_SECURITY,
7281                                 FILE_ATTRIBUTE_NORMAL,
7282                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7283                                         FILE_SHARE_DELETE,
7284                                 FILE_OPEN,
7285                                 0,
7286                                 0,
7287                                 &fnum,
7288                                 NULL);
7289         if (!NT_STATUS_IS_OK(status)) {
7290                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7291                 goto fail;
7292         }
7293
7294         status = cli_close(cli, fnum);
7295
7296         cli_unlink(cli, fname,
7297                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7298
7299         torture_close_connection(cli);
7300         TALLOC_FREE(frame);
7301         return true;
7302
7303   fail:
7304
7305         if (cli) {
7306                 if (fnum != (uint16_t)-1) {
7307                         cli_close(cli, fnum);
7308                 }
7309                 cli_unlink(cli, fname,
7310                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7311                 torture_close_connection(cli);
7312         }
7313
7314         TALLOC_FREE(frame);
7315         return false;
7316 }
7317
7318 static bool run_pipe_number(int dummy)
7319 {
7320         struct cli_state *cli1;
7321         const char *pipe_name = "\\SPOOLSS";
7322         uint16_t fnum;
7323         int num_pipes = 0;
7324         NTSTATUS status;
7325
7326         printf("starting pipenumber test\n");
7327         if (!torture_open_connection(&cli1, 0)) {
7328                 return False;
7329         }
7330
7331         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7332         while(1) {
7333                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7334                                       FILE_ATTRIBUTE_NORMAL,
7335                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
7336                                       FILE_OPEN_IF, 0, 0, &fnum, NULL);
7337                 if (!NT_STATUS_IS_OK(status)) {
7338                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7339                         break;
7340                 }
7341                 num_pipes++;
7342                 printf("\r%6d", num_pipes);
7343         }
7344
7345         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7346         torture_close_connection(cli1);
7347         return True;
7348 }
7349
7350 /*
7351   Test open mode returns on read-only files.
7352  */
7353 static bool run_opentest(int dummy)
7354 {
7355         static struct cli_state *cli1;
7356         static struct cli_state *cli2;
7357         const char *fname = "\\readonly.file";
7358         uint16_t fnum1, fnum2;
7359         char buf[20];
7360         off_t fsize;
7361         bool correct = True;
7362         char *tmp_path;
7363         NTSTATUS status;
7364
7365         printf("starting open test\n");
7366
7367         if (!torture_open_connection(&cli1, 0)) {
7368                 return False;
7369         }
7370
7371         cli_setatr(cli1, fname, 0, 0);
7372         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7373
7374         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7375
7376         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7377         if (!NT_STATUS_IS_OK(status)) {
7378                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7379                 return False;
7380         }
7381
7382         status = cli_close(cli1, fnum1);
7383         if (!NT_STATUS_IS_OK(status)) {
7384                 printf("close2 failed (%s)\n", nt_errstr(status));
7385                 return False;
7386         }
7387
7388         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7389         if (!NT_STATUS_IS_OK(status)) {
7390                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7391                 return False;
7392         }
7393
7394         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7395         if (!NT_STATUS_IS_OK(status)) {
7396                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7397                 return False;
7398         }
7399
7400         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7401         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7402
7403         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7404                         NT_STATUS_ACCESS_DENIED)) {
7405                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7406         }
7407
7408         printf("finished open test 1\n");
7409
7410         cli_close(cli1, fnum1);
7411
7412         /* Now try not readonly and ensure ERRbadshare is returned. */
7413
7414         cli_setatr(cli1, fname, 0, 0);
7415
7416         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7417         if (!NT_STATUS_IS_OK(status)) {
7418                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7419                 return False;
7420         }
7421
7422         /* This will fail - but the error should be ERRshare. */
7423         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7424
7425         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7426                         NT_STATUS_SHARING_VIOLATION)) {
7427                 printf("correct error code ERRDOS/ERRbadshare returned\n");
7428         }
7429
7430         status = cli_close(cli1, fnum1);
7431         if (!NT_STATUS_IS_OK(status)) {
7432                 printf("close2 failed (%s)\n", nt_errstr(status));
7433                 return False;
7434         }
7435
7436         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7437
7438         printf("finished open test 2\n");
7439
7440         /* Test truncate open disposition on file opened for read. */
7441         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7442         if (!NT_STATUS_IS_OK(status)) {
7443                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7444                 return False;
7445         }
7446
7447         /* write 20 bytes. */
7448
7449         memset(buf, '\0', 20);
7450
7451         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7452         if (!NT_STATUS_IS_OK(status)) {
7453                 printf("write failed (%s)\n", nt_errstr(status));
7454                 correct = False;
7455         }
7456
7457         status = cli_close(cli1, fnum1);
7458         if (!NT_STATUS_IS_OK(status)) {
7459                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7460                 return False;
7461         }
7462
7463         /* Ensure size == 20. */
7464         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7465         if (!NT_STATUS_IS_OK(status)) {
7466                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7467                 return False;
7468         }
7469
7470         if (fsize != 20) {
7471                 printf("(3) file size != 20\n");
7472                 return False;
7473         }
7474
7475         /* Now test if we can truncate a file opened for readonly. */
7476         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7477         if (!NT_STATUS_IS_OK(status)) {
7478                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7479                 return False;
7480         }
7481
7482         status = cli_close(cli1, fnum1);
7483         if (!NT_STATUS_IS_OK(status)) {
7484                 printf("close2 failed (%s)\n", nt_errstr(status));
7485                 return False;
7486         }
7487
7488         /* Ensure size == 0. */
7489         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7490         if (!NT_STATUS_IS_OK(status)) {
7491                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7492                 return False;
7493         }
7494
7495         if (fsize != 0) {
7496                 printf("(3) file size != 0\n");
7497                 return False;
7498         }
7499         printf("finished open test 3\n");
7500
7501         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7502
7503         printf("Do ctemp tests\n");
7504         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7505         if (!NT_STATUS_IS_OK(status)) {
7506                 printf("ctemp failed (%s)\n", nt_errstr(status));
7507                 return False;
7508         }
7509
7510         printf("ctemp gave path %s\n", tmp_path);
7511         status = cli_close(cli1, fnum1);
7512         if (!NT_STATUS_IS_OK(status)) {
7513                 printf("close of temp failed (%s)\n", nt_errstr(status));
7514         }
7515
7516         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7517         if (!NT_STATUS_IS_OK(status)) {
7518                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7519         }
7520
7521         /* Test the non-io opens... */
7522
7523         if (!torture_open_connection(&cli2, 1)) {
7524                 return False;
7525         }
7526
7527         cli_setatr(cli2, fname, 0, 0);
7528         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7529
7530         smbXcli_conn_set_sockopt(cli2->conn, sockops);
7531
7532         printf("TEST #1 testing 2 non-io opens (no delete)\n");
7533         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7534                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7535                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7536         if (!NT_STATUS_IS_OK(status)) {
7537                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7538                 return False;
7539         }
7540
7541         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7542                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7543                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7544         if (!NT_STATUS_IS_OK(status)) {
7545                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7546                 return False;
7547         }
7548
7549         status = cli_close(cli1, fnum1);
7550         if (!NT_STATUS_IS_OK(status)) {
7551                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7552                 return False;
7553         }
7554
7555         status = cli_close(cli2, fnum2);
7556         if (!NT_STATUS_IS_OK(status)) {
7557                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7558                 return False;
7559         }
7560
7561         printf("non-io open test #1 passed.\n");
7562
7563         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7564
7565         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7566
7567         status = cli_ntcreate(cli1, fname, 0,
7568                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7569                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7570                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7571         if (!NT_STATUS_IS_OK(status)) {
7572                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7573                 return False;
7574         }
7575
7576         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7577                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7578                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7579         if (!NT_STATUS_IS_OK(status)) {
7580                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7581                 return False;
7582         }
7583
7584         status = cli_close(cli1, fnum1);
7585         if (!NT_STATUS_IS_OK(status)) {
7586                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7587                 return False;
7588         }
7589
7590         status = cli_close(cli2, fnum2);
7591         if (!NT_STATUS_IS_OK(status)) {
7592                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7593                 return False;
7594         }
7595
7596         printf("non-io open test #2 passed.\n");
7597
7598         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7599
7600         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7601
7602         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7603                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7604                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7605         if (!NT_STATUS_IS_OK(status)) {
7606                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7607                 return False;
7608         }
7609
7610         status = cli_ntcreate(cli2, fname, 0,
7611                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7612                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7613                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7614         if (!NT_STATUS_IS_OK(status)) {
7615                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7616                 return False;
7617         }
7618
7619         status = cli_close(cli1, fnum1);
7620         if (!NT_STATUS_IS_OK(status)) {
7621                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7622                 return False;
7623         }
7624
7625         status = cli_close(cli2, fnum2);
7626         if (!NT_STATUS_IS_OK(status)) {
7627                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7628                 return False;
7629         }
7630
7631         printf("non-io open test #3 passed.\n");
7632
7633         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7634
7635         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7636
7637         status = cli_ntcreate(cli1, fname, 0,
7638                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7639                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7640                                FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7641         if (!NT_STATUS_IS_OK(status)) {
7642                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7643                 return False;
7644         }
7645
7646         status = cli_ntcreate(cli2, fname, 0,
7647                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7648                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7649                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7650         if (NT_STATUS_IS_OK(status)) {
7651                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7652                 return False;
7653         }
7654
7655         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7656
7657         status = cli_close(cli1, fnum1);
7658         if (!NT_STATUS_IS_OK(status)) {
7659                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7660                 return False;
7661         }
7662
7663         printf("non-io open test #4 passed.\n");
7664
7665         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7666
7667         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7668
7669         status = cli_ntcreate(cli1, fname, 0,
7670                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7671                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7672                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7673         if (!NT_STATUS_IS_OK(status)) {
7674                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7675                 return False;
7676         }
7677
7678         status = cli_ntcreate(cli2, fname, 0,
7679                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7680                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7681                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7682         if (!NT_STATUS_IS_OK(status)) {
7683                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7684                 return False;
7685         }
7686
7687         status = cli_close(cli1, fnum1);
7688         if (!NT_STATUS_IS_OK(status)) {
7689                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7690                 return False;
7691         }
7692
7693         status = cli_close(cli2, fnum2);
7694         if (!NT_STATUS_IS_OK(status)) {
7695                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7696                 return False;
7697         }
7698
7699         printf("non-io open test #5 passed.\n");
7700
7701         printf("TEST #6 testing 1 non-io open, one io open\n");
7702
7703         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7704
7705         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7706                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7707                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7708         if (!NT_STATUS_IS_OK(status)) {
7709                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7710                 return False;
7711         }
7712
7713         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7714                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7715                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7716         if (!NT_STATUS_IS_OK(status)) {
7717                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7718                 return False;
7719         }
7720
7721         status = cli_close(cli1, fnum1);
7722         if (!NT_STATUS_IS_OK(status)) {
7723                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7724                 return False;
7725         }
7726
7727         status = cli_close(cli2, fnum2);
7728         if (!NT_STATUS_IS_OK(status)) {
7729                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7730                 return False;
7731         }
7732
7733         printf("non-io open test #6 passed.\n");
7734
7735         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7736
7737         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7738
7739         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7740                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7741                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7742         if (!NT_STATUS_IS_OK(status)) {
7743                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7744                 return False;
7745         }
7746
7747         status = cli_ntcreate(cli2, fname, 0,
7748                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7749                               FILE_ATTRIBUTE_NORMAL,
7750                               FILE_SHARE_READ|FILE_SHARE_DELETE,
7751                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7752         if (NT_STATUS_IS_OK(status)) {
7753                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7754                 return False;
7755         }
7756
7757         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7758
7759         status = cli_close(cli1, fnum1);
7760         if (!NT_STATUS_IS_OK(status)) {
7761                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7762                 return False;
7763         }
7764
7765         printf("non-io open test #7 passed.\n");
7766
7767         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7768
7769         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7770         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7771                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7772                                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7773         if (!NT_STATUS_IS_OK(status)) {
7774                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7775                 correct = false;
7776                 goto out;
7777         }
7778
7779         /* Write to ensure we have to update the file time. */
7780         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7781                               NULL);
7782         if (!NT_STATUS_IS_OK(status)) {
7783                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7784                 correct = false;
7785                 goto out;
7786         }
7787
7788         status = cli_close(cli1, fnum1);
7789         if (!NT_STATUS_IS_OK(status)) {
7790                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7791                 correct = false;
7792         }
7793
7794   out:
7795
7796         if (!torture_close_connection(cli1)) {
7797                 correct = False;
7798         }
7799         if (!torture_close_connection(cli2)) {
7800                 correct = False;
7801         }
7802
7803         return correct;
7804 }
7805
7806 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7807 {
7808         uint16_t major, minor;
7809         uint32_t caplow, caphigh;
7810         NTSTATUS status;
7811
7812         if (!SERVER_HAS_UNIX_CIFS(cli)) {
7813                 printf("Server doesn't support UNIX CIFS extensions.\n");
7814                 return NT_STATUS_NOT_SUPPORTED;
7815         }
7816
7817         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7818                                              &caphigh);
7819         if (!NT_STATUS_IS_OK(status)) {
7820                 printf("Server didn't return UNIX CIFS extensions: %s\n",
7821                        nt_errstr(status));
7822                 return status;
7823         }
7824
7825         status = cli_set_unix_extensions_capabilities(cli, major, minor,
7826                                                       caplow, caphigh);
7827         if (!NT_STATUS_IS_OK(status)) {
7828                 printf("Server doesn't support setting UNIX CIFS extensions: "
7829                        "%s.\n", nt_errstr(status));
7830                 return status;
7831         }
7832
7833         return NT_STATUS_OK;
7834 }
7835
7836 /*
7837   Test POSIX open /mkdir calls.
7838  */
7839 static bool run_simple_posix_open_test(int dummy)
7840 {
7841         static struct cli_state *cli1;
7842         const char *fname = "posix:file";
7843         const char *hname = "posix:hlink";
7844         const char *sname = "posix:symlink";
7845         const char *dname = "posix:dir";
7846         char buf[10];
7847         char *target = NULL;
7848         uint16_t fnum1 = (uint16_t)-1;
7849         SMB_STRUCT_STAT sbuf;
7850         bool correct = false;
7851         NTSTATUS status;
7852         size_t nread;
7853         const char *fname_windows = "windows_file";
7854         uint16_t fnum2 = (uint16_t)-1;
7855         bool ok;
7856
7857         printf("Starting simple POSIX open test\n");
7858
7859         if (!torture_open_connection(&cli1, 0)) {
7860                 return false;
7861         }
7862
7863         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7864
7865         status = torture_setup_unix_extensions(cli1);
7866         if (!NT_STATUS_IS_OK(status)) {
7867                 return false;
7868         }
7869
7870         cli_setatr(cli1, fname, 0, 0);
7871         cli_posix_unlink(cli1, fname);
7872         cli_setatr(cli1, dname, 0, 0);
7873         cli_posix_rmdir(cli1, dname);
7874         cli_setatr(cli1, hname, 0, 0);
7875         cli_posix_unlink(cli1, hname);
7876         cli_setatr(cli1, sname, 0, 0);
7877         cli_posix_unlink(cli1, sname);
7878         cli_setatr(cli1, fname_windows, 0, 0);
7879         cli_posix_unlink(cli1, fname_windows);
7880
7881         /* Create a directory. */
7882         status = cli_posix_mkdir(cli1, dname, 0777);
7883         if (!NT_STATUS_IS_OK(status)) {
7884                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7885                 goto out;
7886         }
7887
7888         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7889                                 0600, &fnum1);
7890         if (!NT_STATUS_IS_OK(status)) {
7891                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7892                 goto out;
7893         }
7894
7895         /* Test ftruncate - set file size. */
7896         status = cli_ftruncate(cli1, fnum1, 1000);
7897         if (!NT_STATUS_IS_OK(status)) {
7898                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7899                 goto out;
7900         }
7901
7902         /* Ensure st_size == 1000 */
7903         status = cli_posix_stat(cli1, fname, &sbuf);
7904         if (!NT_STATUS_IS_OK(status)) {
7905                 printf("stat failed (%s)\n", nt_errstr(status));
7906                 goto out;
7907         }
7908
7909         if (sbuf.st_ex_size != 1000) {
7910                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7911                 goto out;
7912         }
7913
7914         /* Ensure st_mode == 0600 */
7915         if ((sbuf.st_ex_mode & 07777) != 0600) {
7916                 printf("posix_open - bad permissions 0%o != 0600\n",
7917                                 (unsigned int)(sbuf.st_ex_mode & 07777));
7918                 goto out;
7919         }
7920
7921         /* Test ftruncate - set file size back to zero. */
7922         status = cli_ftruncate(cli1, fnum1, 0);
7923         if (!NT_STATUS_IS_OK(status)) {
7924                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7925                 goto out;
7926         }
7927
7928         status = cli_close(cli1, fnum1);
7929         if (!NT_STATUS_IS_OK(status)) {
7930                 printf("close failed (%s)\n", nt_errstr(status));
7931                 goto out;
7932         }
7933
7934         /* Now open the file again for read only. */
7935         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7936         if (!NT_STATUS_IS_OK(status)) {
7937                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7938                 goto out;
7939         }
7940
7941         /* Now unlink while open. */
7942         status = cli_posix_unlink(cli1, fname);
7943         if (!NT_STATUS_IS_OK(status)) {
7944                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7945                 goto out;
7946         }
7947
7948         status = cli_close(cli1, fnum1);
7949         if (!NT_STATUS_IS_OK(status)) {
7950                 printf("close(2) failed (%s)\n", nt_errstr(status));
7951                 goto out;
7952         }
7953
7954         /* Ensure the file has gone. */
7955         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7956         if (NT_STATUS_IS_OK(status)) {
7957                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7958                 goto out;
7959         }
7960
7961         /* Create again to test open with O_TRUNC. */
7962         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7963         if (!NT_STATUS_IS_OK(status)) {
7964                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7965                 goto out;
7966         }
7967
7968         /* Test ftruncate - set file size. */
7969         status = cli_ftruncate(cli1, fnum1, 1000);
7970         if (!NT_STATUS_IS_OK(status)) {
7971                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7972                 goto out;
7973         }
7974
7975         /* Ensure st_size == 1000 */
7976         status = cli_posix_stat(cli1, fname, &sbuf);
7977         if (!NT_STATUS_IS_OK(status)) {
7978                 printf("stat failed (%s)\n", nt_errstr(status));
7979                 goto out;
7980         }
7981
7982         if (sbuf.st_ex_size != 1000) {
7983                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7984                 goto out;
7985         }
7986
7987         status = cli_close(cli1, fnum1);
7988         if (!NT_STATUS_IS_OK(status)) {
7989                 printf("close(2) failed (%s)\n", nt_errstr(status));
7990                 goto out;
7991         }
7992
7993         /* Re-open with O_TRUNC. */
7994         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7995         if (!NT_STATUS_IS_OK(status)) {
7996                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7997                 goto out;
7998         }
7999
8000         /* Ensure st_size == 0 */
8001         status = cli_posix_stat(cli1, fname, &sbuf);
8002         if (!NT_STATUS_IS_OK(status)) {
8003                 printf("stat failed (%s)\n", nt_errstr(status));
8004                 goto out;
8005         }
8006
8007         if (sbuf.st_ex_size != 0) {
8008                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
8009                 goto out;
8010         }
8011
8012         status = cli_close(cli1, fnum1);
8013         if (!NT_STATUS_IS_OK(status)) {
8014                 printf("close failed (%s)\n", nt_errstr(status));
8015                 goto out;
8016         }
8017
8018         status = cli_posix_unlink(cli1, fname);
8019         if (!NT_STATUS_IS_OK(status)) {
8020                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
8021                 goto out;
8022         }
8023
8024         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
8025         if (!NT_STATUS_IS_OK(status)) {
8026                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
8027                         dname, nt_errstr(status));
8028                 goto out;
8029         }
8030
8031         cli_close(cli1, fnum1);
8032
8033         /* What happens when we try and POSIX open a directory for write ? */
8034         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
8035         if (NT_STATUS_IS_OK(status)) {
8036                 printf("POSIX open of directory %s succeeded, "
8037                        "should have failed.\n",
8038                        dname);
8039                 goto out;
8040         } else {
8041                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
8042                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
8043                         goto out;
8044                 }
8045         }
8046
8047         /* Create the file. */
8048         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8049                                 0600, &fnum1);
8050         if (!NT_STATUS_IS_OK(status)) {
8051                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
8052                 goto out;
8053         }
8054
8055         /* Write some data into it. */
8056         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
8057                               NULL);
8058         if (!NT_STATUS_IS_OK(status)) {
8059                 printf("cli_write failed: %s\n", nt_errstr(status));
8060                 goto out;
8061         }
8062
8063         cli_close(cli1, fnum1);
8064
8065         /* Now create a hardlink. */
8066         status = cli_posix_hardlink(cli1, fname, hname);
8067         if (!NT_STATUS_IS_OK(status)) {
8068                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
8069                 goto out;
8070         }
8071
8072         /* Now create a symlink. */
8073         status = cli_posix_symlink(cli1, fname, sname);
8074         if (!NT_STATUS_IS_OK(status)) {
8075                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
8076                 goto out;
8077         }
8078
8079         /* Open the hardlink for read. */
8080         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
8081         if (!NT_STATUS_IS_OK(status)) {
8082                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
8083                 goto out;
8084         }
8085
8086         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
8087         if (!NT_STATUS_IS_OK(status)) {
8088                 printf("POSIX read of %s failed (%s)\n", hname,
8089                        nt_errstr(status));
8090                 goto out;
8091         } else if (nread != 10) {
8092                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
8093                        hname, (unsigned long)nread, 10);
8094                 goto out;
8095         }
8096
8097         if (memcmp(buf, "TEST DATA\n", 10)) {
8098                 printf("invalid data read from hardlink\n");
8099                 goto out;
8100         }
8101
8102         /* Do a POSIX lock/unlock. */
8103         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8104         if (!NT_STATUS_IS_OK(status)) {
8105                 printf("POSIX lock failed %s\n", nt_errstr(status));
8106                 goto out;
8107         }
8108
8109         /* Punch a hole in the locked area. */
8110         status = cli_posix_unlock(cli1, fnum1, 10, 80);
8111         if (!NT_STATUS_IS_OK(status)) {
8112                 printf("POSIX unlock failed %s\n", nt_errstr(status));
8113                 goto out;
8114         }
8115
8116         cli_close(cli1, fnum1);
8117
8118         /* Open the symlink for read - this should fail. A POSIX
8119            client should not be doing opens on a symlink. */
8120         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8121         if (NT_STATUS_IS_OK(status)) {
8122                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
8123                 goto out;
8124         }
8125         ok = check_both_error(
8126                 __LINE__, status, ERRDOS, ERRbadpath,
8127                 NT_STATUS_OBJECT_NAME_NOT_FOUND);
8128         if (!ok) {
8129                 printf("POSIX open of %s should have failed "
8130                        "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8131                        "failed with %s instead.\n",
8132                        sname, nt_errstr(status));
8133                 goto out;
8134         }
8135
8136         status = cli_readlink(cli1, sname, talloc_tos(), &target, NULL, NULL);
8137         if (!NT_STATUS_IS_OK(status)) {
8138                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8139                 goto out;
8140         }
8141
8142         if (strcmp(target, fname) != 0) {
8143                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8144                         sname, fname, target);
8145                 goto out;
8146         }
8147
8148         status = cli_posix_rmdir(cli1, dname);
8149         if (!NT_STATUS_IS_OK(status)) {
8150                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8151                 goto out;
8152         }
8153
8154         /* Check directory opens with a specific permission. */
8155         status = cli_posix_mkdir(cli1, dname, 0700);
8156         if (!NT_STATUS_IS_OK(status)) {
8157                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8158                 goto out;
8159         }
8160
8161         /* Ensure st_mode == 0700 */
8162         status = cli_posix_stat(cli1, dname, &sbuf);
8163         if (!NT_STATUS_IS_OK(status)) {
8164                 printf("stat failed (%s)\n", nt_errstr(status));
8165                 goto out;
8166         }
8167
8168         if ((sbuf.st_ex_mode & 07777) != 0700) {
8169                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
8170                                 (unsigned int)(sbuf.st_ex_mode & 07777));
8171                 goto out;
8172         }
8173
8174         /*
8175          * Now create a Windows file, and attempt a POSIX unlink.
8176          * This should fail with a sharing violation but due to:
8177          *
8178          * [Bug 9571] Unlink after open causes smbd to panic
8179          *
8180          * ensure we've fixed the lock ordering violation.
8181          */
8182
8183         status = cli_ntcreate(cli1, fname_windows, 0,
8184                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
8185                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8186                         FILE_CREATE,
8187                         0x0, 0x0, &fnum2, NULL);
8188         if (!NT_STATUS_IS_OK(status)) {
8189                 printf("Windows create of %s failed (%s)\n", fname_windows,
8190                         nt_errstr(status));
8191                 goto out;
8192         }
8193
8194         /* Now try posix_unlink. */
8195         status = cli_posix_unlink(cli1, fname_windows);
8196         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8197                 printf("POSIX unlink of %s should fail "
8198                         "with NT_STATUS_SHARING_VIOLATION "
8199                         "got %s instead !\n",
8200                         fname_windows,
8201                         nt_errstr(status));
8202                 goto out;
8203         }
8204
8205         cli_close(cli1, fnum2);
8206
8207         printf("Simple POSIX open test passed\n");
8208         correct = true;
8209
8210   out:
8211
8212         if (fnum1 != (uint16_t)-1) {
8213                 cli_close(cli1, fnum1);
8214                 fnum1 = (uint16_t)-1;
8215         }
8216
8217         if (fnum2 != (uint16_t)-1) {
8218                 cli_close(cli1, fnum2);
8219                 fnum2 = (uint16_t)-1;
8220         }
8221
8222         cli_setatr(cli1, sname, 0, 0);
8223         cli_posix_unlink(cli1, sname);
8224         cli_setatr(cli1, hname, 0, 0);
8225         cli_posix_unlink(cli1, hname);
8226         cli_setatr(cli1, fname, 0, 0);
8227         cli_posix_unlink(cli1, fname);
8228         cli_setatr(cli1, dname, 0, 0);
8229         cli_posix_rmdir(cli1, dname);
8230         cli_setatr(cli1, fname_windows, 0, 0);
8231         cli_posix_unlink(cli1, fname_windows);
8232
8233         if (!torture_close_connection(cli1)) {
8234                 correct = false;
8235         }
8236
8237         return correct;
8238 }
8239
8240 /*
8241   Test POSIX and Windows ACLs are rejected on symlinks.
8242  */
8243 static bool run_acl_symlink_test(int dummy)
8244 {
8245         static struct cli_state *cli;
8246         const char *fname = "posix_file";
8247         const char *sname = "posix_symlink";
8248         uint16_t fnum = (uint16_t)-1;
8249         bool correct = false;
8250         NTSTATUS status;
8251         char *posix_acl = NULL;
8252         size_t posix_acl_len = 0;
8253         char *posix_acl_sym = NULL;
8254         size_t posix_acl_len_sym = 0;
8255         struct security_descriptor *sd = NULL;
8256         TALLOC_CTX *frame = NULL;
8257
8258         frame = talloc_stackframe();
8259
8260         printf("Starting acl symlink test\n");
8261
8262         if (!torture_open_connection(&cli, 0)) {
8263                 TALLOC_FREE(frame);
8264                 return false;
8265         }
8266
8267         smbXcli_conn_set_sockopt(cli->conn, sockops);
8268
8269         status = torture_setup_unix_extensions(cli);
8270         if (!NT_STATUS_IS_OK(status)) {
8271                 TALLOC_FREE(frame);
8272                 return false;
8273         }
8274
8275         cli_setatr(cli, fname, 0, 0);
8276         cli_posix_unlink(cli, fname);
8277         cli_setatr(cli, sname, 0, 0);
8278         cli_posix_unlink(cli, sname);
8279
8280         status = cli_ntcreate(cli,
8281                         fname,
8282                         0,
8283                         READ_CONTROL_ACCESS,
8284                         0,
8285                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8286                         FILE_CREATE,
8287                         0x0,
8288                         0x0,
8289                         &fnum,
8290                         NULL);
8291
8292         if (!NT_STATUS_IS_OK(status)) {
8293                 printf("cli_ntcreate of %s failed (%s)\n",
8294                         fname,
8295                         nt_errstr(status));
8296                 goto out;
8297         }
8298
8299         /* Get the Windows ACL on the file. */
8300         status = cli_query_secdesc(cli,
8301                                 fnum,
8302                                 frame,
8303                                 &sd);
8304         if (!NT_STATUS_IS_OK(status)) {
8305                 printf("cli_query_secdesc failed (%s)\n",
8306                         nt_errstr(status));
8307                 goto out;
8308         }
8309
8310         /* Get the POSIX ACL on the file. */
8311         status = cli_posix_getacl(cli,
8312                                 fname,
8313                                 frame,
8314                                 &posix_acl_len,
8315                                 &posix_acl);
8316
8317         if (!NT_STATUS_IS_OK(status)) {
8318                 printf("cli_posix_getacl failed (%s)\n",
8319                         nt_errstr(status));
8320                 goto out;
8321         }
8322
8323         status = cli_close(cli, fnum);
8324         if (!NT_STATUS_IS_OK(status)) {
8325                 printf("close failed (%s)\n", nt_errstr(status));
8326                 goto out;
8327         }
8328         fnum = (uint16_t)-1;
8329
8330         /* Now create a symlink. */
8331         status = cli_posix_symlink(cli, fname, sname);
8332         if (!NT_STATUS_IS_OK(status)) {
8333                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8334                         sname,
8335                         fname,
8336                         nt_errstr(status));
8337                 goto out;
8338         }
8339
8340         /* Open a handle on the symlink for SD set/get should fail. */
8341         status = cli_ntcreate(cli,
8342                         sname,
8343                         0,
8344                         READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8345                         0,
8346                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8347                         FILE_OPEN,
8348                         0x0,
8349                         0x0,
8350                         &fnum,
8351                         NULL);
8352
8353         if (NT_STATUS_IS_OK(status)) {
8354                 printf("Symlink open for getsd/setsd of %s "
8355                         "succeeded (should fail)\n",
8356                         sname);
8357                 goto out;
8358         }
8359
8360         /* Try a stat-open on the symlink, should also fail. */
8361         status = cli_ntcreate(cli,
8362                         sname,
8363                         0,
8364                         FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8365                         0,
8366                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8367                         FILE_OPEN,
8368                         0x0,
8369                         0x0,
8370                         &fnum,
8371                         NULL);
8372
8373         if (NT_STATUS_IS_OK(status)) {
8374                 printf("Stat-open of symlink succeeded (should fail)\n");
8375                 goto out;
8376         }
8377
8378         /* Get the POSIX ACL on the symlink pathname. Should fail. */
8379         status = cli_posix_getacl(cli,
8380                                 sname,
8381                                 frame,
8382                                 &posix_acl_len_sym,
8383                                 &posix_acl_sym);
8384
8385         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8386                 printf("cli_posix_getacl on a symlink gave %s. "
8387                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8388                         nt_errstr(status));
8389                 goto out;
8390         }
8391
8392         /* Set the POSIX ACL on the symlink pathname. Should fail. */
8393         status = cli_posix_setacl(cli,
8394                                 sname,
8395                                 posix_acl,
8396                                 posix_acl_len);
8397
8398         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8399                 printf("cli_posix_setacl on a symlink gave %s. "
8400                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8401                         nt_errstr(status));
8402                 goto out;
8403         }
8404
8405         printf("ACL symlink test passed\n");
8406         correct = true;
8407
8408   out:
8409
8410         if (fnum != (uint16_t)-1) {
8411                 cli_close(cli, fnum);
8412                 fnum = (uint16_t)-1;
8413         }
8414
8415         cli_setatr(cli, sname, 0, 0);
8416         cli_posix_unlink(cli, sname);
8417         cli_setatr(cli, fname, 0, 0);
8418         cli_posix_unlink(cli, fname);
8419
8420         if (!torture_close_connection(cli)) {
8421                 correct = false;
8422         }
8423
8424         TALLOC_FREE(frame);
8425         return correct;
8426 }
8427
8428 /*
8429   Test POSIX can delete a file containing streams.
8430  */
8431 static bool run_posix_stream_delete(int dummy)
8432 {
8433         struct cli_state *cli1 = NULL;
8434         struct cli_state *cli2 = NULL;
8435         const char *fname = "streamfile";
8436         const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8437         uint16_t fnum1 = (uint16_t)-1;
8438         bool correct = false;
8439         NTSTATUS status;
8440         TALLOC_CTX *frame = NULL;
8441
8442         frame = talloc_stackframe();
8443
8444         printf("Starting POSIX stream delete test\n");
8445
8446         if (!torture_open_connection(&cli1, 0) ||
8447                         !torture_open_connection(&cli2, 1)) {
8448                 TALLOC_FREE(frame);
8449                 return false;
8450         }
8451
8452         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8453         smbXcli_conn_set_sockopt(cli2->conn, sockops);
8454
8455         status = torture_setup_unix_extensions(cli2);
8456         if (!NT_STATUS_IS_OK(status)) {
8457                 goto out;
8458         }
8459
8460         cli_setatr(cli1, fname, 0, 0);
8461         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8462
8463         /* Create the file. */
8464         status = cli_ntcreate(cli1,
8465                         fname,
8466                         0,
8467                         READ_CONTROL_ACCESS,
8468                         0,
8469                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8470                         FILE_CREATE,
8471                         0x0,
8472                         0x0,
8473                         &fnum1,
8474                         NULL);
8475
8476         if (!NT_STATUS_IS_OK(status)) {
8477                 printf("cli_ntcreate of %s failed (%s)\n",
8478                         fname,
8479                         nt_errstr(status));
8480                 goto out;
8481         }
8482
8483         status = cli_close(cli1, fnum1);
8484         if (!NT_STATUS_IS_OK(status)) {
8485                 printf("cli_close of %s failed (%s)\n",
8486                         fname,
8487                         nt_errstr(status));
8488                 goto out;
8489         }
8490         fnum1 = (uint16_t)-1;
8491
8492         /* Now create the stream. */
8493         status = cli_ntcreate(cli1,
8494                         stream_fname,
8495                         0,
8496                         FILE_WRITE_DATA,
8497                         0,
8498                         FILE_SHARE_READ|FILE_SHARE_WRITE,
8499                         FILE_CREATE,
8500                         0x0,
8501                         0x0,
8502                         &fnum1,
8503                         NULL);
8504
8505         if (!NT_STATUS_IS_OK(status)) {
8506                 printf("cli_ntcreate of %s failed (%s)\n",
8507                         stream_fname,
8508                         nt_errstr(status));
8509                 goto out;
8510         }
8511
8512         /* Leave the stream handle open... */
8513
8514         /* POSIX unlink should fail. */
8515         status = cli_posix_unlink(cli2, fname);
8516         if (NT_STATUS_IS_OK(status)) {
8517                 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8518                         fname);
8519                 goto out;
8520         }
8521
8522         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8523                 printf("cli_posix_unlink of %s failed with (%s) "
8524                         "should have been NT_STATUS_SHARING_VIOLATION\n",
8525                         fname,
8526                         nt_errstr(status));
8527                 goto out;
8528         }
8529
8530         /* Close the stream handle. */
8531         status = cli_close(cli1, fnum1);
8532         if (!NT_STATUS_IS_OK(status)) {
8533                 printf("cli_close of %s failed (%s)\n",
8534                         stream_fname,
8535                         nt_errstr(status));
8536                 goto out;
8537         }
8538         fnum1 = (uint16_t)-1;
8539
8540         /* POSIX unlink after stream handle closed should succeed. */
8541         status = cli_posix_unlink(cli2, fname);
8542         if (!NT_STATUS_IS_OK(status)) {
8543                 printf("cli_posix_unlink of %s failed (%s)\n",
8544                         fname,
8545                         nt_errstr(status));
8546                 goto out;
8547         }
8548
8549         printf("POSIX stream delete test passed\n");
8550         correct = true;
8551
8552   out:
8553
8554         if (fnum1 != (uint16_t)-1) {
8555                 cli_close(cli1, fnum1);
8556                 fnum1 = (uint16_t)-1;
8557         }
8558
8559         cli_setatr(cli1, fname, 0, 0);
8560         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8561
8562         if (!torture_close_connection(cli1)) {
8563                 correct = false;
8564         }
8565         if (!torture_close_connection(cli2)) {
8566                 correct = false;
8567         }
8568
8569         TALLOC_FREE(frame);
8570         return correct;
8571 }
8572
8573 /*
8574   Test setting EA's are rejected on symlinks.
8575  */
8576 static bool run_ea_symlink_test(int dummy)
8577 {
8578         static struct cli_state *cli;
8579         const char *fname = "posix_file_ea";
8580         const char *sname = "posix_symlink_ea";
8581         const char *ea_name = "testea_name";
8582         const char *ea_value = "testea_value";
8583         uint16_t fnum = (uint16_t)-1;
8584         bool correct = false;
8585         NTSTATUS status;
8586         size_t i, num_eas;
8587         struct ea_struct *eas = NULL;
8588         TALLOC_CTX *frame = NULL;
8589
8590         frame = talloc_stackframe();
8591
8592         printf("Starting EA symlink test\n");
8593
8594         if (!torture_open_connection(&cli, 0)) {
8595                 TALLOC_FREE(frame);
8596                 return false;
8597         }
8598
8599         smbXcli_conn_set_sockopt(cli->conn, sockops);
8600
8601         status = torture_setup_unix_extensions(cli);
8602         if (!NT_STATUS_IS_OK(status)) {
8603                 TALLOC_FREE(frame);
8604                 return false;
8605         }
8606
8607         cli_setatr(cli, fname, 0, 0);
8608         cli_posix_unlink(cli, fname);
8609         cli_setatr(cli, sname, 0, 0);
8610         cli_posix_unlink(cli, sname);
8611
8612         status = cli_ntcreate(cli,
8613                         fname,
8614                         0,
8615                         READ_CONTROL_ACCESS,
8616                         0,
8617                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8618                         FILE_CREATE,
8619                         0x0,
8620                         0x0,
8621                         &fnum,
8622                         NULL);
8623
8624         if (!NT_STATUS_IS_OK(status)) {
8625                 printf("cli_ntcreate of %s failed (%s)\n",
8626                         fname,
8627                         nt_errstr(status));
8628                 goto out;
8629         }
8630
8631         status = cli_close(cli, fnum);
8632         if (!NT_STATUS_IS_OK(status)) {
8633                 printf("close failed (%s)\n",
8634                         nt_errstr(status));
8635                 goto out;
8636         }
8637         fnum = (uint16_t)-1;
8638
8639         /* Set an EA on the path. */
8640         status = cli_set_ea_path(cli,
8641                                 fname,
8642                                 ea_name,
8643                                 ea_value,
8644                                 strlen(ea_value)+1);
8645
8646         if (!NT_STATUS_IS_OK(status)) {
8647                 printf("cli_set_ea_path failed (%s)\n",
8648                         nt_errstr(status));
8649                 goto out;
8650         }
8651
8652         /* Now create a symlink. */
8653         status = cli_posix_symlink(cli, fname, sname);
8654         if (!NT_STATUS_IS_OK(status)) {
8655                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8656                         sname,
8657                         fname,
8658                         nt_errstr(status));
8659                 goto out;
8660         }
8661
8662         /* Get the EA list on the path. Should return value set. */
8663         status = cli_get_ea_list_path(cli,
8664                                 fname,
8665                                 frame,
8666                                 &num_eas,
8667                                 &eas);
8668
8669         if (!NT_STATUS_IS_OK(status)) {
8670                 printf("cli_get_ea_list_path failed (%s)\n",
8671                         nt_errstr(status));
8672                 goto out;
8673         }
8674
8675         /* Ensure the EA we set is there. */
8676         for (i=0; i<num_eas; i++) {
8677                 if (strcmp(eas[i].name, ea_name) == 0 &&
8678                                 eas[i].value.length == strlen(ea_value)+1 &&
8679                                 memcmp(eas[i].value.data,
8680                                         ea_value,
8681                                         eas[i].value.length) == 0) {
8682                         break;
8683                 }
8684         }
8685
8686         if (i == num_eas) {
8687                 printf("Didn't find EA on pathname %s\n",
8688                         fname);
8689                 goto out;
8690         }
8691
8692         num_eas = 0;
8693         TALLOC_FREE(eas);
8694
8695         /* Get the EA list on the symlink. Should return empty list. */
8696         status = cli_get_ea_list_path(cli,
8697                                 sname,
8698                                 frame,
8699                                 &num_eas,
8700                                 &eas);
8701
8702         if (!NT_STATUS_IS_OK(status)) {
8703                 printf("cli_get_ea_list_path failed (%s)\n",
8704                         nt_errstr(status));
8705                 goto out;
8706         }
8707
8708         if (num_eas != 0) {
8709                 printf("cli_get_ea_list_path failed (%s)\n",
8710                         nt_errstr(status));
8711                 goto out;
8712         }
8713
8714         /* Set an EA on the symlink. Should fail. */
8715         status = cli_set_ea_path(cli,
8716                                 sname,
8717                                 ea_name,
8718                                 ea_value,
8719                                 strlen(ea_value)+1);
8720
8721         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8722                 printf("cli_set_ea_path on a symlink gave %s. "
8723                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8724                         nt_errstr(status));
8725                 goto out;
8726         }
8727
8728         printf("EA symlink test passed\n");
8729         correct = true;
8730
8731   out:
8732
8733         if (fnum != (uint16_t)-1) {
8734                 cli_close(cli, fnum);
8735                 fnum = (uint16_t)-1;
8736         }
8737
8738         cli_setatr(cli, sname, 0, 0);
8739         cli_posix_unlink(cli, sname);
8740         cli_setatr(cli, fname, 0, 0);
8741         cli_posix_unlink(cli, fname);
8742
8743         if (!torture_close_connection(cli)) {
8744                 correct = false;
8745         }
8746
8747         TALLOC_FREE(frame);
8748         return correct;
8749 }
8750
8751 /*
8752   Test POSIX locks are OFD-locks.
8753  */
8754 static bool run_posix_ofd_lock_test(int dummy)
8755 {
8756         static struct cli_state *cli;
8757         const char *fname = "posix_file";
8758         uint16_t fnum1 = (uint16_t)-1;
8759         uint16_t fnum2 = (uint16_t)-1;
8760         bool correct = false;
8761         NTSTATUS status;
8762         TALLOC_CTX *frame = NULL;
8763
8764         frame = talloc_stackframe();
8765
8766         printf("Starting POSIX ofd-lock test\n");
8767
8768         if (!torture_open_connection(&cli, 0)) {
8769                 TALLOC_FREE(frame);
8770                 return false;
8771         }
8772
8773         smbXcli_conn_set_sockopt(cli->conn, sockops);
8774
8775         status = torture_setup_unix_extensions(cli);
8776         if (!NT_STATUS_IS_OK(status)) {
8777                 TALLOC_FREE(frame);
8778                 return false;
8779         }
8780
8781         cli_setatr(cli, fname, 0, 0);
8782         cli_posix_unlink(cli, fname);
8783
8784         /* Open the file twice. */
8785         status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8786                                 0600, &fnum1);
8787         if (!NT_STATUS_IS_OK(status)) {
8788                 printf("First POSIX open of %s failed\n", fname);
8789                 goto out;
8790         }
8791
8792         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8793         if (!NT_STATUS_IS_OK(status)) {
8794                 printf("First POSIX open of %s failed\n", fname);
8795                 goto out;
8796         }
8797
8798         /* Set a 0-50 lock on fnum1. */
8799         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8800         if (!NT_STATUS_IS_OK(status)) {
8801                 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8802                 goto out;
8803         }
8804
8805         /* Set a 60-100 lock on fnum2. */
8806         status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8807         if (!NT_STATUS_IS_OK(status)) {
8808                 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8809                 goto out;
8810         }
8811
8812         /* close fnum1 - 0-50 lock should go away. */
8813         status = cli_close(cli, fnum1);
8814         if (!NT_STATUS_IS_OK(status)) {
8815                 printf("close failed (%s)\n",
8816                         nt_errstr(status));
8817                 goto out;
8818         }
8819         fnum1 = (uint16_t)-1;
8820
8821         /* Change the lock context. */
8822         cli_setpid(cli, cli_getpid(cli) + 1);
8823
8824         /* Re-open fnum1. */
8825         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8826         if (!NT_STATUS_IS_OK(status)) {
8827                 printf("Third POSIX open of %s failed\n", fname);
8828                 goto out;
8829         }
8830
8831         /* 60-100 lock should still be there. */
8832         status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8833         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8834                 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8835                 goto out;
8836         }
8837
8838         /* 0-50 lock should be gone. */
8839         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8840         if (!NT_STATUS_IS_OK(status)) {
8841                 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8842                 goto out;
8843         }
8844
8845         printf("POSIX OFD lock test passed\n");
8846         correct = true;
8847
8848   out:
8849
8850         if (fnum1 != (uint16_t)-1) {
8851                 cli_close(cli, fnum1);
8852                 fnum1 = (uint16_t)-1;
8853         }
8854         if (fnum2 != (uint16_t)-1) {
8855                 cli_close(cli, fnum2);
8856                 fnum2 = (uint16_t)-1;
8857         }
8858
8859         cli_setatr(cli, fname, 0, 0);
8860         cli_posix_unlink(cli, fname);
8861
8862         if (!torture_close_connection(cli)) {
8863                 correct = false;
8864         }
8865
8866         TALLOC_FREE(frame);
8867         return correct;
8868 }
8869
8870 struct posix_blocking_state {
8871         struct tevent_context *ev;
8872         struct cli_state *cli1;
8873         uint16_t fnum1;
8874         struct cli_state *cli2;
8875         uint16_t fnum2;
8876         bool gotblocked;
8877         bool gotecho;
8878 };
8879
8880 static void posix_blocking_locked(struct tevent_req *subreq);
8881 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8882 static void posix_blocking_gotecho(struct tevent_req *subreq);
8883 static void posix_blocking_unlocked(struct tevent_req *subreq);
8884
8885 static struct tevent_req *posix_blocking_send(
8886         TALLOC_CTX *mem_ctx,
8887         struct tevent_context *ev,
8888         struct cli_state *cli1,
8889         uint16_t fnum1,
8890         struct cli_state *cli2,
8891         uint16_t fnum2)
8892 {
8893         struct tevent_req *req = NULL, *subreq = NULL;
8894         struct posix_blocking_state *state = NULL;
8895
8896         req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8897         if (req == NULL) {
8898                 return NULL;
8899         }
8900         state->ev = ev;
8901         state->cli1 = cli1;
8902         state->fnum1 = fnum1;
8903         state->cli2 = cli2;
8904         state->fnum2 = fnum2;
8905
8906         subreq = cli_posix_lock_send(
8907                 state,
8908                 state->ev,
8909                 state->cli1,
8910                 state->fnum1,
8911                 0,
8912                 1,
8913                 false,
8914                 WRITE_LOCK);
8915         if (tevent_req_nomem(subreq, req)) {
8916                 return tevent_req_post(req, ev);
8917         }
8918         tevent_req_set_callback(subreq, posix_blocking_locked, req);
8919         return req;
8920 }
8921
8922 static void posix_blocking_locked(struct tevent_req *subreq)
8923 {
8924         struct tevent_req *req = tevent_req_callback_data(
8925                 subreq, struct tevent_req);
8926         struct posix_blocking_state *state = tevent_req_data(
8927                 req, struct posix_blocking_state);
8928         NTSTATUS status;
8929
8930         status = cli_posix_lock_recv(subreq);
8931         TALLOC_FREE(subreq);
8932         if (tevent_req_nterror(req, status)) {
8933                 return;
8934         }
8935
8936         subreq = cli_posix_lock_send(
8937                 state,
8938                 state->ev,
8939                 state->cli2,
8940                 state->fnum2,
8941                 0,
8942                 1,
8943                 true,
8944                 WRITE_LOCK);
8945         if (tevent_req_nomem(subreq, req)) {
8946                 return;
8947         }
8948         tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8949
8950         /* Make sure the blocking request is delivered */
8951         subreq = cli_echo_send(
8952                 state,
8953                 state->ev,
8954                 state->cli2,
8955                 1,
8956                 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8957         if (tevent_req_nomem(subreq, req)) {
8958                 return;
8959         }
8960         tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8961 }
8962
8963 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8964 {
8965         struct tevent_req *req = tevent_req_callback_data(
8966                 subreq, struct tevent_req);
8967         struct posix_blocking_state *state = tevent_req_data(
8968                 req, struct posix_blocking_state);
8969         NTSTATUS status;
8970
8971         status = cli_posix_lock_recv(subreq);
8972         TALLOC_FREE(subreq);
8973         if (tevent_req_nterror(req, status)) {
8974                 return;
8975         }
8976         if (!state->gotecho) {
8977                 printf("blocked req got through before echo\n");
8978                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8979                 return;
8980         }
8981         tevent_req_done(req);
8982 }
8983
8984 static void posix_blocking_gotecho(struct tevent_req *subreq)
8985 {
8986         struct tevent_req *req = tevent_req_callback_data(
8987                 subreq, struct tevent_req);
8988         struct posix_blocking_state *state = tevent_req_data(
8989                 req, struct posix_blocking_state);
8990         NTSTATUS status;
8991
8992         status = cli_echo_recv(subreq);
8993         TALLOC_FREE(subreq);
8994         if (tevent_req_nterror(req, status)) {
8995                 return;
8996         }
8997         if (state->gotblocked) {
8998                 printf("blocked req got through before echo\n");
8999                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
9000                 return;
9001         }
9002         state->gotecho = true;
9003
9004         subreq = cli_posix_lock_send(
9005                 state,
9006                 state->ev,
9007                 state->cli1,
9008                 state->fnum1,
9009                 0,
9010                 1,
9011                 false,
9012                 UNLOCK_LOCK);
9013         if (tevent_req_nomem(subreq, req)) {
9014                 return;
9015         }
9016         tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
9017 }
9018
9019 static void posix_blocking_unlocked(struct tevent_req *subreq)
9020 {
9021         struct tevent_req *req = tevent_req_callback_data(
9022                 subreq, struct tevent_req);
9023         NTSTATUS status;
9024
9025         status = cli_posix_lock_recv(subreq);
9026         TALLOC_FREE(subreq);
9027         if (tevent_req_nterror(req, status)) {
9028                 return;
9029         }
9030         /* tevent_req_done in posix_blocking_gotlocked */
9031 }
9032
9033 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
9034 {
9035         return tevent_req_simple_recv_ntstatus(req);
9036 }
9037
9038 static bool run_posix_blocking_lock(int dummy)
9039 {
9040         struct tevent_context *ev = NULL;
9041         struct cli_state *cli1 = NULL, *cli2 = NULL;
9042         const char *fname = "posix_blocking";
9043         uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
9044         struct tevent_req *req = NULL;
9045         NTSTATUS status;
9046         bool ret = false;
9047         bool ok;
9048
9049         printf("Starting posix blocking lock test\n");
9050
9051         ev = samba_tevent_context_init(NULL);
9052         if (ev == NULL) {
9053                 return false;
9054         }
9055
9056         ok = torture_open_connection(&cli1, 0);
9057         if (!ok) {
9058                 goto fail;
9059         }
9060         ok = torture_open_connection(&cli2, 0);
9061         if (!ok) {
9062                 goto fail;
9063         }
9064
9065         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9066
9067         status = torture_setup_unix_extensions(cli1);
9068         if (!NT_STATUS_IS_OK(status)) {
9069                 return false;
9070         }
9071
9072         status = torture_setup_unix_extensions(cli2);
9073         if (!NT_STATUS_IS_OK(status)) {
9074                 return false;
9075         }
9076
9077         cli_setatr(cli1, fname, 0, 0);
9078         cli_posix_unlink(cli1, fname);
9079
9080         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
9081                                 0600, &fnum1);
9082         if (!NT_STATUS_IS_OK(status)) {
9083                 printf("First POSIX open of %s failed: %s\n",
9084                        fname,
9085                        nt_errstr(status));
9086                 goto fail;
9087         }
9088
9089         status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
9090         if (!NT_STATUS_IS_OK(status)) {
9091                 printf("Second POSIX open of %s failed: %s\n",
9092                        fname,
9093                        nt_errstr(status));
9094                 goto fail;
9095         }
9096
9097         req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9098         if (req == NULL) {
9099                 printf("cli_posix_blocking failed\n");
9100                 goto fail;
9101         }
9102
9103         ok = tevent_req_poll_ntstatus(req, ev, &status);
9104         if (!ok) {
9105                 printf("tevent_req_poll_ntstatus failed: %s\n",
9106                        nt_errstr(status));
9107                 goto fail;
9108         }
9109         status = posix_blocking_recv(req);
9110         TALLOC_FREE(req);
9111         if (!NT_STATUS_IS_OK(status)) {
9112                 printf("posix_blocking_recv returned %s\n",
9113                        nt_errstr(status));
9114                 goto fail;
9115         }
9116
9117         ret = true;
9118 fail:
9119
9120         if (fnum1 != UINT16_MAX) {
9121                 cli_close(cli1, fnum1);
9122                 fnum1 = UINT16_MAX;
9123         }
9124         if (fnum2 != UINT16_MAX) {
9125                 cli_close(cli2, fnum2);
9126                 fnum2 = UINT16_MAX;
9127         }
9128
9129         if (cli1 != NULL) {
9130                 cli_setatr(cli1, fname, 0, 0);
9131                 cli_posix_unlink(cli1, fname);
9132         }
9133
9134         ok = true;
9135
9136         if (cli1 != NULL) {
9137                 ok &= torture_close_connection(cli1);
9138                 cli1 = NULL;
9139         }
9140         if (cli2 != NULL) {
9141                 ok &= torture_close_connection(cli2);
9142                 cli2 = NULL;
9143         }
9144
9145         if (!ok) {
9146                 ret = false;
9147         }
9148         TALLOC_FREE(ev);
9149         return ret;
9150 }
9151
9152 /*
9153   Test POSIX mkdir is case-sensitive.
9154  */
9155 static bool run_posix_mkdir_test(int dummy)
9156 {
9157         static struct cli_state *cli;
9158         const char *fname_foo = "POSIX_foo";
9159         const char *fname_foo_Foo = "POSIX_foo/Foo";
9160         const char *fname_foo_foo = "POSIX_foo/foo";
9161         const char *fname_Foo = "POSIX_Foo";
9162         const char *fname_Foo_Foo = "POSIX_Foo/Foo";
9163         const char *fname_Foo_foo = "POSIX_Foo/foo";
9164         bool correct = false;
9165         NTSTATUS status;
9166         TALLOC_CTX *frame = NULL;
9167         uint16_t fnum = (uint16_t)-1;
9168
9169         frame = talloc_stackframe();
9170
9171         printf("Starting POSIX mkdir test\n");
9172
9173         if (!torture_open_connection(&cli, 0)) {
9174                 TALLOC_FREE(frame);
9175                 return false;
9176         }
9177
9178         smbXcli_conn_set_sockopt(cli->conn, sockops);
9179
9180         status = torture_setup_unix_extensions(cli);
9181         if (!NT_STATUS_IS_OK(status)) {
9182                 TALLOC_FREE(frame);
9183                 return false;
9184         }
9185
9186         cli_posix_rmdir(cli, fname_foo_foo);
9187         cli_posix_rmdir(cli, fname_foo_Foo);
9188         cli_posix_rmdir(cli, fname_foo);
9189
9190         cli_posix_rmdir(cli, fname_Foo_foo);
9191         cli_posix_rmdir(cli, fname_Foo_Foo);
9192         cli_posix_rmdir(cli, fname_Foo);
9193
9194         /*
9195          * Create a file POSIX_foo then try
9196          * and use it in a directory path by
9197          * doing mkdir POSIX_foo/bar.
9198          * The mkdir should fail with
9199          * NT_STATUS_OBJECT_PATH_NOT_FOUND
9200          */
9201
9202         status = cli_posix_open(cli,
9203                         fname_foo,
9204                         O_RDWR|O_CREAT,
9205                         0666,
9206                         &fnum);
9207         if (!NT_STATUS_IS_OK(status)) {
9208                 printf("cli_posix_open of %s failed error %s\n",
9209                         fname_foo,
9210                         nt_errstr(status));
9211                 goto out;
9212         }
9213
9214         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9215         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9216                 printf("cli_posix_mkdir of %s should fail with "
9217                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9218                         "%s instead\n",
9219                         fname_foo_foo,
9220                         nt_errstr(status));
9221                 goto out;
9222         }
9223
9224         status = cli_close(cli, fnum);
9225         if (!NT_STATUS_IS_OK(status)) {
9226                 printf("cli_close failed %s\n", nt_errstr(status));
9227                 goto out;
9228         }
9229         fnum = (uint16_t)-1;
9230
9231         status = cli_posix_unlink(cli, fname_foo);
9232         if (!NT_STATUS_IS_OK(status)) {
9233                 printf("cli_posix_unlink of %s failed error %s\n",
9234                         fname_foo,
9235                         nt_errstr(status));
9236                 goto out;
9237         }
9238
9239         /*
9240          * Now we've deleted everything, posix_mkdir, posix_rmdir,
9241          * posix_open, posix_unlink, on
9242          * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9243          * not silently create POSIX_foo/foo.
9244          */
9245
9246         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9247         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9248                 printf("cli_posix_mkdir of %s should fail with "
9249                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9250                         "%s instead\n",
9251                         fname_foo_foo,
9252                         nt_errstr(status));
9253                 goto out;
9254         }
9255
9256         status = cli_posix_rmdir(cli, fname_foo_foo);
9257         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9258                 printf("cli_posix_rmdir of %s should fail with "
9259                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9260                         "%s instead\n",
9261                         fname_foo_foo,
9262                         nt_errstr(status));
9263                 goto out;
9264         }
9265
9266         status = cli_posix_open(cli,
9267                         fname_foo_foo,
9268                         O_RDWR|O_CREAT,
9269                         0666,
9270                         &fnum);
9271         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9272                 printf("cli_posix_open of %s should fail with "
9273                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9274                         "%s instead\n",
9275                         fname_foo_foo,
9276                         nt_errstr(status));
9277                 goto out;
9278         }
9279
9280         status = cli_posix_unlink(cli, fname_foo_foo);
9281         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9282                 printf("cli_posix_unlink of %s should fail with "
9283                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9284                         "%s instead\n",
9285                         fname_foo_foo,
9286                         nt_errstr(status));
9287                 goto out;
9288         }
9289
9290         status = cli_posix_mkdir(cli, fname_foo, 0777);
9291         if (!NT_STATUS_IS_OK(status)) {
9292                 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9293                 goto out;
9294         }
9295
9296         status = cli_posix_mkdir(cli, fname_Foo, 0777);
9297         if (!NT_STATUS_IS_OK(status)) {
9298                 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9299                 goto out;
9300         }
9301
9302         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9303         if (!NT_STATUS_IS_OK(status)) {
9304                 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9305                 goto out;
9306         }
9307
9308         status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9309         if (!NT_STATUS_IS_OK(status)) {
9310                 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9311                 goto out;
9312         }
9313
9314         status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9315         if (!NT_STATUS_IS_OK(status)) {
9316                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9317                 goto out;
9318         }
9319
9320         status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9321         if (!NT_STATUS_IS_OK(status)) {
9322                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9323                 goto out;
9324         }
9325
9326         printf("POSIX mkdir test passed\n");
9327         correct = true;
9328
9329   out:
9330
9331         if (fnum != (uint16_t)-1) {
9332                 cli_close(cli, fnum);
9333                 fnum = (uint16_t)-1;
9334         }
9335
9336         cli_posix_rmdir(cli, fname_foo_foo);
9337         cli_posix_rmdir(cli, fname_foo_Foo);
9338         cli_posix_rmdir(cli, fname_foo);
9339
9340         cli_posix_rmdir(cli, fname_Foo_foo);
9341         cli_posix_rmdir(cli, fname_Foo_Foo);
9342         cli_posix_rmdir(cli, fname_Foo);
9343
9344         if (!torture_close_connection(cli)) {
9345                 correct = false;
9346         }
9347
9348         TALLOC_FREE(frame);
9349         return correct;
9350 }
9351
9352 struct posix_acl_oplock_state {
9353         struct tevent_context *ev;
9354         struct cli_state *cli;
9355         bool *got_break;
9356         bool *acl_ret;
9357         NTSTATUS status;
9358 };
9359
9360 static void posix_acl_oplock_got_break(struct tevent_req *req)
9361 {
9362         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9363                 req, struct posix_acl_oplock_state);
9364         uint16_t fnum;
9365         uint8_t level;
9366         NTSTATUS status;
9367
9368         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9369         TALLOC_FREE(req);
9370         if (!NT_STATUS_IS_OK(status)) {
9371                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9372                        nt_errstr(status));
9373                 return;
9374         }
9375         *state->got_break = true;
9376
9377         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9378                                   NO_OPLOCK);
9379         if (req == NULL) {
9380                 printf("cli_oplock_ack_send failed\n");
9381                 return;
9382         }
9383 }
9384
9385 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9386 {
9387         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9388                 req, struct posix_acl_oplock_state);
9389         size_t ret_size = 0;
9390         char *ret_data = NULL;
9391
9392         state->status = cli_posix_getacl_recv(req,
9393                         state,
9394                         &ret_size,
9395                         &ret_data);
9396
9397         if (!NT_STATUS_IS_OK(state->status)) {
9398                 printf("cli_posix_getacl_recv returned %s\n",
9399                         nt_errstr(state->status));
9400         }
9401         *state->acl_ret = true;
9402 }
9403
9404 static bool run_posix_acl_oplock_test(int dummy)
9405 {
9406         struct tevent_context *ev;
9407         struct cli_state *cli1, *cli2;
9408         struct tevent_req *oplock_req, *getacl_req;
9409         const char *fname = "posix_acl_oplock";
9410         uint16_t fnum;
9411         int saved_use_oplocks = use_oplocks;
9412         NTSTATUS status;
9413         bool correct = true;
9414         bool got_break = false;
9415         bool acl_ret = false;
9416
9417         struct posix_acl_oplock_state *state;
9418
9419         printf("starting posix_acl_oplock test\n");
9420
9421         if (!torture_open_connection(&cli1, 0)) {
9422                 use_level_II_oplocks = false;
9423                 use_oplocks = saved_use_oplocks;
9424                 return false;
9425         }
9426
9427         if (!torture_open_connection(&cli2, 1)) {
9428                 use_level_II_oplocks = false;
9429                 use_oplocks = saved_use_oplocks;
9430                 return false;
9431         }
9432
9433         /* Setup posix on cli2 only. */
9434         status = torture_setup_unix_extensions(cli2);
9435         if (!NT_STATUS_IS_OK(status)) {
9436                 return false;
9437         }
9438
9439         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9440         smbXcli_conn_set_sockopt(cli2->conn, sockops);
9441
9442         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9443
9444         /* Create the file on the Windows connection. */
9445         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9446                           &fnum);
9447         if (!NT_STATUS_IS_OK(status)) {
9448                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9449                 return false;
9450         }
9451
9452         status = cli_close(cli1, fnum);
9453         if (!NT_STATUS_IS_OK(status)) {
9454                 printf("close1 failed (%s)\n", nt_errstr(status));
9455                 return false;
9456         }
9457
9458         cli1->use_oplocks = true;
9459
9460         /* Open with oplock. */
9461         status = cli_ntcreate(cli1,
9462                         fname,
9463                         0,
9464                         FILE_READ_DATA,
9465                         FILE_ATTRIBUTE_NORMAL,
9466                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9467                         FILE_OPEN,
9468                         0,
9469                         0,
9470                         &fnum,
9471                         NULL);
9472
9473         if (!NT_STATUS_IS_OK(status)) {
9474                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9475                 return false;
9476         }
9477
9478         ev = samba_tevent_context_init(talloc_tos());
9479         if (ev == NULL) {
9480                 printf("tevent_context_init failed\n");
9481                 return false;
9482         }
9483
9484         state = talloc_zero(ev, struct posix_acl_oplock_state);
9485         if (state == NULL) {
9486                 printf("talloc failed\n");
9487                 return false;
9488         }
9489         state->ev = ev;
9490         state->cli = cli1;
9491         state->got_break = &got_break;
9492         state->acl_ret = &acl_ret;
9493
9494         oplock_req = cli_smb_oplock_break_waiter_send(
9495                 talloc_tos(), ev, cli1);
9496         if (oplock_req == NULL) {
9497                 printf("cli_smb_oplock_break_waiter_send failed\n");
9498                 return false;
9499         }
9500         tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9501
9502         /* Get ACL on POSIX connection - should break oplock. */
9503         getacl_req = cli_posix_getacl_send(talloc_tos(),
9504                                 ev,
9505                                 cli2,
9506                                 fname);
9507         if (getacl_req == NULL) {
9508                 printf("cli_posix_getacl_send failed\n");
9509                 return false;
9510         }
9511         tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9512
9513         while (!got_break || !acl_ret) {
9514                 int ret;
9515                 ret = tevent_loop_once(ev);
9516                 if (ret == -1) {
9517                         printf("tevent_loop_once failed: %s\n",
9518                                strerror(errno));
9519                         return false;
9520                 }
9521         }
9522
9523         if (!NT_STATUS_IS_OK(state->status)) {
9524                 printf("getacl failed (%s)\n", nt_errstr(state->status));
9525                 correct = false;
9526         }
9527
9528         status = cli_close(cli1, fnum);
9529         if (!NT_STATUS_IS_OK(status)) {
9530                 printf("close2 failed (%s)\n", nt_errstr(status));
9531                 correct = false;
9532         }
9533
9534         status = cli_unlink(cli1,
9535                         fname,
9536                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9537         if (!NT_STATUS_IS_OK(status)) {
9538                 printf("unlink failed (%s)\n", nt_errstr(status));
9539                 correct = false;
9540         }
9541
9542         if (!torture_close_connection(cli1)) {
9543                 correct = false;
9544         }
9545         if (!torture_close_connection(cli2)) {
9546                 correct = false;
9547         }
9548
9549         if (!got_break) {
9550                 correct = false;
9551         }
9552
9553         printf("finished posix acl oplock test\n");
9554
9555         return correct;
9556 }
9557
9558 static bool run_posix_acl_shareroot_test(int dummy)
9559 {
9560         struct cli_state *cli;
9561         NTSTATUS status;
9562         bool correct = false;
9563         char *posix_acl = NULL;
9564         size_t posix_acl_len = 0;
9565         uint16_t num_file_acls = 0;
9566         uint16_t num_dir_acls = 0;
9567         uint16_t i;
9568         uint32_t expected_size = 0;
9569         bool got_user = false;
9570         bool got_group = false;
9571         bool got_other = false;
9572         TALLOC_CTX *frame = NULL;
9573
9574         frame = talloc_stackframe();
9575
9576         printf("starting posix_acl_shareroot test\n");
9577
9578         if (!torture_open_connection(&cli, 0)) {
9579                 TALLOC_FREE(frame);
9580                 return false;
9581         }
9582
9583         smbXcli_conn_set_sockopt(cli->conn, sockops);
9584
9585         status = torture_setup_unix_extensions(cli);
9586         if (!NT_STATUS_IS_OK(status)) {
9587                 printf("Failed to setup unix extensions\n");
9588                 goto out;
9589         }
9590
9591         /* Get the POSIX ACL on the root of the share. */
9592         status = cli_posix_getacl(cli,
9593                                 ".",
9594                                 frame,
9595                                 &posix_acl_len,
9596                                 &posix_acl);
9597
9598         if (!NT_STATUS_IS_OK(status)) {
9599                 printf("cli_posix_getacl of '.' failed (%s)\n",
9600                         nt_errstr(status));
9601                 goto out;
9602         }
9603
9604         if (posix_acl_len < 6 ||
9605                         SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9606                 printf("getfacl ., unknown POSIX acl version %u.\n",
9607                         (unsigned int)CVAL(posix_acl,0) );
9608                 goto out;
9609         }
9610
9611         num_file_acls = SVAL(posix_acl,2);
9612         num_dir_acls = SVAL(posix_acl,4);
9613         expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9614                                 SMB_POSIX_ACL_ENTRY_SIZE*
9615                                 (num_file_acls+num_dir_acls);
9616
9617         if (posix_acl_len != expected_size) {
9618                 printf("incorrect POSIX acl buffer size "
9619                         "(should be %u, was %u).\n",
9620                         (unsigned int)expected_size,
9621                         (unsigned int)posix_acl_len);
9622                 goto out;
9623         }
9624
9625         /*
9626          * We don't need to know what the ACL's are
9627          * we just need to know we have at least 3
9628          * file entries (u,g,o).
9629          */
9630
9631         for (i = 0; i < num_file_acls; i++) {
9632                 unsigned char tagtype =
9633                         CVAL(posix_acl,
9634                                 SMB_POSIX_ACL_HEADER_SIZE+
9635                                 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9636
9637                 switch(tagtype) {
9638                         case SMB_POSIX_ACL_USER_OBJ:
9639                                 got_user = true;
9640                                 break;
9641                         case SMB_POSIX_ACL_GROUP_OBJ:
9642                                 got_group = true;
9643                                 break;
9644                         case SMB_POSIX_ACL_OTHER:
9645                                 got_other = true;
9646                                 break;
9647                         default:
9648                                 break;
9649                 }
9650         }
9651
9652         if (!got_user) {
9653                 printf("Missing user entry\n");
9654                 goto out;
9655         }
9656
9657         if (!got_group) {
9658                 printf("Missing group entry\n");
9659                 goto out;
9660         }
9661
9662         if (!got_other) {
9663                 printf("Missing other entry\n");
9664                 goto out;
9665         }
9666
9667         correct = true;
9668
9669   out:
9670
9671         if (!torture_close_connection(cli)) {
9672                 correct = false;
9673         }
9674
9675         printf("finished posix acl shareroot test\n");
9676         TALLOC_FREE(frame);
9677
9678         return correct;
9679 }
9680
9681 static uint32_t open_attrs_table[] = {
9682                 FILE_ATTRIBUTE_NORMAL,
9683                 FILE_ATTRIBUTE_ARCHIVE,
9684                 FILE_ATTRIBUTE_READONLY,
9685                 FILE_ATTRIBUTE_HIDDEN,
9686                 FILE_ATTRIBUTE_SYSTEM,
9687
9688                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9689                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9690                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9691                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9692                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9693                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9694
9695                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9696                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9697                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9698                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9699 };
9700
9701 struct trunc_open_results {
9702         unsigned int num;
9703         uint32_t init_attr;
9704         uint32_t trunc_attr;
9705         uint32_t result_attr;
9706 };
9707
9708 static struct trunc_open_results attr_results[] = {
9709         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9710         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9711         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9712         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9713         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9714         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9715         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9716         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9717         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9718         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9719         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9720         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9721         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9722         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9723         { 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 },
9724         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9725         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9726         { 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 },
9727         { 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 },
9728         { 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 },
9729         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9730         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9731         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9732         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9733         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9734         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9735 };
9736
9737 static bool run_openattrtest(int dummy)
9738 {
9739         static struct cli_state *cli1;
9740         const char *fname = "\\openattr.file";
9741         uint16_t fnum1;
9742         bool correct = True;
9743         uint32_t attr;
9744         unsigned int i, j, k, l;
9745         NTSTATUS status;
9746
9747         printf("starting open attr test\n");
9748
9749         if (!torture_open_connection(&cli1, 0)) {
9750                 return False;
9751         }
9752
9753         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9754
9755         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9756                 cli_setatr(cli1, fname, 0, 0);
9757                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9758
9759                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9760                                        open_attrs_table[i], FILE_SHARE_NONE,
9761                                        FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9762                 if (!NT_STATUS_IS_OK(status)) {
9763                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9764                         return False;
9765                 }
9766
9767                 status = cli_close(cli1, fnum1);
9768                 if (!NT_STATUS_IS_OK(status)) {
9769                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9770                         return False;
9771                 }
9772
9773                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9774                         status = cli_ntcreate(cli1, fname, 0,
9775                                               FILE_READ_DATA|FILE_WRITE_DATA,
9776                                               open_attrs_table[j],
9777                                               FILE_SHARE_NONE, FILE_OVERWRITE,
9778                                               0, 0, &fnum1, NULL);
9779                         if (!NT_STATUS_IS_OK(status)) {
9780                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9781                                         if (attr_results[l].num == k) {
9782                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9783                                                                 k, open_attrs_table[i],
9784                                                                 open_attrs_table[j],
9785                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
9786                                                 correct = False;
9787                                         }
9788                                 }
9789
9790                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9791                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9792                                                         k, open_attrs_table[i], open_attrs_table[j],
9793                                                         nt_errstr(status));
9794                                         correct = False;
9795                                 }
9796 #if 0
9797                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9798 #endif
9799                                 k++;
9800                                 continue;
9801                         }
9802
9803                         status = cli_close(cli1, fnum1);
9804                         if (!NT_STATUS_IS_OK(status)) {
9805                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9806                                 return False;
9807                         }
9808
9809                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9810                         if (!NT_STATUS_IS_OK(status)) {
9811                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9812                                 return False;
9813                         }
9814
9815 #if 0
9816                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9817                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
9818 #endif
9819
9820                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9821                                 if (attr_results[l].num == k) {
9822                                         if (attr != attr_results[l].result_attr ||
9823                                                         open_attrs_table[i] != attr_results[l].init_attr ||
9824                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
9825                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9826                                                 open_attrs_table[i],
9827                                                 open_attrs_table[j],
9828                                                 (unsigned int)attr,
9829                                                 attr_results[l].result_attr);
9830                                                 correct = False;
9831                                         }
9832                                         break;
9833                                 }
9834                         }
9835                         k++;
9836                 }
9837         }
9838
9839         cli_setatr(cli1, fname, 0, 0);
9840         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9841
9842         printf("open attr test %s.\n", correct ? "passed" : "failed");
9843
9844         if (!torture_close_connection(cli1)) {
9845                 correct = False;
9846         }
9847         return correct;
9848 }
9849
9850 static NTSTATUS list_fn(struct file_info *finfo,
9851                     const char *name, void *state)
9852 {
9853         int *matched = (int *)state;
9854         if (matched != NULL) {
9855                 *matched += 1;
9856         }
9857         return NT_STATUS_OK;
9858 }
9859
9860 /*
9861   test directory listing speed
9862  */
9863 static bool run_dirtest(int dummy)
9864 {
9865         int i;
9866         static struct cli_state *cli;
9867         uint16_t fnum;
9868         struct timeval core_start;
9869         bool correct = True;
9870         int matched;
9871
9872         printf("starting directory test\n");
9873
9874         if (!torture_open_connection(&cli, 0)) {
9875                 return False;
9876         }
9877
9878         smbXcli_conn_set_sockopt(cli->conn, sockops);
9879
9880         srandom(0);
9881         for (i=0;i<torture_numops;i++) {
9882                 fstring fname;
9883                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9884                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9885                         fprintf(stderr,"Failed to open %s\n", fname);
9886                         return False;
9887                 }
9888                 cli_close(cli, fnum);
9889         }
9890
9891         core_start = timeval_current();
9892
9893         matched = 0;
9894         cli_list(cli, "a*.*", 0, list_fn, &matched);
9895         printf("Matched %d\n", matched);
9896
9897         matched = 0;
9898         cli_list(cli, "b*.*", 0, list_fn, &matched);
9899         printf("Matched %d\n", matched);
9900
9901         matched = 0;
9902         cli_list(cli, "xyzabc", 0, list_fn, &matched);
9903         printf("Matched %d\n", matched);
9904
9905         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9906
9907         srandom(0);
9908         for (i=0;i<torture_numops;i++) {
9909                 fstring fname;
9910                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9911                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9912         }
9913
9914         if (!torture_close_connection(cli)) {
9915                 correct = False;
9916         }
9917
9918         printf("finished dirtest\n");
9919
9920         return correct;
9921 }
9922
9923 static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9924                    void *state)
9925 {
9926         struct cli_state *pcli = (struct cli_state *)state;
9927         fstring fname;
9928         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9929
9930         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9931                 return NT_STATUS_OK;
9932
9933         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9934                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9935                         printf("del_fn: failed to rmdir %s\n,", fname );
9936         } else {
9937                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9938                         printf("del_fn: failed to unlink %s\n,", fname );
9939         }
9940         return NT_STATUS_OK;
9941 }
9942
9943
9944 /*
9945    send a raw ioctl - used by the torture code
9946 */
9947 static NTSTATUS cli_raw_ioctl(struct cli_state *cli,
9948                               uint16_t fnum,
9949                               uint32_t code,
9950                               DATA_BLOB *blob)
9951 {
9952         uint16_t vwv[3];
9953         NTSTATUS status;
9954
9955         PUSH_LE_U16(vwv + 0, 0, fnum);
9956         PUSH_LE_U16(vwv + 1, 0, code >> 16);
9957         PUSH_LE_U16(vwv + 2, 0, (code & 0xFFFF));
9958
9959         status = cli_smb(talloc_tos(),
9960                          cli,
9961                          SMBioctl,
9962                          0,
9963                          3,
9964                          vwv,
9965                          0,
9966                          NULL,
9967                          NULL,
9968                          0,
9969                          NULL,
9970                          NULL,
9971                          NULL,
9972                          NULL);
9973         if (!NT_STATUS_IS_OK(status)) {
9974                 return status;
9975         }
9976         *blob = data_blob_null;
9977         return NT_STATUS_OK;
9978 }
9979
9980 /*
9981   sees what IOCTLs are supported
9982  */
9983 bool torture_ioctl_test(int dummy)
9984 {
9985         static struct cli_state *cli;
9986         uint16_t device, function;
9987         uint16_t fnum;
9988         const char *fname = "\\ioctl.dat";
9989         DATA_BLOB blob;
9990         NTSTATUS status;
9991
9992         if (!torture_open_connection(&cli, 0)) {
9993                 return False;
9994         }
9995
9996         printf("starting ioctl test\n");
9997
9998         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9999
10000         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
10001         if (!NT_STATUS_IS_OK(status)) {
10002                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
10003                 return False;
10004         }
10005
10006         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
10007         printf("ioctl device info: %s\n", nt_errstr(status));
10008
10009         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
10010         printf("ioctl job info: %s\n", nt_errstr(status));
10011
10012         for (device=0;device<0x100;device++) {
10013                 printf("ioctl test with device = 0x%x\n", device);
10014                 for (function=0;function<0x100;function++) {
10015                         uint32_t code = (device<<16) | function;
10016
10017                         status = cli_raw_ioctl(cli, fnum, code, &blob);
10018
10019                         if (NT_STATUS_IS_OK(status)) {
10020                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
10021                                        (int)blob.length);
10022                                 data_blob_free(&blob);
10023                         }
10024                 }
10025         }
10026
10027         if (!torture_close_connection(cli)) {
10028                 return False;
10029         }
10030
10031         return True;
10032 }
10033
10034
10035 /*
10036   tries variants of chkpath
10037  */
10038 bool torture_chkpath_test(int dummy)
10039 {
10040         static struct cli_state *cli;
10041         uint16_t fnum;
10042         bool ret;
10043         NTSTATUS status;
10044
10045         if (!torture_open_connection(&cli, 0)) {
10046                 return False;
10047         }
10048
10049         printf("starting chkpath test\n");
10050
10051         /* cleanup from an old run */
10052         torture_deltree(cli, "\\chkpath.dir");
10053
10054         status = cli_mkdir(cli, "\\chkpath.dir");
10055         if (!NT_STATUS_IS_OK(status)) {
10056                 printf("mkdir1 failed : %s\n", nt_errstr(status));
10057                 return False;
10058         }
10059
10060         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
10061         if (!NT_STATUS_IS_OK(status)) {
10062                 printf("mkdir2 failed : %s\n", nt_errstr(status));
10063                 return False;
10064         }
10065
10066         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
10067                           DENY_NONE, &fnum);
10068         if (!NT_STATUS_IS_OK(status)) {
10069                 printf("open1 failed (%s)\n", nt_errstr(status));
10070                 return False;
10071         }
10072         cli_close(cli, fnum);
10073
10074         status = cli_chkpath(cli, "\\chkpath.dir");
10075         if (!NT_STATUS_IS_OK(status)) {
10076                 printf("chkpath1 failed: %s\n", nt_errstr(status));
10077                 ret = False;
10078         }
10079
10080         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
10081         if (!NT_STATUS_IS_OK(status)) {
10082                 printf("chkpath2 failed: %s\n", nt_errstr(status));
10083                 ret = False;
10084         }
10085
10086         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
10087         if (!NT_STATUS_IS_OK(status)) {
10088                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10089                                   NT_STATUS_NOT_A_DIRECTORY);
10090         } else {
10091                 printf("* chkpath on a file should fail\n");
10092                 ret = False;
10093         }
10094
10095         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
10096         if (!NT_STATUS_IS_OK(status)) {
10097                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
10098                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
10099         } else {
10100                 printf("* chkpath on a non existent file should fail\n");
10101                 ret = False;
10102         }
10103
10104         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
10105         if (!NT_STATUS_IS_OK(status)) {
10106                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10107                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
10108         } else {
10109                 printf("* chkpath on a non existent component should fail\n");
10110                 ret = False;
10111         }
10112
10113         torture_deltree(cli, "\\chkpath.dir");
10114
10115         if (!torture_close_connection(cli)) {
10116                 return False;
10117         }
10118
10119         return ret;
10120 }
10121
10122 static bool run_eatest(int dummy)
10123 {
10124         static struct cli_state *cli;
10125         const char *fname = "\\eatest.txt";
10126         bool correct = True;
10127         uint16_t fnum;
10128         size_t i, num_eas;
10129         struct ea_struct *ea_list = NULL;
10130         TALLOC_CTX *mem_ctx = talloc_init("eatest");
10131         NTSTATUS status;
10132
10133         printf("starting eatest\n");
10134
10135         if (!torture_open_connection(&cli, 0)) {
10136                 talloc_destroy(mem_ctx);
10137                 return False;
10138         }
10139
10140         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10141
10142         status = cli_ntcreate(cli, fname, 0,
10143                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10144                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10145                               0x4044, 0, &fnum, NULL);
10146         if (!NT_STATUS_IS_OK(status)) {
10147                 printf("open failed - %s\n", nt_errstr(status));
10148                 talloc_destroy(mem_ctx);
10149                 return False;
10150         }
10151
10152         for (i = 0; i < 10; i++) {
10153                 fstring ea_name, ea_val;
10154
10155                 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10156                 memset(ea_val, (char)i+1, i+1);
10157                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10158                 if (!NT_STATUS_IS_OK(status)) {
10159                         printf("ea_set of name %s failed - %s\n", ea_name,
10160                                nt_errstr(status));
10161                         talloc_destroy(mem_ctx);
10162                         return False;
10163                 }
10164         }
10165
10166         cli_close(cli, fnum);
10167         for (i = 0; i < 10; i++) {
10168                 fstring ea_name, ea_val;
10169
10170                 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10171                 memset(ea_val, (char)i+1, i+1);
10172                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10173                 if (!NT_STATUS_IS_OK(status)) {
10174                         printf("ea_set of name %s failed - %s\n", ea_name,
10175                                nt_errstr(status));
10176                         talloc_destroy(mem_ctx);
10177                         return False;
10178                 }
10179         }
10180
10181         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10182         if (!NT_STATUS_IS_OK(status)) {
10183                 printf("ea_get list failed - %s\n", nt_errstr(status));
10184                 correct = False;
10185         }
10186
10187         printf("num_eas = %d\n", (int)num_eas);
10188
10189         if (num_eas != 20) {
10190                 printf("Should be 20 EA's stored... failing.\n");
10191                 correct = False;
10192         }
10193
10194         for (i = 0; i < num_eas; i++) {
10195                 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10196                 dump_data(0, ea_list[i].value.data,
10197                           ea_list[i].value.length);
10198         }
10199
10200         /* Setting EA's to zero length deletes them. Test this */
10201         printf("Now deleting all EA's - case independent....\n");
10202
10203 #if 1
10204         cli_set_ea_path(cli, fname, "", "", 0);
10205 #else
10206         for (i = 0; i < 20; i++) {
10207                 fstring ea_name;
10208                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10209                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10210                 if (!NT_STATUS_IS_OK(status)) {
10211                         printf("ea_set of name %s failed - %s\n", ea_name,
10212                                nt_errstr(status));
10213                         talloc_destroy(mem_ctx);
10214                         return False;
10215                 }
10216         }
10217 #endif
10218
10219         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10220         if (!NT_STATUS_IS_OK(status)) {
10221                 printf("ea_get list failed - %s\n", nt_errstr(status));
10222                 correct = False;
10223         }
10224
10225         printf("num_eas = %d\n", (int)num_eas);
10226         for (i = 0; i < num_eas; i++) {
10227                 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10228                 dump_data(0, ea_list[i].value.data,
10229                           ea_list[i].value.length);
10230         }
10231
10232         if (num_eas != 0) {
10233                 printf("deleting EA's failed.\n");
10234                 correct = False;
10235         }
10236
10237         /* Try and delete a non existent EA. */
10238         status = cli_set_ea_path(cli, fname, "foo", "", 0);
10239         if (!NT_STATUS_IS_OK(status)) {
10240                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10241                        nt_errstr(status));
10242                 correct = False;
10243         }
10244
10245         talloc_destroy(mem_ctx);
10246         if (!torture_close_connection(cli)) {
10247                 correct = False;
10248         }
10249
10250         return correct;
10251 }
10252
10253 static bool run_dirtest1(int dummy)
10254 {
10255         int i;
10256         static struct cli_state *cli;
10257         uint16_t fnum;
10258         int num_seen;
10259         bool correct = True;
10260
10261         printf("starting directory test\n");
10262
10263         if (!torture_open_connection(&cli, 0)) {
10264                 return False;
10265         }
10266
10267         smbXcli_conn_set_sockopt(cli->conn, sockops);
10268
10269         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10270         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10271         cli_rmdir(cli, "\\LISTDIR");
10272         cli_mkdir(cli, "\\LISTDIR");
10273
10274         /* Create 1000 files and 1000 directories. */
10275         for (i=0;i<1000;i++) {
10276                 fstring fname;
10277                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10278                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10279                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10280                                    0, 0, &fnum, NULL))) {
10281                         fprintf(stderr,"Failed to open %s\n", fname);
10282                         return False;
10283                 }
10284                 cli_close(cli, fnum);
10285         }
10286         for (i=0;i<1000;i++) {
10287                 fstring fname;
10288                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10289                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10290                         fprintf(stderr,"Failed to open %s\n", fname);
10291                         return False;
10292                 }
10293         }
10294
10295         /* Now ensure that doing an old list sees both files and directories. */
10296         num_seen = 0;
10297         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10298         printf("num_seen = %d\n", num_seen );
10299         /* We should see 100 files + 1000 directories + . and .. */
10300         if (num_seen != 2002)
10301                 correct = False;
10302
10303         /* Ensure if we have the "must have" bits we only see the
10304          * relevant entries.
10305          */
10306         num_seen = 0;
10307         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10308         printf("num_seen = %d\n", num_seen );
10309         if (num_seen != 1002)
10310                 correct = False;
10311
10312         num_seen = 0;
10313         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10314         printf("num_seen = %d\n", num_seen );
10315         if (num_seen != 1000)
10316                 correct = False;
10317
10318         /* Delete everything. */
10319         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10320         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10321         cli_rmdir(cli, "\\LISTDIR");
10322
10323 #if 0
10324         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10325         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10326         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10327 #endif
10328
10329         if (!torture_close_connection(cli)) {
10330                 correct = False;
10331         }
10332
10333         printf("finished dirtest1\n");
10334
10335         return correct;
10336 }
10337
10338 static bool run_error_map_extract(int dummy) {
10339
10340         static struct cli_state *c_dos;
10341         static struct cli_state *c_nt;
10342         NTSTATUS status;
10343
10344         uint32_t error;
10345
10346         uint32_t errnum;
10347         uint8_t errclass;
10348
10349         NTSTATUS nt_status;
10350
10351         fstring user;
10352
10353         /* NT-Error connection */
10354
10355         disable_spnego = true;
10356         if (!(c_nt = open_nbt_connection())) {
10357                 disable_spnego = false;
10358                 return False;
10359         }
10360         disable_spnego = false;
10361
10362         status = smbXcli_negprot(c_nt->conn,
10363                                  c_nt->timeout,
10364                                  PROTOCOL_CORE,
10365                                  PROTOCOL_NT1,
10366                                  NULL,
10367                                  NULL,
10368                                  NULL);
10369
10370         if (!NT_STATUS_IS_OK(status)) {
10371                 printf("%s rejected the NT-error negprot (%s)\n", host,
10372                        nt_errstr(status));
10373                 cli_shutdown(c_nt);
10374                 return False;
10375         }
10376
10377         status = cli_session_setup_anon(c_nt);
10378         if (!NT_STATUS_IS_OK(status)) {
10379                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10380                 return False;
10381         }
10382
10383         /* DOS-Error connection */
10384
10385         disable_spnego = true;
10386         force_dos_errors = true;
10387         if (!(c_dos = open_nbt_connection())) {
10388                 disable_spnego = false;
10389                 force_dos_errors = false;
10390                 return False;
10391         }
10392         disable_spnego = false;
10393         force_dos_errors = false;
10394
10395         status = smbXcli_negprot(c_dos->conn,
10396                                  c_dos->timeout,
10397                                  PROTOCOL_CORE,
10398                                  PROTOCOL_NT1,
10399                                  NULL,
10400                                  NULL,
10401                                  NULL);
10402         if (!NT_STATUS_IS_OK(status)) {
10403                 printf("%s rejected the DOS-error negprot (%s)\n", host,
10404                        nt_errstr(status));
10405                 cli_shutdown(c_dos);
10406                 return False;
10407         }
10408
10409         status = cli_session_setup_anon(c_dos);
10410         if (!NT_STATUS_IS_OK(status)) {
10411                 printf("%s rejected the DOS-error initial session setup (%s)\n",
10412                         host, nt_errstr(status));
10413                 return False;
10414         }
10415
10416         c_nt->map_dos_errors = false;
10417         c_dos->map_dos_errors = false;
10418
10419         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10420                 struct cli_credentials *user_creds = NULL;
10421
10422                 fstr_sprintf(user, "%X", error);
10423
10424                 user_creds = cli_session_creds_init(talloc_tos(),
10425                                                     user,
10426                                                     workgroup,
10427                                                     NULL, /* realm */
10428                                                     password,
10429                                                     false, /* use_kerberos */
10430                                                     false, /* fallback_after_kerberos */
10431                                                     false, /* use_ccache */
10432                                                     false); /* password_is_nt_hash */
10433                 if (user_creds == NULL) {
10434                         printf("cli_session_creds_init(%s) failed\n", user);
10435                         return false;
10436                 }
10437
10438                 status = cli_session_setup_creds(c_nt, user_creds);
10439                 if (NT_STATUS_IS_OK(status)) {
10440                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10441                 }
10442
10443                 /* Case #1: 32-bit NT errors */
10444                 if (!NT_STATUS_IS_DOS(status)) {
10445                         nt_status = status;
10446                 } else {
10447                         printf("/** Dos error on NT connection! (%s) */\n",
10448                                nt_errstr(status));
10449                         nt_status = NT_STATUS(0xc0000000);
10450                 }
10451
10452                 status = cli_session_setup_creds(c_dos, user_creds);
10453                 if (NT_STATUS_IS_OK(status)) {
10454                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10455                 }
10456
10457                 /* Case #1: 32-bit NT errors */
10458                 if (NT_STATUS_IS_DOS(status)) {
10459                         printf("/** NT error on DOS connection! (%s) */\n",
10460                                nt_errstr(status));
10461                         errnum = errclass = 0;
10462                 } else {
10463                         errclass = NT_STATUS_DOS_CLASS(status);
10464                         errnum = NT_STATUS_DOS_CODE(status);
10465                 }
10466
10467                 if (NT_STATUS_V(nt_status) != error) {
10468                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10469                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
10470                                get_nt_error_c_code(talloc_tos(), nt_status));
10471                 }
10472
10473                 printf("\t{%s,\t%s,\t%s},\n",
10474                        smb_dos_err_class(errclass),
10475                        smb_dos_err_name(errclass, errnum),
10476                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10477
10478                 TALLOC_FREE(user_creds);
10479         }
10480         return True;
10481 }
10482
10483 static bool run_sesssetup_bench(int dummy)
10484 {
10485         static struct cli_state *c;
10486         const char *fname = "\\file.dat";
10487         uint16_t fnum;
10488         NTSTATUS status;
10489         int i;
10490
10491         if (!torture_open_connection(&c, 0)) {
10492                 return false;
10493         }
10494
10495         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10496                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10497                               FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10498         if (!NT_STATUS_IS_OK(status)) {
10499                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10500                 return false;
10501         }
10502
10503         for (i=0; i<torture_numops; i++) {
10504                 status = cli_session_setup_creds(c, torture_creds);
10505                 if (!NT_STATUS_IS_OK(status)) {
10506                         d_printf("(%s) cli_session_setup_creds failed: %s\n",
10507                                  __location__, nt_errstr(status));
10508                         return false;
10509                 }
10510
10511                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
10512
10513                 status = cli_ulogoff(c);
10514                 if (!NT_STATUS_IS_OK(status)) {
10515                         d_printf("(%s) cli_ulogoff failed: %s\n",
10516                                  __location__, nt_errstr(status));
10517                         return false;
10518                 }
10519         }
10520
10521         return true;
10522 }
10523
10524 static bool subst_test(const char *str, const char *user, const char *domain,
10525                        uid_t uid, gid_t gid, const char *expected)
10526 {
10527         char *subst;
10528         bool result = true;
10529
10530         subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10531
10532         if (strcmp(subst, expected) != 0) {
10533                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10534                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10535                        expected);
10536                 result = false;
10537         }
10538
10539         TALLOC_FREE(subst);
10540         return result;
10541 }
10542
10543 static void chain1_open_completion(struct tevent_req *req)
10544 {
10545         uint16_t fnum;
10546         NTSTATUS status;
10547         status = cli_openx_recv(req, &fnum);
10548         TALLOC_FREE(req);
10549
10550         d_printf("cli_openx_recv returned %s: %d\n",
10551                  nt_errstr(status),
10552                  NT_STATUS_IS_OK(status) ? fnum : -1);
10553 }
10554
10555 static void chain1_write_completion(struct tevent_req *req)
10556 {
10557         size_t written;
10558         NTSTATUS status;
10559         status = cli_write_andx_recv(req, &written);
10560         TALLOC_FREE(req);
10561
10562         d_printf("cli_write_andx_recv returned %s: %d\n",
10563                  nt_errstr(status),
10564                  NT_STATUS_IS_OK(status) ? (int)written : -1);
10565 }
10566
10567 static void chain1_close_completion(struct tevent_req *req)
10568 {
10569         NTSTATUS status;
10570         bool *done = (bool *)tevent_req_callback_data_void(req);
10571
10572         status = cli_close_recv(req);
10573         *done = true;
10574
10575         TALLOC_FREE(req);
10576
10577         d_printf("cli_close returned %s\n", nt_errstr(status));
10578 }
10579
10580 static bool run_chain1(int dummy)
10581 {
10582         struct cli_state *cli1;
10583         struct tevent_context *evt = samba_tevent_context_init(NULL);
10584         struct tevent_req *reqs[3], *smbreqs[3];
10585         bool done = false;
10586         const char *str = "foobar";
10587         const char *fname = "\\test_chain";
10588         NTSTATUS status;
10589
10590         printf("starting chain1 test\n");
10591         if (!torture_open_connection(&cli1, 0)) {
10592                 return False;
10593         }
10594
10595         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10596
10597         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10598
10599         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10600                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
10601         if (reqs[0] == NULL) return false;
10602         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10603
10604
10605         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10606                                         (const uint8_t *)str, 0, strlen(str)+1,
10607                                         smbreqs, 1, &smbreqs[1]);
10608         if (reqs[1] == NULL) return false;
10609         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10610
10611         reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10612         if (reqs[2] == NULL) return false;
10613         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10614
10615         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10616         if (!NT_STATUS_IS_OK(status)) {
10617                 return false;
10618         }
10619
10620         while (!done) {
10621                 tevent_loop_once(evt);
10622         }
10623
10624         torture_close_connection(cli1);
10625         return True;
10626 }
10627
10628 static void chain2_sesssetup_completion(struct tevent_req *req)
10629 {
10630         NTSTATUS status;
10631         status = cli_session_setup_guest_recv(req);
10632         d_printf("sesssetup returned %s\n", nt_errstr(status));
10633 }
10634
10635 static void chain2_tcon_completion(struct tevent_req *req)
10636 {
10637         bool *done = (bool *)tevent_req_callback_data_void(req);
10638         NTSTATUS status;
10639         status = cli_tcon_andx_recv(req);
10640         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10641         *done = true;
10642 }
10643
10644 static bool run_chain2(int dummy)
10645 {
10646         struct cli_state *cli1;
10647         struct tevent_context *evt = samba_tevent_context_init(NULL);
10648         struct tevent_req *reqs[2], *smbreqs[2];
10649         bool done = false;
10650         NTSTATUS status;
10651         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10652
10653         printf("starting chain2 test\n");
10654         status = cli_start_connection(talloc_tos(),
10655                                       &cli1,
10656                                       lp_netbios_name(),
10657                                       host,
10658                                       NULL,
10659                                       port_to_use,
10660                                       SMB_SIGNING_DEFAULT,
10661                                       flags);
10662         if (!NT_STATUS_IS_OK(status)) {
10663                 return False;
10664         }
10665
10666         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10667
10668         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10669                                                  &smbreqs[0]);
10670         if (reqs[0] == NULL) return false;
10671         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10672
10673         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10674                                        "?????", NULL, 0, &smbreqs[1]);
10675         if (reqs[1] == NULL) return false;
10676         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10677
10678         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10679         if (!NT_STATUS_IS_OK(status)) {
10680                 return false;
10681         }
10682
10683         while (!done) {
10684                 tevent_loop_once(evt);
10685         }
10686
10687         torture_close_connection(cli1);
10688         return True;
10689 }
10690
10691
10692 struct torture_createdel_state {
10693         struct tevent_context *ev;
10694         struct cli_state *cli;
10695 };
10696
10697 static void torture_createdel_created(struct tevent_req *subreq);
10698 static void torture_createdel_closed(struct tevent_req *subreq);
10699
10700 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10701                                                  struct tevent_context *ev,
10702                                                  struct cli_state *cli,
10703                                                  const char *name)
10704 {
10705         struct tevent_req *req, *subreq;
10706         struct torture_createdel_state *state;
10707
10708         req = tevent_req_create(mem_ctx, &state,
10709                                 struct torture_createdel_state);
10710         if (req == NULL) {
10711                 return NULL;
10712         }
10713         state->ev = ev;
10714         state->cli = cli;
10715
10716         subreq = cli_ntcreate_send(
10717                 state, ev, cli, name, 0,
10718                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10719                 FILE_ATTRIBUTE_NORMAL,
10720                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10721                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10722                 SMB2_IMPERSONATION_IMPERSONATION, 0);
10723
10724         if (tevent_req_nomem(subreq, req)) {
10725                 return tevent_req_post(req, ev);
10726         }
10727         tevent_req_set_callback(subreq, torture_createdel_created, req);
10728         return req;
10729 }
10730
10731 static void torture_createdel_created(struct tevent_req *subreq)
10732 {
10733         struct tevent_req *req = tevent_req_callback_data(
10734                 subreq, struct tevent_req);
10735         struct torture_createdel_state *state = tevent_req_data(
10736                 req, struct torture_createdel_state);
10737         NTSTATUS status;
10738         uint16_t fnum;
10739
10740         status = cli_ntcreate_recv(subreq, &fnum, NULL);
10741         TALLOC_FREE(subreq);
10742         if (tevent_req_nterror(req, status)) {
10743                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10744                            nt_errstr(status)));
10745                 return;
10746         }
10747
10748         subreq = cli_close_send(state, state->ev, state->cli, fnum, 0);
10749         if (tevent_req_nomem(subreq, req)) {
10750                 return;
10751         }
10752         tevent_req_set_callback(subreq, torture_createdel_closed, req);
10753 }
10754
10755 static void torture_createdel_closed(struct tevent_req *subreq)
10756 {
10757         struct tevent_req *req = tevent_req_callback_data(
10758                 subreq, struct tevent_req);
10759         NTSTATUS status;
10760
10761         status = cli_close_recv(subreq);
10762         if (tevent_req_nterror(req, status)) {
10763                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10764                 return;
10765         }
10766         tevent_req_done(req);
10767 }
10768
10769 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10770 {
10771         return tevent_req_simple_recv_ntstatus(req);
10772 }
10773
10774 struct torture_createdels_state {
10775         struct tevent_context *ev;
10776         struct cli_state *cli;
10777         const char *base_name;
10778         int sent;
10779         int received;
10780         int num_files;
10781         struct tevent_req **reqs;
10782 };
10783
10784 static void torture_createdels_done(struct tevent_req *subreq);
10785
10786 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10787                                                   struct tevent_context *ev,
10788                                                   struct cli_state *cli,
10789                                                   const char *base_name,
10790                                                   int num_parallel,
10791                                                   int num_files)
10792 {
10793         struct tevent_req *req;
10794         struct torture_createdels_state *state;
10795         int i;
10796
10797         req = tevent_req_create(mem_ctx, &state,
10798                                 struct torture_createdels_state);
10799         if (req == NULL) {
10800                 return NULL;
10801         }
10802         state->ev = ev;
10803         state->cli = cli;
10804         state->base_name = talloc_strdup(state, base_name);
10805         if (tevent_req_nomem(state->base_name, req)) {
10806                 return tevent_req_post(req, ev);
10807         }
10808         state->num_files = MAX(num_parallel, num_files);
10809         state->sent = 0;
10810         state->received = 0;
10811
10812         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10813         if (tevent_req_nomem(state->reqs, req)) {
10814                 return tevent_req_post(req, ev);
10815         }
10816
10817         for (i=0; i<num_parallel; i++) {
10818                 char *name;
10819
10820                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10821                                        state->sent);
10822                 if (tevent_req_nomem(name, req)) {
10823                         return tevent_req_post(req, ev);
10824                 }
10825                 state->reqs[i] = torture_createdel_send(
10826                         state->reqs, state->ev, state->cli, name);
10827                 if (tevent_req_nomem(state->reqs[i], req)) {
10828                         return tevent_req_post(req, ev);
10829                 }
10830                 name = talloc_move(state->reqs[i], &name);
10831                 tevent_req_set_callback(state->reqs[i],
10832                                         torture_createdels_done, req);
10833                 state->sent += 1;
10834         }
10835         return req;
10836 }
10837
10838 static void torture_createdels_done(struct tevent_req *subreq)
10839 {
10840         struct tevent_req *req = tevent_req_callback_data(
10841                 subreq, struct tevent_req);
10842         struct torture_createdels_state *state = tevent_req_data(
10843                 req, struct torture_createdels_state);
10844         size_t i, num_parallel = talloc_array_length(state->reqs);
10845         NTSTATUS status;
10846         char *name;
10847
10848         status = torture_createdel_recv(subreq);
10849         if (!NT_STATUS_IS_OK(status)){
10850                 DEBUG(10, ("torture_createdel_recv returned %s\n",
10851                            nt_errstr(status)));
10852                 TALLOC_FREE(subreq);
10853                 tevent_req_nterror(req, status);
10854                 return;
10855         }
10856
10857         for (i=0; i<num_parallel; i++) {
10858                 if (subreq == state->reqs[i]) {
10859                         break;
10860                 }
10861         }
10862         if (i == num_parallel) {
10863                 DEBUG(10, ("received something we did not send\n"));
10864                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10865                 return;
10866         }
10867         TALLOC_FREE(state->reqs[i]);
10868
10869         if (state->sent >= state->num_files) {
10870                 tevent_req_done(req);
10871                 return;
10872         }
10873
10874         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10875                                state->sent);
10876         if (tevent_req_nomem(name, req)) {
10877                 return;
10878         }
10879         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10880                                                 state->cli, name);
10881         if (tevent_req_nomem(state->reqs[i], req)) {
10882                 return;
10883         }
10884         name = talloc_move(state->reqs[i], &name);
10885         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10886         state->sent += 1;
10887 }
10888
10889 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10890 {
10891         return tevent_req_simple_recv_ntstatus(req);
10892 }
10893
10894 struct swallow_notify_state {
10895         struct tevent_context *ev;
10896         struct cli_state *cli;
10897         uint16_t fnum;
10898         uint32_t completion_filter;
10899         bool recursive;
10900         bool (*fn)(uint32_t action, const char *name, void *priv);
10901         void *priv;
10902 };
10903
10904 static void swallow_notify_done(struct tevent_req *subreq);
10905
10906 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10907                                               struct tevent_context *ev,
10908                                               struct cli_state *cli,
10909                                               uint16_t fnum,
10910                                               uint32_t completion_filter,
10911                                               bool recursive,
10912                                               bool (*fn)(uint32_t action,
10913                                                          const char *name,
10914                                                          void *priv),
10915                                               void *priv)
10916 {
10917         struct tevent_req *req, *subreq;
10918         struct swallow_notify_state *state;
10919
10920         req = tevent_req_create(mem_ctx, &state,
10921                                 struct swallow_notify_state);
10922         if (req == NULL) {
10923                 return NULL;
10924         }
10925         state->ev = ev;
10926         state->cli = cli;
10927         state->fnum = fnum;
10928         state->completion_filter = completion_filter;
10929         state->recursive = recursive;
10930         state->fn = fn;
10931         state->priv = priv;
10932
10933         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10934                                  0xffff, state->completion_filter,
10935                                  state->recursive);
10936         if (tevent_req_nomem(subreq, req)) {
10937                 return tevent_req_post(req, ev);
10938         }
10939         tevent_req_set_callback(subreq, swallow_notify_done, req);
10940         return req;
10941 }
10942
10943 static void swallow_notify_done(struct tevent_req *subreq)
10944 {
10945         struct tevent_req *req = tevent_req_callback_data(
10946                 subreq, struct tevent_req);
10947         struct swallow_notify_state *state = tevent_req_data(
10948                 req, struct swallow_notify_state);
10949         NTSTATUS status;
10950         uint32_t i, num_changes;
10951         struct notify_change *changes;
10952
10953         status = cli_notify_recv(subreq, state, &num_changes, &changes);
10954         TALLOC_FREE(subreq);
10955         if (!NT_STATUS_IS_OK(status)) {
10956                 DEBUG(10, ("cli_notify_recv returned %s\n",
10957                            nt_errstr(status)));
10958                 tevent_req_nterror(req, status);
10959                 return;
10960         }
10961
10962         for (i=0; i<num_changes; i++) {
10963                 state->fn(changes[i].action, changes[i].name, state->priv);
10964         }
10965         TALLOC_FREE(changes);
10966
10967         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10968                                  0xffff, state->completion_filter,
10969                                  state->recursive);
10970         if (tevent_req_nomem(subreq, req)) {
10971                 return;
10972         }
10973         tevent_req_set_callback(subreq, swallow_notify_done, req);
10974 }
10975
10976 static bool print_notifies(uint32_t action, const char *name, void *priv)
10977 {
10978         if (DEBUGLEVEL > 5) {
10979                 d_printf("%d %s\n", (int)action, name);
10980         }
10981         return true;
10982 }
10983
10984 static void notify_bench_done(struct tevent_req *req)
10985 {
10986         int *num_finished = (int *)tevent_req_callback_data_void(req);
10987         *num_finished += 1;
10988 }
10989
10990 static bool run_notify_bench(int dummy)
10991 {
10992         const char *dname = "\\notify-bench";
10993         struct tevent_context *ev;
10994         NTSTATUS status;
10995         uint16_t dnum;
10996         struct tevent_req *req1;
10997         struct tevent_req *req2 = NULL;
10998         int i, num_unc_names;
10999         int num_finished = 0;
11000
11001         printf("starting notify-bench test\n");
11002
11003         if (use_multishare_conn) {
11004                 char **unc_list;
11005                 unc_list = file_lines_load(multishare_conn_fname,
11006                                            &num_unc_names, 0, NULL);
11007                 if (!unc_list || num_unc_names <= 0) {
11008                         d_printf("Failed to load unc names list from '%s'\n",
11009                                  multishare_conn_fname);
11010                         return false;
11011                 }
11012                 TALLOC_FREE(unc_list);
11013         } else {
11014                 num_unc_names = 1;
11015         }
11016
11017         ev = samba_tevent_context_init(talloc_tos());
11018         if (ev == NULL) {
11019                 d_printf("tevent_context_init failed\n");
11020                 return false;
11021         }
11022
11023         for (i=0; i<num_unc_names; i++) {
11024                 struct cli_state *cli;
11025                 char *base_fname;
11026
11027                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
11028                                              dname, i);
11029                 if (base_fname == NULL) {
11030                         return false;
11031                 }
11032
11033                 if (!torture_open_connection(&cli, i)) {
11034                         return false;
11035                 }
11036
11037                 status = cli_ntcreate(cli, dname, 0,
11038                                       MAXIMUM_ALLOWED_ACCESS,
11039                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
11040                                       FILE_SHARE_DELETE,
11041                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
11042                                       &dnum, NULL);
11043
11044                 if (!NT_STATUS_IS_OK(status)) {
11045                         d_printf("Could not create %s: %s\n", dname,
11046                                  nt_errstr(status));
11047                         return false;
11048                 }
11049
11050                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
11051                                            FILE_NOTIFY_CHANGE_FILE_NAME |
11052                                            FILE_NOTIFY_CHANGE_DIR_NAME |
11053                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
11054                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
11055                                            false, print_notifies, NULL);
11056                 if (req1 == NULL) {
11057                         d_printf("Could not create notify request\n");
11058                         return false;
11059                 }
11060
11061                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
11062                                                base_fname, 10, torture_numops);
11063                 if (req2 == NULL) {
11064                         d_printf("Could not create createdels request\n");
11065                         return false;
11066                 }
11067                 TALLOC_FREE(base_fname);
11068
11069                 tevent_req_set_callback(req2, notify_bench_done,
11070                                         &num_finished);
11071         }
11072
11073         while (num_finished < num_unc_names) {
11074                 int ret;
11075                 ret = tevent_loop_once(ev);
11076                 if (ret != 0) {
11077                         d_printf("tevent_loop_once failed\n");
11078                         return false;
11079                 }
11080         }
11081
11082         if (!tevent_req_poll(req2, ev)) {
11083                 d_printf("tevent_req_poll failed\n");
11084         }
11085
11086         status = torture_createdels_recv(req2);
11087         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
11088
11089         return true;
11090 }
11091
11092 static bool run_mangle1(int dummy)
11093 {
11094         struct cli_state *cli;
11095         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
11096         uint16_t fnum;
11097         fstring alt_name;
11098         NTSTATUS status;
11099
11100         printf("starting mangle1 test\n");
11101         if (!torture_open_connection(&cli, 0)) {
11102                 return False;
11103         }
11104
11105         smbXcli_conn_set_sockopt(cli->conn, sockops);
11106
11107         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11108                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11109                               0, 0, &fnum, NULL);
11110         if (!NT_STATUS_IS_OK(status)) {
11111                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11112                 return false;
11113         }
11114         cli_close(cli, fnum);
11115
11116         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
11117         if (!NT_STATUS_IS_OK(status)) {
11118                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
11119                          nt_errstr(status));
11120                 return false;
11121         }
11122         d_printf("alt_name: %s\n", alt_name);
11123
11124         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
11125         if (!NT_STATUS_IS_OK(status)) {
11126                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
11127                          nt_errstr(status));
11128                 return false;
11129         }
11130         cli_close(cli, fnum);
11131
11132         status = cli_qpathinfo1(cli, alt_name, NULL, NULL, NULL, NULL, NULL);
11133         if (!NT_STATUS_IS_OK(status)) {
11134                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
11135                          nt_errstr(status));
11136                 return false;
11137         }
11138
11139         return true;
11140 }
11141
11142 static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
11143                                                  const char *mask,
11144                                                  void *state)
11145 {
11146         if (f->short_name == NULL) {
11147                 return NT_STATUS_OK;
11148         }
11149
11150         if (strlen(f->short_name) == 0) {
11151                 return NT_STATUS_OK;
11152         }
11153
11154         printf("unexpected shortname: %s\n", f->short_name);
11155
11156         return NT_STATUS_OBJECT_NAME_INVALID;
11157 }
11158
11159 static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11160                                             const char *mask,
11161                                             void *state)
11162 {
11163         char *name = state;
11164
11165         printf("name: %s\n", f->name);
11166         fstrcpy(name, f->name);
11167         return NT_STATUS_OK;
11168 }
11169
11170 static bool run_mangle_illegal(int dummy)
11171 {
11172         struct cli_state *cli = NULL;
11173         struct cli_state *cli_posix = NULL;
11174         const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11175         const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11176         char *mangled_path = NULL;
11177         uint16_t fnum;
11178         fstring name;
11179         fstring alt_name;
11180         NTSTATUS status;
11181
11182         printf("starting mangle-illegal test\n");
11183
11184         if (!torture_open_connection(&cli, 0)) {
11185                 return False;
11186         }
11187
11188         smbXcli_conn_set_sockopt(cli->conn, sockops);
11189
11190         if (!torture_open_connection(&cli_posix, 0)) {
11191                 return false;
11192         }
11193
11194         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11195
11196         status = torture_setup_unix_extensions(cli_posix);
11197         if (!NT_STATUS_IS_OK(status)) {
11198                 return false;
11199         }
11200
11201         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11202         status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11203         if (!NT_STATUS_IS_OK(status)) {
11204                 printf("mkdir1 failed : %s\n", nt_errstr(status));
11205                 return False;
11206         }
11207
11208         /*
11209          * Create a file with illegal NTFS characters and test that we
11210          * get a usable mangled name
11211          */
11212
11213         cli_setatr(cli_posix, illegal_fname, 0, 0);
11214         cli_posix_unlink(cli_posix, illegal_fname);
11215
11216         status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11217                                 0600, &fnum);
11218         if (!NT_STATUS_IS_OK(status)) {
11219                 printf("POSIX create of %s failed (%s)\n",
11220                        illegal_fname, nt_errstr(status));
11221                 return false;
11222         }
11223
11224         status = cli_close(cli_posix, fnum);
11225         if (!NT_STATUS_IS_OK(status)) {
11226                 printf("close failed (%s)\n", nt_errstr(status));
11227                 return false;
11228         }
11229
11230         status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11231         if (!NT_STATUS_IS_OK(status)) {
11232                 d_printf("cli_list failed: %s\n", nt_errstr(status));
11233                 return false;
11234         }
11235
11236         mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11237         if (mangled_path == NULL) {
11238                 return false;
11239         }
11240
11241         status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11242         if (!NT_STATUS_IS_OK(status)) {
11243                 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11244                 TALLOC_FREE(mangled_path);
11245                 return false;
11246         }
11247         TALLOC_FREE(mangled_path);
11248         cli_close(cli, fnum);
11249
11250         cli_setatr(cli_posix, illegal_fname, 0, 0);
11251         cli_posix_unlink(cli_posix, illegal_fname);
11252
11253         /*
11254          * Create a file with a long name and check that we got *no* short name.
11255          */
11256
11257         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11258                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11259                               0, 0, &fnum, NULL);
11260         if (!NT_STATUS_IS_OK(status)) {
11261                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11262                 return false;
11263         }
11264         cli_close(cli, fnum);
11265
11266         status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11267         if (!NT_STATUS_IS_OK(status)) {
11268                 d_printf("cli_list failed\n");
11269                 return false;
11270         }
11271
11272         cli_unlink(cli, fname, 0);
11273         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11274
11275         if (!torture_close_connection(cli_posix)) {
11276                 return false;
11277         }
11278
11279         if (!torture_close_connection(cli)) {
11280                 return false;
11281         }
11282
11283         return true;
11284 }
11285
11286 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11287 {
11288         size_t *to_pull = (size_t *)priv;
11289         size_t thistime = *to_pull;
11290
11291         thistime = MIN(thistime, n);
11292         if (thistime == 0) {
11293                 return 0;
11294         }
11295
11296         memset(buf, 0, thistime);
11297         *to_pull -= thistime;
11298         return thistime;
11299 }
11300
11301 static bool run_windows_write(int dummy)
11302 {
11303         struct cli_state *cli1;
11304         uint16_t fnum;
11305         int i;
11306         bool ret = false;
11307         const char *fname = "\\writetest.txt";
11308         struct timeval start_time;
11309         double seconds;
11310         double kbytes;
11311         NTSTATUS status;
11312
11313         printf("starting windows_write test\n");
11314         if (!torture_open_connection(&cli1, 0)) {
11315                 return False;
11316         }
11317
11318         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11319         if (!NT_STATUS_IS_OK(status)) {
11320                 printf("open failed (%s)\n", nt_errstr(status));
11321                 return False;
11322         }
11323
11324         smbXcli_conn_set_sockopt(cli1->conn, sockops);
11325
11326         start_time = timeval_current();
11327
11328         for (i=0; i<torture_numops; i++) {
11329                 uint8_t c = 0;
11330                 off_t start = i * torture_blocksize;
11331                 size_t to_pull = torture_blocksize - 1;
11332
11333                 status = cli_writeall(cli1, fnum, 0, &c,
11334                                       start + torture_blocksize - 1, 1, NULL);
11335                 if (!NT_STATUS_IS_OK(status)) {
11336                         printf("cli_write failed: %s\n", nt_errstr(status));
11337                         goto fail;
11338                 }
11339
11340                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11341                                   null_source, &to_pull);
11342                 if (!NT_STATUS_IS_OK(status)) {
11343                         printf("cli_push returned: %s\n", nt_errstr(status));
11344                         goto fail;
11345                 }
11346         }
11347
11348         seconds = timeval_elapsed(&start_time);
11349         kbytes = (double)torture_blocksize * torture_numops;
11350         kbytes /= 1024;
11351
11352         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11353                (double)seconds, (int)(kbytes/seconds));
11354
11355         ret = true;
11356  fail:
11357         cli_close(cli1, fnum);
11358         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11359         torture_close_connection(cli1);
11360         return ret;
11361 }
11362
11363 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11364 {
11365         size_t max_pdu = 0x1FFFF;
11366
11367         if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11368                 max_pdu = 0xFFFFFF;
11369         }
11370
11371         if (smb1cli_conn_signing_is_active(cli->conn)) {
11372                 max_pdu = 0x1FFFF;
11373         }
11374
11375         if (smb1cli_conn_encryption_on(cli->conn)) {
11376                 max_pdu = CLI_BUFFER_SIZE;
11377         }
11378
11379         if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11380                 len_requested &= 0xFFFF;
11381         }
11382
11383         return MIN(len_requested,
11384                    max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11385 }
11386
11387 static bool check_read_call(struct cli_state *cli,
11388                             uint16_t fnum,
11389                             uint8_t *buf,
11390                             size_t len_requested)
11391 {
11392         NTSTATUS status;
11393         struct tevent_req *subreq = NULL;
11394         ssize_t len_read = 0;
11395         size_t len_expected = 0;
11396         struct tevent_context *ev = NULL;
11397
11398         ev = samba_tevent_context_init(talloc_tos());
11399         if (ev == NULL) {
11400                 return false;
11401         }
11402
11403         subreq = cli_read_andx_send(talloc_tos(),
11404                                     ev,
11405                                     cli,
11406                                     fnum,
11407                                     0,
11408                                     len_requested);
11409
11410         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11411                 return false;
11412         }
11413
11414         status = cli_read_andx_recv(subreq, &len_read, &buf);
11415         if (!NT_STATUS_IS_OK(status)) {
11416                 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11417                 return false;
11418         }
11419
11420         TALLOC_FREE(subreq);
11421         TALLOC_FREE(ev);
11422
11423         len_expected = calc_expected_return(cli, len_requested);
11424
11425         if (len_expected > 0x10000 && len_read == 0x10000) {
11426                 /* Windows servers only return a max of 0x10000,
11427                    doesn't matter if you set CAP_LARGE_READX in
11428                    the client sessionsetupX call or not. */
11429                 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11430                         (unsigned int)len_requested);
11431         } else if (len_read != len_expected) {
11432                 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11433                         (unsigned int)len_requested,
11434                         (unsigned int)len_read,
11435                         (unsigned int)len_expected);
11436                 return false;
11437         } else {
11438                 d_printf("Correct read reply.\n");
11439         }
11440
11441         return true;
11442 }
11443
11444 /* Test large readX variants. */
11445 static bool large_readx_tests(struct cli_state *cli,
11446                                 uint16_t fnum,
11447                                 uint8_t *buf)
11448 {
11449         /* A read of 0xFFFF0001 should *always* return 1 byte. */
11450         if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11451                 return false;
11452         }
11453         /* A read of 0x10000 should return 0x10000 bytes. */
11454         if (check_read_call(cli, fnum, buf,    0x10000) == false) {
11455                 return false;
11456         }
11457         /* A read of 0x10000 should return 0x10001 bytes. */
11458         if (check_read_call(cli, fnum, buf,    0x10001) == false) {
11459                 return false;
11460         }
11461         /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11462            the requested number of bytes. */
11463         if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11464                 return false;
11465         }
11466         /* A read of 1MB should return 1MB bytes (on Samba). */
11467         if (check_read_call(cli, fnum, buf,   0x100000) == false) {
11468                 return false;
11469         }
11470
11471         if (check_read_call(cli, fnum, buf,    0x20001) == false) {
11472                 return false;
11473         }
11474         if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11475                 return false;
11476         }
11477         if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11478                 return false;
11479         }
11480         return true;
11481 }
11482
11483 static bool run_large_readx(int dummy)
11484 {
11485         uint8_t *buf = NULL;
11486         struct cli_state *cli1 = NULL;
11487         struct cli_state *cli2 = NULL;
11488         bool correct = false;
11489         const char *fname = "\\large_readx.dat";
11490         NTSTATUS status;
11491         uint16_t fnum1 = UINT16_MAX;
11492         uint32_t normal_caps = 0;
11493         size_t file_size = 20*1024*1024;
11494         TALLOC_CTX *frame = talloc_stackframe();
11495         size_t i;
11496         struct {
11497                 const char *name;
11498                 enum smb_signing_setting signing_setting;
11499                 enum protocol_types protocol;
11500         } runs[] = {
11501                 {
11502                         .name = "NT1",
11503                         .signing_setting = SMB_SIGNING_IF_REQUIRED,
11504                         .protocol = PROTOCOL_NT1,
11505                 },{
11506                         .name = "NT1 - SIGNING_REQUIRED",
11507                         .signing_setting = SMB_SIGNING_REQUIRED,
11508                         .protocol = PROTOCOL_NT1,
11509                 },
11510         };
11511
11512         printf("starting large_readx test\n");
11513
11514         if (!torture_open_connection(&cli1, 0)) {
11515                 goto out;
11516         }
11517
11518         normal_caps = smb1cli_conn_capabilities(cli1->conn);
11519
11520         if (!(normal_caps & CAP_LARGE_READX)) {
11521                 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11522                         (unsigned int)normal_caps);
11523                 goto out;
11524         }
11525
11526         /* Create a file of size 4MB. */
11527         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11528                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11529                         0, 0, &fnum1, NULL);
11530
11531         if (!NT_STATUS_IS_OK(status)) {
11532                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11533                 goto out;
11534         }
11535
11536         /* Write file_size bytes. */
11537         buf = talloc_zero_array(frame, uint8_t, file_size);
11538         if (buf == NULL) {
11539                 goto out;
11540         }
11541
11542         status = cli_writeall(cli1,
11543                               fnum1,
11544                               0,
11545                               buf,
11546                               0,
11547                               file_size,
11548                               NULL);
11549         if (!NT_STATUS_IS_OK(status)) {
11550                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11551                 goto out;
11552         }
11553
11554         status = cli_close(cli1, fnum1);
11555         if (!NT_STATUS_IS_OK(status)) {
11556                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11557                 goto out;
11558         }
11559
11560         fnum1 = UINT16_MAX;
11561
11562         for (i=0; i < ARRAY_SIZE(runs); i++) {
11563                 enum smb_signing_setting saved_signing_setting = signing_state;
11564                 uint16_t fnum2 = -1;
11565
11566                 if (do_encrypt &&
11567                     (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11568                 {
11569                         d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11570                         continue;
11571                 }
11572
11573                 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11574
11575                 signing_state = runs[i].signing_setting;
11576                 cli2 = open_nbt_connection();
11577                 signing_state = saved_signing_setting;
11578                 if (cli2 == NULL) {
11579                         goto out;
11580                 }
11581
11582                 status = smbXcli_negprot(cli2->conn,
11583                                          cli2->timeout,
11584                                          runs[i].protocol,
11585                                          runs[i].protocol,
11586                                          NULL,
11587                                          NULL,
11588                                          NULL);
11589                 if (!NT_STATUS_IS_OK(status)) {
11590                         goto out;
11591                 }
11592
11593                 status = cli_session_setup_creds(cli2, torture_creds);
11594                 if (!NT_STATUS_IS_OK(status)) {
11595                         goto out;
11596                 }
11597
11598                 status = cli_tree_connect(cli2,
11599                                         share,
11600                                         "?????",
11601                                         password);
11602                 if (!NT_STATUS_IS_OK(status)) {
11603                         goto out;
11604                 }
11605
11606                 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11607
11608                 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11609
11610                 if (!(normal_caps & CAP_LARGE_READX)) {
11611                         d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11612                                 (unsigned int)normal_caps);
11613                         goto out;
11614                 }
11615
11616                 if (do_encrypt) {
11617                         if (force_cli_encryption(cli2, share) == false) {
11618                                 goto out;
11619                         }
11620                 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11621                         uint16_t major, minor;
11622                         uint32_t caplow, caphigh;
11623
11624                         status = cli_unix_extensions_version(cli2,
11625                                                              &major, &minor,
11626                                                              &caplow, &caphigh);
11627                         if (!NT_STATUS_IS_OK(status)) {
11628                                 goto out;
11629                         }
11630                 }
11631
11632                 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11633                                 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11634                                 0, 0, &fnum2, NULL);
11635                 if (!NT_STATUS_IS_OK(status)) {
11636                         d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11637                         goto out;
11638                 }
11639
11640                 /* All reads must return less than file_size bytes. */
11641                 if (!large_readx_tests(cli2, fnum2, buf)) {
11642                         goto out;
11643                 }
11644
11645                 status = cli_close(cli2, fnum2);
11646                 if (!NT_STATUS_IS_OK(status)) {
11647                         d_printf("cli_close failed: %s\n", nt_errstr(status));
11648                         goto out;
11649                 }
11650                 fnum2 = -1;
11651
11652                 if (!torture_close_connection(cli2)) {
11653                         goto out;
11654                 }
11655                 cli2 = NULL;
11656         }
11657
11658         correct = true;
11659         printf("Success on large_readx test\n");
11660
11661   out:
11662
11663         if (cli2) {
11664                 if (!torture_close_connection(cli2)) {
11665                         correct = false;
11666                 }
11667         }
11668
11669         if (cli1) {
11670                 if (fnum1 != UINT16_MAX) {
11671                         status = cli_close(cli1, fnum1);
11672                         if (!NT_STATUS_IS_OK(status)) {
11673                                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11674                         }
11675                         fnum1 = UINT16_MAX;
11676                 }
11677
11678                 status = cli_unlink(cli1, fname,
11679                                     FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11680                 if (!NT_STATUS_IS_OK(status)) {
11681                         printf("unlink failed (%s)\n", nt_errstr(status));
11682                 }
11683
11684                 if (!torture_close_connection(cli1)) {
11685                         correct = false;
11686                 }
11687         }
11688
11689         TALLOC_FREE(frame);
11690
11691         printf("finished large_readx test\n");
11692         return correct;
11693 }
11694
11695 static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11696                                   const char *mask,
11697                                   void *private_data)
11698 {
11699         uint32_t *p_attr = (uint32_t *)private_data;
11700
11701         if (strequal(finfo->name, test_filename)) {
11702                 *p_attr = finfo->attr;
11703         }
11704
11705         return NT_STATUS_OK;
11706 }
11707
11708 static bool run_msdfs_attribute(int dummy)
11709 {
11710         static struct cli_state *cli;
11711         bool correct = false;
11712         uint32_t attr = 0;
11713         NTSTATUS status;
11714
11715         printf("Starting MSDFS-ATTRIBUTE test\n");
11716
11717         if (test_filename == NULL || test_filename[0] == '\0') {
11718                 printf("MSDFS-ATTRIBUTE test "
11719                         "needs -f filename-of-msdfs-link\n");
11720                 return false;
11721         }
11722
11723         /*
11724          * NB. We use torture_open_connection_flags() not
11725          * torture_open_connection() as the latter forces
11726          * SMB1.
11727          */
11728         if (!torture_open_connection_flags(&cli, 0, 0)) {
11729                 return false;
11730         }
11731
11732         smbXcli_conn_set_sockopt(cli->conn, sockops);
11733
11734         status = cli_list(cli,
11735                         "*",
11736                         FILE_ATTRIBUTE_DIRECTORY,
11737                         msdfs_attribute_list_fn,
11738                         &attr);
11739
11740         if (!NT_STATUS_IS_OK(status)) {
11741                 printf("cli_list failed with %s\n",
11742                         nt_errstr(status));
11743                 goto out;
11744         }
11745         if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11746                 printf("file %s should have "
11747                         "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11748                         test_filename,
11749                         (unsigned int)attr);
11750                 goto out;
11751         }
11752
11753         if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11754                 printf("file %s should have "
11755                         "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11756                         test_filename,
11757                         (unsigned int)attr);
11758                 goto out;
11759         }
11760
11761         correct = true;
11762
11763   out:
11764
11765         torture_close_connection(cli);
11766         return correct;
11767 }
11768
11769 static bool run_cli_echo(int dummy)
11770 {
11771         struct cli_state *cli;
11772         NTSTATUS status;
11773
11774         printf("starting cli_echo test\n");
11775         if (!torture_open_connection(&cli, 0)) {
11776                 return false;
11777         }
11778         smbXcli_conn_set_sockopt(cli->conn, sockops);
11779
11780         status = cli_echo(cli, 5, data_blob_const("hello", 5));
11781
11782         d_printf("cli_echo returned %s\n", nt_errstr(status));
11783
11784         torture_close_connection(cli);
11785         return NT_STATUS_IS_OK(status);
11786 }
11787
11788 static int splice_status(off_t written, void *priv)
11789 {
11790         return true;
11791 }
11792
11793 static bool run_cli_splice(int dummy)
11794 {
11795         uint8_t *buf = NULL;
11796         struct cli_state *cli1 = NULL;
11797         bool correct = false;
11798         const char *fname_src = "\\splice_src.dat";
11799         const char *fname_dst = "\\splice_dst.dat";
11800         NTSTATUS status;
11801         uint16_t fnum1 = UINT16_MAX;
11802         uint16_t fnum2 = UINT16_MAX;
11803         size_t file_size = 2*1024*1024;
11804         size_t splice_size = 1*1024*1024 + 713;
11805         uint8_t digest1[16], digest2[16];
11806         off_t written = 0;
11807         size_t nread = 0;
11808         TALLOC_CTX *frame = talloc_stackframe();
11809
11810         printf("starting cli_splice test\n");
11811
11812         if (!torture_open_connection(&cli1, 0)) {
11813                 goto out;
11814         }
11815
11816         cli_unlink(cli1, fname_src,
11817                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11818         cli_unlink(cli1, fname_dst,
11819                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11820
11821         /* Create a file */
11822         status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11823                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11824                         0, 0, &fnum1, NULL);
11825
11826         if (!NT_STATUS_IS_OK(status)) {
11827                 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11828                 goto out;
11829         }
11830
11831         /* Write file_size bytes - must be bigger than splice_size. */
11832         buf = talloc_zero_array(frame, uint8_t, file_size);
11833         if (buf == NULL) {
11834                 d_printf("talloc_fail\n");
11835                 goto out;
11836         }
11837
11838         /* Fill it with random numbers. */
11839         generate_random_buffer(buf, file_size);
11840
11841         /* MD5 the first 1MB + 713 bytes. */
11842         gnutls_hash_fast(GNUTLS_DIG_MD5,
11843                          buf,
11844                          splice_size,
11845                          digest1);
11846
11847         status = cli_writeall(cli1,
11848                               fnum1,
11849                               0,
11850                               buf,
11851                               0,
11852                               file_size,
11853                               NULL);
11854         if (!NT_STATUS_IS_OK(status)) {
11855                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11856                 goto out;
11857         }
11858
11859         status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11860                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11861                         0, 0, &fnum2, NULL);
11862
11863         if (!NT_STATUS_IS_OK(status)) {
11864                 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11865                 goto out;
11866         }
11867
11868         /* Now splice 1MB + 713 bytes. */
11869         status = cli_splice(cli1,
11870                                 cli1,
11871                                 fnum1,
11872                                 fnum2,
11873                                 splice_size,
11874                                 0,
11875                                 0,
11876                                 &written,
11877                                 splice_status,
11878                                 NULL);
11879
11880         if (!NT_STATUS_IS_OK(status)) {
11881                 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11882                 goto out;
11883         }
11884
11885         /* Clear the old buffer. */
11886         memset(buf, '\0', file_size);
11887
11888         /* Read the new file. */
11889         status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11890         if (!NT_STATUS_IS_OK(status)) {
11891                 d_printf("cli_read failed: %s\n", nt_errstr(status));
11892                 goto out;
11893         }
11894         if (nread != splice_size) {
11895                 d_printf("bad read of 0x%x, should be 0x%x\n",
11896                         (unsigned int)nread,
11897                         (unsigned int)splice_size);
11898                 goto out;
11899         }
11900
11901         /* MD5 the first 1MB + 713 bytes. */
11902         gnutls_hash_fast(GNUTLS_DIG_MD5,
11903                          buf,
11904                          splice_size,
11905                          digest2);
11906
11907         /* Must be the same. */
11908         if (memcmp(digest1, digest2, 16) != 0) {
11909                 d_printf("bad MD5 compare\n");
11910                 goto out;
11911         }
11912
11913         correct = true;
11914         printf("Success on cli_splice test\n");
11915
11916   out:
11917
11918         if (cli1) {
11919                 if (fnum1 != UINT16_MAX) {
11920                         cli_close(cli1, fnum1);
11921                 }
11922                 if (fnum2 != UINT16_MAX) {
11923                         cli_close(cli1, fnum2);
11924                 }
11925
11926                 cli_unlink(cli1, fname_src,
11927                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11928                 cli_unlink(cli1, fname_dst,
11929                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11930
11931                 if (!torture_close_connection(cli1)) {
11932                         correct = false;
11933                 }
11934         }
11935
11936         TALLOC_FREE(frame);
11937         return correct;
11938 }
11939
11940 static bool run_uid_regression_test(int dummy)
11941 {
11942         static struct cli_state *cli;
11943         int16_t old_vuid;
11944         int32_t old_cnum;
11945         bool correct = True;
11946         struct smbXcli_tcon *tcon_copy = NULL;
11947         NTSTATUS status;
11948
11949         printf("starting uid regression test\n");
11950
11951         if (!torture_open_connection(&cli, 0)) {
11952                 return False;
11953         }
11954
11955         smbXcli_conn_set_sockopt(cli->conn, sockops);
11956
11957         /* Ok - now save then logoff our current user. */
11958         old_vuid = cli_state_get_uid(cli);
11959
11960         status = cli_ulogoff(cli);
11961         if (!NT_STATUS_IS_OK(status)) {
11962                 d_printf("(%s) cli_ulogoff failed: %s\n",
11963                          __location__, nt_errstr(status));
11964                 correct = false;
11965                 goto out;
11966         }
11967
11968         cli_state_set_uid(cli, old_vuid);
11969
11970         /* Try an operation. */
11971         status = cli_mkdir(cli, "\\uid_reg_test");
11972         if (NT_STATUS_IS_OK(status)) {
11973                 d_printf("(%s) cli_mkdir succeeded\n",
11974                          __location__);
11975                 correct = false;
11976                 goto out;
11977         } else {
11978                 /* Should be bad uid. */
11979                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11980                                  NT_STATUS_USER_SESSION_DELETED)) {
11981                         correct = false;
11982                         goto out;
11983                 }
11984         }
11985
11986         old_cnum = cli_state_get_tid(cli);
11987         /*
11988          * This is an SMB1-only test.
11989          * Copy the tcon, not "save/restore".
11990          *
11991          * In SMB1 the cli_tdis() below frees
11992          * cli->smb1.tcon so we need a copy
11993          * of the struct to put back for the
11994          * second tdis call with invalid vuid.
11995          *
11996          * This is a test-only hack. Real client code
11997          * uses cli_state_save_tcon_share()/cli_state_restore_tcon_share().
11998          */
11999         tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
12000         if (tcon_copy == NULL) {
12001                 correct = false;
12002                 goto out;
12003         }
12004
12005         /* Now try a SMBtdis with the invalid vuid set to zero. */
12006         cli_state_set_uid(cli, 0);
12007
12008         /* This should succeed. */
12009         status = cli_tdis(cli);
12010
12011         if (NT_STATUS_IS_OK(status)) {
12012                 d_printf("First tdis with invalid vuid should succeed.\n");
12013         } else {
12014                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
12015                 correct = false;
12016                 cli->smb1.tcon = tcon_copy;
12017                 goto out;
12018         }
12019
12020         cli->smb1.tcon = tcon_copy;
12021         cli_state_set_uid(cli, old_vuid);
12022         cli_state_set_tid(cli, old_cnum);
12023
12024         /* This should fail. */
12025         status = cli_tdis(cli);
12026         if (NT_STATUS_IS_OK(status)) {
12027                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
12028                 correct = false;
12029                 goto out;
12030         } else {
12031                 /* Should be bad tid. */
12032                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
12033                                 NT_STATUS_NETWORK_NAME_DELETED)) {
12034                         correct = false;
12035                         goto out;
12036                 }
12037         }
12038
12039         cli_rmdir(cli, "\\uid_reg_test");
12040
12041   out:
12042
12043         cli_shutdown(cli);
12044         return correct;
12045 }
12046
12047
12048 static const char *illegal_chars = "*\\/?<>|\":";
12049 static char force_shortname_chars[] = " +,.[];=\177";
12050
12051 static NTSTATUS shortname_del_fn(struct file_info *finfo,
12052                              const char *mask, void *state)
12053 {
12054         struct cli_state *pcli = (struct cli_state *)state;
12055         fstring fname;
12056         NTSTATUS status = NT_STATUS_OK;
12057
12058         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
12059
12060         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
12061                 return NT_STATUS_OK;
12062
12063         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
12064                 status = cli_rmdir(pcli, fname);
12065                 if (!NT_STATUS_IS_OK(status)) {
12066                         printf("del_fn: failed to rmdir %s\n,", fname );
12067                 }
12068         } else {
12069                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12070                 if (!NT_STATUS_IS_OK(status)) {
12071                         printf("del_fn: failed to unlink %s\n,", fname );
12072                 }
12073         }
12074         return status;
12075 }
12076
12077 struct sn_state {
12078         int matched;
12079         int i;
12080         bool val;
12081 };
12082
12083 static NTSTATUS shortname_list_fn(struct file_info *finfo,
12084                               const char *name, void *state)
12085 {
12086         struct sn_state *s = (struct sn_state  *)state;
12087         int i = s->i;
12088
12089 #if 0
12090         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
12091                 i, finfo->name, finfo->short_name);
12092 #endif
12093
12094         if (strchr(force_shortname_chars, i)) {
12095                 if (!finfo->short_name) {
12096                         /* Shortname not created when it should be. */
12097                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
12098                                 __location__, finfo->name, i);
12099                         s->val = true;
12100                 }
12101         } else if (finfo->short_name){
12102                 /* Shortname created when it should not be. */
12103                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
12104                         __location__, finfo->short_name, finfo->name);
12105                 s->val = true;
12106         }
12107         s->matched += 1;
12108         return NT_STATUS_OK;
12109 }
12110
12111 static bool run_shortname_test(int dummy)
12112 {
12113         static struct cli_state *cli;
12114         bool correct = True;
12115         int i;
12116         struct sn_state s;
12117         char fname[40];
12118         NTSTATUS status;
12119
12120         printf("starting shortname test\n");
12121
12122         if (!torture_open_connection(&cli, 0)) {
12123                 return False;
12124         }
12125
12126         smbXcli_conn_set_sockopt(cli->conn, sockops);
12127
12128         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12129         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12130         cli_rmdir(cli, "\\shortname");
12131
12132         status = cli_mkdir(cli, "\\shortname");
12133         if (!NT_STATUS_IS_OK(status)) {
12134                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
12135                         __location__, nt_errstr(status));
12136                 correct = false;
12137                 goto out;
12138         }
12139
12140         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
12141                 correct = false;
12142                 goto out;
12143         }
12144         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
12145                 correct = false;
12146                 goto out;
12147         }
12148
12149         s.val = false;
12150
12151         for (i = 32; i < 128; i++) {
12152                 uint16_t fnum = (uint16_t)-1;
12153
12154                 s.i = i;
12155
12156                 if (strchr(illegal_chars, i)) {
12157                         continue;
12158                 }
12159                 fname[15] = i;
12160
12161                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12162                                    FILE_SHARE_READ|FILE_SHARE_WRITE,
12163                                    FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12164                 if (!NT_STATUS_IS_OK(status)) {
12165                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
12166                                 __location__, fname, nt_errstr(status));
12167                         correct = false;
12168                         goto out;
12169                 }
12170                 cli_close(cli, fnum);
12171
12172                 s.matched = 0;
12173                 status = cli_list(cli, "\\shortname\\test*.*", 0,
12174                                   shortname_list_fn, &s);
12175                 if (s.matched != 1) {
12176                         d_printf("(%s) failed to list %s: %s\n",
12177                                 __location__, fname, nt_errstr(status));
12178                         correct = false;
12179                         goto out;
12180                 }
12181
12182                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12183                 if (!NT_STATUS_IS_OK(status)) {
12184                         d_printf("(%s) failed to delete %s: %s\n",
12185                                 __location__, fname, nt_errstr(status));
12186                         correct = false;
12187                         goto out;
12188                 }
12189
12190                 if (s.val) {
12191                         correct = false;
12192                         goto out;
12193                 }
12194         }
12195
12196   out:
12197
12198         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12199         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12200         cli_rmdir(cli, "\\shortname");
12201         torture_close_connection(cli);
12202         return correct;
12203 }
12204
12205 TLDAPRC callback_code;
12206
12207 static void pagedsearch_cb(struct tevent_req *req)
12208 {
12209         TLDAPRC rc;
12210         struct tldap_message *msg;
12211         char *dn;
12212
12213         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12214         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12215                 d_printf("tldap_search_paged_recv failed: %s\n",
12216                          tldap_rc2string(rc));
12217                 callback_code = rc;
12218                 return;
12219         }
12220         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12221                 TALLOC_FREE(msg);
12222                 return;
12223         }
12224         if (!tldap_entry_dn(msg, &dn)) {
12225                 d_printf("tldap_entry_dn failed\n");
12226                 return;
12227         }
12228         d_printf("%s\n", dn);
12229         TALLOC_FREE(msg);
12230 }
12231
12232 enum tldap_extended_val {
12233         EXTENDED_ZERO = 0,
12234         EXTENDED_ONE = 1,
12235         EXTENDED_NONE = 2,
12236 };
12237
12238 /*
12239  * Construct an extended dn control with either no value, 0 or 1
12240  *
12241  * No value and 0 are equivalent (non-hyphenated GUID)
12242  * 1 has the hyphenated GUID
12243  */
12244 static struct tldap_control *
12245 tldap_build_extended_control(enum tldap_extended_val val)
12246 {
12247         struct tldap_control empty_control;
12248         struct asn1_data *data;
12249
12250         ZERO_STRUCT(empty_control);
12251
12252         if (val != EXTENDED_NONE) {
12253                 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12254
12255                 if (!data) {
12256                         return NULL;
12257                 }
12258
12259                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12260                         return NULL;
12261                 }
12262
12263                 if (!asn1_write_Integer(data, (int)val)) {
12264                         return NULL;
12265                 }
12266
12267                 if (!asn1_pop_tag(data)) {
12268                         return NULL;
12269                 }
12270
12271                 if (!asn1_blob(data, &empty_control.value)) {
12272                         return NULL;
12273                 }
12274         }
12275
12276         empty_control.oid = "1.2.840.113556.1.4.529";
12277         empty_control.critical = true;
12278
12279         return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12280
12281 }
12282
12283 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12284                                       enum tldap_extended_val control_val)
12285 {
12286         struct tldap_control *control = tldap_build_extended_control(control_val);
12287         char *dn = NULL;
12288         struct tldap_message **msg;
12289         TLDAPRC rc;
12290
12291         rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12292                           "(objectClass=*)", NULL, 0, 0,
12293                           control, 1, NULL,
12294                           0, 0, 0, 0, talloc_tos(), &msg);
12295         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12296                 d_printf("tldap_search for domain DN failed: %s\n",
12297                          tldap_errstr(talloc_tos(), ld, rc));
12298                 return false;
12299         }
12300
12301         if (!tldap_entry_dn(msg[0], &dn)) {
12302                 d_printf("tldap_search domain DN fetch failed: %s\n",
12303                          tldap_errstr(talloc_tos(), ld, rc));
12304                 return false;
12305         }
12306
12307         d_printf("%s\n", dn);
12308         {
12309                 uint32_t time_low;
12310                 uint32_t time_mid, time_hi_and_version;
12311                 uint32_t clock_seq[2];
12312                 uint32_t node[6];
12313                 char next;
12314
12315                 switch (control_val) {
12316                 case EXTENDED_NONE:
12317                 case EXTENDED_ZERO:
12318                         /*
12319                          * When reading GUIDs with hyphens, scanf will treat
12320                          * hyphen as a hex character (and counts as part of the
12321                          * width). This creates leftover GUID string which we
12322                          * check will for with 'next' and closing '>'.
12323                          */
12324                         if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12325                                          &time_low, &time_mid,
12326                                          &time_hi_and_version, &clock_seq[0],
12327                                          &clock_seq[1], &node[0], &node[1],
12328                                          &node[2], &node[3], &node[4],
12329                                          &node[5], &next)) {
12330                                 /* This GUID is good */
12331                         } else {
12332                                 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12333                                 return false;
12334                         }
12335
12336                         break;
12337                 case EXTENDED_ONE:
12338                         if (12 == sscanf(dn,
12339                                          "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12340                                          &time_low, &time_mid,
12341                                          &time_hi_and_version, &clock_seq[0],
12342                                          &clock_seq[1], &node[0], &node[1],
12343                                          &node[2], &node[3], &node[4],
12344                                          &node[5], &next)) {
12345                                 /* This GUID is good */
12346                         } else {
12347                                 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12348                                 return false;
12349                         }
12350
12351                         break;
12352                 default:
12353                         return false;
12354                 }
12355         }
12356
12357         return true;
12358 }
12359
12360 static bool run_tldap(int dummy)
12361 {
12362         struct tldap_context *ld;
12363         int fd;
12364         TLDAPRC rc;
12365         NTSTATUS status;
12366         struct sockaddr_storage addr;
12367         struct tevent_context *ev;
12368         struct tevent_req *req;
12369         char *basedn;
12370         const char *filter;
12371         struct loadparm_context *lp_ctx = NULL;
12372         int tcp_port = 389;
12373         bool use_tls = false;
12374         bool use_starttls = false;
12375         int wrap_flags = -1;
12376         uint32_t gensec_features = 0;
12377
12378         lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
12379
12380         wrap_flags = lpcfg_client_ldap_sasl_wrapping(lp_ctx);
12381
12382         if (wrap_flags & ADS_AUTH_SASL_LDAPS) {
12383                 use_tls = true;
12384                 tcp_port = 636;
12385         } else if (wrap_flags & ADS_AUTH_SASL_STARTTLS) {
12386                 use_tls = true;
12387                 use_starttls = true;
12388         }
12389         if (wrap_flags & ADS_AUTH_SASL_SEAL) {
12390                 gensec_features |= GENSEC_FEATURE_SEAL;
12391         }
12392         if (wrap_flags & ADS_AUTH_SASL_SIGN) {
12393                 gensec_features |= GENSEC_FEATURE_SIGN;
12394         }
12395
12396         if (gensec_features != 0) {
12397                 gensec_features |= GENSEC_FEATURE_LDAP_STYLE;
12398         }
12399
12400         if (!resolve_name(host, &addr, 0, false)) {
12401                 d_printf("could not find host %s\n", host);
12402                 return false;
12403         }
12404         status = open_socket_out(&addr, tcp_port, 9999, &fd);
12405         if (!NT_STATUS_IS_OK(status)) {
12406                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12407                 return false;
12408         }
12409
12410         ld = tldap_context_create(talloc_tos(), fd);
12411         if (ld == NULL) {
12412                 close(fd);
12413                 d_printf("tldap_context_create failed\n");
12414                 return false;
12415         }
12416
12417         if (use_tls && !tldap_has_tls_tstream(ld)) {
12418                 tldap_set_starttls_needed(ld, use_starttls);
12419
12420                 rc = tldap_tls_connect(ld, lp_ctx, host);
12421                 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12422                         DBG_ERR("tldap_tls_connect(%s) failed: %s\n",
12423                                 host, tldap_errstr(talloc_tos(), ld, rc));
12424                         return false;
12425                 }
12426         }
12427
12428         rc = tldap_fetch_rootdse(ld);
12429         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12430                 d_printf("tldap_fetch_rootdse failed: %s\n",
12431                          tldap_errstr(talloc_tos(), ld, rc));
12432                 return false;
12433         }
12434
12435         basedn = tldap_talloc_single_attribute(
12436                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12437         if (basedn == NULL) {
12438                 d_printf("no defaultNamingContext\n");
12439                 return false;
12440         }
12441         d_printf("defaultNamingContext: %s\n", basedn);
12442
12443         ev = samba_tevent_context_init(talloc_tos());
12444         if (ev == NULL) {
12445                 d_printf("tevent_context_init failed\n");
12446                 return false;
12447         }
12448
12449         rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12450                                lp_ctx, gensec_features);
12451         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12452                 d_printf("tldap_gensec_bind failed\n");
12453                 return false;
12454         }
12455
12456         callback_code = TLDAP_SUCCESS;
12457
12458         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12459                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
12460                                       NULL, 0, 0,
12461                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
12462         if (req == NULL) {
12463                 d_printf("tldap_search_paged_send failed\n");
12464                 return false;
12465         }
12466         tevent_req_set_callback(req, pagedsearch_cb, NULL);
12467
12468         tevent_req_poll(req, ev);
12469
12470         TALLOC_FREE(req);
12471
12472         rc = callback_code;
12473
12474         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12475                 d_printf("tldap_search with paging failed: %s\n",
12476                          tldap_errstr(talloc_tos(), ld, rc));
12477                 return false;
12478         }
12479
12480         /* test search filters against rootDSE */
12481         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12482                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12483
12484         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12485                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12486                           talloc_tos(), NULL);
12487         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12488                 d_printf("tldap_search with complex filter failed: %s\n",
12489                          tldap_errstr(talloc_tos(), ld, rc));
12490                 return false;
12491         }
12492
12493         /*
12494          * Tests to check for regression of:
12495          *
12496          * https://bugzilla.samba.org/show_bug.cgi?id=14029
12497          *
12498          * TLDAP used here to pick apart the original string DN (with GUID)
12499          */
12500         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12501                 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12502                          tldap_errstr(talloc_tos(), ld, rc));
12503                 return false;
12504         }
12505         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12506                 d_printf("tldap_search with extended dn (0) failed: %s\n",
12507                          tldap_errstr(talloc_tos(), ld, rc));
12508                 return false;
12509         }
12510         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12511                 d_printf("tldap_search with extended dn (1) failed: %s\n",
12512                          tldap_errstr(talloc_tos(), ld, rc));
12513                 return false;
12514         }
12515
12516         TALLOC_FREE(ld);
12517         return true;
12518 }
12519
12520 /* Torture test to ensure no regression of :
12521 https://bugzilla.samba.org/show_bug.cgi?id=7084
12522 */
12523
12524 static bool run_dir_createtime(int dummy)
12525 {
12526         struct cli_state *cli;
12527         const char *dname = "\\testdir_createtime";
12528         const char *fname = "\\testdir_createtime\\testfile";
12529         NTSTATUS status;
12530         struct timespec create_time;
12531         struct timespec create_time1;
12532         uint16_t fnum;
12533         bool ret = false;
12534         uint64_t ino;
12535
12536         if (!torture_open_connection(&cli, 0)) {
12537                 return false;
12538         }
12539
12540         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12541                 /* Ensure ino is zero, SMB2 gets a real one. */
12542                 ino = 0;
12543         } else {
12544                 /* Ensure ino is -1, SMB1 never gets a real one. */
12545                 ino = (uint64_t)-1;
12546         }
12547
12548         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12549         cli_rmdir(cli, dname);
12550
12551         status = cli_mkdir(cli, dname);
12552         if (!NT_STATUS_IS_OK(status)) {
12553                 printf("mkdir failed: %s\n", nt_errstr(status));
12554                 goto out;
12555         }
12556
12557         status = cli_qpathinfo2(cli,
12558                                 dname,
12559                                 &create_time,
12560                                 NULL,
12561                                 NULL,
12562                                 NULL,
12563                                 NULL,
12564                                 NULL,
12565                                 &ino,
12566                                 NULL);
12567         if (!NT_STATUS_IS_OK(status)) {
12568                 printf("cli_qpathinfo2 returned %s\n",
12569                        nt_errstr(status));
12570                 goto out;
12571         }
12572
12573         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12574                 /* SMB2 should always return an inode. */
12575                 if (ino == 0) {
12576                         printf("SMB2 bad inode (0)\n");
12577                         goto out;
12578                 }
12579         } else {
12580                 /* SMB1 must always return zero here. */
12581                 if (ino != 0) {
12582                         printf("SMB1 bad inode (!0)\n");
12583                         goto out;
12584                 }
12585         }
12586
12587         /* Sleep 3 seconds, then create a file. */
12588         sleep(3);
12589
12590         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12591                          DENY_NONE, &fnum);
12592         if (!NT_STATUS_IS_OK(status)) {
12593                 printf("cli_openx failed: %s\n", nt_errstr(status));
12594                 goto out;
12595         }
12596
12597         status = cli_qpathinfo2(cli,
12598                                 dname,
12599                                 &create_time1,
12600                                 NULL,
12601                                 NULL,
12602                                 NULL,
12603                                 NULL,
12604                                 NULL,
12605                                 NULL,
12606                                 NULL);
12607         if (!NT_STATUS_IS_OK(status)) {
12608                 printf("cli_qpathinfo2 (2) returned %s\n",
12609                        nt_errstr(status));
12610                 goto out;
12611         }
12612
12613         if (timespec_compare(&create_time1, &create_time)) {
12614                 printf("run_dir_createtime: create time was updated (error)\n");
12615         } else {
12616                 printf("run_dir_createtime: create time was not updated (correct)\n");
12617                 ret = true;
12618         }
12619
12620   out:
12621
12622         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12623         cli_rmdir(cli, dname);
12624         if (!torture_close_connection(cli)) {
12625                 ret = false;
12626         }
12627         return ret;
12628 }
12629
12630
12631 static bool run_streamerror(int dummy)
12632 {
12633         struct cli_state *cli;
12634         const char *dname = "\\testdir_streamerror";
12635         const char *streamname =
12636                 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12637         NTSTATUS status;
12638         time_t change_time, access_time, write_time;
12639         off_t size;
12640         uint16_t fnum;
12641         uint32_t attr;
12642         bool ret = true;
12643
12644         if (!torture_open_connection(&cli, 0)) {
12645                 return false;
12646         }
12647
12648         torture_deltree(cli, dname);
12649
12650         status = cli_mkdir(cli, dname);
12651         if (!NT_STATUS_IS_OK(status)) {
12652                 printf("mkdir failed: %s\n", nt_errstr(status));
12653                 return false;
12654         }
12655
12656         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12657                                 &write_time, &size, &attr);
12658         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12659                 printf("pathinfo returned %s, expected "
12660                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12661                        nt_errstr(status));
12662                 ret = false;
12663         }
12664
12665         status = cli_ntcreate(cli, streamname, 0x16,
12666                               FILE_READ_DATA|FILE_READ_EA|
12667                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12668                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12669                               FILE_OPEN, 0, 0, &fnum, NULL);
12670
12671         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12672                 printf("ntcreate returned %s, expected "
12673                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12674                        nt_errstr(status));
12675                 ret = false;
12676         }
12677
12678
12679         cli_rmdir(cli, dname);
12680         return ret;
12681 }
12682
12683 struct pidtest_state {
12684         bool success;
12685         uint16_t vwv[1];
12686         DATA_BLOB data;
12687 };
12688
12689 static void pid_echo_done(struct tevent_req *subreq);
12690
12691 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12692                         struct tevent_context *ev,
12693                         struct cli_state *cli)
12694 {
12695         struct tevent_req *req, *subreq;
12696         struct pidtest_state *state;
12697
12698         req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12699         if (req == NULL) {
12700                 return NULL;
12701         }
12702
12703         SSVAL(state->vwv, 0, 1);
12704         state->data = data_blob_const("hello", 5);
12705
12706         subreq = smb1cli_req_send(state,
12707                                 ev,
12708                                 cli->conn,
12709                                 SMBecho,
12710                                 0, 0, /* *_flags */
12711                                 0, 0, /* *_flags2 */
12712                                 cli->timeout,
12713                                 0xDEADBEEF, /* pid */
12714                                 NULL, /* tcon */
12715                                 NULL, /* session */
12716                                 ARRAY_SIZE(state->vwv), state->vwv,
12717                                 state->data.length, state->data.data);
12718
12719         if (tevent_req_nomem(subreq, req)) {
12720                 return tevent_req_post(req, ev);
12721         }
12722         tevent_req_set_callback(subreq, pid_echo_done, req);
12723         return req;
12724 }
12725
12726 static void pid_echo_done(struct tevent_req *subreq)
12727 {
12728         struct tevent_req *req = tevent_req_callback_data(
12729                 subreq, struct tevent_req);
12730         struct pidtest_state *state = tevent_req_data(
12731                 req, struct pidtest_state);
12732         NTSTATUS status;
12733         uint32_t num_bytes;
12734         uint8_t *bytes = NULL;
12735         struct iovec *recv_iov = NULL;
12736         uint8_t *phdr = NULL;
12737         uint16_t pidlow = 0;
12738         uint16_t pidhigh = 0;
12739         struct smb1cli_req_expected_response expected[] = {
12740         {
12741                 .status = NT_STATUS_OK,
12742                 .wct    = 1,
12743         },
12744         };
12745
12746         status = smb1cli_req_recv(subreq, state,
12747                                 &recv_iov,
12748                                 &phdr,
12749                                 NULL, /* pwct */
12750                                 NULL, /* pvwv */
12751                                 NULL, /* pvwv_offset */
12752                                 &num_bytes,
12753                                 &bytes,
12754                                 NULL, /* pbytes_offset */
12755                                 NULL, /* pinbuf */
12756                                 expected, ARRAY_SIZE(expected));
12757
12758         TALLOC_FREE(subreq);
12759
12760         if (!NT_STATUS_IS_OK(status)) {
12761                 tevent_req_nterror(req, status);
12762                 return;
12763         }
12764
12765         if (num_bytes != state->data.length) {
12766                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12767                 return;
12768         }
12769
12770         if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12771                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12772                 return;
12773         }
12774
12775         /* Check pid low/high == DEADBEEF */
12776         pidlow = SVAL(phdr, HDR_PID);
12777         if (pidlow != 0xBEEF){
12778                 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12779                         (unsigned int)pidlow);
12780                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12781                 return;
12782         }
12783         pidhigh = SVAL(phdr, HDR_PIDHIGH);
12784         if (pidhigh != 0xDEAD){
12785                 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12786                         (unsigned int)pidhigh);
12787                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12788                 return;
12789         }
12790
12791         tevent_req_done(req);
12792 }
12793
12794 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12795 {
12796         return tevent_req_simple_recv_ntstatus(req);
12797 }
12798
12799 static bool run_pidhigh(int dummy)
12800 {
12801         bool success = false;
12802         struct cli_state *cli = NULL;
12803         NTSTATUS status;
12804         struct tevent_context *ev = NULL;
12805         struct tevent_req *req = NULL;
12806         TALLOC_CTX *frame = talloc_stackframe();
12807
12808         printf("starting pid high test\n");
12809         if (!torture_open_connection(&cli, 0)) {
12810                 return false;
12811         }
12812         smbXcli_conn_set_sockopt(cli->conn, sockops);
12813
12814         ev = samba_tevent_context_init(frame);
12815         if (ev == NULL) {
12816                 goto fail;
12817         }
12818
12819         req = pid_echo_send(frame, ev, cli);
12820         if (req == NULL) {
12821                 goto fail;
12822         }
12823
12824         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12825                 goto fail;
12826         }
12827
12828         status = pid_echo_recv(req);
12829         if (NT_STATUS_IS_OK(status)) {
12830                 printf("pid high test ok\n");
12831                 success = true;
12832         }
12833
12834  fail:
12835
12836         TALLOC_FREE(frame);
12837         torture_close_connection(cli);
12838         return success;
12839 }
12840
12841 /*
12842   Test Windows open on a bad POSIX symlink.
12843  */
12844 static bool run_symlink_open_test(int dummy)
12845 {
12846         static struct cli_state *cli;
12847         const char *fname = "non_existant_file";
12848         const char *sname = "dangling_symlink";
12849         uint16_t fnum = (uint16_t)-1;
12850         bool correct = false;
12851         NTSTATUS status;
12852         TALLOC_CTX *frame = NULL;
12853
12854         frame = talloc_stackframe();
12855
12856         printf("Starting Windows bad symlink open test\n");
12857
12858         if (!torture_open_connection(&cli, 0)) {
12859                 TALLOC_FREE(frame);
12860                 return false;
12861         }
12862
12863         smbXcli_conn_set_sockopt(cli->conn, sockops);
12864
12865         status = torture_setup_unix_extensions(cli);
12866         if (!NT_STATUS_IS_OK(status)) {
12867                 TALLOC_FREE(frame);
12868                 return false;
12869         }
12870
12871         /* Ensure nothing exists. */
12872         cli_setatr(cli, fname, 0, 0);
12873         cli_posix_unlink(cli, fname);
12874         cli_setatr(cli, sname, 0, 0);
12875         cli_posix_unlink(cli, sname);
12876
12877         /* Create a symlink pointing nowhere. */
12878         status = cli_posix_symlink(cli, fname, sname);
12879         if (!NT_STATUS_IS_OK(status)) {
12880                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12881                         sname,
12882                         fname,
12883                         nt_errstr(status));
12884                 goto out;
12885         }
12886
12887         /* Now ensure that a Windows open doesn't hang. */
12888         status = cli_ntcreate(cli,
12889                         sname,
12890                         0,
12891                         FILE_READ_DATA|FILE_WRITE_DATA,
12892                         0,
12893                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12894                         FILE_OPEN_IF,
12895                         0x0,
12896                         0x0,
12897                         &fnum,
12898                         NULL);
12899
12900         /*
12901          * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12902          * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12903          * we use O_NOFOLLOW on the server or not.
12904          */
12905         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12906             NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12907         {
12908                 correct = true;
12909         } else {
12910                 printf("cli_ntcreate of %s returned %s - should return"
12911                                 " either (%s) or (%s)\n",
12912                         sname,
12913                         nt_errstr(status),
12914                         nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12915                         nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12916                 goto out;
12917         }
12918
12919         correct = true;
12920
12921   out:
12922
12923         if (fnum != (uint16_t)-1) {
12924                 cli_close(cli, fnum);
12925                 fnum = (uint16_t)-1;
12926         }
12927
12928         cli_setatr(cli, sname, 0, 0);
12929         cli_posix_unlink(cli, sname);
12930         cli_setatr(cli, fname, 0, 0);
12931         cli_posix_unlink(cli, fname);
12932
12933         if (!torture_close_connection(cli)) {
12934                 correct = false;
12935         }
12936
12937         TALLOC_FREE(frame);
12938         return correct;
12939 }
12940
12941 static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12942                                         const char *name,
12943                                         void *state)
12944 {
12945         char **mangled_name_return = (char **)state;
12946         bool is_mangled = strchr(finfo->name, '~');
12947
12948         if (is_mangled) {
12949                 *mangled_name_return = talloc_strdup(NULL, finfo->name);
12950                 if (*mangled_name_return == NULL) {
12951                         return NT_STATUS_NO_MEMORY;
12952                 }
12953         }
12954         return NT_STATUS_OK;
12955 }
12956
12957 static bool run_smb1_wild_mangle_unlink_test(int dummy)
12958 {
12959         static struct cli_state *cli_posix = NULL;
12960         static struct cli_state *cli = NULL;
12961         uint16_t fnum = (uint16_t)-1;
12962         bool correct = false;
12963         const char *dname = "smb1_wild_mangle_unlink";
12964         const char *aname = "smb1_wild_mangle_unlink/a";
12965         const char *star_name = "smb1_wild_mangle_unlink/*";
12966         char *windows_unlink_name = NULL;
12967         char *mangled_name = NULL;
12968         NTSTATUS status;
12969
12970         printf("Starting SMB1 wild mangle unlink test\n");
12971
12972         /* Open a Windows connection. */
12973         if (!torture_open_connection(&cli, 0)) {
12974                 return false;
12975         }
12976
12977         smbXcli_conn_set_sockopt(cli->conn, sockops);
12978
12979         /* Open a POSIX connection. */
12980         if (!torture_open_connection(&cli_posix, 0)) {
12981                 goto out;
12982         }
12983
12984         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12985
12986         status = torture_setup_unix_extensions(cli_posix);
12987         if (!NT_STATUS_IS_OK(status)) {
12988                 printf("server doesn't support POSIX\n");
12989                 goto out;
12990         }
12991
12992         /* Start fresh. */
12993         torture_deltree(cli, dname);
12994
12995         /*
12996          * Create two files - 'a' and '*'.
12997          * We need POSIX extensions for this as '*'
12998          * is not a valid Windows name.
12999          */
13000
13001         status = cli_mkdir(cli, dname);
13002         if (!NT_STATUS_IS_OK(status)) {
13003                 printf("cli_mkdir of %s returned %s\n",
13004                         dname,
13005                         nt_errstr(status));
13006                 goto out;
13007         }
13008
13009         status = cli_posix_open(cli_posix,
13010                                 aname,
13011                                 O_RDWR|O_CREAT|O_EXCL,
13012                                 0660,
13013                                 &fnum);
13014         if (!NT_STATUS_IS_OK(status)) {
13015                 printf("cli_posix_open (create) of %s returned %s\n",
13016                         aname,
13017                         nt_errstr(status));
13018                 goto out;
13019         }
13020         status = cli_close(cli_posix, fnum);
13021         if (!NT_STATUS_IS_OK(status)) {
13022                 goto out;
13023         }
13024         status = cli_posix_open(cli_posix,
13025                                 star_name,
13026                                 O_RDWR|O_CREAT|O_EXCL,
13027                                 0660,
13028                                 &fnum);
13029         if (!NT_STATUS_IS_OK(status)) {
13030                 printf("cli_posix_open (create) of %s returned %s\n",
13031                         star_name,
13032                         nt_errstr(status));
13033                 goto out;
13034         }
13035         status = cli_close(cli_posix, fnum);
13036         if (!NT_STATUS_IS_OK(status)) {
13037                 goto out;
13038         }
13039
13040         status = cli_list(cli,
13041                         star_name,
13042                         0,
13043                         smb1_wild_mangle_list_fn,
13044                         &mangled_name);
13045         if (!NT_STATUS_IS_OK(status)) {
13046                 printf("cli_list of %s returned %s\n",
13047                         star_name,
13048                         nt_errstr(status));
13049                 goto out;
13050         }
13051
13052         if (mangled_name == NULL) {
13053                 goto out;
13054         }
13055
13056         printf("mangled_name = %s\n",
13057                 mangled_name);
13058
13059         /*
13060          * Try a Windows unlink with the mangled name.
13061          * This should *NOT* unlink the 'a' name.
13062          */
13063
13064         windows_unlink_name = talloc_asprintf(cli_posix,
13065                                         "%s\\%s",
13066                                         dname,
13067                                         mangled_name);
13068
13069         status = cli_unlink(cli, windows_unlink_name, 0);
13070         if (!NT_STATUS_IS_OK(status)) {
13071                 printf("cli_unlink of %s returned %s\n",
13072                         windows_unlink_name,
13073                         nt_errstr(status));
13074                 goto out;
13075         }
13076
13077         /* Does 'a' still exist ? */
13078         status = cli_posix_open(cli_posix,
13079                                 aname,
13080                                 O_RDONLY,
13081                                 0,
13082                                 &fnum);
13083         if (!NT_STATUS_IS_OK(status)) {
13084                 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13085                         aname,
13086                         nt_errstr(status));
13087                 goto out;
13088         }
13089
13090         status = cli_close(cli_posix, fnum);
13091         if (!NT_STATUS_IS_OK(status)) {
13092                 goto out;
13093         }
13094
13095         correct = true;
13096
13097   out:
13098
13099         TALLOC_FREE(windows_unlink_name);
13100         TALLOC_FREE(mangled_name);
13101
13102         if (cli != NULL) {
13103                 torture_deltree(cli, dname);
13104                 torture_close_connection(cli);
13105         }
13106
13107         if (cli_posix != NULL) {
13108                 torture_close_connection(cli_posix);
13109         }
13110
13111         return correct;
13112 }
13113
13114 static bool run_smb1_wild_mangle_rename_test(int dummy)
13115 {
13116         static struct cli_state *cli_posix = NULL;
13117         static struct cli_state *cli = NULL;
13118         uint16_t fnum = (uint16_t)-1;
13119         bool correct = false;
13120         const char *dname = "smb1_wild_mangle_rename";
13121         const char *fooname = "smb1_wild_mangle_rename/foo";
13122         const char *foostar_name = "smb1_wild_mangle_rename/fo*";
13123         const char *wild_name = "smb1_wild_mangle_rename/*";
13124         char *windows_rename_src = NULL;
13125         const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
13126         char *mangled_name = NULL;
13127         NTSTATUS status;
13128
13129         printf("Starting SMB1 wild mangle rename test\n");
13130
13131         if (!torture_open_connection(&cli_posix, 0)) {
13132                 return false;
13133         }
13134
13135         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
13136
13137         status = torture_setup_unix_extensions(cli_posix);
13138         if (!NT_STATUS_IS_OK(status)) {
13139                 printf("server doesn't support POSIX\n");
13140                 return false;
13141         }
13142
13143         /* Open a Windows connection. */
13144         if (!torture_open_connection(&cli, 0)) {
13145                 goto out;
13146         }
13147
13148         smbXcli_conn_set_sockopt(cli->conn, sockops);
13149
13150         /* Ensure we start from fresh. */
13151         torture_deltree(cli, dname);
13152
13153         /*
13154          * Create two files - 'foo' and 'fo*'.
13155          * We need POSIX extensions for this as 'fo*'
13156          * is not a valid Windows name.
13157          */
13158
13159         status = cli_posix_mkdir(cli_posix, dname, 0770);
13160         if (!NT_STATUS_IS_OK(status)) {
13161                 printf("cli_posix_mkdir of %s returned %s\n",
13162                         dname,
13163                         nt_errstr(status));
13164                 goto out;
13165         }
13166
13167         status = cli_posix_open(cli_posix,
13168                                 fooname,
13169                                 O_RDWR|O_CREAT|O_EXCL,
13170                                 0660,
13171                                 &fnum);
13172         if (!NT_STATUS_IS_OK(status)) {
13173                 printf("cli_posix_open (create) of %s returned %s\n",
13174                         fooname,
13175                         nt_errstr(status));
13176                 goto out;
13177         }
13178         status = cli_close(cli_posix, fnum);
13179         if (!NT_STATUS_IS_OK(status)) {
13180                 goto out;
13181         }
13182         status = cli_posix_open(cli_posix,
13183                                 foostar_name,
13184                                 O_RDWR|O_CREAT|O_EXCL,
13185                                 0660,
13186                                 &fnum);
13187         if (!NT_STATUS_IS_OK(status)) {
13188                 printf("cli_posix_open (create) of %s returned %s\n",
13189                         foostar_name,
13190                         nt_errstr(status));
13191                 goto out;
13192         }
13193         status = cli_close(cli_posix, fnum);
13194         if (!NT_STATUS_IS_OK(status)) {
13195                 goto out;
13196         }
13197
13198         /*
13199          * Get the mangled name. We can re-use the
13200          * previous smb1_wild_mangle_list_fn for this.
13201          */
13202
13203         status = cli_list(cli,
13204                         wild_name,
13205                         0,
13206                         smb1_wild_mangle_list_fn,
13207                         &mangled_name);
13208         if (!NT_STATUS_IS_OK(status)) {
13209                 printf("cli_list of %s returned %s\n",
13210                         wild_name,
13211                         nt_errstr(status));
13212                 goto out;
13213         }
13214
13215         if (mangled_name == NULL) {
13216                 goto out;
13217         }
13218
13219         printf("mangled_name = %s\n",
13220                 mangled_name);
13221
13222         /*
13223          * Try a Windows rename with the mangled name.
13224          * This should *NOT* rename the 'foo' name.
13225          */
13226
13227         windows_rename_src = talloc_asprintf(cli_posix,
13228                                         "%s\\%s",
13229                                         dname,
13230                                         mangled_name);
13231
13232         status = cli_rename(cli,
13233                         windows_rename_src,
13234                         windows_rename_dst,
13235                         false);
13236         if (!NT_STATUS_IS_OK(status)) {
13237                 printf("cli_rename of %s -> %s returned %s\n",
13238                         windows_rename_src,
13239                         windows_rename_dst,
13240                         nt_errstr(status));
13241                 goto out;
13242         }
13243
13244         /* Does 'foo' still exist ? */
13245         status = cli_posix_open(cli_posix,
13246                                 fooname,
13247                                 O_RDONLY,
13248                                 0,
13249                                 &fnum);
13250         if (!NT_STATUS_IS_OK(status)) {
13251                 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13252                         fooname,
13253                         nt_errstr(status));
13254                 goto out;
13255         }
13256
13257         status = cli_close(cli_posix, fnum);
13258         if (!NT_STATUS_IS_OK(status)) {
13259                 goto out;
13260         }
13261
13262         correct = true;
13263
13264   out:
13265
13266         TALLOC_FREE(mangled_name);
13267         TALLOC_FREE(windows_rename_src);
13268
13269         if (cli != NULL) {
13270                 torture_deltree(cli, dname);
13271                 torture_close_connection(cli);
13272         }
13273
13274         torture_close_connection(cli_posix);
13275
13276         return correct;
13277 }
13278
13279 /*
13280  * Only testing minimal time strings, as the others
13281  * need (locale-dependent) guessing at what strftime does and
13282  * even may differ in builds.
13283  */
13284 static bool timesubst_test(void)
13285 {
13286         TALLOC_CTX *ctx = NULL;
13287         /* Sa 23. Dez 04:33:20 CET 2017 */
13288         const struct timeval tv = { 1514000000, 123 };
13289         const char* expect_minimal = "20171223_033320";
13290         const char* expect_minus   = "20171223_033320_000123";
13291         char *s;
13292         char *env_tz, *orig_tz = NULL;
13293         bool result = true;
13294
13295         ctx = talloc_new(NULL);
13296
13297         env_tz = getenv("TZ");
13298         if(env_tz) {
13299                 orig_tz = talloc_strdup(ctx, env_tz);
13300         }
13301         setenv("TZ", "UTC", 1);
13302
13303         s = minimal_timeval_string(ctx, &tv, false);
13304
13305         if(!s || strcmp(s, expect_minimal)) {
13306                 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13307                        "[%s]\n", s ? s : "<nil>", expect_minimal);
13308                 result = false;
13309         }
13310         TALLOC_FREE(s);
13311         s = minimal_timeval_string(ctx, &tv, true);
13312         if(!s || strcmp(s, expect_minus)) {
13313                 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13314                        "[%s]\n", s ? s : "<nil>", expect_minus);
13315                 result = false;
13316         }
13317         TALLOC_FREE(s);
13318
13319         if(orig_tz) {
13320                 setenv("TZ", orig_tz, 1);
13321         }
13322
13323         TALLOC_FREE(ctx);
13324         return result;
13325 }
13326
13327 static bool run_local_substitute(int dummy)
13328 {
13329         bool ok = true;
13330
13331         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13332         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13333         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13334         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13335         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13336         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13337         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13338         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13339         ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13340         /* Substitution depends on current time, so better test the underlying
13341            formatting function. At least covers %t. */
13342         ok &= timesubst_test();
13343
13344         /* Different captialization rules in sub_basic... */
13345
13346         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13347                        "blaDOM") == 0);
13348
13349         return ok;
13350 }
13351
13352 static bool run_local_base64(int dummy)
13353 {
13354         int i;
13355         bool ret = true;
13356
13357         for (i=1; i<2000; i++) {
13358                 DATA_BLOB blob1, blob2;
13359                 char *b64;
13360
13361                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13362                 blob1.length = i;
13363                 generate_random_buffer(blob1.data, blob1.length);
13364
13365                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
13366                 if (b64 == NULL) {
13367                         d_fprintf(stderr, "base64_encode_data_blob failed "
13368                                   "for %d bytes\n", i);
13369                         ret = false;
13370                 }
13371                 blob2 = base64_decode_data_blob(b64);
13372                 TALLOC_FREE(b64);
13373
13374                 if (data_blob_cmp(&blob1, &blob2)) {
13375                         d_fprintf(stderr, "data_blob_cmp failed for %d "
13376                                   "bytes\n", i);
13377                         ret = false;
13378                 }
13379                 TALLOC_FREE(blob1.data);
13380                 data_blob_free(&blob2);
13381         }
13382         return ret;
13383 }
13384
13385 static void parse_fn(const struct gencache_timeout *t,
13386                      DATA_BLOB blob,
13387                      void *private_data)
13388 {
13389         return;
13390 }
13391
13392 static bool run_local_gencache(int dummy)
13393 {
13394         char *val;
13395         time_t tm;
13396         DATA_BLOB blob;
13397         char v;
13398         struct memcache *mem;
13399         int i;
13400
13401         mem = memcache_init(NULL, 0);
13402         if (mem == NULL) {
13403                 d_printf("%s: memcache_init failed\n", __location__);
13404                 return false;
13405         }
13406         memcache_set_global(mem);
13407
13408         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13409                 d_printf("%s: gencache_set() failed\n", __location__);
13410                 return False;
13411         }
13412
13413         if (!gencache_get("foo", NULL, NULL, NULL)) {
13414                 d_printf("%s: gencache_get() failed\n", __location__);
13415                 return False;
13416         }
13417
13418         for (i=0; i<1000000; i++) {
13419                 gencache_parse("foo", parse_fn, NULL);
13420         }
13421
13422         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13423                 d_printf("%s: gencache_get() failed\n", __location__);
13424                 return False;
13425         }
13426         TALLOC_FREE(val);
13427
13428         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13429                 d_printf("%s: gencache_get() failed\n", __location__);
13430                 return False;
13431         }
13432
13433         if (strcmp(val, "bar") != 0) {
13434                 d_printf("%s: gencache_get() returned %s, expected %s\n",
13435                          __location__, val, "bar");
13436                 TALLOC_FREE(val);
13437                 return False;
13438         }
13439
13440         TALLOC_FREE(val);
13441
13442         if (!gencache_del("foo")) {
13443                 d_printf("%s: gencache_del() failed\n", __location__);
13444                 return False;
13445         }
13446         if (gencache_del("foo")) {
13447                 d_printf("%s: second gencache_del() succeeded\n",
13448                          __location__);
13449                 return False;
13450         }
13451
13452         if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13453                 d_printf("%s: gencache_get() on deleted entry "
13454                          "succeeded\n", __location__);
13455                 return False;
13456         }
13457
13458         blob = data_blob_string_const_null("bar");
13459         tm = time(NULL) + 60;
13460
13461         if (!gencache_set_data_blob("foo", blob, tm)) {
13462                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13463                 return False;
13464         }
13465
13466         if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13467                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13468                 return False;
13469         }
13470
13471         if (strcmp((const char *)blob.data, "bar") != 0) {
13472                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13473                          __location__, (const char *)blob.data, "bar");
13474                 data_blob_free(&blob);
13475                 return False;
13476         }
13477
13478         data_blob_free(&blob);
13479
13480         if (!gencache_del("foo")) {
13481                 d_printf("%s: gencache_del() failed\n", __location__);
13482                 return False;
13483         }
13484         if (gencache_del("foo")) {
13485                 d_printf("%s: second gencache_del() succeeded\n",
13486                          __location__);
13487                 return False;
13488         }
13489
13490         if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13491                 d_printf("%s: gencache_get_data_blob() on deleted entry "
13492                          "succeeded\n", __location__);
13493                 return False;
13494         }
13495
13496         v = 1;
13497         blob.data = (uint8_t *)&v;
13498         blob.length = sizeof(v);
13499
13500         if (!gencache_set_data_blob("blob", blob, tm)) {
13501                 d_printf("%s: gencache_set_data_blob() failed\n",
13502                          __location__);
13503                 return false;
13504         }
13505         if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13506                 d_printf("%s: gencache_get succeeded\n", __location__);
13507                 return false;
13508         }
13509
13510         return True;
13511 }
13512
13513 static bool rbt_testflags(struct db_context *db, const char *key,
13514                           const char *value)
13515 {
13516         bool ret = false;
13517         NTSTATUS status;
13518         struct db_record *rec;
13519
13520         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13521         if (rec == NULL) {
13522                 d_fprintf(stderr, "fetch_locked failed\n");
13523                 goto done;
13524         }
13525
13526         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13527         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13528                 d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13529                           nt_errstr(status));
13530                 goto done;
13531         }
13532
13533         status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13534                                      TDB_INSERT);
13535         if (!NT_STATUS_IS_OK(status)) {
13536                 d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13537                           nt_errstr(status));
13538                 goto done;
13539         }
13540
13541         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13542         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13543                 d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13544                           nt_errstr(status));
13545                 goto done;
13546         }
13547
13548         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13549         if (!NT_STATUS_IS_OK(status)) {
13550                 d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13551                           nt_errstr(status));
13552                 goto done;
13553         }
13554
13555         ret = true;
13556 done:
13557         TALLOC_FREE(rec);
13558         return ret;
13559 }
13560
13561 static bool rbt_testval(struct db_context *db, const char *key,
13562                         const char *value)
13563 {
13564         struct db_record *rec;
13565         TDB_DATA data = string_tdb_data(value);
13566         bool ret = false;
13567         NTSTATUS status;
13568         TDB_DATA dbvalue;
13569
13570         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13571         if (rec == NULL) {
13572                 d_fprintf(stderr, "fetch_locked failed\n");
13573                 goto done;
13574         }
13575         status = dbwrap_record_store(rec, data, 0);
13576         if (!NT_STATUS_IS_OK(status)) {
13577                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13578                 goto done;
13579         }
13580         TALLOC_FREE(rec);
13581
13582         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13583         if (rec == NULL) {
13584                 d_fprintf(stderr, "second fetch_locked failed\n");
13585                 goto done;
13586         }
13587
13588         dbvalue = dbwrap_record_get_value(rec);
13589         if ((dbvalue.dsize != data.dsize)
13590             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13591                 d_fprintf(stderr, "Got wrong data back\n");
13592                 goto done;
13593         }
13594
13595         ret = true;
13596  done:
13597         TALLOC_FREE(rec);
13598         return ret;
13599 }
13600
13601 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13602 {
13603         int *count2 = (int *)private_data;
13604         (*count2)++;
13605         return 0;
13606 }
13607
13608 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13609 {
13610         int *count2 = (int *)private_data;
13611         (*count2)++;
13612         dbwrap_record_delete(rec);
13613         return 0;
13614 }
13615
13616 static bool run_local_rbtree(int dummy)
13617 {
13618         struct db_context *db;
13619         bool ret = false;
13620         int i;
13621         NTSTATUS status;
13622         int count = 0;
13623         int count2 = 0;
13624
13625         db = db_open_rbt(NULL);
13626
13627         if (db == NULL) {
13628                 d_fprintf(stderr, "db_open_rbt failed\n");
13629                 return false;
13630         }
13631
13632         if (!rbt_testflags(db, "firstkey", "firstval")) {
13633                 goto done;
13634         }
13635
13636         for (i = 0; i < 999; i++) {
13637                 char key[sizeof("key-9223372036854775807")];
13638                 char value[sizeof("value-9223372036854775807")];
13639
13640                 snprintf(key, sizeof(key), "key%ld", random());
13641                 snprintf(value, sizeof(value) ,"value%ld", random());
13642
13643                 if (!rbt_testval(db, key, value)) {
13644                         goto done;
13645                 }
13646
13647                 snprintf(value, sizeof(value) ,"value%ld", random());
13648
13649                 if (!rbt_testval(db, key, value)) {
13650                         goto done;
13651                 }
13652         }
13653
13654         ret = true;
13655         count = 0; count2 = 0;
13656         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13657                                       &count2, &count);
13658         printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13659         if ((count != count2) || (count != 1000)) {
13660                 ret = false;
13661         }
13662         count = 0; count2 = 0;
13663         status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13664                                  &count2, &count);
13665         printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13666         if ((count != count2) || (count != 1000)) {
13667                 ret = false;
13668         }
13669         count = 0; count2 = 0;
13670         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13671                                       &count2, &count);
13672         printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13673         if ((count != count2) || (count != 0)) {
13674                 ret = false;
13675         }
13676
13677  done:
13678         TALLOC_FREE(db);
13679         return ret;
13680 }
13681
13682
13683 /*
13684   local test for character set functions
13685
13686   This is a very simple test for the functionality in convert_string_error()
13687  */
13688 static bool run_local_convert_string(int dummy)
13689 {
13690         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13691         const char *test_strings[2] = { "March", "M\303\244rz" };
13692         char dst[7];
13693         int i;
13694
13695         for (i=0; i<2; i++) {
13696                 const char *str = test_strings[i];
13697                 int len = strlen(str);
13698                 size_t converted_size;
13699                 bool ret;
13700
13701                 memset(dst, 'X', sizeof(dst));
13702
13703                 /* first try with real source length */
13704                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13705                                            str, len,
13706                                            dst, sizeof(dst),
13707                                            &converted_size);
13708                 if (ret != true) {
13709                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13710                         goto failed;
13711                 }
13712
13713                 if (converted_size != len) {
13714                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13715                                   str, len, (int)converted_size);
13716                         goto failed;
13717                 }
13718
13719                 if (strncmp(str, dst, converted_size) != 0) {
13720                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13721                         goto failed;
13722                 }
13723
13724                 if (strlen(str) != converted_size) {
13725                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13726                                   (int)strlen(str), (int)converted_size);
13727                         goto failed;
13728                 }
13729
13730                 if (dst[converted_size] != 'X') {
13731                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13732                         goto failed;
13733                 }
13734
13735                 /* now with srclen==-1, this causes the nul to be
13736                  * converted too */
13737                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13738                                            str, -1,
13739                                            dst, sizeof(dst),
13740                                            &converted_size);
13741                 if (ret != true) {
13742                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13743                         goto failed;
13744                 }
13745
13746                 if (converted_size != len+1) {
13747                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13748                                   str, len, (int)converted_size);
13749                         goto failed;
13750                 }
13751
13752                 if (strncmp(str, dst, converted_size) != 0) {
13753                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13754                         goto failed;
13755                 }
13756
13757                 if (len+1 != converted_size) {
13758                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13759                                   len+1, (int)converted_size);
13760                         goto failed;
13761                 }
13762
13763                 if (dst[converted_size] != 'X') {
13764                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13765                         goto failed;
13766                 }
13767
13768         }
13769
13770
13771         TALLOC_FREE(tmp_ctx);
13772         return true;
13773 failed:
13774         TALLOC_FREE(tmp_ctx);
13775         return false;
13776 }
13777
13778 static bool run_local_string_to_sid(int dummy) {
13779         struct dom_sid sid;
13780
13781         if (string_to_sid(&sid, "S--1-5-32-545")) {
13782                 printf("allowing S--1-5-32-545\n");
13783                 return false;
13784         }
13785         if (string_to_sid(&sid, "S-1-5-32-+545")) {
13786                 printf("allowing S-1-5-32-+545\n");
13787                 return false;
13788         }
13789         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")) {
13790                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13791                 return false;
13792         }
13793         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13794                 printf("allowing S-1-5-32-545-abc\n");
13795                 return false;
13796         }
13797         if (string_to_sid(&sid, "S-300-5-32-545")) {
13798                 printf("allowing S-300-5-32-545\n");
13799                 return false;
13800         }
13801         if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13802                 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13803                 return false;
13804         }
13805         if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13806                 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13807                 return false;
13808         }
13809         if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13810                 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13811                 return false;
13812         }
13813         if (!string_to_sid(&sid, "S-1-5-32-545")) {
13814                 printf("could not parse S-1-5-32-545\n");
13815                 return false;
13816         }
13817         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13818                 struct dom_sid_buf buf;
13819                 printf("mis-parsed S-1-5-32-545 as %s\n",
13820                        dom_sid_str_buf(&sid, &buf));
13821                 return false;
13822         }
13823         return true;
13824 }
13825
13826 static bool sid_to_string_test(const char *expected) {
13827         char *str;
13828         bool res = true;
13829         struct dom_sid sid;
13830
13831         if (!string_to_sid(&sid, expected)) {
13832                 printf("could not parse %s\n", expected);
13833                 return false;
13834         }
13835
13836         str = dom_sid_string(NULL, &sid);
13837         if (strcmp(str, expected)) {
13838                 printf("Comparison failed (%s != %s)\n", str, expected);
13839                 res = false;
13840         }
13841         TALLOC_FREE(str);
13842         return res;
13843 }
13844
13845 static bool run_local_sid_to_string(int dummy) {
13846         if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13847                 return false;
13848         if (!sid_to_string_test("S-1-545"))
13849                 return false;
13850         if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13851                 return false;
13852         return true;
13853 }
13854
13855 static bool run_local_binary_to_sid(int dummy) {
13856         ssize_t ret;
13857         struct dom_sid *sid = talloc(NULL, struct dom_sid);
13858         static const uint8_t good_binary_sid[] = {
13859                 0x1, /* revision number */
13860                 15, /* num auths */
13861                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13862                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13863                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13864                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13865                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13866                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13867                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13868                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13869                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13870                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13871                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13872                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13873                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13874                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13875                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13876                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13877         };
13878
13879         static const uint8_t long_binary_sid[] = {
13880                 0x1, /* revision number */
13881                 15, /* num auths */
13882                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13883                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13884                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13885                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13886                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13887                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13888                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13889                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13890                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13891                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13892                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13893                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13894                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13895                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13896                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13897                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13898                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13899                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13900                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13901         };
13902
13903         static const uint8_t long_binary_sid2[] = {
13904                 0x1, /* revision number */
13905                 32, /* num auths */
13906                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13907                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13908                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13909                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13910                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13911                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13912                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13913                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13914                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13915                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13916                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13917                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13918                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13919                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13920                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13921                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13922                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13923                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13924                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13925                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13926                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13927                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13928                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13929                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13930                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13931                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13932                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13933                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13934                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13935                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13936                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13937                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13938                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13939         };
13940
13941         ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13942         if (ret == -1) {
13943                 return false;
13944         }
13945         ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13946         if (ret != -1) {
13947                 return false;
13948         }
13949         ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13950         if (ret != -1) {
13951                 return false;
13952         }
13953         return true;
13954 }
13955
13956 /* Split a path name into filename and stream name components. Canonicalise
13957  * such that an implicit $DATA token is always explicit.
13958  *
13959  * The "specification" of this function can be found in the
13960  * run_local_stream_name() function in torture.c, I've tried those
13961  * combinations against a W2k3 server.
13962  */
13963
13964 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13965                                        char **pbase, char **pstream)
13966 {
13967         char *base = NULL;
13968         char *stream = NULL;
13969         char *sname; /* stream name */
13970         const char *stype; /* stream type */
13971
13972         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13973
13974         sname = strchr_m(fname, ':');
13975
13976         if (sname == NULL) {
13977                 if (pbase != NULL) {
13978                         base = talloc_strdup(mem_ctx, fname);
13979                         NT_STATUS_HAVE_NO_MEMORY(base);
13980                 }
13981                 goto done;
13982         }
13983
13984         if (pbase != NULL) {
13985                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13986                 NT_STATUS_HAVE_NO_MEMORY(base);
13987         }
13988
13989         sname += 1;
13990
13991         stype = strchr_m(sname, ':');
13992
13993         if (stype == NULL) {
13994                 sname = talloc_strdup(mem_ctx, sname);
13995                 stype = "$DATA";
13996         }
13997         else {
13998                 if (strcasecmp_m(stype, ":$DATA") != 0) {
13999                         /*
14000                          * If there is an explicit stream type, so far we only
14001                          * allow $DATA. Is there anything else allowed? -- vl
14002                          */
14003                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
14004                         TALLOC_FREE(base);
14005                         return NT_STATUS_OBJECT_NAME_INVALID;
14006                 }
14007                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
14008                 stype += 1;
14009         }
14010
14011         if (sname == NULL) {
14012                 TALLOC_FREE(base);
14013                 return NT_STATUS_NO_MEMORY;
14014         }
14015
14016         if (sname[0] == '\0') {
14017                 /*
14018                  * no stream name, so no stream
14019                  */
14020                 goto done;
14021         }
14022
14023         if (pstream != NULL) {
14024                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
14025                 if (stream == NULL) {
14026                         TALLOC_FREE(sname);
14027                         TALLOC_FREE(base);
14028                         return NT_STATUS_NO_MEMORY;
14029                 }
14030                 /*
14031                  * upper-case the type field
14032                  */
14033                 (void)strupper_m(strchr_m(stream, ':')+1);
14034         }
14035
14036  done:
14037         if (pbase != NULL) {
14038                 *pbase = base;
14039         }
14040         if (pstream != NULL) {
14041                 *pstream = stream;
14042         }
14043         return NT_STATUS_OK;
14044 }
14045
14046 static bool test_stream_name(const char *fname, const char *expected_base,
14047                              const char *expected_stream,
14048                              NTSTATUS expected_status)
14049 {
14050         NTSTATUS status;
14051         char *base = NULL;
14052         char *stream = NULL;
14053
14054         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
14055         if (!NT_STATUS_EQUAL(status, expected_status)) {
14056                 goto error;
14057         }
14058
14059         if (!NT_STATUS_IS_OK(status)) {
14060                 return true;
14061         }
14062
14063         if (base == NULL) goto error;
14064
14065         if (strcmp(expected_base, base) != 0) goto error;
14066
14067         if ((expected_stream != NULL) && (stream == NULL)) goto error;
14068         if ((expected_stream == NULL) && (stream != NULL)) goto error;
14069
14070         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
14071                 goto error;
14072
14073         TALLOC_FREE(base);
14074         TALLOC_FREE(stream);
14075         return true;
14076
14077  error:
14078         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
14079                   fname, expected_base ? expected_base : "<NULL>",
14080                   expected_stream ? expected_stream : "<NULL>",
14081                   nt_errstr(expected_status));
14082         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
14083                   base ? base : "<NULL>", stream ? stream : "<NULL>",
14084                   nt_errstr(status));
14085         TALLOC_FREE(base);
14086         TALLOC_FREE(stream);
14087         return false;
14088 }
14089
14090 static bool run_local_stream_name(int dummy)
14091 {
14092         bool ret = true;
14093
14094         ret &= test_stream_name(
14095                 "bla", "bla", NULL, NT_STATUS_OK);
14096         ret &= test_stream_name(
14097                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
14098         ret &= test_stream_name(
14099                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14100         ret &= test_stream_name(
14101                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
14102         ret &= test_stream_name(
14103                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14104         ret &= test_stream_name(
14105                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
14106         ret &= test_stream_name(
14107                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
14108         ret &= test_stream_name(
14109                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
14110
14111         return ret;
14112 }
14113
14114 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
14115 {
14116         if (a.length != b.length) {
14117                 printf("a.length=%d != b.length=%d\n",
14118                        (int)a.length, (int)b.length);
14119                 return false;
14120         }
14121         if (memcmp(a.data, b.data, a.length) != 0) {
14122                 printf("a.data and b.data differ\n");
14123                 return false;
14124         }
14125         return true;
14126 }
14127
14128 static bool run_local_memcache(int dummy)
14129 {
14130         struct memcache *cache;
14131         DATA_BLOB k1, k2, k3, k4, k5;
14132         DATA_BLOB d1, d3;
14133         DATA_BLOB v1, v3;
14134
14135         TALLOC_CTX *mem_ctx;
14136         char *ptr1 = NULL;
14137         char *ptr2 = NULL;
14138         char *ptr3 = NULL;
14139
14140         char *str1, *str2;
14141         size_t size1, size2;
14142         bool ret = false;
14143
14144         mem_ctx = talloc_init("foo");
14145         if (mem_ctx == NULL) {
14146                 return false;
14147         }
14148
14149         /* STAT_CACHE TESTS */
14150
14151         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14152
14153         if (cache == NULL) {
14154                 printf("memcache_init failed\n");
14155                 return false;
14156         }
14157
14158         d1 = data_blob_const("d1", 2);
14159         d3 = data_blob_const("d3", 2);
14160
14161         k1 = data_blob_const("d1", 2);
14162         k2 = data_blob_const("d2", 2);
14163         k3 = data_blob_const("d3", 2);
14164         k4 = data_blob_const("d4", 2);
14165         k5 = data_blob_const("d5", 2);
14166
14167         memcache_add(cache, STAT_CACHE, k1, d1);
14168
14169         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
14170                 printf("could not find k1\n");
14171                 return false;
14172         }
14173         if (!data_blob_equal(d1, v1)) {
14174                 return false;
14175         }
14176
14177         memcache_add(cache, STAT_CACHE, k1, d3);
14178
14179         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
14180                 printf("could not find replaced k1\n");
14181                 return false;
14182         }
14183         if (!data_blob_equal(d3, v3)) {
14184                 return false;
14185         }
14186
14187         TALLOC_FREE(cache);
14188
14189         /* GETWD_CACHE TESTS */
14190         str1 = talloc_strdup(mem_ctx, "string1");
14191         if (str1 == NULL) {
14192                 return false;
14193         }
14194         ptr2 = str1; /* Keep an alias for comparison. */
14195
14196         str2 = talloc_strdup(mem_ctx, "string2");
14197         if (str2 == NULL) {
14198                 return false;
14199         }
14200
14201         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14202         if (cache == NULL) {
14203                 printf("memcache_init failed\n");
14204                 return false;
14205         }
14206
14207         memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14208         /* str1 == NULL now. */
14209         ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14210         if (ptr1 == NULL) {
14211                 printf("could not find k2\n");
14212                 return false;
14213         }
14214         if (ptr1 != ptr2) {
14215                 printf("fetch of k2 got wrong string\n");
14216                 return false;
14217         }
14218
14219         /* Add a blob to ensure k2 gets purged. */
14220         d3 = data_blob_talloc_zero(mem_ctx, 180);
14221         memcache_add(cache, STAT_CACHE, k3, d3);
14222
14223         ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14224         if (ptr2 != NULL) {
14225                 printf("Did find k2, should have been purged\n");
14226                 return false;
14227         }
14228
14229         /*
14230          * Test that talloc size also is accounted in memcache and
14231          * causes purge of other object.
14232          */
14233
14234         str1 = talloc_zero_size(mem_ctx, 100);
14235         str2 = talloc_zero_size(mem_ctx, 100);
14236
14237         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14238         memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14239
14240         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14241         if (ptr3 != NULL) {
14242                 printf("Did find k4, should have been purged\n");
14243                 return false;
14244         }
14245
14246         /*
14247          * Test that adding a duplicate non-talloced
14248          * key/value on top of a talloced key/value takes account
14249          * of the talloc_freed value size.
14250          */
14251         TALLOC_FREE(cache);
14252         TALLOC_FREE(mem_ctx);
14253
14254         mem_ctx = talloc_init("key_replace");
14255         if (mem_ctx == NULL) {
14256                 return false;
14257         }
14258
14259         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14260         if (cache == NULL) {
14261                 return false;
14262         }
14263
14264         /*
14265          * Add a 100 byte talloced string. This will
14266          * store a (4 or 8 byte) pointer and record the
14267          * total talloced size.
14268          */
14269         str1 = talloc_zero_size(mem_ctx, 100);
14270         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14271         /*
14272          * Now overwrite with a small talloced
14273          * value. This should fit in the existing size
14274          * and the total talloced size should be removed
14275          * from the cache size.
14276          */
14277         str1 = talloc_zero_size(mem_ctx, 2);
14278         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14279         /*
14280          * Now store a 20 byte string. If the
14281          * total talloced size wasn't accounted for
14282          * and removed in the overwrite, then this
14283          * will evict k4.
14284          */
14285         str2 = talloc_zero_size(mem_ctx, 20);
14286         memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14287
14288         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14289         if (ptr3 == NULL) {
14290                 printf("Did not find k4, should not have been purged\n");
14291                 return false;
14292         }
14293
14294         TALLOC_FREE(cache);
14295         TALLOC_FREE(mem_ctx);
14296
14297         mem_ctx = talloc_init("foo");
14298         if (mem_ctx == NULL) {
14299                 return false;
14300         }
14301
14302         cache = memcache_init(NULL, 0);
14303         if (cache == NULL) {
14304                 return false;
14305         }
14306
14307         str1 = talloc_strdup(mem_ctx, "string1");
14308         if (str1 == NULL) {
14309                 return false;
14310         }
14311         str2 = talloc_strdup(mem_ctx, "string2");
14312         if (str2 == NULL) {
14313                 return false;
14314         }
14315         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14316                             data_blob_string_const("torture"), &str1);
14317         size1 = talloc_total_size(cache);
14318
14319         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14320                             data_blob_string_const("torture"), &str2);
14321         size2 = talloc_total_size(cache);
14322
14323         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14324
14325         if (size2 > size1) {
14326                 printf("memcache leaks memory!\n");
14327                 goto fail;
14328         }
14329
14330         ret = true;
14331  fail:
14332         TALLOC_FREE(cache);
14333         return ret;
14334 }
14335
14336 static void wbclient_done(struct tevent_req *req)
14337 {
14338         wbcErr wbc_err;
14339         struct winbindd_response *wb_resp;
14340         int *i = (int *)tevent_req_callback_data_void(req);
14341
14342         wbc_err = wb_trans_recv(req, req, &wb_resp);
14343         TALLOC_FREE(req);
14344         *i += 1;
14345         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14346 }
14347
14348 static bool run_wbclient_multi_ping(int dummy)
14349 {
14350         struct tevent_context *ev;
14351         struct wb_context **wb_ctx;
14352         struct winbindd_request wb_req;
14353         bool result = false;
14354         int i, j;
14355
14356         BlockSignals(True, SIGPIPE);
14357
14358         ev = tevent_context_init(talloc_tos());
14359         if (ev == NULL) {
14360                 goto fail;
14361         }
14362
14363         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14364         if (wb_ctx == NULL) {
14365                 goto fail;
14366         }
14367
14368         ZERO_STRUCT(wb_req);
14369         wb_req.cmd = WINBINDD_PING;
14370
14371         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14372
14373         for (i=0; i<torture_nprocs; i++) {
14374                 wb_ctx[i] = wb_context_init(ev, NULL);
14375                 if (wb_ctx[i] == NULL) {
14376                         goto fail;
14377                 }
14378                 for (j=0; j<torture_numops; j++) {
14379                         struct tevent_req *req;
14380                         req = wb_trans_send(ev, ev, wb_ctx[i],
14381                                             (j % 2) == 0, &wb_req);
14382                         if (req == NULL) {
14383                                 goto fail;
14384                         }
14385                         tevent_req_set_callback(req, wbclient_done, &i);
14386                 }
14387         }
14388
14389         i = 0;
14390
14391         while (i < torture_nprocs * torture_numops) {
14392                 tevent_loop_once(ev);
14393         }
14394
14395         result = true;
14396  fail:
14397         TALLOC_FREE(ev);
14398         return result;
14399 }
14400
14401 static bool dbtrans_inc(struct db_context *db)
14402 {
14403         struct db_record *rec;
14404         uint32_t val;
14405         bool ret = false;
14406         NTSTATUS status;
14407         TDB_DATA value;
14408
14409         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14410         if (rec == NULL) {
14411                 printf(__location__ "fetch_lock failed\n");
14412                 return false;
14413         }
14414
14415         value = dbwrap_record_get_value(rec);
14416
14417         if (value.dsize != sizeof(uint32_t)) {
14418                 printf(__location__ "value.dsize = %d\n",
14419                        (int)value.dsize);
14420                 goto fail;
14421         }
14422
14423         memcpy(&val, value.dptr, sizeof(val));
14424         val += 1;
14425
14426         status = dbwrap_record_store(
14427                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14428         if (!NT_STATUS_IS_OK(status)) {
14429                 printf(__location__ "store failed: %s\n",
14430                        nt_errstr(status));
14431                 goto fail;
14432         }
14433
14434         ret = true;
14435 fail:
14436         TALLOC_FREE(rec);
14437         return ret;
14438 }
14439
14440 static bool run_local_dbtrans(int dummy)
14441 {
14442         struct db_context *db;
14443         struct db_record *rec;
14444         NTSTATUS status;
14445         uint32_t initial;
14446         int res;
14447         TDB_DATA value;
14448
14449         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14450                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14451                      DBWRAP_FLAG_NONE);
14452         if (db == NULL) {
14453                 printf("Could not open transtest.db\n");
14454                 return false;
14455         }
14456
14457         res = dbwrap_transaction_start(db);
14458         if (res != 0) {
14459                 printf(__location__ "transaction_start failed\n");
14460                 return false;
14461         }
14462
14463         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14464         if (rec == NULL) {
14465                 printf(__location__ "fetch_lock failed\n");
14466                 return false;
14467         }
14468
14469         value = dbwrap_record_get_value(rec);
14470
14471         if (value.dptr == NULL) {
14472                 initial = 0;
14473                 status = dbwrap_record_store(
14474                         rec, make_tdb_data((uint8_t *)&initial,
14475                                            sizeof(initial)),
14476                         0);
14477                 if (!NT_STATUS_IS_OK(status)) {
14478                         printf(__location__ "store returned %s\n",
14479                                nt_errstr(status));
14480                         return false;
14481                 }
14482         }
14483
14484         TALLOC_FREE(rec);
14485
14486         res = dbwrap_transaction_commit(db);
14487         if (res != 0) {
14488                 printf(__location__ "transaction_commit failed\n");
14489                 return false;
14490         }
14491
14492         while (true) {
14493                 uint32_t val, val2;
14494                 int i;
14495
14496                 res = dbwrap_transaction_start(db);
14497                 if (res != 0) {
14498                         printf(__location__ "transaction_start failed\n");
14499                         break;
14500                 }
14501
14502                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14503                 if (!NT_STATUS_IS_OK(status)) {
14504                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14505                                nt_errstr(status));
14506                         break;
14507                 }
14508
14509                 for (i=0; i<10; i++) {
14510                         if (!dbtrans_inc(db)) {
14511                                 return false;
14512                         }
14513                 }
14514
14515                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14516                 if (!NT_STATUS_IS_OK(status)) {
14517                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14518                                nt_errstr(status));
14519                         break;
14520                 }
14521
14522                 if (val2 != val + 10) {
14523                         printf(__location__ "val=%d, val2=%d\n",
14524                                (int)val, (int)val2);
14525                         break;
14526                 }
14527
14528                 printf("val2=%d\r", val2);
14529
14530                 res = dbwrap_transaction_commit(db);
14531                 if (res != 0) {
14532                         printf(__location__ "transaction_commit failed\n");
14533                         break;
14534                 }
14535         }
14536
14537         TALLOC_FREE(db);
14538         return true;
14539 }
14540
14541 /*
14542  * Just a dummy test to be run under a debugger. There's no real way
14543  * to inspect the tevent_poll specific function from outside of
14544  * tevent_poll.c.
14545  */
14546
14547 static bool run_local_tevent_poll(int dummy)
14548 {
14549         struct tevent_context *ev;
14550         struct tevent_fd *fd1, *fd2;
14551         bool result = false;
14552
14553         ev = tevent_context_init_byname(NULL, "poll");
14554         if (ev == NULL) {
14555                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
14556                 goto fail;
14557         }
14558
14559         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14560         if (fd1 == NULL) {
14561                 d_fprintf(stderr, "tevent_add_fd failed\n");
14562                 goto fail;
14563         }
14564         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14565         if (fd2 == NULL) {
14566                 d_fprintf(stderr, "tevent_add_fd failed\n");
14567                 goto fail;
14568         }
14569         TALLOC_FREE(fd2);
14570
14571         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14572         if (fd2 == NULL) {
14573                 d_fprintf(stderr, "tevent_add_fd failed\n");
14574                 goto fail;
14575         }
14576
14577         result = true;
14578 fail:
14579         TALLOC_FREE(ev);
14580         return result;
14581 }
14582
14583 static bool run_local_hex_encode_buf(int dummy)
14584 {
14585         char buf[17];
14586         uint8_t src[8];
14587         size_t i;
14588
14589         for (i=0; i<sizeof(src); i++) {
14590                 src[i] = i;
14591         }
14592         hex_encode_buf(buf, src, sizeof(src));
14593         if (strcmp(buf, "0001020304050607") != 0) {
14594                 return false;
14595         }
14596         hex_encode_buf(buf, NULL, 0);
14597         if (buf[0] != '\0') {
14598                 return false;
14599         }
14600         return true;
14601 }
14602
14603 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14604         "0.0.0.0",
14605         "::0",
14606         "1.2.3.1",
14607         "0.0.0.0",
14608         "0.0.0.0",
14609         "1.2.3.2",
14610         "1.2.3.3",
14611         "1.2.3.4",
14612         "1.2.3.5",
14613         "::0",
14614         "1.2.3.6",
14615         "1.2.3.7",
14616         "::0",
14617         "::0",
14618         "::0",
14619         "1.2.3.8",
14620         "1.2.3.9",
14621         "1.2.3.10",
14622         "1.2.3.11",
14623         "1.2.3.12",
14624         "1.2.3.13",
14625         "1001:1111:1111:1000:0:1111:1111:1111",
14626         "1.2.3.1",
14627         "1.2.3.2",
14628         "1.2.3.3",
14629         "1.2.3.12",
14630         "::0",
14631         "::0"
14632 };
14633
14634 static const char *remove_duplicate_addrs2_test_strings_result[] = {
14635         "1.2.3.1",
14636         "1.2.3.2",
14637         "1.2.3.3",
14638         "1.2.3.4",
14639         "1.2.3.5",
14640         "1.2.3.6",
14641         "1.2.3.7",
14642         "1.2.3.8",
14643         "1.2.3.9",
14644         "1.2.3.10",
14645         "1.2.3.11",
14646         "1.2.3.12",
14647         "1.2.3.13",
14648         "1001:1111:1111:1000:0:1111:1111:1111"
14649 };
14650
14651 static bool run_local_remove_duplicate_addrs2(int dummy)
14652 {
14653         struct samba_sockaddr test_vector[28];
14654         size_t count, i;
14655
14656         /* Construct the sockaddr_storage test vector. */
14657         for (i = 0; i < 28; i++) {
14658                 struct addrinfo hints;
14659                 struct addrinfo *res = NULL;
14660                 int ret;
14661
14662                 memset(&hints, '\0', sizeof(hints));
14663                 hints.ai_flags = AI_NUMERICHOST;
14664                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14665                                 NULL,
14666                                 &hints,
14667                                 &res);
14668                 if (ret) {
14669                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
14670                                 remove_duplicate_addrs2_test_strings_vector[i]);
14671                         return false;
14672                 }
14673                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14674                 memcpy(&test_vector[i].u.ss,
14675                         res->ai_addr,
14676                         res->ai_addrlen);
14677                 freeaddrinfo(res);
14678         }
14679
14680         count = remove_duplicate_addrs2(test_vector, i);
14681
14682         if (count != 14) {
14683                 fprintf(stderr, "count wrong (%zu) should be 14\n",
14684                         count);
14685                 return false;
14686         }
14687
14688         for (i = 0; i < count; i++) {
14689                 char addr[INET6_ADDRSTRLEN];
14690
14691                 print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14692
14693                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14694                         fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14695                                 i,
14696                                 addr,
14697                                 remove_duplicate_addrs2_test_strings_result[i]);
14698                         return false;
14699                 }
14700         }
14701
14702         printf("run_local_remove_duplicate_addrs2: success\n");
14703         return true;
14704 }
14705
14706 static bool run_local_tdb_opener(int dummy)
14707 {
14708         TDB_CONTEXT *t;
14709         unsigned v = 0;
14710
14711         while (1) {
14712                 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14713                              O_RDWR|O_CREAT, 0755);
14714                 if (t == NULL) {
14715                         perror("tdb_open failed");
14716                         return false;
14717                 }
14718                 tdb_close(t);
14719
14720                 v += 1;
14721                 printf("\r%u", v);
14722         }
14723         return true;
14724 }
14725
14726 static bool run_local_tdb_writer(int dummy)
14727 {
14728         TDB_CONTEXT *t;
14729         unsigned v = 0;
14730         TDB_DATA val;
14731
14732         t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14733         if (t == 0) {
14734                 perror("tdb_open failed");
14735                 return 1;
14736         }
14737
14738         val.dptr = (uint8_t *)&v;
14739         val.dsize = sizeof(v);
14740
14741         while (1) {
14742                 TDB_DATA data;
14743                 int ret;
14744
14745                 ret = tdb_store(t, val, val, 0);
14746                 if (ret != 0) {
14747                         printf("%s\n", tdb_errorstr(t));
14748                 }
14749                 v += 1;
14750                 printf("\r%u", v);
14751
14752                 data = tdb_fetch(t, val);
14753                 if (data.dptr != NULL) {
14754                         SAFE_FREE(data.dptr);
14755                 }
14756         }
14757         return true;
14758 }
14759
14760 static bool run_local_canonicalize_path(int dummy)
14761 {
14762         const char *src[] = {
14763                         "/foo/..",
14764                         "/..",
14765                         "/foo/bar/../baz",
14766                         "/foo/././",
14767                         "/../foo",
14768                         ".././././",
14769                         ".././././../../../boo",
14770                         "./..",
14771                         "/",
14772                         "/../../",
14773                         "/foo/../",
14774                         "/./././",
14775                         "/./././.",
14776                         "/.../././.",
14777                         "/./././.foo",
14778                         "/./././.foo.",
14779                         "/./././foo.",
14780                         "/foo/bar/..",
14781                         "/foo/bar/../baz/",
14782                         "////////////////",
14783                         "/////////./././././.",
14784                         "/./.././../.boo/../baz",
14785                         "/a/component/path",
14786                         "/a/component/path/",
14787                         "/a/component/path/..",
14788                         "/a/component/../path/",
14789                         "///a/./././///component/../////path/",
14790                         NULL
14791                         };
14792         const char *dst[] = {
14793                         "/",
14794                         "/",
14795                         "/foo/baz",
14796                         "/foo",
14797                         "/foo",
14798                         "/",
14799                         "/boo",
14800                         "/",
14801                         "/",
14802                         "/",
14803                         "/",
14804                         "/",
14805                         "/",
14806                         "/...",
14807                         "/.foo",
14808                         "/.foo.",
14809                         "/foo.",
14810                         "/foo",
14811                         "/foo/baz",
14812                         "/",
14813                         "/",
14814                         "/baz",
14815                         "/a/component/path",
14816                         "/a/component/path",
14817                         "/a/component",
14818                         "/a/path",
14819                         "/a/path",
14820                         NULL
14821                         };
14822         unsigned int i;
14823
14824         for (i = 0; src[i] != NULL; i++) {
14825                 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14826                 if (d == NULL) {
14827                         perror("talloc fail\n");
14828                         return false;
14829                 }
14830                 if (strcmp(d, dst[i]) != 0) {
14831                         d_fprintf(stderr,
14832                                 "canonicalize mismatch %s -> %s != %s",
14833                                 src[i], d, dst[i]);
14834                         return false;
14835                 }
14836                 talloc_free(d);
14837         }
14838         return true;
14839 }
14840 struct session_setup_nt1_truncated_state {
14841         uint16_t vwv[13];
14842         uint8_t bytes[20];
14843 };
14844
14845 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq);
14846
14847 static struct tevent_req *smb1_session_setup_nt1_truncated_send(
14848                 TALLOC_CTX *mem_ctx,
14849                 struct tevent_context *ev,
14850                 struct smbXcli_conn *conn)
14851 {
14852         uint16_t *vwv = NULL;
14853         uint8_t *bytes = NULL;
14854         const char *pass = "12345678";
14855         const char *uname = "z";
14856         struct session_setup_nt1_truncated_state *state = NULL;
14857         struct tevent_req *req = NULL;
14858         struct tevent_req *subreq = NULL;
14859
14860         req = tevent_req_create(mem_ctx,
14861                                 &state,
14862                                 struct session_setup_nt1_truncated_state);
14863         if (req == NULL) {
14864                 return NULL;
14865         }
14866         vwv = &state->vwv[0];
14867         bytes = &state->bytes[0];
14868
14869         SCVAL(vwv+0,  0, 0xff);
14870         SCVAL(vwv+0,  1, 0);
14871         SSVAL(vwv+1,  0, 0);
14872         SSVAL(vwv+2,  0, 8192);
14873         SSVAL(vwv+3,  0, 2);
14874         SSVAL(vwv+4,  0, 1);
14875         SIVAL(vwv+5,  0, 0);
14876         SSVAL(vwv+7,  0, strlen(pass)); /* OEMPasswordLen */
14877         SSVAL(vwv+8,  0, 0); /* UnicodePasswordLen */
14878         SSVAL(vwv+9,  0, 0); /* reserved */
14879         SSVAL(vwv+10, 0, 0); /* reserved */
14880         SIVAL(vwv+11, 0, CAP_STATUS32);
14881
14882         memcpy(bytes, pass, strlen(pass));
14883         bytes += strlen(pass);
14884         memcpy(bytes, uname, strlen(uname)+1);
14885
14886         subreq = smb1cli_req_send(state, ev, conn,
14887                                   SMBsesssetupX,
14888                                   0, /*  additional_flags */
14889                                   0, /*  clear_flags */
14890                                   0, /*  additional_flags2 */
14891                                   0, /*  clear_flags2 */
14892                                   10000, /* timeout_msec */
14893                                   getpid(),
14894                                   NULL, /* tcon */
14895                                   NULL, /* session */
14896                                   13, /* wct */
14897                                   state->vwv,
14898                                   strlen(pass), /* Truncate length at password. */
14899                                   state->bytes);
14900         if (tevent_req_nomem(subreq, req)) {
14901                 return tevent_req_post(req, ev);
14902         }
14903         tevent_req_set_callback(subreq,
14904                                 smb1_session_setup_nt1_truncated_done,
14905                                 req);
14906         return req;
14907 }
14908
14909 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq)
14910 {
14911         struct tevent_req *req =
14912                 tevent_req_callback_data(subreq,
14913                 struct tevent_req);
14914         struct session_setup_nt1_truncated_state *state =
14915                 tevent_req_data(req,
14916                 struct session_setup_nt1_truncated_state);
14917         NTSTATUS status;
14918         struct smb1cli_req_expected_response expected[] = {
14919         {
14920                 .status = NT_STATUS_OK,
14921                 .wct    = 3,
14922         },
14923         };
14924
14925         status = smb1cli_req_recv(subreq, state,
14926                                   NULL,
14927                                   NULL,
14928                                   NULL,
14929                                   NULL,
14930                                   NULL, /* pvwv_offset */
14931                                   NULL,
14932                                   NULL,
14933                                   NULL, /* pbytes_offset */
14934                                   NULL,
14935                                   expected, ARRAY_SIZE(expected));
14936         TALLOC_FREE(subreq);
14937         if (tevent_req_nterror(req, status)) {
14938                 return;
14939         }
14940         tevent_req_done(req);
14941 }
14942
14943 static NTSTATUS smb1_session_setup_nt1_truncated_recv(struct tevent_req *req)
14944 {
14945         return tevent_req_simple_recv_ntstatus(req);
14946 }
14947
14948 static bool run_smb1_truncated_sesssetup(int dummy)
14949 {
14950         struct tevent_context *ev;
14951         struct tevent_req *req;
14952         struct smbXcli_conn *conn;
14953         struct sockaddr_storage ss;
14954         NTSTATUS status;
14955         int fd;
14956         bool ok;
14957
14958         printf("Starting send truncated SMB1 sesssetup.\n");
14959
14960         ok = resolve_name(host, &ss, 0x20, true);
14961         if (!ok) {
14962                 d_fprintf(stderr, "Could not resolve name %s\n", host);
14963                 return false;
14964         }
14965
14966         status = open_socket_out(&ss, 445, 10000, &fd);
14967         if (!NT_STATUS_IS_OK(status)) {
14968                 d_fprintf(stderr, "open_socket_out failed: %s\n",
14969                           nt_errstr(status));
14970                 return false;
14971         }
14972
14973         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14974                                    NULL, 0, NULL);
14975         if (conn == NULL) {
14976                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14977                 return false;
14978         }
14979
14980         status = smbXcli_negprot(conn,
14981                                  0,
14982                                  PROTOCOL_NT1,
14983                                  PROTOCOL_NT1,
14984                                  NULL,
14985                                  NULL,
14986                                  NULL);
14987         if (!NT_STATUS_IS_OK(status)) {
14988                 d_fprintf(stderr, "smbXcli_negprot failed!\n");
14989                 return false;
14990         }
14991
14992         ev = samba_tevent_context_init(talloc_tos());
14993         if (ev == NULL) {
14994                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14995                 return false;
14996         }
14997
14998         req = smb1_session_setup_nt1_truncated_send(ev, ev, conn);
14999         if (req == NULL) {
15000                 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_send failed\n");
15001                 return false;
15002         }
15003
15004         ok = tevent_req_poll_ntstatus(req, ev, &status);
15005         if (!ok) {
15006                 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
15007                         nt_errstr(status));
15008                 return false;
15009         }
15010
15011         status = smb1_session_setup_nt1_truncated_recv(req);
15012         if (!NT_STATUS_IS_OK(status)) {
15013                 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_recv returned "
15014                           "%s, expected NT_STATUS_OK\n",
15015                           nt_errstr(status));
15016                 return false;
15017         }
15018
15019         TALLOC_FREE(conn);
15020         return true;
15021 }
15022
15023 struct smb1_negotiate_exit_state {
15024         int dummy;
15025 };
15026
15027 static void smb1_negotiate_exit_done(struct tevent_req *subreq);
15028
15029 static struct tevent_req *smb1_negotiate_exit_send(
15030                 TALLOC_CTX *mem_ctx,
15031                 struct tevent_context *ev,
15032                 struct smbXcli_conn *conn)
15033 {
15034         struct smb1_negotiate_exit_state *state = NULL;
15035         struct tevent_req *req = NULL;
15036         struct tevent_req *subreq = NULL;
15037
15038         req = tevent_req_create(mem_ctx,
15039                                 &state,
15040                                 struct smb1_negotiate_exit_state);
15041         if (req == NULL) {
15042                 return NULL;
15043         }
15044         subreq = smb1cli_req_send(state, ev, conn,
15045                                   SMBexit,
15046                                   0, /*  additional_flags */
15047                                   0, /*  clear_flags */
15048                                   0, /*  additional_flags2 */
15049                                   0, /*  clear_flags2 */
15050                                   10000, /* timeout_msec */
15051                                   getpid(),
15052                                   NULL, /* tcon */
15053                                   NULL, /* session */
15054                                   0, /* wct */
15055                                   NULL,
15056                                   0,
15057                                   NULL);
15058         if (tevent_req_nomem(subreq, req)) {
15059                 return tevent_req_post(req, ev);
15060         }
15061         tevent_req_set_callback(subreq,
15062                                 smb1_negotiate_exit_done,
15063                                 req);
15064         return req;
15065 }
15066
15067 static void smb1_negotiate_exit_done(struct tevent_req *subreq)
15068 {
15069         struct tevent_req *req =
15070                 tevent_req_callback_data(subreq,
15071                 struct tevent_req);
15072         struct smb1_negotiate_exit_state *state =
15073                 tevent_req_data(req,
15074                 struct smb1_negotiate_exit_state);
15075         NTSTATUS status;
15076         struct smb1cli_req_expected_response expected[] = {
15077         {
15078                 .status = NT_STATUS_OK,
15079                 .wct    = 0,
15080         },
15081         };
15082
15083         status = smb1cli_req_recv(subreq, state,
15084                                   NULL,
15085                                   NULL,
15086                                   NULL,
15087                                   NULL,
15088                                   NULL, /* pvwv_offset */
15089                                   NULL,
15090                                   NULL,
15091                                   NULL, /* pbytes_offset */
15092                                   NULL,
15093                                   expected, ARRAY_SIZE(expected));
15094         TALLOC_FREE(subreq);
15095         if (tevent_req_nterror(req, status)) {
15096                 return;
15097         }
15098         tevent_req_done(req);
15099 }
15100
15101 static NTSTATUS smb1_negotiate_exit_recv(struct tevent_req *req)
15102 {
15103         return tevent_req_simple_recv_ntstatus(req);
15104 }
15105
15106 static bool do_smb1_exit(TALLOC_CTX *mem_ctx,
15107                          struct tevent_context *ev,
15108                          struct smbXcli_conn *conn)
15109 {
15110         struct tevent_req *req;
15111         bool ok;
15112         NTSTATUS status;
15113         NTSTATUS expected_status = NT_STATUS_DOS(ERRSRV, ERRinvnid);;
15114
15115         req = smb1_negotiate_exit_send(ev, ev, conn);
15116         if (req == NULL) {
15117                 d_fprintf(stderr, "smb1_negotiate_exit_send failed\n");
15118                 return false;
15119         }
15120
15121         ok = tevent_req_poll_ntstatus(req, ev, &status);
15122         if (!ok) {
15123                 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
15124                         nt_errstr(status));
15125                 return false;
15126         }
15127
15128         status = smb1_negotiate_exit_recv(req);
15129         if (!NT_STATUS_EQUAL(status, expected_status)) {
15130                 d_fprintf(stderr, "smb1_negotiate_exit_recv returned "
15131                           "%s, expected ERRSRV, ERRinvnid\n",
15132                           nt_errstr(status));
15133                 return false;
15134         }
15135         return true;
15136 }
15137
15138 static bool run_smb1_negotiate_exit(int dummy)
15139 {
15140         struct tevent_context *ev;
15141         struct smbXcli_conn *conn;
15142         struct sockaddr_storage ss;
15143         NTSTATUS status;
15144         int fd;
15145         bool ok;
15146
15147         printf("Starting send SMB1 negotiate+exit.\n");
15148
15149         ok = resolve_name(host, &ss, 0x20, true);
15150         if (!ok) {
15151                 d_fprintf(stderr, "Could not resolve name %s\n", host);
15152                 return false;
15153         }
15154
15155         status = open_socket_out(&ss, 445, 10000, &fd);
15156         if (!NT_STATUS_IS_OK(status)) {
15157                 d_fprintf(stderr, "open_socket_out failed: %s\n",
15158                           nt_errstr(status));
15159                 return false;
15160         }
15161
15162         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15163                                    NULL, 0, NULL);
15164         if (conn == NULL) {
15165                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15166                 return false;
15167         }
15168
15169         status = smbXcli_negprot(conn,
15170                                  0,
15171                                  PROTOCOL_NT1,
15172                                  PROTOCOL_NT1,
15173                                  NULL,
15174                                  NULL,
15175                                  NULL);
15176         if (!NT_STATUS_IS_OK(status)) {
15177                 d_fprintf(stderr, "smbXcli_negprot failed!\n");
15178                 return false;
15179         }
15180
15181         ev = samba_tevent_context_init(talloc_tos());
15182         if (ev == NULL) {
15183                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15184                 return false;
15185         }
15186
15187         /*
15188          * Call do_smb1_exit twice to catch a server crash, the
15189          * server sends the first return code then crashes.
15190          */
15191         ok = do_smb1_exit(ev, ev, conn);
15192         if (!ok) {
15193                 d_fprintf(stderr, "do_smb1_exit (1) failed\n");
15194                 return false;
15195         }
15196         ok = do_smb1_exit(ev, ev, conn);
15197         if (!ok) {
15198                 d_fprintf(stderr, "do_smb1_exit (2) failed\n");
15199                 return false;
15200         }
15201
15202         TALLOC_FREE(conn);
15203         return true;
15204 }
15205
15206 static bool run_smb1_negotiate_tcon(int dummy)
15207 {
15208         struct cli_state *cli = NULL;
15209         uint16_t cnum = 0;
15210         uint16_t max_xmit = 0;
15211         NTSTATUS status;
15212
15213         printf("Starting send SMB1 negotiate+tcon.\n");
15214         cli = open_nbt_connection();
15215         if (cli == NULL) {
15216                 d_fprintf(stderr, "open_nbt_connection failed!\n");
15217                 return false;
15218         }
15219         smbXcli_conn_set_sockopt(cli->conn, sockops);
15220
15221         status = smbXcli_negprot(cli->conn,
15222                                  0,
15223                                  PROTOCOL_NT1,
15224                                  PROTOCOL_NT1,
15225                                  NULL,
15226                                  NULL,
15227                                  NULL);
15228         if (!NT_STATUS_IS_OK(status)) {
15229                 d_fprintf(stderr, "smbXcli_negprot failed %s!\n",
15230                         nt_errstr(status));
15231                 return false;
15232         }
15233         status = cli_raw_tcon(cli,
15234                               share,
15235                               "",
15236                               "?????",
15237                               &max_xmit,
15238                               &cnum);
15239         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
15240                 d_fprintf(stderr, "cli_raw_tcon failed - got %s "
15241                         "(should get NT_STATUS_ACCESS_DENIED)!\n",
15242                         nt_errstr(status));
15243                 return false;
15244         }
15245         return true;
15246 }
15247
15248 static bool run_ign_bad_negprot(int dummy)
15249 {
15250         struct tevent_context *ev;
15251         struct tevent_req *req;
15252         struct smbXcli_conn *conn;
15253         struct sockaddr_storage ss;
15254         NTSTATUS status;
15255         int fd;
15256         bool ok;
15257
15258         printf("starting ignore bad negprot\n");
15259
15260         ok = resolve_name(host, &ss, 0x20, true);
15261         if (!ok) {
15262                 d_fprintf(stderr, "Could not resolve name %s\n", host);
15263                 return false;
15264         }
15265
15266         status = open_socket_out(&ss, 445, 10000, &fd);
15267         if (!NT_STATUS_IS_OK(status)) {
15268                 d_fprintf(stderr, "open_socket_out failed: %s\n",
15269                           nt_errstr(status));
15270                 return false;
15271         }
15272
15273         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15274                                    NULL, 0, NULL);
15275         if (conn == NULL) {
15276                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15277                 return false;
15278         }
15279
15280         status = smbXcli_negprot(conn,
15281                                  0,
15282                                  PROTOCOL_CORE,
15283                                  PROTOCOL_CORE,
15284                                  NULL,
15285                                  NULL,
15286                                  NULL);
15287         if (NT_STATUS_IS_OK(status)) {
15288                 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
15289                 return false;
15290         }
15291
15292         ev = samba_tevent_context_init(talloc_tos());
15293         if (ev == NULL) {
15294                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15295                 return false;
15296         }
15297
15298         req = smb1cli_session_setup_nt1_send(
15299                 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
15300                 data_blob_null, data_blob_null, 0x40,
15301                 "Windows 2000 2195", "Windows 2000 5.0");
15302         if (req == NULL) {
15303                 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
15304                 return false;
15305         }
15306
15307         ok = tevent_req_poll_ntstatus(req, ev, &status);
15308         if (!ok) {
15309                 d_fprintf(stderr, "tevent_req_poll failed\n");
15310                 return false;
15311         }
15312
15313         status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
15314                                                 NULL, NULL);
15315         if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
15316                 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
15317                           "%s, expected NT_STATUS_CONNECTION_RESET\n",
15318                           nt_errstr(status));
15319                 return false;
15320         }
15321
15322         TALLOC_FREE(conn);
15323
15324         printf("starting ignore bad negprot\n");
15325
15326         return true;
15327 }
15328
15329
15330 static double create_procs(bool (*fn)(int), bool *result)
15331 {
15332         int i, status;
15333         volatile pid_t *child_status;
15334         volatile bool *child_status_out;
15335         int synccount;
15336         int tries = 8;
15337         struct timeval start;
15338
15339         synccount = 0;
15340
15341         child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
15342         if (!child_status) {
15343                 printf("Failed to setup shared memory\n");
15344                 return -1;
15345         }
15346
15347         child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
15348         if (!child_status_out) {
15349                 printf("Failed to setup result status shared memory\n");
15350                 return -1;
15351         }
15352
15353         for (i = 0; i < torture_nprocs; i++) {
15354                 child_status[i] = 0;
15355                 child_status_out[i] = True;
15356         }
15357
15358         start = timeval_current();
15359
15360         for (i=0;i<torture_nprocs;i++) {
15361                 procnum = i;
15362                 if (fork() == 0) {
15363                         pid_t mypid = getpid();
15364                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
15365
15366                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
15367
15368                         while (1) {
15369                                 if (torture_open_connection(&current_cli, i)) break;
15370                                 if (tries-- == 0) {
15371                                         printf("pid %d failed to start\n", (int)getpid());
15372                                         _exit(1);
15373                                 }
15374                                 smb_msleep(10);
15375                         }
15376
15377                         child_status[i] = getpid();
15378
15379                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
15380
15381                         child_status_out[i] = fn(i);
15382                         _exit(0);
15383                 }
15384         }
15385
15386         do {
15387                 synccount = 0;
15388                 for (i=0;i<torture_nprocs;i++) {
15389                         if (child_status[i]) synccount++;
15390                 }
15391                 if (synccount == torture_nprocs) break;
15392                 smb_msleep(10);
15393         } while (timeval_elapsed(&start) < 30);
15394
15395         if (synccount != torture_nprocs) {
15396                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
15397                 *result = False;
15398                 return timeval_elapsed(&start);
15399         }
15400
15401         /* start the client load */
15402         start = timeval_current();
15403
15404         for (i=0;i<torture_nprocs;i++) {
15405                 child_status[i] = 0;
15406         }
15407
15408         printf("%d clients started\n", torture_nprocs);
15409
15410         for (i=0;i<torture_nprocs;i++) {
15411                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
15412         }
15413
15414         printf("\n");
15415
15416         for (i=0;i<torture_nprocs;i++) {
15417                 if (!child_status_out[i]) {
15418                         *result = False;
15419                 }
15420         }
15421         return timeval_elapsed(&start);
15422 }
15423
15424 #define FLAG_MULTIPROC 1
15425
15426 static struct {
15427         const char *name;
15428         bool (*fn)(int);
15429         unsigned flags;
15430 } torture_ops[] = {
15431         {
15432                 .name = "FDPASS",
15433                 .fn   = run_fdpasstest,
15434         },
15435         {
15436                 .name = "LOCK1",
15437                 .fn   = run_locktest1,
15438         },
15439         {
15440                 .name = "LOCK2",
15441                 .fn   =  run_locktest2,
15442         },
15443         {
15444                 .name = "LOCK3",
15445                 .fn   =  run_locktest3,
15446         },
15447         {
15448                 .name = "LOCK4",
15449                 .fn   =  run_locktest4,
15450         },
15451         {
15452                 .name = "LOCK5",
15453                 .fn   =  run_locktest5,
15454         },
15455         {
15456                 .name = "LOCK6",
15457                 .fn   =  run_locktest6,
15458         },
15459         {
15460                 .name = "LOCK7",
15461                 .fn   =  run_locktest7,
15462         },
15463         {
15464                 .name = "LOCK8",
15465                 .fn   =  run_locktest8,
15466         },
15467         {
15468                 .name = "LOCK9A",
15469                 .fn   =  run_locktest9a,
15470         },
15471         {
15472                 .name = "LOCK9B",
15473                 .fn   =  run_locktest9b,
15474         },
15475         {
15476                 .name = "LOCK10",
15477                 .fn   =  run_locktest10,
15478         },
15479         {
15480                 .name = "LOCK11",
15481                 .fn   =  run_locktest11,
15482         },
15483         {
15484                 .name = "LOCK12",
15485                 .fn   =  run_locktest12,
15486         },
15487         {
15488                 .name = "LOCK13",
15489                 .fn   =  run_locktest13,
15490         },
15491         {
15492                 .name = "UNLINK",
15493                 .fn   = run_unlinktest,
15494         },
15495         {
15496                 .name = "BROWSE",
15497                 .fn   = run_browsetest,
15498         },
15499         {
15500                 .name = "ATTR",
15501                 .fn   =   run_attrtest,
15502         },
15503         {
15504                 .name = "TRANS2",
15505                 .fn   = run_trans2test,
15506         },
15507         {
15508                 .name  = "MAXFID",
15509                 .fn    = run_maxfidtest,
15510                 .flags = FLAG_MULTIPROC,
15511         },
15512         {
15513                 .name  = "TORTURE",
15514                 .fn    = run_torture,
15515                 .flags = FLAG_MULTIPROC,
15516         },
15517         {
15518                 .name  = "RANDOMIPC",
15519                 .fn    = run_randomipc,
15520         },
15521         {
15522                 .name  = "NEGNOWAIT",
15523                 .fn    = run_negprot_nowait,
15524         },
15525         {
15526                 .name  = "NBENCH",
15527                 .fn    =  run_nbench,
15528         },
15529         {
15530                 .name  = "NBENCH2",
15531                 .fn    = run_nbench2,
15532         },
15533         {
15534                 .name  = "OPLOCK1",
15535                 .fn    =  run_oplock1,
15536         },
15537         {
15538                 .name  = "OPLOCK2",
15539                 .fn    =  run_oplock2,
15540         },
15541         {
15542                 .name  = "OPLOCK4",
15543                 .fn    =  run_oplock4,
15544         },
15545 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
15546         {
15547                 .name  = "OPLOCK5",
15548                 .fn    =  run_oplock5,
15549         },
15550 #endif
15551         {
15552                 .name  = "DIR",
15553                 .fn    =  run_dirtest,
15554         },
15555         {
15556                 .name  = "DIR1",
15557                 .fn    =  run_dirtest1,
15558         },
15559         {
15560                 .name  = "DIR-CREATETIME",
15561                 .fn    =  run_dir_createtime,
15562         },
15563         {
15564                 .name  = "DENY1",
15565                 .fn    =  torture_denytest1,
15566         },
15567         {
15568                 .name  = "DENY2",
15569                 .fn    =  torture_denytest2,
15570         },
15571         {
15572                 .name  = "TCON",
15573                 .fn    =  run_tcon_test,
15574         },
15575         {
15576                 .name  = "TCONDEV",
15577                 .fn    =  run_tcon_devtype_test,
15578         },
15579         {
15580                 .name  = "RW1",
15581                 .fn    =  run_readwritetest,
15582         },
15583         {
15584                 .name  = "RW2",
15585                 .fn    =  run_readwritemulti,
15586                 .flags = FLAG_MULTIPROC
15587         },
15588         {
15589                 .name  = "RW3",
15590                 .fn    =  run_readwritelarge,
15591         },
15592         {
15593                 .name  = "RW-SIGNING",
15594                 .fn    =  run_readwritelarge_signtest,
15595         },
15596         {
15597                 .name  = "OPEN",
15598                 .fn    = run_opentest,
15599         },
15600         {
15601                 .name  = "POSIX",
15602                 .fn    = run_simple_posix_open_test,
15603         },
15604         {
15605                 .name  = "POSIX-APPEND",
15606                 .fn    = run_posix_append,
15607         },
15608         {
15609                 .name  = "POSIX-SYMLINK-ACL",
15610                 .fn    = run_acl_symlink_test,
15611         },
15612         {
15613                 .name  = "POSIX-SYMLINK-EA",
15614                 .fn    = run_ea_symlink_test,
15615         },
15616         {
15617                 .name  = "POSIX-STREAM-DELETE",
15618                 .fn    = run_posix_stream_delete,
15619         },
15620         {
15621                 .name  = "POSIX-OFD-LOCK",
15622                 .fn    = run_posix_ofd_lock_test,
15623         },
15624         {
15625                 .name  = "POSIX-BLOCKING-LOCK",
15626                 .fn    = run_posix_blocking_lock,
15627         },
15628         {
15629                 .name  = "POSIX-MKDIR",
15630                 .fn    = run_posix_mkdir_test,
15631         },
15632         {
15633                 .name  = "POSIX-ACL-OPLOCK",
15634                 .fn    = run_posix_acl_oplock_test,
15635         },
15636         {
15637                 .name  = "POSIX-ACL-SHAREROOT",
15638                 .fn    = run_posix_acl_shareroot_test,
15639         },
15640         {
15641                 .name  = "POSIX-LS-WILDCARD",
15642                 .fn    = run_posix_ls_wildcard_test,
15643         },
15644         {
15645                 .name  = "POSIX-LS-SINGLE",
15646                 .fn    = run_posix_ls_single_test,
15647         },
15648         {
15649                 .name  = "POSIX-READLINK",
15650                 .fn    = run_posix_readlink_test,
15651         },
15652         {
15653                 .name  = "POSIX-STAT",
15654                 .fn    = run_posix_stat_test,
15655         },
15656         {
15657                 .name  = "POSIX-SYMLINK-PARENT",
15658                 .fn    = run_posix_symlink_parent_test,
15659         },
15660         {
15661                 .name  = "POSIX-SYMLINK-CHMOD",
15662                 .fn    = run_posix_symlink_chmod_test,
15663         },
15664         {
15665                 .name  = "POSIX-SYMLINK-RENAME",
15666                 .fn    = run_posix_symlink_rename_test,
15667         },
15668         {
15669                 .name  = "POSIX-DIR-DEFAULT-ACL",
15670                 .fn    = run_posix_dir_default_acl_test,
15671         },
15672         {
15673                 .name  = "POSIX-SYMLINK-GETPATHINFO",
15674                 .fn    = run_posix_symlink_getpathinfo_test,
15675         },
15676         {
15677                 .name  = "POSIX-SYMLINK-SETPATHINFO",
15678                 .fn    = run_posix_symlink_setpathinfo_test,
15679         },
15680         {
15681                 .name  = "WINDOWS-BAD-SYMLINK",
15682                 .fn    = run_symlink_open_test,
15683         },
15684         {
15685                 .name  = "SMB1-WILD-MANGLE-UNLINK",
15686                 .fn    = run_smb1_wild_mangle_unlink_test,
15687         },
15688         {
15689                 .name  = "SMB1-WILD-MANGLE-RENAME",
15690                 .fn    = run_smb1_wild_mangle_rename_test,
15691         },
15692         {
15693                 .name  = "CASE-INSENSITIVE-CREATE",
15694                 .fn    = run_case_insensitive_create,
15695         },
15696         {
15697                 .name  = "ASYNC-ECHO",
15698                 .fn    = run_async_echo,
15699         },
15700         {
15701                 .name  = "UID-REGRESSION-TEST",
15702                 .fn    = run_uid_regression_test,
15703         },
15704         {
15705                 .name  = "SHORTNAME-TEST",
15706                 .fn    = run_shortname_test,
15707         },
15708         {
15709                 .name  = "ADDRCHANGE",
15710                 .fn    = run_addrchange,
15711         },
15712 #if 1
15713         {
15714                 .name  = "OPENATTR",
15715                 .fn    = run_openattrtest,
15716         },
15717 #endif
15718         {
15719                 .name  = "XCOPY",
15720                 .fn    = run_xcopy,
15721         },
15722         {
15723                 .name  = "RENAME",
15724                 .fn    = run_rename,
15725         },
15726         {
15727                 .name  = "RENAME-ACCESS",
15728                 .fn    = run_rename_access,
15729         },
15730         {
15731                 .name  = "OWNER-RIGHTS",
15732                 .fn    = run_owner_rights,
15733         },
15734         {
15735                 .name  = "DELETE",
15736                 .fn    = run_deletetest,
15737         },
15738         {
15739                 .name  = "DELETE-STREAM",
15740                 .fn    = run_delete_stream,
15741         },
15742         {
15743                 .name  = "DELETE-PRINT",
15744                 .fn    = run_delete_print_test,
15745         },
15746         {
15747                 .name  = "DELETE-LN",
15748                 .fn    = run_deletetest_ln,
15749         },
15750         {
15751                 .name  = "PROPERTIES",
15752                 .fn    = run_properties,
15753         },
15754         {
15755                 .name  = "MANGLE",
15756                 .fn    = torture_mangle,
15757         },
15758         {
15759                 .name  = "MANGLE1",
15760                 .fn    = run_mangle1,
15761         },
15762         {
15763                 .name  = "MANGLE-ILLEGAL",
15764                 .fn    = run_mangle_illegal,
15765         },
15766         {
15767                 .name  = "W2K",
15768                 .fn    = run_w2ktest,
15769         },
15770         {
15771                 .name  = "TRANS2SCAN",
15772                 .fn    = torture_trans2_scan,
15773         },
15774         {
15775                 .name  = "NTTRANSSCAN",
15776                 .fn    = torture_nttrans_scan,
15777         },
15778         {
15779                 .name  = "UTABLE",
15780                 .fn    = torture_utable,
15781         },
15782         {
15783                 .name  = "CASETABLE",
15784                 .fn    = torture_casetable,
15785         },
15786         {
15787                 .name  = "ERRMAPEXTRACT",
15788                 .fn    = run_error_map_extract,
15789         },
15790         {
15791                 .name  = "PIPE_NUMBER",
15792                 .fn    = run_pipe_number,
15793         },
15794         {
15795                 .name  = "TCON2",
15796                 .fn    =  run_tcon2_test,
15797         },
15798         {
15799                 .name  = "IOCTL",
15800                 .fn    =  torture_ioctl_test,
15801         },
15802         {
15803                 .name  = "CHKPATH",
15804                 .fn    =  torture_chkpath_test,
15805         },
15806         {
15807                 .name  = "FDSESS",
15808                 .fn    = run_fdsesstest,
15809         },
15810         {
15811                 .name  = "EATEST",
15812                 .fn    = run_eatest,
15813         },
15814         {
15815                 .name  = "SESSSETUP_BENCH",
15816                 .fn    = run_sesssetup_bench,
15817         },
15818         {
15819                 .name  = "CHAIN1",
15820                 .fn    = run_chain1,
15821         },
15822         {
15823                 .name  = "CHAIN2",
15824                 .fn    = run_chain2,
15825         },
15826         {
15827                 .name  = "CHAIN3",
15828                 .fn    = run_chain3,
15829         },
15830         {
15831                 .name  = "WINDOWS-WRITE",
15832                 .fn    = run_windows_write,
15833         },
15834         {
15835                 .name  = "LARGE_READX",
15836                 .fn    = run_large_readx,
15837         },
15838         {
15839                 .name  = "MSDFS-ATTRIBUTE",
15840                 .fn    = run_msdfs_attribute,
15841         },
15842         {
15843                 .name  = "NTTRANS-CREATE",
15844                 .fn    = run_nttrans_create,
15845         },
15846         {
15847                 .name  = "NTTRANS-FSCTL",
15848                 .fn    = run_nttrans_fsctl,
15849         },
15850         {
15851                 .name  = "CLI_ECHO",
15852                 .fn    = run_cli_echo,
15853         },
15854         {
15855                 .name  = "CLI_SPLICE",
15856                 .fn    = run_cli_splice,
15857         },
15858         {
15859                 .name  = "TLDAP",
15860                 .fn    = run_tldap,
15861         },
15862         {
15863                 .name  = "STREAMERROR",
15864                 .fn    = run_streamerror,
15865         },
15866         {
15867                 .name  = "NOTIFY-BENCH",
15868                 .fn    = run_notify_bench,
15869         },
15870         {
15871                 .name  = "NOTIFY-BENCH2",
15872                 .fn    = run_notify_bench2,
15873         },
15874         {
15875                 .name  = "NOTIFY-BENCH3",
15876                 .fn    = run_notify_bench3,
15877         },
15878         {
15879                 .name  = "BAD-NBT-SESSION",
15880                 .fn    = run_bad_nbt_session,
15881         },
15882         {
15883                 .name  = "IGN-BAD-NEGPROT",
15884                 .fn    = run_ign_bad_negprot,
15885         },
15886         {
15887                 .name  = "SMB-ANY-CONNECT",
15888                 .fn    = run_smb_any_connect,
15889         },
15890         {
15891                 .name  = "NOTIFY-ONLINE",
15892                 .fn    = run_notify_online,
15893         },
15894         {
15895                 .name  = "SMB2-BASIC",
15896                 .fn    = run_smb2_basic,
15897         },
15898         {
15899                 .name  = "SMB2-NEGPROT",
15900                 .fn    = run_smb2_negprot,
15901         },
15902         {
15903                 .name  = "SMB2-ANONYMOUS",
15904                 .fn    = run_smb2_anonymous,
15905         },
15906         {
15907                 .name  = "SMB2-SESSION-RECONNECT",
15908                 .fn    = run_smb2_session_reconnect,
15909         },
15910         {
15911                 .name  = "SMB2-TCON-DEPENDENCE",
15912                 .fn    = run_smb2_tcon_dependence,
15913         },
15914         {
15915                 .name  = "SMB2-MULTI-CHANNEL",
15916                 .fn    = run_smb2_multi_channel,
15917         },
15918         {
15919                 .name  = "SMB2-SESSION-REAUTH",
15920                 .fn    = run_smb2_session_reauth,
15921         },
15922         {
15923                 .name  = "SMB2-FTRUNCATE",
15924                 .fn    = run_smb2_ftruncate,
15925         },
15926         {
15927                 .name  = "SMB2-DIR-FSYNC",
15928                 .fn    = run_smb2_dir_fsync,
15929         },
15930         {
15931                 .name  = "SMB2-PATH-SLASH",
15932                 .fn    = run_smb2_path_slash,
15933         },
15934         {
15935                 .name  = "SMB1-SYSTEM-SECURITY",
15936                 .fn    = run_smb1_system_security,
15937         },
15938         {
15939                 .name  = "SMB2-SACL",
15940                 .fn    = run_smb2_sacl,
15941         },
15942         {
15943                 .name  = "SMB2-QUOTA1",
15944                 .fn    = run_smb2_quota1,
15945         },
15946         {
15947                 .name  = "SMB2-INVALID-PIPENAME",
15948                 .fn    = run_smb2_invalid_pipename,
15949         },
15950         {
15951                 .name  = "SMB2-STREAM-ACL",
15952                 .fn    = run_smb2_stream_acl,
15953         },
15954         {
15955                 .name  = "SMB2-LIST-DIR-ASYNC",
15956                 .fn    = run_list_dir_async_test,
15957         },
15958         {
15959                 .name  = "SMB2-DEL-ON-CLOSE-NONEMPTY",
15960                 .fn    = run_delete_on_close_non_empty,
15961         },
15962         {
15963                 .name  = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15964                 .fn    = run_delete_on_close_nonwrite_delete_yes_test,
15965         },
15966         {
15967                 .name  = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15968                 .fn    = run_delete_on_close_nonwrite_delete_no_test,
15969         },
15970         {
15971                 .name  = "SMB2-DFS-PATHS",
15972                 .fn    = run_smb2_dfs_paths,
15973         },
15974         {
15975                 .name  = "SMB2-NON-DFS-SHARE",
15976                 .fn    = run_smb2_non_dfs_share,
15977         },
15978         {
15979                 .name  = "SMB2-DFS-SHARE-NON-DFS-PATH",
15980                 .fn    = run_smb2_dfs_share_non_dfs_path,
15981         },
15982         {
15983                 .name  = "SMB2-DFS-FILENAME-LEADING-BACKSLASH",
15984                 .fn    = run_smb2_dfs_filename_leading_backslash,
15985         },
15986         {
15987                 .name  = "SMB2-PIPE-READ-ASYNC-DISCONNECT",
15988                 .fn    = run_smb2_pipe_read_async_disconnect,
15989         },
15990         {
15991                 .name  = "SMB1-TRUNCATED-SESSSETUP",
15992                 .fn    = run_smb1_truncated_sesssetup,
15993         },
15994         {
15995                 .name  = "SMB1-NEGOTIATE-EXIT",
15996                 .fn    = run_smb1_negotiate_exit,
15997         },
15998         {
15999                 .name  = "SMB1-NEGOTIATE-TCON",
16000                 .fn    = run_smb1_negotiate_tcon,
16001         },
16002         {
16003                 .name  = "SMB1-DFS-PATHS",
16004                 .fn    = run_smb1_dfs_paths,
16005         },
16006         {
16007                 .name  = "SMB1-DFS-SEARCH-PATHS",
16008                 .fn    = run_smb1_dfs_search_paths,
16009         },
16010         {
16011                 .name  = "SMB1-DFS-OPERATIONS",
16012                 .fn    = run_smb1_dfs_operations,
16013         },
16014         {
16015                 .name  = "SMB1-DFS-BADPATH",
16016                 .fn    = run_smb1_dfs_check_badpath,
16017         },
16018         {
16019                 .name  = "CLEANUP1",
16020                 .fn    = run_cleanup1,
16021         },
16022         {
16023                 .name  = "CLEANUP2",
16024                 .fn    = run_cleanup2,
16025         },
16026         {
16027                 .name  = "CLEANUP4",
16028                 .fn    = run_cleanup4,
16029         },
16030         {
16031                 .name  = "OPLOCK-CANCEL",
16032                 .fn    = run_oplock_cancel,
16033         },
16034         {
16035                 .name  = "PIDHIGH",
16036                 .fn    = run_pidhigh,
16037         },
16038         {
16039                 .name  = "LOCAL-SUBSTITUTE",
16040                 .fn    = run_local_substitute,
16041         },
16042         {
16043                 .name  = "LOCAL-GENCACHE",
16044                 .fn    = run_local_gencache,
16045         },
16046         {
16047                 .name  = "LOCAL-DBWRAP-WATCH1",
16048                 .fn    = run_dbwrap_watch1,
16049         },
16050         {
16051                 .name  = "LOCAL-DBWRAP-WATCH2",
16052                 .fn    = run_dbwrap_watch2,
16053         },
16054         {
16055                 .name  = "LOCAL-DBWRAP-WATCH3",
16056                 .fn    = run_dbwrap_watch3,
16057         },
16058         {
16059                 .name  = "LOCAL-DBWRAP-WATCH4",
16060                 .fn    = run_dbwrap_watch4,
16061         },
16062         {
16063                 .name  = "LOCAL-DBWRAP-DO-LOCKED1",
16064                 .fn    = run_dbwrap_do_locked1,
16065         },
16066         {
16067                 .name  = "LOCAL-MESSAGING-READ1",
16068                 .fn    = run_messaging_read1,
16069         },
16070         {
16071                 .name  = "LOCAL-MESSAGING-READ2",
16072                 .fn    = run_messaging_read2,
16073         },
16074         {
16075                 .name  = "LOCAL-MESSAGING-READ3",
16076                 .fn    = run_messaging_read3,
16077         },
16078         {
16079                 .name  = "LOCAL-MESSAGING-READ4",
16080                 .fn    = run_messaging_read4,
16081         },
16082         {
16083                 .name  = "LOCAL-MESSAGING-FDPASS1",
16084                 .fn    = run_messaging_fdpass1,
16085         },
16086         {
16087                 .name  = "LOCAL-MESSAGING-FDPASS2",
16088                 .fn    = run_messaging_fdpass2,
16089         },
16090         {
16091                 .name  = "LOCAL-MESSAGING-FDPASS2a",
16092                 .fn    = run_messaging_fdpass2a,
16093         },
16094         {
16095                 .name  = "LOCAL-MESSAGING-FDPASS2b",
16096                 .fn    = run_messaging_fdpass2b,
16097         },
16098         {
16099                 .name  = "LOCAL-MESSAGING-SEND-ALL",
16100                 .fn    = run_messaging_send_all,
16101         },
16102         {
16103                 .name  = "LOCAL-BASE64",
16104                 .fn    = run_local_base64,
16105         },
16106         {
16107                 .name  = "LOCAL-RBTREE",
16108                 .fn    = run_local_rbtree,
16109         },
16110         {
16111                 .name  = "LOCAL-MEMCACHE",
16112                 .fn    = run_local_memcache,
16113         },
16114         {
16115                 .name  = "LOCAL-STREAM-NAME",
16116                 .fn    = run_local_stream_name,
16117         },
16118         {
16119                 .name  = "LOCAL-STR-MATCH-MSWILD",
16120                 .fn    = run_str_match_mswild,
16121         },
16122         {
16123                 .name  = "LOCAL-STR-MATCH-REGEX-SUB1",
16124                 .fn    = run_str_match_regex_sub1,
16125         },
16126         {
16127                 .name  = "WBCLIENT-MULTI-PING",
16128                 .fn    = run_wbclient_multi_ping,
16129         },
16130         {
16131                 .name  = "LOCAL-string_to_sid",
16132                 .fn    = run_local_string_to_sid,
16133         },
16134         {
16135                 .name  = "LOCAL-sid_to_string",
16136                 .fn    = run_local_sid_to_string,
16137         },
16138         {
16139                 .name  = "LOCAL-binary_to_sid",
16140                 .fn    = run_local_binary_to_sid,
16141         },
16142         {
16143                 .name  = "LOCAL-DBTRANS",
16144                 .fn    = run_local_dbtrans,
16145         },
16146         {
16147                 .name  = "LOCAL-TEVENT-POLL",
16148                 .fn    = run_local_tevent_poll,
16149         },
16150         {
16151                 .name  = "LOCAL-CONVERT-STRING",
16152                 .fn    = run_local_convert_string,
16153         },
16154         {
16155                 .name  = "LOCAL-CONV-AUTH-INFO",
16156                 .fn    = run_local_conv_auth_info,
16157         },
16158         {
16159                 .name  = "LOCAL-hex_encode_buf",
16160                 .fn    = run_local_hex_encode_buf,
16161         },
16162         {
16163                 .name  = "LOCAL-IDMAP-TDB-COMMON",
16164                 .fn    = run_idmap_tdb_common_test,
16165         },
16166         {
16167                 .name  = "LOCAL-remove_duplicate_addrs2",
16168                 .fn    = run_local_remove_duplicate_addrs2,
16169         },
16170         {
16171                 .name  = "local-tdb-opener",
16172                 .fn    = run_local_tdb_opener,
16173         },
16174         {
16175                 .name  = "local-tdb-writer",
16176                 .fn    = run_local_tdb_writer,
16177         },
16178         {
16179                 .name  = "LOCAL-DBWRAP-CTDB1",
16180                 .fn    = run_local_dbwrap_ctdb1,
16181         },
16182         {
16183                 .name  = "LOCAL-BENCH-PTHREADPOOL",
16184                 .fn    = run_bench_pthreadpool,
16185         },
16186         {
16187                 .name  = "LOCAL-PTHREADPOOL-TEVENT",
16188                 .fn    = run_pthreadpool_tevent,
16189         },
16190         {
16191                 .name  = "LOCAL-G-LOCK1",
16192                 .fn    = run_g_lock1,
16193         },
16194         {
16195                 .name  = "LOCAL-G-LOCK2",
16196                 .fn    = run_g_lock2,
16197         },
16198         {
16199                 .name  = "LOCAL-G-LOCK3",
16200                 .fn    = run_g_lock3,
16201         },
16202         {
16203                 .name  = "LOCAL-G-LOCK4",
16204                 .fn    = run_g_lock4,
16205         },
16206         {
16207                 .name  = "LOCAL-G-LOCK4A",
16208                 .fn    = run_g_lock4a,
16209         },
16210         {
16211                 .name  = "LOCAL-G-LOCK5",
16212                 .fn    = run_g_lock5,
16213         },
16214         {
16215                 .name  = "LOCAL-G-LOCK6",
16216                 .fn    = run_g_lock6,
16217         },
16218         {
16219                 .name  = "LOCAL-G-LOCK7",
16220                 .fn    = run_g_lock7,
16221         },
16222         {
16223                 .name  = "LOCAL-G-LOCK8",
16224                 .fn    = run_g_lock8,
16225         },
16226         {
16227                 .name  = "LOCAL-G-LOCK-PING-PONG",
16228                 .fn    = run_g_lock_ping_pong,
16229         },
16230         {
16231                 .name  = "LOCAL-CANONICALIZE-PATH",
16232                 .fn    = run_local_canonicalize_path,
16233         },
16234         {
16235                 .name  = "LOCAL-NAMEMAP-CACHE1",
16236                 .fn    = run_local_namemap_cache1,
16237         },
16238         {
16239                 .name  = "LOCAL-IDMAP-CACHE1",
16240                 .fn    = run_local_idmap_cache1,
16241         },
16242         {
16243                 .name  = "qpathinfo-bufsize",
16244                 .fn    = run_qpathinfo_bufsize,
16245         },
16246         {
16247                 .name  = "hide-new-files-timeout",
16248                 .fn    = run_hidenewfiles,
16249         },
16250         {
16251                 .name  = "hide-new-files-timeout-showdirs",
16252                 .fn    = run_hidenewfiles_showdirs,
16253         },
16254 #ifdef CLUSTER_SUPPORT
16255         {
16256                 .name  = "ctdbd-conn1",
16257                 .fn    = run_ctdbd_conn1,
16258         },
16259 #endif
16260         {
16261                 .name  = "readdir-timestamp",
16262                 .fn    = run_readdir_timestamp,
16263         },
16264         {
16265                 .name  = "rpc-scale",
16266                 .fn    = run_rpc_scale,
16267         },
16268         {
16269                 .name  = "LOCAL-TDB-VALIDATE",
16270                 .fn    = run_tdb_validate,
16271         },
16272         {
16273                 .name = NULL,
16274         },
16275 };
16276
16277 /****************************************************************************
16278 run a specified test or "ALL"
16279 ****************************************************************************/
16280 static bool run_test(const char *name)
16281 {
16282         bool ret = True;
16283         bool result = True;
16284         bool found = False;
16285         int i;
16286         double t;
16287         if (strequal(name,"ALL")) {
16288                 for (i=0;torture_ops[i].name;i++) {
16289                         run_test(torture_ops[i].name);
16290                 }
16291                 found = True;
16292         }
16293
16294         for (i=0;torture_ops[i].name;i++) {
16295                 fstr_sprintf(randomfname, "\\XX%x",
16296                          (unsigned)random());
16297
16298                 if (strequal(name, torture_ops[i].name)) {
16299                         found = True;
16300                         printf("Running %s\n", name);
16301                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
16302                                 t = create_procs(torture_ops[i].fn, &result);
16303                                 if (!result) {
16304                                         ret = False;
16305                                         printf("TEST %s FAILED!\n", name);
16306                                 }
16307                         } else {
16308                                 struct timeval start;
16309                                 start = timeval_current();
16310                                 if (!torture_ops[i].fn(0)) {
16311                                         ret = False;
16312                                         printf("TEST %s FAILED!\n", name);
16313                                 }
16314                                 t = timeval_elapsed(&start);
16315                         }
16316                         printf("%s took %g secs\n\n", name, t);
16317                 }
16318         }
16319
16320         if (!found) {
16321                 printf("Did not find a test named %s\n", name);
16322                 ret = False;
16323         }
16324
16325         return ret;
16326 }
16327
16328
16329 static void usage(void)
16330 {
16331         int i;
16332
16333         printf("WARNING samba4 test suite is much more complete nowadays.\n");
16334         printf("Please use samba4 torture.\n\n");
16335
16336         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
16337
16338         printf("\t-d debuglevel\n");
16339         printf("\t-U user%%pass\n");
16340         printf("\t-k                    use kerberos\n");
16341         printf("\t-N numprocs\n");
16342         printf("\t-n my_netbios_name\n");
16343         printf("\t-W workgroup\n");
16344         printf("\t-o num_operations\n");
16345         printf("\t-O socket_options\n");
16346         printf("\t-m maximum protocol\n");
16347         printf("\t-L use oplocks\n");
16348         printf("\t-c CLIENT.TXT         specify client load file for NBENCH\n");
16349         printf("\t-A showall\n");
16350         printf("\t-p port\n");
16351         printf("\t-s seed\n");
16352         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
16353         printf("\t-f filename           filename to test\n");
16354         printf("\t-e                    encrypt\n");
16355         printf("\t-T 'OPTION=VALUE'     smb.conf option line\n");
16356         printf("\n\n");
16357
16358         printf("tests are:");
16359         for (i=0;torture_ops[i].name;i++) {
16360                 printf(" %s", torture_ops[i].name);
16361         }
16362         printf("\n");
16363
16364         printf("default test is ALL\n");
16365
16366         exit(1);
16367 }
16368
16369 /****************************************************************************
16370   main program
16371 ****************************************************************************/
16372  int main(int argc,char *argv[])
16373 {
16374         int opt, i;
16375         char *p;
16376         int gotuser = 0;
16377         int gotpass = 0;
16378         bool correct = True;
16379         TALLOC_CTX *frame = talloc_stackframe();
16380         int seed = time(NULL);
16381         struct loadparm_context *lp_ctx = NULL;
16382
16383 #ifdef HAVE_SETBUFFER
16384         setbuffer(stdout, NULL, 0);
16385 #endif
16386
16387         setup_logging("smbtorture", DEBUG_STDOUT);
16388
16389         smb_init_locale();
16390         fault_setup();
16391
16392         lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
16393         if (lp_ctx == NULL) {
16394                 fprintf(stderr,
16395                         "Failed to initialise the global parameter structure.\n");
16396                 return 1;
16397         }
16398
16399         if (is_default_dyn_CONFIGFILE()) {
16400                 if(getenv("SMB_CONF_PATH")) {
16401                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
16402                 }
16403         }
16404         lp_load_global(get_dyn_CONFIGFILE());
16405         load_interfaces();
16406
16407         if (argc < 2) {
16408                 usage();
16409         }
16410
16411         for(p = argv[1]; *p; p++)
16412           if(*p == '\\')
16413             *p = '/';
16414
16415         if (strncmp(argv[1], "//", 2)) {
16416                 usage();
16417         }
16418
16419         fstrcpy(host, &argv[1][2]);
16420         p = strchr_m(&host[2],'/');
16421         if (!p) {
16422                 usage();
16423         }
16424         *p = 0;
16425         fstrcpy(share, p+1);
16426
16427         fstrcpy(myname, get_myname(talloc_tos()));
16428         if (!*myname) {
16429                 fprintf(stderr, "Failed to get my hostname.\n");
16430                 return 1;
16431         }
16432
16433         if (*username == 0 && getenv("LOGNAME")) {
16434           fstrcpy(username,getenv("LOGNAME"));
16435         }
16436
16437         argc--;
16438         argv++;
16439
16440         fstrcpy(workgroup, lp_workgroup());
16441
16442         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:T:"))
16443                != EOF) {
16444                 switch (opt) {
16445                 case 'p':
16446                         port_to_use = atoi(optarg);
16447                         break;
16448                 case 's':
16449                         seed = atoi(optarg);
16450                         break;
16451                 case 'W':
16452                         fstrcpy(workgroup,optarg);
16453                         break;
16454                 case 'm':
16455                         lpcfg_set_cmdline(lp_ctx, "client max protocol", optarg);
16456                         break;
16457                 case 'N':
16458                         torture_nprocs = atoi(optarg);
16459                         break;
16460                 case 'o':
16461                         torture_numops = atoi(optarg);
16462                         break;
16463                 case 'd':
16464                         lpcfg_set_cmdline(lp_ctx, "log level", optarg);
16465                         break;
16466                 case 'O':
16467                         sockops = optarg;
16468                         break;
16469                 case 'L':
16470                         use_oplocks = True;
16471                         break;
16472                 case 'l':
16473                         local_path = optarg;
16474                         break;
16475                 case 'A':
16476                         torture_showall = True;
16477                         break;
16478                 case 'n':
16479                         fstrcpy(myname, optarg);
16480                         break;
16481                 case 'c':
16482                         client_txt = optarg;
16483                         break;
16484                 case 'e':
16485                         do_encrypt = true;
16486                         break;
16487                 case 'k':
16488 #ifdef HAVE_KRB5
16489                         use_kerberos = True;
16490 #else
16491                         d_printf("No kerberos support compiled in\n");
16492                         exit(1);
16493 #endif
16494                         break;
16495                 case 'U':
16496                         gotuser = 1;
16497                         fstrcpy(username,optarg);
16498                         p = strchr_m(username,'%');
16499                         if (p) {
16500                                 *p = 0;
16501                                 fstrcpy(password, p+1);
16502                                 gotpass = 1;
16503                         }
16504                         break;
16505                 case 'b':
16506                         fstrcpy(multishare_conn_fname, optarg);
16507                         use_multishare_conn = True;
16508                         break;
16509                 case 'B':
16510                         torture_blocksize = atoi(optarg);
16511                         break;
16512                 case 'f':
16513                         test_filename = SMB_STRDUP(optarg);
16514                         break;
16515                 case 'T':
16516                         lpcfg_set_option(lp_ctx, optarg);
16517                         break;
16518                 default:
16519                         printf("Unknown option %c (%d)\n", (char)opt, opt);
16520                         usage();
16521                 }
16522         }
16523
16524         d_printf("using seed %d\n", seed);
16525
16526         srandom(seed);
16527
16528         if(use_kerberos && !gotuser) gotpass = True;
16529
16530         while (!gotpass) {
16531                 char pwd[256] = {0};
16532                 int rc;
16533
16534                 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
16535                 if (rc == 0) {
16536                         fstrcpy(password, pwd);
16537                         gotpass = 1;
16538                 }
16539         }
16540
16541         printf("host=%s share=%s user=%s myname=%s\n",
16542                host, share, username, myname);
16543
16544         torture_creds = cli_session_creds_init(frame,
16545                                                username,
16546                                                workgroup,
16547                                                NULL, /* realm */
16548                                                password,
16549                                                use_kerberos,
16550                                                false, /* fallback_after_kerberos */
16551                                                false, /* use_ccache */
16552                                                false); /* password_is_nt_hash */
16553         if (torture_creds == NULL) {
16554                 d_printf("cli_session_creds_init() failed.\n");
16555                 exit(1);
16556         }
16557
16558         if (argc == optind) {
16559                 correct = run_test("ALL");
16560         } else {
16561                 for (i=optind;i<argc;i++) {
16562                         if (!run_test(argv[i])) {
16563                                 correct = False;
16564                         }
16565                 }
16566         }
16567
16568         TALLOC_FREE(frame);
16569
16570         if (correct) {
16571                 return(0);
16572         } else {
16573                 return(1);
16574         }
16575 }