source: trunk/server/source3/torture/torture.c

Last change on this file was 796, checked in by Silvan Scherrer, 12 years ago

Samba Server 3.6: make torture working

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