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