s3:libsmb: get rid of clisigning routines
[Samba/gebeck_regimport.git] / source3 / torture / torture.c
blob1f463f66729d69649a1f089ee23f4f70a5122662
1 /*
2 Unix SMB/CIFS implementation.
3 SMB torture tester
4 Copyright (C) Andrew Tridgell 1997-1998
5 Copyright (C) Jeremy Allison 2009
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.
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.
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/>.
21 #include "includes.h"
22 #include "system/shmem.h"
23 #include "wbc_async.h"
24 #include "torture/proto.h"
25 #include "libcli/security/security.h"
26 #include "tldap.h"
27 #include "tldap_util.h"
28 #include "../librpc/gen_ndr/svcctl.h"
29 #include "memcache.h"
30 #include "nsswitch/winbind_client.h"
31 #include "dbwrap/dbwrap.h"
32 #include "dbwrap/dbwrap_open.h"
33 #include "dbwrap/dbwrap_rbt.h"
34 #include "talloc_dict.h"
35 #include "async_smb.h"
36 #include "libsmb/libsmb.h"
37 #include "libsmb/clirap.h"
38 #include "trans2.h"
39 #include "libsmb/nmblib.h"
40 #include "../lib/util/tevent_ntstatus.h"
41 #include "util_tdb.h"
42 #include "../libcli/smb/read_smb.h"
43 #include "../libcli/smb/smbXcli_base.h"
45 extern char *optarg;
46 extern int optind;
48 fstring host, workgroup, share, password, username, myname;
49 static int max_protocol = PROTOCOL_NT1;
50 static const char *sockops="TCP_NODELAY";
51 int torture_nprocs=1;
52 static int port_to_use=0;
53 int torture_numops=100;
54 int torture_blocksize=1024*1024;
55 static int procnum; /* records process count number when forking */
56 static struct cli_state *current_cli;
57 static fstring randomfname;
58 static bool use_oplocks;
59 static bool use_level_II_oplocks;
60 static const char *client_txt = "client_oplocks.txt";
61 static bool disable_spnego;
62 static bool use_kerberos;
63 static bool force_dos_errors;
64 static fstring multishare_conn_fname;
65 static bool use_multishare_conn = False;
66 static bool do_encrypt;
67 static const char *local_path = NULL;
68 static int signing_state = SMB_SIGNING_DEFAULT;
69 char *test_filename;
71 bool torture_showall = False;
73 static double create_procs(bool (*fn)(int), bool *result);
76 /* return a pointer to a anonymous shared memory segment of size "size"
77 which will persist across fork() but will disappear when all processes
78 exit
80 The memory is not zeroed
82 This function uses system5 shared memory. It takes advantage of a property
83 that the memory is not destroyed if it is attached when the id is removed
85 void *shm_setup(int size)
87 int shmid;
88 void *ret;
90 #ifdef __QNXNTO__
91 shmid = shm_open("private", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
92 if (shmid == -1) {
93 printf("can't get shared memory\n");
94 exit(1);
96 shm_unlink("private");
97 if (ftruncate(shmid, size) == -1) {
98 printf("can't set shared memory size\n");
99 exit(1);
101 ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0);
102 if (ret == MAP_FAILED) {
103 printf("can't map shared memory\n");
104 exit(1);
106 #else
107 shmid = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);
108 if (shmid == -1) {
109 printf("can't get shared memory\n");
110 exit(1);
112 ret = (void *)shmat(shmid, 0, 0);
113 if (!ret || ret == (void *)-1) {
114 printf("can't attach to shared memory\n");
115 return NULL;
117 /* the following releases the ipc, but note that this process
118 and all its children will still have access to the memory, its
119 just that the shmid is no longer valid for other shm calls. This
120 means we don't leave behind lots of shm segments after we exit
122 See Stevens "advanced programming in unix env" for details
124 shmctl(shmid, IPC_RMID, 0);
125 #endif
127 return ret;
130 /********************************************************************
131 Ensure a connection is encrypted.
132 ********************************************************************/
134 static bool force_cli_encryption(struct cli_state *c,
135 const char *sharename)
137 uint16 major, minor;
138 uint32 caplow, caphigh;
139 NTSTATUS status;
141 if (!SERVER_HAS_UNIX_CIFS(c)) {
142 d_printf("Encryption required and "
143 "server that doesn't support "
144 "UNIX extensions - failing connect\n");
145 return false;
148 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
149 &caphigh);
150 if (!NT_STATUS_IS_OK(status)) {
151 d_printf("Encryption required and "
152 "can't get UNIX CIFS extensions "
153 "version from server: %s\n", nt_errstr(status));
154 return false;
157 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
158 d_printf("Encryption required and "
159 "share %s doesn't support "
160 "encryption.\n", sharename);
161 return false;
164 if (c->use_kerberos) {
165 status = cli_gss_smb_encryption_start(c);
166 } else {
167 status = cli_raw_ntlm_smb_encryption_start(c,
168 username,
169 password,
170 workgroup);
173 if (!NT_STATUS_IS_OK(status)) {
174 d_printf("Encryption required and "
175 "setup failed with error %s.\n",
176 nt_errstr(status));
177 return false;
180 return true;
184 static struct cli_state *open_nbt_connection(void)
186 struct cli_state *c;
187 NTSTATUS status;
188 int flags = 0;
190 if (disable_spnego) {
191 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
194 if (use_oplocks) {
195 flags |= CLI_FULL_CONNECTION_OPLOCKS;
198 if (use_level_II_oplocks) {
199 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
202 if (use_kerberos) {
203 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
206 if (force_dos_errors) {
207 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
210 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
211 signing_state, flags, &c);
212 if (!NT_STATUS_IS_OK(status)) {
213 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
214 return NULL;
217 cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
219 return c;
222 /****************************************************************************
223 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
224 ****************************************************************************/
226 static bool cli_bad_session_request(int fd,
227 struct nmb_name *calling, struct nmb_name *called)
229 TALLOC_CTX *frame;
230 uint8_t len_buf[4];
231 struct iovec iov[3];
232 ssize_t len;
233 uint8_t *inbuf;
234 int err;
235 bool ret = false;
236 uint8_t message_type;
237 uint8_t error;
238 struct event_context *ev;
239 struct tevent_req *req;
241 frame = talloc_stackframe();
243 iov[0].iov_base = len_buf;
244 iov[0].iov_len = sizeof(len_buf);
246 /* put in the destination name */
248 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
249 called->name_type);
250 if (iov[1].iov_base == NULL) {
251 goto fail;
253 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
254 talloc_get_size(iov[1].iov_base));
256 /* and my name */
258 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
259 calling->name_type);
260 if (iov[2].iov_base == NULL) {
261 goto fail;
263 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
264 talloc_get_size(iov[2].iov_base));
266 /* Deliberately corrupt the name len (first byte) */
267 *((uint8_t *)iov[2].iov_base) = 100;
269 /* send a session request (RFC 1002) */
270 /* setup the packet length
271 * Remove four bytes from the length count, since the length
272 * field in the NBT Session Service header counts the number
273 * of bytes which follow. The cli_send_smb() function knows
274 * about this and accounts for those four bytes.
275 * CRH.
278 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
279 SCVAL(len_buf,0,0x81);
281 len = write_data_iov(fd, iov, 3);
282 if (len == -1) {
283 goto fail;
286 ev = event_context_init(frame);
287 if (ev == NULL) {
288 goto fail;
290 req = read_smb_send(frame, ev, fd);
291 if (req == NULL) {
292 goto fail;
294 if (!tevent_req_poll(req, ev)) {
295 goto fail;
297 len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
298 if (len == -1) {
299 errno = err;
300 goto fail;
302 TALLOC_FREE(ev);
304 message_type = CVAL(inbuf, 0);
305 if (message_type != 0x83) {
306 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
307 message_type);
308 goto fail;
311 if (smb_len(inbuf) != 1) {
312 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
313 (int)smb_len(inbuf));
314 goto fail;
317 error = CVAL(inbuf, 4);
318 if (error != 0x82) {
319 d_fprintf(stderr, "Expected error 0x82, got %d\n",
320 (int)error);
321 goto fail;
324 ret = true;
325 fail:
326 TALLOC_FREE(frame);
327 return ret;
330 /* Insert a NULL at the first separator of the given path and return a pointer
331 * to the remainder of the string.
333 static char *
334 terminate_path_at_separator(char * path)
336 char * p;
338 if (!path) {
339 return NULL;
342 if ((p = strchr_m(path, '/'))) {
343 *p = '\0';
344 return p + 1;
347 if ((p = strchr_m(path, '\\'))) {
348 *p = '\0';
349 return p + 1;
352 /* No separator. */
353 return NULL;
357 parse a //server/share type UNC name
359 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
360 char **hostname, char **sharename)
362 char *p;
364 *hostname = *sharename = NULL;
366 if (strncmp(unc_name, "\\\\", 2) &&
367 strncmp(unc_name, "//", 2)) {
368 return False;
371 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
372 p = terminate_path_at_separator(*hostname);
374 if (p && *p) {
375 *sharename = talloc_strdup(mem_ctx, p);
376 terminate_path_at_separator(*sharename);
379 if (*hostname && *sharename) {
380 return True;
383 TALLOC_FREE(*hostname);
384 TALLOC_FREE(*sharename);
385 return False;
388 static bool torture_open_connection_share(struct cli_state **c,
389 const char *hostname,
390 const char *sharename)
392 int flags = 0;
393 NTSTATUS status;
395 if (use_kerberos)
396 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
397 if (use_oplocks)
398 flags |= CLI_FULL_CONNECTION_OPLOCKS;
399 if (use_level_II_oplocks)
400 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
402 status = cli_full_connection(c, myname,
403 hostname, NULL, port_to_use,
404 sharename, "?????",
405 username, workgroup,
406 password, flags, signing_state);
407 if (!NT_STATUS_IS_OK(status)) {
408 printf("failed to open share connection: //%s/%s port:%d - %s\n",
409 hostname, sharename, port_to_use, nt_errstr(status));
410 return False;
413 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
415 if (do_encrypt) {
416 return force_cli_encryption(*c,
417 sharename);
419 return True;
422 bool torture_open_connection(struct cli_state **c, int conn_index)
424 char **unc_list = NULL;
425 int num_unc_names = 0;
426 bool result;
428 if (use_multishare_conn==True) {
429 char *h, *s;
430 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
431 if (!unc_list || num_unc_names <= 0) {
432 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
433 exit(1);
436 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
437 NULL, &h, &s)) {
438 printf("Failed to parse UNC name %s\n",
439 unc_list[conn_index % num_unc_names]);
440 TALLOC_FREE(unc_list);
441 exit(1);
444 result = torture_open_connection_share(c, h, s);
446 /* h, s were copied earlier */
447 TALLOC_FREE(unc_list);
448 return result;
451 return torture_open_connection_share(c, host, share);
454 bool torture_init_connection(struct cli_state **pcli)
456 struct cli_state *cli;
458 cli = open_nbt_connection();
459 if (cli == NULL) {
460 return false;
463 *pcli = cli;
464 return true;
467 bool torture_cli_session_setup2(struct cli_state *cli, uint16 *new_vuid)
469 uint16_t old_vuid = cli_state_get_uid(cli);
470 fstring old_user_name;
471 size_t passlen = strlen(password);
472 NTSTATUS status;
473 bool ret;
475 fstrcpy(old_user_name, cli->user_name);
476 cli_state_set_uid(cli, 0);
477 ret = NT_STATUS_IS_OK(cli_session_setup(cli, username,
478 password, passlen,
479 password, passlen,
480 workgroup));
481 *new_vuid = cli_state_get_uid(cli);
482 cli_state_set_uid(cli, old_vuid);
483 status = cli_set_username(cli, old_user_name);
484 if (!NT_STATUS_IS_OK(status)) {
485 return false;
487 return ret;
491 bool torture_close_connection(struct cli_state *c)
493 bool ret = True;
494 NTSTATUS status;
496 status = cli_tdis(c);
497 if (!NT_STATUS_IS_OK(status)) {
498 printf("tdis failed (%s)\n", nt_errstr(status));
499 ret = False;
502 cli_shutdown(c);
504 return ret;
508 /* check if the server produced the expected dos or nt error code */
509 static bool check_both_error(int line, NTSTATUS status,
510 uint8 eclass, uint32 ecode, NTSTATUS nterr)
512 if (NT_STATUS_IS_DOS(status)) {
513 uint8 cclass;
514 uint32 num;
516 /* Check DOS error */
517 cclass = NT_STATUS_DOS_CLASS(status);
518 num = NT_STATUS_DOS_CODE(status);
520 if (eclass != cclass || ecode != num) {
521 printf("unexpected error code class=%d code=%d\n",
522 (int)cclass, (int)num);
523 printf(" expected %d/%d %s (line=%d)\n",
524 (int)eclass, (int)ecode, nt_errstr(nterr), line);
525 return false;
527 } else {
528 /* Check NT error */
529 if (!NT_STATUS_EQUAL(nterr, status)) {
530 printf("unexpected error code %s\n",
531 nt_errstr(status));
532 printf(" expected %s (line=%d)\n",
533 nt_errstr(nterr), line);
534 return false;
538 return true;
542 /* check if the server produced the expected error code */
543 static bool check_error(int line, NTSTATUS status,
544 uint8 eclass, uint32 ecode, NTSTATUS nterr)
546 if (NT_STATUS_IS_DOS(status)) {
547 uint8 cclass;
548 uint32 num;
550 /* Check DOS error */
552 cclass = NT_STATUS_DOS_CLASS(status);
553 num = NT_STATUS_DOS_CODE(status);
555 if (eclass != cclass || ecode != num) {
556 printf("unexpected error code class=%d code=%d\n",
557 (int)cclass, (int)num);
558 printf(" expected %d/%d %s (line=%d)\n",
559 (int)eclass, (int)ecode, nt_errstr(nterr),
560 line);
561 return False;
564 } else {
565 /* Check NT error */
567 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
568 printf("unexpected error code %s\n",
569 nt_errstr(status));
570 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
571 line);
572 return False;
576 return True;
580 static bool wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
582 NTSTATUS status;
584 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
586 while (!NT_STATUS_IS_OK(status)) {
587 if (!check_both_error(__LINE__, status, ERRDOS,
588 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
589 return false;
592 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
595 return true;
599 static bool rw_torture(struct cli_state *c)
601 const char *lockfname = "\\torture.lck";
602 fstring fname;
603 uint16_t fnum;
604 uint16_t fnum2;
605 pid_t pid2, pid = getpid();
606 int i, j;
607 char buf[1024];
608 bool correct = True;
609 size_t nread = 0;
610 NTSTATUS status;
612 memset(buf, '\0', sizeof(buf));
614 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
615 DENY_NONE, &fnum2);
616 if (!NT_STATUS_IS_OK(status)) {
617 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
619 if (!NT_STATUS_IS_OK(status)) {
620 printf("open of %s failed (%s)\n",
621 lockfname, nt_errstr(status));
622 return False;
625 for (i=0;i<torture_numops;i++) {
626 unsigned n = (unsigned)sys_random()%10;
628 if (i % 10 == 0) {
629 printf("%d\r", i); fflush(stdout);
631 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
633 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
634 return False;
637 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
638 DENY_ALL, &fnum);
639 if (!NT_STATUS_IS_OK(status)) {
640 printf("open failed (%s)\n", nt_errstr(status));
641 correct = False;
642 break;
645 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
646 sizeof(pid), NULL);
647 if (!NT_STATUS_IS_OK(status)) {
648 printf("write failed (%s)\n", nt_errstr(status));
649 correct = False;
652 for (j=0;j<50;j++) {
653 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
654 sizeof(pid)+(j*sizeof(buf)),
655 sizeof(buf), NULL);
656 if (!NT_STATUS_IS_OK(status)) {
657 printf("write failed (%s)\n",
658 nt_errstr(status));
659 correct = False;
663 pid2 = 0;
665 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
666 &nread);
667 if (!NT_STATUS_IS_OK(status)) {
668 printf("read failed (%s)\n", nt_errstr(status));
669 correct = false;
670 } else if (nread != sizeof(pid)) {
671 printf("read/write compare failed: "
672 "recv %ld req %ld\n", (unsigned long)nread,
673 (unsigned long)sizeof(pid));
674 correct = false;
677 if (pid2 != pid) {
678 printf("data corruption!\n");
679 correct = False;
682 status = cli_close(c, fnum);
683 if (!NT_STATUS_IS_OK(status)) {
684 printf("close failed (%s)\n", nt_errstr(status));
685 correct = False;
688 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
689 if (!NT_STATUS_IS_OK(status)) {
690 printf("unlink failed (%s)\n", nt_errstr(status));
691 correct = False;
694 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
695 if (!NT_STATUS_IS_OK(status)) {
696 printf("unlock failed (%s)\n", nt_errstr(status));
697 correct = False;
701 cli_close(c, fnum2);
702 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
704 printf("%d\n", i);
706 return correct;
709 static bool run_torture(int dummy)
711 struct cli_state *cli;
712 bool ret;
714 cli = current_cli;
716 smbXcli_conn_set_sockopt(cli->conn, sockops);
718 ret = rw_torture(cli);
720 if (!torture_close_connection(cli)) {
721 ret = False;
724 return ret;
727 static bool rw_torture3(struct cli_state *c, char *lockfname)
729 uint16_t fnum = (uint16_t)-1;
730 unsigned int i = 0;
731 char buf[131072];
732 char buf_rd[131072];
733 unsigned count;
734 unsigned countprev = 0;
735 size_t sent = 0;
736 bool correct = True;
737 NTSTATUS status = NT_STATUS_OK;
739 srandom(1);
740 for (i = 0; i < sizeof(buf); i += sizeof(uint32))
742 SIVAL(buf, i, sys_random());
745 if (procnum == 0)
747 status = cli_unlink(
748 c, lockfname,
749 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
750 if (!NT_STATUS_IS_OK(status)) {
751 printf("unlink failed (%s) (normal, this file should "
752 "not exist)\n", nt_errstr(status));
755 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
756 DENY_NONE, &fnum);
757 if (!NT_STATUS_IS_OK(status)) {
758 printf("first open read/write of %s failed (%s)\n",
759 lockfname, nt_errstr(status));
760 return False;
763 else
765 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
767 status = cli_openx(c, lockfname, O_RDONLY,
768 DENY_NONE, &fnum);
769 if (!NT_STATUS_IS_OK(status)) {
770 break;
772 smb_msleep(10);
774 if (!NT_STATUS_IS_OK(status)) {
775 printf("second open read-only of %s failed (%s)\n",
776 lockfname, nt_errstr(status));
777 return False;
781 i = 0;
782 for (count = 0; count < sizeof(buf); count += sent)
784 if (count >= countprev) {
785 printf("%d %8d\r", i, count);
786 fflush(stdout);
787 i++;
788 countprev += (sizeof(buf) / 20);
791 if (procnum == 0)
793 sent = ((unsigned)sys_random()%(20))+ 1;
794 if (sent > sizeof(buf) - count)
796 sent = sizeof(buf) - count;
799 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
800 count, sent, NULL);
801 if (!NT_STATUS_IS_OK(status)) {
802 printf("write failed (%s)\n",
803 nt_errstr(status));
804 correct = False;
807 else
809 status = cli_read(c, fnum, buf_rd+count, count,
810 sizeof(buf)-count, &sent);
811 if(!NT_STATUS_IS_OK(status)) {
812 printf("read failed offset:%d size:%ld (%s)\n",
813 count, (unsigned long)sizeof(buf)-count,
814 nt_errstr(status));
815 correct = False;
816 sent = 0;
817 } else if (sent > 0) {
818 if (memcmp(buf_rd+count, buf+count, sent) != 0)
820 printf("read/write compare failed\n");
821 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
822 correct = False;
823 break;
830 status = cli_close(c, fnum);
831 if (!NT_STATUS_IS_OK(status)) {
832 printf("close failed (%s)\n", nt_errstr(status));
833 correct = False;
836 return correct;
839 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
841 const char *lockfname = "\\torture2.lck";
842 uint16_t fnum1;
843 uint16_t fnum2;
844 int i;
845 char buf[131072];
846 char buf_rd[131072];
847 bool correct = True;
848 size_t bytes_read;
849 NTSTATUS status;
851 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
852 if (!NT_STATUS_IS_OK(status)) {
853 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
856 status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
857 DENY_NONE, &fnum1);
858 if (!NT_STATUS_IS_OK(status)) {
859 printf("first open read/write of %s failed (%s)\n",
860 lockfname, nt_errstr(status));
861 return False;
864 status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
865 if (!NT_STATUS_IS_OK(status)) {
866 printf("second open read-only of %s failed (%s)\n",
867 lockfname, nt_errstr(status));
868 cli_close(c1, fnum1);
869 return False;
872 for (i = 0; i < torture_numops; i++)
874 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
875 if (i % 10 == 0) {
876 printf("%d\r", i); fflush(stdout);
879 generate_random_buffer((unsigned char *)buf, buf_size);
881 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
882 buf_size, NULL);
883 if (!NT_STATUS_IS_OK(status)) {
884 printf("write failed (%s)\n", nt_errstr(status));
885 correct = False;
886 break;
889 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
890 if(!NT_STATUS_IS_OK(status)) {
891 printf("read failed (%s)\n", nt_errstr(status));
892 correct = false;
893 break;
894 } else if (bytes_read != buf_size) {
895 printf("read failed\n");
896 printf("read %ld, expected %ld\n",
897 (unsigned long)bytes_read,
898 (unsigned long)buf_size);
899 correct = False;
900 break;
903 if (memcmp(buf_rd, buf, buf_size) != 0)
905 printf("read/write compare failed\n");
906 correct = False;
907 break;
911 status = cli_close(c2, fnum2);
912 if (!NT_STATUS_IS_OK(status)) {
913 printf("close failed (%s)\n", nt_errstr(status));
914 correct = False;
917 status = cli_close(c1, fnum1);
918 if (!NT_STATUS_IS_OK(status)) {
919 printf("close failed (%s)\n", nt_errstr(status));
920 correct = False;
923 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
924 if (!NT_STATUS_IS_OK(status)) {
925 printf("unlink failed (%s)\n", nt_errstr(status));
926 correct = False;
929 return correct;
932 static bool run_readwritetest(int dummy)
934 struct cli_state *cli1, *cli2;
935 bool test1, test2 = False;
937 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
938 return False;
940 smbXcli_conn_set_sockopt(cli1->conn, sockops);
941 smbXcli_conn_set_sockopt(cli2->conn, sockops);
943 printf("starting readwritetest\n");
945 test1 = rw_torture2(cli1, cli2);
946 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
948 if (test1) {
949 test2 = rw_torture2(cli1, cli1);
950 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
953 if (!torture_close_connection(cli1)) {
954 test1 = False;
957 if (!torture_close_connection(cli2)) {
958 test2 = False;
961 return (test1 && test2);
964 static bool run_readwritemulti(int dummy)
966 struct cli_state *cli;
967 bool test;
969 cli = current_cli;
971 smbXcli_conn_set_sockopt(cli->conn, sockops);
973 printf("run_readwritemulti: fname %s\n", randomfname);
974 test = rw_torture3(cli, randomfname);
976 if (!torture_close_connection(cli)) {
977 test = False;
980 return test;
983 static bool run_readwritelarge_internal(void)
985 static struct cli_state *cli1;
986 uint16_t fnum1;
987 const char *lockfname = "\\large.dat";
988 off_t fsize;
989 char buf[126*1024];
990 bool correct = True;
991 NTSTATUS status;
993 if (!torture_open_connection(&cli1, 0)) {
994 return False;
996 smbXcli_conn_set_sockopt(cli1->conn, sockops);
997 memset(buf,'\0',sizeof(buf));
999 printf("starting readwritelarge_internal\n");
1001 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1003 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1004 DENY_NONE, &fnum1);
1005 if (!NT_STATUS_IS_OK(status)) {
1006 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1007 return False;
1010 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1012 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1013 NULL, NULL, NULL);
1014 if (!NT_STATUS_IS_OK(status)) {
1015 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1016 correct = False;
1019 if (fsize == sizeof(buf))
1020 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1021 (unsigned long)fsize);
1022 else {
1023 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1024 (unsigned long)fsize);
1025 correct = False;
1028 status = cli_close(cli1, fnum1);
1029 if (!NT_STATUS_IS_OK(status)) {
1030 printf("close failed (%s)\n", nt_errstr(status));
1031 correct = False;
1034 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1035 if (!NT_STATUS_IS_OK(status)) {
1036 printf("unlink failed (%s)\n", nt_errstr(status));
1037 correct = False;
1040 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1041 DENY_NONE, &fnum1);
1042 if (!NT_STATUS_IS_OK(status)) {
1043 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1044 return False;
1047 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1049 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1050 NULL, NULL, NULL);
1051 if (!NT_STATUS_IS_OK(status)) {
1052 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1053 correct = False;
1056 if (fsize == sizeof(buf))
1057 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1058 (unsigned long)fsize);
1059 else {
1060 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1061 (unsigned long)fsize);
1062 correct = False;
1065 #if 0
1066 /* ToDo - set allocation. JRA */
1067 if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1068 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1069 return False;
1071 if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1072 NULL, NULL)) {
1073 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1074 correct = False;
1076 if (fsize != 0)
1077 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1078 #endif
1080 status = cli_close(cli1, fnum1);
1081 if (!NT_STATUS_IS_OK(status)) {
1082 printf("close failed (%s)\n", nt_errstr(status));
1083 correct = False;
1086 if (!torture_close_connection(cli1)) {
1087 correct = False;
1089 return correct;
1092 static bool run_readwritelarge(int dummy)
1094 return run_readwritelarge_internal();
1097 static bool run_readwritelarge_signtest(int dummy)
1099 bool ret;
1100 signing_state = SMB_SIGNING_REQUIRED;
1101 ret = run_readwritelarge_internal();
1102 signing_state = SMB_SIGNING_DEFAULT;
1103 return ret;
1106 int line_count = 0;
1107 int nbio_id;
1109 #define ival(s) strtol(s, NULL, 0)
1111 /* run a test that simulates an approximate netbench client load */
1112 static bool run_netbench(int client)
1114 struct cli_state *cli;
1115 int i;
1116 char line[1024];
1117 char cname[20];
1118 FILE *f;
1119 const char *params[20];
1120 bool correct = True;
1122 cli = current_cli;
1124 nbio_id = client;
1126 smbXcli_conn_set_sockopt(cli->conn, sockops);
1128 nb_setup(cli);
1130 slprintf(cname,sizeof(cname)-1, "client%d", client);
1132 f = fopen(client_txt, "r");
1134 if (!f) {
1135 perror(client_txt);
1136 return False;
1139 while (fgets(line, sizeof(line)-1, f)) {
1140 char *saveptr;
1141 line_count++;
1143 line[strlen(line)-1] = 0;
1145 /* printf("[%d] %s\n", line_count, line); */
1147 all_string_sub(line,"client1", cname, sizeof(line));
1149 /* parse the command parameters */
1150 params[0] = strtok_r(line, " ", &saveptr);
1151 i = 0;
1152 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1154 params[i] = "";
1156 if (i < 2) continue;
1158 if (!strncmp(params[0],"SMB", 3)) {
1159 printf("ERROR: You are using a dbench 1 load file\n");
1160 exit(1);
1163 if (!strcmp(params[0],"NTCreateX")) {
1164 nb_createx(params[1], ival(params[2]), ival(params[3]),
1165 ival(params[4]));
1166 } else if (!strcmp(params[0],"Close")) {
1167 nb_close(ival(params[1]));
1168 } else if (!strcmp(params[0],"Rename")) {
1169 nb_rename(params[1], params[2]);
1170 } else if (!strcmp(params[0],"Unlink")) {
1171 nb_unlink(params[1]);
1172 } else if (!strcmp(params[0],"Deltree")) {
1173 nb_deltree(params[1]);
1174 } else if (!strcmp(params[0],"Rmdir")) {
1175 nb_rmdir(params[1]);
1176 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1177 nb_qpathinfo(params[1]);
1178 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1179 nb_qfileinfo(ival(params[1]));
1180 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1181 nb_qfsinfo(ival(params[1]));
1182 } else if (!strcmp(params[0],"FIND_FIRST")) {
1183 nb_findfirst(params[1]);
1184 } else if (!strcmp(params[0],"WriteX")) {
1185 nb_writex(ival(params[1]),
1186 ival(params[2]), ival(params[3]), ival(params[4]));
1187 } else if (!strcmp(params[0],"ReadX")) {
1188 nb_readx(ival(params[1]),
1189 ival(params[2]), ival(params[3]), ival(params[4]));
1190 } else if (!strcmp(params[0],"Flush")) {
1191 nb_flush(ival(params[1]));
1192 } else {
1193 printf("Unknown operation %s\n", params[0]);
1194 exit(1);
1197 fclose(f);
1199 nb_cleanup();
1201 if (!torture_close_connection(cli)) {
1202 correct = False;
1205 return correct;
1209 /* run a test that simulates an approximate netbench client load */
1210 static bool run_nbench(int dummy)
1212 double t;
1213 bool correct = True;
1215 nbio_shmem(torture_nprocs);
1217 nbio_id = -1;
1219 signal(SIGALRM, nb_alarm);
1220 alarm(1);
1221 t = create_procs(run_netbench, &correct);
1222 alarm(0);
1224 printf("\nThroughput %g MB/sec\n",
1225 1.0e-6 * nbio_total() / t);
1226 return correct;
1231 This test checks for two things:
1233 1) correct support for retaining locks over a close (ie. the server
1234 must not use posix semantics)
1235 2) support for lock timeouts
1237 static bool run_locktest1(int dummy)
1239 struct cli_state *cli1, *cli2;
1240 const char *fname = "\\lockt1.lck";
1241 uint16_t fnum1, fnum2, fnum3;
1242 time_t t1, t2;
1243 unsigned lock_timeout;
1244 NTSTATUS status;
1246 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1247 return False;
1249 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1250 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1252 printf("starting locktest1\n");
1254 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1256 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1257 &fnum1);
1258 if (!NT_STATUS_IS_OK(status)) {
1259 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1260 return False;
1263 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1264 if (!NT_STATUS_IS_OK(status)) {
1265 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1266 return False;
1269 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1270 if (!NT_STATUS_IS_OK(status)) {
1271 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1272 return False;
1275 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1276 if (!NT_STATUS_IS_OK(status)) {
1277 printf("lock1 failed (%s)\n", nt_errstr(status));
1278 return false;
1281 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1282 if (NT_STATUS_IS_OK(status)) {
1283 printf("lock2 succeeded! This is a locking bug\n");
1284 return false;
1285 } else {
1286 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1287 NT_STATUS_LOCK_NOT_GRANTED)) {
1288 return false;
1292 lock_timeout = (1 + (random() % 20));
1293 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1294 t1 = time(NULL);
1295 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1296 if (NT_STATUS_IS_OK(status)) {
1297 printf("lock3 succeeded! This is a locking bug\n");
1298 return false;
1299 } else {
1300 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1301 NT_STATUS_FILE_LOCK_CONFLICT)) {
1302 return false;
1305 t2 = time(NULL);
1307 if (ABS(t2 - t1) < lock_timeout-1) {
1308 printf("error: This server appears not to support timed lock requests\n");
1311 printf("server slept for %u seconds for a %u second timeout\n",
1312 (unsigned int)(t2-t1), lock_timeout);
1314 status = cli_close(cli1, fnum2);
1315 if (!NT_STATUS_IS_OK(status)) {
1316 printf("close1 failed (%s)\n", nt_errstr(status));
1317 return False;
1320 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1321 if (NT_STATUS_IS_OK(status)) {
1322 printf("lock4 succeeded! This is a locking bug\n");
1323 return false;
1324 } else {
1325 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1326 NT_STATUS_FILE_LOCK_CONFLICT)) {
1327 return false;
1331 status = cli_close(cli1, fnum1);
1332 if (!NT_STATUS_IS_OK(status)) {
1333 printf("close2 failed (%s)\n", nt_errstr(status));
1334 return False;
1337 status = cli_close(cli2, fnum3);
1338 if (!NT_STATUS_IS_OK(status)) {
1339 printf("close3 failed (%s)\n", nt_errstr(status));
1340 return False;
1343 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1344 if (!NT_STATUS_IS_OK(status)) {
1345 printf("unlink failed (%s)\n", nt_errstr(status));
1346 return False;
1350 if (!torture_close_connection(cli1)) {
1351 return False;
1354 if (!torture_close_connection(cli2)) {
1355 return False;
1358 printf("Passed locktest1\n");
1359 return True;
1363 this checks to see if a secondary tconx can use open files from an
1364 earlier tconx
1366 static bool run_tcon_test(int dummy)
1368 static struct cli_state *cli;
1369 const char *fname = "\\tcontest.tmp";
1370 uint16 fnum1;
1371 uint16 cnum1, cnum2, cnum3;
1372 uint16 vuid1, vuid2;
1373 char buf[4];
1374 bool ret = True;
1375 NTSTATUS status;
1377 memset(buf, '\0', sizeof(buf));
1379 if (!torture_open_connection(&cli, 0)) {
1380 return False;
1382 smbXcli_conn_set_sockopt(cli->conn, sockops);
1384 printf("starting tcontest\n");
1386 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1388 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1389 if (!NT_STATUS_IS_OK(status)) {
1390 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1391 return False;
1394 cnum1 = cli_state_get_tid(cli);
1395 vuid1 = cli_state_get_uid(cli);
1397 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1398 if (!NT_STATUS_IS_OK(status)) {
1399 printf("initial write failed (%s)", nt_errstr(status));
1400 return False;
1403 status = cli_tree_connect(cli, share, "?????",
1404 password, strlen(password)+1);
1405 if (!NT_STATUS_IS_OK(status)) {
1406 printf("%s refused 2nd tree connect (%s)\n", host,
1407 nt_errstr(status));
1408 cli_shutdown(cli);
1409 return False;
1412 cnum2 = cli_state_get_tid(cli);
1413 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1414 vuid2 = cli_state_get_uid(cli) + 1;
1416 /* try a write with the wrong tid */
1417 cli_state_set_tid(cli, cnum2);
1419 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1420 if (NT_STATUS_IS_OK(status)) {
1421 printf("* server allows write with wrong TID\n");
1422 ret = False;
1423 } else {
1424 printf("server fails write with wrong TID : %s\n",
1425 nt_errstr(status));
1429 /* try a write with an invalid tid */
1430 cli_state_set_tid(cli, cnum3);
1432 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1433 if (NT_STATUS_IS_OK(status)) {
1434 printf("* server allows write with invalid TID\n");
1435 ret = False;
1436 } else {
1437 printf("server fails write with invalid TID : %s\n",
1438 nt_errstr(status));
1441 /* try a write with an invalid vuid */
1442 cli_state_set_uid(cli, vuid2);
1443 cli_state_set_tid(cli, cnum1);
1445 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1446 if (NT_STATUS_IS_OK(status)) {
1447 printf("* server allows write with invalid VUID\n");
1448 ret = False;
1449 } else {
1450 printf("server fails write with invalid VUID : %s\n",
1451 nt_errstr(status));
1454 cli_state_set_tid(cli, cnum1);
1455 cli_state_set_uid(cli, vuid1);
1457 status = cli_close(cli, fnum1);
1458 if (!NT_STATUS_IS_OK(status)) {
1459 printf("close failed (%s)\n", nt_errstr(status));
1460 return False;
1463 cli_state_set_tid(cli, cnum2);
1465 status = cli_tdis(cli);
1466 if (!NT_STATUS_IS_OK(status)) {
1467 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1468 return False;
1471 cli_state_set_tid(cli, cnum1);
1473 if (!torture_close_connection(cli)) {
1474 return False;
1477 return ret;
1482 checks for old style tcon support
1484 static bool run_tcon2_test(int dummy)
1486 static struct cli_state *cli;
1487 uint16 cnum, max_xmit;
1488 char *service;
1489 NTSTATUS status;
1491 if (!torture_open_connection(&cli, 0)) {
1492 return False;
1494 smbXcli_conn_set_sockopt(cli->conn, sockops);
1496 printf("starting tcon2 test\n");
1498 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1499 return false;
1502 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1504 SAFE_FREE(service);
1506 if (!NT_STATUS_IS_OK(status)) {
1507 printf("tcon2 failed : %s\n", nt_errstr(status));
1508 } else {
1509 printf("tcon OK : max_xmit=%d cnum=%d\n",
1510 (int)max_xmit, (int)cnum);
1513 if (!torture_close_connection(cli)) {
1514 return False;
1517 printf("Passed tcon2 test\n");
1518 return True;
1521 static bool tcon_devtest(struct cli_state *cli,
1522 const char *myshare, const char *devtype,
1523 const char *return_devtype,
1524 NTSTATUS expected_error)
1526 NTSTATUS status;
1527 bool ret;
1529 status = cli_tree_connect(cli, myshare, devtype,
1530 password, strlen(password)+1);
1532 if (NT_STATUS_IS_OK(expected_error)) {
1533 if (NT_STATUS_IS_OK(status)) {
1534 if (strcmp(cli->dev, return_devtype) == 0) {
1535 ret = True;
1536 } else {
1537 printf("tconX to share %s with type %s "
1538 "succeeded but returned the wrong "
1539 "device type (got [%s] but should have got [%s])\n",
1540 myshare, devtype, cli->dev, return_devtype);
1541 ret = False;
1543 } else {
1544 printf("tconX to share %s with type %s "
1545 "should have succeeded but failed\n",
1546 myshare, devtype);
1547 ret = False;
1549 cli_tdis(cli);
1550 } else {
1551 if (NT_STATUS_IS_OK(status)) {
1552 printf("tconx to share %s with type %s "
1553 "should have failed but succeeded\n",
1554 myshare, devtype);
1555 ret = False;
1556 } else {
1557 if (NT_STATUS_EQUAL(status, expected_error)) {
1558 ret = True;
1559 } else {
1560 printf("Returned unexpected error\n");
1561 ret = False;
1565 return ret;
1569 checks for correct tconX support
1571 static bool run_tcon_devtype_test(int dummy)
1573 static struct cli_state *cli1 = NULL;
1574 int flags = 0;
1575 NTSTATUS status;
1576 bool ret = True;
1578 status = cli_full_connection(&cli1, myname,
1579 host, NULL, port_to_use,
1580 NULL, NULL,
1581 username, workgroup,
1582 password, flags, signing_state);
1584 if (!NT_STATUS_IS_OK(status)) {
1585 printf("could not open connection\n");
1586 return False;
1589 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1590 ret = False;
1592 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1593 ret = False;
1595 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1596 ret = False;
1598 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1599 ret = False;
1601 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1602 ret = False;
1604 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1605 ret = False;
1607 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1608 ret = False;
1610 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1611 ret = False;
1613 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1614 ret = False;
1616 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1617 ret = False;
1619 cli_shutdown(cli1);
1621 if (ret)
1622 printf("Passed tcondevtest\n");
1624 return ret;
1629 This test checks that
1631 1) the server supports multiple locking contexts on the one SMB
1632 connection, distinguished by PID.
1634 2) the server correctly fails overlapping locks made by the same PID (this
1635 goes against POSIX behaviour, which is why it is tricky to implement)
1637 3) the server denies unlock requests by an incorrect client PID
1639 static bool run_locktest2(int dummy)
1641 static struct cli_state *cli;
1642 const char *fname = "\\lockt2.lck";
1643 uint16_t fnum1, fnum2, fnum3;
1644 bool correct = True;
1645 NTSTATUS status;
1647 if (!torture_open_connection(&cli, 0)) {
1648 return False;
1651 smbXcli_conn_set_sockopt(cli->conn, sockops);
1653 printf("starting locktest2\n");
1655 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1657 cli_setpid(cli, 1);
1659 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1660 if (!NT_STATUS_IS_OK(status)) {
1661 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1662 return False;
1665 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1666 if (!NT_STATUS_IS_OK(status)) {
1667 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1668 return False;
1671 cli_setpid(cli, 2);
1673 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1674 if (!NT_STATUS_IS_OK(status)) {
1675 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1676 return False;
1679 cli_setpid(cli, 1);
1681 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1682 if (!NT_STATUS_IS_OK(status)) {
1683 printf("lock1 failed (%s)\n", nt_errstr(status));
1684 return false;
1687 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1688 if (NT_STATUS_IS_OK(status)) {
1689 printf("WRITE lock1 succeeded! This is a locking bug\n");
1690 correct = false;
1691 } else {
1692 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1693 NT_STATUS_LOCK_NOT_GRANTED)) {
1694 return false;
1698 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1699 if (NT_STATUS_IS_OK(status)) {
1700 printf("WRITE lock2 succeeded! This is a locking bug\n");
1701 correct = false;
1702 } else {
1703 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1704 NT_STATUS_LOCK_NOT_GRANTED)) {
1705 return false;
1709 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1710 if (NT_STATUS_IS_OK(status)) {
1711 printf("READ lock2 succeeded! This is a locking bug\n");
1712 correct = false;
1713 } else {
1714 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1715 NT_STATUS_FILE_LOCK_CONFLICT)) {
1716 return false;
1720 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1721 if (!NT_STATUS_IS_OK(status)) {
1722 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1724 cli_setpid(cli, 2);
1725 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1726 printf("unlock at 100 succeeded! This is a locking bug\n");
1727 correct = False;
1730 status = cli_unlock(cli, fnum1, 0, 4);
1731 if (NT_STATUS_IS_OK(status)) {
1732 printf("unlock1 succeeded! This is a locking bug\n");
1733 correct = false;
1734 } else {
1735 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1736 NT_STATUS_RANGE_NOT_LOCKED)) {
1737 return false;
1741 status = cli_unlock(cli, fnum1, 0, 8);
1742 if (NT_STATUS_IS_OK(status)) {
1743 printf("unlock2 succeeded! This is a locking bug\n");
1744 correct = false;
1745 } else {
1746 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1747 NT_STATUS_RANGE_NOT_LOCKED)) {
1748 return false;
1752 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1753 if (NT_STATUS_IS_OK(status)) {
1754 printf("lock3 succeeded! This is a locking bug\n");
1755 correct = false;
1756 } else {
1757 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1758 NT_STATUS_LOCK_NOT_GRANTED)) {
1759 return false;
1763 cli_setpid(cli, 1);
1765 status = cli_close(cli, fnum1);
1766 if (!NT_STATUS_IS_OK(status)) {
1767 printf("close1 failed (%s)\n", nt_errstr(status));
1768 return False;
1771 status = cli_close(cli, fnum2);
1772 if (!NT_STATUS_IS_OK(status)) {
1773 printf("close2 failed (%s)\n", nt_errstr(status));
1774 return False;
1777 status = cli_close(cli, fnum3);
1778 if (!NT_STATUS_IS_OK(status)) {
1779 printf("close3 failed (%s)\n", nt_errstr(status));
1780 return False;
1783 if (!torture_close_connection(cli)) {
1784 correct = False;
1787 printf("locktest2 finished\n");
1789 return correct;
1794 This test checks that
1796 1) the server supports the full offset range in lock requests
1798 static bool run_locktest3(int dummy)
1800 static struct cli_state *cli1, *cli2;
1801 const char *fname = "\\lockt3.lck";
1802 uint16_t fnum1, fnum2;
1803 int i;
1804 uint32 offset;
1805 bool correct = True;
1806 NTSTATUS status;
1808 #define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
1810 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1811 return False;
1813 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1814 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1816 printf("starting locktest3\n");
1818 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1820 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1821 &fnum1);
1822 if (!NT_STATUS_IS_OK(status)) {
1823 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1824 return False;
1827 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1828 if (!NT_STATUS_IS_OK(status)) {
1829 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1830 return False;
1833 for (offset=i=0;i<torture_numops;i++) {
1834 NEXT_OFFSET;
1836 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1837 if (!NT_STATUS_IS_OK(status)) {
1838 printf("lock1 %d failed (%s)\n",
1840 nt_errstr(status));
1841 return False;
1844 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1845 if (!NT_STATUS_IS_OK(status)) {
1846 printf("lock2 %d failed (%s)\n",
1848 nt_errstr(status));
1849 return False;
1853 for (offset=i=0;i<torture_numops;i++) {
1854 NEXT_OFFSET;
1856 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1857 if (NT_STATUS_IS_OK(status)) {
1858 printf("error: lock1 %d succeeded!\n", i);
1859 return False;
1862 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1863 if (NT_STATUS_IS_OK(status)) {
1864 printf("error: lock2 %d succeeded!\n", i);
1865 return False;
1868 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1869 if (NT_STATUS_IS_OK(status)) {
1870 printf("error: lock3 %d succeeded!\n", i);
1871 return False;
1874 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1875 if (NT_STATUS_IS_OK(status)) {
1876 printf("error: lock4 %d succeeded!\n", i);
1877 return False;
1881 for (offset=i=0;i<torture_numops;i++) {
1882 NEXT_OFFSET;
1884 status = cli_unlock(cli1, fnum1, offset-1, 1);
1885 if (!NT_STATUS_IS_OK(status)) {
1886 printf("unlock1 %d failed (%s)\n",
1888 nt_errstr(status));
1889 return False;
1892 status = cli_unlock(cli2, fnum2, offset-2, 1);
1893 if (!NT_STATUS_IS_OK(status)) {
1894 printf("unlock2 %d failed (%s)\n",
1896 nt_errstr(status));
1897 return False;
1901 status = cli_close(cli1, fnum1);
1902 if (!NT_STATUS_IS_OK(status)) {
1903 printf("close1 failed (%s)\n", nt_errstr(status));
1904 return False;
1907 status = cli_close(cli2, fnum2);
1908 if (!NT_STATUS_IS_OK(status)) {
1909 printf("close2 failed (%s)\n", nt_errstr(status));
1910 return False;
1913 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1914 if (!NT_STATUS_IS_OK(status)) {
1915 printf("unlink failed (%s)\n", nt_errstr(status));
1916 return False;
1919 if (!torture_close_connection(cli1)) {
1920 correct = False;
1923 if (!torture_close_connection(cli2)) {
1924 correct = False;
1927 printf("finished locktest3\n");
1929 return correct;
1932 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1933 char *buf, off_t offset, size_t size,
1934 size_t *nread, size_t expect)
1936 NTSTATUS status;
1937 size_t l_nread;
1939 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1941 if(!NT_STATUS_IS_OK(status)) {
1942 return false;
1943 } else if (l_nread != expect) {
1944 return false;
1947 if (nread) {
1948 *nread = l_nread;
1951 return true;
1954 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1955 printf("** "); correct = False; \
1959 looks at overlapping locks
1961 static bool run_locktest4(int dummy)
1963 static struct cli_state *cli1, *cli2;
1964 const char *fname = "\\lockt4.lck";
1965 uint16_t fnum1, fnum2, f;
1966 bool ret;
1967 char buf[1000];
1968 bool correct = True;
1969 NTSTATUS status;
1971 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1972 return False;
1975 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1976 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1978 printf("starting locktest4\n");
1980 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1982 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1983 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1985 memset(buf, 0, sizeof(buf));
1987 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1988 NULL);
1989 if (!NT_STATUS_IS_OK(status)) {
1990 printf("Failed to create file: %s\n", nt_errstr(status));
1991 correct = False;
1992 goto fail;
1995 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1996 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1997 EXPECTED(ret, False);
1998 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2000 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2001 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2002 EXPECTED(ret, True);
2003 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2005 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2006 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2007 EXPECTED(ret, False);
2008 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2010 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2011 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2012 EXPECTED(ret, True);
2013 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2015 ret = (cli_setpid(cli1, 1),
2016 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2017 (cli_setpid(cli1, 2),
2018 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2019 EXPECTED(ret, False);
2020 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2022 ret = (cli_setpid(cli1, 1),
2023 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2024 (cli_setpid(cli1, 2),
2025 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2026 EXPECTED(ret, True);
2027 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2029 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2030 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2031 EXPECTED(ret, True);
2032 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2034 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2035 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2036 EXPECTED(ret, False);
2037 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2039 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2040 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2041 EXPECTED(ret, False);
2042 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2044 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2045 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2046 EXPECTED(ret, True);
2047 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2049 ret = (cli_setpid(cli1, 1),
2050 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2051 (cli_setpid(cli1, 2),
2052 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2053 EXPECTED(ret, False);
2054 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2056 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2057 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2058 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2059 EXPECTED(ret, False);
2060 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2063 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2064 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2065 EXPECTED(ret, False);
2066 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2068 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2069 ret = NT_STATUS_IS_OK(status);
2070 if (ret) {
2071 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2072 NULL);
2073 ret = NT_STATUS_IS_OK(status);
2075 EXPECTED(ret, False);
2076 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2079 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2080 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2081 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2082 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2083 EXPECTED(ret, True);
2084 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2087 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2088 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2089 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2090 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2091 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2092 150, 4, NULL))) &&
2093 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2094 EXPECTED(ret, True);
2095 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2097 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2098 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2099 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2100 160, 4, NULL)) &&
2101 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2102 EXPECTED(ret, True);
2103 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2105 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2106 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2107 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2108 170, 4, NULL)) &&
2109 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2110 EXPECTED(ret, True);
2111 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2113 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2114 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2115 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2116 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2117 190, 4, NULL)) &&
2118 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2119 EXPECTED(ret, True);
2120 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2122 cli_close(cli1, fnum1);
2123 cli_close(cli2, fnum2);
2124 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2125 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2126 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2127 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2128 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2129 NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2130 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2131 cli_close(cli1, f);
2132 cli_close(cli1, fnum1);
2133 EXPECTED(ret, True);
2134 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2136 fail:
2137 cli_close(cli1, fnum1);
2138 cli_close(cli2, fnum2);
2139 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2140 torture_close_connection(cli1);
2141 torture_close_connection(cli2);
2143 printf("finished locktest4\n");
2144 return correct;
2148 looks at lock upgrade/downgrade.
2150 static bool run_locktest5(int dummy)
2152 static struct cli_state *cli1, *cli2;
2153 const char *fname = "\\lockt5.lck";
2154 uint16_t fnum1, fnum2, fnum3;
2155 bool ret;
2156 char buf[1000];
2157 bool correct = True;
2158 NTSTATUS status;
2160 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2161 return False;
2164 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2165 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2167 printf("starting locktest5\n");
2169 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2171 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2172 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2173 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2175 memset(buf, 0, sizeof(buf));
2177 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2178 NULL);
2179 if (!NT_STATUS_IS_OK(status)) {
2180 printf("Failed to create file: %s\n", nt_errstr(status));
2181 correct = False;
2182 goto fail;
2185 /* Check for NT bug... */
2186 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2187 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2188 cli_close(cli1, fnum1);
2189 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2190 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2191 ret = NT_STATUS_IS_OK(status);
2192 EXPECTED(ret, True);
2193 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2194 cli_close(cli1, fnum1);
2195 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2196 cli_unlock(cli1, fnum3, 0, 1);
2198 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2199 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2200 EXPECTED(ret, True);
2201 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2203 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2204 ret = NT_STATUS_IS_OK(status);
2205 EXPECTED(ret, False);
2207 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2209 /* Unlock the process 2 lock. */
2210 cli_unlock(cli2, fnum2, 0, 4);
2212 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2213 ret = NT_STATUS_IS_OK(status);
2214 EXPECTED(ret, False);
2216 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2218 /* Unlock the process 1 fnum3 lock. */
2219 cli_unlock(cli1, fnum3, 0, 4);
2221 /* Stack 2 more locks here. */
2222 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2223 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2225 EXPECTED(ret, True);
2226 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2228 /* Unlock the first process lock, then check this was the WRITE lock that was
2229 removed. */
2231 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2232 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2234 EXPECTED(ret, True);
2235 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2237 /* Unlock the process 2 lock. */
2238 cli_unlock(cli2, fnum2, 0, 4);
2240 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2242 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2243 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2244 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2246 EXPECTED(ret, True);
2247 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2249 /* Ensure the next unlock fails. */
2250 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2251 EXPECTED(ret, False);
2252 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2254 /* Ensure connection 2 can get a write lock. */
2255 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2256 ret = NT_STATUS_IS_OK(status);
2257 EXPECTED(ret, True);
2259 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2262 fail:
2263 cli_close(cli1, fnum1);
2264 cli_close(cli2, fnum2);
2265 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2266 if (!torture_close_connection(cli1)) {
2267 correct = False;
2269 if (!torture_close_connection(cli2)) {
2270 correct = False;
2273 printf("finished locktest5\n");
2275 return correct;
2279 tries the unusual lockingX locktype bits
2281 static bool run_locktest6(int dummy)
2283 static struct cli_state *cli;
2284 const char *fname[1] = { "\\lock6.txt" };
2285 int i;
2286 uint16_t fnum;
2287 NTSTATUS status;
2289 if (!torture_open_connection(&cli, 0)) {
2290 return False;
2293 smbXcli_conn_set_sockopt(cli->conn, sockops);
2295 printf("starting locktest6\n");
2297 for (i=0;i<1;i++) {
2298 printf("Testing %s\n", fname[i]);
2300 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2302 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2303 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2304 cli_close(cli, fnum);
2305 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2307 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2308 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2309 cli_close(cli, fnum);
2310 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2312 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2315 torture_close_connection(cli);
2317 printf("finished locktest6\n");
2318 return True;
2321 static bool run_locktest7(int dummy)
2323 struct cli_state *cli1;
2324 const char *fname = "\\lockt7.lck";
2325 uint16_t fnum1;
2326 char buf[200];
2327 bool correct = False;
2328 size_t nread;
2329 NTSTATUS status;
2331 if (!torture_open_connection(&cli1, 0)) {
2332 return False;
2335 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2337 printf("starting locktest7\n");
2339 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2341 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2343 memset(buf, 0, sizeof(buf));
2345 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2346 NULL);
2347 if (!NT_STATUS_IS_OK(status)) {
2348 printf("Failed to create file: %s\n", nt_errstr(status));
2349 goto fail;
2352 cli_setpid(cli1, 1);
2354 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2355 if (!NT_STATUS_IS_OK(status)) {
2356 printf("Unable to apply read lock on range 130:4, "
2357 "error was %s\n", nt_errstr(status));
2358 goto fail;
2359 } else {
2360 printf("pid1 successfully locked range 130:4 for READ\n");
2363 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2364 if (!NT_STATUS_IS_OK(status)) {
2365 printf("pid1 unable to read the range 130:4, error was %s\n",
2366 nt_errstr(status));
2367 goto fail;
2368 } else if (nread != 4) {
2369 printf("pid1 unable to read the range 130:4, "
2370 "recv %ld req %d\n", (unsigned long)nread, 4);
2371 goto fail;
2372 } else {
2373 printf("pid1 successfully read the range 130:4\n");
2376 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2377 if (!NT_STATUS_IS_OK(status)) {
2378 printf("pid1 unable to write to the range 130:4, error was "
2379 "%s\n", nt_errstr(status));
2380 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2381 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2382 goto fail;
2384 } else {
2385 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2386 goto fail;
2389 cli_setpid(cli1, 2);
2391 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2392 if (!NT_STATUS_IS_OK(status)) {
2393 printf("pid2 unable to read the range 130:4, error was %s\n",
2394 nt_errstr(status));
2395 goto fail;
2396 } else if (nread != 4) {
2397 printf("pid2 unable to read the range 130:4, "
2398 "recv %ld req %d\n", (unsigned long)nread, 4);
2399 goto fail;
2400 } else {
2401 printf("pid2 successfully read the range 130:4\n");
2404 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2405 if (!NT_STATUS_IS_OK(status)) {
2406 printf("pid2 unable to write to the range 130:4, error was "
2407 "%s\n", nt_errstr(status));
2408 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2409 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2410 goto fail;
2412 } else {
2413 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2414 goto fail;
2417 cli_setpid(cli1, 1);
2418 cli_unlock(cli1, fnum1, 130, 4);
2420 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2421 if (!NT_STATUS_IS_OK(status)) {
2422 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2423 goto fail;
2424 } else {
2425 printf("pid1 successfully locked range 130:4 for WRITE\n");
2428 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2429 if (!NT_STATUS_IS_OK(status)) {
2430 printf("pid1 unable to read the range 130:4, error was %s\n",
2431 nt_errstr(status));
2432 goto fail;
2433 } else if (nread != 4) {
2434 printf("pid1 unable to read the range 130:4, "
2435 "recv %ld req %d\n", (unsigned long)nread, 4);
2436 goto fail;
2437 } else {
2438 printf("pid1 successfully read the range 130:4\n");
2441 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2442 if (!NT_STATUS_IS_OK(status)) {
2443 printf("pid1 unable to write to the range 130:4, error was "
2444 "%s\n", nt_errstr(status));
2445 goto fail;
2446 } else {
2447 printf("pid1 successfully wrote to the range 130:4\n");
2450 cli_setpid(cli1, 2);
2452 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2453 if (!NT_STATUS_IS_OK(status)) {
2454 printf("pid2 unable to read the range 130:4, error was "
2455 "%s\n", nt_errstr(status));
2456 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2457 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2458 goto fail;
2460 } else {
2461 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2462 (unsigned long)nread);
2463 goto fail;
2466 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2467 if (!NT_STATUS_IS_OK(status)) {
2468 printf("pid2 unable to write to the range 130:4, error was "
2469 "%s\n", nt_errstr(status));
2470 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2471 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2472 goto fail;
2474 } else {
2475 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2476 goto fail;
2479 cli_unlock(cli1, fnum1, 130, 0);
2480 correct = True;
2482 fail:
2483 cli_close(cli1, fnum1);
2484 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2485 torture_close_connection(cli1);
2487 printf("finished locktest7\n");
2488 return correct;
2492 * This demonstrates a problem with our use of GPFS share modes: A file
2493 * descriptor sitting in the pending close queue holding a GPFS share mode
2494 * blocks opening a file another time. Happens with Word 2007 temp files.
2495 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2496 * open is denied with NT_STATUS_SHARING_VIOLATION.
2499 static bool run_locktest8(int dummy)
2501 struct cli_state *cli1;
2502 const char *fname = "\\lockt8.lck";
2503 uint16_t fnum1, fnum2;
2504 char buf[200];
2505 bool correct = False;
2506 NTSTATUS status;
2508 if (!torture_open_connection(&cli1, 0)) {
2509 return False;
2512 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2514 printf("starting locktest8\n");
2516 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2518 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2519 &fnum1);
2520 if (!NT_STATUS_IS_OK(status)) {
2521 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2522 return false;
2525 memset(buf, 0, sizeof(buf));
2527 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2528 if (!NT_STATUS_IS_OK(status)) {
2529 d_fprintf(stderr, "cli_openx second time returned %s\n",
2530 nt_errstr(status));
2531 goto fail;
2534 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2535 if (!NT_STATUS_IS_OK(status)) {
2536 printf("Unable to apply read lock on range 1:1, error was "
2537 "%s\n", nt_errstr(status));
2538 goto fail;
2541 status = cli_close(cli1, fnum1);
2542 if (!NT_STATUS_IS_OK(status)) {
2543 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2544 goto fail;
2547 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2548 if (!NT_STATUS_IS_OK(status)) {
2549 d_fprintf(stderr, "cli_openx third time returned %s\n",
2550 nt_errstr(status));
2551 goto fail;
2554 correct = true;
2556 fail:
2557 cli_close(cli1, fnum1);
2558 cli_close(cli1, fnum2);
2559 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2560 torture_close_connection(cli1);
2562 printf("finished locktest8\n");
2563 return correct;
2567 * This test is designed to be run in conjunction with
2568 * external NFS or POSIX locks taken in the filesystem.
2569 * It checks that the smbd server will block until the
2570 * lock is released and then acquire it. JRA.
2573 static bool got_alarm;
2574 static struct cli_state *alarm_cli;
2576 static void alarm_handler(int dummy)
2578 got_alarm = True;
2581 static void alarm_handler_parent(int dummy)
2583 smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_OK);
2586 static void do_local_lock(int read_fd, int write_fd)
2588 int fd;
2589 char c = '\0';
2590 struct flock lock;
2591 const char *local_pathname = NULL;
2592 int ret;
2594 local_pathname = talloc_asprintf(talloc_tos(),
2595 "%s/lockt9.lck", local_path);
2596 if (!local_pathname) {
2597 printf("child: alloc fail\n");
2598 exit(1);
2601 unlink(local_pathname);
2602 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2603 if (fd == -1) {
2604 printf("child: open of %s failed %s.\n",
2605 local_pathname, strerror(errno));
2606 exit(1);
2609 /* Now take a fcntl lock. */
2610 lock.l_type = F_WRLCK;
2611 lock.l_whence = SEEK_SET;
2612 lock.l_start = 0;
2613 lock.l_len = 4;
2614 lock.l_pid = getpid();
2616 ret = fcntl(fd,F_SETLK,&lock);
2617 if (ret == -1) {
2618 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2619 local_pathname, strerror(errno));
2620 exit(1);
2621 } else {
2622 printf("child: got lock 0:4 on file %s.\n",
2623 local_pathname );
2624 fflush(stdout);
2627 CatchSignal(SIGALRM, alarm_handler);
2628 alarm(5);
2629 /* Signal the parent. */
2630 if (write(write_fd, &c, 1) != 1) {
2631 printf("child: start signal fail %s.\n",
2632 strerror(errno));
2633 exit(1);
2635 alarm(0);
2637 alarm(10);
2638 /* Wait for the parent to be ready. */
2639 if (read(read_fd, &c, 1) != 1) {
2640 printf("child: reply signal fail %s.\n",
2641 strerror(errno));
2642 exit(1);
2644 alarm(0);
2646 sleep(5);
2647 close(fd);
2648 printf("child: released lock 0:4 on file %s.\n",
2649 local_pathname );
2650 fflush(stdout);
2651 exit(0);
2654 static bool run_locktest9(int dummy)
2656 struct cli_state *cli1;
2657 const char *fname = "\\lockt9.lck";
2658 uint16_t fnum;
2659 bool correct = False;
2660 int pipe_in[2], pipe_out[2];
2661 pid_t child_pid;
2662 char c = '\0';
2663 int ret;
2664 struct timeval start;
2665 double seconds;
2666 NTSTATUS status;
2668 printf("starting locktest9\n");
2670 if (local_path == NULL) {
2671 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2672 return false;
2675 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2676 return false;
2679 child_pid = fork();
2680 if (child_pid == -1) {
2681 return false;
2684 if (child_pid == 0) {
2685 /* Child. */
2686 do_local_lock(pipe_out[0], pipe_in[1]);
2687 exit(0);
2690 close(pipe_out[0]);
2691 close(pipe_in[1]);
2692 pipe_out[0] = -1;
2693 pipe_in[1] = -1;
2695 /* Parent. */
2696 ret = read(pipe_in[0], &c, 1);
2697 if (ret != 1) {
2698 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2699 strerror(errno));
2700 return false;
2703 if (!torture_open_connection(&cli1, 0)) {
2704 return false;
2707 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2709 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE,
2710 &fnum);
2711 if (!NT_STATUS_IS_OK(status)) {
2712 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2713 return false;
2716 /* Ensure the child has the lock. */
2717 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2718 if (NT_STATUS_IS_OK(status)) {
2719 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2720 goto fail;
2721 } else {
2722 d_printf("Child has the lock.\n");
2725 /* Tell the child to wait 5 seconds then exit. */
2726 ret = write(pipe_out[1], &c, 1);
2727 if (ret != 1) {
2728 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2729 strerror(errno));
2730 goto fail;
2733 /* Wait 20 seconds for the lock. */
2734 alarm_cli = cli1;
2735 CatchSignal(SIGALRM, alarm_handler_parent);
2736 alarm(20);
2738 start = timeval_current();
2740 status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2741 if (!NT_STATUS_IS_OK(status)) {
2742 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2743 "%s\n", nt_errstr(status));
2744 goto fail_nofd;
2746 alarm(0);
2748 seconds = timeval_elapsed(&start);
2750 printf("Parent got the lock after %.2f seconds.\n",
2751 seconds);
2753 status = cli_close(cli1, fnum);
2754 if (!NT_STATUS_IS_OK(status)) {
2755 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2756 goto fail;
2759 correct = true;
2761 fail:
2762 cli_close(cli1, fnum);
2763 torture_close_connection(cli1);
2765 fail_nofd:
2767 printf("finished locktest9\n");
2768 return correct;
2772 test whether fnums and tids open on one VC are available on another (a major
2773 security hole)
2775 static bool run_fdpasstest(int dummy)
2777 struct cli_state *cli1, *cli2;
2778 const char *fname = "\\fdpass.tst";
2779 uint16_t fnum1;
2780 char buf[1024];
2781 NTSTATUS status;
2783 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2784 return False;
2786 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2787 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2789 printf("starting fdpasstest\n");
2791 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2793 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2794 &fnum1);
2795 if (!NT_STATUS_IS_OK(status)) {
2796 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2797 return False;
2800 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2801 13, NULL);
2802 if (!NT_STATUS_IS_OK(status)) {
2803 printf("write failed (%s)\n", nt_errstr(status));
2804 return False;
2807 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
2808 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2809 cli_setpid(cli2, cli_getpid(cli1));
2811 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
2812 printf("read succeeded! nasty security hole [%s]\n", buf);
2813 return false;
2816 cli_close(cli1, fnum1);
2817 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2819 torture_close_connection(cli1);
2820 torture_close_connection(cli2);
2822 printf("finished fdpasstest\n");
2823 return True;
2826 static bool run_fdsesstest(int dummy)
2828 struct cli_state *cli;
2829 uint16 new_vuid;
2830 uint16 saved_vuid;
2831 uint16 new_cnum;
2832 uint16 saved_cnum;
2833 const char *fname = "\\fdsess.tst";
2834 const char *fname1 = "\\fdsess1.tst";
2835 uint16_t fnum1;
2836 uint16_t fnum2;
2837 char buf[1024];
2838 bool ret = True;
2839 NTSTATUS status;
2841 if (!torture_open_connection(&cli, 0))
2842 return False;
2843 smbXcli_conn_set_sockopt(cli->conn, sockops);
2845 if (!torture_cli_session_setup2(cli, &new_vuid))
2846 return False;
2848 saved_cnum = cli_state_get_tid(cli);
2849 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", "", 1)))
2850 return False;
2851 new_cnum = cli_state_get_tid(cli);
2852 cli_state_set_tid(cli, saved_cnum);
2854 printf("starting fdsesstest\n");
2856 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2857 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2859 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2860 if (!NT_STATUS_IS_OK(status)) {
2861 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2862 return False;
2865 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2866 NULL);
2867 if (!NT_STATUS_IS_OK(status)) {
2868 printf("write failed (%s)\n", nt_errstr(status));
2869 return False;
2872 saved_vuid = cli_state_get_uid(cli);
2873 cli_state_set_uid(cli, new_vuid);
2875 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2876 printf("read succeeded with different vuid! "
2877 "nasty security hole [%s]\n", buf);
2878 ret = false;
2880 /* Try to open a file with different vuid, samba cnum. */
2881 if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2882 printf("create with different vuid, same cnum succeeded.\n");
2883 cli_close(cli, fnum2);
2884 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2885 } else {
2886 printf("create with different vuid, same cnum failed.\n");
2887 printf("This will cause problems with service clients.\n");
2888 ret = False;
2891 cli_state_set_uid(cli, saved_vuid);
2893 /* Try with same vuid, different cnum. */
2894 cli_state_set_tid(cli, new_cnum);
2896 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2897 printf("read succeeded with different cnum![%s]\n", buf);
2898 ret = false;
2901 cli_state_set_tid(cli, saved_cnum);
2902 cli_close(cli, fnum1);
2903 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2905 torture_close_connection(cli);
2907 printf("finished fdsesstest\n");
2908 return ret;
2912 This test checks that
2914 1) the server does not allow an unlink on a file that is open
2916 static bool run_unlinktest(int dummy)
2918 struct cli_state *cli;
2919 const char *fname = "\\unlink.tst";
2920 uint16_t fnum;
2921 bool correct = True;
2922 NTSTATUS status;
2924 if (!torture_open_connection(&cli, 0)) {
2925 return False;
2928 smbXcli_conn_set_sockopt(cli->conn, sockops);
2930 printf("starting unlink test\n");
2932 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2934 cli_setpid(cli, 1);
2936 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2937 if (!NT_STATUS_IS_OK(status)) {
2938 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2939 return False;
2942 status = cli_unlink(cli, fname,
2943 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2944 if (NT_STATUS_IS_OK(status)) {
2945 printf("error: server allowed unlink on an open file\n");
2946 correct = False;
2947 } else {
2948 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
2949 NT_STATUS_SHARING_VIOLATION);
2952 cli_close(cli, fnum);
2953 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2955 if (!torture_close_connection(cli)) {
2956 correct = False;
2959 printf("unlink test finished\n");
2961 return correct;
2966 test how many open files this server supports on the one socket
2968 static bool run_maxfidtest(int dummy)
2970 struct cli_state *cli;
2971 fstring fname;
2972 uint16_t fnums[0x11000];
2973 int i;
2974 int retries=4;
2975 bool correct = True;
2976 NTSTATUS status;
2978 cli = current_cli;
2980 if (retries <= 0) {
2981 printf("failed to connect\n");
2982 return False;
2985 smbXcli_conn_set_sockopt(cli->conn, sockops);
2987 for (i=0; i<0x11000; i++) {
2988 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2989 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2990 &fnums[i]);
2991 if (!NT_STATUS_IS_OK(status)) {
2992 printf("open of %s failed (%s)\n",
2993 fname, nt_errstr(status));
2994 printf("maximum fnum is %d\n", i);
2995 break;
2997 printf("%6d\r", i);
2999 printf("%6d\n", i);
3000 i--;
3002 printf("cleaning up\n");
3003 for (;i>=0;i--) {
3004 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3005 cli_close(cli, fnums[i]);
3007 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3008 if (!NT_STATUS_IS_OK(status)) {
3009 printf("unlink of %s failed (%s)\n",
3010 fname, nt_errstr(status));
3011 correct = False;
3013 printf("%6d\r", i);
3015 printf("%6d\n", 0);
3017 printf("maxfid test finished\n");
3018 if (!torture_close_connection(cli)) {
3019 correct = False;
3021 return correct;
3024 /* generate a random buffer */
3025 static void rand_buf(char *buf, int len)
3027 while (len--) {
3028 *buf = (char)sys_random();
3029 buf++;
3033 /* send smb negprot commands, not reading the response */
3034 static bool run_negprot_nowait(int dummy)
3036 struct tevent_context *ev;
3037 int i;
3038 struct cli_state *cli;
3039 bool correct = True;
3041 printf("starting negprot nowait test\n");
3043 ev = tevent_context_init(talloc_tos());
3044 if (ev == NULL) {
3045 return false;
3048 if (!(cli = open_nbt_connection())) {
3049 TALLOC_FREE(ev);
3050 return False;
3053 for (i=0;i<50000;i++) {
3054 struct tevent_req *req;
3056 req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
3057 PROTOCOL_CORE, PROTOCOL_NT1);
3058 if (req == NULL) {
3059 TALLOC_FREE(ev);
3060 return false;
3062 if (!tevent_req_poll(req, ev)) {
3063 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3064 strerror(errno));
3065 TALLOC_FREE(ev);
3066 return false;
3068 TALLOC_FREE(req);
3071 if (torture_close_connection(cli)) {
3072 correct = False;
3075 printf("finished negprot nowait test\n");
3077 return correct;
3080 /* send smb negprot commands, not reading the response */
3081 static bool run_bad_nbt_session(int dummy)
3083 struct nmb_name called, calling;
3084 struct sockaddr_storage ss;
3085 NTSTATUS status;
3086 int fd;
3087 bool ret;
3089 printf("starting bad nbt session test\n");
3091 make_nmb_name(&calling, myname, 0x0);
3092 make_nmb_name(&called , host, 0x20);
3094 if (!resolve_name(host, &ss, 0x20, true)) {
3095 d_fprintf(stderr, "Could not resolve name %s\n", host);
3096 return false;
3099 status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3100 if (!NT_STATUS_IS_OK(status)) {
3101 d_fprintf(stderr, "open_socket_out failed: %s\n",
3102 nt_errstr(status));
3103 return false;
3106 ret = cli_bad_session_request(fd, &calling, &called);
3107 close(fd);
3108 if (!ret) {
3109 d_fprintf(stderr, "open_socket_out failed: %s\n",
3110 nt_errstr(status));
3111 return false;
3114 printf("finished bad nbt session test\n");
3115 return true;
3118 /* send random IPC commands */
3119 static bool run_randomipc(int dummy)
3121 char *rparam = NULL;
3122 char *rdata = NULL;
3123 unsigned int rdrcnt,rprcnt;
3124 char param[1024];
3125 int api, param_len, i;
3126 struct cli_state *cli;
3127 bool correct = True;
3128 int count = 50000;
3130 printf("starting random ipc test\n");
3132 if (!torture_open_connection(&cli, 0)) {
3133 return False;
3136 for (i=0;i<count;i++) {
3137 api = sys_random() % 500;
3138 param_len = (sys_random() % 64);
3140 rand_buf(param, param_len);
3142 SSVAL(param,0,api);
3144 cli_api(cli,
3145 param, param_len, 8,
3146 NULL, 0, BUFFER_SIZE,
3147 &rparam, &rprcnt,
3148 &rdata, &rdrcnt);
3149 if (i % 100 == 0) {
3150 printf("%d/%d\r", i,count);
3153 printf("%d/%d\n", i, count);
3155 if (!torture_close_connection(cli)) {
3156 correct = False;
3159 printf("finished random ipc test\n");
3161 return correct;
3166 static void browse_callback(const char *sname, uint32 stype,
3167 const char *comment, void *state)
3169 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3175 This test checks the browse list code
3178 static bool run_browsetest(int dummy)
3180 static struct cli_state *cli;
3181 bool correct = True;
3183 printf("starting browse test\n");
3185 if (!torture_open_connection(&cli, 0)) {
3186 return False;
3189 printf("domain list:\n");
3190 cli_NetServerEnum(cli, cli->server_domain,
3191 SV_TYPE_DOMAIN_ENUM,
3192 browse_callback, NULL);
3194 printf("machine list:\n");
3195 cli_NetServerEnum(cli, cli->server_domain,
3196 SV_TYPE_ALL,
3197 browse_callback, NULL);
3199 if (!torture_close_connection(cli)) {
3200 correct = False;
3203 printf("browse test finished\n");
3205 return correct;
3211 This checks how the getatr calls works
3213 static bool run_attrtest(int dummy)
3215 struct cli_state *cli;
3216 uint16_t fnum;
3217 time_t t, t2;
3218 const char *fname = "\\attrib123456789.tst";
3219 bool correct = True;
3220 NTSTATUS status;
3222 printf("starting attrib test\n");
3224 if (!torture_open_connection(&cli, 0)) {
3225 return False;
3228 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3229 cli_openx(cli, fname,
3230 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3231 cli_close(cli, fnum);
3233 status = cli_getatr(cli, fname, NULL, NULL, &t);
3234 if (!NT_STATUS_IS_OK(status)) {
3235 printf("getatr failed (%s)\n", nt_errstr(status));
3236 correct = False;
3239 if (abs(t - time(NULL)) > 60*60*24*10) {
3240 printf("ERROR: SMBgetatr bug. time is %s",
3241 ctime(&t));
3242 t = time(NULL);
3243 correct = True;
3246 t2 = t-60*60*24; /* 1 day ago */
3248 status = cli_setatr(cli, fname, 0, t2);
3249 if (!NT_STATUS_IS_OK(status)) {
3250 printf("setatr failed (%s)\n", nt_errstr(status));
3251 correct = True;
3254 status = cli_getatr(cli, fname, NULL, NULL, &t);
3255 if (!NT_STATUS_IS_OK(status)) {
3256 printf("getatr failed (%s)\n", nt_errstr(status));
3257 correct = True;
3260 if (t != t2) {
3261 printf("ERROR: getatr/setatr bug. times are\n%s",
3262 ctime(&t));
3263 printf("%s", ctime(&t2));
3264 correct = True;
3267 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3269 if (!torture_close_connection(cli)) {
3270 correct = False;
3273 printf("attrib test finished\n");
3275 return correct;
3280 This checks a couple of trans2 calls
3282 static bool run_trans2test(int dummy)
3284 struct cli_state *cli;
3285 uint16_t fnum;
3286 off_t size;
3287 time_t c_time, a_time, m_time;
3288 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3289 const char *fname = "\\trans2.tst";
3290 const char *dname = "\\trans2";
3291 const char *fname2 = "\\trans2\\trans2.tst";
3292 char *pname;
3293 bool correct = True;
3294 NTSTATUS status;
3295 uint32_t fs_attr;
3297 printf("starting trans2 test\n");
3299 if (!torture_open_connection(&cli, 0)) {
3300 return False;
3303 status = cli_get_fs_attr_info(cli, &fs_attr);
3304 if (!NT_STATUS_IS_OK(status)) {
3305 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3306 nt_errstr(status));
3307 correct = false;
3310 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3311 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3312 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3313 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3314 if (!NT_STATUS_IS_OK(status)) {
3315 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3316 correct = False;
3319 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3320 if (!NT_STATUS_IS_OK(status)) {
3321 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3322 correct = False;
3325 if (strcmp(pname, fname)) {
3326 printf("qfilename gave different name? [%s] [%s]\n",
3327 fname, pname);
3328 correct = False;
3331 cli_close(cli, fnum);
3333 sleep(2);
3335 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3336 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3337 &fnum);
3338 if (!NT_STATUS_IS_OK(status)) {
3339 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3340 return False;
3342 cli_close(cli, fnum);
3344 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3345 NULL);
3346 if (!NT_STATUS_IS_OK(status)) {
3347 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3348 correct = False;
3349 } else {
3350 time_t t = time(NULL);
3352 if (c_time != m_time) {
3353 printf("create time=%s", ctime(&c_time));
3354 printf("modify time=%s", ctime(&m_time));
3355 printf("This system appears to have sticky create times\n");
3357 if ((abs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
3358 printf("access time=%s", ctime(&a_time));
3359 printf("This system appears to set a midnight access time\n");
3360 correct = False;
3363 if (abs(m_time - t) > 60*60*24*7) {
3364 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3365 correct = False;
3370 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3371 cli_openx(cli, fname,
3372 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3373 cli_close(cli, fnum);
3374 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3375 &m_time_ts, &size, NULL, NULL);
3376 if (!NT_STATUS_IS_OK(status)) {
3377 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3378 correct = False;
3379 } else {
3380 if (w_time_ts.tv_sec < 60*60*24*2) {
3381 printf("write time=%s", ctime(&w_time_ts.tv_sec));
3382 printf("This system appears to set a initial 0 write time\n");
3383 correct = False;
3387 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3390 /* check if the server updates the directory modification time
3391 when creating a new file */
3392 status = cli_mkdir(cli, dname);
3393 if (!NT_STATUS_IS_OK(status)) {
3394 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3395 correct = False;
3397 sleep(3);
3398 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3399 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3400 if (!NT_STATUS_IS_OK(status)) {
3401 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3402 correct = False;
3405 cli_openx(cli, fname2,
3406 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3407 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3408 cli_close(cli, fnum);
3409 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3410 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3411 if (!NT_STATUS_IS_OK(status)) {
3412 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3413 correct = False;
3414 } else {
3415 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3416 == 0) {
3417 printf("This system does not update directory modification times\n");
3418 correct = False;
3421 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3422 cli_rmdir(cli, dname);
3424 if (!torture_close_connection(cli)) {
3425 correct = False;
3428 printf("trans2 test finished\n");
3430 return correct;
3434 This checks new W2K calls.
3437 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3439 uint8_t *buf = NULL;
3440 uint32 len;
3441 NTSTATUS status;
3443 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3444 CLI_BUFFER_SIZE, NULL, &buf, &len);
3445 if (!NT_STATUS_IS_OK(status)) {
3446 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3447 nt_errstr(status));
3448 } else {
3449 printf("qfileinfo: level %d, len = %u\n", level, len);
3450 dump_data(0, (uint8 *)buf, len);
3451 printf("\n");
3453 TALLOC_FREE(buf);
3454 return status;
3457 static bool run_w2ktest(int dummy)
3459 struct cli_state *cli;
3460 uint16_t fnum;
3461 const char *fname = "\\w2ktest\\w2k.tst";
3462 int level;
3463 bool correct = True;
3465 printf("starting w2k test\n");
3467 if (!torture_open_connection(&cli, 0)) {
3468 return False;
3471 cli_openx(cli, fname,
3472 O_RDWR | O_CREAT , DENY_NONE, &fnum);
3474 for (level = 1004; level < 1040; level++) {
3475 new_trans(cli, fnum, level);
3478 cli_close(cli, fnum);
3480 if (!torture_close_connection(cli)) {
3481 correct = False;
3484 printf("w2k test finished\n");
3486 return correct;
3491 this is a harness for some oplock tests
3493 static bool run_oplock1(int dummy)
3495 struct cli_state *cli1;
3496 const char *fname = "\\lockt1.lck";
3497 uint16_t fnum1;
3498 bool correct = True;
3499 NTSTATUS status;
3501 printf("starting oplock test 1\n");
3503 if (!torture_open_connection(&cli1, 0)) {
3504 return False;
3507 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3509 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3511 cli1->use_oplocks = True;
3513 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3514 &fnum1);
3515 if (!NT_STATUS_IS_OK(status)) {
3516 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3517 return False;
3520 cli1->use_oplocks = False;
3522 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3523 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3525 status = cli_close(cli1, fnum1);
3526 if (!NT_STATUS_IS_OK(status)) {
3527 printf("close2 failed (%s)\n", nt_errstr(status));
3528 return False;
3531 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3532 if (!NT_STATUS_IS_OK(status)) {
3533 printf("unlink failed (%s)\n", nt_errstr(status));
3534 return False;
3537 if (!torture_close_connection(cli1)) {
3538 correct = False;
3541 printf("finished oplock test 1\n");
3543 return correct;
3546 static bool run_oplock2(int dummy)
3548 struct cli_state *cli1, *cli2;
3549 const char *fname = "\\lockt2.lck";
3550 uint16_t fnum1, fnum2;
3551 int saved_use_oplocks = use_oplocks;
3552 char buf[4];
3553 bool correct = True;
3554 volatile bool *shared_correct;
3555 size_t nread;
3556 NTSTATUS status;
3558 shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3559 *shared_correct = True;
3561 use_level_II_oplocks = True;
3562 use_oplocks = True;
3564 printf("starting oplock test 2\n");
3566 if (!torture_open_connection(&cli1, 0)) {
3567 use_level_II_oplocks = False;
3568 use_oplocks = saved_use_oplocks;
3569 return False;
3572 if (!torture_open_connection(&cli2, 1)) {
3573 use_level_II_oplocks = False;
3574 use_oplocks = saved_use_oplocks;
3575 return False;
3578 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3580 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3581 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3583 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3584 &fnum1);
3585 if (!NT_STATUS_IS_OK(status)) {
3586 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3587 return False;
3590 /* Don't need the globals any more. */
3591 use_level_II_oplocks = False;
3592 use_oplocks = saved_use_oplocks;
3594 if (fork() == 0) {
3595 /* Child code */
3596 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3597 if (!NT_STATUS_IS_OK(status)) {
3598 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3599 *shared_correct = False;
3600 exit(0);
3603 sleep(2);
3605 status = cli_close(cli2, fnum2);
3606 if (!NT_STATUS_IS_OK(status)) {
3607 printf("close2 failed (%s)\n", nt_errstr(status));
3608 *shared_correct = False;
3611 exit(0);
3614 sleep(2);
3616 /* Ensure cli1 processes the break. Empty file should always return 0
3617 * bytes. */
3618 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
3619 if (!NT_STATUS_IS_OK(status)) {
3620 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
3621 correct = false;
3622 } else if (nread != 0) {
3623 printf("read on empty fnum1 failed. recv %ld expected %d\n",
3624 (unsigned long)nread, 0);
3625 correct = false;
3628 /* Should now be at level II. */
3629 /* Test if sending a write locks causes a break to none. */
3630 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3631 if (!NT_STATUS_IS_OK(status)) {
3632 printf("lock failed (%s)\n", nt_errstr(status));
3633 correct = False;
3636 cli_unlock(cli1, fnum1, 0, 4);
3638 sleep(2);
3640 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3641 if (!NT_STATUS_IS_OK(status)) {
3642 printf("lock failed (%s)\n", nt_errstr(status));
3643 correct = False;
3646 cli_unlock(cli1, fnum1, 0, 4);
3648 sleep(2);
3650 cli_read(cli1, fnum1, buf, 0, 4, NULL);
3652 status = cli_close(cli1, fnum1);
3653 if (!NT_STATUS_IS_OK(status)) {
3654 printf("close1 failed (%s)\n", nt_errstr(status));
3655 correct = False;
3658 sleep(4);
3660 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3661 if (!NT_STATUS_IS_OK(status)) {
3662 printf("unlink failed (%s)\n", nt_errstr(status));
3663 correct = False;
3666 if (!torture_close_connection(cli1)) {
3667 correct = False;
3670 if (!*shared_correct) {
3671 correct = False;
3674 printf("finished oplock test 2\n");
3676 return correct;
3679 struct oplock4_state {
3680 struct tevent_context *ev;
3681 struct cli_state *cli;
3682 bool *got_break;
3683 uint16_t *fnum2;
3686 static void oplock4_got_break(struct tevent_req *req);
3687 static void oplock4_got_open(struct tevent_req *req);
3689 static bool run_oplock4(int dummy)
3691 struct tevent_context *ev;
3692 struct cli_state *cli1, *cli2;
3693 struct tevent_req *oplock_req, *open_req;
3694 const char *fname = "\\lockt4.lck";
3695 const char *fname_ln = "\\lockt4_ln.lck";
3696 uint16_t fnum1, fnum2;
3697 int saved_use_oplocks = use_oplocks;
3698 NTSTATUS status;
3699 bool correct = true;
3701 bool got_break;
3703 struct oplock4_state *state;
3705 printf("starting oplock test 4\n");
3707 if (!torture_open_connection(&cli1, 0)) {
3708 use_level_II_oplocks = false;
3709 use_oplocks = saved_use_oplocks;
3710 return false;
3713 if (!torture_open_connection(&cli2, 1)) {
3714 use_level_II_oplocks = false;
3715 use_oplocks = saved_use_oplocks;
3716 return false;
3719 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3720 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3722 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3723 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3725 /* Create the file. */
3726 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3727 &fnum1);
3728 if (!NT_STATUS_IS_OK(status)) {
3729 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3730 return false;
3733 status = cli_close(cli1, fnum1);
3734 if (!NT_STATUS_IS_OK(status)) {
3735 printf("close1 failed (%s)\n", nt_errstr(status));
3736 return false;
3739 /* Now create a hardlink. */
3740 status = cli_nt_hardlink(cli1, fname, fname_ln);
3741 if (!NT_STATUS_IS_OK(status)) {
3742 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3743 return false;
3746 /* Prove that opening hardlinks cause deny modes to conflict. */
3747 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3748 if (!NT_STATUS_IS_OK(status)) {
3749 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3750 return false;
3753 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3754 if (NT_STATUS_IS_OK(status)) {
3755 printf("open of %s succeeded - should fail with sharing violation.\n",
3756 fname_ln);
3757 return false;
3760 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3761 printf("open of %s should fail with sharing violation. Got %s\n",
3762 fname_ln, nt_errstr(status));
3763 return false;
3766 status = cli_close(cli1, fnum1);
3767 if (!NT_STATUS_IS_OK(status)) {
3768 printf("close1 failed (%s)\n", nt_errstr(status));
3769 return false;
3772 cli1->use_oplocks = true;
3773 cli2->use_oplocks = true;
3775 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3776 if (!NT_STATUS_IS_OK(status)) {
3777 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3778 return false;
3781 ev = tevent_context_init(talloc_tos());
3782 if (ev == NULL) {
3783 printf("tevent_context_init failed\n");
3784 return false;
3787 state = talloc(ev, struct oplock4_state);
3788 if (state == NULL) {
3789 printf("talloc failed\n");
3790 return false;
3792 state->ev = ev;
3793 state->cli = cli1;
3794 state->got_break = &got_break;
3795 state->fnum2 = &fnum2;
3797 oplock_req = cli_smb_oplock_break_waiter_send(
3798 talloc_tos(), ev, cli1);
3799 if (oplock_req == NULL) {
3800 printf("cli_smb_oplock_break_waiter_send failed\n");
3801 return false;
3803 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3805 open_req = cli_openx_send(
3806 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3807 if (open_req == NULL) {
3808 printf("cli_openx_send failed\n");
3809 return false;
3811 tevent_req_set_callback(open_req, oplock4_got_open, state);
3813 got_break = false;
3814 fnum2 = 0xffff;
3816 while (!got_break || fnum2 == 0xffff) {
3817 int ret;
3818 ret = tevent_loop_once(ev);
3819 if (ret == -1) {
3820 printf("tevent_loop_once failed: %s\n",
3821 strerror(errno));
3822 return false;
3826 status = cli_close(cli2, fnum2);
3827 if (!NT_STATUS_IS_OK(status)) {
3828 printf("close2 failed (%s)\n", nt_errstr(status));
3829 correct = false;
3832 status = cli_close(cli1, fnum1);
3833 if (!NT_STATUS_IS_OK(status)) {
3834 printf("close1 failed (%s)\n", nt_errstr(status));
3835 correct = false;
3838 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3839 if (!NT_STATUS_IS_OK(status)) {
3840 printf("unlink failed (%s)\n", nt_errstr(status));
3841 correct = false;
3844 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3845 if (!NT_STATUS_IS_OK(status)) {
3846 printf("unlink failed (%s)\n", nt_errstr(status));
3847 correct = false;
3850 if (!torture_close_connection(cli1)) {
3851 correct = false;
3854 if (!got_break) {
3855 correct = false;
3858 printf("finished oplock test 4\n");
3860 return correct;
3863 static void oplock4_got_break(struct tevent_req *req)
3865 struct oplock4_state *state = tevent_req_callback_data(
3866 req, struct oplock4_state);
3867 uint16_t fnum;
3868 uint8_t level;
3869 NTSTATUS status;
3871 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3872 TALLOC_FREE(req);
3873 if (!NT_STATUS_IS_OK(status)) {
3874 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3875 nt_errstr(status));
3876 return;
3878 *state->got_break = true;
3880 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3881 NO_OPLOCK);
3882 if (req == NULL) {
3883 printf("cli_oplock_ack_send failed\n");
3884 return;
3888 static void oplock4_got_open(struct tevent_req *req)
3890 struct oplock4_state *state = tevent_req_callback_data(
3891 req, struct oplock4_state);
3892 NTSTATUS status;
3894 status = cli_openx_recv(req, state->fnum2);
3895 if (!NT_STATUS_IS_OK(status)) {
3896 printf("cli_openx_recv returned %s\n", nt_errstr(status));
3897 *state->fnum2 = 0xffff;
3902 Test delete on close semantics.
3904 static bool run_deletetest(int dummy)
3906 struct cli_state *cli1 = NULL;
3907 struct cli_state *cli2 = NULL;
3908 const char *fname = "\\delete.file";
3909 uint16_t fnum1 = (uint16_t)-1;
3910 uint16_t fnum2 = (uint16_t)-1;
3911 bool correct = True;
3912 NTSTATUS status;
3914 printf("starting delete test\n");
3916 if (!torture_open_connection(&cli1, 0)) {
3917 return False;
3920 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3922 /* Test 1 - this should delete the file on close. */
3924 cli_setatr(cli1, fname, 0, 0);
3925 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3927 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3928 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3929 FILE_DELETE_ON_CLOSE, 0, &fnum1);
3930 if (!NT_STATUS_IS_OK(status)) {
3931 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3932 correct = False;
3933 goto fail;
3936 status = cli_close(cli1, fnum1);
3937 if (!NT_STATUS_IS_OK(status)) {
3938 printf("[1] close failed (%s)\n", nt_errstr(status));
3939 correct = False;
3940 goto fail;
3943 if (NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1))) {
3944 printf("[1] open of %s succeeded (should fail)\n", fname);
3945 correct = False;
3946 goto fail;
3949 printf("first delete on close test succeeded.\n");
3951 /* Test 2 - this should delete the file on close. */
3953 cli_setatr(cli1, fname, 0, 0);
3954 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3956 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3957 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3958 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3959 if (!NT_STATUS_IS_OK(status)) {
3960 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3961 correct = False;
3962 goto fail;
3965 status = cli_nt_delete_on_close(cli1, fnum1, true);
3966 if (!NT_STATUS_IS_OK(status)) {
3967 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3968 correct = False;
3969 goto fail;
3972 status = cli_close(cli1, fnum1);
3973 if (!NT_STATUS_IS_OK(status)) {
3974 printf("[2] close failed (%s)\n", nt_errstr(status));
3975 correct = False;
3976 goto fail;
3979 if (NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3980 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3981 status = cli_close(cli1, fnum1);
3982 if (!NT_STATUS_IS_OK(status)) {
3983 printf("[2] close failed (%s)\n", nt_errstr(status));
3984 correct = False;
3985 goto fail;
3987 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3988 } else
3989 printf("second delete on close test succeeded.\n");
3991 /* Test 3 - ... */
3992 cli_setatr(cli1, fname, 0, 0);
3993 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3995 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3996 FILE_ATTRIBUTE_NORMAL,
3997 FILE_SHARE_READ|FILE_SHARE_WRITE,
3998 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3999 if (!NT_STATUS_IS_OK(status)) {
4000 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
4001 correct = False;
4002 goto fail;
4005 /* This should fail with a sharing violation - open for delete is only compatible
4006 with SHARE_DELETE. */
4008 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4009 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, &fnum2))) {
4010 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
4011 correct = False;
4012 goto fail;
4015 /* This should succeed. */
4016 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4017 FILE_ATTRIBUTE_NORMAL,
4018 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4019 FILE_OPEN, 0, 0, &fnum2);
4020 if (!NT_STATUS_IS_OK(status)) {
4021 printf("[3] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4022 correct = False;
4023 goto fail;
4026 status = cli_nt_delete_on_close(cli1, fnum1, true);
4027 if (!NT_STATUS_IS_OK(status)) {
4028 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
4029 correct = False;
4030 goto fail;
4033 status = cli_close(cli1, fnum1);
4034 if (!NT_STATUS_IS_OK(status)) {
4035 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
4036 correct = False;
4037 goto fail;
4040 status = cli_close(cli1, fnum2);
4041 if (!NT_STATUS_IS_OK(status)) {
4042 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
4043 correct = False;
4044 goto fail;
4047 /* This should fail - file should no longer be there. */
4049 if (NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4050 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
4051 status = cli_close(cli1, fnum1);
4052 if (!NT_STATUS_IS_OK(status)) {
4053 printf("[3] close failed (%s)\n", nt_errstr(status));
4055 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4056 correct = False;
4057 goto fail;
4058 } else
4059 printf("third delete on close test succeeded.\n");
4061 /* Test 4 ... */
4062 cli_setatr(cli1, fname, 0, 0);
4063 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4065 status = cli_ntcreate(cli1, fname, 0,
4066 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4067 FILE_ATTRIBUTE_NORMAL,
4068 FILE_SHARE_READ|FILE_SHARE_WRITE,
4069 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4070 if (!NT_STATUS_IS_OK(status)) {
4071 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4072 correct = False;
4073 goto fail;
4076 /* This should succeed. */
4077 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4078 FILE_ATTRIBUTE_NORMAL,
4079 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4080 FILE_OPEN, 0, 0, &fnum2);
4081 if (!NT_STATUS_IS_OK(status)) {
4082 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4083 correct = False;
4084 goto fail;
4087 status = cli_close(cli1, fnum2);
4088 if (!NT_STATUS_IS_OK(status)) {
4089 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4090 correct = False;
4091 goto fail;
4094 status = cli_nt_delete_on_close(cli1, fnum1, true);
4095 if (!NT_STATUS_IS_OK(status)) {
4096 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4097 correct = False;
4098 goto fail;
4101 /* This should fail - no more opens once delete on close set. */
4102 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4103 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4104 FILE_OPEN, 0, 0, &fnum2))) {
4105 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
4106 correct = False;
4107 goto fail;
4108 } else
4109 printf("fourth delete on close test succeeded.\n");
4111 status = cli_close(cli1, fnum1);
4112 if (!NT_STATUS_IS_OK(status)) {
4113 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4114 correct = False;
4115 goto fail;
4118 /* Test 5 ... */
4119 cli_setatr(cli1, fname, 0, 0);
4120 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4122 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4123 if (!NT_STATUS_IS_OK(status)) {
4124 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4125 correct = False;
4126 goto fail;
4129 /* This should fail - only allowed on NT opens with DELETE access. */
4131 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4132 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4133 correct = False;
4134 goto fail;
4137 status = cli_close(cli1, fnum1);
4138 if (!NT_STATUS_IS_OK(status)) {
4139 printf("[5] close - 2 failed (%s)\n", nt_errstr(status));
4140 correct = False;
4141 goto fail;
4144 printf("fifth delete on close test succeeded.\n");
4146 /* Test 6 ... */
4147 cli_setatr(cli1, fname, 0, 0);
4148 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4150 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4151 FILE_ATTRIBUTE_NORMAL,
4152 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4153 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4154 if (!NT_STATUS_IS_OK(status)) {
4155 printf("[6] open of %s failed (%s)\n", fname,
4156 nt_errstr(status));
4157 correct = False;
4158 goto fail;
4161 /* This should fail - only allowed on NT opens with DELETE access. */
4163 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4164 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4165 correct = False;
4166 goto fail;
4169 status = cli_close(cli1, fnum1);
4170 if (!NT_STATUS_IS_OK(status)) {
4171 printf("[6] close - 2 failed (%s)\n", nt_errstr(status));
4172 correct = False;
4173 goto fail;
4176 printf("sixth delete on close test succeeded.\n");
4178 /* Test 7 ... */
4179 cli_setatr(cli1, fname, 0, 0);
4180 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4182 status = cli_ntcreate(cli1, fname, 0,
4183 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4184 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4185 0, 0, &fnum1);
4186 if (!NT_STATUS_IS_OK(status)) {
4187 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4188 correct = False;
4189 goto fail;
4192 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4193 printf("[7] setting delete_on_close on file failed !\n");
4194 correct = False;
4195 goto fail;
4198 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, false))) {
4199 printf("[7] unsetting delete_on_close on file failed !\n");
4200 correct = False;
4201 goto fail;
4204 status = cli_close(cli1, fnum1);
4205 if (!NT_STATUS_IS_OK(status)) {
4206 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4207 correct = False;
4208 goto fail;
4211 /* This next open should succeed - we reset the flag. */
4212 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4213 if (!NT_STATUS_IS_OK(status)) {
4214 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4215 correct = False;
4216 goto fail;
4219 status = cli_close(cli1, fnum1);
4220 if (!NT_STATUS_IS_OK(status)) {
4221 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4222 correct = False;
4223 goto fail;
4226 printf("seventh delete on close test succeeded.\n");
4228 /* Test 7 ... */
4229 cli_setatr(cli1, fname, 0, 0);
4230 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4232 if (!torture_open_connection(&cli2, 1)) {
4233 printf("[8] failed to open second connection.\n");
4234 correct = False;
4235 goto fail;
4238 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4240 status = cli_ntcreate(cli1, fname, 0,
4241 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4242 FILE_ATTRIBUTE_NORMAL,
4243 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4244 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4245 if (!NT_STATUS_IS_OK(status)) {
4246 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4247 correct = False;
4248 goto fail;
4251 status = cli_ntcreate(cli2, fname, 0,
4252 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4253 FILE_ATTRIBUTE_NORMAL,
4254 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4255 FILE_OPEN, 0, 0, &fnum2);
4256 if (!NT_STATUS_IS_OK(status)) {
4257 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4258 correct = False;
4259 goto fail;
4262 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4263 printf("[8] setting delete_on_close on file failed !\n");
4264 correct = False;
4265 goto fail;
4268 status = cli_close(cli1, fnum1);
4269 if (!NT_STATUS_IS_OK(status)) {
4270 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4271 correct = False;
4272 goto fail;
4275 status = cli_close(cli2, fnum2);
4276 if (!NT_STATUS_IS_OK(status)) {
4277 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4278 correct = False;
4279 goto fail;
4282 /* This should fail.. */
4283 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4284 if (NT_STATUS_IS_OK(status)) {
4285 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4286 goto fail;
4287 correct = False;
4288 } else
4289 printf("eighth delete on close test succeeded.\n");
4291 /* This should fail - we need to set DELETE_ACCESS. */
4292 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,FILE_READ_DATA|FILE_WRITE_DATA,
4293 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
4294 printf("[9] open of %s succeeded should have failed!\n", fname);
4295 correct = False;
4296 goto fail;
4299 printf("ninth delete on close test succeeded.\n");
4301 status = cli_ntcreate(cli1, fname, 0,
4302 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4303 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4304 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4305 0, &fnum1);
4306 if (!NT_STATUS_IS_OK(status)) {
4307 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4308 correct = False;
4309 goto fail;
4312 /* This should delete the file. */
4313 status = cli_close(cli1, fnum1);
4314 if (!NT_STATUS_IS_OK(status)) {
4315 printf("[10] close failed (%s)\n", nt_errstr(status));
4316 correct = False;
4317 goto fail;
4320 /* This should fail.. */
4321 if (NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4322 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4323 goto fail;
4324 correct = False;
4325 } else
4326 printf("tenth delete on close test succeeded.\n");
4328 cli_setatr(cli1, fname, 0, 0);
4329 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4331 /* What error do we get when attempting to open a read-only file with
4332 delete access ? */
4334 /* Create a readonly file. */
4335 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4336 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4337 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4338 if (!NT_STATUS_IS_OK(status)) {
4339 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4340 correct = False;
4341 goto fail;
4344 status = cli_close(cli1, fnum1);
4345 if (!NT_STATUS_IS_OK(status)) {
4346 printf("[11] close failed (%s)\n", nt_errstr(status));
4347 correct = False;
4348 goto fail;
4351 /* Now try open for delete access. */
4352 status = cli_ntcreate(cli1, fname, 0,
4353 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4355 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4356 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4357 if (NT_STATUS_IS_OK(status)) {
4358 printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
4359 cli_close(cli1, fnum1);
4360 goto fail;
4361 correct = False;
4362 } else {
4363 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
4364 printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(status));
4365 goto fail;
4366 correct = False;
4367 } else {
4368 printf("eleventh delete on close test succeeded.\n");
4372 printf("finished delete test\n");
4374 fail:
4375 /* FIXME: This will crash if we aborted before cli2 got
4376 * intialized, because these functions don't handle
4377 * uninitialized connections. */
4379 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4380 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4381 cli_setatr(cli1, fname, 0, 0);
4382 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4384 if (cli1 && !torture_close_connection(cli1)) {
4385 correct = False;
4387 if (cli2 && !torture_close_connection(cli2)) {
4388 correct = False;
4390 return correct;
4393 static bool run_deletetest_ln(int dummy)
4395 struct cli_state *cli;
4396 const char *fname = "\\delete1";
4397 const char *fname_ln = "\\delete1_ln";
4398 uint16_t fnum;
4399 uint16_t fnum1;
4400 NTSTATUS status;
4401 bool correct = true;
4402 time_t t;
4404 printf("starting deletetest-ln\n");
4406 if (!torture_open_connection(&cli, 0)) {
4407 return false;
4410 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4411 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4413 smbXcli_conn_set_sockopt(cli->conn, sockops);
4415 /* Create the file. */
4416 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4417 if (!NT_STATUS_IS_OK(status)) {
4418 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4419 return false;
4422 status = cli_close(cli, fnum);
4423 if (!NT_STATUS_IS_OK(status)) {
4424 printf("close1 failed (%s)\n", nt_errstr(status));
4425 return false;
4428 /* Now create a hardlink. */
4429 status = cli_nt_hardlink(cli, fname, fname_ln);
4430 if (!NT_STATUS_IS_OK(status)) {
4431 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4432 return false;
4435 /* Open the original file. */
4436 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4437 FILE_ATTRIBUTE_NORMAL,
4438 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4439 FILE_OPEN_IF, 0, 0, &fnum);
4440 if (!NT_STATUS_IS_OK(status)) {
4441 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4442 return false;
4445 /* Unlink the hard link path. */
4446 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4447 FILE_ATTRIBUTE_NORMAL,
4448 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4449 FILE_OPEN_IF, 0, 0, &fnum1);
4450 if (!NT_STATUS_IS_OK(status)) {
4451 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4452 return false;
4454 status = cli_nt_delete_on_close(cli, fnum1, true);
4455 if (!NT_STATUS_IS_OK(status)) {
4456 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4457 __location__, fname_ln, nt_errstr(status));
4458 return false;
4461 status = cli_close(cli, fnum1);
4462 if (!NT_STATUS_IS_OK(status)) {
4463 printf("close %s failed (%s)\n",
4464 fname_ln, nt_errstr(status));
4465 return false;
4468 status = cli_close(cli, fnum);
4469 if (!NT_STATUS_IS_OK(status)) {
4470 printf("close %s failed (%s)\n",
4471 fname, nt_errstr(status));
4472 return false;
4475 /* Ensure the original file is still there. */
4476 status = cli_getatr(cli, fname, NULL, NULL, &t);
4477 if (!NT_STATUS_IS_OK(status)) {
4478 printf("%s getatr on file %s failed (%s)\n",
4479 __location__,
4480 fname,
4481 nt_errstr(status));
4482 correct = False;
4485 /* Ensure the link path is gone. */
4486 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4487 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4488 printf("%s, getatr for file %s returned wrong error code %s "
4489 "- should have been deleted\n",
4490 __location__,
4491 fname_ln, nt_errstr(status));
4492 correct = False;
4495 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4496 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4498 if (!torture_close_connection(cli)) {
4499 correct = false;
4502 printf("finished deletetest-ln\n");
4504 return correct;
4508 print out server properties
4510 static bool run_properties(int dummy)
4512 struct cli_state *cli;
4513 bool correct = True;
4515 printf("starting properties test\n");
4517 ZERO_STRUCT(cli);
4519 if (!torture_open_connection(&cli, 0)) {
4520 return False;
4523 smbXcli_conn_set_sockopt(cli->conn, sockops);
4525 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
4527 if (!torture_close_connection(cli)) {
4528 correct = False;
4531 return correct;
4536 /* FIRST_DESIRED_ACCESS 0xf019f */
4537 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4538 FILE_READ_EA| /* 0xf */ \
4539 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
4540 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
4541 DELETE_ACCESS|READ_CONTROL_ACCESS|\
4542 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
4543 /* SECOND_DESIRED_ACCESS 0xe0080 */
4544 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4545 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4546 WRITE_OWNER_ACCESS /* 0xe0000 */
4548 #if 0
4549 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4550 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4551 FILE_READ_DATA|\
4552 WRITE_OWNER_ACCESS /* */
4553 #endif
4556 Test ntcreate calls made by xcopy
4558 static bool run_xcopy(int dummy)
4560 static struct cli_state *cli1;
4561 const char *fname = "\\test.txt";
4562 bool correct = True;
4563 uint16_t fnum1, fnum2;
4564 NTSTATUS status;
4566 printf("starting xcopy test\n");
4568 if (!torture_open_connection(&cli1, 0)) {
4569 return False;
4572 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4573 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4574 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1);
4575 if (!NT_STATUS_IS_OK(status)) {
4576 printf("First open failed - %s\n", nt_errstr(status));
4577 return False;
4580 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4581 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4582 FILE_OPEN, 0x200000, 0, &fnum2);
4583 if (!NT_STATUS_IS_OK(status)) {
4584 printf("second open failed - %s\n", nt_errstr(status));
4585 return False;
4588 if (!torture_close_connection(cli1)) {
4589 correct = False;
4592 return correct;
4596 Test rename on files open with share delete and no share delete.
4598 static bool run_rename(int dummy)
4600 static struct cli_state *cli1;
4601 const char *fname = "\\test.txt";
4602 const char *fname1 = "\\test1.txt";
4603 bool correct = True;
4604 uint16_t fnum1;
4605 uint16_t attr;
4606 NTSTATUS status;
4608 printf("starting rename test\n");
4610 if (!torture_open_connection(&cli1, 0)) {
4611 return False;
4614 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4615 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4617 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4618 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4619 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4620 if (!NT_STATUS_IS_OK(status)) {
4621 printf("First open failed - %s\n", nt_errstr(status));
4622 return False;
4625 status = cli_rename(cli1, fname, fname1);
4626 if (!NT_STATUS_IS_OK(status)) {
4627 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4628 } else {
4629 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4630 correct = False;
4633 status = cli_close(cli1, fnum1);
4634 if (!NT_STATUS_IS_OK(status)) {
4635 printf("close - 1 failed (%s)\n", nt_errstr(status));
4636 return False;
4639 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4640 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4641 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4642 #if 0
4643 FILE_SHARE_DELETE|FILE_SHARE_NONE,
4644 #else
4645 FILE_SHARE_DELETE|FILE_SHARE_READ,
4646 #endif
4647 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4648 if (!NT_STATUS_IS_OK(status)) {
4649 printf("Second open failed - %s\n", nt_errstr(status));
4650 return False;
4653 status = cli_rename(cli1, fname, fname1);
4654 if (!NT_STATUS_IS_OK(status)) {
4655 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4656 correct = False;
4657 } else {
4658 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4661 status = cli_close(cli1, fnum1);
4662 if (!NT_STATUS_IS_OK(status)) {
4663 printf("close - 2 failed (%s)\n", nt_errstr(status));
4664 return False;
4667 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4668 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4670 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4671 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4672 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4673 if (!NT_STATUS_IS_OK(status)) {
4674 printf("Third open failed - %s\n", nt_errstr(status));
4675 return False;
4679 #if 0
4681 uint16_t fnum2;
4683 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4684 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4685 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4686 return False;
4688 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4689 printf("[8] setting delete_on_close on file failed !\n");
4690 return False;
4693 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4694 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4695 return False;
4698 #endif
4700 status = cli_rename(cli1, fname, fname1);
4701 if (!NT_STATUS_IS_OK(status)) {
4702 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4703 correct = False;
4704 } else {
4705 printf("Third rename succeeded (SHARE_NONE)\n");
4708 status = cli_close(cli1, fnum1);
4709 if (!NT_STATUS_IS_OK(status)) {
4710 printf("close - 3 failed (%s)\n", nt_errstr(status));
4711 return False;
4714 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4715 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4717 /*----*/
4719 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4720 FILE_ATTRIBUTE_NORMAL,
4721 FILE_SHARE_READ | FILE_SHARE_WRITE,
4722 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4723 if (!NT_STATUS_IS_OK(status)) {
4724 printf("Fourth open failed - %s\n", nt_errstr(status));
4725 return False;
4728 status = cli_rename(cli1, fname, fname1);
4729 if (!NT_STATUS_IS_OK(status)) {
4730 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4731 } else {
4732 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4733 correct = False;
4736 status = cli_close(cli1, fnum1);
4737 if (!NT_STATUS_IS_OK(status)) {
4738 printf("close - 4 failed (%s)\n", nt_errstr(status));
4739 return False;
4742 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4743 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4745 /*--*/
4747 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4748 FILE_ATTRIBUTE_NORMAL,
4749 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4750 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4751 if (!NT_STATUS_IS_OK(status)) {
4752 printf("Fifth open failed - %s\n", nt_errstr(status));
4753 return False;
4756 status = cli_rename(cli1, fname, fname1);
4757 if (!NT_STATUS_IS_OK(status)) {
4758 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4759 correct = False;
4760 } else {
4761 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4765 * Now check if the first name still exists ...
4768 /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4769 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4770 printf("Opening original file after rename of open file fails: %s\n",
4771 cli_errstr(cli1));
4773 else {
4774 printf("Opening original file after rename of open file works ...\n");
4775 (void)cli_close(cli1, fnum2);
4776 } */
4778 /*--*/
4779 status = cli_close(cli1, fnum1);
4780 if (!NT_STATUS_IS_OK(status)) {
4781 printf("close - 5 failed (%s)\n", nt_errstr(status));
4782 return False;
4785 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4786 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4787 if (!NT_STATUS_IS_OK(status)) {
4788 printf("getatr on file %s failed - %s ! \n",
4789 fname1, nt_errstr(status));
4790 correct = False;
4791 } else {
4792 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4793 printf("Renamed file %s has wrong attr 0x%x "
4794 "(should be 0x%x)\n",
4795 fname1,
4796 attr,
4797 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4798 correct = False;
4799 } else {
4800 printf("Renamed file %s has archive bit set\n", fname1);
4804 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4805 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4807 if (!torture_close_connection(cli1)) {
4808 correct = False;
4811 return correct;
4814 static bool run_pipe_number(int dummy)
4816 struct cli_state *cli1;
4817 const char *pipe_name = "\\SPOOLSS";
4818 uint16_t fnum;
4819 int num_pipes = 0;
4820 NTSTATUS status;
4822 printf("starting pipenumber test\n");
4823 if (!torture_open_connection(&cli1, 0)) {
4824 return False;
4827 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4828 while(1) {
4829 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
4830 FILE_ATTRIBUTE_NORMAL,
4831 FILE_SHARE_READ|FILE_SHARE_WRITE,
4832 FILE_OPEN_IF, 0, 0, &fnum);
4833 if (!NT_STATUS_IS_OK(status)) {
4834 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
4835 break;
4837 num_pipes++;
4838 printf("\r%6d", num_pipes);
4841 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4842 torture_close_connection(cli1);
4843 return True;
4847 Test open mode returns on read-only files.
4849 static bool run_opentest(int dummy)
4851 static struct cli_state *cli1;
4852 static struct cli_state *cli2;
4853 const char *fname = "\\readonly.file";
4854 uint16_t fnum1, fnum2;
4855 char buf[20];
4856 off_t fsize;
4857 bool correct = True;
4858 char *tmp_path;
4859 NTSTATUS status;
4861 printf("starting open test\n");
4863 if (!torture_open_connection(&cli1, 0)) {
4864 return False;
4867 cli_setatr(cli1, fname, 0, 0);
4868 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4870 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4872 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4873 if (!NT_STATUS_IS_OK(status)) {
4874 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4875 return False;
4878 status = cli_close(cli1, fnum1);
4879 if (!NT_STATUS_IS_OK(status)) {
4880 printf("close2 failed (%s)\n", nt_errstr(status));
4881 return False;
4884 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
4885 if (!NT_STATUS_IS_OK(status)) {
4886 printf("cli_setatr failed (%s)\n", nt_errstr(status));
4887 return False;
4890 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4891 if (!NT_STATUS_IS_OK(status)) {
4892 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4893 return False;
4896 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4897 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4899 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
4900 NT_STATUS_ACCESS_DENIED)) {
4901 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4904 printf("finished open test 1\n");
4906 cli_close(cli1, fnum1);
4908 /* Now try not readonly and ensure ERRbadshare is returned. */
4910 cli_setatr(cli1, fname, 0, 0);
4912 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4913 if (!NT_STATUS_IS_OK(status)) {
4914 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4915 return False;
4918 /* This will fail - but the error should be ERRshare. */
4919 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4921 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
4922 NT_STATUS_SHARING_VIOLATION)) {
4923 printf("correct error code ERRDOS/ERRbadshare returned\n");
4926 status = cli_close(cli1, fnum1);
4927 if (!NT_STATUS_IS_OK(status)) {
4928 printf("close2 failed (%s)\n", nt_errstr(status));
4929 return False;
4932 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4934 printf("finished open test 2\n");
4936 /* Test truncate open disposition on file opened for read. */
4937 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4938 if (!NT_STATUS_IS_OK(status)) {
4939 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
4940 return False;
4943 /* write 20 bytes. */
4945 memset(buf, '\0', 20);
4947 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
4948 if (!NT_STATUS_IS_OK(status)) {
4949 printf("write failed (%s)\n", nt_errstr(status));
4950 correct = False;
4953 status = cli_close(cli1, fnum1);
4954 if (!NT_STATUS_IS_OK(status)) {
4955 printf("(3) close1 failed (%s)\n", nt_errstr(status));
4956 return False;
4959 /* Ensure size == 20. */
4960 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4961 if (!NT_STATUS_IS_OK(status)) {
4962 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4963 return False;
4966 if (fsize != 20) {
4967 printf("(3) file size != 20\n");
4968 return False;
4971 /* Now test if we can truncate a file opened for readonly. */
4972 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
4973 if (!NT_STATUS_IS_OK(status)) {
4974 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
4975 return False;
4978 status = cli_close(cli1, fnum1);
4979 if (!NT_STATUS_IS_OK(status)) {
4980 printf("close2 failed (%s)\n", nt_errstr(status));
4981 return False;
4984 /* Ensure size == 0. */
4985 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4986 if (!NT_STATUS_IS_OK(status)) {
4987 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4988 return False;
4991 if (fsize != 0) {
4992 printf("(3) file size != 0\n");
4993 return False;
4995 printf("finished open test 3\n");
4997 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4999 printf("Do ctemp tests\n");
5000 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
5001 if (!NT_STATUS_IS_OK(status)) {
5002 printf("ctemp failed (%s)\n", nt_errstr(status));
5003 return False;
5006 printf("ctemp gave path %s\n", tmp_path);
5007 status = cli_close(cli1, fnum1);
5008 if (!NT_STATUS_IS_OK(status)) {
5009 printf("close of temp failed (%s)\n", nt_errstr(status));
5012 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5013 if (!NT_STATUS_IS_OK(status)) {
5014 printf("unlink of temp failed (%s)\n", nt_errstr(status));
5017 /* Test the non-io opens... */
5019 if (!torture_open_connection(&cli2, 1)) {
5020 return False;
5023 cli_setatr(cli2, fname, 0, 0);
5024 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5026 smbXcli_conn_set_sockopt(cli2->conn, sockops);
5028 printf("TEST #1 testing 2 non-io opens (no delete)\n");
5029 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5030 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5031 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5032 if (!NT_STATUS_IS_OK(status)) {
5033 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5034 return False;
5037 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5038 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5039 FILE_OPEN_IF, 0, 0, &fnum2);
5040 if (!NT_STATUS_IS_OK(status)) {
5041 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5042 return False;
5045 status = cli_close(cli1, fnum1);
5046 if (!NT_STATUS_IS_OK(status)) {
5047 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5048 return False;
5051 status = cli_close(cli2, fnum2);
5052 if (!NT_STATUS_IS_OK(status)) {
5053 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5054 return False;
5057 printf("non-io open test #1 passed.\n");
5059 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5061 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5063 status = cli_ntcreate(cli1, fname, 0,
5064 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5065 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5066 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5067 if (!NT_STATUS_IS_OK(status)) {
5068 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5069 return False;
5072 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5073 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5074 FILE_OPEN_IF, 0, 0, &fnum2);
5075 if (!NT_STATUS_IS_OK(status)) {
5076 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5077 return False;
5080 status = cli_close(cli1, fnum1);
5081 if (!NT_STATUS_IS_OK(status)) {
5082 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5083 return False;
5086 status = cli_close(cli2, fnum2);
5087 if (!NT_STATUS_IS_OK(status)) {
5088 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5089 return False;
5092 printf("non-io open test #2 passed.\n");
5094 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5096 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5098 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5099 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5100 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5101 if (!NT_STATUS_IS_OK(status)) {
5102 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5103 return False;
5106 status = cli_ntcreate(cli2, fname, 0,
5107 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5108 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5109 FILE_OPEN_IF, 0, 0, &fnum2);
5110 if (!NT_STATUS_IS_OK(status)) {
5111 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5112 return False;
5115 status = cli_close(cli1, fnum1);
5116 if (!NT_STATUS_IS_OK(status)) {
5117 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5118 return False;
5121 status = cli_close(cli2, fnum2);
5122 if (!NT_STATUS_IS_OK(status)) {
5123 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5124 return False;
5127 printf("non-io open test #3 passed.\n");
5129 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5131 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5133 status = cli_ntcreate(cli1, fname, 0,
5134 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5135 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5136 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5137 if (!NT_STATUS_IS_OK(status)) {
5138 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5139 return False;
5142 status = cli_ntcreate(cli2, fname, 0,
5143 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5144 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5145 FILE_OPEN_IF, 0, 0, &fnum2);
5146 if (NT_STATUS_IS_OK(status)) {
5147 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5148 return False;
5151 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5153 status = cli_close(cli1, fnum1);
5154 if (!NT_STATUS_IS_OK(status)) {
5155 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5156 return False;
5159 printf("non-io open test #4 passed.\n");
5161 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5163 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5165 status = cli_ntcreate(cli1, fname, 0,
5166 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5167 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5168 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5169 if (!NT_STATUS_IS_OK(status)) {
5170 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5171 return False;
5174 status = cli_ntcreate(cli2, fname, 0,
5175 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5176 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5177 FILE_OPEN_IF, 0, 0, &fnum2);
5178 if (!NT_STATUS_IS_OK(status)) {
5179 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5180 return False;
5183 status = cli_close(cli1, fnum1);
5184 if (!NT_STATUS_IS_OK(status)) {
5185 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5186 return False;
5189 status = cli_close(cli2, fnum2);
5190 if (!NT_STATUS_IS_OK(status)) {
5191 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5192 return False;
5195 printf("non-io open test #5 passed.\n");
5197 printf("TEST #6 testing 1 non-io open, one io open\n");
5199 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5201 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5202 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5203 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5204 if (!NT_STATUS_IS_OK(status)) {
5205 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5206 return False;
5209 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5210 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5211 FILE_OPEN_IF, 0, 0, &fnum2);
5212 if (!NT_STATUS_IS_OK(status)) {
5213 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5214 return False;
5217 status = cli_close(cli1, fnum1);
5218 if (!NT_STATUS_IS_OK(status)) {
5219 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5220 return False;
5223 status = cli_close(cli2, fnum2);
5224 if (!NT_STATUS_IS_OK(status)) {
5225 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5226 return False;
5229 printf("non-io open test #6 passed.\n");
5231 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5233 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5235 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5236 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5237 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5238 if (!NT_STATUS_IS_OK(status)) {
5239 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5240 return False;
5243 status = cli_ntcreate(cli2, fname, 0,
5244 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5245 FILE_ATTRIBUTE_NORMAL,
5246 FILE_SHARE_READ|FILE_SHARE_DELETE,
5247 FILE_OPEN_IF, 0, 0, &fnum2);
5248 if (NT_STATUS_IS_OK(status)) {
5249 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5250 return False;
5253 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5255 status = cli_close(cli1, fnum1);
5256 if (!NT_STATUS_IS_OK(status)) {
5257 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5258 return False;
5261 printf("non-io open test #7 passed.\n");
5263 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5265 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5266 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5267 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5268 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5269 if (!NT_STATUS_IS_OK(status)) {
5270 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5271 correct = false;
5272 goto out;
5275 /* Write to ensure we have to update the file time. */
5276 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5277 NULL);
5278 if (!NT_STATUS_IS_OK(status)) {
5279 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5280 correct = false;
5281 goto out;
5284 status = cli_close(cli1, fnum1);
5285 if (!NT_STATUS_IS_OK(status)) {
5286 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5287 correct = false;
5290 out:
5292 if (!torture_close_connection(cli1)) {
5293 correct = False;
5295 if (!torture_close_connection(cli2)) {
5296 correct = False;
5299 return correct;
5302 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5304 uint16 major, minor;
5305 uint32 caplow, caphigh;
5306 NTSTATUS status;
5308 if (!SERVER_HAS_UNIX_CIFS(cli)) {
5309 printf("Server doesn't support UNIX CIFS extensions.\n");
5310 return NT_STATUS_NOT_SUPPORTED;
5313 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5314 &caphigh);
5315 if (!NT_STATUS_IS_OK(status)) {
5316 printf("Server didn't return UNIX CIFS extensions: %s\n",
5317 nt_errstr(status));
5318 return status;
5321 status = cli_set_unix_extensions_capabilities(cli, major, minor,
5322 caplow, caphigh);
5323 if (!NT_STATUS_IS_OK(status)) {
5324 printf("Server doesn't support setting UNIX CIFS extensions: "
5325 "%s.\n", nt_errstr(status));
5326 return status;
5329 return NT_STATUS_OK;
5333 Test POSIX open /mkdir calls.
5335 static bool run_simple_posix_open_test(int dummy)
5337 static struct cli_state *cli1;
5338 const char *fname = "posix:file";
5339 const char *hname = "posix:hlink";
5340 const char *sname = "posix:symlink";
5341 const char *dname = "posix:dir";
5342 char buf[10];
5343 char namebuf[11];
5344 uint16_t fnum1 = (uint16_t)-1;
5345 SMB_STRUCT_STAT sbuf;
5346 bool correct = false;
5347 NTSTATUS status;
5348 size_t nread;
5350 printf("Starting simple POSIX open test\n");
5352 if (!torture_open_connection(&cli1, 0)) {
5353 return false;
5356 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5358 status = torture_setup_unix_extensions(cli1);
5359 if (!NT_STATUS_IS_OK(status)) {
5360 return false;
5363 cli_setatr(cli1, fname, 0, 0);
5364 cli_posix_unlink(cli1, fname);
5365 cli_setatr(cli1, dname, 0, 0);
5366 cli_posix_rmdir(cli1, dname);
5367 cli_setatr(cli1, hname, 0, 0);
5368 cli_posix_unlink(cli1, hname);
5369 cli_setatr(cli1, sname, 0, 0);
5370 cli_posix_unlink(cli1, sname);
5372 /* Create a directory. */
5373 status = cli_posix_mkdir(cli1, dname, 0777);
5374 if (!NT_STATUS_IS_OK(status)) {
5375 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5376 goto out;
5379 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5380 0600, &fnum1);
5381 if (!NT_STATUS_IS_OK(status)) {
5382 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5383 goto out;
5386 /* Test ftruncate - set file size. */
5387 status = cli_ftruncate(cli1, fnum1, 1000);
5388 if (!NT_STATUS_IS_OK(status)) {
5389 printf("ftruncate failed (%s)\n", nt_errstr(status));
5390 goto out;
5393 /* Ensure st_size == 1000 */
5394 status = cli_posix_stat(cli1, fname, &sbuf);
5395 if (!NT_STATUS_IS_OK(status)) {
5396 printf("stat failed (%s)\n", nt_errstr(status));
5397 goto out;
5400 if (sbuf.st_ex_size != 1000) {
5401 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5402 goto out;
5405 /* Test ftruncate - set file size back to zero. */
5406 status = cli_ftruncate(cli1, fnum1, 0);
5407 if (!NT_STATUS_IS_OK(status)) {
5408 printf("ftruncate failed (%s)\n", nt_errstr(status));
5409 goto out;
5412 status = cli_close(cli1, fnum1);
5413 if (!NT_STATUS_IS_OK(status)) {
5414 printf("close failed (%s)\n", nt_errstr(status));
5415 goto out;
5418 /* Now open the file again for read only. */
5419 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5420 if (!NT_STATUS_IS_OK(status)) {
5421 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5422 goto out;
5425 /* Now unlink while open. */
5426 status = cli_posix_unlink(cli1, fname);
5427 if (!NT_STATUS_IS_OK(status)) {
5428 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5429 goto out;
5432 status = cli_close(cli1, fnum1);
5433 if (!NT_STATUS_IS_OK(status)) {
5434 printf("close(2) failed (%s)\n", nt_errstr(status));
5435 goto out;
5438 /* Ensure the file has gone. */
5439 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5440 if (NT_STATUS_IS_OK(status)) {
5441 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5442 goto out;
5445 /* Create again to test open with O_TRUNC. */
5446 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
5447 if (!NT_STATUS_IS_OK(status)) {
5448 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5449 goto out;
5452 /* Test ftruncate - set file size. */
5453 status = cli_ftruncate(cli1, fnum1, 1000);
5454 if (!NT_STATUS_IS_OK(status)) {
5455 printf("ftruncate failed (%s)\n", nt_errstr(status));
5456 goto out;
5459 /* Ensure st_size == 1000 */
5460 status = cli_posix_stat(cli1, fname, &sbuf);
5461 if (!NT_STATUS_IS_OK(status)) {
5462 printf("stat failed (%s)\n", nt_errstr(status));
5463 goto out;
5466 if (sbuf.st_ex_size != 1000) {
5467 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5468 goto out;
5471 status = cli_close(cli1, fnum1);
5472 if (!NT_STATUS_IS_OK(status)) {
5473 printf("close(2) failed (%s)\n", nt_errstr(status));
5474 goto out;
5477 /* Re-open with O_TRUNC. */
5478 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
5479 if (!NT_STATUS_IS_OK(status)) {
5480 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5481 goto out;
5484 /* Ensure st_size == 0 */
5485 status = cli_posix_stat(cli1, fname, &sbuf);
5486 if (!NT_STATUS_IS_OK(status)) {
5487 printf("stat failed (%s)\n", nt_errstr(status));
5488 goto out;
5491 if (sbuf.st_ex_size != 0) {
5492 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5493 goto out;
5496 status = cli_close(cli1, fnum1);
5497 if (!NT_STATUS_IS_OK(status)) {
5498 printf("close failed (%s)\n", nt_errstr(status));
5499 goto out;
5502 status = cli_posix_unlink(cli1, fname);
5503 if (!NT_STATUS_IS_OK(status)) {
5504 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5505 goto out;
5508 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
5509 if (!NT_STATUS_IS_OK(status)) {
5510 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5511 dname, nt_errstr(status));
5512 goto out;
5515 cli_close(cli1, fnum1);
5517 /* What happens when we try and POSIX open a directory for write ? */
5518 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
5519 if (NT_STATUS_IS_OK(status)) {
5520 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5521 goto out;
5522 } else {
5523 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
5524 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5525 goto out;
5529 /* Create the file. */
5530 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5531 0600, &fnum1);
5532 if (!NT_STATUS_IS_OK(status)) {
5533 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5534 goto out;
5537 /* Write some data into it. */
5538 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5539 NULL);
5540 if (!NT_STATUS_IS_OK(status)) {
5541 printf("cli_write failed: %s\n", nt_errstr(status));
5542 goto out;
5545 cli_close(cli1, fnum1);
5547 /* Now create a hardlink. */
5548 status = cli_posix_hardlink(cli1, fname, hname);
5549 if (!NT_STATUS_IS_OK(status)) {
5550 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5551 goto out;
5554 /* Now create a symlink. */
5555 status = cli_posix_symlink(cli1, fname, sname);
5556 if (!NT_STATUS_IS_OK(status)) {
5557 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5558 goto out;
5561 /* Open the hardlink for read. */
5562 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5563 if (!NT_STATUS_IS_OK(status)) {
5564 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5565 goto out;
5568 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
5569 if (!NT_STATUS_IS_OK(status)) {
5570 printf("POSIX read of %s failed (%s)\n", hname,
5571 nt_errstr(status));
5572 goto out;
5573 } else if (nread != 10) {
5574 printf("POSIX read of %s failed. Received %ld, expected %d\n",
5575 hname, (unsigned long)nread, 10);
5576 goto out;
5579 if (memcmp(buf, "TEST DATA\n", 10)) {
5580 printf("invalid data read from hardlink\n");
5581 goto out;
5584 /* Do a POSIX lock/unlock. */
5585 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5586 if (!NT_STATUS_IS_OK(status)) {
5587 printf("POSIX lock failed %s\n", nt_errstr(status));
5588 goto out;
5591 /* Punch a hole in the locked area. */
5592 status = cli_posix_unlock(cli1, fnum1, 10, 80);
5593 if (!NT_STATUS_IS_OK(status)) {
5594 printf("POSIX unlock failed %s\n", nt_errstr(status));
5595 goto out;
5598 cli_close(cli1, fnum1);
5600 /* Open the symlink for read - this should fail. A POSIX
5601 client should not be doing opens on a symlink. */
5602 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5603 if (NT_STATUS_IS_OK(status)) {
5604 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5605 goto out;
5606 } else {
5607 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
5608 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5609 printf("POSIX open of %s should have failed "
5610 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5611 "failed with %s instead.\n",
5612 sname, nt_errstr(status));
5613 goto out;
5617 status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5618 if (!NT_STATUS_IS_OK(status)) {
5619 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5620 goto out;
5623 if (strcmp(namebuf, fname) != 0) {
5624 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5625 sname, fname, namebuf);
5626 goto out;
5629 status = cli_posix_rmdir(cli1, dname);
5630 if (!NT_STATUS_IS_OK(status)) {
5631 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5632 goto out;
5635 printf("Simple POSIX open test passed\n");
5636 correct = true;
5638 out:
5640 if (fnum1 != (uint16_t)-1) {
5641 cli_close(cli1, fnum1);
5642 fnum1 = (uint16_t)-1;
5645 cli_setatr(cli1, sname, 0, 0);
5646 cli_posix_unlink(cli1, sname);
5647 cli_setatr(cli1, hname, 0, 0);
5648 cli_posix_unlink(cli1, hname);
5649 cli_setatr(cli1, fname, 0, 0);
5650 cli_posix_unlink(cli1, fname);
5651 cli_setatr(cli1, dname, 0, 0);
5652 cli_posix_rmdir(cli1, dname);
5654 if (!torture_close_connection(cli1)) {
5655 correct = false;
5658 return correct;
5662 static uint32 open_attrs_table[] = {
5663 FILE_ATTRIBUTE_NORMAL,
5664 FILE_ATTRIBUTE_ARCHIVE,
5665 FILE_ATTRIBUTE_READONLY,
5666 FILE_ATTRIBUTE_HIDDEN,
5667 FILE_ATTRIBUTE_SYSTEM,
5669 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
5670 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
5671 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
5672 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5673 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5674 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5676 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5677 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5678 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5679 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
5682 struct trunc_open_results {
5683 unsigned int num;
5684 uint32 init_attr;
5685 uint32 trunc_attr;
5686 uint32 result_attr;
5689 static struct trunc_open_results attr_results[] = {
5690 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5691 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5692 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5693 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5694 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5695 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5696 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5697 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5698 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5699 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5700 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5701 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5702 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5703 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5704 { 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 },
5705 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5706 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5707 { 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 },
5708 { 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 },
5709 { 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 },
5710 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5711 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5712 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5713 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5714 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5715 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
5718 static bool run_openattrtest(int dummy)
5720 static struct cli_state *cli1;
5721 const char *fname = "\\openattr.file";
5722 uint16_t fnum1;
5723 bool correct = True;
5724 uint16 attr;
5725 unsigned int i, j, k, l;
5726 NTSTATUS status;
5728 printf("starting open attr test\n");
5730 if (!torture_open_connection(&cli1, 0)) {
5731 return False;
5734 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5736 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
5737 cli_setatr(cli1, fname, 0, 0);
5738 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5740 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
5741 open_attrs_table[i], FILE_SHARE_NONE,
5742 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5743 if (!NT_STATUS_IS_OK(status)) {
5744 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5745 return False;
5748 status = cli_close(cli1, fnum1);
5749 if (!NT_STATUS_IS_OK(status)) {
5750 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5751 return False;
5754 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
5755 status = cli_ntcreate(cli1, fname, 0,
5756 FILE_READ_DATA|FILE_WRITE_DATA,
5757 open_attrs_table[j],
5758 FILE_SHARE_NONE, FILE_OVERWRITE,
5759 0, 0, &fnum1);
5760 if (!NT_STATUS_IS_OK(status)) {
5761 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5762 if (attr_results[l].num == k) {
5763 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5764 k, open_attrs_table[i],
5765 open_attrs_table[j],
5766 fname, NT_STATUS_V(status), nt_errstr(status));
5767 correct = False;
5771 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5772 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5773 k, open_attrs_table[i], open_attrs_table[j],
5774 nt_errstr(status));
5775 correct = False;
5777 #if 0
5778 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5779 #endif
5780 k++;
5781 continue;
5784 status = cli_close(cli1, fnum1);
5785 if (!NT_STATUS_IS_OK(status)) {
5786 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
5787 return False;
5790 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
5791 if (!NT_STATUS_IS_OK(status)) {
5792 printf("getatr(2) failed (%s)\n", nt_errstr(status));
5793 return False;
5796 #if 0
5797 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5798 k, open_attrs_table[i], open_attrs_table[j], attr );
5799 #endif
5801 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5802 if (attr_results[l].num == k) {
5803 if (attr != attr_results[l].result_attr ||
5804 open_attrs_table[i] != attr_results[l].init_attr ||
5805 open_attrs_table[j] != attr_results[l].trunc_attr) {
5806 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5807 open_attrs_table[i],
5808 open_attrs_table[j],
5809 (unsigned int)attr,
5810 attr_results[l].result_attr);
5811 correct = False;
5813 break;
5816 k++;
5820 cli_setatr(cli1, fname, 0, 0);
5821 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5823 printf("open attr test %s.\n", correct ? "passed" : "failed");
5825 if (!torture_close_connection(cli1)) {
5826 correct = False;
5828 return correct;
5831 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5832 const char *name, void *state)
5834 int *matched = (int *)state;
5835 if (matched != NULL) {
5836 *matched += 1;
5838 return NT_STATUS_OK;
5842 test directory listing speed
5844 static bool run_dirtest(int dummy)
5846 int i;
5847 static struct cli_state *cli;
5848 uint16_t fnum;
5849 struct timeval core_start;
5850 bool correct = True;
5851 int matched;
5853 printf("starting directory test\n");
5855 if (!torture_open_connection(&cli, 0)) {
5856 return False;
5859 smbXcli_conn_set_sockopt(cli->conn, sockops);
5861 srandom(0);
5862 for (i=0;i<torture_numops;i++) {
5863 fstring fname;
5864 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5865 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5866 fprintf(stderr,"Failed to open %s\n", fname);
5867 return False;
5869 cli_close(cli, fnum);
5872 core_start = timeval_current();
5874 matched = 0;
5875 cli_list(cli, "a*.*", 0, list_fn, &matched);
5876 printf("Matched %d\n", matched);
5878 matched = 0;
5879 cli_list(cli, "b*.*", 0, list_fn, &matched);
5880 printf("Matched %d\n", matched);
5882 matched = 0;
5883 cli_list(cli, "xyzabc", 0, list_fn, &matched);
5884 printf("Matched %d\n", matched);
5886 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5888 srandom(0);
5889 for (i=0;i<torture_numops;i++) {
5890 fstring fname;
5891 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5892 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5895 if (!torture_close_connection(cli)) {
5896 correct = False;
5899 printf("finished dirtest\n");
5901 return correct;
5904 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5905 void *state)
5907 struct cli_state *pcli = (struct cli_state *)state;
5908 fstring fname;
5909 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5911 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5912 return NT_STATUS_OK;
5914 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
5915 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5916 printf("del_fn: failed to rmdir %s\n,", fname );
5917 } else {
5918 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
5919 printf("del_fn: failed to unlink %s\n,", fname );
5921 return NT_STATUS_OK;
5926 sees what IOCTLs are supported
5928 bool torture_ioctl_test(int dummy)
5930 static struct cli_state *cli;
5931 uint16_t device, function;
5932 uint16_t fnum;
5933 const char *fname = "\\ioctl.dat";
5934 DATA_BLOB blob;
5935 NTSTATUS status;
5937 if (!torture_open_connection(&cli, 0)) {
5938 return False;
5941 printf("starting ioctl test\n");
5943 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5945 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5946 if (!NT_STATUS_IS_OK(status)) {
5947 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5948 return False;
5951 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5952 printf("ioctl device info: %s\n", nt_errstr(status));
5954 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5955 printf("ioctl job info: %s\n", nt_errstr(status));
5957 for (device=0;device<0x100;device++) {
5958 printf("ioctl test with device = 0x%x\n", device);
5959 for (function=0;function<0x100;function++) {
5960 uint32 code = (device<<16) | function;
5962 status = cli_raw_ioctl(cli, fnum, code, &blob);
5964 if (NT_STATUS_IS_OK(status)) {
5965 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5966 (int)blob.length);
5967 data_blob_free(&blob);
5972 if (!torture_close_connection(cli)) {
5973 return False;
5976 return True;
5981 tries varients of chkpath
5983 bool torture_chkpath_test(int dummy)
5985 static struct cli_state *cli;
5986 uint16_t fnum;
5987 bool ret;
5988 NTSTATUS status;
5990 if (!torture_open_connection(&cli, 0)) {
5991 return False;
5994 printf("starting chkpath test\n");
5996 /* cleanup from an old run */
5997 cli_rmdir(cli, "\\chkpath.dir\\dir2");
5998 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5999 cli_rmdir(cli, "\\chkpath.dir");
6001 status = cli_mkdir(cli, "\\chkpath.dir");
6002 if (!NT_STATUS_IS_OK(status)) {
6003 printf("mkdir1 failed : %s\n", nt_errstr(status));
6004 return False;
6007 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
6008 if (!NT_STATUS_IS_OK(status)) {
6009 printf("mkdir2 failed : %s\n", nt_errstr(status));
6010 return False;
6013 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
6014 DENY_NONE, &fnum);
6015 if (!NT_STATUS_IS_OK(status)) {
6016 printf("open1 failed (%s)\n", nt_errstr(status));
6017 return False;
6019 cli_close(cli, fnum);
6021 status = cli_chkpath(cli, "\\chkpath.dir");
6022 if (!NT_STATUS_IS_OK(status)) {
6023 printf("chkpath1 failed: %s\n", nt_errstr(status));
6024 ret = False;
6027 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
6028 if (!NT_STATUS_IS_OK(status)) {
6029 printf("chkpath2 failed: %s\n", nt_errstr(status));
6030 ret = False;
6033 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
6034 if (!NT_STATUS_IS_OK(status)) {
6035 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6036 NT_STATUS_NOT_A_DIRECTORY);
6037 } else {
6038 printf("* chkpath on a file should fail\n");
6039 ret = False;
6042 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
6043 if (!NT_STATUS_IS_OK(status)) {
6044 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
6045 NT_STATUS_OBJECT_NAME_NOT_FOUND);
6046 } else {
6047 printf("* chkpath on a non existant file should fail\n");
6048 ret = False;
6051 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
6052 if (!NT_STATUS_IS_OK(status)) {
6053 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6054 NT_STATUS_OBJECT_PATH_NOT_FOUND);
6055 } else {
6056 printf("* chkpath on a non existent component should fail\n");
6057 ret = False;
6060 cli_rmdir(cli, "\\chkpath.dir\\dir2");
6061 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6062 cli_rmdir(cli, "\\chkpath.dir");
6064 if (!torture_close_connection(cli)) {
6065 return False;
6068 return ret;
6071 static bool run_eatest(int dummy)
6073 static struct cli_state *cli;
6074 const char *fname = "\\eatest.txt";
6075 bool correct = True;
6076 uint16_t fnum;
6077 int i;
6078 size_t num_eas;
6079 struct ea_struct *ea_list = NULL;
6080 TALLOC_CTX *mem_ctx = talloc_init("eatest");
6081 NTSTATUS status;
6083 printf("starting eatest\n");
6085 if (!torture_open_connection(&cli, 0)) {
6086 talloc_destroy(mem_ctx);
6087 return False;
6090 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6092 status = cli_ntcreate(cli, fname, 0,
6093 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6094 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
6095 0x4044, 0, &fnum);
6096 if (!NT_STATUS_IS_OK(status)) {
6097 printf("open failed - %s\n", nt_errstr(status));
6098 talloc_destroy(mem_ctx);
6099 return False;
6102 for (i = 0; i < 10; i++) {
6103 fstring ea_name, ea_val;
6105 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
6106 memset(ea_val, (char)i+1, i+1);
6107 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
6108 if (!NT_STATUS_IS_OK(status)) {
6109 printf("ea_set of name %s failed - %s\n", ea_name,
6110 nt_errstr(status));
6111 talloc_destroy(mem_ctx);
6112 return False;
6116 cli_close(cli, fnum);
6117 for (i = 0; i < 10; i++) {
6118 fstring ea_name, ea_val;
6120 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
6121 memset(ea_val, (char)i+1, i+1);
6122 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
6123 if (!NT_STATUS_IS_OK(status)) {
6124 printf("ea_set of name %s failed - %s\n", ea_name,
6125 nt_errstr(status));
6126 talloc_destroy(mem_ctx);
6127 return False;
6131 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6132 if (!NT_STATUS_IS_OK(status)) {
6133 printf("ea_get list failed - %s\n", nt_errstr(status));
6134 correct = False;
6137 printf("num_eas = %d\n", (int)num_eas);
6139 if (num_eas != 20) {
6140 printf("Should be 20 EA's stored... failing.\n");
6141 correct = False;
6144 for (i = 0; i < num_eas; i++) {
6145 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6146 dump_data(0, ea_list[i].value.data,
6147 ea_list[i].value.length);
6150 /* Setting EA's to zero length deletes them. Test this */
6151 printf("Now deleting all EA's - case indepenent....\n");
6153 #if 1
6154 cli_set_ea_path(cli, fname, "", "", 0);
6155 #else
6156 for (i = 0; i < 20; i++) {
6157 fstring ea_name;
6158 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
6159 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
6160 if (!NT_STATUS_IS_OK(status)) {
6161 printf("ea_set of name %s failed - %s\n", ea_name,
6162 nt_errstr(status));
6163 talloc_destroy(mem_ctx);
6164 return False;
6167 #endif
6169 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6170 if (!NT_STATUS_IS_OK(status)) {
6171 printf("ea_get list failed - %s\n", nt_errstr(status));
6172 correct = False;
6175 printf("num_eas = %d\n", (int)num_eas);
6176 for (i = 0; i < num_eas; i++) {
6177 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6178 dump_data(0, ea_list[i].value.data,
6179 ea_list[i].value.length);
6182 if (num_eas != 0) {
6183 printf("deleting EA's failed.\n");
6184 correct = False;
6187 /* Try and delete a non existant EA. */
6188 status = cli_set_ea_path(cli, fname, "foo", "", 0);
6189 if (!NT_STATUS_IS_OK(status)) {
6190 printf("deleting non-existant EA 'foo' should succeed. %s\n",
6191 nt_errstr(status));
6192 correct = False;
6195 talloc_destroy(mem_ctx);
6196 if (!torture_close_connection(cli)) {
6197 correct = False;
6200 return correct;
6203 static bool run_dirtest1(int dummy)
6205 int i;
6206 static struct cli_state *cli;
6207 uint16_t fnum;
6208 int num_seen;
6209 bool correct = True;
6211 printf("starting directory test\n");
6213 if (!torture_open_connection(&cli, 0)) {
6214 return False;
6217 smbXcli_conn_set_sockopt(cli->conn, sockops);
6219 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6220 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6221 cli_rmdir(cli, "\\LISTDIR");
6222 cli_mkdir(cli, "\\LISTDIR");
6224 /* Create 1000 files and 1000 directories. */
6225 for (i=0;i<1000;i++) {
6226 fstring fname;
6227 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6228 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6229 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6230 fprintf(stderr,"Failed to open %s\n", fname);
6231 return False;
6233 cli_close(cli, fnum);
6235 for (i=0;i<1000;i++) {
6236 fstring fname;
6237 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6238 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6239 fprintf(stderr,"Failed to open %s\n", fname);
6240 return False;
6244 /* Now ensure that doing an old list sees both files and directories. */
6245 num_seen = 0;
6246 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6247 printf("num_seen = %d\n", num_seen );
6248 /* We should see 100 files + 1000 directories + . and .. */
6249 if (num_seen != 2002)
6250 correct = False;
6252 /* Ensure if we have the "must have" bits we only see the
6253 * relevent entries.
6255 num_seen = 0;
6256 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6257 printf("num_seen = %d\n", num_seen );
6258 if (num_seen != 1002)
6259 correct = False;
6261 num_seen = 0;
6262 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6263 printf("num_seen = %d\n", num_seen );
6264 if (num_seen != 1000)
6265 correct = False;
6267 /* Delete everything. */
6268 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6269 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6270 cli_rmdir(cli, "\\LISTDIR");
6272 #if 0
6273 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6274 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6275 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6276 #endif
6278 if (!torture_close_connection(cli)) {
6279 correct = False;
6282 printf("finished dirtest1\n");
6284 return correct;
6287 static bool run_error_map_extract(int dummy) {
6289 static struct cli_state *c_dos;
6290 static struct cli_state *c_nt;
6291 NTSTATUS status;
6293 uint32 error;
6295 uint32 errnum;
6296 uint8 errclass;
6298 NTSTATUS nt_status;
6300 fstring user;
6302 /* NT-Error connection */
6304 disable_spnego = true;
6305 if (!(c_nt = open_nbt_connection())) {
6306 disable_spnego = false;
6307 return False;
6309 disable_spnego = false;
6311 status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
6312 PROTOCOL_NT1);
6314 if (!NT_STATUS_IS_OK(status)) {
6315 printf("%s rejected the NT-error negprot (%s)\n", host,
6316 nt_errstr(status));
6317 cli_shutdown(c_nt);
6318 return False;
6321 status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6322 if (!NT_STATUS_IS_OK(status)) {
6323 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6324 return False;
6327 /* DOS-Error connection */
6329 disable_spnego = true;
6330 force_dos_errors = true;
6331 if (!(c_dos = open_nbt_connection())) {
6332 disable_spnego = false;
6333 force_dos_errors = false;
6334 return False;
6336 disable_spnego = false;
6337 force_dos_errors = false;
6339 status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
6340 PROTOCOL_NT1);
6341 if (!NT_STATUS_IS_OK(status)) {
6342 printf("%s rejected the DOS-error negprot (%s)\n", host,
6343 nt_errstr(status));
6344 cli_shutdown(c_dos);
6345 return False;
6348 status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
6349 if (!NT_STATUS_IS_OK(status)) {
6350 printf("%s rejected the DOS-error initial session setup (%s)\n",
6351 host, nt_errstr(status));
6352 return False;
6355 c_nt->map_dos_errors = false;
6356 c_dos->map_dos_errors = false;
6358 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
6359 fstr_sprintf(user, "%X", error);
6361 status = cli_session_setup(c_nt, user,
6362 password, strlen(password),
6363 password, strlen(password),
6364 workgroup);
6365 if (NT_STATUS_IS_OK(status)) {
6366 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6369 /* Case #1: 32-bit NT errors */
6370 if (!NT_STATUS_IS_DOS(status)) {
6371 nt_status = status;
6372 } else {
6373 printf("/** Dos error on NT connection! (%s) */\n",
6374 nt_errstr(status));
6375 nt_status = NT_STATUS(0xc0000000);
6378 status = cli_session_setup(c_dos, user,
6379 password, strlen(password),
6380 password, strlen(password),
6381 workgroup);
6382 if (NT_STATUS_IS_OK(status)) {
6383 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6386 /* Case #1: 32-bit NT errors */
6387 if (NT_STATUS_IS_DOS(status)) {
6388 printf("/** NT error on DOS connection! (%s) */\n",
6389 nt_errstr(status));
6390 errnum = errclass = 0;
6391 } else {
6392 errclass = NT_STATUS_DOS_CLASS(status);
6393 errnum = NT_STATUS_DOS_CODE(status);
6396 if (NT_STATUS_V(nt_status) != error) {
6397 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
6398 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
6399 get_nt_error_c_code(talloc_tos(), nt_status));
6402 printf("\t{%s,\t%s,\t%s},\n",
6403 smb_dos_err_class(errclass),
6404 smb_dos_err_name(errclass, errnum),
6405 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
6407 return True;
6410 static bool run_sesssetup_bench(int dummy)
6412 static struct cli_state *c;
6413 const char *fname = "\\file.dat";
6414 uint16_t fnum;
6415 NTSTATUS status;
6416 int i;
6418 if (!torture_open_connection(&c, 0)) {
6419 return false;
6422 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6423 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6424 FILE_DELETE_ON_CLOSE, 0, &fnum);
6425 if (!NT_STATUS_IS_OK(status)) {
6426 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6427 return false;
6430 for (i=0; i<torture_numops; i++) {
6431 status = cli_session_setup(
6432 c, username,
6433 password, strlen(password),
6434 password, strlen(password),
6435 workgroup);
6436 if (!NT_STATUS_IS_OK(status)) {
6437 d_printf("(%s) cli_session_setup failed: %s\n",
6438 __location__, nt_errstr(status));
6439 return false;
6442 d_printf("\r%d ", (int)cli_state_get_uid(c));
6444 status = cli_ulogoff(c);
6445 if (!NT_STATUS_IS_OK(status)) {
6446 d_printf("(%s) cli_ulogoff failed: %s\n",
6447 __location__, nt_errstr(status));
6448 return false;
6452 return true;
6455 static bool subst_test(const char *str, const char *user, const char *domain,
6456 uid_t uid, gid_t gid, const char *expected)
6458 char *subst;
6459 bool result = true;
6461 subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
6463 if (strcmp(subst, expected) != 0) {
6464 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
6465 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
6466 expected);
6467 result = false;
6470 TALLOC_FREE(subst);
6471 return result;
6474 static void chain1_open_completion(struct tevent_req *req)
6476 uint16_t fnum;
6477 NTSTATUS status;
6478 status = cli_openx_recv(req, &fnum);
6479 TALLOC_FREE(req);
6481 d_printf("cli_openx_recv returned %s: %d\n",
6482 nt_errstr(status),
6483 NT_STATUS_IS_OK(status) ? fnum : -1);
6486 static void chain1_write_completion(struct tevent_req *req)
6488 size_t written;
6489 NTSTATUS status;
6490 status = cli_write_andx_recv(req, &written);
6491 TALLOC_FREE(req);
6493 d_printf("cli_write_andx_recv returned %s: %d\n",
6494 nt_errstr(status),
6495 NT_STATUS_IS_OK(status) ? (int)written : -1);
6498 static void chain1_close_completion(struct tevent_req *req)
6500 NTSTATUS status;
6501 bool *done = (bool *)tevent_req_callback_data_void(req);
6503 status = cli_close_recv(req);
6504 *done = true;
6506 TALLOC_FREE(req);
6508 d_printf("cli_close returned %s\n", nt_errstr(status));
6511 static bool run_chain1(int dummy)
6513 struct cli_state *cli1;
6514 struct event_context *evt = event_context_init(NULL);
6515 struct tevent_req *reqs[3], *smbreqs[3];
6516 bool done = false;
6517 const char *str = "foobar";
6518 NTSTATUS status;
6520 printf("starting chain1 test\n");
6521 if (!torture_open_connection(&cli1, 0)) {
6522 return False;
6525 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6527 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, "\\test",
6528 O_CREAT|O_RDWR, 0, &smbreqs[0]);
6529 if (reqs[0] == NULL) return false;
6530 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
6533 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
6534 (const uint8_t *)str, 0, strlen(str)+1,
6535 smbreqs, 1, &smbreqs[1]);
6536 if (reqs[1] == NULL) return false;
6537 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
6539 reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
6540 if (reqs[2] == NULL) return false;
6541 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
6543 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6544 if (!NT_STATUS_IS_OK(status)) {
6545 return false;
6548 while (!done) {
6549 tevent_loop_once(evt);
6552 torture_close_connection(cli1);
6553 return True;
6556 static void chain2_sesssetup_completion(struct tevent_req *req)
6558 NTSTATUS status;
6559 status = cli_session_setup_guest_recv(req);
6560 d_printf("sesssetup returned %s\n", nt_errstr(status));
6563 static void chain2_tcon_completion(struct tevent_req *req)
6565 bool *done = (bool *)tevent_req_callback_data_void(req);
6566 NTSTATUS status;
6567 status = cli_tcon_andx_recv(req);
6568 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
6569 *done = true;
6572 static bool run_chain2(int dummy)
6574 struct cli_state *cli1;
6575 struct event_context *evt = event_context_init(NULL);
6576 struct tevent_req *reqs[2], *smbreqs[2];
6577 bool done = false;
6578 NTSTATUS status;
6580 printf("starting chain2 test\n");
6581 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
6582 port_to_use, SMB_SIGNING_DEFAULT, 0);
6583 if (!NT_STATUS_IS_OK(status)) {
6584 return False;
6587 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6589 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
6590 &smbreqs[0]);
6591 if (reqs[0] == NULL) return false;
6592 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
6594 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
6595 "?????", NULL, 0, &smbreqs[1]);
6596 if (reqs[1] == NULL) return false;
6597 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
6599 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6600 if (!NT_STATUS_IS_OK(status)) {
6601 return false;
6604 while (!done) {
6605 tevent_loop_once(evt);
6608 torture_close_connection(cli1);
6609 return True;
6613 struct torture_createdel_state {
6614 struct tevent_context *ev;
6615 struct cli_state *cli;
6618 static void torture_createdel_created(struct tevent_req *subreq);
6619 static void torture_createdel_closed(struct tevent_req *subreq);
6621 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
6622 struct tevent_context *ev,
6623 struct cli_state *cli,
6624 const char *name)
6626 struct tevent_req *req, *subreq;
6627 struct torture_createdel_state *state;
6629 req = tevent_req_create(mem_ctx, &state,
6630 struct torture_createdel_state);
6631 if (req == NULL) {
6632 return NULL;
6634 state->ev = ev;
6635 state->cli = cli;
6637 subreq = cli_ntcreate_send(
6638 state, ev, cli, name, 0,
6639 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
6640 FILE_ATTRIBUTE_NORMAL,
6641 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6642 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
6644 if (tevent_req_nomem(subreq, req)) {
6645 return tevent_req_post(req, ev);
6647 tevent_req_set_callback(subreq, torture_createdel_created, req);
6648 return req;
6651 static void torture_createdel_created(struct tevent_req *subreq)
6653 struct tevent_req *req = tevent_req_callback_data(
6654 subreq, struct tevent_req);
6655 struct torture_createdel_state *state = tevent_req_data(
6656 req, struct torture_createdel_state);
6657 NTSTATUS status;
6658 uint16_t fnum;
6660 status = cli_ntcreate_recv(subreq, &fnum);
6661 TALLOC_FREE(subreq);
6662 if (!NT_STATUS_IS_OK(status)) {
6663 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
6664 nt_errstr(status)));
6665 tevent_req_nterror(req, status);
6666 return;
6669 subreq = cli_close_send(state, state->ev, state->cli, fnum);
6670 if (tevent_req_nomem(subreq, req)) {
6671 return;
6673 tevent_req_set_callback(subreq, torture_createdel_closed, req);
6676 static void torture_createdel_closed(struct tevent_req *subreq)
6678 struct tevent_req *req = tevent_req_callback_data(
6679 subreq, struct tevent_req);
6680 NTSTATUS status;
6682 status = cli_close_recv(subreq);
6683 if (!NT_STATUS_IS_OK(status)) {
6684 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
6685 tevent_req_nterror(req, status);
6686 return;
6688 tevent_req_done(req);
6691 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
6693 return tevent_req_simple_recv_ntstatus(req);
6696 struct torture_createdels_state {
6697 struct tevent_context *ev;
6698 struct cli_state *cli;
6699 const char *base_name;
6700 int sent;
6701 int received;
6702 int num_files;
6703 struct tevent_req **reqs;
6706 static void torture_createdels_done(struct tevent_req *subreq);
6708 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
6709 struct tevent_context *ev,
6710 struct cli_state *cli,
6711 const char *base_name,
6712 int num_parallel,
6713 int num_files)
6715 struct tevent_req *req;
6716 struct torture_createdels_state *state;
6717 int i;
6719 req = tevent_req_create(mem_ctx, &state,
6720 struct torture_createdels_state);
6721 if (req == NULL) {
6722 return NULL;
6724 state->ev = ev;
6725 state->cli = cli;
6726 state->base_name = talloc_strdup(state, base_name);
6727 if (tevent_req_nomem(state->base_name, req)) {
6728 return tevent_req_post(req, ev);
6730 state->num_files = MAX(num_parallel, num_files);
6731 state->sent = 0;
6732 state->received = 0;
6734 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
6735 if (tevent_req_nomem(state->reqs, req)) {
6736 return tevent_req_post(req, ev);
6739 for (i=0; i<num_parallel; i++) {
6740 char *name;
6742 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6743 state->sent);
6744 if (tevent_req_nomem(name, req)) {
6745 return tevent_req_post(req, ev);
6747 state->reqs[i] = torture_createdel_send(
6748 state->reqs, state->ev, state->cli, name);
6749 if (tevent_req_nomem(state->reqs[i], req)) {
6750 return tevent_req_post(req, ev);
6752 name = talloc_move(state->reqs[i], &name);
6753 tevent_req_set_callback(state->reqs[i],
6754 torture_createdels_done, req);
6755 state->sent += 1;
6757 return req;
6760 static void torture_createdels_done(struct tevent_req *subreq)
6762 struct tevent_req *req = tevent_req_callback_data(
6763 subreq, struct tevent_req);
6764 struct torture_createdels_state *state = tevent_req_data(
6765 req, struct torture_createdels_state);
6766 size_t num_parallel = talloc_array_length(state->reqs);
6767 NTSTATUS status;
6768 char *name;
6769 int i;
6771 status = torture_createdel_recv(subreq);
6772 if (!NT_STATUS_IS_OK(status)){
6773 DEBUG(10, ("torture_createdel_recv returned %s\n",
6774 nt_errstr(status)));
6775 TALLOC_FREE(subreq);
6776 tevent_req_nterror(req, status);
6777 return;
6780 for (i=0; i<num_parallel; i++) {
6781 if (subreq == state->reqs[i]) {
6782 break;
6785 if (i == num_parallel) {
6786 DEBUG(10, ("received something we did not send\n"));
6787 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6788 return;
6790 TALLOC_FREE(state->reqs[i]);
6792 if (state->sent >= state->num_files) {
6793 tevent_req_done(req);
6794 return;
6797 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6798 state->sent);
6799 if (tevent_req_nomem(name, req)) {
6800 return;
6802 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
6803 state->cli, name);
6804 if (tevent_req_nomem(state->reqs[i], req)) {
6805 return;
6807 name = talloc_move(state->reqs[i], &name);
6808 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
6809 state->sent += 1;
6812 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
6814 return tevent_req_simple_recv_ntstatus(req);
6817 struct swallow_notify_state {
6818 struct tevent_context *ev;
6819 struct cli_state *cli;
6820 uint16_t fnum;
6821 uint32_t completion_filter;
6822 bool recursive;
6823 bool (*fn)(uint32_t action, const char *name, void *priv);
6824 void *priv;
6827 static void swallow_notify_done(struct tevent_req *subreq);
6829 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
6830 struct tevent_context *ev,
6831 struct cli_state *cli,
6832 uint16_t fnum,
6833 uint32_t completion_filter,
6834 bool recursive,
6835 bool (*fn)(uint32_t action,
6836 const char *name,
6837 void *priv),
6838 void *priv)
6840 struct tevent_req *req, *subreq;
6841 struct swallow_notify_state *state;
6843 req = tevent_req_create(mem_ctx, &state,
6844 struct swallow_notify_state);
6845 if (req == NULL) {
6846 return NULL;
6848 state->ev = ev;
6849 state->cli = cli;
6850 state->fnum = fnum;
6851 state->completion_filter = completion_filter;
6852 state->recursive = recursive;
6853 state->fn = fn;
6854 state->priv = priv;
6856 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6857 0xffff, state->completion_filter,
6858 state->recursive);
6859 if (tevent_req_nomem(subreq, req)) {
6860 return tevent_req_post(req, ev);
6862 tevent_req_set_callback(subreq, swallow_notify_done, req);
6863 return req;
6866 static void swallow_notify_done(struct tevent_req *subreq)
6868 struct tevent_req *req = tevent_req_callback_data(
6869 subreq, struct tevent_req);
6870 struct swallow_notify_state *state = tevent_req_data(
6871 req, struct swallow_notify_state);
6872 NTSTATUS status;
6873 uint32_t i, num_changes;
6874 struct notify_change *changes;
6876 status = cli_notify_recv(subreq, state, &num_changes, &changes);
6877 TALLOC_FREE(subreq);
6878 if (!NT_STATUS_IS_OK(status)) {
6879 DEBUG(10, ("cli_notify_recv returned %s\n",
6880 nt_errstr(status)));
6881 tevent_req_nterror(req, status);
6882 return;
6885 for (i=0; i<num_changes; i++) {
6886 state->fn(changes[i].action, changes[i].name, state->priv);
6888 TALLOC_FREE(changes);
6890 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6891 0xffff, state->completion_filter,
6892 state->recursive);
6893 if (tevent_req_nomem(subreq, req)) {
6894 return;
6896 tevent_req_set_callback(subreq, swallow_notify_done, req);
6899 static bool print_notifies(uint32_t action, const char *name, void *priv)
6901 if (DEBUGLEVEL > 5) {
6902 d_printf("%d %s\n", (int)action, name);
6904 return true;
6907 static void notify_bench_done(struct tevent_req *req)
6909 int *num_finished = (int *)tevent_req_callback_data_void(req);
6910 *num_finished += 1;
6913 static bool run_notify_bench(int dummy)
6915 const char *dname = "\\notify-bench";
6916 struct tevent_context *ev;
6917 NTSTATUS status;
6918 uint16_t dnum;
6919 struct tevent_req *req1;
6920 struct tevent_req *req2 = NULL;
6921 int i, num_unc_names;
6922 int num_finished = 0;
6924 printf("starting notify-bench test\n");
6926 if (use_multishare_conn) {
6927 char **unc_list;
6928 unc_list = file_lines_load(multishare_conn_fname,
6929 &num_unc_names, 0, NULL);
6930 if (!unc_list || num_unc_names <= 0) {
6931 d_printf("Failed to load unc names list from '%s'\n",
6932 multishare_conn_fname);
6933 return false;
6935 TALLOC_FREE(unc_list);
6936 } else {
6937 num_unc_names = 1;
6940 ev = tevent_context_init(talloc_tos());
6941 if (ev == NULL) {
6942 d_printf("tevent_context_init failed\n");
6943 return false;
6946 for (i=0; i<num_unc_names; i++) {
6947 struct cli_state *cli;
6948 char *base_fname;
6950 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
6951 dname, i);
6952 if (base_fname == NULL) {
6953 return false;
6956 if (!torture_open_connection(&cli, i)) {
6957 return false;
6960 status = cli_ntcreate(cli, dname, 0,
6961 MAXIMUM_ALLOWED_ACCESS,
6962 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
6963 FILE_SHARE_DELETE,
6964 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
6965 &dnum);
6967 if (!NT_STATUS_IS_OK(status)) {
6968 d_printf("Could not create %s: %s\n", dname,
6969 nt_errstr(status));
6970 return false;
6973 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
6974 FILE_NOTIFY_CHANGE_FILE_NAME |
6975 FILE_NOTIFY_CHANGE_DIR_NAME |
6976 FILE_NOTIFY_CHANGE_ATTRIBUTES |
6977 FILE_NOTIFY_CHANGE_LAST_WRITE,
6978 false, print_notifies, NULL);
6979 if (req1 == NULL) {
6980 d_printf("Could not create notify request\n");
6981 return false;
6984 req2 = torture_createdels_send(talloc_tos(), ev, cli,
6985 base_fname, 10, torture_numops);
6986 if (req2 == NULL) {
6987 d_printf("Could not create createdels request\n");
6988 return false;
6990 TALLOC_FREE(base_fname);
6992 tevent_req_set_callback(req2, notify_bench_done,
6993 &num_finished);
6996 while (num_finished < num_unc_names) {
6997 int ret;
6998 ret = tevent_loop_once(ev);
6999 if (ret != 0) {
7000 d_printf("tevent_loop_once failed\n");
7001 return false;
7005 if (!tevent_req_poll(req2, ev)) {
7006 d_printf("tevent_req_poll failed\n");
7009 status = torture_createdels_recv(req2);
7010 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
7012 return true;
7015 static bool run_mangle1(int dummy)
7017 struct cli_state *cli;
7018 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
7019 uint16_t fnum;
7020 fstring alt_name;
7021 NTSTATUS status;
7022 time_t change_time, access_time, write_time;
7023 off_t size;
7024 uint16_t mode;
7026 printf("starting mangle1 test\n");
7027 if (!torture_open_connection(&cli, 0)) {
7028 return False;
7031 smbXcli_conn_set_sockopt(cli->conn, sockops);
7033 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7034 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7035 0, 0, &fnum);
7036 if (!NT_STATUS_IS_OK(status)) {
7037 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7038 return false;
7040 cli_close(cli, fnum);
7042 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
7043 if (!NT_STATUS_IS_OK(status)) {
7044 d_printf("cli_qpathinfo_alt_name failed: %s\n",
7045 nt_errstr(status));
7046 return false;
7048 d_printf("alt_name: %s\n", alt_name);
7050 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
7051 if (!NT_STATUS_IS_OK(status)) {
7052 d_printf("cli_openx(%s) failed: %s\n", alt_name,
7053 nt_errstr(status));
7054 return false;
7056 cli_close(cli, fnum);
7058 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
7059 &write_time, &size, &mode);
7060 if (!NT_STATUS_IS_OK(status)) {
7061 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
7062 nt_errstr(status));
7063 return false;
7066 return true;
7069 static size_t null_source(uint8_t *buf, size_t n, void *priv)
7071 size_t *to_pull = (size_t *)priv;
7072 size_t thistime = *to_pull;
7074 thistime = MIN(thistime, n);
7075 if (thistime == 0) {
7076 return 0;
7079 memset(buf, 0, thistime);
7080 *to_pull -= thistime;
7081 return thistime;
7084 static bool run_windows_write(int dummy)
7086 struct cli_state *cli1;
7087 uint16_t fnum;
7088 int i;
7089 bool ret = false;
7090 const char *fname = "\\writetest.txt";
7091 struct timeval start_time;
7092 double seconds;
7093 double kbytes;
7094 NTSTATUS status;
7096 printf("starting windows_write test\n");
7097 if (!torture_open_connection(&cli1, 0)) {
7098 return False;
7101 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7102 if (!NT_STATUS_IS_OK(status)) {
7103 printf("open failed (%s)\n", nt_errstr(status));
7104 return False;
7107 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7109 start_time = timeval_current();
7111 for (i=0; i<torture_numops; i++) {
7112 uint8_t c = 0;
7113 off_t start = i * torture_blocksize;
7114 size_t to_pull = torture_blocksize - 1;
7116 status = cli_writeall(cli1, fnum, 0, &c,
7117 start + torture_blocksize - 1, 1, NULL);
7118 if (!NT_STATUS_IS_OK(status)) {
7119 printf("cli_write failed: %s\n", nt_errstr(status));
7120 goto fail;
7123 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
7124 null_source, &to_pull);
7125 if (!NT_STATUS_IS_OK(status)) {
7126 printf("cli_push returned: %s\n", nt_errstr(status));
7127 goto fail;
7131 seconds = timeval_elapsed(&start_time);
7132 kbytes = (double)torture_blocksize * torture_numops;
7133 kbytes /= 1024;
7135 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
7136 (double)seconds, (int)(kbytes/seconds));
7138 ret = true;
7139 fail:
7140 cli_close(cli1, fnum);
7141 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7142 torture_close_connection(cli1);
7143 return ret;
7146 static bool run_cli_echo(int dummy)
7148 struct cli_state *cli;
7149 NTSTATUS status;
7151 printf("starting cli_echo test\n");
7152 if (!torture_open_connection(&cli, 0)) {
7153 return false;
7155 smbXcli_conn_set_sockopt(cli->conn, sockops);
7157 status = cli_echo(cli, 5, data_blob_const("hello", 5));
7159 d_printf("cli_echo returned %s\n", nt_errstr(status));
7161 torture_close_connection(cli);
7162 return NT_STATUS_IS_OK(status);
7165 static bool run_uid_regression_test(int dummy)
7167 static struct cli_state *cli;
7168 int16_t old_vuid;
7169 int16_t old_cnum;
7170 bool correct = True;
7171 NTSTATUS status;
7173 printf("starting uid regression test\n");
7175 if (!torture_open_connection(&cli, 0)) {
7176 return False;
7179 smbXcli_conn_set_sockopt(cli->conn, sockops);
7181 /* Ok - now save then logoff our current user. */
7182 old_vuid = cli_state_get_uid(cli);
7184 status = cli_ulogoff(cli);
7185 if (!NT_STATUS_IS_OK(status)) {
7186 d_printf("(%s) cli_ulogoff failed: %s\n",
7187 __location__, nt_errstr(status));
7188 correct = false;
7189 goto out;
7192 cli_state_set_uid(cli, old_vuid);
7194 /* Try an operation. */
7195 status = cli_mkdir(cli, "\\uid_reg_test");
7196 if (NT_STATUS_IS_OK(status)) {
7197 d_printf("(%s) cli_mkdir succeeded\n",
7198 __location__);
7199 correct = false;
7200 goto out;
7201 } else {
7202 /* Should be bad uid. */
7203 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
7204 NT_STATUS_USER_SESSION_DELETED)) {
7205 correct = false;
7206 goto out;
7210 old_cnum = cli_state_get_tid(cli);
7212 /* Now try a SMBtdis with the invald vuid set to zero. */
7213 cli_state_set_uid(cli, 0);
7215 /* This should succeed. */
7216 status = cli_tdis(cli);
7218 if (NT_STATUS_IS_OK(status)) {
7219 d_printf("First tdis with invalid vuid should succeed.\n");
7220 } else {
7221 d_printf("First tdis failed (%s)\n", nt_errstr(status));
7222 correct = false;
7223 goto out;
7226 cli_state_set_uid(cli, old_vuid);
7227 cli_state_set_tid(cli, old_cnum);
7229 /* This should fail. */
7230 status = cli_tdis(cli);
7231 if (NT_STATUS_IS_OK(status)) {
7232 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
7233 correct = false;
7234 goto out;
7235 } else {
7236 /* Should be bad tid. */
7237 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
7238 NT_STATUS_NETWORK_NAME_DELETED)) {
7239 correct = false;
7240 goto out;
7244 cli_rmdir(cli, "\\uid_reg_test");
7246 out:
7248 cli_shutdown(cli);
7249 return correct;
7253 static const char *illegal_chars = "*\\/?<>|\":";
7254 static char force_shortname_chars[] = " +,.[];=\177";
7256 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
7257 const char *mask, void *state)
7259 struct cli_state *pcli = (struct cli_state *)state;
7260 fstring fname;
7261 NTSTATUS status = NT_STATUS_OK;
7263 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
7265 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7266 return NT_STATUS_OK;
7268 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7269 status = cli_rmdir(pcli, fname);
7270 if (!NT_STATUS_IS_OK(status)) {
7271 printf("del_fn: failed to rmdir %s\n,", fname );
7273 } else {
7274 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7275 if (!NT_STATUS_IS_OK(status)) {
7276 printf("del_fn: failed to unlink %s\n,", fname );
7279 return status;
7282 struct sn_state {
7283 int matched;
7284 int i;
7285 bool val;
7288 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
7289 const char *name, void *state)
7291 struct sn_state *s = (struct sn_state *)state;
7292 int i = s->i;
7294 #if 0
7295 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
7296 i, finfo->name, finfo->short_name);
7297 #endif
7299 if (strchr(force_shortname_chars, i)) {
7300 if (!finfo->short_name) {
7301 /* Shortname not created when it should be. */
7302 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
7303 __location__, finfo->name, i);
7304 s->val = true;
7306 } else if (finfo->short_name){
7307 /* Shortname created when it should not be. */
7308 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
7309 __location__, finfo->short_name, finfo->name);
7310 s->val = true;
7312 s->matched += 1;
7313 return NT_STATUS_OK;
7316 static bool run_shortname_test(int dummy)
7318 static struct cli_state *cli;
7319 bool correct = True;
7320 int i;
7321 struct sn_state s;
7322 char fname[40];
7323 NTSTATUS status;
7325 printf("starting shortname test\n");
7327 if (!torture_open_connection(&cli, 0)) {
7328 return False;
7331 smbXcli_conn_set_sockopt(cli->conn, sockops);
7333 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7334 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7335 cli_rmdir(cli, "\\shortname");
7337 status = cli_mkdir(cli, "\\shortname");
7338 if (!NT_STATUS_IS_OK(status)) {
7339 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
7340 __location__, nt_errstr(status));
7341 correct = false;
7342 goto out;
7345 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
7346 correct = false;
7347 goto out;
7349 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
7350 correct = false;
7351 goto out;
7354 s.val = false;
7356 for (i = 32; i < 128; i++) {
7357 uint16_t fnum = (uint16_t)-1;
7359 s.i = i;
7361 if (strchr(illegal_chars, i)) {
7362 continue;
7364 fname[15] = i;
7366 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
7367 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
7368 if (!NT_STATUS_IS_OK(status)) {
7369 d_printf("(%s) cli_nt_create of %s failed: %s\n",
7370 __location__, fname, nt_errstr(status));
7371 correct = false;
7372 goto out;
7374 cli_close(cli, fnum);
7376 s.matched = 0;
7377 status = cli_list(cli, "\\shortname\\test*.*", 0,
7378 shortname_list_fn, &s);
7379 if (s.matched != 1) {
7380 d_printf("(%s) failed to list %s: %s\n",
7381 __location__, fname, nt_errstr(status));
7382 correct = false;
7383 goto out;
7386 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7387 if (!NT_STATUS_IS_OK(status)) {
7388 d_printf("(%s) failed to delete %s: %s\n",
7389 __location__, fname, nt_errstr(status));
7390 correct = false;
7391 goto out;
7394 if (s.val) {
7395 correct = false;
7396 goto out;
7400 out:
7402 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7403 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7404 cli_rmdir(cli, "\\shortname");
7405 torture_close_connection(cli);
7406 return correct;
7409 static void pagedsearch_cb(struct tevent_req *req)
7411 int rc;
7412 struct tldap_message *msg;
7413 char *dn;
7415 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
7416 if (rc != TLDAP_SUCCESS) {
7417 d_printf("tldap_search_paged_recv failed: %s\n",
7418 tldap_err2string(rc));
7419 return;
7421 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
7422 TALLOC_FREE(msg);
7423 return;
7425 if (!tldap_entry_dn(msg, &dn)) {
7426 d_printf("tldap_entry_dn failed\n");
7427 return;
7429 d_printf("%s\n", dn);
7430 TALLOC_FREE(msg);
7433 static bool run_tldap(int dummy)
7435 struct tldap_context *ld;
7436 int fd, rc;
7437 NTSTATUS status;
7438 struct sockaddr_storage addr;
7439 struct tevent_context *ev;
7440 struct tevent_req *req;
7441 char *basedn;
7442 const char *filter;
7444 if (!resolve_name(host, &addr, 0, false)) {
7445 d_printf("could not find host %s\n", host);
7446 return false;
7448 status = open_socket_out(&addr, 389, 9999, &fd);
7449 if (!NT_STATUS_IS_OK(status)) {
7450 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
7451 return false;
7454 ld = tldap_context_create(talloc_tos(), fd);
7455 if (ld == NULL) {
7456 close(fd);
7457 d_printf("tldap_context_create failed\n");
7458 return false;
7461 rc = tldap_fetch_rootdse(ld);
7462 if (rc != TLDAP_SUCCESS) {
7463 d_printf("tldap_fetch_rootdse failed: %s\n",
7464 tldap_errstr(talloc_tos(), ld, rc));
7465 return false;
7468 basedn = tldap_talloc_single_attribute(
7469 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
7470 if (basedn == NULL) {
7471 d_printf("no defaultNamingContext\n");
7472 return false;
7474 d_printf("defaultNamingContext: %s\n", basedn);
7476 ev = tevent_context_init(talloc_tos());
7477 if (ev == NULL) {
7478 d_printf("tevent_context_init failed\n");
7479 return false;
7482 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
7483 TLDAP_SCOPE_SUB, "(objectclass=*)",
7484 NULL, 0, 0,
7485 NULL, 0, NULL, 0, 0, 0, 0, 5);
7486 if (req == NULL) {
7487 d_printf("tldap_search_paged_send failed\n");
7488 return false;
7490 tevent_req_set_callback(req, pagedsearch_cb, NULL);
7492 tevent_req_poll(req, ev);
7494 TALLOC_FREE(req);
7496 /* test search filters against rootDSE */
7497 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
7498 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
7500 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
7501 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
7502 talloc_tos(), NULL, NULL);
7503 if (rc != TLDAP_SUCCESS) {
7504 d_printf("tldap_search with complex filter failed: %s\n",
7505 tldap_errstr(talloc_tos(), ld, rc));
7506 return false;
7509 TALLOC_FREE(ld);
7510 return true;
7513 /* Torture test to ensure no regression of :
7514 https://bugzilla.samba.org/show_bug.cgi?id=7084
7517 static bool run_dir_createtime(int dummy)
7519 struct cli_state *cli;
7520 const char *dname = "\\testdir";
7521 const char *fname = "\\testdir\\testfile";
7522 NTSTATUS status;
7523 struct timespec create_time;
7524 struct timespec create_time1;
7525 uint16_t fnum;
7526 bool ret = false;
7528 if (!torture_open_connection(&cli, 0)) {
7529 return false;
7532 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7533 cli_rmdir(cli, dname);
7535 status = cli_mkdir(cli, dname);
7536 if (!NT_STATUS_IS_OK(status)) {
7537 printf("mkdir failed: %s\n", nt_errstr(status));
7538 goto out;
7541 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
7542 NULL, NULL, NULL);
7543 if (!NT_STATUS_IS_OK(status)) {
7544 printf("cli_qpathinfo2 returned %s\n",
7545 nt_errstr(status));
7546 goto out;
7549 /* Sleep 3 seconds, then create a file. */
7550 sleep(3);
7552 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
7553 DENY_NONE, &fnum);
7554 if (!NT_STATUS_IS_OK(status)) {
7555 printf("cli_openx failed: %s\n", nt_errstr(status));
7556 goto out;
7559 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
7560 NULL, NULL, NULL);
7561 if (!NT_STATUS_IS_OK(status)) {
7562 printf("cli_qpathinfo2 (2) returned %s\n",
7563 nt_errstr(status));
7564 goto out;
7567 if (timespec_compare(&create_time1, &create_time)) {
7568 printf("run_dir_createtime: create time was updated (error)\n");
7569 } else {
7570 printf("run_dir_createtime: create time was not updated (correct)\n");
7571 ret = true;
7574 out:
7576 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7577 cli_rmdir(cli, dname);
7578 if (!torture_close_connection(cli)) {
7579 ret = false;
7581 return ret;
7585 static bool run_streamerror(int dummy)
7587 struct cli_state *cli;
7588 const char *dname = "\\testdir";
7589 const char *streamname =
7590 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
7591 NTSTATUS status;
7592 time_t change_time, access_time, write_time;
7593 off_t size;
7594 uint16_t mode, fnum;
7595 bool ret = true;
7597 if (!torture_open_connection(&cli, 0)) {
7598 return false;
7601 cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7602 cli_rmdir(cli, dname);
7604 status = cli_mkdir(cli, dname);
7605 if (!NT_STATUS_IS_OK(status)) {
7606 printf("mkdir failed: %s\n", nt_errstr(status));
7607 return false;
7610 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
7611 &write_time, &size, &mode);
7612 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7613 printf("pathinfo returned %s, expected "
7614 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7615 nt_errstr(status));
7616 ret = false;
7619 status = cli_ntcreate(cli, streamname, 0x16,
7620 FILE_READ_DATA|FILE_READ_EA|
7621 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
7622 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7623 FILE_OPEN, 0, 0, &fnum);
7625 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7626 printf("ntcreate returned %s, expected "
7627 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7628 nt_errstr(status));
7629 ret = false;
7633 cli_rmdir(cli, dname);
7634 return ret;
7637 static bool run_local_substitute(int dummy)
7639 bool ok = true;
7641 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
7642 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
7643 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
7644 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
7645 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
7646 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
7647 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
7648 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
7650 /* Different captialization rules in sub_basic... */
7652 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
7653 "blaDOM") == 0);
7655 return ok;
7658 static bool run_local_base64(int dummy)
7660 int i;
7661 bool ret = true;
7663 for (i=1; i<2000; i++) {
7664 DATA_BLOB blob1, blob2;
7665 char *b64;
7667 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
7668 blob1.length = i;
7669 generate_random_buffer(blob1.data, blob1.length);
7671 b64 = base64_encode_data_blob(talloc_tos(), blob1);
7672 if (b64 == NULL) {
7673 d_fprintf(stderr, "base64_encode_data_blob failed "
7674 "for %d bytes\n", i);
7675 ret = false;
7677 blob2 = base64_decode_data_blob(b64);
7678 TALLOC_FREE(b64);
7680 if (data_blob_cmp(&blob1, &blob2)) {
7681 d_fprintf(stderr, "data_blob_cmp failed for %d "
7682 "bytes\n", i);
7683 ret = false;
7685 TALLOC_FREE(blob1.data);
7686 data_blob_free(&blob2);
7688 return ret;
7691 static bool run_local_gencache(int dummy)
7693 char *val;
7694 time_t tm;
7695 DATA_BLOB blob;
7697 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
7698 d_printf("%s: gencache_set() failed\n", __location__);
7699 return False;
7702 if (!gencache_get("foo", NULL, NULL)) {
7703 d_printf("%s: gencache_get() failed\n", __location__);
7704 return False;
7707 if (!gencache_get("foo", &val, &tm)) {
7708 d_printf("%s: gencache_get() failed\n", __location__);
7709 return False;
7712 if (strcmp(val, "bar") != 0) {
7713 d_printf("%s: gencache_get() returned %s, expected %s\n",
7714 __location__, val, "bar");
7715 SAFE_FREE(val);
7716 return False;
7719 SAFE_FREE(val);
7721 if (!gencache_del("foo")) {
7722 d_printf("%s: gencache_del() failed\n", __location__);
7723 return False;
7725 if (gencache_del("foo")) {
7726 d_printf("%s: second gencache_del() succeeded\n",
7727 __location__);
7728 return False;
7731 if (gencache_get("foo", &val, &tm)) {
7732 d_printf("%s: gencache_get() on deleted entry "
7733 "succeeded\n", __location__);
7734 return False;
7737 blob = data_blob_string_const_null("bar");
7738 tm = time(NULL) + 60;
7740 if (!gencache_set_data_blob("foo", &blob, tm)) {
7741 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
7742 return False;
7745 if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7746 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
7747 return False;
7750 if (strcmp((const char *)blob.data, "bar") != 0) {
7751 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
7752 __location__, (const char *)blob.data, "bar");
7753 data_blob_free(&blob);
7754 return False;
7757 data_blob_free(&blob);
7759 if (!gencache_del("foo")) {
7760 d_printf("%s: gencache_del() failed\n", __location__);
7761 return False;
7763 if (gencache_del("foo")) {
7764 d_printf("%s: second gencache_del() succeeded\n",
7765 __location__);
7766 return False;
7769 if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7770 d_printf("%s: gencache_get_data_blob() on deleted entry "
7771 "succeeded\n", __location__);
7772 return False;
7775 return True;
7778 static bool rbt_testval(struct db_context *db, const char *key,
7779 const char *value)
7781 struct db_record *rec;
7782 TDB_DATA data = string_tdb_data(value);
7783 bool ret = false;
7784 NTSTATUS status;
7785 TDB_DATA dbvalue;
7787 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
7788 if (rec == NULL) {
7789 d_fprintf(stderr, "fetch_locked failed\n");
7790 goto done;
7792 status = dbwrap_record_store(rec, data, 0);
7793 if (!NT_STATUS_IS_OK(status)) {
7794 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
7795 goto done;
7797 TALLOC_FREE(rec);
7799 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
7800 if (rec == NULL) {
7801 d_fprintf(stderr, "second fetch_locked failed\n");
7802 goto done;
7805 dbvalue = dbwrap_record_get_value(rec);
7806 if ((dbvalue.dsize != data.dsize)
7807 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
7808 d_fprintf(stderr, "Got wrong data back\n");
7809 goto done;
7812 ret = true;
7813 done:
7814 TALLOC_FREE(rec);
7815 return ret;
7818 static bool run_local_rbtree(int dummy)
7820 struct db_context *db;
7821 bool ret = false;
7822 int i;
7824 db = db_open_rbt(NULL);
7826 if (db == NULL) {
7827 d_fprintf(stderr, "db_open_rbt failed\n");
7828 return false;
7831 for (i=0; i<1000; i++) {
7832 char *key, *value;
7834 if (asprintf(&key, "key%ld", random()) == -1) {
7835 goto done;
7837 if (asprintf(&value, "value%ld", random()) == -1) {
7838 SAFE_FREE(key);
7839 goto done;
7842 if (!rbt_testval(db, key, value)) {
7843 SAFE_FREE(key);
7844 SAFE_FREE(value);
7845 goto done;
7848 SAFE_FREE(value);
7849 if (asprintf(&value, "value%ld", random()) == -1) {
7850 SAFE_FREE(key);
7851 goto done;
7854 if (!rbt_testval(db, key, value)) {
7855 SAFE_FREE(key);
7856 SAFE_FREE(value);
7857 goto done;
7860 SAFE_FREE(key);
7861 SAFE_FREE(value);
7864 ret = true;
7866 done:
7867 TALLOC_FREE(db);
7868 return ret;
7873 local test for character set functions
7875 This is a very simple test for the functionality in convert_string_error()
7877 static bool run_local_convert_string(int dummy)
7879 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
7880 const char *test_strings[2] = { "March", "M\303\244rz" };
7881 char dst[7];
7882 int i;
7884 for (i=0; i<2; i++) {
7885 const char *str = test_strings[i];
7886 int len = strlen(str);
7887 size_t converted_size;
7888 bool ret;
7890 memset(dst, 'X', sizeof(dst));
7892 /* first try with real source length */
7893 ret = convert_string_error(CH_UNIX, CH_UTF8,
7894 str, len,
7895 dst, sizeof(dst),
7896 &converted_size);
7897 if (ret != true) {
7898 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7899 goto failed;
7902 if (converted_size != len) {
7903 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7904 str, len, (int)converted_size);
7905 goto failed;
7908 if (strncmp(str, dst, converted_size) != 0) {
7909 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7910 goto failed;
7913 if (strlen(str) != converted_size) {
7914 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7915 (int)strlen(str), (int)converted_size);
7916 goto failed;
7919 if (dst[converted_size] != 'X') {
7920 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7921 goto failed;
7924 /* now with srclen==-1, this causes the nul to be
7925 * converted too */
7926 ret = convert_string_error(CH_UNIX, CH_UTF8,
7927 str, -1,
7928 dst, sizeof(dst),
7929 &converted_size);
7930 if (ret != true) {
7931 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7932 goto failed;
7935 if (converted_size != len+1) {
7936 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7937 str, len, (int)converted_size);
7938 goto failed;
7941 if (strncmp(str, dst, converted_size) != 0) {
7942 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7943 goto failed;
7946 if (len+1 != converted_size) {
7947 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7948 len+1, (int)converted_size);
7949 goto failed;
7952 if (dst[converted_size] != 'X') {
7953 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7954 goto failed;
7960 TALLOC_FREE(tmp_ctx);
7961 return true;
7962 failed:
7963 TALLOC_FREE(tmp_ctx);
7964 return false;
7968 struct talloc_dict_test {
7969 int content;
7972 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
7974 int *count = (int *)priv;
7975 *count += 1;
7976 return 0;
7979 static bool run_local_talloc_dict(int dummy)
7981 struct talloc_dict *dict;
7982 struct talloc_dict_test *t;
7983 int key, count, res;
7984 bool ok;
7986 dict = talloc_dict_init(talloc_tos());
7987 if (dict == NULL) {
7988 return false;
7991 t = talloc(talloc_tos(), struct talloc_dict_test);
7992 if (t == NULL) {
7993 return false;
7996 key = 1;
7997 t->content = 1;
7998 ok = talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), &t);
7999 if (!ok) {
8000 return false;
8003 count = 0;
8004 res = talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count);
8005 if (res == -1) {
8006 return false;
8009 if (count != 1) {
8010 return false;
8013 if (count != res) {
8014 return false;
8017 TALLOC_FREE(dict);
8019 return true;
8022 static bool run_local_string_to_sid(int dummy) {
8023 struct dom_sid sid;
8025 if (string_to_sid(&sid, "S--1-5-32-545")) {
8026 printf("allowing S--1-5-32-545\n");
8027 return false;
8029 if (string_to_sid(&sid, "S-1-5-32-+545")) {
8030 printf("allowing S-1-5-32-+545\n");
8031 return false;
8033 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")) {
8034 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
8035 return false;
8037 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
8038 printf("allowing S-1-5-32-545-abc\n");
8039 return false;
8041 if (!string_to_sid(&sid, "S-1-5-32-545")) {
8042 printf("could not parse S-1-5-32-545\n");
8043 return false;
8045 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
8046 printf("mis-parsed S-1-5-32-545 as %s\n",
8047 sid_string_tos(&sid));
8048 return false;
8050 return true;
8053 static bool run_local_binary_to_sid(int dummy) {
8054 struct dom_sid *sid = talloc(NULL, struct dom_sid);
8055 static const char good_binary_sid[] = {
8056 0x1, /* revision number */
8057 15, /* num auths */
8058 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8059 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8060 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8061 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8062 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8063 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8064 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8065 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8066 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8067 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8068 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8069 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8070 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8071 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8072 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8073 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8076 static const char long_binary_sid[] = {
8077 0x1, /* revision number */
8078 15, /* num auths */
8079 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8080 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8081 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8082 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8083 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8084 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8085 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8086 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8087 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8088 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8089 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8090 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8091 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8092 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8093 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8094 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8095 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8096 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8097 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8100 static const char long_binary_sid2[] = {
8101 0x1, /* revision number */
8102 32, /* num auths */
8103 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8104 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8105 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8106 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8107 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8108 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8109 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8110 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8111 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8112 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8113 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8114 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8115 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8116 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8117 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8118 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8119 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8120 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8121 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8122 0x1, 0x1, 0x1, 0x1, /* auth[18] */
8123 0x1, 0x1, 0x1, 0x1, /* auth[19] */
8124 0x1, 0x1, 0x1, 0x1, /* auth[20] */
8125 0x1, 0x1, 0x1, 0x1, /* auth[21] */
8126 0x1, 0x1, 0x1, 0x1, /* auth[22] */
8127 0x1, 0x1, 0x1, 0x1, /* auth[23] */
8128 0x1, 0x1, 0x1, 0x1, /* auth[24] */
8129 0x1, 0x1, 0x1, 0x1, /* auth[25] */
8130 0x1, 0x1, 0x1, 0x1, /* auth[26] */
8131 0x1, 0x1, 0x1, 0x1, /* auth[27] */
8132 0x1, 0x1, 0x1, 0x1, /* auth[28] */
8133 0x1, 0x1, 0x1, 0x1, /* auth[29] */
8134 0x1, 0x1, 0x1, 0x1, /* auth[30] */
8135 0x1, 0x1, 0x1, 0x1, /* auth[31] */
8138 if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
8139 return false;
8141 if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
8142 return false;
8144 if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
8145 return false;
8147 return true;
8150 /* Split a path name into filename and stream name components. Canonicalise
8151 * such that an implicit $DATA token is always explicit.
8153 * The "specification" of this function can be found in the
8154 * run_local_stream_name() function in torture.c, I've tried those
8155 * combinations against a W2k3 server.
8158 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
8159 char **pbase, char **pstream)
8161 char *base = NULL;
8162 char *stream = NULL;
8163 char *sname; /* stream name */
8164 const char *stype; /* stream type */
8166 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
8168 sname = strchr_m(fname, ':');
8170 if (lp_posix_pathnames() || (sname == NULL)) {
8171 if (pbase != NULL) {
8172 base = talloc_strdup(mem_ctx, fname);
8173 NT_STATUS_HAVE_NO_MEMORY(base);
8175 goto done;
8178 if (pbase != NULL) {
8179 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
8180 NT_STATUS_HAVE_NO_MEMORY(base);
8183 sname += 1;
8185 stype = strchr_m(sname, ':');
8187 if (stype == NULL) {
8188 sname = talloc_strdup(mem_ctx, sname);
8189 stype = "$DATA";
8191 else {
8192 if (strcasecmp_m(stype, ":$DATA") != 0) {
8194 * If there is an explicit stream type, so far we only
8195 * allow $DATA. Is there anything else allowed? -- vl
8197 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
8198 TALLOC_FREE(base);
8199 return NT_STATUS_OBJECT_NAME_INVALID;
8201 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
8202 stype += 1;
8205 if (sname == NULL) {
8206 TALLOC_FREE(base);
8207 return NT_STATUS_NO_MEMORY;
8210 if (sname[0] == '\0') {
8212 * no stream name, so no stream
8214 goto done;
8217 if (pstream != NULL) {
8218 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
8219 if (stream == NULL) {
8220 TALLOC_FREE(sname);
8221 TALLOC_FREE(base);
8222 return NT_STATUS_NO_MEMORY;
8225 * upper-case the type field
8227 strupper_m(strchr_m(stream, ':')+1);
8230 done:
8231 if (pbase != NULL) {
8232 *pbase = base;
8234 if (pstream != NULL) {
8235 *pstream = stream;
8237 return NT_STATUS_OK;
8240 static bool test_stream_name(const char *fname, const char *expected_base,
8241 const char *expected_stream,
8242 NTSTATUS expected_status)
8244 NTSTATUS status;
8245 char *base = NULL;
8246 char *stream = NULL;
8248 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
8249 if (!NT_STATUS_EQUAL(status, expected_status)) {
8250 goto error;
8253 if (!NT_STATUS_IS_OK(status)) {
8254 return true;
8257 if (base == NULL) goto error;
8259 if (strcmp(expected_base, base) != 0) goto error;
8261 if ((expected_stream != NULL) && (stream == NULL)) goto error;
8262 if ((expected_stream == NULL) && (stream != NULL)) goto error;
8264 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
8265 goto error;
8267 TALLOC_FREE(base);
8268 TALLOC_FREE(stream);
8269 return true;
8271 error:
8272 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
8273 fname, expected_base ? expected_base : "<NULL>",
8274 expected_stream ? expected_stream : "<NULL>",
8275 nt_errstr(expected_status));
8276 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
8277 base ? base : "<NULL>", stream ? stream : "<NULL>",
8278 nt_errstr(status));
8279 TALLOC_FREE(base);
8280 TALLOC_FREE(stream);
8281 return false;
8284 static bool run_local_stream_name(int dummy)
8286 bool ret = true;
8288 ret &= test_stream_name(
8289 "bla", "bla", NULL, NT_STATUS_OK);
8290 ret &= test_stream_name(
8291 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
8292 ret &= test_stream_name(
8293 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8294 ret &= test_stream_name(
8295 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
8296 ret &= test_stream_name(
8297 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8298 ret &= test_stream_name(
8299 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
8300 ret &= test_stream_name(
8301 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
8302 ret &= test_stream_name(
8303 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
8305 return ret;
8308 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
8310 if (a.length != b.length) {
8311 printf("a.length=%d != b.length=%d\n",
8312 (int)a.length, (int)b.length);
8313 return false;
8315 if (memcmp(a.data, b.data, a.length) != 0) {
8316 printf("a.data and b.data differ\n");
8317 return false;
8319 return true;
8322 static bool run_local_memcache(int dummy)
8324 struct memcache *cache;
8325 DATA_BLOB k1, k2;
8326 DATA_BLOB d1, d2, d3;
8327 DATA_BLOB v1, v2, v3;
8329 TALLOC_CTX *mem_ctx;
8330 char *str1, *str2;
8331 size_t size1, size2;
8332 bool ret = false;
8334 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
8336 if (cache == NULL) {
8337 printf("memcache_init failed\n");
8338 return false;
8341 d1 = data_blob_const("d1", 2);
8342 d2 = data_blob_const("d2", 2);
8343 d3 = data_blob_const("d3", 2);
8345 k1 = data_blob_const("d1", 2);
8346 k2 = data_blob_const("d2", 2);
8348 memcache_add(cache, STAT_CACHE, k1, d1);
8349 memcache_add(cache, GETWD_CACHE, k2, d2);
8351 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
8352 printf("could not find k1\n");
8353 return false;
8355 if (!data_blob_equal(d1, v1)) {
8356 return false;
8359 if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8360 printf("could not find k2\n");
8361 return false;
8363 if (!data_blob_equal(d2, v2)) {
8364 return false;
8367 memcache_add(cache, STAT_CACHE, k1, d3);
8369 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
8370 printf("could not find replaced k1\n");
8371 return false;
8373 if (!data_blob_equal(d3, v3)) {
8374 return false;
8377 memcache_add(cache, GETWD_CACHE, k1, d1);
8379 if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8380 printf("Did find k2, should have been purged\n");
8381 return false;
8384 TALLOC_FREE(cache);
8386 cache = memcache_init(NULL, 0);
8388 mem_ctx = talloc_init("foo");
8390 str1 = talloc_strdup(mem_ctx, "string1");
8391 str2 = talloc_strdup(mem_ctx, "string2");
8393 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8394 data_blob_string_const("torture"), &str1);
8395 size1 = talloc_total_size(cache);
8397 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8398 data_blob_string_const("torture"), &str2);
8399 size2 = talloc_total_size(cache);
8401 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
8403 if (size2 > size1) {
8404 printf("memcache leaks memory!\n");
8405 goto fail;
8408 ret = true;
8409 fail:
8410 TALLOC_FREE(cache);
8411 return ret;
8414 static void wbclient_done(struct tevent_req *req)
8416 wbcErr wbc_err;
8417 struct winbindd_response *wb_resp;
8418 int *i = (int *)tevent_req_callback_data_void(req);
8420 wbc_err = wb_trans_recv(req, req, &wb_resp);
8421 TALLOC_FREE(req);
8422 *i += 1;
8423 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
8426 static bool run_local_wbclient(int dummy)
8428 struct event_context *ev;
8429 struct wb_context **wb_ctx;
8430 struct winbindd_request wb_req;
8431 bool result = false;
8432 int i, j;
8434 BlockSignals(True, SIGPIPE);
8436 ev = tevent_context_init_byname(talloc_tos(), "epoll");
8437 if (ev == NULL) {
8438 goto fail;
8441 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
8442 if (wb_ctx == NULL) {
8443 goto fail;
8446 ZERO_STRUCT(wb_req);
8447 wb_req.cmd = WINBINDD_PING;
8449 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
8451 for (i=0; i<torture_nprocs; i++) {
8452 wb_ctx[i] = wb_context_init(ev, NULL);
8453 if (wb_ctx[i] == NULL) {
8454 goto fail;
8456 for (j=0; j<torture_numops; j++) {
8457 struct tevent_req *req;
8458 req = wb_trans_send(ev, ev, wb_ctx[i],
8459 (j % 2) == 0, &wb_req);
8460 if (req == NULL) {
8461 goto fail;
8463 tevent_req_set_callback(req, wbclient_done, &i);
8467 i = 0;
8469 while (i < torture_nprocs * torture_numops) {
8470 tevent_loop_once(ev);
8473 result = true;
8474 fail:
8475 TALLOC_FREE(ev);
8476 return result;
8479 static void getaddrinfo_finished(struct tevent_req *req)
8481 char *name = (char *)tevent_req_callback_data_void(req);
8482 struct addrinfo *ainfo;
8483 int res;
8485 res = getaddrinfo_recv(req, &ainfo);
8486 if (res != 0) {
8487 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
8488 return;
8490 d_printf("gai(%s) succeeded\n", name);
8491 freeaddrinfo(ainfo);
8494 static bool run_getaddrinfo_send(int dummy)
8496 TALLOC_CTX *frame = talloc_stackframe();
8497 struct fncall_context *ctx;
8498 struct tevent_context *ev;
8499 bool result = false;
8500 const char *names[4] = { "www.samba.org", "notfound.samba.org",
8501 "www.slashdot.org", "heise.de" };
8502 struct tevent_req *reqs[4];
8503 int i;
8505 ev = event_context_init(frame);
8506 if (ev == NULL) {
8507 goto fail;
8510 ctx = fncall_context_init(frame, 4);
8512 for (i=0; i<ARRAY_SIZE(names); i++) {
8513 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
8514 NULL);
8515 if (reqs[i] == NULL) {
8516 goto fail;
8518 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
8519 discard_const_p(void, names[i]));
8522 for (i=0; i<ARRAY_SIZE(reqs); i++) {
8523 tevent_loop_once(ev);
8526 result = true;
8527 fail:
8528 TALLOC_FREE(frame);
8529 return result;
8532 static bool dbtrans_inc(struct db_context *db)
8534 struct db_record *rec;
8535 uint32_t val;
8536 bool ret = false;
8537 NTSTATUS status;
8538 TDB_DATA value;
8540 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
8541 if (rec == NULL) {
8542 printf(__location__ "fetch_lock failed\n");
8543 return false;
8546 value = dbwrap_record_get_value(rec);
8548 if (value.dsize != sizeof(uint32_t)) {
8549 printf(__location__ "value.dsize = %d\n",
8550 (int)value.dsize);
8551 goto fail;
8554 memcpy(&val, value.dptr, sizeof(val));
8555 val += 1;
8557 status = dbwrap_record_store(
8558 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
8559 if (!NT_STATUS_IS_OK(status)) {
8560 printf(__location__ "store failed: %s\n",
8561 nt_errstr(status));
8562 goto fail;
8565 ret = true;
8566 fail:
8567 TALLOC_FREE(rec);
8568 return ret;
8571 static bool run_local_dbtrans(int dummy)
8573 struct db_context *db;
8574 struct db_record *rec;
8575 NTSTATUS status;
8576 uint32_t initial;
8577 int res;
8578 TDB_DATA value;
8580 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
8581 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1);
8582 if (db == NULL) {
8583 printf("Could not open transtest.db\n");
8584 return false;
8587 res = dbwrap_transaction_start(db);
8588 if (res != 0) {
8589 printf(__location__ "transaction_start failed\n");
8590 return false;
8593 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
8594 if (rec == NULL) {
8595 printf(__location__ "fetch_lock failed\n");
8596 return false;
8599 value = dbwrap_record_get_value(rec);
8601 if (value.dptr == NULL) {
8602 initial = 0;
8603 status = dbwrap_record_store(
8604 rec, make_tdb_data((uint8_t *)&initial,
8605 sizeof(initial)),
8607 if (!NT_STATUS_IS_OK(status)) {
8608 printf(__location__ "store returned %s\n",
8609 nt_errstr(status));
8610 return false;
8614 TALLOC_FREE(rec);
8616 res = dbwrap_transaction_commit(db);
8617 if (res != 0) {
8618 printf(__location__ "transaction_commit failed\n");
8619 return false;
8622 while (true) {
8623 uint32_t val, val2;
8624 int i;
8626 res = dbwrap_transaction_start(db);
8627 if (res != 0) {
8628 printf(__location__ "transaction_start failed\n");
8629 break;
8632 status = dbwrap_fetch_uint32(db, "transtest", &val);
8633 if (!NT_STATUS_IS_OK(status)) {
8634 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
8635 nt_errstr(status));
8636 break;
8639 for (i=0; i<10; i++) {
8640 if (!dbtrans_inc(db)) {
8641 return false;
8645 status = dbwrap_fetch_uint32(db, "transtest", &val2);
8646 if (!NT_STATUS_IS_OK(status)) {
8647 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
8648 nt_errstr(status));
8649 break;
8652 if (val2 != val + 10) {
8653 printf(__location__ "val=%d, val2=%d\n",
8654 (int)val, (int)val2);
8655 break;
8658 printf("val2=%d\r", val2);
8660 res = dbwrap_transaction_commit(db);
8661 if (res != 0) {
8662 printf(__location__ "transaction_commit failed\n");
8663 break;
8667 TALLOC_FREE(db);
8668 return true;
8672 * Just a dummy test to be run under a debugger. There's no real way
8673 * to inspect the tevent_select specific function from outside of
8674 * tevent_select.c.
8677 static bool run_local_tevent_select(int dummy)
8679 struct tevent_context *ev;
8680 struct tevent_fd *fd1, *fd2;
8681 bool result = false;
8683 ev = tevent_context_init_byname(NULL, "select");
8684 if (ev == NULL) {
8685 d_fprintf(stderr, "tevent_context_init_byname failed\n");
8686 goto fail;
8689 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
8690 if (fd1 == NULL) {
8691 d_fprintf(stderr, "tevent_add_fd failed\n");
8692 goto fail;
8694 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
8695 if (fd2 == NULL) {
8696 d_fprintf(stderr, "tevent_add_fd failed\n");
8697 goto fail;
8699 TALLOC_FREE(fd2);
8701 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
8702 if (fd2 == NULL) {
8703 d_fprintf(stderr, "tevent_add_fd failed\n");
8704 goto fail;
8707 result = true;
8708 fail:
8709 TALLOC_FREE(ev);
8710 return result;
8713 static bool run_local_hex_encode_buf(int dummy)
8715 char buf[17];
8716 uint8_t src[8];
8717 int i;
8719 for (i=0; i<sizeof(src); i++) {
8720 src[i] = i;
8722 hex_encode_buf(buf, src, sizeof(src));
8723 if (strcmp(buf, "0001020304050607") != 0) {
8724 return false;
8726 hex_encode_buf(buf, NULL, 0);
8727 if (buf[0] != '\0') {
8728 return false;
8730 return true;
8733 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
8734 "0.0.0.0",
8735 "::0",
8736 "1.2.3.1",
8737 "0.0.0.0",
8738 "0.0.0.0",
8739 "1.2.3.2",
8740 "1.2.3.3",
8741 "1.2.3.4",
8742 "1.2.3.5",
8743 "::0",
8744 "1.2.3.6",
8745 "1.2.3.7",
8746 "::0",
8747 "::0",
8748 "::0",
8749 "1.2.3.8",
8750 "1.2.3.9",
8751 "1.2.3.10",
8752 "1.2.3.11",
8753 "1.2.3.12",
8754 "1.2.3.13",
8755 "1001:1111:1111:1000:0:1111:1111:1111",
8756 "1.2.3.1",
8757 "1.2.3.2",
8758 "1.2.3.3",
8759 "1.2.3.12",
8760 "::0",
8761 "::0"
8764 static const char *remove_duplicate_addrs2_test_strings_result[] = {
8765 "1.2.3.1",
8766 "1.2.3.2",
8767 "1.2.3.3",
8768 "1.2.3.4",
8769 "1.2.3.5",
8770 "1.2.3.6",
8771 "1.2.3.7",
8772 "1.2.3.8",
8773 "1.2.3.9",
8774 "1.2.3.10",
8775 "1.2.3.11",
8776 "1.2.3.12",
8777 "1.2.3.13",
8778 "1001:1111:1111:1000:0:1111:1111:1111"
8781 static bool run_local_remove_duplicate_addrs2(int dummy)
8783 struct ip_service test_vector[28];
8784 int count, i;
8786 /* Construct the sockaddr_storage test vector. */
8787 for (i = 0; i < 28; i++) {
8788 struct addrinfo hints;
8789 struct addrinfo *res = NULL;
8790 int ret;
8792 memset(&hints, '\0', sizeof(hints));
8793 hints.ai_flags = AI_NUMERICHOST;
8794 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
8795 NULL,
8796 &hints,
8797 &res);
8798 if (ret) {
8799 fprintf(stderr, "getaddrinfo failed on [%s]\n",
8800 remove_duplicate_addrs2_test_strings_vector[i]);
8801 return false;
8803 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
8804 memcpy(&test_vector[i].ss,
8805 res->ai_addr,
8806 res->ai_addrlen);
8807 freeaddrinfo(res);
8810 count = remove_duplicate_addrs2(test_vector, i);
8812 if (count != 14) {
8813 fprintf(stderr, "count wrong (%d) should be 14\n",
8814 count);
8815 return false;
8818 for (i = 0; i < count; i++) {
8819 char addr[INET6_ADDRSTRLEN];
8821 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
8823 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
8824 fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
8826 addr,
8827 remove_duplicate_addrs2_test_strings_result[i]);
8828 return false;
8832 printf("run_local_remove_duplicate_addrs2: success\n");
8833 return true;
8836 static double create_procs(bool (*fn)(int), bool *result)
8838 int i, status;
8839 volatile pid_t *child_status;
8840 volatile bool *child_status_out;
8841 int synccount;
8842 int tries = 8;
8843 struct timeval start;
8845 synccount = 0;
8847 child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*torture_nprocs);
8848 if (!child_status) {
8849 printf("Failed to setup shared memory\n");
8850 return -1;
8853 child_status_out = (volatile bool *)shm_setup(sizeof(bool)*torture_nprocs);
8854 if (!child_status_out) {
8855 printf("Failed to setup result status shared memory\n");
8856 return -1;
8859 for (i = 0; i < torture_nprocs; i++) {
8860 child_status[i] = 0;
8861 child_status_out[i] = True;
8864 start = timeval_current();
8866 for (i=0;i<torture_nprocs;i++) {
8867 procnum = i;
8868 if (fork() == 0) {
8869 pid_t mypid = getpid();
8870 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
8872 slprintf(myname,sizeof(myname),"CLIENT%d", i);
8874 while (1) {
8875 if (torture_open_connection(&current_cli, i)) break;
8876 if (tries-- == 0) {
8877 printf("pid %d failed to start\n", (int)getpid());
8878 _exit(1);
8880 smb_msleep(10);
8883 child_status[i] = getpid();
8885 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
8887 child_status_out[i] = fn(i);
8888 _exit(0);
8892 do {
8893 synccount = 0;
8894 for (i=0;i<torture_nprocs;i++) {
8895 if (child_status[i]) synccount++;
8897 if (synccount == torture_nprocs) break;
8898 smb_msleep(10);
8899 } while (timeval_elapsed(&start) < 30);
8901 if (synccount != torture_nprocs) {
8902 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
8903 *result = False;
8904 return timeval_elapsed(&start);
8907 /* start the client load */
8908 start = timeval_current();
8910 for (i=0;i<torture_nprocs;i++) {
8911 child_status[i] = 0;
8914 printf("%d clients started\n", torture_nprocs);
8916 for (i=0;i<torture_nprocs;i++) {
8917 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
8920 printf("\n");
8922 for (i=0;i<torture_nprocs;i++) {
8923 if (!child_status_out[i]) {
8924 *result = False;
8927 return timeval_elapsed(&start);
8930 #define FLAG_MULTIPROC 1
8932 static struct {
8933 const char *name;
8934 bool (*fn)(int);
8935 unsigned flags;
8936 } torture_ops[] = {
8937 {"FDPASS", run_fdpasstest, 0},
8938 {"LOCK1", run_locktest1, 0},
8939 {"LOCK2", run_locktest2, 0},
8940 {"LOCK3", run_locktest3, 0},
8941 {"LOCK4", run_locktest4, 0},
8942 {"LOCK5", run_locktest5, 0},
8943 {"LOCK6", run_locktest6, 0},
8944 {"LOCK7", run_locktest7, 0},
8945 {"LOCK8", run_locktest8, 0},
8946 {"LOCK9", run_locktest9, 0},
8947 {"UNLINK", run_unlinktest, 0},
8948 {"BROWSE", run_browsetest, 0},
8949 {"ATTR", run_attrtest, 0},
8950 {"TRANS2", run_trans2test, 0},
8951 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
8952 {"TORTURE",run_torture, FLAG_MULTIPROC},
8953 {"RANDOMIPC", run_randomipc, 0},
8954 {"NEGNOWAIT", run_negprot_nowait, 0},
8955 {"NBENCH", run_nbench, 0},
8956 {"NBENCH2", run_nbench2, 0},
8957 {"OPLOCK1", run_oplock1, 0},
8958 {"OPLOCK2", run_oplock2, 0},
8959 {"OPLOCK4", run_oplock4, 0},
8960 {"DIR", run_dirtest, 0},
8961 {"DIR1", run_dirtest1, 0},
8962 {"DIR-CREATETIME", run_dir_createtime, 0},
8963 {"DENY1", torture_denytest1, 0},
8964 {"DENY2", torture_denytest2, 0},
8965 {"TCON", run_tcon_test, 0},
8966 {"TCONDEV", run_tcon_devtype_test, 0},
8967 {"RW1", run_readwritetest, 0},
8968 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
8969 {"RW3", run_readwritelarge, 0},
8970 {"RW-SIGNING", run_readwritelarge_signtest, 0},
8971 {"OPEN", run_opentest, 0},
8972 {"POSIX", run_simple_posix_open_test, 0},
8973 {"POSIX-APPEND", run_posix_append, 0},
8974 {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
8975 {"ASYNC-ECHO", run_async_echo, 0},
8976 { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
8977 { "SHORTNAME-TEST", run_shortname_test, 0},
8978 { "ADDRCHANGE", run_addrchange, 0},
8979 #if 1
8980 {"OPENATTR", run_openattrtest, 0},
8981 #endif
8982 {"XCOPY", run_xcopy, 0},
8983 {"RENAME", run_rename, 0},
8984 {"DELETE", run_deletetest, 0},
8985 {"DELETE-LN", run_deletetest_ln, 0},
8986 {"PROPERTIES", run_properties, 0},
8987 {"MANGLE", torture_mangle, 0},
8988 {"MANGLE1", run_mangle1, 0},
8989 {"W2K", run_w2ktest, 0},
8990 {"TRANS2SCAN", torture_trans2_scan, 0},
8991 {"NTTRANSSCAN", torture_nttrans_scan, 0},
8992 {"UTABLE", torture_utable, 0},
8993 {"CASETABLE", torture_casetable, 0},
8994 {"ERRMAPEXTRACT", run_error_map_extract, 0},
8995 {"PIPE_NUMBER", run_pipe_number, 0},
8996 {"TCON2", run_tcon2_test, 0},
8997 {"IOCTL", torture_ioctl_test, 0},
8998 {"CHKPATH", torture_chkpath_test, 0},
8999 {"FDSESS", run_fdsesstest, 0},
9000 { "EATEST", run_eatest, 0},
9001 { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
9002 { "CHAIN1", run_chain1, 0},
9003 { "CHAIN2", run_chain2, 0},
9004 { "CHAIN3", run_chain3, 0},
9005 { "WINDOWS-WRITE", run_windows_write, 0},
9006 { "NTTRANS-CREATE", run_nttrans_create, 0},
9007 { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
9008 { "CLI_ECHO", run_cli_echo, 0},
9009 { "GETADDRINFO", run_getaddrinfo_send, 0},
9010 { "TLDAP", run_tldap },
9011 { "STREAMERROR", run_streamerror },
9012 { "NOTIFY-BENCH", run_notify_bench },
9013 { "NOTIFY-BENCH2", run_notify_bench2 },
9014 { "NOTIFY-BENCH3", run_notify_bench3 },
9015 { "BAD-NBT-SESSION", run_bad_nbt_session },
9016 { "SMB-ANY-CONNECT", run_smb_any_connect },
9017 { "NOTIFY-ONLINE", run_notify_online },
9018 { "SMB2-BASIC", run_smb2_basic },
9019 { "SMB2-NEGPROT", run_smb2_negprot },
9020 { "SMB2-SESSION-RECONNECT", run_smb2_session_reconnect },
9021 { "SMB2-TCON-DEPENDENCE", run_smb2_tcon_dependence },
9022 { "SMB2-MULTI-CHANNEL", run_smb2_multi_channel },
9023 { "SMB2-SESSION-REAUTH", run_smb2_session_reauth },
9024 { "CLEANUP1", run_cleanup1 },
9025 { "CLEANUP2", run_cleanup2 },
9026 { "CLEANUP3", run_cleanup3 },
9027 { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
9028 { "LOCAL-GENCACHE", run_local_gencache, 0},
9029 { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
9030 { "LOCAL-CTDB-CONN", run_ctdb_conn, 0},
9031 { "LOCAL-MSG", run_msg_test, 0},
9032 { "LOCAL-DBWRAP-WATCH1", run_dbwrap_watch1, 0 },
9033 { "LOCAL-BASE64", run_local_base64, 0},
9034 { "LOCAL-RBTREE", run_local_rbtree, 0},
9035 { "LOCAL-MEMCACHE", run_local_memcache, 0},
9036 { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
9037 { "LOCAL-WBCLIENT", run_local_wbclient, 0},
9038 { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
9039 { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
9040 { "LOCAL-DBTRANS", run_local_dbtrans, 0},
9041 { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
9042 { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
9043 { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
9044 { "LOCAL-sprintf_append", run_local_sprintf_append, 0},
9045 { "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0},
9046 { "LOCAL-IDMAP-TDB-COMMON", run_idmap_tdb_common_test, 0},
9047 { "LOCAL-remove_duplicate_addrs2", run_local_remove_duplicate_addrs2, 0},
9048 {NULL, NULL, 0}};
9052 /****************************************************************************
9053 run a specified test or "ALL"
9054 ****************************************************************************/
9055 static bool run_test(const char *name)
9057 bool ret = True;
9058 bool result = True;
9059 bool found = False;
9060 int i;
9061 double t;
9062 if (strequal(name,"ALL")) {
9063 for (i=0;torture_ops[i].name;i++) {
9064 run_test(torture_ops[i].name);
9066 found = True;
9069 for (i=0;torture_ops[i].name;i++) {
9070 fstr_sprintf(randomfname, "\\XX%x",
9071 (unsigned)random());
9073 if (strequal(name, torture_ops[i].name)) {
9074 found = True;
9075 printf("Running %s\n", name);
9076 if (torture_ops[i].flags & FLAG_MULTIPROC) {
9077 t = create_procs(torture_ops[i].fn, &result);
9078 if (!result) {
9079 ret = False;
9080 printf("TEST %s FAILED!\n", name);
9082 } else {
9083 struct timeval start;
9084 start = timeval_current();
9085 if (!torture_ops[i].fn(0)) {
9086 ret = False;
9087 printf("TEST %s FAILED!\n", name);
9089 t = timeval_elapsed(&start);
9091 printf("%s took %g secs\n\n", name, t);
9095 if (!found) {
9096 printf("Did not find a test named %s\n", name);
9097 ret = False;
9100 return ret;
9104 static void usage(void)
9106 int i;
9108 printf("WARNING samba4 test suite is much more complete nowadays.\n");
9109 printf("Please use samba4 torture.\n\n");
9111 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
9113 printf("\t-d debuglevel\n");
9114 printf("\t-U user%%pass\n");
9115 printf("\t-k use kerberos\n");
9116 printf("\t-N numprocs\n");
9117 printf("\t-n my_netbios_name\n");
9118 printf("\t-W workgroup\n");
9119 printf("\t-o num_operations\n");
9120 printf("\t-O socket_options\n");
9121 printf("\t-m maximum protocol\n");
9122 printf("\t-L use oplocks\n");
9123 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
9124 printf("\t-A showall\n");
9125 printf("\t-p port\n");
9126 printf("\t-s seed\n");
9127 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
9128 printf("\t-f filename filename to test\n");
9129 printf("\n\n");
9131 printf("tests are:");
9132 for (i=0;torture_ops[i].name;i++) {
9133 printf(" %s", torture_ops[i].name);
9135 printf("\n");
9137 printf("default test is ALL\n");
9139 exit(1);
9142 /****************************************************************************
9143 main program
9144 ****************************************************************************/
9145 int main(int argc,char *argv[])
9147 int opt, i;
9148 char *p;
9149 int gotuser = 0;
9150 int gotpass = 0;
9151 bool correct = True;
9152 TALLOC_CTX *frame = talloc_stackframe();
9153 int seed = time(NULL);
9155 #ifdef HAVE_SETBUFFER
9156 setbuffer(stdout, NULL, 0);
9157 #endif
9159 setup_logging("smbtorture", DEBUG_STDOUT);
9161 load_case_tables();
9163 if (is_default_dyn_CONFIGFILE()) {
9164 if(getenv("SMB_CONF_PATH")) {
9165 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
9168 lp_load_global(get_dyn_CONFIGFILE());
9169 load_interfaces();
9171 if (argc < 2) {
9172 usage();
9175 for(p = argv[1]; *p; p++)
9176 if(*p == '\\')
9177 *p = '/';
9179 if (strncmp(argv[1], "//", 2)) {
9180 usage();
9183 fstrcpy(host, &argv[1][2]);
9184 p = strchr_m(&host[2],'/');
9185 if (!p) {
9186 usage();
9188 *p = 0;
9189 fstrcpy(share, p+1);
9191 fstrcpy(myname, get_myname(talloc_tos()));
9192 if (!*myname) {
9193 fprintf(stderr, "Failed to get my hostname.\n");
9194 return 1;
9197 if (*username == 0 && getenv("LOGNAME")) {
9198 fstrcpy(username,getenv("LOGNAME"));
9201 argc--;
9202 argv++;
9204 fstrcpy(workgroup, lp_workgroup());
9206 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
9207 != EOF) {
9208 switch (opt) {
9209 case 'p':
9210 port_to_use = atoi(optarg);
9211 break;
9212 case 's':
9213 seed = atoi(optarg);
9214 break;
9215 case 'W':
9216 fstrcpy(workgroup,optarg);
9217 break;
9218 case 'm':
9219 max_protocol = interpret_protocol(optarg, max_protocol);
9220 break;
9221 case 'N':
9222 torture_nprocs = atoi(optarg);
9223 break;
9224 case 'o':
9225 torture_numops = atoi(optarg);
9226 break;
9227 case 'd':
9228 lp_set_cmdline("log level", optarg);
9229 break;
9230 case 'O':
9231 sockops = optarg;
9232 break;
9233 case 'L':
9234 use_oplocks = True;
9235 break;
9236 case 'l':
9237 local_path = optarg;
9238 break;
9239 case 'A':
9240 torture_showall = True;
9241 break;
9242 case 'n':
9243 fstrcpy(myname, optarg);
9244 break;
9245 case 'c':
9246 client_txt = optarg;
9247 break;
9248 case 'e':
9249 do_encrypt = true;
9250 break;
9251 case 'k':
9252 #ifdef HAVE_KRB5
9253 use_kerberos = True;
9254 #else
9255 d_printf("No kerberos support compiled in\n");
9256 exit(1);
9257 #endif
9258 break;
9259 case 'U':
9260 gotuser = 1;
9261 fstrcpy(username,optarg);
9262 p = strchr_m(username,'%');
9263 if (p) {
9264 *p = 0;
9265 fstrcpy(password, p+1);
9266 gotpass = 1;
9268 break;
9269 case 'b':
9270 fstrcpy(multishare_conn_fname, optarg);
9271 use_multishare_conn = True;
9272 break;
9273 case 'B':
9274 torture_blocksize = atoi(optarg);
9275 break;
9276 case 'f':
9277 test_filename = SMB_STRDUP(optarg);
9278 break;
9279 default:
9280 printf("Unknown option %c (%d)\n", (char)opt, opt);
9281 usage();
9285 d_printf("using seed %d\n", seed);
9287 srandom(seed);
9289 if(use_kerberos && !gotuser) gotpass = True;
9291 while (!gotpass) {
9292 p = getpass("Password:");
9293 if (p) {
9294 fstrcpy(password, p);
9295 gotpass = 1;
9299 printf("host=%s share=%s user=%s myname=%s\n",
9300 host, share, username, myname);
9302 if (argc == optind) {
9303 correct = run_test("ALL");
9304 } else {
9305 for (i=optind;i<argc;i++) {
9306 if (!run_test(argv[i])) {
9307 correct = False;
9312 TALLOC_FREE(frame);
9314 if (correct) {
9315 return(0);
9316 } else {
9317 return(1);