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