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