s3:smbd: change blocking.c to use fsp_fnum_dbg() for fsp->fnum logging.
[Samba/gebeck_regimport.git] / source3 / torture / torture.c
blob5fa633060cd1a5e8c92c90e82fa8eb8900f098d8
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 /* Ensure st_mode == 0600 */
5406 if ((sbuf.st_ex_mode & 07777) != 0600) {
5407 printf("posix_open - bad permissions 0%o != 0600\n",
5408 (unsigned int)(sbuf.st_ex_mode & 07777));
5409 goto out;
5412 /* Test ftruncate - set file size back to zero. */
5413 status = cli_ftruncate(cli1, fnum1, 0);
5414 if (!NT_STATUS_IS_OK(status)) {
5415 printf("ftruncate failed (%s)\n", nt_errstr(status));
5416 goto out;
5419 status = cli_close(cli1, fnum1);
5420 if (!NT_STATUS_IS_OK(status)) {
5421 printf("close failed (%s)\n", nt_errstr(status));
5422 goto out;
5425 /* Now open the file again for read only. */
5426 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5427 if (!NT_STATUS_IS_OK(status)) {
5428 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5429 goto out;
5432 /* Now unlink while open. */
5433 status = cli_posix_unlink(cli1, fname);
5434 if (!NT_STATUS_IS_OK(status)) {
5435 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5436 goto out;
5439 status = cli_close(cli1, fnum1);
5440 if (!NT_STATUS_IS_OK(status)) {
5441 printf("close(2) failed (%s)\n", nt_errstr(status));
5442 goto out;
5445 /* Ensure the file has gone. */
5446 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5447 if (NT_STATUS_IS_OK(status)) {
5448 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5449 goto out;
5452 /* Create again to test open with O_TRUNC. */
5453 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
5454 if (!NT_STATUS_IS_OK(status)) {
5455 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5456 goto out;
5459 /* Test ftruncate - set file size. */
5460 status = cli_ftruncate(cli1, fnum1, 1000);
5461 if (!NT_STATUS_IS_OK(status)) {
5462 printf("ftruncate failed (%s)\n", nt_errstr(status));
5463 goto out;
5466 /* Ensure st_size == 1000 */
5467 status = cli_posix_stat(cli1, fname, &sbuf);
5468 if (!NT_STATUS_IS_OK(status)) {
5469 printf("stat failed (%s)\n", nt_errstr(status));
5470 goto out;
5473 if (sbuf.st_ex_size != 1000) {
5474 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5475 goto out;
5478 status = cli_close(cli1, fnum1);
5479 if (!NT_STATUS_IS_OK(status)) {
5480 printf("close(2) failed (%s)\n", nt_errstr(status));
5481 goto out;
5484 /* Re-open with O_TRUNC. */
5485 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
5486 if (!NT_STATUS_IS_OK(status)) {
5487 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5488 goto out;
5491 /* Ensure st_size == 0 */
5492 status = cli_posix_stat(cli1, fname, &sbuf);
5493 if (!NT_STATUS_IS_OK(status)) {
5494 printf("stat failed (%s)\n", nt_errstr(status));
5495 goto out;
5498 if (sbuf.st_ex_size != 0) {
5499 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5500 goto out;
5503 status = cli_close(cli1, fnum1);
5504 if (!NT_STATUS_IS_OK(status)) {
5505 printf("close failed (%s)\n", nt_errstr(status));
5506 goto out;
5509 status = cli_posix_unlink(cli1, fname);
5510 if (!NT_STATUS_IS_OK(status)) {
5511 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5512 goto out;
5515 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
5516 if (!NT_STATUS_IS_OK(status)) {
5517 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5518 dname, nt_errstr(status));
5519 goto out;
5522 cli_close(cli1, fnum1);
5524 /* What happens when we try and POSIX open a directory for write ? */
5525 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
5526 if (NT_STATUS_IS_OK(status)) {
5527 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5528 goto out;
5529 } else {
5530 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
5531 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5532 goto out;
5536 /* Create the file. */
5537 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5538 0600, &fnum1);
5539 if (!NT_STATUS_IS_OK(status)) {
5540 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5541 goto out;
5544 /* Write some data into it. */
5545 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5546 NULL);
5547 if (!NT_STATUS_IS_OK(status)) {
5548 printf("cli_write failed: %s\n", nt_errstr(status));
5549 goto out;
5552 cli_close(cli1, fnum1);
5554 /* Now create a hardlink. */
5555 status = cli_posix_hardlink(cli1, fname, hname);
5556 if (!NT_STATUS_IS_OK(status)) {
5557 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5558 goto out;
5561 /* Now create a symlink. */
5562 status = cli_posix_symlink(cli1, fname, sname);
5563 if (!NT_STATUS_IS_OK(status)) {
5564 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5565 goto out;
5568 /* Open the hardlink for read. */
5569 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5570 if (!NT_STATUS_IS_OK(status)) {
5571 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5572 goto out;
5575 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
5576 if (!NT_STATUS_IS_OK(status)) {
5577 printf("POSIX read of %s failed (%s)\n", hname,
5578 nt_errstr(status));
5579 goto out;
5580 } else if (nread != 10) {
5581 printf("POSIX read of %s failed. Received %ld, expected %d\n",
5582 hname, (unsigned long)nread, 10);
5583 goto out;
5586 if (memcmp(buf, "TEST DATA\n", 10)) {
5587 printf("invalid data read from hardlink\n");
5588 goto out;
5591 /* Do a POSIX lock/unlock. */
5592 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5593 if (!NT_STATUS_IS_OK(status)) {
5594 printf("POSIX lock failed %s\n", nt_errstr(status));
5595 goto out;
5598 /* Punch a hole in the locked area. */
5599 status = cli_posix_unlock(cli1, fnum1, 10, 80);
5600 if (!NT_STATUS_IS_OK(status)) {
5601 printf("POSIX unlock failed %s\n", nt_errstr(status));
5602 goto out;
5605 cli_close(cli1, fnum1);
5607 /* Open the symlink for read - this should fail. A POSIX
5608 client should not be doing opens on a symlink. */
5609 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5610 if (NT_STATUS_IS_OK(status)) {
5611 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5612 goto out;
5613 } else {
5614 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
5615 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5616 printf("POSIX open of %s should have failed "
5617 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5618 "failed with %s instead.\n",
5619 sname, nt_errstr(status));
5620 goto out;
5624 status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5625 if (!NT_STATUS_IS_OK(status)) {
5626 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5627 goto out;
5630 if (strcmp(namebuf, fname) != 0) {
5631 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5632 sname, fname, namebuf);
5633 goto out;
5636 status = cli_posix_rmdir(cli1, dname);
5637 if (!NT_STATUS_IS_OK(status)) {
5638 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5639 goto out;
5642 /* Check directory opens with a specific permission. */
5643 status = cli_posix_mkdir(cli1, dname, 0700);
5644 if (!NT_STATUS_IS_OK(status)) {
5645 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5646 goto out;
5649 /* Ensure st_mode == 0700 */
5650 status = cli_posix_stat(cli1, dname, &sbuf);
5651 if (!NT_STATUS_IS_OK(status)) {
5652 printf("stat failed (%s)\n", nt_errstr(status));
5653 goto out;
5656 if ((sbuf.st_ex_mode & 07777) != 0700) {
5657 printf("posix_mkdir - bad permissions 0%o != 0700\n",
5658 (unsigned int)(sbuf.st_ex_mode & 07777));
5659 goto out;
5662 printf("Simple POSIX open test passed\n");
5663 correct = true;
5665 out:
5667 if (fnum1 != (uint16_t)-1) {
5668 cli_close(cli1, fnum1);
5669 fnum1 = (uint16_t)-1;
5672 cli_setatr(cli1, sname, 0, 0);
5673 cli_posix_unlink(cli1, sname);
5674 cli_setatr(cli1, hname, 0, 0);
5675 cli_posix_unlink(cli1, hname);
5676 cli_setatr(cli1, fname, 0, 0);
5677 cli_posix_unlink(cli1, fname);
5678 cli_setatr(cli1, dname, 0, 0);
5679 cli_posix_rmdir(cli1, dname);
5681 if (!torture_close_connection(cli1)) {
5682 correct = false;
5685 return correct;
5689 static uint32 open_attrs_table[] = {
5690 FILE_ATTRIBUTE_NORMAL,
5691 FILE_ATTRIBUTE_ARCHIVE,
5692 FILE_ATTRIBUTE_READONLY,
5693 FILE_ATTRIBUTE_HIDDEN,
5694 FILE_ATTRIBUTE_SYSTEM,
5696 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
5697 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
5698 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
5699 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5700 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5701 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5703 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5704 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5705 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5706 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
5709 struct trunc_open_results {
5710 unsigned int num;
5711 uint32 init_attr;
5712 uint32 trunc_attr;
5713 uint32 result_attr;
5716 static struct trunc_open_results attr_results[] = {
5717 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5718 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5719 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5720 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5721 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5722 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5723 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5724 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5725 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5726 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5727 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5728 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5729 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5730 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5731 { 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 },
5732 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5733 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5734 { 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 },
5735 { 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 },
5736 { 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 },
5737 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5738 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5739 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5740 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5741 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5742 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
5745 static bool run_openattrtest(int dummy)
5747 static struct cli_state *cli1;
5748 const char *fname = "\\openattr.file";
5749 uint16_t fnum1;
5750 bool correct = True;
5751 uint16 attr;
5752 unsigned int i, j, k, l;
5753 NTSTATUS status;
5755 printf("starting open attr test\n");
5757 if (!torture_open_connection(&cli1, 0)) {
5758 return False;
5761 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5763 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
5764 cli_setatr(cli1, fname, 0, 0);
5765 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5767 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
5768 open_attrs_table[i], FILE_SHARE_NONE,
5769 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5770 if (!NT_STATUS_IS_OK(status)) {
5771 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5772 return False;
5775 status = cli_close(cli1, fnum1);
5776 if (!NT_STATUS_IS_OK(status)) {
5777 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5778 return False;
5781 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
5782 status = cli_ntcreate(cli1, fname, 0,
5783 FILE_READ_DATA|FILE_WRITE_DATA,
5784 open_attrs_table[j],
5785 FILE_SHARE_NONE, FILE_OVERWRITE,
5786 0, 0, &fnum1);
5787 if (!NT_STATUS_IS_OK(status)) {
5788 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5789 if (attr_results[l].num == k) {
5790 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5791 k, open_attrs_table[i],
5792 open_attrs_table[j],
5793 fname, NT_STATUS_V(status), nt_errstr(status));
5794 correct = False;
5798 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5799 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5800 k, open_attrs_table[i], open_attrs_table[j],
5801 nt_errstr(status));
5802 correct = False;
5804 #if 0
5805 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5806 #endif
5807 k++;
5808 continue;
5811 status = cli_close(cli1, fnum1);
5812 if (!NT_STATUS_IS_OK(status)) {
5813 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
5814 return False;
5817 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
5818 if (!NT_STATUS_IS_OK(status)) {
5819 printf("getatr(2) failed (%s)\n", nt_errstr(status));
5820 return False;
5823 #if 0
5824 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5825 k, open_attrs_table[i], open_attrs_table[j], attr );
5826 #endif
5828 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5829 if (attr_results[l].num == k) {
5830 if (attr != attr_results[l].result_attr ||
5831 open_attrs_table[i] != attr_results[l].init_attr ||
5832 open_attrs_table[j] != attr_results[l].trunc_attr) {
5833 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5834 open_attrs_table[i],
5835 open_attrs_table[j],
5836 (unsigned int)attr,
5837 attr_results[l].result_attr);
5838 correct = False;
5840 break;
5843 k++;
5847 cli_setatr(cli1, fname, 0, 0);
5848 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5850 printf("open attr test %s.\n", correct ? "passed" : "failed");
5852 if (!torture_close_connection(cli1)) {
5853 correct = False;
5855 return correct;
5858 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5859 const char *name, void *state)
5861 int *matched = (int *)state;
5862 if (matched != NULL) {
5863 *matched += 1;
5865 return NT_STATUS_OK;
5869 test directory listing speed
5871 static bool run_dirtest(int dummy)
5873 int i;
5874 static struct cli_state *cli;
5875 uint16_t fnum;
5876 struct timeval core_start;
5877 bool correct = True;
5878 int matched;
5880 printf("starting directory test\n");
5882 if (!torture_open_connection(&cli, 0)) {
5883 return False;
5886 smbXcli_conn_set_sockopt(cli->conn, sockops);
5888 srandom(0);
5889 for (i=0;i<torture_numops;i++) {
5890 fstring fname;
5891 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5892 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5893 fprintf(stderr,"Failed to open %s\n", fname);
5894 return False;
5896 cli_close(cli, fnum);
5899 core_start = timeval_current();
5901 matched = 0;
5902 cli_list(cli, "a*.*", 0, list_fn, &matched);
5903 printf("Matched %d\n", matched);
5905 matched = 0;
5906 cli_list(cli, "b*.*", 0, list_fn, &matched);
5907 printf("Matched %d\n", matched);
5909 matched = 0;
5910 cli_list(cli, "xyzabc", 0, list_fn, &matched);
5911 printf("Matched %d\n", matched);
5913 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5915 srandom(0);
5916 for (i=0;i<torture_numops;i++) {
5917 fstring fname;
5918 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5919 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5922 if (!torture_close_connection(cli)) {
5923 correct = False;
5926 printf("finished dirtest\n");
5928 return correct;
5931 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5932 void *state)
5934 struct cli_state *pcli = (struct cli_state *)state;
5935 fstring fname;
5936 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5938 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5939 return NT_STATUS_OK;
5941 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
5942 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5943 printf("del_fn: failed to rmdir %s\n,", fname );
5944 } else {
5945 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
5946 printf("del_fn: failed to unlink %s\n,", fname );
5948 return NT_STATUS_OK;
5953 sees what IOCTLs are supported
5955 bool torture_ioctl_test(int dummy)
5957 static struct cli_state *cli;
5958 uint16_t device, function;
5959 uint16_t fnum;
5960 const char *fname = "\\ioctl.dat";
5961 DATA_BLOB blob;
5962 NTSTATUS status;
5964 if (!torture_open_connection(&cli, 0)) {
5965 return False;
5968 printf("starting ioctl test\n");
5970 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5972 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5973 if (!NT_STATUS_IS_OK(status)) {
5974 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5975 return False;
5978 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5979 printf("ioctl device info: %s\n", nt_errstr(status));
5981 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5982 printf("ioctl job info: %s\n", nt_errstr(status));
5984 for (device=0;device<0x100;device++) {
5985 printf("ioctl test with device = 0x%x\n", device);
5986 for (function=0;function<0x100;function++) {
5987 uint32 code = (device<<16) | function;
5989 status = cli_raw_ioctl(cli, fnum, code, &blob);
5991 if (NT_STATUS_IS_OK(status)) {
5992 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5993 (int)blob.length);
5994 data_blob_free(&blob);
5999 if (!torture_close_connection(cli)) {
6000 return False;
6003 return True;
6008 tries varients of chkpath
6010 bool torture_chkpath_test(int dummy)
6012 static struct cli_state *cli;
6013 uint16_t fnum;
6014 bool ret;
6015 NTSTATUS status;
6017 if (!torture_open_connection(&cli, 0)) {
6018 return False;
6021 printf("starting chkpath test\n");
6023 /* cleanup from an old run */
6024 cli_rmdir(cli, "\\chkpath.dir\\dir2");
6025 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6026 cli_rmdir(cli, "\\chkpath.dir");
6028 status = cli_mkdir(cli, "\\chkpath.dir");
6029 if (!NT_STATUS_IS_OK(status)) {
6030 printf("mkdir1 failed : %s\n", nt_errstr(status));
6031 return False;
6034 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
6035 if (!NT_STATUS_IS_OK(status)) {
6036 printf("mkdir2 failed : %s\n", nt_errstr(status));
6037 return False;
6040 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
6041 DENY_NONE, &fnum);
6042 if (!NT_STATUS_IS_OK(status)) {
6043 printf("open1 failed (%s)\n", nt_errstr(status));
6044 return False;
6046 cli_close(cli, fnum);
6048 status = cli_chkpath(cli, "\\chkpath.dir");
6049 if (!NT_STATUS_IS_OK(status)) {
6050 printf("chkpath1 failed: %s\n", nt_errstr(status));
6051 ret = False;
6054 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
6055 if (!NT_STATUS_IS_OK(status)) {
6056 printf("chkpath2 failed: %s\n", nt_errstr(status));
6057 ret = False;
6060 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
6061 if (!NT_STATUS_IS_OK(status)) {
6062 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6063 NT_STATUS_NOT_A_DIRECTORY);
6064 } else {
6065 printf("* chkpath on a file should fail\n");
6066 ret = False;
6069 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
6070 if (!NT_STATUS_IS_OK(status)) {
6071 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
6072 NT_STATUS_OBJECT_NAME_NOT_FOUND);
6073 } else {
6074 printf("* chkpath on a non existent file should fail\n");
6075 ret = False;
6078 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
6079 if (!NT_STATUS_IS_OK(status)) {
6080 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6081 NT_STATUS_OBJECT_PATH_NOT_FOUND);
6082 } else {
6083 printf("* chkpath on a non existent component should fail\n");
6084 ret = False;
6087 cli_rmdir(cli, "\\chkpath.dir\\dir2");
6088 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6089 cli_rmdir(cli, "\\chkpath.dir");
6091 if (!torture_close_connection(cli)) {
6092 return False;
6095 return ret;
6098 static bool run_eatest(int dummy)
6100 static struct cli_state *cli;
6101 const char *fname = "\\eatest.txt";
6102 bool correct = True;
6103 uint16_t fnum;
6104 int i;
6105 size_t num_eas;
6106 struct ea_struct *ea_list = NULL;
6107 TALLOC_CTX *mem_ctx = talloc_init("eatest");
6108 NTSTATUS status;
6110 printf("starting eatest\n");
6112 if (!torture_open_connection(&cli, 0)) {
6113 talloc_destroy(mem_ctx);
6114 return False;
6117 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6119 status = cli_ntcreate(cli, fname, 0,
6120 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6121 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
6122 0x4044, 0, &fnum);
6123 if (!NT_STATUS_IS_OK(status)) {
6124 printf("open failed - %s\n", nt_errstr(status));
6125 talloc_destroy(mem_ctx);
6126 return False;
6129 for (i = 0; i < 10; i++) {
6130 fstring ea_name, ea_val;
6132 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
6133 memset(ea_val, (char)i+1, i+1);
6134 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
6135 if (!NT_STATUS_IS_OK(status)) {
6136 printf("ea_set of name %s failed - %s\n", ea_name,
6137 nt_errstr(status));
6138 talloc_destroy(mem_ctx);
6139 return False;
6143 cli_close(cli, fnum);
6144 for (i = 0; i < 10; i++) {
6145 fstring ea_name, ea_val;
6147 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
6148 memset(ea_val, (char)i+1, i+1);
6149 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
6150 if (!NT_STATUS_IS_OK(status)) {
6151 printf("ea_set of name %s failed - %s\n", ea_name,
6152 nt_errstr(status));
6153 talloc_destroy(mem_ctx);
6154 return False;
6158 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6159 if (!NT_STATUS_IS_OK(status)) {
6160 printf("ea_get list failed - %s\n", nt_errstr(status));
6161 correct = False;
6164 printf("num_eas = %d\n", (int)num_eas);
6166 if (num_eas != 20) {
6167 printf("Should be 20 EA's stored... failing.\n");
6168 correct = False;
6171 for (i = 0; i < num_eas; i++) {
6172 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6173 dump_data(0, ea_list[i].value.data,
6174 ea_list[i].value.length);
6177 /* Setting EA's to zero length deletes them. Test this */
6178 printf("Now deleting all EA's - case indepenent....\n");
6180 #if 1
6181 cli_set_ea_path(cli, fname, "", "", 0);
6182 #else
6183 for (i = 0; i < 20; i++) {
6184 fstring ea_name;
6185 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
6186 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
6187 if (!NT_STATUS_IS_OK(status)) {
6188 printf("ea_set of name %s failed - %s\n", ea_name,
6189 nt_errstr(status));
6190 talloc_destroy(mem_ctx);
6191 return False;
6194 #endif
6196 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6197 if (!NT_STATUS_IS_OK(status)) {
6198 printf("ea_get list failed - %s\n", nt_errstr(status));
6199 correct = False;
6202 printf("num_eas = %d\n", (int)num_eas);
6203 for (i = 0; i < num_eas; i++) {
6204 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6205 dump_data(0, ea_list[i].value.data,
6206 ea_list[i].value.length);
6209 if (num_eas != 0) {
6210 printf("deleting EA's failed.\n");
6211 correct = False;
6214 /* Try and delete a non existent EA. */
6215 status = cli_set_ea_path(cli, fname, "foo", "", 0);
6216 if (!NT_STATUS_IS_OK(status)) {
6217 printf("deleting non-existent EA 'foo' should succeed. %s\n",
6218 nt_errstr(status));
6219 correct = False;
6222 talloc_destroy(mem_ctx);
6223 if (!torture_close_connection(cli)) {
6224 correct = False;
6227 return correct;
6230 static bool run_dirtest1(int dummy)
6232 int i;
6233 static struct cli_state *cli;
6234 uint16_t fnum;
6235 int num_seen;
6236 bool correct = True;
6238 printf("starting directory test\n");
6240 if (!torture_open_connection(&cli, 0)) {
6241 return False;
6244 smbXcli_conn_set_sockopt(cli->conn, sockops);
6246 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6247 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6248 cli_rmdir(cli, "\\LISTDIR");
6249 cli_mkdir(cli, "\\LISTDIR");
6251 /* Create 1000 files and 1000 directories. */
6252 for (i=0;i<1000;i++) {
6253 fstring fname;
6254 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6255 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6256 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6257 fprintf(stderr,"Failed to open %s\n", fname);
6258 return False;
6260 cli_close(cli, fnum);
6262 for (i=0;i<1000;i++) {
6263 fstring fname;
6264 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6265 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6266 fprintf(stderr,"Failed to open %s\n", fname);
6267 return False;
6271 /* Now ensure that doing an old list sees both files and directories. */
6272 num_seen = 0;
6273 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6274 printf("num_seen = %d\n", num_seen );
6275 /* We should see 100 files + 1000 directories + . and .. */
6276 if (num_seen != 2002)
6277 correct = False;
6279 /* Ensure if we have the "must have" bits we only see the
6280 * relevent entries.
6282 num_seen = 0;
6283 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6284 printf("num_seen = %d\n", num_seen );
6285 if (num_seen != 1002)
6286 correct = False;
6288 num_seen = 0;
6289 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6290 printf("num_seen = %d\n", num_seen );
6291 if (num_seen != 1000)
6292 correct = False;
6294 /* Delete everything. */
6295 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6296 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6297 cli_rmdir(cli, "\\LISTDIR");
6299 #if 0
6300 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6301 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6302 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6303 #endif
6305 if (!torture_close_connection(cli)) {
6306 correct = False;
6309 printf("finished dirtest1\n");
6311 return correct;
6314 static bool run_error_map_extract(int dummy) {
6316 static struct cli_state *c_dos;
6317 static struct cli_state *c_nt;
6318 NTSTATUS status;
6320 uint32 error;
6322 uint32 errnum;
6323 uint8 errclass;
6325 NTSTATUS nt_status;
6327 fstring user;
6329 /* NT-Error connection */
6331 disable_spnego = true;
6332 if (!(c_nt = open_nbt_connection())) {
6333 disable_spnego = false;
6334 return False;
6336 disable_spnego = false;
6338 status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
6339 PROTOCOL_NT1);
6341 if (!NT_STATUS_IS_OK(status)) {
6342 printf("%s rejected the NT-error negprot (%s)\n", host,
6343 nt_errstr(status));
6344 cli_shutdown(c_nt);
6345 return False;
6348 status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6349 if (!NT_STATUS_IS_OK(status)) {
6350 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6351 return False;
6354 /* DOS-Error connection */
6356 disable_spnego = true;
6357 force_dos_errors = true;
6358 if (!(c_dos = open_nbt_connection())) {
6359 disable_spnego = false;
6360 force_dos_errors = false;
6361 return False;
6363 disable_spnego = false;
6364 force_dos_errors = false;
6366 status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
6367 PROTOCOL_NT1);
6368 if (!NT_STATUS_IS_OK(status)) {
6369 printf("%s rejected the DOS-error negprot (%s)\n", host,
6370 nt_errstr(status));
6371 cli_shutdown(c_dos);
6372 return False;
6375 status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
6376 if (!NT_STATUS_IS_OK(status)) {
6377 printf("%s rejected the DOS-error initial session setup (%s)\n",
6378 host, nt_errstr(status));
6379 return False;
6382 c_nt->map_dos_errors = false;
6383 c_dos->map_dos_errors = false;
6385 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
6386 fstr_sprintf(user, "%X", error);
6388 status = cli_session_setup(c_nt, user,
6389 password, strlen(password),
6390 password, strlen(password),
6391 workgroup);
6392 if (NT_STATUS_IS_OK(status)) {
6393 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6396 /* Case #1: 32-bit NT errors */
6397 if (!NT_STATUS_IS_DOS(status)) {
6398 nt_status = status;
6399 } else {
6400 printf("/** Dos error on NT connection! (%s) */\n",
6401 nt_errstr(status));
6402 nt_status = NT_STATUS(0xc0000000);
6405 status = cli_session_setup(c_dos, user,
6406 password, strlen(password),
6407 password, strlen(password),
6408 workgroup);
6409 if (NT_STATUS_IS_OK(status)) {
6410 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6413 /* Case #1: 32-bit NT errors */
6414 if (NT_STATUS_IS_DOS(status)) {
6415 printf("/** NT error on DOS connection! (%s) */\n",
6416 nt_errstr(status));
6417 errnum = errclass = 0;
6418 } else {
6419 errclass = NT_STATUS_DOS_CLASS(status);
6420 errnum = NT_STATUS_DOS_CODE(status);
6423 if (NT_STATUS_V(nt_status) != error) {
6424 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
6425 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
6426 get_nt_error_c_code(talloc_tos(), nt_status));
6429 printf("\t{%s,\t%s,\t%s},\n",
6430 smb_dos_err_class(errclass),
6431 smb_dos_err_name(errclass, errnum),
6432 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
6434 return True;
6437 static bool run_sesssetup_bench(int dummy)
6439 static struct cli_state *c;
6440 const char *fname = "\\file.dat";
6441 uint16_t fnum;
6442 NTSTATUS status;
6443 int i;
6445 if (!torture_open_connection(&c, 0)) {
6446 return false;
6449 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6450 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6451 FILE_DELETE_ON_CLOSE, 0, &fnum);
6452 if (!NT_STATUS_IS_OK(status)) {
6453 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6454 return false;
6457 for (i=0; i<torture_numops; i++) {
6458 status = cli_session_setup(
6459 c, username,
6460 password, strlen(password),
6461 password, strlen(password),
6462 workgroup);
6463 if (!NT_STATUS_IS_OK(status)) {
6464 d_printf("(%s) cli_session_setup failed: %s\n",
6465 __location__, nt_errstr(status));
6466 return false;
6469 d_printf("\r%d ", (int)cli_state_get_uid(c));
6471 status = cli_ulogoff(c);
6472 if (!NT_STATUS_IS_OK(status)) {
6473 d_printf("(%s) cli_ulogoff failed: %s\n",
6474 __location__, nt_errstr(status));
6475 return false;
6479 return true;
6482 static bool subst_test(const char *str, const char *user, const char *domain,
6483 uid_t uid, gid_t gid, const char *expected)
6485 char *subst;
6486 bool result = true;
6488 subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
6490 if (strcmp(subst, expected) != 0) {
6491 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
6492 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
6493 expected);
6494 result = false;
6497 TALLOC_FREE(subst);
6498 return result;
6501 static void chain1_open_completion(struct tevent_req *req)
6503 uint16_t fnum;
6504 NTSTATUS status;
6505 status = cli_openx_recv(req, &fnum);
6506 TALLOC_FREE(req);
6508 d_printf("cli_openx_recv returned %s: %d\n",
6509 nt_errstr(status),
6510 NT_STATUS_IS_OK(status) ? fnum : -1);
6513 static void chain1_write_completion(struct tevent_req *req)
6515 size_t written;
6516 NTSTATUS status;
6517 status = cli_write_andx_recv(req, &written);
6518 TALLOC_FREE(req);
6520 d_printf("cli_write_andx_recv returned %s: %d\n",
6521 nt_errstr(status),
6522 NT_STATUS_IS_OK(status) ? (int)written : -1);
6525 static void chain1_close_completion(struct tevent_req *req)
6527 NTSTATUS status;
6528 bool *done = (bool *)tevent_req_callback_data_void(req);
6530 status = cli_close_recv(req);
6531 *done = true;
6533 TALLOC_FREE(req);
6535 d_printf("cli_close returned %s\n", nt_errstr(status));
6538 static bool run_chain1(int dummy)
6540 struct cli_state *cli1;
6541 struct event_context *evt = event_context_init(NULL);
6542 struct tevent_req *reqs[3], *smbreqs[3];
6543 bool done = false;
6544 const char *str = "foobar";
6545 NTSTATUS status;
6547 printf("starting chain1 test\n");
6548 if (!torture_open_connection(&cli1, 0)) {
6549 return False;
6552 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6554 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, "\\test",
6555 O_CREAT|O_RDWR, 0, &smbreqs[0]);
6556 if (reqs[0] == NULL) return false;
6557 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
6560 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
6561 (const uint8_t *)str, 0, strlen(str)+1,
6562 smbreqs, 1, &smbreqs[1]);
6563 if (reqs[1] == NULL) return false;
6564 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
6566 reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
6567 if (reqs[2] == NULL) return false;
6568 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
6570 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
6571 if (!NT_STATUS_IS_OK(status)) {
6572 return false;
6575 while (!done) {
6576 tevent_loop_once(evt);
6579 torture_close_connection(cli1);
6580 return True;
6583 static void chain2_sesssetup_completion(struct tevent_req *req)
6585 NTSTATUS status;
6586 status = cli_session_setup_guest_recv(req);
6587 d_printf("sesssetup returned %s\n", nt_errstr(status));
6590 static void chain2_tcon_completion(struct tevent_req *req)
6592 bool *done = (bool *)tevent_req_callback_data_void(req);
6593 NTSTATUS status;
6594 status = cli_tcon_andx_recv(req);
6595 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
6596 *done = true;
6599 static bool run_chain2(int dummy)
6601 struct cli_state *cli1;
6602 struct event_context *evt = event_context_init(NULL);
6603 struct tevent_req *reqs[2], *smbreqs[2];
6604 bool done = false;
6605 NTSTATUS status;
6607 printf("starting chain2 test\n");
6608 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
6609 port_to_use, SMB_SIGNING_DEFAULT, 0);
6610 if (!NT_STATUS_IS_OK(status)) {
6611 return False;
6614 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6616 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
6617 &smbreqs[0]);
6618 if (reqs[0] == NULL) return false;
6619 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
6621 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
6622 "?????", NULL, 0, &smbreqs[1]);
6623 if (reqs[1] == NULL) return false;
6624 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
6626 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
6627 if (!NT_STATUS_IS_OK(status)) {
6628 return false;
6631 while (!done) {
6632 tevent_loop_once(evt);
6635 torture_close_connection(cli1);
6636 return True;
6640 struct torture_createdel_state {
6641 struct tevent_context *ev;
6642 struct cli_state *cli;
6645 static void torture_createdel_created(struct tevent_req *subreq);
6646 static void torture_createdel_closed(struct tevent_req *subreq);
6648 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
6649 struct tevent_context *ev,
6650 struct cli_state *cli,
6651 const char *name)
6653 struct tevent_req *req, *subreq;
6654 struct torture_createdel_state *state;
6656 req = tevent_req_create(mem_ctx, &state,
6657 struct torture_createdel_state);
6658 if (req == NULL) {
6659 return NULL;
6661 state->ev = ev;
6662 state->cli = cli;
6664 subreq = cli_ntcreate_send(
6665 state, ev, cli, name, 0,
6666 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
6667 FILE_ATTRIBUTE_NORMAL,
6668 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6669 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
6671 if (tevent_req_nomem(subreq, req)) {
6672 return tevent_req_post(req, ev);
6674 tevent_req_set_callback(subreq, torture_createdel_created, req);
6675 return req;
6678 static void torture_createdel_created(struct tevent_req *subreq)
6680 struct tevent_req *req = tevent_req_callback_data(
6681 subreq, struct tevent_req);
6682 struct torture_createdel_state *state = tevent_req_data(
6683 req, struct torture_createdel_state);
6684 NTSTATUS status;
6685 uint16_t fnum;
6687 status = cli_ntcreate_recv(subreq, &fnum);
6688 TALLOC_FREE(subreq);
6689 if (!NT_STATUS_IS_OK(status)) {
6690 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
6691 nt_errstr(status)));
6692 tevent_req_nterror(req, status);
6693 return;
6696 subreq = cli_close_send(state, state->ev, state->cli, fnum);
6697 if (tevent_req_nomem(subreq, req)) {
6698 return;
6700 tevent_req_set_callback(subreq, torture_createdel_closed, req);
6703 static void torture_createdel_closed(struct tevent_req *subreq)
6705 struct tevent_req *req = tevent_req_callback_data(
6706 subreq, struct tevent_req);
6707 NTSTATUS status;
6709 status = cli_close_recv(subreq);
6710 if (!NT_STATUS_IS_OK(status)) {
6711 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
6712 tevent_req_nterror(req, status);
6713 return;
6715 tevent_req_done(req);
6718 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
6720 return tevent_req_simple_recv_ntstatus(req);
6723 struct torture_createdels_state {
6724 struct tevent_context *ev;
6725 struct cli_state *cli;
6726 const char *base_name;
6727 int sent;
6728 int received;
6729 int num_files;
6730 struct tevent_req **reqs;
6733 static void torture_createdels_done(struct tevent_req *subreq);
6735 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
6736 struct tevent_context *ev,
6737 struct cli_state *cli,
6738 const char *base_name,
6739 int num_parallel,
6740 int num_files)
6742 struct tevent_req *req;
6743 struct torture_createdels_state *state;
6744 int i;
6746 req = tevent_req_create(mem_ctx, &state,
6747 struct torture_createdels_state);
6748 if (req == NULL) {
6749 return NULL;
6751 state->ev = ev;
6752 state->cli = cli;
6753 state->base_name = talloc_strdup(state, base_name);
6754 if (tevent_req_nomem(state->base_name, req)) {
6755 return tevent_req_post(req, ev);
6757 state->num_files = MAX(num_parallel, num_files);
6758 state->sent = 0;
6759 state->received = 0;
6761 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
6762 if (tevent_req_nomem(state->reqs, req)) {
6763 return tevent_req_post(req, ev);
6766 for (i=0; i<num_parallel; i++) {
6767 char *name;
6769 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6770 state->sent);
6771 if (tevent_req_nomem(name, req)) {
6772 return tevent_req_post(req, ev);
6774 state->reqs[i] = torture_createdel_send(
6775 state->reqs, state->ev, state->cli, name);
6776 if (tevent_req_nomem(state->reqs[i], req)) {
6777 return tevent_req_post(req, ev);
6779 name = talloc_move(state->reqs[i], &name);
6780 tevent_req_set_callback(state->reqs[i],
6781 torture_createdels_done, req);
6782 state->sent += 1;
6784 return req;
6787 static void torture_createdels_done(struct tevent_req *subreq)
6789 struct tevent_req *req = tevent_req_callback_data(
6790 subreq, struct tevent_req);
6791 struct torture_createdels_state *state = tevent_req_data(
6792 req, struct torture_createdels_state);
6793 size_t num_parallel = talloc_array_length(state->reqs);
6794 NTSTATUS status;
6795 char *name;
6796 int i;
6798 status = torture_createdel_recv(subreq);
6799 if (!NT_STATUS_IS_OK(status)){
6800 DEBUG(10, ("torture_createdel_recv returned %s\n",
6801 nt_errstr(status)));
6802 TALLOC_FREE(subreq);
6803 tevent_req_nterror(req, status);
6804 return;
6807 for (i=0; i<num_parallel; i++) {
6808 if (subreq == state->reqs[i]) {
6809 break;
6812 if (i == num_parallel) {
6813 DEBUG(10, ("received something we did not send\n"));
6814 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6815 return;
6817 TALLOC_FREE(state->reqs[i]);
6819 if (state->sent >= state->num_files) {
6820 tevent_req_done(req);
6821 return;
6824 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6825 state->sent);
6826 if (tevent_req_nomem(name, req)) {
6827 return;
6829 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
6830 state->cli, name);
6831 if (tevent_req_nomem(state->reqs[i], req)) {
6832 return;
6834 name = talloc_move(state->reqs[i], &name);
6835 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
6836 state->sent += 1;
6839 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
6841 return tevent_req_simple_recv_ntstatus(req);
6844 struct swallow_notify_state {
6845 struct tevent_context *ev;
6846 struct cli_state *cli;
6847 uint16_t fnum;
6848 uint32_t completion_filter;
6849 bool recursive;
6850 bool (*fn)(uint32_t action, const char *name, void *priv);
6851 void *priv;
6854 static void swallow_notify_done(struct tevent_req *subreq);
6856 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
6857 struct tevent_context *ev,
6858 struct cli_state *cli,
6859 uint16_t fnum,
6860 uint32_t completion_filter,
6861 bool recursive,
6862 bool (*fn)(uint32_t action,
6863 const char *name,
6864 void *priv),
6865 void *priv)
6867 struct tevent_req *req, *subreq;
6868 struct swallow_notify_state *state;
6870 req = tevent_req_create(mem_ctx, &state,
6871 struct swallow_notify_state);
6872 if (req == NULL) {
6873 return NULL;
6875 state->ev = ev;
6876 state->cli = cli;
6877 state->fnum = fnum;
6878 state->completion_filter = completion_filter;
6879 state->recursive = recursive;
6880 state->fn = fn;
6881 state->priv = priv;
6883 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6884 0xffff, state->completion_filter,
6885 state->recursive);
6886 if (tevent_req_nomem(subreq, req)) {
6887 return tevent_req_post(req, ev);
6889 tevent_req_set_callback(subreq, swallow_notify_done, req);
6890 return req;
6893 static void swallow_notify_done(struct tevent_req *subreq)
6895 struct tevent_req *req = tevent_req_callback_data(
6896 subreq, struct tevent_req);
6897 struct swallow_notify_state *state = tevent_req_data(
6898 req, struct swallow_notify_state);
6899 NTSTATUS status;
6900 uint32_t i, num_changes;
6901 struct notify_change *changes;
6903 status = cli_notify_recv(subreq, state, &num_changes, &changes);
6904 TALLOC_FREE(subreq);
6905 if (!NT_STATUS_IS_OK(status)) {
6906 DEBUG(10, ("cli_notify_recv returned %s\n",
6907 nt_errstr(status)));
6908 tevent_req_nterror(req, status);
6909 return;
6912 for (i=0; i<num_changes; i++) {
6913 state->fn(changes[i].action, changes[i].name, state->priv);
6915 TALLOC_FREE(changes);
6917 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6918 0xffff, state->completion_filter,
6919 state->recursive);
6920 if (tevent_req_nomem(subreq, req)) {
6921 return;
6923 tevent_req_set_callback(subreq, swallow_notify_done, req);
6926 static bool print_notifies(uint32_t action, const char *name, void *priv)
6928 if (DEBUGLEVEL > 5) {
6929 d_printf("%d %s\n", (int)action, name);
6931 return true;
6934 static void notify_bench_done(struct tevent_req *req)
6936 int *num_finished = (int *)tevent_req_callback_data_void(req);
6937 *num_finished += 1;
6940 static bool run_notify_bench(int dummy)
6942 const char *dname = "\\notify-bench";
6943 struct tevent_context *ev;
6944 NTSTATUS status;
6945 uint16_t dnum;
6946 struct tevent_req *req1;
6947 struct tevent_req *req2 = NULL;
6948 int i, num_unc_names;
6949 int num_finished = 0;
6951 printf("starting notify-bench test\n");
6953 if (use_multishare_conn) {
6954 char **unc_list;
6955 unc_list = file_lines_load(multishare_conn_fname,
6956 &num_unc_names, 0, NULL);
6957 if (!unc_list || num_unc_names <= 0) {
6958 d_printf("Failed to load unc names list from '%s'\n",
6959 multishare_conn_fname);
6960 return false;
6962 TALLOC_FREE(unc_list);
6963 } else {
6964 num_unc_names = 1;
6967 ev = tevent_context_init(talloc_tos());
6968 if (ev == NULL) {
6969 d_printf("tevent_context_init failed\n");
6970 return false;
6973 for (i=0; i<num_unc_names; i++) {
6974 struct cli_state *cli;
6975 char *base_fname;
6977 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
6978 dname, i);
6979 if (base_fname == NULL) {
6980 return false;
6983 if (!torture_open_connection(&cli, i)) {
6984 return false;
6987 status = cli_ntcreate(cli, dname, 0,
6988 MAXIMUM_ALLOWED_ACCESS,
6989 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
6990 FILE_SHARE_DELETE,
6991 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
6992 &dnum);
6994 if (!NT_STATUS_IS_OK(status)) {
6995 d_printf("Could not create %s: %s\n", dname,
6996 nt_errstr(status));
6997 return false;
7000 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
7001 FILE_NOTIFY_CHANGE_FILE_NAME |
7002 FILE_NOTIFY_CHANGE_DIR_NAME |
7003 FILE_NOTIFY_CHANGE_ATTRIBUTES |
7004 FILE_NOTIFY_CHANGE_LAST_WRITE,
7005 false, print_notifies, NULL);
7006 if (req1 == NULL) {
7007 d_printf("Could not create notify request\n");
7008 return false;
7011 req2 = torture_createdels_send(talloc_tos(), ev, cli,
7012 base_fname, 10, torture_numops);
7013 if (req2 == NULL) {
7014 d_printf("Could not create createdels request\n");
7015 return false;
7017 TALLOC_FREE(base_fname);
7019 tevent_req_set_callback(req2, notify_bench_done,
7020 &num_finished);
7023 while (num_finished < num_unc_names) {
7024 int ret;
7025 ret = tevent_loop_once(ev);
7026 if (ret != 0) {
7027 d_printf("tevent_loop_once failed\n");
7028 return false;
7032 if (!tevent_req_poll(req2, ev)) {
7033 d_printf("tevent_req_poll failed\n");
7036 status = torture_createdels_recv(req2);
7037 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
7039 return true;
7042 static bool run_mangle1(int dummy)
7044 struct cli_state *cli;
7045 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
7046 uint16_t fnum;
7047 fstring alt_name;
7048 NTSTATUS status;
7049 time_t change_time, access_time, write_time;
7050 off_t size;
7051 uint16_t mode;
7053 printf("starting mangle1 test\n");
7054 if (!torture_open_connection(&cli, 0)) {
7055 return False;
7058 smbXcli_conn_set_sockopt(cli->conn, sockops);
7060 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7061 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7062 0, 0, &fnum);
7063 if (!NT_STATUS_IS_OK(status)) {
7064 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7065 return false;
7067 cli_close(cli, fnum);
7069 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
7070 if (!NT_STATUS_IS_OK(status)) {
7071 d_printf("cli_qpathinfo_alt_name failed: %s\n",
7072 nt_errstr(status));
7073 return false;
7075 d_printf("alt_name: %s\n", alt_name);
7077 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
7078 if (!NT_STATUS_IS_OK(status)) {
7079 d_printf("cli_openx(%s) failed: %s\n", alt_name,
7080 nt_errstr(status));
7081 return false;
7083 cli_close(cli, fnum);
7085 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
7086 &write_time, &size, &mode);
7087 if (!NT_STATUS_IS_OK(status)) {
7088 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
7089 nt_errstr(status));
7090 return false;
7093 return true;
7096 static size_t null_source(uint8_t *buf, size_t n, void *priv)
7098 size_t *to_pull = (size_t *)priv;
7099 size_t thistime = *to_pull;
7101 thistime = MIN(thistime, n);
7102 if (thistime == 0) {
7103 return 0;
7106 memset(buf, 0, thistime);
7107 *to_pull -= thistime;
7108 return thistime;
7111 static bool run_windows_write(int dummy)
7113 struct cli_state *cli1;
7114 uint16_t fnum;
7115 int i;
7116 bool ret = false;
7117 const char *fname = "\\writetest.txt";
7118 struct timeval start_time;
7119 double seconds;
7120 double kbytes;
7121 NTSTATUS status;
7123 printf("starting windows_write test\n");
7124 if (!torture_open_connection(&cli1, 0)) {
7125 return False;
7128 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7129 if (!NT_STATUS_IS_OK(status)) {
7130 printf("open failed (%s)\n", nt_errstr(status));
7131 return False;
7134 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7136 start_time = timeval_current();
7138 for (i=0; i<torture_numops; i++) {
7139 uint8_t c = 0;
7140 off_t start = i * torture_blocksize;
7141 size_t to_pull = torture_blocksize - 1;
7143 status = cli_writeall(cli1, fnum, 0, &c,
7144 start + torture_blocksize - 1, 1, NULL);
7145 if (!NT_STATUS_IS_OK(status)) {
7146 printf("cli_write failed: %s\n", nt_errstr(status));
7147 goto fail;
7150 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
7151 null_source, &to_pull);
7152 if (!NT_STATUS_IS_OK(status)) {
7153 printf("cli_push returned: %s\n", nt_errstr(status));
7154 goto fail;
7158 seconds = timeval_elapsed(&start_time);
7159 kbytes = (double)torture_blocksize * torture_numops;
7160 kbytes /= 1024;
7162 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
7163 (double)seconds, (int)(kbytes/seconds));
7165 ret = true;
7166 fail:
7167 cli_close(cli1, fnum);
7168 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7169 torture_close_connection(cli1);
7170 return ret;
7173 static bool run_cli_echo(int dummy)
7175 struct cli_state *cli;
7176 NTSTATUS status;
7178 printf("starting cli_echo test\n");
7179 if (!torture_open_connection(&cli, 0)) {
7180 return false;
7182 smbXcli_conn_set_sockopt(cli->conn, sockops);
7184 status = cli_echo(cli, 5, data_blob_const("hello", 5));
7186 d_printf("cli_echo returned %s\n", nt_errstr(status));
7188 torture_close_connection(cli);
7189 return NT_STATUS_IS_OK(status);
7192 static bool run_uid_regression_test(int dummy)
7194 static struct cli_state *cli;
7195 int16_t old_vuid;
7196 int16_t old_cnum;
7197 bool correct = True;
7198 NTSTATUS status;
7200 printf("starting uid regression test\n");
7202 if (!torture_open_connection(&cli, 0)) {
7203 return False;
7206 smbXcli_conn_set_sockopt(cli->conn, sockops);
7208 /* Ok - now save then logoff our current user. */
7209 old_vuid = cli_state_get_uid(cli);
7211 status = cli_ulogoff(cli);
7212 if (!NT_STATUS_IS_OK(status)) {
7213 d_printf("(%s) cli_ulogoff failed: %s\n",
7214 __location__, nt_errstr(status));
7215 correct = false;
7216 goto out;
7219 cli_state_set_uid(cli, old_vuid);
7221 /* Try an operation. */
7222 status = cli_mkdir(cli, "\\uid_reg_test");
7223 if (NT_STATUS_IS_OK(status)) {
7224 d_printf("(%s) cli_mkdir succeeded\n",
7225 __location__);
7226 correct = false;
7227 goto out;
7228 } else {
7229 /* Should be bad uid. */
7230 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
7231 NT_STATUS_USER_SESSION_DELETED)) {
7232 correct = false;
7233 goto out;
7237 old_cnum = cli_state_get_tid(cli);
7239 /* Now try a SMBtdis with the invald vuid set to zero. */
7240 cli_state_set_uid(cli, 0);
7242 /* This should succeed. */
7243 status = cli_tdis(cli);
7245 if (NT_STATUS_IS_OK(status)) {
7246 d_printf("First tdis with invalid vuid should succeed.\n");
7247 } else {
7248 d_printf("First tdis failed (%s)\n", nt_errstr(status));
7249 correct = false;
7250 goto out;
7253 cli_state_set_uid(cli, old_vuid);
7254 cli_state_set_tid(cli, old_cnum);
7256 /* This should fail. */
7257 status = cli_tdis(cli);
7258 if (NT_STATUS_IS_OK(status)) {
7259 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
7260 correct = false;
7261 goto out;
7262 } else {
7263 /* Should be bad tid. */
7264 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
7265 NT_STATUS_NETWORK_NAME_DELETED)) {
7266 correct = false;
7267 goto out;
7271 cli_rmdir(cli, "\\uid_reg_test");
7273 out:
7275 cli_shutdown(cli);
7276 return correct;
7280 static const char *illegal_chars = "*\\/?<>|\":";
7281 static char force_shortname_chars[] = " +,.[];=\177";
7283 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
7284 const char *mask, void *state)
7286 struct cli_state *pcli = (struct cli_state *)state;
7287 fstring fname;
7288 NTSTATUS status = NT_STATUS_OK;
7290 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
7292 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7293 return NT_STATUS_OK;
7295 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7296 status = cli_rmdir(pcli, fname);
7297 if (!NT_STATUS_IS_OK(status)) {
7298 printf("del_fn: failed to rmdir %s\n,", fname );
7300 } else {
7301 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7302 if (!NT_STATUS_IS_OK(status)) {
7303 printf("del_fn: failed to unlink %s\n,", fname );
7306 return status;
7309 struct sn_state {
7310 int matched;
7311 int i;
7312 bool val;
7315 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
7316 const char *name, void *state)
7318 struct sn_state *s = (struct sn_state *)state;
7319 int i = s->i;
7321 #if 0
7322 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
7323 i, finfo->name, finfo->short_name);
7324 #endif
7326 if (strchr(force_shortname_chars, i)) {
7327 if (!finfo->short_name) {
7328 /* Shortname not created when it should be. */
7329 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
7330 __location__, finfo->name, i);
7331 s->val = true;
7333 } else if (finfo->short_name){
7334 /* Shortname created when it should not be. */
7335 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
7336 __location__, finfo->short_name, finfo->name);
7337 s->val = true;
7339 s->matched += 1;
7340 return NT_STATUS_OK;
7343 static bool run_shortname_test(int dummy)
7345 static struct cli_state *cli;
7346 bool correct = True;
7347 int i;
7348 struct sn_state s;
7349 char fname[40];
7350 NTSTATUS status;
7352 printf("starting shortname test\n");
7354 if (!torture_open_connection(&cli, 0)) {
7355 return False;
7358 smbXcli_conn_set_sockopt(cli->conn, sockops);
7360 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7361 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7362 cli_rmdir(cli, "\\shortname");
7364 status = cli_mkdir(cli, "\\shortname");
7365 if (!NT_STATUS_IS_OK(status)) {
7366 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
7367 __location__, nt_errstr(status));
7368 correct = false;
7369 goto out;
7372 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
7373 correct = false;
7374 goto out;
7376 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
7377 correct = false;
7378 goto out;
7381 s.val = false;
7383 for (i = 32; i < 128; i++) {
7384 uint16_t fnum = (uint16_t)-1;
7386 s.i = i;
7388 if (strchr(illegal_chars, i)) {
7389 continue;
7391 fname[15] = i;
7393 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
7394 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
7395 if (!NT_STATUS_IS_OK(status)) {
7396 d_printf("(%s) cli_nt_create of %s failed: %s\n",
7397 __location__, fname, nt_errstr(status));
7398 correct = false;
7399 goto out;
7401 cli_close(cli, fnum);
7403 s.matched = 0;
7404 status = cli_list(cli, "\\shortname\\test*.*", 0,
7405 shortname_list_fn, &s);
7406 if (s.matched != 1) {
7407 d_printf("(%s) failed to list %s: %s\n",
7408 __location__, fname, nt_errstr(status));
7409 correct = false;
7410 goto out;
7413 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7414 if (!NT_STATUS_IS_OK(status)) {
7415 d_printf("(%s) failed to delete %s: %s\n",
7416 __location__, fname, nt_errstr(status));
7417 correct = false;
7418 goto out;
7421 if (s.val) {
7422 correct = false;
7423 goto out;
7427 out:
7429 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7430 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7431 cli_rmdir(cli, "\\shortname");
7432 torture_close_connection(cli);
7433 return correct;
7436 static void pagedsearch_cb(struct tevent_req *req)
7438 int rc;
7439 struct tldap_message *msg;
7440 char *dn;
7442 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
7443 if (rc != TLDAP_SUCCESS) {
7444 d_printf("tldap_search_paged_recv failed: %s\n",
7445 tldap_err2string(rc));
7446 return;
7448 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
7449 TALLOC_FREE(msg);
7450 return;
7452 if (!tldap_entry_dn(msg, &dn)) {
7453 d_printf("tldap_entry_dn failed\n");
7454 return;
7456 d_printf("%s\n", dn);
7457 TALLOC_FREE(msg);
7460 static bool run_tldap(int dummy)
7462 struct tldap_context *ld;
7463 int fd, rc;
7464 NTSTATUS status;
7465 struct sockaddr_storage addr;
7466 struct tevent_context *ev;
7467 struct tevent_req *req;
7468 char *basedn;
7469 const char *filter;
7471 if (!resolve_name(host, &addr, 0, false)) {
7472 d_printf("could not find host %s\n", host);
7473 return false;
7475 status = open_socket_out(&addr, 389, 9999, &fd);
7476 if (!NT_STATUS_IS_OK(status)) {
7477 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
7478 return false;
7481 ld = tldap_context_create(talloc_tos(), fd);
7482 if (ld == NULL) {
7483 close(fd);
7484 d_printf("tldap_context_create failed\n");
7485 return false;
7488 rc = tldap_fetch_rootdse(ld);
7489 if (rc != TLDAP_SUCCESS) {
7490 d_printf("tldap_fetch_rootdse failed: %s\n",
7491 tldap_errstr(talloc_tos(), ld, rc));
7492 return false;
7495 basedn = tldap_talloc_single_attribute(
7496 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
7497 if (basedn == NULL) {
7498 d_printf("no defaultNamingContext\n");
7499 return false;
7501 d_printf("defaultNamingContext: %s\n", basedn);
7503 ev = tevent_context_init(talloc_tos());
7504 if (ev == NULL) {
7505 d_printf("tevent_context_init failed\n");
7506 return false;
7509 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
7510 TLDAP_SCOPE_SUB, "(objectclass=*)",
7511 NULL, 0, 0,
7512 NULL, 0, NULL, 0, 0, 0, 0, 5);
7513 if (req == NULL) {
7514 d_printf("tldap_search_paged_send failed\n");
7515 return false;
7517 tevent_req_set_callback(req, pagedsearch_cb, NULL);
7519 tevent_req_poll(req, ev);
7521 TALLOC_FREE(req);
7523 /* test search filters against rootDSE */
7524 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
7525 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
7527 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
7528 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
7529 talloc_tos(), NULL, NULL);
7530 if (rc != TLDAP_SUCCESS) {
7531 d_printf("tldap_search with complex filter failed: %s\n",
7532 tldap_errstr(talloc_tos(), ld, rc));
7533 return false;
7536 TALLOC_FREE(ld);
7537 return true;
7540 /* Torture test to ensure no regression of :
7541 https://bugzilla.samba.org/show_bug.cgi?id=7084
7544 static bool run_dir_createtime(int dummy)
7546 struct cli_state *cli;
7547 const char *dname = "\\testdir";
7548 const char *fname = "\\testdir\\testfile";
7549 NTSTATUS status;
7550 struct timespec create_time;
7551 struct timespec create_time1;
7552 uint16_t fnum;
7553 bool ret = false;
7555 if (!torture_open_connection(&cli, 0)) {
7556 return false;
7559 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7560 cli_rmdir(cli, dname);
7562 status = cli_mkdir(cli, dname);
7563 if (!NT_STATUS_IS_OK(status)) {
7564 printf("mkdir failed: %s\n", nt_errstr(status));
7565 goto out;
7568 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
7569 NULL, NULL, NULL);
7570 if (!NT_STATUS_IS_OK(status)) {
7571 printf("cli_qpathinfo2 returned %s\n",
7572 nt_errstr(status));
7573 goto out;
7576 /* Sleep 3 seconds, then create a file. */
7577 sleep(3);
7579 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
7580 DENY_NONE, &fnum);
7581 if (!NT_STATUS_IS_OK(status)) {
7582 printf("cli_openx failed: %s\n", nt_errstr(status));
7583 goto out;
7586 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
7587 NULL, NULL, NULL);
7588 if (!NT_STATUS_IS_OK(status)) {
7589 printf("cli_qpathinfo2 (2) returned %s\n",
7590 nt_errstr(status));
7591 goto out;
7594 if (timespec_compare(&create_time1, &create_time)) {
7595 printf("run_dir_createtime: create time was updated (error)\n");
7596 } else {
7597 printf("run_dir_createtime: create time was not updated (correct)\n");
7598 ret = true;
7601 out:
7603 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7604 cli_rmdir(cli, dname);
7605 if (!torture_close_connection(cli)) {
7606 ret = false;
7608 return ret;
7612 static bool run_streamerror(int dummy)
7614 struct cli_state *cli;
7615 const char *dname = "\\testdir";
7616 const char *streamname =
7617 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
7618 NTSTATUS status;
7619 time_t change_time, access_time, write_time;
7620 off_t size;
7621 uint16_t mode, fnum;
7622 bool ret = true;
7624 if (!torture_open_connection(&cli, 0)) {
7625 return false;
7628 cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7629 cli_rmdir(cli, dname);
7631 status = cli_mkdir(cli, dname);
7632 if (!NT_STATUS_IS_OK(status)) {
7633 printf("mkdir failed: %s\n", nt_errstr(status));
7634 return false;
7637 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
7638 &write_time, &size, &mode);
7639 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7640 printf("pathinfo returned %s, expected "
7641 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7642 nt_errstr(status));
7643 ret = false;
7646 status = cli_ntcreate(cli, streamname, 0x16,
7647 FILE_READ_DATA|FILE_READ_EA|
7648 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
7649 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7650 FILE_OPEN, 0, 0, &fnum);
7652 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7653 printf("ntcreate returned %s, expected "
7654 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7655 nt_errstr(status));
7656 ret = false;
7660 cli_rmdir(cli, dname);
7661 return ret;
7664 static bool run_local_substitute(int dummy)
7666 bool ok = true;
7668 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
7669 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
7670 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
7671 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
7672 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
7673 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
7674 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
7675 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
7677 /* Different captialization rules in sub_basic... */
7679 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
7680 "blaDOM") == 0);
7682 return ok;
7685 static bool run_local_base64(int dummy)
7687 int i;
7688 bool ret = true;
7690 for (i=1; i<2000; i++) {
7691 DATA_BLOB blob1, blob2;
7692 char *b64;
7694 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
7695 blob1.length = i;
7696 generate_random_buffer(blob1.data, blob1.length);
7698 b64 = base64_encode_data_blob(talloc_tos(), blob1);
7699 if (b64 == NULL) {
7700 d_fprintf(stderr, "base64_encode_data_blob failed "
7701 "for %d bytes\n", i);
7702 ret = false;
7704 blob2 = base64_decode_data_blob(b64);
7705 TALLOC_FREE(b64);
7707 if (data_blob_cmp(&blob1, &blob2)) {
7708 d_fprintf(stderr, "data_blob_cmp failed for %d "
7709 "bytes\n", i);
7710 ret = false;
7712 TALLOC_FREE(blob1.data);
7713 data_blob_free(&blob2);
7715 return ret;
7718 static bool run_local_gencache(int dummy)
7720 char *val;
7721 time_t tm;
7722 DATA_BLOB blob;
7724 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
7725 d_printf("%s: gencache_set() failed\n", __location__);
7726 return False;
7729 if (!gencache_get("foo", NULL, NULL)) {
7730 d_printf("%s: gencache_get() failed\n", __location__);
7731 return False;
7734 if (!gencache_get("foo", &val, &tm)) {
7735 d_printf("%s: gencache_get() failed\n", __location__);
7736 return False;
7739 if (strcmp(val, "bar") != 0) {
7740 d_printf("%s: gencache_get() returned %s, expected %s\n",
7741 __location__, val, "bar");
7742 SAFE_FREE(val);
7743 return False;
7746 SAFE_FREE(val);
7748 if (!gencache_del("foo")) {
7749 d_printf("%s: gencache_del() failed\n", __location__);
7750 return False;
7752 if (gencache_del("foo")) {
7753 d_printf("%s: second gencache_del() succeeded\n",
7754 __location__);
7755 return False;
7758 if (gencache_get("foo", &val, &tm)) {
7759 d_printf("%s: gencache_get() on deleted entry "
7760 "succeeded\n", __location__);
7761 return False;
7764 blob = data_blob_string_const_null("bar");
7765 tm = time(NULL) + 60;
7767 if (!gencache_set_data_blob("foo", &blob, tm)) {
7768 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
7769 return False;
7772 if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7773 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
7774 return False;
7777 if (strcmp((const char *)blob.data, "bar") != 0) {
7778 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
7779 __location__, (const char *)blob.data, "bar");
7780 data_blob_free(&blob);
7781 return False;
7784 data_blob_free(&blob);
7786 if (!gencache_del("foo")) {
7787 d_printf("%s: gencache_del() failed\n", __location__);
7788 return False;
7790 if (gencache_del("foo")) {
7791 d_printf("%s: second gencache_del() succeeded\n",
7792 __location__);
7793 return False;
7796 if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7797 d_printf("%s: gencache_get_data_blob() on deleted entry "
7798 "succeeded\n", __location__);
7799 return False;
7802 return True;
7805 static bool rbt_testval(struct db_context *db, const char *key,
7806 const char *value)
7808 struct db_record *rec;
7809 TDB_DATA data = string_tdb_data(value);
7810 bool ret = false;
7811 NTSTATUS status;
7812 TDB_DATA dbvalue;
7814 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
7815 if (rec == NULL) {
7816 d_fprintf(stderr, "fetch_locked failed\n");
7817 goto done;
7819 status = dbwrap_record_store(rec, data, 0);
7820 if (!NT_STATUS_IS_OK(status)) {
7821 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
7822 goto done;
7824 TALLOC_FREE(rec);
7826 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
7827 if (rec == NULL) {
7828 d_fprintf(stderr, "second fetch_locked failed\n");
7829 goto done;
7832 dbvalue = dbwrap_record_get_value(rec);
7833 if ((dbvalue.dsize != data.dsize)
7834 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
7835 d_fprintf(stderr, "Got wrong data back\n");
7836 goto done;
7839 ret = true;
7840 done:
7841 TALLOC_FREE(rec);
7842 return ret;
7845 static bool run_local_rbtree(int dummy)
7847 struct db_context *db;
7848 bool ret = false;
7849 int i;
7851 db = db_open_rbt(NULL);
7853 if (db == NULL) {
7854 d_fprintf(stderr, "db_open_rbt failed\n");
7855 return false;
7858 for (i=0; i<1000; i++) {
7859 char *key, *value;
7861 if (asprintf(&key, "key%ld", random()) == -1) {
7862 goto done;
7864 if (asprintf(&value, "value%ld", random()) == -1) {
7865 SAFE_FREE(key);
7866 goto done;
7869 if (!rbt_testval(db, key, value)) {
7870 SAFE_FREE(key);
7871 SAFE_FREE(value);
7872 goto done;
7875 SAFE_FREE(value);
7876 if (asprintf(&value, "value%ld", random()) == -1) {
7877 SAFE_FREE(key);
7878 goto done;
7881 if (!rbt_testval(db, key, value)) {
7882 SAFE_FREE(key);
7883 SAFE_FREE(value);
7884 goto done;
7887 SAFE_FREE(key);
7888 SAFE_FREE(value);
7891 ret = true;
7893 done:
7894 TALLOC_FREE(db);
7895 return ret;
7900 local test for character set functions
7902 This is a very simple test for the functionality in convert_string_error()
7904 static bool run_local_convert_string(int dummy)
7906 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
7907 const char *test_strings[2] = { "March", "M\303\244rz" };
7908 char dst[7];
7909 int i;
7911 for (i=0; i<2; i++) {
7912 const char *str = test_strings[i];
7913 int len = strlen(str);
7914 size_t converted_size;
7915 bool ret;
7917 memset(dst, 'X', sizeof(dst));
7919 /* first try with real source length */
7920 ret = convert_string_error(CH_UNIX, CH_UTF8,
7921 str, len,
7922 dst, sizeof(dst),
7923 &converted_size);
7924 if (ret != true) {
7925 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7926 goto failed;
7929 if (converted_size != len) {
7930 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7931 str, len, (int)converted_size);
7932 goto failed;
7935 if (strncmp(str, dst, converted_size) != 0) {
7936 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7937 goto failed;
7940 if (strlen(str) != converted_size) {
7941 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7942 (int)strlen(str), (int)converted_size);
7943 goto failed;
7946 if (dst[converted_size] != 'X') {
7947 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7948 goto failed;
7951 /* now with srclen==-1, this causes the nul to be
7952 * converted too */
7953 ret = convert_string_error(CH_UNIX, CH_UTF8,
7954 str, -1,
7955 dst, sizeof(dst),
7956 &converted_size);
7957 if (ret != true) {
7958 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7959 goto failed;
7962 if (converted_size != len+1) {
7963 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7964 str, len, (int)converted_size);
7965 goto failed;
7968 if (strncmp(str, dst, converted_size) != 0) {
7969 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7970 goto failed;
7973 if (len+1 != converted_size) {
7974 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7975 len+1, (int)converted_size);
7976 goto failed;
7979 if (dst[converted_size] != 'X') {
7980 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7981 goto failed;
7987 TALLOC_FREE(tmp_ctx);
7988 return true;
7989 failed:
7990 TALLOC_FREE(tmp_ctx);
7991 return false;
7995 struct talloc_dict_test {
7996 int content;
7999 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
8001 int *count = (int *)priv;
8002 *count += 1;
8003 return 0;
8006 static bool run_local_talloc_dict(int dummy)
8008 struct talloc_dict *dict;
8009 struct talloc_dict_test *t;
8010 int key, count, res;
8011 bool ok;
8013 dict = talloc_dict_init(talloc_tos());
8014 if (dict == NULL) {
8015 return false;
8018 t = talloc(talloc_tos(), struct talloc_dict_test);
8019 if (t == NULL) {
8020 return false;
8023 key = 1;
8024 t->content = 1;
8025 ok = talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), &t);
8026 if (!ok) {
8027 return false;
8030 count = 0;
8031 res = talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count);
8032 if (res == -1) {
8033 return false;
8036 if (count != 1) {
8037 return false;
8040 if (count != res) {
8041 return false;
8044 TALLOC_FREE(dict);
8046 return true;
8049 static bool run_local_string_to_sid(int dummy) {
8050 struct dom_sid sid;
8052 if (string_to_sid(&sid, "S--1-5-32-545")) {
8053 printf("allowing S--1-5-32-545\n");
8054 return false;
8056 if (string_to_sid(&sid, "S-1-5-32-+545")) {
8057 printf("allowing S-1-5-32-+545\n");
8058 return false;
8060 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")) {
8061 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
8062 return false;
8064 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
8065 printf("allowing S-1-5-32-545-abc\n");
8066 return false;
8068 if (!string_to_sid(&sid, "S-1-5-32-545")) {
8069 printf("could not parse S-1-5-32-545\n");
8070 return false;
8072 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
8073 printf("mis-parsed S-1-5-32-545 as %s\n",
8074 sid_string_tos(&sid));
8075 return false;
8077 return true;
8080 static bool run_local_binary_to_sid(int dummy) {
8081 struct dom_sid *sid = talloc(NULL, struct dom_sid);
8082 static const char good_binary_sid[] = {
8083 0x1, /* revision number */
8084 15, /* num auths */
8085 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8086 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8087 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8088 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8089 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8090 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8091 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8092 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8093 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8094 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8095 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8096 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8097 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8098 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8099 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8100 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8103 static const char long_binary_sid[] = {
8104 0x1, /* revision number */
8105 15, /* num auths */
8106 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8107 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8108 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8109 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8110 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8111 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8112 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8113 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8114 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8115 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8116 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8117 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8118 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8119 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8120 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8121 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8122 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8123 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8124 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8127 static const char long_binary_sid2[] = {
8128 0x1, /* revision number */
8129 32, /* num auths */
8130 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8131 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8132 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8133 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8134 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8135 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8136 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8137 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8138 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8139 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8140 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8141 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8142 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8143 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8144 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8145 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8146 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8147 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8148 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8149 0x1, 0x1, 0x1, 0x1, /* auth[18] */
8150 0x1, 0x1, 0x1, 0x1, /* auth[19] */
8151 0x1, 0x1, 0x1, 0x1, /* auth[20] */
8152 0x1, 0x1, 0x1, 0x1, /* auth[21] */
8153 0x1, 0x1, 0x1, 0x1, /* auth[22] */
8154 0x1, 0x1, 0x1, 0x1, /* auth[23] */
8155 0x1, 0x1, 0x1, 0x1, /* auth[24] */
8156 0x1, 0x1, 0x1, 0x1, /* auth[25] */
8157 0x1, 0x1, 0x1, 0x1, /* auth[26] */
8158 0x1, 0x1, 0x1, 0x1, /* auth[27] */
8159 0x1, 0x1, 0x1, 0x1, /* auth[28] */
8160 0x1, 0x1, 0x1, 0x1, /* auth[29] */
8161 0x1, 0x1, 0x1, 0x1, /* auth[30] */
8162 0x1, 0x1, 0x1, 0x1, /* auth[31] */
8165 if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
8166 return false;
8168 if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
8169 return false;
8171 if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
8172 return false;
8174 return true;
8177 /* Split a path name into filename and stream name components. Canonicalise
8178 * such that an implicit $DATA token is always explicit.
8180 * The "specification" of this function can be found in the
8181 * run_local_stream_name() function in torture.c, I've tried those
8182 * combinations against a W2k3 server.
8185 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
8186 char **pbase, char **pstream)
8188 char *base = NULL;
8189 char *stream = NULL;
8190 char *sname; /* stream name */
8191 const char *stype; /* stream type */
8193 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
8195 sname = strchr_m(fname, ':');
8197 if (lp_posix_pathnames() || (sname == NULL)) {
8198 if (pbase != NULL) {
8199 base = talloc_strdup(mem_ctx, fname);
8200 NT_STATUS_HAVE_NO_MEMORY(base);
8202 goto done;
8205 if (pbase != NULL) {
8206 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
8207 NT_STATUS_HAVE_NO_MEMORY(base);
8210 sname += 1;
8212 stype = strchr_m(sname, ':');
8214 if (stype == NULL) {
8215 sname = talloc_strdup(mem_ctx, sname);
8216 stype = "$DATA";
8218 else {
8219 if (strcasecmp_m(stype, ":$DATA") != 0) {
8221 * If there is an explicit stream type, so far we only
8222 * allow $DATA. Is there anything else allowed? -- vl
8224 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
8225 TALLOC_FREE(base);
8226 return NT_STATUS_OBJECT_NAME_INVALID;
8228 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
8229 stype += 1;
8232 if (sname == NULL) {
8233 TALLOC_FREE(base);
8234 return NT_STATUS_NO_MEMORY;
8237 if (sname[0] == '\0') {
8239 * no stream name, so no stream
8241 goto done;
8244 if (pstream != NULL) {
8245 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
8246 if (stream == NULL) {
8247 TALLOC_FREE(sname);
8248 TALLOC_FREE(base);
8249 return NT_STATUS_NO_MEMORY;
8252 * upper-case the type field
8254 strupper_m(strchr_m(stream, ':')+1);
8257 done:
8258 if (pbase != NULL) {
8259 *pbase = base;
8261 if (pstream != NULL) {
8262 *pstream = stream;
8264 return NT_STATUS_OK;
8267 static bool test_stream_name(const char *fname, const char *expected_base,
8268 const char *expected_stream,
8269 NTSTATUS expected_status)
8271 NTSTATUS status;
8272 char *base = NULL;
8273 char *stream = NULL;
8275 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
8276 if (!NT_STATUS_EQUAL(status, expected_status)) {
8277 goto error;
8280 if (!NT_STATUS_IS_OK(status)) {
8281 return true;
8284 if (base == NULL) goto error;
8286 if (strcmp(expected_base, base) != 0) goto error;
8288 if ((expected_stream != NULL) && (stream == NULL)) goto error;
8289 if ((expected_stream == NULL) && (stream != NULL)) goto error;
8291 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
8292 goto error;
8294 TALLOC_FREE(base);
8295 TALLOC_FREE(stream);
8296 return true;
8298 error:
8299 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
8300 fname, expected_base ? expected_base : "<NULL>",
8301 expected_stream ? expected_stream : "<NULL>",
8302 nt_errstr(expected_status));
8303 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
8304 base ? base : "<NULL>", stream ? stream : "<NULL>",
8305 nt_errstr(status));
8306 TALLOC_FREE(base);
8307 TALLOC_FREE(stream);
8308 return false;
8311 static bool run_local_stream_name(int dummy)
8313 bool ret = true;
8315 ret &= test_stream_name(
8316 "bla", "bla", NULL, NT_STATUS_OK);
8317 ret &= test_stream_name(
8318 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
8319 ret &= test_stream_name(
8320 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8321 ret &= test_stream_name(
8322 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
8323 ret &= test_stream_name(
8324 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8325 ret &= test_stream_name(
8326 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
8327 ret &= test_stream_name(
8328 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
8329 ret &= test_stream_name(
8330 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
8332 return ret;
8335 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
8337 if (a.length != b.length) {
8338 printf("a.length=%d != b.length=%d\n",
8339 (int)a.length, (int)b.length);
8340 return false;
8342 if (memcmp(a.data, b.data, a.length) != 0) {
8343 printf("a.data and b.data differ\n");
8344 return false;
8346 return true;
8349 static bool run_local_memcache(int dummy)
8351 struct memcache *cache;
8352 DATA_BLOB k1, k2;
8353 DATA_BLOB d1, d2, d3;
8354 DATA_BLOB v1, v2, v3;
8356 TALLOC_CTX *mem_ctx;
8357 char *str1, *str2;
8358 size_t size1, size2;
8359 bool ret = false;
8361 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
8363 if (cache == NULL) {
8364 printf("memcache_init failed\n");
8365 return false;
8368 d1 = data_blob_const("d1", 2);
8369 d2 = data_blob_const("d2", 2);
8370 d3 = data_blob_const("d3", 2);
8372 k1 = data_blob_const("d1", 2);
8373 k2 = data_blob_const("d2", 2);
8375 memcache_add(cache, STAT_CACHE, k1, d1);
8376 memcache_add(cache, GETWD_CACHE, k2, d2);
8378 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
8379 printf("could not find k1\n");
8380 return false;
8382 if (!data_blob_equal(d1, v1)) {
8383 return false;
8386 if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8387 printf("could not find k2\n");
8388 return false;
8390 if (!data_blob_equal(d2, v2)) {
8391 return false;
8394 memcache_add(cache, STAT_CACHE, k1, d3);
8396 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
8397 printf("could not find replaced k1\n");
8398 return false;
8400 if (!data_blob_equal(d3, v3)) {
8401 return false;
8404 memcache_add(cache, GETWD_CACHE, k1, d1);
8406 if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8407 printf("Did find k2, should have been purged\n");
8408 return false;
8411 TALLOC_FREE(cache);
8413 cache = memcache_init(NULL, 0);
8415 mem_ctx = talloc_init("foo");
8417 str1 = talloc_strdup(mem_ctx, "string1");
8418 str2 = talloc_strdup(mem_ctx, "string2");
8420 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8421 data_blob_string_const("torture"), &str1);
8422 size1 = talloc_total_size(cache);
8424 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8425 data_blob_string_const("torture"), &str2);
8426 size2 = talloc_total_size(cache);
8428 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
8430 if (size2 > size1) {
8431 printf("memcache leaks memory!\n");
8432 goto fail;
8435 ret = true;
8436 fail:
8437 TALLOC_FREE(cache);
8438 return ret;
8441 static void wbclient_done(struct tevent_req *req)
8443 wbcErr wbc_err;
8444 struct winbindd_response *wb_resp;
8445 int *i = (int *)tevent_req_callback_data_void(req);
8447 wbc_err = wb_trans_recv(req, req, &wb_resp);
8448 TALLOC_FREE(req);
8449 *i += 1;
8450 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
8453 static bool run_local_wbclient(int dummy)
8455 struct event_context *ev;
8456 struct wb_context **wb_ctx;
8457 struct winbindd_request wb_req;
8458 bool result = false;
8459 int i, j;
8461 BlockSignals(True, SIGPIPE);
8463 ev = tevent_context_init_byname(talloc_tos(), "epoll");
8464 if (ev == NULL) {
8465 goto fail;
8468 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
8469 if (wb_ctx == NULL) {
8470 goto fail;
8473 ZERO_STRUCT(wb_req);
8474 wb_req.cmd = WINBINDD_PING;
8476 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
8478 for (i=0; i<torture_nprocs; i++) {
8479 wb_ctx[i] = wb_context_init(ev, NULL);
8480 if (wb_ctx[i] == NULL) {
8481 goto fail;
8483 for (j=0; j<torture_numops; j++) {
8484 struct tevent_req *req;
8485 req = wb_trans_send(ev, ev, wb_ctx[i],
8486 (j % 2) == 0, &wb_req);
8487 if (req == NULL) {
8488 goto fail;
8490 tevent_req_set_callback(req, wbclient_done, &i);
8494 i = 0;
8496 while (i < torture_nprocs * torture_numops) {
8497 tevent_loop_once(ev);
8500 result = true;
8501 fail:
8502 TALLOC_FREE(ev);
8503 return result;
8506 static void getaddrinfo_finished(struct tevent_req *req)
8508 char *name = (char *)tevent_req_callback_data_void(req);
8509 struct addrinfo *ainfo;
8510 int res;
8512 res = getaddrinfo_recv(req, &ainfo);
8513 if (res != 0) {
8514 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
8515 return;
8517 d_printf("gai(%s) succeeded\n", name);
8518 freeaddrinfo(ainfo);
8521 static bool run_getaddrinfo_send(int dummy)
8523 TALLOC_CTX *frame = talloc_stackframe();
8524 struct fncall_context *ctx;
8525 struct tevent_context *ev;
8526 bool result = false;
8527 const char *names[4] = { "www.samba.org", "notfound.samba.org",
8528 "www.slashdot.org", "heise.de" };
8529 struct tevent_req *reqs[4];
8530 int i;
8532 ev = event_context_init(frame);
8533 if (ev == NULL) {
8534 goto fail;
8537 ctx = fncall_context_init(frame, 4);
8539 for (i=0; i<ARRAY_SIZE(names); i++) {
8540 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
8541 NULL);
8542 if (reqs[i] == NULL) {
8543 goto fail;
8545 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
8546 discard_const_p(void, names[i]));
8549 for (i=0; i<ARRAY_SIZE(reqs); i++) {
8550 tevent_loop_once(ev);
8553 result = true;
8554 fail:
8555 TALLOC_FREE(frame);
8556 return result;
8559 static bool dbtrans_inc(struct db_context *db)
8561 struct db_record *rec;
8562 uint32_t val;
8563 bool ret = false;
8564 NTSTATUS status;
8565 TDB_DATA value;
8567 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
8568 if (rec == NULL) {
8569 printf(__location__ "fetch_lock failed\n");
8570 return false;
8573 value = dbwrap_record_get_value(rec);
8575 if (value.dsize != sizeof(uint32_t)) {
8576 printf(__location__ "value.dsize = %d\n",
8577 (int)value.dsize);
8578 goto fail;
8581 memcpy(&val, value.dptr, sizeof(val));
8582 val += 1;
8584 status = dbwrap_record_store(
8585 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
8586 if (!NT_STATUS_IS_OK(status)) {
8587 printf(__location__ "store failed: %s\n",
8588 nt_errstr(status));
8589 goto fail;
8592 ret = true;
8593 fail:
8594 TALLOC_FREE(rec);
8595 return ret;
8598 static bool run_local_dbtrans(int dummy)
8600 struct db_context *db;
8601 struct db_record *rec;
8602 NTSTATUS status;
8603 uint32_t initial;
8604 int res;
8605 TDB_DATA value;
8607 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
8608 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1);
8609 if (db == NULL) {
8610 printf("Could not open transtest.db\n");
8611 return false;
8614 res = dbwrap_transaction_start(db);
8615 if (res != 0) {
8616 printf(__location__ "transaction_start failed\n");
8617 return false;
8620 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
8621 if (rec == NULL) {
8622 printf(__location__ "fetch_lock failed\n");
8623 return false;
8626 value = dbwrap_record_get_value(rec);
8628 if (value.dptr == NULL) {
8629 initial = 0;
8630 status = dbwrap_record_store(
8631 rec, make_tdb_data((uint8_t *)&initial,
8632 sizeof(initial)),
8634 if (!NT_STATUS_IS_OK(status)) {
8635 printf(__location__ "store returned %s\n",
8636 nt_errstr(status));
8637 return false;
8641 TALLOC_FREE(rec);
8643 res = dbwrap_transaction_commit(db);
8644 if (res != 0) {
8645 printf(__location__ "transaction_commit failed\n");
8646 return false;
8649 while (true) {
8650 uint32_t val, val2;
8651 int i;
8653 res = dbwrap_transaction_start(db);
8654 if (res != 0) {
8655 printf(__location__ "transaction_start failed\n");
8656 break;
8659 status = dbwrap_fetch_uint32(db, "transtest", &val);
8660 if (!NT_STATUS_IS_OK(status)) {
8661 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
8662 nt_errstr(status));
8663 break;
8666 for (i=0; i<10; i++) {
8667 if (!dbtrans_inc(db)) {
8668 return false;
8672 status = dbwrap_fetch_uint32(db, "transtest", &val2);
8673 if (!NT_STATUS_IS_OK(status)) {
8674 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
8675 nt_errstr(status));
8676 break;
8679 if (val2 != val + 10) {
8680 printf(__location__ "val=%d, val2=%d\n",
8681 (int)val, (int)val2);
8682 break;
8685 printf("val2=%d\r", val2);
8687 res = dbwrap_transaction_commit(db);
8688 if (res != 0) {
8689 printf(__location__ "transaction_commit failed\n");
8690 break;
8694 TALLOC_FREE(db);
8695 return true;
8699 * Just a dummy test to be run under a debugger. There's no real way
8700 * to inspect the tevent_select specific function from outside of
8701 * tevent_select.c.
8704 static bool run_local_tevent_select(int dummy)
8706 struct tevent_context *ev;
8707 struct tevent_fd *fd1, *fd2;
8708 bool result = false;
8710 ev = tevent_context_init_byname(NULL, "select");
8711 if (ev == NULL) {
8712 d_fprintf(stderr, "tevent_context_init_byname failed\n");
8713 goto fail;
8716 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
8717 if (fd1 == NULL) {
8718 d_fprintf(stderr, "tevent_add_fd failed\n");
8719 goto fail;
8721 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
8722 if (fd2 == NULL) {
8723 d_fprintf(stderr, "tevent_add_fd failed\n");
8724 goto fail;
8726 TALLOC_FREE(fd2);
8728 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
8729 if (fd2 == NULL) {
8730 d_fprintf(stderr, "tevent_add_fd failed\n");
8731 goto fail;
8734 result = true;
8735 fail:
8736 TALLOC_FREE(ev);
8737 return result;
8740 static bool run_local_hex_encode_buf(int dummy)
8742 char buf[17];
8743 uint8_t src[8];
8744 int i;
8746 for (i=0; i<sizeof(src); i++) {
8747 src[i] = i;
8749 hex_encode_buf(buf, src, sizeof(src));
8750 if (strcmp(buf, "0001020304050607") != 0) {
8751 return false;
8753 hex_encode_buf(buf, NULL, 0);
8754 if (buf[0] != '\0') {
8755 return false;
8757 return true;
8760 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
8761 "0.0.0.0",
8762 "::0",
8763 "1.2.3.1",
8764 "0.0.0.0",
8765 "0.0.0.0",
8766 "1.2.3.2",
8767 "1.2.3.3",
8768 "1.2.3.4",
8769 "1.2.3.5",
8770 "::0",
8771 "1.2.3.6",
8772 "1.2.3.7",
8773 "::0",
8774 "::0",
8775 "::0",
8776 "1.2.3.8",
8777 "1.2.3.9",
8778 "1.2.3.10",
8779 "1.2.3.11",
8780 "1.2.3.12",
8781 "1.2.3.13",
8782 "1001:1111:1111:1000:0:1111:1111:1111",
8783 "1.2.3.1",
8784 "1.2.3.2",
8785 "1.2.3.3",
8786 "1.2.3.12",
8787 "::0",
8788 "::0"
8791 static const char *remove_duplicate_addrs2_test_strings_result[] = {
8792 "1.2.3.1",
8793 "1.2.3.2",
8794 "1.2.3.3",
8795 "1.2.3.4",
8796 "1.2.3.5",
8797 "1.2.3.6",
8798 "1.2.3.7",
8799 "1.2.3.8",
8800 "1.2.3.9",
8801 "1.2.3.10",
8802 "1.2.3.11",
8803 "1.2.3.12",
8804 "1.2.3.13",
8805 "1001:1111:1111:1000:0:1111:1111:1111"
8808 static bool run_local_remove_duplicate_addrs2(int dummy)
8810 struct ip_service test_vector[28];
8811 int count, i;
8813 /* Construct the sockaddr_storage test vector. */
8814 for (i = 0; i < 28; i++) {
8815 struct addrinfo hints;
8816 struct addrinfo *res = NULL;
8817 int ret;
8819 memset(&hints, '\0', sizeof(hints));
8820 hints.ai_flags = AI_NUMERICHOST;
8821 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
8822 NULL,
8823 &hints,
8824 &res);
8825 if (ret) {
8826 fprintf(stderr, "getaddrinfo failed on [%s]\n",
8827 remove_duplicate_addrs2_test_strings_vector[i]);
8828 return false;
8830 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
8831 memcpy(&test_vector[i].ss,
8832 res->ai_addr,
8833 res->ai_addrlen);
8834 freeaddrinfo(res);
8837 count = remove_duplicate_addrs2(test_vector, i);
8839 if (count != 14) {
8840 fprintf(stderr, "count wrong (%d) should be 14\n",
8841 count);
8842 return false;
8845 for (i = 0; i < count; i++) {
8846 char addr[INET6_ADDRSTRLEN];
8848 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
8850 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
8851 fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
8853 addr,
8854 remove_duplicate_addrs2_test_strings_result[i]);
8855 return false;
8859 printf("run_local_remove_duplicate_addrs2: success\n");
8860 return true;
8863 static double create_procs(bool (*fn)(int), bool *result)
8865 int i, status;
8866 volatile pid_t *child_status;
8867 volatile bool *child_status_out;
8868 int synccount;
8869 int tries = 8;
8870 struct timeval start;
8872 synccount = 0;
8874 child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*torture_nprocs);
8875 if (!child_status) {
8876 printf("Failed to setup shared memory\n");
8877 return -1;
8880 child_status_out = (volatile bool *)shm_setup(sizeof(bool)*torture_nprocs);
8881 if (!child_status_out) {
8882 printf("Failed to setup result status shared memory\n");
8883 return -1;
8886 for (i = 0; i < torture_nprocs; i++) {
8887 child_status[i] = 0;
8888 child_status_out[i] = True;
8891 start = timeval_current();
8893 for (i=0;i<torture_nprocs;i++) {
8894 procnum = i;
8895 if (fork() == 0) {
8896 pid_t mypid = getpid();
8897 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
8899 slprintf(myname,sizeof(myname),"CLIENT%d", i);
8901 while (1) {
8902 if (torture_open_connection(&current_cli, i)) break;
8903 if (tries-- == 0) {
8904 printf("pid %d failed to start\n", (int)getpid());
8905 _exit(1);
8907 smb_msleep(10);
8910 child_status[i] = getpid();
8912 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
8914 child_status_out[i] = fn(i);
8915 _exit(0);
8919 do {
8920 synccount = 0;
8921 for (i=0;i<torture_nprocs;i++) {
8922 if (child_status[i]) synccount++;
8924 if (synccount == torture_nprocs) break;
8925 smb_msleep(10);
8926 } while (timeval_elapsed(&start) < 30);
8928 if (synccount != torture_nprocs) {
8929 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
8930 *result = False;
8931 return timeval_elapsed(&start);
8934 /* start the client load */
8935 start = timeval_current();
8937 for (i=0;i<torture_nprocs;i++) {
8938 child_status[i] = 0;
8941 printf("%d clients started\n", torture_nprocs);
8943 for (i=0;i<torture_nprocs;i++) {
8944 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
8947 printf("\n");
8949 for (i=0;i<torture_nprocs;i++) {
8950 if (!child_status_out[i]) {
8951 *result = False;
8954 return timeval_elapsed(&start);
8957 #define FLAG_MULTIPROC 1
8959 static struct {
8960 const char *name;
8961 bool (*fn)(int);
8962 unsigned flags;
8963 } torture_ops[] = {
8964 {"FDPASS", run_fdpasstest, 0},
8965 {"LOCK1", run_locktest1, 0},
8966 {"LOCK2", run_locktest2, 0},
8967 {"LOCK3", run_locktest3, 0},
8968 {"LOCK4", run_locktest4, 0},
8969 {"LOCK5", run_locktest5, 0},
8970 {"LOCK6", run_locktest6, 0},
8971 {"LOCK7", run_locktest7, 0},
8972 {"LOCK8", run_locktest8, 0},
8973 {"LOCK9", run_locktest9, 0},
8974 {"UNLINK", run_unlinktest, 0},
8975 {"BROWSE", run_browsetest, 0},
8976 {"ATTR", run_attrtest, 0},
8977 {"TRANS2", run_trans2test, 0},
8978 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
8979 {"TORTURE",run_torture, FLAG_MULTIPROC},
8980 {"RANDOMIPC", run_randomipc, 0},
8981 {"NEGNOWAIT", run_negprot_nowait, 0},
8982 {"NBENCH", run_nbench, 0},
8983 {"NBENCH2", run_nbench2, 0},
8984 {"OPLOCK1", run_oplock1, 0},
8985 {"OPLOCK2", run_oplock2, 0},
8986 {"OPLOCK4", run_oplock4, 0},
8987 {"DIR", run_dirtest, 0},
8988 {"DIR1", run_dirtest1, 0},
8989 {"DIR-CREATETIME", run_dir_createtime, 0},
8990 {"DENY1", torture_denytest1, 0},
8991 {"DENY2", torture_denytest2, 0},
8992 {"TCON", run_tcon_test, 0},
8993 {"TCONDEV", run_tcon_devtype_test, 0},
8994 {"RW1", run_readwritetest, 0},
8995 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
8996 {"RW3", run_readwritelarge, 0},
8997 {"RW-SIGNING", run_readwritelarge_signtest, 0},
8998 {"OPEN", run_opentest, 0},
8999 {"POSIX", run_simple_posix_open_test, 0},
9000 {"POSIX-APPEND", run_posix_append, 0},
9001 {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
9002 {"ASYNC-ECHO", run_async_echo, 0},
9003 { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
9004 { "SHORTNAME-TEST", run_shortname_test, 0},
9005 { "ADDRCHANGE", run_addrchange, 0},
9006 #if 1
9007 {"OPENATTR", run_openattrtest, 0},
9008 #endif
9009 {"XCOPY", run_xcopy, 0},
9010 {"RENAME", run_rename, 0},
9011 {"DELETE", run_deletetest, 0},
9012 {"DELETE-LN", run_deletetest_ln, 0},
9013 {"PROPERTIES", run_properties, 0},
9014 {"MANGLE", torture_mangle, 0},
9015 {"MANGLE1", run_mangle1, 0},
9016 {"W2K", run_w2ktest, 0},
9017 {"TRANS2SCAN", torture_trans2_scan, 0},
9018 {"NTTRANSSCAN", torture_nttrans_scan, 0},
9019 {"UTABLE", torture_utable, 0},
9020 {"CASETABLE", torture_casetable, 0},
9021 {"ERRMAPEXTRACT", run_error_map_extract, 0},
9022 {"PIPE_NUMBER", run_pipe_number, 0},
9023 {"TCON2", run_tcon2_test, 0},
9024 {"IOCTL", torture_ioctl_test, 0},
9025 {"CHKPATH", torture_chkpath_test, 0},
9026 {"FDSESS", run_fdsesstest, 0},
9027 { "EATEST", run_eatest, 0},
9028 { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
9029 { "CHAIN1", run_chain1, 0},
9030 { "CHAIN2", run_chain2, 0},
9031 { "CHAIN3", run_chain3, 0},
9032 { "WINDOWS-WRITE", run_windows_write, 0},
9033 { "NTTRANS-CREATE", run_nttrans_create, 0},
9034 { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
9035 { "CLI_ECHO", run_cli_echo, 0},
9036 { "GETADDRINFO", run_getaddrinfo_send, 0},
9037 { "TLDAP", run_tldap },
9038 { "STREAMERROR", run_streamerror },
9039 { "NOTIFY-BENCH", run_notify_bench },
9040 { "NOTIFY-BENCH2", run_notify_bench2 },
9041 { "NOTIFY-BENCH3", run_notify_bench3 },
9042 { "BAD-NBT-SESSION", run_bad_nbt_session },
9043 { "SMB-ANY-CONNECT", run_smb_any_connect },
9044 { "NOTIFY-ONLINE", run_notify_online },
9045 { "SMB2-BASIC", run_smb2_basic },
9046 { "SMB2-NEGPROT", run_smb2_negprot },
9047 { "SMB2-SESSION-RECONNECT", run_smb2_session_reconnect },
9048 { "SMB2-TCON-DEPENDENCE", run_smb2_tcon_dependence },
9049 { "SMB2-MULTI-CHANNEL", run_smb2_multi_channel },
9050 { "SMB2-SESSION-REAUTH", run_smb2_session_reauth },
9051 { "CLEANUP1", run_cleanup1 },
9052 { "CLEANUP2", run_cleanup2 },
9053 { "CLEANUP3", run_cleanup3 },
9054 { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
9055 { "LOCAL-GENCACHE", run_local_gencache, 0},
9056 { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
9057 { "LOCAL-CTDB-CONN", run_ctdb_conn, 0},
9058 { "LOCAL-MSG", run_msg_test, 0},
9059 { "LOCAL-DBWRAP-WATCH1", run_dbwrap_watch1, 0 },
9060 { "LOCAL-BASE64", run_local_base64, 0},
9061 { "LOCAL-RBTREE", run_local_rbtree, 0},
9062 { "LOCAL-MEMCACHE", run_local_memcache, 0},
9063 { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
9064 { "LOCAL-WBCLIENT", run_local_wbclient, 0},
9065 { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
9066 { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
9067 { "LOCAL-DBTRANS", run_local_dbtrans, 0},
9068 { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
9069 { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
9070 { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
9071 { "LOCAL-sprintf_append", run_local_sprintf_append, 0},
9072 { "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0},
9073 { "LOCAL-IDMAP-TDB-COMMON", run_idmap_tdb_common_test, 0},
9074 { "LOCAL-remove_duplicate_addrs2", run_local_remove_duplicate_addrs2, 0},
9075 {NULL, NULL, 0}};
9079 /****************************************************************************
9080 run a specified test or "ALL"
9081 ****************************************************************************/
9082 static bool run_test(const char *name)
9084 bool ret = True;
9085 bool result = True;
9086 bool found = False;
9087 int i;
9088 double t;
9089 if (strequal(name,"ALL")) {
9090 for (i=0;torture_ops[i].name;i++) {
9091 run_test(torture_ops[i].name);
9093 found = True;
9096 for (i=0;torture_ops[i].name;i++) {
9097 fstr_sprintf(randomfname, "\\XX%x",
9098 (unsigned)random());
9100 if (strequal(name, torture_ops[i].name)) {
9101 found = True;
9102 printf("Running %s\n", name);
9103 if (torture_ops[i].flags & FLAG_MULTIPROC) {
9104 t = create_procs(torture_ops[i].fn, &result);
9105 if (!result) {
9106 ret = False;
9107 printf("TEST %s FAILED!\n", name);
9109 } else {
9110 struct timeval start;
9111 start = timeval_current();
9112 if (!torture_ops[i].fn(0)) {
9113 ret = False;
9114 printf("TEST %s FAILED!\n", name);
9116 t = timeval_elapsed(&start);
9118 printf("%s took %g secs\n\n", name, t);
9122 if (!found) {
9123 printf("Did not find a test named %s\n", name);
9124 ret = False;
9127 return ret;
9131 static void usage(void)
9133 int i;
9135 printf("WARNING samba4 test suite is much more complete nowadays.\n");
9136 printf("Please use samba4 torture.\n\n");
9138 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
9140 printf("\t-d debuglevel\n");
9141 printf("\t-U user%%pass\n");
9142 printf("\t-k use kerberos\n");
9143 printf("\t-N numprocs\n");
9144 printf("\t-n my_netbios_name\n");
9145 printf("\t-W workgroup\n");
9146 printf("\t-o num_operations\n");
9147 printf("\t-O socket_options\n");
9148 printf("\t-m maximum protocol\n");
9149 printf("\t-L use oplocks\n");
9150 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
9151 printf("\t-A showall\n");
9152 printf("\t-p port\n");
9153 printf("\t-s seed\n");
9154 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
9155 printf("\t-f filename filename to test\n");
9156 printf("\n\n");
9158 printf("tests are:");
9159 for (i=0;torture_ops[i].name;i++) {
9160 printf(" %s", torture_ops[i].name);
9162 printf("\n");
9164 printf("default test is ALL\n");
9166 exit(1);
9169 /****************************************************************************
9170 main program
9171 ****************************************************************************/
9172 int main(int argc,char *argv[])
9174 int opt, i;
9175 char *p;
9176 int gotuser = 0;
9177 int gotpass = 0;
9178 bool correct = True;
9179 TALLOC_CTX *frame = talloc_stackframe();
9180 int seed = time(NULL);
9182 #ifdef HAVE_SETBUFFER
9183 setbuffer(stdout, NULL, 0);
9184 #endif
9186 setup_logging("smbtorture", DEBUG_STDOUT);
9188 load_case_tables();
9190 if (is_default_dyn_CONFIGFILE()) {
9191 if(getenv("SMB_CONF_PATH")) {
9192 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
9195 lp_load_global(get_dyn_CONFIGFILE());
9196 load_interfaces();
9198 if (argc < 2) {
9199 usage();
9202 for(p = argv[1]; *p; p++)
9203 if(*p == '\\')
9204 *p = '/';
9206 if (strncmp(argv[1], "//", 2)) {
9207 usage();
9210 fstrcpy(host, &argv[1][2]);
9211 p = strchr_m(&host[2],'/');
9212 if (!p) {
9213 usage();
9215 *p = 0;
9216 fstrcpy(share, p+1);
9218 fstrcpy(myname, get_myname(talloc_tos()));
9219 if (!*myname) {
9220 fprintf(stderr, "Failed to get my hostname.\n");
9221 return 1;
9224 if (*username == 0 && getenv("LOGNAME")) {
9225 fstrcpy(username,getenv("LOGNAME"));
9228 argc--;
9229 argv++;
9231 fstrcpy(workgroup, lp_workgroup());
9233 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
9234 != EOF) {
9235 switch (opt) {
9236 case 'p':
9237 port_to_use = atoi(optarg);
9238 break;
9239 case 's':
9240 seed = atoi(optarg);
9241 break;
9242 case 'W':
9243 fstrcpy(workgroup,optarg);
9244 break;
9245 case 'm':
9246 max_protocol = interpret_protocol(optarg, max_protocol);
9247 break;
9248 case 'N':
9249 torture_nprocs = atoi(optarg);
9250 break;
9251 case 'o':
9252 torture_numops = atoi(optarg);
9253 break;
9254 case 'd':
9255 lp_set_cmdline("log level", optarg);
9256 break;
9257 case 'O':
9258 sockops = optarg;
9259 break;
9260 case 'L':
9261 use_oplocks = True;
9262 break;
9263 case 'l':
9264 local_path = optarg;
9265 break;
9266 case 'A':
9267 torture_showall = True;
9268 break;
9269 case 'n':
9270 fstrcpy(myname, optarg);
9271 break;
9272 case 'c':
9273 client_txt = optarg;
9274 break;
9275 case 'e':
9276 do_encrypt = true;
9277 break;
9278 case 'k':
9279 #ifdef HAVE_KRB5
9280 use_kerberos = True;
9281 #else
9282 d_printf("No kerberos support compiled in\n");
9283 exit(1);
9284 #endif
9285 break;
9286 case 'U':
9287 gotuser = 1;
9288 fstrcpy(username,optarg);
9289 p = strchr_m(username,'%');
9290 if (p) {
9291 *p = 0;
9292 fstrcpy(password, p+1);
9293 gotpass = 1;
9295 break;
9296 case 'b':
9297 fstrcpy(multishare_conn_fname, optarg);
9298 use_multishare_conn = True;
9299 break;
9300 case 'B':
9301 torture_blocksize = atoi(optarg);
9302 break;
9303 case 'f':
9304 test_filename = SMB_STRDUP(optarg);
9305 break;
9306 default:
9307 printf("Unknown option %c (%d)\n", (char)opt, opt);
9308 usage();
9312 d_printf("using seed %d\n", seed);
9314 srandom(seed);
9316 if(use_kerberos && !gotuser) gotpass = True;
9318 while (!gotpass) {
9319 p = getpass("Password:");
9320 if (p) {
9321 fstrcpy(password, p);
9322 gotpass = 1;
9326 printf("host=%s share=%s user=%s myname=%s\n",
9327 host, share, username, myname);
9329 if (argc == optind) {
9330 correct = run_test("ALL");
9331 } else {
9332 for (i=optind;i<argc;i++) {
9333 if (!run_test(argv[i])) {
9334 correct = False;
9339 TALLOC_FREE(frame);
9341 if (correct) {
9342 return(0);
9343 } else {
9344 return(1);