idmap: Remove "domname" from idmap_backends_unixid_to_sid
[Samba.git] / source3 / torture / torture.c
blobe0be44e8e56b4782488ecf580b1f5c4d9fc190a0
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 "../lib/util/memcache.h"
30 #include "nsswitch/winbind_client.h"
31 #include "dbwrap/dbwrap.h"
32 #include "dbwrap/dbwrap_open.h"
33 #include "dbwrap/dbwrap_rbt.h"
34 #include "talloc_dict.h"
35 #include "async_smb.h"
36 #include "libsmb/libsmb.h"
37 #include "libsmb/clirap.h"
38 #include "trans2.h"
39 #include "libsmb/nmblib.h"
40 #include "../lib/util/tevent_ntstatus.h"
41 #include "util_tdb.h"
42 #include "../libcli/smb/read_smb.h"
43 #include "../libcli/smb/smbXcli_base.h"
44 #include "lib/sys_rw_data.h"
46 extern char *optarg;
47 extern int optind;
49 fstring host, workgroup, share, password, username, myname;
50 static const char *sockops="TCP_NODELAY";
51 int torture_nprocs=1;
52 static int port_to_use=0;
53 int torture_numops=100;
54 int torture_blocksize=1024*1024;
55 static int procnum; /* records process count number when forking */
56 static struct cli_state *current_cli;
57 static fstring randomfname;
58 static bool use_oplocks;
59 static bool use_level_II_oplocks;
60 static const char *client_txt = "client_oplocks.txt";
61 static bool disable_spnego;
62 static bool use_kerberos;
63 static bool force_dos_errors;
64 static fstring multishare_conn_fname;
65 static bool use_multishare_conn = False;
66 static bool do_encrypt;
67 static const char *local_path = NULL;
68 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
69 char *test_filename;
71 bool torture_showall = False;
73 static double create_procs(bool (*fn)(int), bool *result);
75 /********************************************************************
76 Ensure a connection is encrypted.
77 ********************************************************************/
79 static bool force_cli_encryption(struct cli_state *c,
80 const char *sharename)
82 uint16_t major, minor;
83 uint32_t caplow, caphigh;
84 NTSTATUS status;
86 if (!SERVER_HAS_UNIX_CIFS(c)) {
87 d_printf("Encryption required and "
88 "server that doesn't support "
89 "UNIX extensions - failing connect\n");
90 return false;
93 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
94 &caphigh);
95 if (!NT_STATUS_IS_OK(status)) {
96 d_printf("Encryption required and "
97 "can't get UNIX CIFS extensions "
98 "version from server: %s\n", nt_errstr(status));
99 return false;
102 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
103 d_printf("Encryption required and "
104 "share %s doesn't support "
105 "encryption.\n", sharename);
106 return false;
109 if (c->use_kerberos) {
110 status = cli_gss_smb_encryption_start(c);
111 } else {
112 status = cli_raw_ntlm_smb_encryption_start(c,
113 username,
114 password,
115 workgroup);
118 if (!NT_STATUS_IS_OK(status)) {
119 d_printf("Encryption required and "
120 "setup failed with error %s.\n",
121 nt_errstr(status));
122 return false;
125 return true;
129 static struct cli_state *open_nbt_connection(void)
131 struct cli_state *c;
132 NTSTATUS status;
133 int flags = 0;
135 if (disable_spnego) {
136 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
139 if (use_oplocks) {
140 flags |= CLI_FULL_CONNECTION_OPLOCKS;
143 if (use_level_II_oplocks) {
144 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
147 if (use_kerberos) {
148 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
151 if (force_dos_errors) {
152 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
155 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
156 signing_state, flags, &c);
157 if (!NT_STATUS_IS_OK(status)) {
158 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
159 return NULL;
162 cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
164 return c;
167 /****************************************************************************
168 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
169 ****************************************************************************/
171 static bool cli_bad_session_request(int fd,
172 struct nmb_name *calling, struct nmb_name *called)
174 TALLOC_CTX *frame;
175 uint8_t len_buf[4];
176 struct iovec iov[3];
177 ssize_t len;
178 uint8_t *inbuf;
179 int err;
180 bool ret = false;
181 uint8_t message_type;
182 uint8_t error;
183 struct tevent_context *ev;
184 struct tevent_req *req;
186 frame = talloc_stackframe();
188 iov[0].iov_base = len_buf;
189 iov[0].iov_len = sizeof(len_buf);
191 /* put in the destination name */
193 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
194 called->name_type);
195 if (iov[1].iov_base == NULL) {
196 goto fail;
198 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
199 talloc_get_size(iov[1].iov_base));
201 /* and my name */
203 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
204 calling->name_type);
205 if (iov[2].iov_base == NULL) {
206 goto fail;
208 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
209 talloc_get_size(iov[2].iov_base));
211 /* Deliberately corrupt the name len (first byte) */
212 *((uint8_t *)iov[2].iov_base) = 100;
214 /* send a session request (RFC 1002) */
215 /* setup the packet length
216 * Remove four bytes from the length count, since the length
217 * field in the NBT Session Service header counts the number
218 * of bytes which follow. The cli_send_smb() function knows
219 * about this and accounts for those four bytes.
220 * CRH.
223 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
224 SCVAL(len_buf,0,0x81);
226 len = write_data_iov(fd, iov, 3);
227 if (len == -1) {
228 goto fail;
231 ev = samba_tevent_context_init(frame);
232 if (ev == NULL) {
233 goto fail;
235 req = read_smb_send(frame, ev, fd);
236 if (req == NULL) {
237 goto fail;
239 if (!tevent_req_poll(req, ev)) {
240 goto fail;
242 len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
243 if (len == -1) {
244 errno = err;
245 goto fail;
247 TALLOC_FREE(ev);
249 message_type = CVAL(inbuf, 0);
250 if (message_type != 0x83) {
251 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
252 message_type);
253 goto fail;
256 if (smb_len(inbuf) != 1) {
257 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
258 (int)smb_len(inbuf));
259 goto fail;
262 error = CVAL(inbuf, 4);
263 if (error != 0x82) {
264 d_fprintf(stderr, "Expected error 0x82, got %d\n",
265 (int)error);
266 goto fail;
269 ret = true;
270 fail:
271 TALLOC_FREE(frame);
272 return ret;
275 /* Insert a NULL at the first separator of the given path and return a pointer
276 * to the remainder of the string.
278 static char *
279 terminate_path_at_separator(char * path)
281 char * p;
283 if (!path) {
284 return NULL;
287 if ((p = strchr_m(path, '/'))) {
288 *p = '\0';
289 return p + 1;
292 if ((p = strchr_m(path, '\\'))) {
293 *p = '\0';
294 return p + 1;
297 /* No separator. */
298 return NULL;
302 parse a //server/share type UNC name
304 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
305 char **hostname, char **sharename)
307 char *p;
309 *hostname = *sharename = NULL;
311 if (strncmp(unc_name, "\\\\", 2) &&
312 strncmp(unc_name, "//", 2)) {
313 return False;
316 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
317 p = terminate_path_at_separator(*hostname);
319 if (p && *p) {
320 *sharename = talloc_strdup(mem_ctx, p);
321 terminate_path_at_separator(*sharename);
324 if (*hostname && *sharename) {
325 return True;
328 TALLOC_FREE(*hostname);
329 TALLOC_FREE(*sharename);
330 return False;
333 static bool torture_open_connection_share(struct cli_state **c,
334 const char *hostname,
335 const char *sharename)
337 int flags = 0;
338 NTSTATUS status;
340 if (use_kerberos)
341 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
342 if (use_oplocks)
343 flags |= CLI_FULL_CONNECTION_OPLOCKS;
344 if (use_level_II_oplocks)
345 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
347 status = cli_full_connection(c, myname,
348 hostname, NULL, port_to_use,
349 sharename, "?????",
350 username, workgroup,
351 password, flags, signing_state);
352 if (!NT_STATUS_IS_OK(status)) {
353 printf("failed to open share connection: //%s/%s port:%d - %s\n",
354 hostname, sharename, port_to_use, nt_errstr(status));
355 return False;
358 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
360 if (do_encrypt) {
361 return force_cli_encryption(*c,
362 sharename);
364 return True;
367 bool torture_open_connection(struct cli_state **c, int conn_index)
369 char **unc_list = NULL;
370 int num_unc_names = 0;
371 bool result;
373 if (use_multishare_conn==True) {
374 char *h, *s;
375 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
376 if (!unc_list || num_unc_names <= 0) {
377 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
378 exit(1);
381 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
382 NULL, &h, &s)) {
383 printf("Failed to parse UNC name %s\n",
384 unc_list[conn_index % num_unc_names]);
385 TALLOC_FREE(unc_list);
386 exit(1);
389 result = torture_open_connection_share(c, h, s);
391 /* h, s were copied earlier */
392 TALLOC_FREE(unc_list);
393 return result;
396 return torture_open_connection_share(c, host, share);
399 bool torture_init_connection(struct cli_state **pcli)
401 struct cli_state *cli;
403 cli = open_nbt_connection();
404 if (cli == NULL) {
405 return false;
408 *pcli = cli;
409 return true;
412 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
414 uint16_t old_vuid = cli_state_get_uid(cli);
415 size_t passlen = strlen(password);
416 NTSTATUS status;
417 bool ret;
419 cli_state_set_uid(cli, 0);
420 status = cli_session_setup(cli, username,
421 password, passlen,
422 password, passlen,
423 workgroup);
424 ret = NT_STATUS_IS_OK(status);
425 *new_vuid = cli_state_get_uid(cli);
426 cli_state_set_uid(cli, old_vuid);
427 return ret;
431 bool torture_close_connection(struct cli_state *c)
433 bool ret = True;
434 NTSTATUS status;
436 status = cli_tdis(c);
437 if (!NT_STATUS_IS_OK(status)) {
438 printf("tdis failed (%s)\n", nt_errstr(status));
439 ret = False;
442 cli_shutdown(c);
444 return ret;
448 /* check if the server produced the expected dos or nt error code */
449 static bool check_both_error(int line, NTSTATUS status,
450 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
452 if (NT_STATUS_IS_DOS(status)) {
453 uint8_t cclass;
454 uint32_t num;
456 /* Check DOS error */
457 cclass = NT_STATUS_DOS_CLASS(status);
458 num = NT_STATUS_DOS_CODE(status);
460 if (eclass != cclass || ecode != num) {
461 printf("unexpected error code class=%d code=%d\n",
462 (int)cclass, (int)num);
463 printf(" expected %d/%d %s (line=%d)\n",
464 (int)eclass, (int)ecode, nt_errstr(nterr), line);
465 return false;
467 } else {
468 /* Check NT error */
469 if (!NT_STATUS_EQUAL(nterr, status)) {
470 printf("unexpected error code %s\n",
471 nt_errstr(status));
472 printf(" expected %s (line=%d)\n",
473 nt_errstr(nterr), line);
474 return false;
478 return true;
482 /* check if the server produced the expected error code */
483 static bool check_error(int line, NTSTATUS status,
484 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
486 if (NT_STATUS_IS_DOS(status)) {
487 uint8_t cclass;
488 uint32_t num;
490 /* Check DOS error */
492 cclass = NT_STATUS_DOS_CLASS(status);
493 num = NT_STATUS_DOS_CODE(status);
495 if (eclass != cclass || ecode != num) {
496 printf("unexpected error code class=%d code=%d\n",
497 (int)cclass, (int)num);
498 printf(" expected %d/%d %s (line=%d)\n",
499 (int)eclass, (int)ecode, nt_errstr(nterr),
500 line);
501 return False;
504 } else {
505 /* Check NT error */
507 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
508 printf("unexpected error code %s\n",
509 nt_errstr(status));
510 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
511 line);
512 return False;
516 return True;
520 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
522 NTSTATUS status;
524 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
526 while (!NT_STATUS_IS_OK(status)) {
527 if (!check_both_error(__LINE__, status, ERRDOS,
528 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
529 return false;
532 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
535 return true;
539 static bool rw_torture(struct cli_state *c)
541 const char *lockfname = "\\torture.lck";
542 fstring fname;
543 uint16_t fnum;
544 uint16_t fnum2;
545 pid_t pid2, pid = getpid();
546 int i, j;
547 char buf[1024];
548 bool correct = True;
549 size_t nread = 0;
550 NTSTATUS status;
552 memset(buf, '\0', sizeof(buf));
554 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
555 DENY_NONE, &fnum2);
556 if (!NT_STATUS_IS_OK(status)) {
557 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
559 if (!NT_STATUS_IS_OK(status)) {
560 printf("open of %s failed (%s)\n",
561 lockfname, nt_errstr(status));
562 return False;
565 for (i=0;i<torture_numops;i++) {
566 unsigned n = (unsigned)sys_random()%10;
568 if (i % 10 == 0) {
569 printf("%d\r", i); fflush(stdout);
571 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
573 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
574 return False;
577 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
578 DENY_ALL, &fnum);
579 if (!NT_STATUS_IS_OK(status)) {
580 printf("open failed (%s)\n", nt_errstr(status));
581 correct = False;
582 break;
585 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
586 sizeof(pid), NULL);
587 if (!NT_STATUS_IS_OK(status)) {
588 printf("write failed (%s)\n", nt_errstr(status));
589 correct = False;
592 for (j=0;j<50;j++) {
593 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
594 sizeof(pid)+(j*sizeof(buf)),
595 sizeof(buf), NULL);
596 if (!NT_STATUS_IS_OK(status)) {
597 printf("write failed (%s)\n",
598 nt_errstr(status));
599 correct = False;
603 pid2 = 0;
605 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
606 &nread);
607 if (!NT_STATUS_IS_OK(status)) {
608 printf("read failed (%s)\n", nt_errstr(status));
609 correct = false;
610 } else if (nread != sizeof(pid)) {
611 printf("read/write compare failed: "
612 "recv %ld req %ld\n", (unsigned long)nread,
613 (unsigned long)sizeof(pid));
614 correct = false;
617 if (pid2 != pid) {
618 printf("data corruption!\n");
619 correct = False;
622 status = cli_close(c, fnum);
623 if (!NT_STATUS_IS_OK(status)) {
624 printf("close failed (%s)\n", nt_errstr(status));
625 correct = False;
628 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
629 if (!NT_STATUS_IS_OK(status)) {
630 printf("unlink failed (%s)\n", nt_errstr(status));
631 correct = False;
634 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
635 if (!NT_STATUS_IS_OK(status)) {
636 printf("unlock failed (%s)\n", nt_errstr(status));
637 correct = False;
641 cli_close(c, fnum2);
642 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
644 printf("%d\n", i);
646 return correct;
649 static bool run_torture(int dummy)
651 struct cli_state *cli;
652 bool ret;
654 cli = current_cli;
656 smbXcli_conn_set_sockopt(cli->conn, sockops);
658 ret = rw_torture(cli);
660 if (!torture_close_connection(cli)) {
661 ret = False;
664 return ret;
667 static bool rw_torture3(struct cli_state *c, char *lockfname)
669 uint16_t fnum = (uint16_t)-1;
670 unsigned int i = 0;
671 char buf[131072];
672 char buf_rd[131072];
673 unsigned count;
674 unsigned countprev = 0;
675 size_t sent = 0;
676 bool correct = True;
677 NTSTATUS status = NT_STATUS_OK;
679 srandom(1);
680 for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
682 SIVAL(buf, i, sys_random());
685 if (procnum == 0)
687 status = cli_unlink(
688 c, lockfname,
689 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
690 if (!NT_STATUS_IS_OK(status)) {
691 printf("unlink failed (%s) (normal, this file should "
692 "not exist)\n", nt_errstr(status));
695 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
696 DENY_NONE, &fnum);
697 if (!NT_STATUS_IS_OK(status)) {
698 printf("first open read/write of %s failed (%s)\n",
699 lockfname, nt_errstr(status));
700 return False;
703 else
705 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
707 status = cli_openx(c, lockfname, O_RDONLY,
708 DENY_NONE, &fnum);
709 if (NT_STATUS_IS_OK(status)) {
710 break;
712 smb_msleep(10);
714 if (!NT_STATUS_IS_OK(status)) {
715 printf("second open read-only of %s failed (%s)\n",
716 lockfname, nt_errstr(status));
717 return False;
721 i = 0;
722 for (count = 0; count < sizeof(buf); count += sent)
724 if (count >= countprev) {
725 printf("%d %8d\r", i, count);
726 fflush(stdout);
727 i++;
728 countprev += (sizeof(buf) / 20);
731 if (procnum == 0)
733 sent = ((unsigned)sys_random()%(20))+ 1;
734 if (sent > sizeof(buf) - count)
736 sent = sizeof(buf) - count;
739 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
740 count, sent, NULL);
741 if (!NT_STATUS_IS_OK(status)) {
742 printf("write failed (%s)\n",
743 nt_errstr(status));
744 correct = False;
747 else
749 status = cli_read(c, fnum, buf_rd+count, count,
750 sizeof(buf)-count, &sent);
751 if(!NT_STATUS_IS_OK(status)) {
752 printf("read failed offset:%d size:%ld (%s)\n",
753 count, (unsigned long)sizeof(buf)-count,
754 nt_errstr(status));
755 correct = False;
756 sent = 0;
757 } else if (sent > 0) {
758 if (memcmp(buf_rd+count, buf+count, sent) != 0)
760 printf("read/write compare failed\n");
761 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
762 correct = False;
763 break;
770 status = cli_close(c, fnum);
771 if (!NT_STATUS_IS_OK(status)) {
772 printf("close failed (%s)\n", nt_errstr(status));
773 correct = False;
776 return correct;
779 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
781 const char *lockfname = "\\torture2.lck";
782 uint16_t fnum1;
783 uint16_t fnum2;
784 int i;
785 char buf[131072];
786 char buf_rd[131072];
787 bool correct = True;
788 size_t bytes_read;
789 NTSTATUS status;
791 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
792 if (!NT_STATUS_IS_OK(status)) {
793 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
796 status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
797 DENY_NONE, &fnum1);
798 if (!NT_STATUS_IS_OK(status)) {
799 printf("first open read/write of %s failed (%s)\n",
800 lockfname, nt_errstr(status));
801 return False;
804 status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
805 if (!NT_STATUS_IS_OK(status)) {
806 printf("second open read-only of %s failed (%s)\n",
807 lockfname, nt_errstr(status));
808 cli_close(c1, fnum1);
809 return False;
812 for (i = 0; i < torture_numops; i++)
814 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
815 if (i % 10 == 0) {
816 printf("%d\r", i); fflush(stdout);
819 generate_random_buffer((unsigned char *)buf, buf_size);
821 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
822 buf_size, NULL);
823 if (!NT_STATUS_IS_OK(status)) {
824 printf("write failed (%s)\n", nt_errstr(status));
825 correct = False;
826 break;
829 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
830 if(!NT_STATUS_IS_OK(status)) {
831 printf("read failed (%s)\n", nt_errstr(status));
832 correct = false;
833 break;
834 } else if (bytes_read != buf_size) {
835 printf("read failed\n");
836 printf("read %ld, expected %ld\n",
837 (unsigned long)bytes_read,
838 (unsigned long)buf_size);
839 correct = False;
840 break;
843 if (memcmp(buf_rd, buf, buf_size) != 0)
845 printf("read/write compare failed\n");
846 correct = False;
847 break;
851 status = cli_close(c2, fnum2);
852 if (!NT_STATUS_IS_OK(status)) {
853 printf("close failed (%s)\n", nt_errstr(status));
854 correct = False;
857 status = cli_close(c1, fnum1);
858 if (!NT_STATUS_IS_OK(status)) {
859 printf("close failed (%s)\n", nt_errstr(status));
860 correct = False;
863 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
864 if (!NT_STATUS_IS_OK(status)) {
865 printf("unlink failed (%s)\n", nt_errstr(status));
866 correct = False;
869 return correct;
872 static bool run_readwritetest(int dummy)
874 struct cli_state *cli1, *cli2;
875 bool test1, test2 = False;
877 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
878 return False;
880 smbXcli_conn_set_sockopt(cli1->conn, sockops);
881 smbXcli_conn_set_sockopt(cli2->conn, sockops);
883 printf("starting readwritetest\n");
885 test1 = rw_torture2(cli1, cli2);
886 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
888 if (test1) {
889 test2 = rw_torture2(cli1, cli1);
890 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
893 if (!torture_close_connection(cli1)) {
894 test1 = False;
897 if (!torture_close_connection(cli2)) {
898 test2 = False;
901 return (test1 && test2);
904 static bool run_readwritemulti(int dummy)
906 struct cli_state *cli;
907 bool test;
909 cli = current_cli;
911 smbXcli_conn_set_sockopt(cli->conn, sockops);
913 printf("run_readwritemulti: fname %s\n", randomfname);
914 test = rw_torture3(cli, randomfname);
916 if (!torture_close_connection(cli)) {
917 test = False;
920 return test;
923 static bool run_readwritelarge_internal(void)
925 static struct cli_state *cli1;
926 uint16_t fnum1;
927 const char *lockfname = "\\large.dat";
928 off_t fsize;
929 char buf[126*1024];
930 bool correct = True;
931 NTSTATUS status;
933 if (!torture_open_connection(&cli1, 0)) {
934 return False;
936 smbXcli_conn_set_sockopt(cli1->conn, sockops);
937 memset(buf,'\0',sizeof(buf));
939 printf("starting readwritelarge_internal\n");
941 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
943 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
944 DENY_NONE, &fnum1);
945 if (!NT_STATUS_IS_OK(status)) {
946 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
947 return False;
950 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
952 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
953 NULL, NULL, NULL);
954 if (!NT_STATUS_IS_OK(status)) {
955 printf("qfileinfo failed (%s)\n", nt_errstr(status));
956 correct = False;
959 if (fsize == sizeof(buf))
960 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
961 (unsigned long)fsize);
962 else {
963 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
964 (unsigned long)fsize);
965 correct = False;
968 status = cli_close(cli1, fnum1);
969 if (!NT_STATUS_IS_OK(status)) {
970 printf("close failed (%s)\n", nt_errstr(status));
971 correct = False;
974 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
975 if (!NT_STATUS_IS_OK(status)) {
976 printf("unlink failed (%s)\n", nt_errstr(status));
977 correct = False;
980 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
981 DENY_NONE, &fnum1);
982 if (!NT_STATUS_IS_OK(status)) {
983 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
984 return False;
987 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
989 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
990 NULL, NULL, NULL);
991 if (!NT_STATUS_IS_OK(status)) {
992 printf("qfileinfo failed (%s)\n", nt_errstr(status));
993 correct = False;
996 if (fsize == sizeof(buf))
997 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
998 (unsigned long)fsize);
999 else {
1000 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1001 (unsigned long)fsize);
1002 correct = False;
1005 #if 0
1006 /* ToDo - set allocation. JRA */
1007 if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1008 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1009 return False;
1011 if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1012 NULL, NULL)) {
1013 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1014 correct = False;
1016 if (fsize != 0)
1017 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1018 #endif
1020 status = cli_close(cli1, fnum1);
1021 if (!NT_STATUS_IS_OK(status)) {
1022 printf("close failed (%s)\n", nt_errstr(status));
1023 correct = False;
1026 if (!torture_close_connection(cli1)) {
1027 correct = False;
1029 return correct;
1032 static bool run_readwritelarge(int dummy)
1034 return run_readwritelarge_internal();
1037 static bool run_readwritelarge_signtest(int dummy)
1039 bool ret;
1040 signing_state = SMB_SIGNING_REQUIRED;
1041 ret = run_readwritelarge_internal();
1042 signing_state = SMB_SIGNING_DEFAULT;
1043 return ret;
1046 int line_count = 0;
1047 int nbio_id;
1049 #define ival(s) strtol(s, NULL, 0)
1051 /* run a test that simulates an approximate netbench client load */
1052 static bool run_netbench(int client)
1054 struct cli_state *cli;
1055 int i;
1056 char line[1024];
1057 char cname[20];
1058 FILE *f;
1059 const char *params[20];
1060 bool correct = True;
1062 cli = current_cli;
1064 nbio_id = client;
1066 smbXcli_conn_set_sockopt(cli->conn, sockops);
1068 nb_setup(cli);
1070 slprintf(cname,sizeof(cname)-1, "client%d", client);
1072 f = fopen(client_txt, "r");
1074 if (!f) {
1075 perror(client_txt);
1076 return False;
1079 while (fgets(line, sizeof(line)-1, f)) {
1080 char *saveptr;
1081 line_count++;
1083 line[strlen(line)-1] = 0;
1085 /* printf("[%d] %s\n", line_count, line); */
1087 all_string_sub(line,"client1", cname, sizeof(line));
1089 /* parse the command parameters */
1090 params[0] = strtok_r(line, " ", &saveptr);
1091 i = 0;
1092 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1094 params[i] = "";
1096 if (i < 2) continue;
1098 if (!strncmp(params[0],"SMB", 3)) {
1099 printf("ERROR: You are using a dbench 1 load file\n");
1100 exit(1);
1103 if (!strcmp(params[0],"NTCreateX")) {
1104 nb_createx(params[1], ival(params[2]), ival(params[3]),
1105 ival(params[4]));
1106 } else if (!strcmp(params[0],"Close")) {
1107 nb_close(ival(params[1]));
1108 } else if (!strcmp(params[0],"Rename")) {
1109 nb_rename(params[1], params[2]);
1110 } else if (!strcmp(params[0],"Unlink")) {
1111 nb_unlink(params[1]);
1112 } else if (!strcmp(params[0],"Deltree")) {
1113 nb_deltree(params[1]);
1114 } else if (!strcmp(params[0],"Rmdir")) {
1115 nb_rmdir(params[1]);
1116 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1117 nb_qpathinfo(params[1]);
1118 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1119 nb_qfileinfo(ival(params[1]));
1120 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1121 nb_qfsinfo(ival(params[1]));
1122 } else if (!strcmp(params[0],"FIND_FIRST")) {
1123 nb_findfirst(params[1]);
1124 } else if (!strcmp(params[0],"WriteX")) {
1125 nb_writex(ival(params[1]),
1126 ival(params[2]), ival(params[3]), ival(params[4]));
1127 } else if (!strcmp(params[0],"ReadX")) {
1128 nb_readx(ival(params[1]),
1129 ival(params[2]), ival(params[3]), ival(params[4]));
1130 } else if (!strcmp(params[0],"Flush")) {
1131 nb_flush(ival(params[1]));
1132 } else {
1133 printf("Unknown operation %s\n", params[0]);
1134 exit(1);
1137 fclose(f);
1139 nb_cleanup();
1141 if (!torture_close_connection(cli)) {
1142 correct = False;
1145 return correct;
1149 /* run a test that simulates an approximate netbench client load */
1150 static bool run_nbench(int dummy)
1152 double t;
1153 bool correct = True;
1155 nbio_shmem(torture_nprocs);
1157 nbio_id = -1;
1159 signal(SIGALRM, nb_alarm);
1160 alarm(1);
1161 t = create_procs(run_netbench, &correct);
1162 alarm(0);
1164 printf("\nThroughput %g MB/sec\n",
1165 1.0e-6 * nbio_total() / t);
1166 return correct;
1171 This test checks for two things:
1173 1) correct support for retaining locks over a close (ie. the server
1174 must not use posix semantics)
1175 2) support for lock timeouts
1177 static bool run_locktest1(int dummy)
1179 struct cli_state *cli1, *cli2;
1180 const char *fname = "\\lockt1.lck";
1181 uint16_t fnum1, fnum2, fnum3;
1182 time_t t1, t2;
1183 unsigned lock_timeout;
1184 NTSTATUS status;
1186 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1187 return False;
1189 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1190 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1192 printf("starting locktest1\n");
1194 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1196 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1197 &fnum1);
1198 if (!NT_STATUS_IS_OK(status)) {
1199 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1200 return False;
1203 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1204 if (!NT_STATUS_IS_OK(status)) {
1205 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1206 return False;
1209 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1210 if (!NT_STATUS_IS_OK(status)) {
1211 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1212 return False;
1215 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1216 if (!NT_STATUS_IS_OK(status)) {
1217 printf("lock1 failed (%s)\n", nt_errstr(status));
1218 return false;
1221 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1222 if (NT_STATUS_IS_OK(status)) {
1223 printf("lock2 succeeded! This is a locking bug\n");
1224 return false;
1225 } else {
1226 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1227 NT_STATUS_LOCK_NOT_GRANTED)) {
1228 return false;
1232 lock_timeout = (1 + (random() % 20));
1233 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1234 t1 = time(NULL);
1235 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1236 if (NT_STATUS_IS_OK(status)) {
1237 printf("lock3 succeeded! This is a locking bug\n");
1238 return false;
1239 } else {
1240 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1241 NT_STATUS_FILE_LOCK_CONFLICT)) {
1242 return false;
1245 t2 = time(NULL);
1247 if (ABS(t2 - t1) < lock_timeout-1) {
1248 printf("error: This server appears not to support timed lock requests\n");
1251 printf("server slept for %u seconds for a %u second timeout\n",
1252 (unsigned int)(t2-t1), lock_timeout);
1254 status = cli_close(cli1, fnum2);
1255 if (!NT_STATUS_IS_OK(status)) {
1256 printf("close1 failed (%s)\n", nt_errstr(status));
1257 return False;
1260 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1261 if (NT_STATUS_IS_OK(status)) {
1262 printf("lock4 succeeded! This is a locking bug\n");
1263 return false;
1264 } else {
1265 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1266 NT_STATUS_FILE_LOCK_CONFLICT)) {
1267 return false;
1271 status = cli_close(cli1, fnum1);
1272 if (!NT_STATUS_IS_OK(status)) {
1273 printf("close2 failed (%s)\n", nt_errstr(status));
1274 return False;
1277 status = cli_close(cli2, fnum3);
1278 if (!NT_STATUS_IS_OK(status)) {
1279 printf("close3 failed (%s)\n", nt_errstr(status));
1280 return False;
1283 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1284 if (!NT_STATUS_IS_OK(status)) {
1285 printf("unlink failed (%s)\n", nt_errstr(status));
1286 return False;
1290 if (!torture_close_connection(cli1)) {
1291 return False;
1294 if (!torture_close_connection(cli2)) {
1295 return False;
1298 printf("Passed locktest1\n");
1299 return True;
1303 this checks to see if a secondary tconx can use open files from an
1304 earlier tconx
1306 static bool run_tcon_test(int dummy)
1308 static struct cli_state *cli;
1309 const char *fname = "\\tcontest.tmp";
1310 uint16_t fnum1;
1311 uint16_t cnum1, cnum2, cnum3;
1312 uint16_t vuid1, vuid2;
1313 char buf[4];
1314 bool ret = True;
1315 NTSTATUS status;
1317 memset(buf, '\0', sizeof(buf));
1319 if (!torture_open_connection(&cli, 0)) {
1320 return False;
1322 smbXcli_conn_set_sockopt(cli->conn, sockops);
1324 printf("starting tcontest\n");
1326 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1328 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1329 if (!NT_STATUS_IS_OK(status)) {
1330 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1331 return False;
1334 cnum1 = cli_state_get_tid(cli);
1335 vuid1 = cli_state_get_uid(cli);
1337 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1338 if (!NT_STATUS_IS_OK(status)) {
1339 printf("initial write failed (%s)", nt_errstr(status));
1340 return False;
1343 status = cli_tree_connect(cli, share, "?????",
1344 password, strlen(password)+1);
1345 if (!NT_STATUS_IS_OK(status)) {
1346 printf("%s refused 2nd tree connect (%s)\n", host,
1347 nt_errstr(status));
1348 cli_shutdown(cli);
1349 return False;
1352 cnum2 = cli_state_get_tid(cli);
1353 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1354 vuid2 = cli_state_get_uid(cli) + 1;
1356 /* try a write with the wrong tid */
1357 cli_state_set_tid(cli, cnum2);
1359 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1360 if (NT_STATUS_IS_OK(status)) {
1361 printf("* server allows write with wrong TID\n");
1362 ret = False;
1363 } else {
1364 printf("server fails write with wrong TID : %s\n",
1365 nt_errstr(status));
1369 /* try a write with an invalid tid */
1370 cli_state_set_tid(cli, cnum3);
1372 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1373 if (NT_STATUS_IS_OK(status)) {
1374 printf("* server allows write with invalid TID\n");
1375 ret = False;
1376 } else {
1377 printf("server fails write with invalid TID : %s\n",
1378 nt_errstr(status));
1381 /* try a write with an invalid vuid */
1382 cli_state_set_uid(cli, vuid2);
1383 cli_state_set_tid(cli, cnum1);
1385 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1386 if (NT_STATUS_IS_OK(status)) {
1387 printf("* server allows write with invalid VUID\n");
1388 ret = False;
1389 } else {
1390 printf("server fails write with invalid VUID : %s\n",
1391 nt_errstr(status));
1394 cli_state_set_tid(cli, cnum1);
1395 cli_state_set_uid(cli, vuid1);
1397 status = cli_close(cli, fnum1);
1398 if (!NT_STATUS_IS_OK(status)) {
1399 printf("close failed (%s)\n", nt_errstr(status));
1400 return False;
1403 cli_state_set_tid(cli, cnum2);
1405 status = cli_tdis(cli);
1406 if (!NT_STATUS_IS_OK(status)) {
1407 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1408 return False;
1411 cli_state_set_tid(cli, cnum1);
1413 if (!torture_close_connection(cli)) {
1414 return False;
1417 return ret;
1422 checks for old style tcon support
1424 static bool run_tcon2_test(int dummy)
1426 static struct cli_state *cli;
1427 uint16_t cnum, max_xmit;
1428 char *service;
1429 NTSTATUS status;
1431 if (!torture_open_connection(&cli, 0)) {
1432 return False;
1434 smbXcli_conn_set_sockopt(cli->conn, sockops);
1436 printf("starting tcon2 test\n");
1438 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1439 return false;
1442 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1444 SAFE_FREE(service);
1446 if (!NT_STATUS_IS_OK(status)) {
1447 printf("tcon2 failed : %s\n", nt_errstr(status));
1448 } else {
1449 printf("tcon OK : max_xmit=%d cnum=%d\n",
1450 (int)max_xmit, (int)cnum);
1453 if (!torture_close_connection(cli)) {
1454 return False;
1457 printf("Passed tcon2 test\n");
1458 return True;
1461 static bool tcon_devtest(struct cli_state *cli,
1462 const char *myshare, const char *devtype,
1463 const char *return_devtype,
1464 NTSTATUS expected_error)
1466 NTSTATUS status;
1467 bool ret;
1469 status = cli_tree_connect(cli, myshare, devtype,
1470 password, strlen(password)+1);
1472 if (NT_STATUS_IS_OK(expected_error)) {
1473 if (NT_STATUS_IS_OK(status)) {
1474 if (strcmp(cli->dev, return_devtype) == 0) {
1475 ret = True;
1476 } else {
1477 printf("tconX to share %s with type %s "
1478 "succeeded but returned the wrong "
1479 "device type (got [%s] but should have got [%s])\n",
1480 myshare, devtype, cli->dev, return_devtype);
1481 ret = False;
1483 } else {
1484 printf("tconX to share %s with type %s "
1485 "should have succeeded but failed\n",
1486 myshare, devtype);
1487 ret = False;
1489 cli_tdis(cli);
1490 } else {
1491 if (NT_STATUS_IS_OK(status)) {
1492 printf("tconx to share %s with type %s "
1493 "should have failed but succeeded\n",
1494 myshare, devtype);
1495 ret = False;
1496 } else {
1497 if (NT_STATUS_EQUAL(status, expected_error)) {
1498 ret = True;
1499 } else {
1500 printf("Returned unexpected error\n");
1501 ret = False;
1505 return ret;
1509 checks for correct tconX support
1511 static bool run_tcon_devtype_test(int dummy)
1513 static struct cli_state *cli1 = NULL;
1514 int flags = 0;
1515 NTSTATUS status;
1516 bool ret = True;
1518 status = cli_full_connection(&cli1, myname,
1519 host, NULL, port_to_use,
1520 NULL, NULL,
1521 username, workgroup,
1522 password, flags, signing_state);
1524 if (!NT_STATUS_IS_OK(status)) {
1525 printf("could not open connection\n");
1526 return False;
1529 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1530 ret = False;
1532 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1533 ret = False;
1535 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1536 ret = False;
1538 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1539 ret = False;
1541 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1542 ret = False;
1544 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1545 ret = False;
1547 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1548 ret = False;
1550 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1551 ret = False;
1553 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1554 ret = False;
1556 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1557 ret = False;
1559 cli_shutdown(cli1);
1561 if (ret)
1562 printf("Passed tcondevtest\n");
1564 return ret;
1569 This test checks that
1571 1) the server supports multiple locking contexts on the one SMB
1572 connection, distinguished by PID.
1574 2) the server correctly fails overlapping locks made by the same PID (this
1575 goes against POSIX behaviour, which is why it is tricky to implement)
1577 3) the server denies unlock requests by an incorrect client PID
1579 static bool run_locktest2(int dummy)
1581 static struct cli_state *cli;
1582 const char *fname = "\\lockt2.lck";
1583 uint16_t fnum1, fnum2, fnum3;
1584 bool correct = True;
1585 NTSTATUS status;
1587 if (!torture_open_connection(&cli, 0)) {
1588 return False;
1591 smbXcli_conn_set_sockopt(cli->conn, sockops);
1593 printf("starting locktest2\n");
1595 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1597 cli_setpid(cli, 1);
1599 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1600 if (!NT_STATUS_IS_OK(status)) {
1601 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1602 return False;
1605 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1606 if (!NT_STATUS_IS_OK(status)) {
1607 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1608 return False;
1611 cli_setpid(cli, 2);
1613 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1614 if (!NT_STATUS_IS_OK(status)) {
1615 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1616 return False;
1619 cli_setpid(cli, 1);
1621 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1622 if (!NT_STATUS_IS_OK(status)) {
1623 printf("lock1 failed (%s)\n", nt_errstr(status));
1624 return false;
1627 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1628 if (NT_STATUS_IS_OK(status)) {
1629 printf("WRITE lock1 succeeded! This is a locking bug\n");
1630 correct = false;
1631 } else {
1632 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1633 NT_STATUS_LOCK_NOT_GRANTED)) {
1634 return false;
1638 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1639 if (NT_STATUS_IS_OK(status)) {
1640 printf("WRITE lock2 succeeded! This is a locking bug\n");
1641 correct = false;
1642 } else {
1643 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1644 NT_STATUS_LOCK_NOT_GRANTED)) {
1645 return false;
1649 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1650 if (NT_STATUS_IS_OK(status)) {
1651 printf("READ lock2 succeeded! This is a locking bug\n");
1652 correct = false;
1653 } else {
1654 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1655 NT_STATUS_FILE_LOCK_CONFLICT)) {
1656 return false;
1660 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1661 if (!NT_STATUS_IS_OK(status)) {
1662 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1664 cli_setpid(cli, 2);
1665 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1666 printf("unlock at 100 succeeded! This is a locking bug\n");
1667 correct = False;
1670 status = cli_unlock(cli, fnum1, 0, 4);
1671 if (NT_STATUS_IS_OK(status)) {
1672 printf("unlock1 succeeded! This is a locking bug\n");
1673 correct = false;
1674 } else {
1675 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1676 NT_STATUS_RANGE_NOT_LOCKED)) {
1677 return false;
1681 status = cli_unlock(cli, fnum1, 0, 8);
1682 if (NT_STATUS_IS_OK(status)) {
1683 printf("unlock2 succeeded! This is a locking bug\n");
1684 correct = false;
1685 } else {
1686 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1687 NT_STATUS_RANGE_NOT_LOCKED)) {
1688 return false;
1692 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1693 if (NT_STATUS_IS_OK(status)) {
1694 printf("lock3 succeeded! This is a locking bug\n");
1695 correct = false;
1696 } else {
1697 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1698 NT_STATUS_LOCK_NOT_GRANTED)) {
1699 return false;
1703 cli_setpid(cli, 1);
1705 status = cli_close(cli, fnum1);
1706 if (!NT_STATUS_IS_OK(status)) {
1707 printf("close1 failed (%s)\n", nt_errstr(status));
1708 return False;
1711 status = cli_close(cli, fnum2);
1712 if (!NT_STATUS_IS_OK(status)) {
1713 printf("close2 failed (%s)\n", nt_errstr(status));
1714 return False;
1717 status = cli_close(cli, fnum3);
1718 if (!NT_STATUS_IS_OK(status)) {
1719 printf("close3 failed (%s)\n", nt_errstr(status));
1720 return False;
1723 if (!torture_close_connection(cli)) {
1724 correct = False;
1727 printf("locktest2 finished\n");
1729 return correct;
1734 This test checks that
1736 1) the server supports the full offset range in lock requests
1738 static bool run_locktest3(int dummy)
1740 static struct cli_state *cli1, *cli2;
1741 const char *fname = "\\lockt3.lck";
1742 uint16_t fnum1, fnum2;
1743 int i;
1744 uint32_t offset;
1745 bool correct = True;
1746 NTSTATUS status;
1748 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1750 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1751 return False;
1753 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1754 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1756 printf("starting locktest3\n");
1758 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1760 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1761 &fnum1);
1762 if (!NT_STATUS_IS_OK(status)) {
1763 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1764 return False;
1767 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1768 if (!NT_STATUS_IS_OK(status)) {
1769 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1770 return False;
1773 for (offset=i=0;i<torture_numops;i++) {
1774 NEXT_OFFSET;
1776 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1777 if (!NT_STATUS_IS_OK(status)) {
1778 printf("lock1 %d failed (%s)\n",
1780 nt_errstr(status));
1781 return False;
1784 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1785 if (!NT_STATUS_IS_OK(status)) {
1786 printf("lock2 %d failed (%s)\n",
1788 nt_errstr(status));
1789 return False;
1793 for (offset=i=0;i<torture_numops;i++) {
1794 NEXT_OFFSET;
1796 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1797 if (NT_STATUS_IS_OK(status)) {
1798 printf("error: lock1 %d succeeded!\n", i);
1799 return False;
1802 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1803 if (NT_STATUS_IS_OK(status)) {
1804 printf("error: lock2 %d succeeded!\n", i);
1805 return False;
1808 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1809 if (NT_STATUS_IS_OK(status)) {
1810 printf("error: lock3 %d succeeded!\n", i);
1811 return False;
1814 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1815 if (NT_STATUS_IS_OK(status)) {
1816 printf("error: lock4 %d succeeded!\n", i);
1817 return False;
1821 for (offset=i=0;i<torture_numops;i++) {
1822 NEXT_OFFSET;
1824 status = cli_unlock(cli1, fnum1, offset-1, 1);
1825 if (!NT_STATUS_IS_OK(status)) {
1826 printf("unlock1 %d failed (%s)\n",
1828 nt_errstr(status));
1829 return False;
1832 status = cli_unlock(cli2, fnum2, offset-2, 1);
1833 if (!NT_STATUS_IS_OK(status)) {
1834 printf("unlock2 %d failed (%s)\n",
1836 nt_errstr(status));
1837 return False;
1841 status = cli_close(cli1, fnum1);
1842 if (!NT_STATUS_IS_OK(status)) {
1843 printf("close1 failed (%s)\n", nt_errstr(status));
1844 return False;
1847 status = cli_close(cli2, fnum2);
1848 if (!NT_STATUS_IS_OK(status)) {
1849 printf("close2 failed (%s)\n", nt_errstr(status));
1850 return False;
1853 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1854 if (!NT_STATUS_IS_OK(status)) {
1855 printf("unlink failed (%s)\n", nt_errstr(status));
1856 return False;
1859 if (!torture_close_connection(cli1)) {
1860 correct = False;
1863 if (!torture_close_connection(cli2)) {
1864 correct = False;
1867 printf("finished locktest3\n");
1869 return correct;
1872 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1873 char *buf, off_t offset, size_t size,
1874 size_t *nread, size_t expect)
1876 NTSTATUS status;
1877 size_t l_nread;
1879 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1881 if(!NT_STATUS_IS_OK(status)) {
1882 return false;
1883 } else if (l_nread != expect) {
1884 return false;
1887 if (nread) {
1888 *nread = l_nread;
1891 return true;
1894 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1895 printf("** "); correct = False; \
1899 looks at overlapping locks
1901 static bool run_locktest4(int dummy)
1903 static struct cli_state *cli1, *cli2;
1904 const char *fname = "\\lockt4.lck";
1905 uint16_t fnum1, fnum2, f;
1906 bool ret;
1907 char buf[1000];
1908 bool correct = True;
1909 NTSTATUS status;
1911 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1912 return False;
1915 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1916 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1918 printf("starting locktest4\n");
1920 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1922 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1923 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1925 memset(buf, 0, sizeof(buf));
1927 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1928 NULL);
1929 if (!NT_STATUS_IS_OK(status)) {
1930 printf("Failed to create file: %s\n", nt_errstr(status));
1931 correct = False;
1932 goto fail;
1935 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1936 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1937 EXPECTED(ret, False);
1938 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1940 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1941 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1942 EXPECTED(ret, True);
1943 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1945 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1946 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1947 EXPECTED(ret, False);
1948 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1950 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1951 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1952 EXPECTED(ret, True);
1953 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1955 ret = (cli_setpid(cli1, 1),
1956 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1957 (cli_setpid(cli1, 2),
1958 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1959 EXPECTED(ret, False);
1960 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1962 ret = (cli_setpid(cli1, 1),
1963 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1964 (cli_setpid(cli1, 2),
1965 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1966 EXPECTED(ret, True);
1967 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1969 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1970 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1971 EXPECTED(ret, True);
1972 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1974 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1975 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1976 EXPECTED(ret, False);
1977 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1979 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1980 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1981 EXPECTED(ret, False);
1982 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1984 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1985 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
1986 EXPECTED(ret, True);
1987 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1989 ret = (cli_setpid(cli1, 1),
1990 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
1991 (cli_setpid(cli1, 2),
1992 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
1993 EXPECTED(ret, False);
1994 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1996 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
1997 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
1998 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
1999 EXPECTED(ret, False);
2000 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2003 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2004 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2005 EXPECTED(ret, False);
2006 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2008 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2009 ret = NT_STATUS_IS_OK(status);
2010 if (ret) {
2011 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2012 NULL);
2013 ret = NT_STATUS_IS_OK(status);
2015 EXPECTED(ret, False);
2016 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2019 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2020 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2021 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2022 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2023 EXPECTED(ret, True);
2024 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2027 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2028 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2029 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2030 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2031 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2032 150, 4, NULL))) &&
2033 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2034 EXPECTED(ret, True);
2035 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2037 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2038 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2039 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2040 160, 4, NULL)) &&
2041 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2042 EXPECTED(ret, True);
2043 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2045 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2046 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2047 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2048 170, 4, NULL)) &&
2049 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2050 EXPECTED(ret, True);
2051 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2053 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2054 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2055 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2056 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2057 190, 4, NULL)) &&
2058 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2059 EXPECTED(ret, True);
2060 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2062 cli_close(cli1, fnum1);
2063 cli_close(cli2, fnum2);
2064 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2065 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2066 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2067 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2068 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2069 NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2070 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2071 cli_close(cli1, f);
2072 cli_close(cli1, fnum1);
2073 EXPECTED(ret, True);
2074 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2076 fail:
2077 cli_close(cli1, fnum1);
2078 cli_close(cli2, fnum2);
2079 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2080 torture_close_connection(cli1);
2081 torture_close_connection(cli2);
2083 printf("finished locktest4\n");
2084 return correct;
2088 looks at lock upgrade/downgrade.
2090 static bool run_locktest5(int dummy)
2092 static struct cli_state *cli1, *cli2;
2093 const char *fname = "\\lockt5.lck";
2094 uint16_t fnum1, fnum2, fnum3;
2095 bool ret;
2096 char buf[1000];
2097 bool correct = True;
2098 NTSTATUS status;
2100 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2101 return False;
2104 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2105 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2107 printf("starting locktest5\n");
2109 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2111 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2112 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2113 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2115 memset(buf, 0, sizeof(buf));
2117 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2118 NULL);
2119 if (!NT_STATUS_IS_OK(status)) {
2120 printf("Failed to create file: %s\n", nt_errstr(status));
2121 correct = False;
2122 goto fail;
2125 /* Check for NT bug... */
2126 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2127 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2128 cli_close(cli1, fnum1);
2129 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2130 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2131 ret = NT_STATUS_IS_OK(status);
2132 EXPECTED(ret, True);
2133 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2134 cli_close(cli1, fnum1);
2135 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2136 cli_unlock(cli1, fnum3, 0, 1);
2138 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2139 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2140 EXPECTED(ret, True);
2141 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2143 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2144 ret = NT_STATUS_IS_OK(status);
2145 EXPECTED(ret, False);
2147 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2149 /* Unlock the process 2 lock. */
2150 cli_unlock(cli2, fnum2, 0, 4);
2152 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2153 ret = NT_STATUS_IS_OK(status);
2154 EXPECTED(ret, False);
2156 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2158 /* Unlock the process 1 fnum3 lock. */
2159 cli_unlock(cli1, fnum3, 0, 4);
2161 /* Stack 2 more locks here. */
2162 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2163 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2165 EXPECTED(ret, True);
2166 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2168 /* Unlock the first process lock, then check this was the WRITE lock that was
2169 removed. */
2171 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2172 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2174 EXPECTED(ret, True);
2175 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2177 /* Unlock the process 2 lock. */
2178 cli_unlock(cli2, fnum2, 0, 4);
2180 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2182 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2183 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2184 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2186 EXPECTED(ret, True);
2187 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2189 /* Ensure the next unlock fails. */
2190 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2191 EXPECTED(ret, False);
2192 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2194 /* Ensure connection 2 can get a write lock. */
2195 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2196 ret = NT_STATUS_IS_OK(status);
2197 EXPECTED(ret, True);
2199 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2202 fail:
2203 cli_close(cli1, fnum1);
2204 cli_close(cli2, fnum2);
2205 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2206 if (!torture_close_connection(cli1)) {
2207 correct = False;
2209 if (!torture_close_connection(cli2)) {
2210 correct = False;
2213 printf("finished locktest5\n");
2215 return correct;
2219 tries the unusual lockingX locktype bits
2221 static bool run_locktest6(int dummy)
2223 static struct cli_state *cli;
2224 const char *fname[1] = { "\\lock6.txt" };
2225 int i;
2226 uint16_t fnum;
2227 NTSTATUS status;
2229 if (!torture_open_connection(&cli, 0)) {
2230 return False;
2233 smbXcli_conn_set_sockopt(cli->conn, sockops);
2235 printf("starting locktest6\n");
2237 for (i=0;i<1;i++) {
2238 printf("Testing %s\n", fname[i]);
2240 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2242 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2243 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2244 cli_close(cli, fnum);
2245 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2247 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2248 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2249 cli_close(cli, fnum);
2250 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2252 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2255 torture_close_connection(cli);
2257 printf("finished locktest6\n");
2258 return True;
2261 static bool run_locktest7(int dummy)
2263 struct cli_state *cli1;
2264 const char *fname = "\\lockt7.lck";
2265 uint16_t fnum1;
2266 char buf[200];
2267 bool correct = False;
2268 size_t nread;
2269 NTSTATUS status;
2271 if (!torture_open_connection(&cli1, 0)) {
2272 return False;
2275 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2277 printf("starting locktest7\n");
2279 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2281 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2283 memset(buf, 0, sizeof(buf));
2285 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2286 NULL);
2287 if (!NT_STATUS_IS_OK(status)) {
2288 printf("Failed to create file: %s\n", nt_errstr(status));
2289 goto fail;
2292 cli_setpid(cli1, 1);
2294 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2295 if (!NT_STATUS_IS_OK(status)) {
2296 printf("Unable to apply read lock on range 130:4, "
2297 "error was %s\n", nt_errstr(status));
2298 goto fail;
2299 } else {
2300 printf("pid1 successfully locked range 130:4 for READ\n");
2303 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2304 if (!NT_STATUS_IS_OK(status)) {
2305 printf("pid1 unable to read the range 130:4, error was %s\n",
2306 nt_errstr(status));
2307 goto fail;
2308 } else if (nread != 4) {
2309 printf("pid1 unable to read the range 130:4, "
2310 "recv %ld req %d\n", (unsigned long)nread, 4);
2311 goto fail;
2312 } else {
2313 printf("pid1 successfully read the range 130:4\n");
2316 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2317 if (!NT_STATUS_IS_OK(status)) {
2318 printf("pid1 unable to write to the range 130:4, error was "
2319 "%s\n", nt_errstr(status));
2320 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2321 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2322 goto fail;
2324 } else {
2325 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2326 goto fail;
2329 cli_setpid(cli1, 2);
2331 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2332 if (!NT_STATUS_IS_OK(status)) {
2333 printf("pid2 unable to read the range 130:4, error was %s\n",
2334 nt_errstr(status));
2335 goto fail;
2336 } else if (nread != 4) {
2337 printf("pid2 unable to read the range 130:4, "
2338 "recv %ld req %d\n", (unsigned long)nread, 4);
2339 goto fail;
2340 } else {
2341 printf("pid2 successfully read the range 130:4\n");
2344 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2345 if (!NT_STATUS_IS_OK(status)) {
2346 printf("pid2 unable to write to the range 130:4, error was "
2347 "%s\n", nt_errstr(status));
2348 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2349 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2350 goto fail;
2352 } else {
2353 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2354 goto fail;
2357 cli_setpid(cli1, 1);
2358 cli_unlock(cli1, fnum1, 130, 4);
2360 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2361 if (!NT_STATUS_IS_OK(status)) {
2362 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2363 goto fail;
2364 } else {
2365 printf("pid1 successfully locked range 130:4 for WRITE\n");
2368 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2369 if (!NT_STATUS_IS_OK(status)) {
2370 printf("pid1 unable to read the range 130:4, error was %s\n",
2371 nt_errstr(status));
2372 goto fail;
2373 } else if (nread != 4) {
2374 printf("pid1 unable to read the range 130:4, "
2375 "recv %ld req %d\n", (unsigned long)nread, 4);
2376 goto fail;
2377 } else {
2378 printf("pid1 successfully read the range 130:4\n");
2381 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2382 if (!NT_STATUS_IS_OK(status)) {
2383 printf("pid1 unable to write to the range 130:4, error was "
2384 "%s\n", nt_errstr(status));
2385 goto fail;
2386 } else {
2387 printf("pid1 successfully wrote to the range 130:4\n");
2390 cli_setpid(cli1, 2);
2392 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2393 if (!NT_STATUS_IS_OK(status)) {
2394 printf("pid2 unable to read the range 130:4, error was "
2395 "%s\n", nt_errstr(status));
2396 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2397 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2398 goto fail;
2400 } else {
2401 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2402 (unsigned long)nread);
2403 goto fail;
2406 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2407 if (!NT_STATUS_IS_OK(status)) {
2408 printf("pid2 unable to write to the range 130:4, error was "
2409 "%s\n", nt_errstr(status));
2410 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2411 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2412 goto fail;
2414 } else {
2415 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2416 goto fail;
2419 cli_unlock(cli1, fnum1, 130, 0);
2420 correct = True;
2422 fail:
2423 cli_close(cli1, fnum1);
2424 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2425 torture_close_connection(cli1);
2427 printf("finished locktest7\n");
2428 return correct;
2432 * This demonstrates a problem with our use of GPFS share modes: A file
2433 * descriptor sitting in the pending close queue holding a GPFS share mode
2434 * blocks opening a file another time. Happens with Word 2007 temp files.
2435 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2436 * open is denied with NT_STATUS_SHARING_VIOLATION.
2439 static bool run_locktest8(int dummy)
2441 struct cli_state *cli1;
2442 const char *fname = "\\lockt8.lck";
2443 uint16_t fnum1, fnum2;
2444 char buf[200];
2445 bool correct = False;
2446 NTSTATUS status;
2448 if (!torture_open_connection(&cli1, 0)) {
2449 return False;
2452 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2454 printf("starting locktest8\n");
2456 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2458 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2459 &fnum1);
2460 if (!NT_STATUS_IS_OK(status)) {
2461 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2462 return false;
2465 memset(buf, 0, sizeof(buf));
2467 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2468 if (!NT_STATUS_IS_OK(status)) {
2469 d_fprintf(stderr, "cli_openx second time returned %s\n",
2470 nt_errstr(status));
2471 goto fail;
2474 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2475 if (!NT_STATUS_IS_OK(status)) {
2476 printf("Unable to apply read lock on range 1:1, error was "
2477 "%s\n", nt_errstr(status));
2478 goto fail;
2481 status = cli_close(cli1, fnum1);
2482 if (!NT_STATUS_IS_OK(status)) {
2483 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2484 goto fail;
2487 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2488 if (!NT_STATUS_IS_OK(status)) {
2489 d_fprintf(stderr, "cli_openx third time returned %s\n",
2490 nt_errstr(status));
2491 goto fail;
2494 correct = true;
2496 fail:
2497 cli_close(cli1, fnum1);
2498 cli_close(cli1, fnum2);
2499 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2500 torture_close_connection(cli1);
2502 printf("finished locktest8\n");
2503 return correct;
2507 * This test is designed to be run in conjunction with
2508 * external NFS or POSIX locks taken in the filesystem.
2509 * It checks that the smbd server will block until the
2510 * lock is released and then acquire it. JRA.
2513 static bool got_alarm;
2514 static struct cli_state *alarm_cli;
2516 static void alarm_handler(int dummy)
2518 got_alarm = True;
2521 static void alarm_handler_parent(int dummy)
2523 smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_OK);
2526 static void do_local_lock(int read_fd, int write_fd)
2528 int fd;
2529 char c = '\0';
2530 struct flock lock;
2531 const char *local_pathname = NULL;
2532 int ret;
2534 local_pathname = talloc_asprintf(talloc_tos(),
2535 "%s/lockt9.lck", local_path);
2536 if (!local_pathname) {
2537 printf("child: alloc fail\n");
2538 exit(1);
2541 unlink(local_pathname);
2542 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2543 if (fd == -1) {
2544 printf("child: open of %s failed %s.\n",
2545 local_pathname, strerror(errno));
2546 exit(1);
2549 /* Now take a fcntl lock. */
2550 lock.l_type = F_WRLCK;
2551 lock.l_whence = SEEK_SET;
2552 lock.l_start = 0;
2553 lock.l_len = 4;
2554 lock.l_pid = getpid();
2556 ret = fcntl(fd,F_SETLK,&lock);
2557 if (ret == -1) {
2558 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2559 local_pathname, strerror(errno));
2560 exit(1);
2561 } else {
2562 printf("child: got lock 0:4 on file %s.\n",
2563 local_pathname );
2564 fflush(stdout);
2567 CatchSignal(SIGALRM, alarm_handler);
2568 alarm(5);
2569 /* Signal the parent. */
2570 if (write(write_fd, &c, 1) != 1) {
2571 printf("child: start signal fail %s.\n",
2572 strerror(errno));
2573 exit(1);
2575 alarm(0);
2577 alarm(10);
2578 /* Wait for the parent to be ready. */
2579 if (read(read_fd, &c, 1) != 1) {
2580 printf("child: reply signal fail %s.\n",
2581 strerror(errno));
2582 exit(1);
2584 alarm(0);
2586 sleep(5);
2587 close(fd);
2588 printf("child: released lock 0:4 on file %s.\n",
2589 local_pathname );
2590 fflush(stdout);
2591 exit(0);
2594 static bool run_locktest9(int dummy)
2596 struct cli_state *cli1;
2597 const char *fname = "\\lockt9.lck";
2598 uint16_t fnum;
2599 bool correct = False;
2600 int pipe_in[2], pipe_out[2];
2601 pid_t child_pid;
2602 char c = '\0';
2603 int ret;
2604 struct timeval start;
2605 double seconds;
2606 NTSTATUS status;
2608 printf("starting locktest9\n");
2610 if (local_path == NULL) {
2611 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2612 return false;
2615 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2616 return false;
2619 child_pid = fork();
2620 if (child_pid == -1) {
2621 return false;
2624 if (child_pid == 0) {
2625 /* Child. */
2626 do_local_lock(pipe_out[0], pipe_in[1]);
2627 exit(0);
2630 close(pipe_out[0]);
2631 close(pipe_in[1]);
2632 pipe_out[0] = -1;
2633 pipe_in[1] = -1;
2635 /* Parent. */
2636 ret = read(pipe_in[0], &c, 1);
2637 if (ret != 1) {
2638 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2639 strerror(errno));
2640 return false;
2643 if (!torture_open_connection(&cli1, 0)) {
2644 return false;
2647 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2649 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE,
2650 &fnum);
2651 if (!NT_STATUS_IS_OK(status)) {
2652 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2653 return false;
2656 /* Ensure the child has the lock. */
2657 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2658 if (NT_STATUS_IS_OK(status)) {
2659 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2660 goto fail;
2661 } else {
2662 d_printf("Child has the lock.\n");
2665 /* Tell the child to wait 5 seconds then exit. */
2666 ret = write(pipe_out[1], &c, 1);
2667 if (ret != 1) {
2668 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2669 strerror(errno));
2670 goto fail;
2673 /* Wait 20 seconds for the lock. */
2674 alarm_cli = cli1;
2675 CatchSignal(SIGALRM, alarm_handler_parent);
2676 alarm(20);
2678 start = timeval_current();
2680 status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2681 if (!NT_STATUS_IS_OK(status)) {
2682 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2683 "%s\n", nt_errstr(status));
2684 goto fail_nofd;
2686 alarm(0);
2688 seconds = timeval_elapsed(&start);
2690 printf("Parent got the lock after %.2f seconds.\n",
2691 seconds);
2693 status = cli_close(cli1, fnum);
2694 if (!NT_STATUS_IS_OK(status)) {
2695 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2696 goto fail;
2699 correct = true;
2701 fail:
2702 cli_close(cli1, fnum);
2703 torture_close_connection(cli1);
2705 fail_nofd:
2707 printf("finished locktest9\n");
2708 return correct;
2712 test whether fnums and tids open on one VC are available on another (a major
2713 security hole)
2715 static bool run_fdpasstest(int dummy)
2717 struct cli_state *cli1, *cli2;
2718 const char *fname = "\\fdpass.tst";
2719 uint16_t fnum1;
2720 char buf[1024];
2721 NTSTATUS status;
2723 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2724 return False;
2726 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2727 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2729 printf("starting fdpasstest\n");
2731 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2733 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2734 &fnum1);
2735 if (!NT_STATUS_IS_OK(status)) {
2736 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2737 return False;
2740 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2741 13, NULL);
2742 if (!NT_STATUS_IS_OK(status)) {
2743 printf("write failed (%s)\n", nt_errstr(status));
2744 return False;
2747 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
2748 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2749 cli_setpid(cli2, cli_getpid(cli1));
2751 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
2752 printf("read succeeded! nasty security hole [%s]\n", buf);
2753 return false;
2756 cli_close(cli1, fnum1);
2757 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2759 torture_close_connection(cli1);
2760 torture_close_connection(cli2);
2762 printf("finished fdpasstest\n");
2763 return True;
2766 static bool run_fdsesstest(int dummy)
2768 struct cli_state *cli;
2769 uint16_t new_vuid;
2770 uint16_t saved_vuid;
2771 uint16_t new_cnum;
2772 uint16_t saved_cnum;
2773 const char *fname = "\\fdsess.tst";
2774 const char *fname1 = "\\fdsess1.tst";
2775 uint16_t fnum1;
2776 uint16_t fnum2;
2777 char buf[1024];
2778 bool ret = True;
2779 NTSTATUS status;
2781 if (!torture_open_connection(&cli, 0))
2782 return False;
2783 smbXcli_conn_set_sockopt(cli->conn, sockops);
2785 if (!torture_cli_session_setup2(cli, &new_vuid))
2786 return False;
2788 saved_cnum = cli_state_get_tid(cli);
2789 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", "", 1)))
2790 return False;
2791 new_cnum = cli_state_get_tid(cli);
2792 cli_state_set_tid(cli, saved_cnum);
2794 printf("starting fdsesstest\n");
2796 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2797 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2799 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2800 if (!NT_STATUS_IS_OK(status)) {
2801 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2802 return False;
2805 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2806 NULL);
2807 if (!NT_STATUS_IS_OK(status)) {
2808 printf("write failed (%s)\n", nt_errstr(status));
2809 return False;
2812 saved_vuid = cli_state_get_uid(cli);
2813 cli_state_set_uid(cli, new_vuid);
2815 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2816 printf("read succeeded with different vuid! "
2817 "nasty security hole [%s]\n", buf);
2818 ret = false;
2820 /* Try to open a file with different vuid, samba cnum. */
2821 if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2822 printf("create with different vuid, same cnum succeeded.\n");
2823 cli_close(cli, fnum2);
2824 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2825 } else {
2826 printf("create with different vuid, same cnum failed.\n");
2827 printf("This will cause problems with service clients.\n");
2828 ret = False;
2831 cli_state_set_uid(cli, saved_vuid);
2833 /* Try with same vuid, different cnum. */
2834 cli_state_set_tid(cli, new_cnum);
2836 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2837 printf("read succeeded with different cnum![%s]\n", buf);
2838 ret = false;
2841 cli_state_set_tid(cli, saved_cnum);
2842 cli_close(cli, fnum1);
2843 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2845 torture_close_connection(cli);
2847 printf("finished fdsesstest\n");
2848 return ret;
2852 This test checks that
2854 1) the server does not allow an unlink on a file that is open
2856 static bool run_unlinktest(int dummy)
2858 struct cli_state *cli;
2859 const char *fname = "\\unlink.tst";
2860 uint16_t fnum;
2861 bool correct = True;
2862 NTSTATUS status;
2864 if (!torture_open_connection(&cli, 0)) {
2865 return False;
2868 smbXcli_conn_set_sockopt(cli->conn, sockops);
2870 printf("starting unlink test\n");
2872 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2874 cli_setpid(cli, 1);
2876 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2877 if (!NT_STATUS_IS_OK(status)) {
2878 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2879 return False;
2882 status = cli_unlink(cli, fname,
2883 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2884 if (NT_STATUS_IS_OK(status)) {
2885 printf("error: server allowed unlink on an open file\n");
2886 correct = False;
2887 } else {
2888 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
2889 NT_STATUS_SHARING_VIOLATION);
2892 cli_close(cli, fnum);
2893 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2895 if (!torture_close_connection(cli)) {
2896 correct = False;
2899 printf("unlink test finished\n");
2901 return correct;
2906 test how many open files this server supports on the one socket
2908 static bool run_maxfidtest(int dummy)
2910 struct cli_state *cli;
2911 fstring fname;
2912 uint16_t fnums[0x11000];
2913 int i;
2914 int retries=4;
2915 bool correct = True;
2916 NTSTATUS status;
2918 cli = current_cli;
2920 if (retries <= 0) {
2921 printf("failed to connect\n");
2922 return False;
2925 smbXcli_conn_set_sockopt(cli->conn, sockops);
2927 for (i=0; i<0x11000; i++) {
2928 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2929 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2930 &fnums[i]);
2931 if (!NT_STATUS_IS_OK(status)) {
2932 printf("open of %s failed (%s)\n",
2933 fname, nt_errstr(status));
2934 printf("maximum fnum is %d\n", i);
2935 break;
2937 printf("%6d\r", i);
2939 printf("%6d\n", i);
2940 i--;
2942 printf("cleaning up\n");
2943 for (;i>=0;i--) {
2944 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2945 cli_close(cli, fnums[i]);
2947 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2948 if (!NT_STATUS_IS_OK(status)) {
2949 printf("unlink of %s failed (%s)\n",
2950 fname, nt_errstr(status));
2951 correct = False;
2953 printf("%6d\r", i);
2955 printf("%6d\n", 0);
2957 printf("maxfid test finished\n");
2958 if (!torture_close_connection(cli)) {
2959 correct = False;
2961 return correct;
2964 /* generate a random buffer */
2965 static void rand_buf(char *buf, int len)
2967 while (len--) {
2968 *buf = (char)sys_random();
2969 buf++;
2973 /* send smb negprot commands, not reading the response */
2974 static bool run_negprot_nowait(int dummy)
2976 struct tevent_context *ev;
2977 int i;
2978 struct cli_state *cli;
2979 bool correct = True;
2981 printf("starting negprot nowait test\n");
2983 ev = samba_tevent_context_init(talloc_tos());
2984 if (ev == NULL) {
2985 return false;
2988 if (!(cli = open_nbt_connection())) {
2989 TALLOC_FREE(ev);
2990 return False;
2993 for (i=0;i<50000;i++) {
2994 struct tevent_req *req;
2996 req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
2997 PROTOCOL_CORE, PROTOCOL_NT1);
2998 if (req == NULL) {
2999 TALLOC_FREE(ev);
3000 return false;
3002 if (!tevent_req_poll(req, ev)) {
3003 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3004 strerror(errno));
3005 TALLOC_FREE(ev);
3006 return false;
3008 TALLOC_FREE(req);
3011 if (torture_close_connection(cli)) {
3012 correct = False;
3015 printf("finished negprot nowait test\n");
3017 return correct;
3020 /* send smb negprot commands, not reading the response */
3021 static bool run_bad_nbt_session(int dummy)
3023 struct nmb_name called, calling;
3024 struct sockaddr_storage ss;
3025 NTSTATUS status;
3026 int fd;
3027 bool ret;
3029 printf("starting bad nbt session test\n");
3031 make_nmb_name(&calling, myname, 0x0);
3032 make_nmb_name(&called , host, 0x20);
3034 if (!resolve_name(host, &ss, 0x20, true)) {
3035 d_fprintf(stderr, "Could not resolve name %s\n", host);
3036 return false;
3039 status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3040 if (!NT_STATUS_IS_OK(status)) {
3041 d_fprintf(stderr, "open_socket_out failed: %s\n",
3042 nt_errstr(status));
3043 return false;
3046 ret = cli_bad_session_request(fd, &calling, &called);
3047 close(fd);
3048 if (!ret) {
3049 d_fprintf(stderr, "open_socket_out failed: %s\n",
3050 nt_errstr(status));
3051 return false;
3054 printf("finished bad nbt session test\n");
3055 return true;
3058 /* send random IPC commands */
3059 static bool run_randomipc(int dummy)
3061 char *rparam = NULL;
3062 char *rdata = NULL;
3063 unsigned int rdrcnt,rprcnt;
3064 char param[1024];
3065 int api, param_len, i;
3066 struct cli_state *cli;
3067 bool correct = True;
3068 int count = 50000;
3070 printf("starting random ipc test\n");
3072 if (!torture_open_connection(&cli, 0)) {
3073 return False;
3076 for (i=0;i<count;i++) {
3077 api = sys_random() % 500;
3078 param_len = (sys_random() % 64);
3080 rand_buf(param, param_len);
3082 SSVAL(param,0,api);
3084 cli_api(cli,
3085 param, param_len, 8,
3086 NULL, 0, CLI_BUFFER_SIZE,
3087 &rparam, &rprcnt,
3088 &rdata, &rdrcnt);
3089 if (i % 100 == 0) {
3090 printf("%d/%d\r", i,count);
3093 printf("%d/%d\n", i, count);
3095 if (!torture_close_connection(cli)) {
3096 correct = False;
3099 SAFE_FREE(rparam);
3100 SAFE_FREE(rdata);
3102 printf("finished random ipc test\n");
3104 return correct;
3109 static void browse_callback(const char *sname, uint32_t stype,
3110 const char *comment, void *state)
3112 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3118 This test checks the browse list code
3121 static bool run_browsetest(int dummy)
3123 static struct cli_state *cli;
3124 bool correct = True;
3126 printf("starting browse test\n");
3128 if (!torture_open_connection(&cli, 0)) {
3129 return False;
3132 printf("domain list:\n");
3133 cli_NetServerEnum(cli, cli->server_domain,
3134 SV_TYPE_DOMAIN_ENUM,
3135 browse_callback, NULL);
3137 printf("machine list:\n");
3138 cli_NetServerEnum(cli, cli->server_domain,
3139 SV_TYPE_ALL,
3140 browse_callback, NULL);
3142 if (!torture_close_connection(cli)) {
3143 correct = False;
3146 printf("browse test finished\n");
3148 return correct;
3154 This checks how the getatr calls works
3156 static bool run_attrtest(int dummy)
3158 struct cli_state *cli;
3159 uint16_t fnum;
3160 time_t t, t2;
3161 const char *fname = "\\attrib123456789.tst";
3162 bool correct = True;
3163 NTSTATUS status;
3165 printf("starting attrib test\n");
3167 if (!torture_open_connection(&cli, 0)) {
3168 return False;
3171 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3172 cli_openx(cli, fname,
3173 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3174 cli_close(cli, fnum);
3176 status = cli_getatr(cli, fname, NULL, NULL, &t);
3177 if (!NT_STATUS_IS_OK(status)) {
3178 printf("getatr failed (%s)\n", nt_errstr(status));
3179 correct = False;
3182 if (abs(t - time(NULL)) > 60*60*24*10) {
3183 printf("ERROR: SMBgetatr bug. time is %s",
3184 ctime(&t));
3185 t = time(NULL);
3186 correct = True;
3189 t2 = t-60*60*24; /* 1 day ago */
3191 status = cli_setatr(cli, fname, 0, t2);
3192 if (!NT_STATUS_IS_OK(status)) {
3193 printf("setatr failed (%s)\n", nt_errstr(status));
3194 correct = True;
3197 status = cli_getatr(cli, fname, NULL, NULL, &t);
3198 if (!NT_STATUS_IS_OK(status)) {
3199 printf("getatr failed (%s)\n", nt_errstr(status));
3200 correct = True;
3203 if (t != t2) {
3204 printf("ERROR: getatr/setatr bug. times are\n%s",
3205 ctime(&t));
3206 printf("%s", ctime(&t2));
3207 correct = True;
3210 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3212 if (!torture_close_connection(cli)) {
3213 correct = False;
3216 printf("attrib test finished\n");
3218 return correct;
3223 This checks a couple of trans2 calls
3225 static bool run_trans2test(int dummy)
3227 struct cli_state *cli;
3228 uint16_t fnum;
3229 off_t size;
3230 time_t c_time, a_time, m_time;
3231 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3232 const char *fname = "\\trans2.tst";
3233 const char *dname = "\\trans2";
3234 const char *fname2 = "\\trans2\\trans2.tst";
3235 char *pname;
3236 bool correct = True;
3237 NTSTATUS status;
3238 uint32_t fs_attr;
3240 printf("starting trans2 test\n");
3242 if (!torture_open_connection(&cli, 0)) {
3243 return False;
3246 status = cli_get_fs_attr_info(cli, &fs_attr);
3247 if (!NT_STATUS_IS_OK(status)) {
3248 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3249 nt_errstr(status));
3250 correct = false;
3253 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3254 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3255 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3256 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3257 if (!NT_STATUS_IS_OK(status)) {
3258 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3259 correct = False;
3262 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3263 if (!NT_STATUS_IS_OK(status)) {
3264 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3265 correct = False;
3267 else if (strcmp(pname, fname)) {
3268 printf("qfilename gave different name? [%s] [%s]\n",
3269 fname, pname);
3270 correct = False;
3273 cli_close(cli, fnum);
3275 sleep(2);
3277 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3278 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3279 &fnum);
3280 if (!NT_STATUS_IS_OK(status)) {
3281 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3282 return False;
3284 cli_close(cli, fnum);
3286 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3287 NULL);
3288 if (!NT_STATUS_IS_OK(status)) {
3289 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3290 correct = False;
3291 } else {
3292 time_t t = time(NULL);
3294 if (c_time != m_time) {
3295 printf("create time=%s", ctime(&c_time));
3296 printf("modify time=%s", ctime(&m_time));
3297 printf("This system appears to have sticky create times\n");
3299 if ((abs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
3300 printf("access time=%s", ctime(&a_time));
3301 printf("This system appears to set a midnight access time\n");
3302 correct = False;
3305 if (abs(m_time - t) > 60*60*24*7) {
3306 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3307 correct = False;
3312 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3313 cli_openx(cli, fname,
3314 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3315 cli_close(cli, fnum);
3316 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3317 &m_time_ts, &size, NULL, NULL);
3318 if (!NT_STATUS_IS_OK(status)) {
3319 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3320 correct = False;
3321 } else {
3322 if (w_time_ts.tv_sec < 60*60*24*2) {
3323 printf("write time=%s", ctime(&w_time_ts.tv_sec));
3324 printf("This system appears to set a initial 0 write time\n");
3325 correct = False;
3329 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3332 /* check if the server updates the directory modification time
3333 when creating a new file */
3334 status = cli_mkdir(cli, dname);
3335 if (!NT_STATUS_IS_OK(status)) {
3336 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3337 correct = False;
3339 sleep(3);
3340 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3341 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3342 if (!NT_STATUS_IS_OK(status)) {
3343 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3344 correct = False;
3347 cli_openx(cli, fname2,
3348 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3349 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3350 cli_close(cli, fnum);
3351 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3352 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3353 if (!NT_STATUS_IS_OK(status)) {
3354 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3355 correct = False;
3356 } else {
3357 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3358 == 0) {
3359 printf("This system does not update directory modification times\n");
3360 correct = False;
3363 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3364 cli_rmdir(cli, dname);
3366 if (!torture_close_connection(cli)) {
3367 correct = False;
3370 printf("trans2 test finished\n");
3372 return correct;
3376 This checks new W2K calls.
3379 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3381 uint8_t *buf = NULL;
3382 uint32_t len;
3383 NTSTATUS status;
3385 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3386 CLI_BUFFER_SIZE, NULL, &buf, &len);
3387 if (!NT_STATUS_IS_OK(status)) {
3388 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3389 nt_errstr(status));
3390 } else {
3391 printf("qfileinfo: level %d, len = %u\n", level, len);
3392 dump_data(0, (uint8_t *)buf, len);
3393 printf("\n");
3395 TALLOC_FREE(buf);
3396 return status;
3399 static bool run_w2ktest(int dummy)
3401 struct cli_state *cli;
3402 uint16_t fnum;
3403 const char *fname = "\\w2ktest\\w2k.tst";
3404 int level;
3405 bool correct = True;
3407 printf("starting w2k test\n");
3409 if (!torture_open_connection(&cli, 0)) {
3410 return False;
3413 cli_openx(cli, fname,
3414 O_RDWR | O_CREAT , DENY_NONE, &fnum);
3416 for (level = 1004; level < 1040; level++) {
3417 new_trans(cli, fnum, level);
3420 cli_close(cli, fnum);
3422 if (!torture_close_connection(cli)) {
3423 correct = False;
3426 printf("w2k test finished\n");
3428 return correct;
3433 this is a harness for some oplock tests
3435 static bool run_oplock1(int dummy)
3437 struct cli_state *cli1;
3438 const char *fname = "\\lockt1.lck";
3439 uint16_t fnum1;
3440 bool correct = True;
3441 NTSTATUS status;
3443 printf("starting oplock test 1\n");
3445 if (!torture_open_connection(&cli1, 0)) {
3446 return False;
3449 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3451 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3453 cli1->use_oplocks = True;
3455 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3456 &fnum1);
3457 if (!NT_STATUS_IS_OK(status)) {
3458 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3459 return False;
3462 cli1->use_oplocks = False;
3464 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3465 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3467 status = cli_close(cli1, fnum1);
3468 if (!NT_STATUS_IS_OK(status)) {
3469 printf("close2 failed (%s)\n", nt_errstr(status));
3470 return False;
3473 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3474 if (!NT_STATUS_IS_OK(status)) {
3475 printf("unlink failed (%s)\n", nt_errstr(status));
3476 return False;
3479 if (!torture_close_connection(cli1)) {
3480 correct = False;
3483 printf("finished oplock test 1\n");
3485 return correct;
3488 static bool run_oplock2(int dummy)
3490 struct cli_state *cli1, *cli2;
3491 const char *fname = "\\lockt2.lck";
3492 uint16_t fnum1, fnum2;
3493 int saved_use_oplocks = use_oplocks;
3494 char buf[4];
3495 bool correct = True;
3496 volatile bool *shared_correct;
3497 size_t nread;
3498 NTSTATUS status;
3500 shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
3501 *shared_correct = True;
3503 use_level_II_oplocks = True;
3504 use_oplocks = True;
3506 printf("starting oplock test 2\n");
3508 if (!torture_open_connection(&cli1, 0)) {
3509 use_level_II_oplocks = False;
3510 use_oplocks = saved_use_oplocks;
3511 return False;
3514 if (!torture_open_connection(&cli2, 1)) {
3515 use_level_II_oplocks = False;
3516 use_oplocks = saved_use_oplocks;
3517 return False;
3520 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3522 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3523 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3525 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3526 &fnum1);
3527 if (!NT_STATUS_IS_OK(status)) {
3528 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3529 return False;
3532 /* Don't need the globals any more. */
3533 use_level_II_oplocks = False;
3534 use_oplocks = saved_use_oplocks;
3536 if (fork() == 0) {
3537 /* Child code */
3538 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3539 if (!NT_STATUS_IS_OK(status)) {
3540 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3541 *shared_correct = False;
3542 exit(0);
3545 sleep(2);
3547 status = cli_close(cli2, fnum2);
3548 if (!NT_STATUS_IS_OK(status)) {
3549 printf("close2 failed (%s)\n", nt_errstr(status));
3550 *shared_correct = False;
3553 exit(0);
3556 sleep(2);
3558 /* Ensure cli1 processes the break. Empty file should always return 0
3559 * bytes. */
3560 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
3561 if (!NT_STATUS_IS_OK(status)) {
3562 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
3563 correct = false;
3564 } else if (nread != 0) {
3565 printf("read on empty fnum1 failed. recv %ld expected %d\n",
3566 (unsigned long)nread, 0);
3567 correct = false;
3570 /* Should now be at level II. */
3571 /* Test if sending a write locks causes a break to none. */
3572 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3573 if (!NT_STATUS_IS_OK(status)) {
3574 printf("lock failed (%s)\n", nt_errstr(status));
3575 correct = False;
3578 cli_unlock(cli1, fnum1, 0, 4);
3580 sleep(2);
3582 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3583 if (!NT_STATUS_IS_OK(status)) {
3584 printf("lock failed (%s)\n", nt_errstr(status));
3585 correct = False;
3588 cli_unlock(cli1, fnum1, 0, 4);
3590 sleep(2);
3592 cli_read(cli1, fnum1, buf, 0, 4, NULL);
3594 status = cli_close(cli1, fnum1);
3595 if (!NT_STATUS_IS_OK(status)) {
3596 printf("close1 failed (%s)\n", nt_errstr(status));
3597 correct = False;
3600 sleep(4);
3602 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3603 if (!NT_STATUS_IS_OK(status)) {
3604 printf("unlink failed (%s)\n", nt_errstr(status));
3605 correct = False;
3608 if (!torture_close_connection(cli1)) {
3609 correct = False;
3612 if (!*shared_correct) {
3613 correct = False;
3616 printf("finished oplock test 2\n");
3618 return correct;
3621 struct oplock4_state {
3622 struct tevent_context *ev;
3623 struct cli_state *cli;
3624 bool *got_break;
3625 uint16_t *fnum2;
3628 static void oplock4_got_break(struct tevent_req *req);
3629 static void oplock4_got_open(struct tevent_req *req);
3631 static bool run_oplock4(int dummy)
3633 struct tevent_context *ev;
3634 struct cli_state *cli1, *cli2;
3635 struct tevent_req *oplock_req, *open_req;
3636 const char *fname = "\\lockt4.lck";
3637 const char *fname_ln = "\\lockt4_ln.lck";
3638 uint16_t fnum1, fnum2;
3639 int saved_use_oplocks = use_oplocks;
3640 NTSTATUS status;
3641 bool correct = true;
3643 bool got_break;
3645 struct oplock4_state *state;
3647 printf("starting oplock test 4\n");
3649 if (!torture_open_connection(&cli1, 0)) {
3650 use_level_II_oplocks = false;
3651 use_oplocks = saved_use_oplocks;
3652 return false;
3655 if (!torture_open_connection(&cli2, 1)) {
3656 use_level_II_oplocks = false;
3657 use_oplocks = saved_use_oplocks;
3658 return false;
3661 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3662 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3664 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3665 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3667 /* Create the file. */
3668 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3669 &fnum1);
3670 if (!NT_STATUS_IS_OK(status)) {
3671 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3672 return false;
3675 status = cli_close(cli1, fnum1);
3676 if (!NT_STATUS_IS_OK(status)) {
3677 printf("close1 failed (%s)\n", nt_errstr(status));
3678 return false;
3681 /* Now create a hardlink. */
3682 status = cli_nt_hardlink(cli1, fname, fname_ln);
3683 if (!NT_STATUS_IS_OK(status)) {
3684 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3685 return false;
3688 /* Prove that opening hardlinks cause deny modes to conflict. */
3689 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3690 if (!NT_STATUS_IS_OK(status)) {
3691 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3692 return false;
3695 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3696 if (NT_STATUS_IS_OK(status)) {
3697 printf("open of %s succeeded - should fail with sharing violation.\n",
3698 fname_ln);
3699 return false;
3702 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3703 printf("open of %s should fail with sharing violation. Got %s\n",
3704 fname_ln, nt_errstr(status));
3705 return false;
3708 status = cli_close(cli1, fnum1);
3709 if (!NT_STATUS_IS_OK(status)) {
3710 printf("close1 failed (%s)\n", nt_errstr(status));
3711 return false;
3714 cli1->use_oplocks = true;
3715 cli2->use_oplocks = true;
3717 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3718 if (!NT_STATUS_IS_OK(status)) {
3719 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3720 return false;
3723 ev = samba_tevent_context_init(talloc_tos());
3724 if (ev == NULL) {
3725 printf("tevent_context_init failed\n");
3726 return false;
3729 state = talloc(ev, struct oplock4_state);
3730 if (state == NULL) {
3731 printf("talloc failed\n");
3732 return false;
3734 state->ev = ev;
3735 state->cli = cli1;
3736 state->got_break = &got_break;
3737 state->fnum2 = &fnum2;
3739 oplock_req = cli_smb_oplock_break_waiter_send(
3740 talloc_tos(), ev, cli1);
3741 if (oplock_req == NULL) {
3742 printf("cli_smb_oplock_break_waiter_send failed\n");
3743 return false;
3745 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3747 open_req = cli_openx_send(
3748 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3749 if (open_req == NULL) {
3750 printf("cli_openx_send failed\n");
3751 return false;
3753 tevent_req_set_callback(open_req, oplock4_got_open, state);
3755 got_break = false;
3756 fnum2 = 0xffff;
3758 while (!got_break || fnum2 == 0xffff) {
3759 int ret;
3760 ret = tevent_loop_once(ev);
3761 if (ret == -1) {
3762 printf("tevent_loop_once failed: %s\n",
3763 strerror(errno));
3764 return false;
3768 status = cli_close(cli2, fnum2);
3769 if (!NT_STATUS_IS_OK(status)) {
3770 printf("close2 failed (%s)\n", nt_errstr(status));
3771 correct = false;
3774 status = cli_close(cli1, fnum1);
3775 if (!NT_STATUS_IS_OK(status)) {
3776 printf("close1 failed (%s)\n", nt_errstr(status));
3777 correct = false;
3780 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3781 if (!NT_STATUS_IS_OK(status)) {
3782 printf("unlink failed (%s)\n", nt_errstr(status));
3783 correct = false;
3786 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3787 if (!NT_STATUS_IS_OK(status)) {
3788 printf("unlink failed (%s)\n", nt_errstr(status));
3789 correct = false;
3792 if (!torture_close_connection(cli1)) {
3793 correct = false;
3796 if (!got_break) {
3797 correct = false;
3800 printf("finished oplock test 4\n");
3802 return correct;
3805 static void oplock4_got_break(struct tevent_req *req)
3807 struct oplock4_state *state = tevent_req_callback_data(
3808 req, struct oplock4_state);
3809 uint16_t fnum;
3810 uint8_t level;
3811 NTSTATUS status;
3813 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3814 TALLOC_FREE(req);
3815 if (!NT_STATUS_IS_OK(status)) {
3816 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3817 nt_errstr(status));
3818 return;
3820 *state->got_break = true;
3822 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3823 NO_OPLOCK);
3824 if (req == NULL) {
3825 printf("cli_oplock_ack_send failed\n");
3826 return;
3830 static void oplock4_got_open(struct tevent_req *req)
3832 struct oplock4_state *state = tevent_req_callback_data(
3833 req, struct oplock4_state);
3834 NTSTATUS status;
3836 status = cli_openx_recv(req, state->fnum2);
3837 if (!NT_STATUS_IS_OK(status)) {
3838 printf("cli_openx_recv returned %s\n", nt_errstr(status));
3839 *state->fnum2 = 0xffff;
3844 Test delete on close semantics.
3846 static bool run_deletetest(int dummy)
3848 struct cli_state *cli1 = NULL;
3849 struct cli_state *cli2 = NULL;
3850 const char *fname = "\\delete.file";
3851 uint16_t fnum1 = (uint16_t)-1;
3852 uint16_t fnum2 = (uint16_t)-1;
3853 bool correct = false;
3854 NTSTATUS status;
3856 printf("starting delete test\n");
3858 if (!torture_open_connection(&cli1, 0)) {
3859 return False;
3862 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3864 /* Test 1 - this should delete the file on close. */
3866 cli_setatr(cli1, fname, 0, 0);
3867 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3869 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3870 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3871 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
3872 if (!NT_STATUS_IS_OK(status)) {
3873 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3874 goto fail;
3877 status = cli_close(cli1, fnum1);
3878 if (!NT_STATUS_IS_OK(status)) {
3879 printf("[1] close failed (%s)\n", nt_errstr(status));
3880 goto fail;
3883 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3884 if (NT_STATUS_IS_OK(status)) {
3885 printf("[1] open of %s succeeded (should fail)\n", fname);
3886 goto fail;
3889 printf("first delete on close test succeeded.\n");
3891 /* Test 2 - this should delete the file on close. */
3893 cli_setatr(cli1, fname, 0, 0);
3894 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3896 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3897 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3898 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
3899 if (!NT_STATUS_IS_OK(status)) {
3900 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3901 goto fail;
3904 status = cli_nt_delete_on_close(cli1, fnum1, true);
3905 if (!NT_STATUS_IS_OK(status)) {
3906 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3907 goto fail;
3910 status = cli_close(cli1, fnum1);
3911 if (!NT_STATUS_IS_OK(status)) {
3912 printf("[2] close failed (%s)\n", nt_errstr(status));
3913 goto fail;
3916 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
3917 if (NT_STATUS_IS_OK(status)) {
3918 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3919 status = cli_close(cli1, fnum1);
3920 if (!NT_STATUS_IS_OK(status)) {
3921 printf("[2] close failed (%s)\n", nt_errstr(status));
3923 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3924 goto fail;
3927 printf("second delete on close test succeeded.\n");
3929 /* Test 3 - ... */
3930 cli_setatr(cli1, fname, 0, 0);
3931 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3933 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3934 FILE_ATTRIBUTE_NORMAL,
3935 FILE_SHARE_READ|FILE_SHARE_WRITE,
3936 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
3937 if (!NT_STATUS_IS_OK(status)) {
3938 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
3939 goto fail;
3942 /* This should fail with a sharing violation - open for delete is only compatible
3943 with SHARE_DELETE. */
3945 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3946 FILE_ATTRIBUTE_NORMAL,
3947 FILE_SHARE_READ|FILE_SHARE_WRITE,
3948 FILE_OPEN, 0, 0, &fnum2, NULL);
3949 if (NT_STATUS_IS_OK(status)) {
3950 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
3951 goto fail;
3954 /* This should succeed. */
3955 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3956 FILE_ATTRIBUTE_NORMAL,
3957 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3958 FILE_OPEN, 0, 0, &fnum2, NULL);
3959 if (!NT_STATUS_IS_OK(status)) {
3960 printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
3961 goto fail;
3964 status = cli_nt_delete_on_close(cli1, fnum1, true);
3965 if (!NT_STATUS_IS_OK(status)) {
3966 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
3967 goto fail;
3970 status = cli_close(cli1, fnum1);
3971 if (!NT_STATUS_IS_OK(status)) {
3972 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
3973 goto fail;
3976 status = cli_close(cli1, fnum2);
3977 if (!NT_STATUS_IS_OK(status)) {
3978 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
3979 goto fail;
3982 /* This should fail - file should no longer be there. */
3984 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
3985 if (NT_STATUS_IS_OK(status)) {
3986 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
3987 status = cli_close(cli1, fnum1);
3988 if (!NT_STATUS_IS_OK(status)) {
3989 printf("[3] close failed (%s)\n", nt_errstr(status));
3991 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3992 goto fail;
3995 printf("third delete on close test succeeded.\n");
3997 /* Test 4 ... */
3998 cli_setatr(cli1, fname, 0, 0);
3999 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4001 status = cli_ntcreate(cli1, fname, 0,
4002 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4003 FILE_ATTRIBUTE_NORMAL,
4004 FILE_SHARE_READ|FILE_SHARE_WRITE,
4005 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4006 if (!NT_STATUS_IS_OK(status)) {
4007 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4008 goto fail;
4011 /* This should succeed. */
4012 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4013 FILE_ATTRIBUTE_NORMAL,
4014 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4015 FILE_OPEN, 0, 0, &fnum2, NULL);
4016 if (!NT_STATUS_IS_OK(status)) {
4017 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4018 goto fail;
4021 status = cli_close(cli1, fnum2);
4022 if (!NT_STATUS_IS_OK(status)) {
4023 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4024 goto fail;
4027 status = cli_nt_delete_on_close(cli1, fnum1, true);
4028 if (!NT_STATUS_IS_OK(status)) {
4029 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4030 goto fail;
4033 /* This should fail - no more opens once delete on close set. */
4034 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4035 FILE_ATTRIBUTE_NORMAL,
4036 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4037 FILE_OPEN, 0, 0, &fnum2, NULL);
4038 if (NT_STATUS_IS_OK(status)) {
4039 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
4040 goto fail;
4043 status = cli_close(cli1, fnum1);
4044 if (!NT_STATUS_IS_OK(status)) {
4045 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4046 goto fail;
4049 printf("fourth delete on close test succeeded.\n");
4051 /* Test 5 ... */
4052 cli_setatr(cli1, fname, 0, 0);
4053 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4055 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4056 if (!NT_STATUS_IS_OK(status)) {
4057 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4058 goto fail;
4061 /* This should fail - only allowed on NT opens with DELETE access. */
4063 status = cli_nt_delete_on_close(cli1, fnum1, true);
4064 if (NT_STATUS_IS_OK(status)) {
4065 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4066 goto fail;
4069 status = cli_close(cli1, fnum1);
4070 if (!NT_STATUS_IS_OK(status)) {
4071 printf("[5] close failed (%s)\n", nt_errstr(status));
4072 goto fail;
4075 printf("fifth delete on close test succeeded.\n");
4077 /* Test 6 ... */
4078 cli_setatr(cli1, fname, 0, 0);
4079 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4081 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4082 FILE_ATTRIBUTE_NORMAL,
4083 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4084 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4085 if (!NT_STATUS_IS_OK(status)) {
4086 printf("[6] open of %s failed (%s)\n", fname,
4087 nt_errstr(status));
4088 goto fail;
4091 /* This should fail - only allowed on NT opens with DELETE access. */
4093 status = cli_nt_delete_on_close(cli1, fnum1, true);
4094 if (NT_STATUS_IS_OK(status)) {
4095 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4096 goto fail;
4099 status = cli_close(cli1, fnum1);
4100 if (!NT_STATUS_IS_OK(status)) {
4101 printf("[6] close failed (%s)\n", nt_errstr(status));
4102 goto fail;
4105 printf("sixth delete on close test succeeded.\n");
4107 /* Test 7 ... */
4108 cli_setatr(cli1, fname, 0, 0);
4109 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4111 status = cli_ntcreate(cli1, fname, 0,
4112 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4113 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4114 0, 0, &fnum1, NULL);
4115 if (!NT_STATUS_IS_OK(status)) {
4116 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4117 goto fail;
4120 status = cli_nt_delete_on_close(cli1, fnum1, true);
4121 if (!NT_STATUS_IS_OK(status)) {
4122 printf("[7] setting delete_on_close on file failed !\n");
4123 goto fail;
4126 status = cli_nt_delete_on_close(cli1, fnum1, false);
4127 if (!NT_STATUS_IS_OK(status)) {
4128 printf("[7] unsetting delete_on_close on file failed !\n");
4129 goto fail;
4132 status = cli_close(cli1, fnum1);
4133 if (!NT_STATUS_IS_OK(status)) {
4134 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
4135 goto fail;
4138 /* This next open should succeed - we reset the flag. */
4139 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4140 if (!NT_STATUS_IS_OK(status)) {
4141 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4142 goto fail;
4145 status = cli_close(cli1, fnum1);
4146 if (!NT_STATUS_IS_OK(status)) {
4147 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4148 goto fail;
4151 printf("seventh delete on close test succeeded.\n");
4153 /* Test 8 ... */
4154 cli_setatr(cli1, fname, 0, 0);
4155 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4157 if (!torture_open_connection(&cli2, 1)) {
4158 printf("[8] failed to open second connection.\n");
4159 goto fail;
4162 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4164 status = cli_ntcreate(cli1, fname, 0,
4165 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4166 FILE_ATTRIBUTE_NORMAL,
4167 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4168 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4169 if (!NT_STATUS_IS_OK(status)) {
4170 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4171 goto fail;
4174 status = cli_ntcreate(cli2, fname, 0,
4175 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4176 FILE_ATTRIBUTE_NORMAL,
4177 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4178 FILE_OPEN, 0, 0, &fnum2, NULL);
4179 if (!NT_STATUS_IS_OK(status)) {
4180 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4181 goto fail;
4184 status = cli_nt_delete_on_close(cli1, fnum1, true);
4185 if (!NT_STATUS_IS_OK(status)) {
4186 printf("[8] setting delete_on_close on file failed !\n");
4187 goto fail;
4190 status = cli_close(cli1, fnum1);
4191 if (!NT_STATUS_IS_OK(status)) {
4192 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4193 goto fail;
4196 status = cli_close(cli2, fnum2);
4197 if (!NT_STATUS_IS_OK(status)) {
4198 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4199 goto fail;
4202 /* This should fail.. */
4203 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4204 if (NT_STATUS_IS_OK(status)) {
4205 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4206 goto fail;
4209 printf("eighth delete on close test succeeded.\n");
4211 /* Test 9 ... */
4213 /* This should fail - we need to set DELETE_ACCESS. */
4214 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4215 FILE_ATTRIBUTE_NORMAL,
4216 FILE_SHARE_NONE,
4217 FILE_OVERWRITE_IF,
4218 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4219 if (NT_STATUS_IS_OK(status)) {
4220 printf("[9] open of %s succeeded should have failed!\n", fname);
4221 goto fail;
4224 printf("ninth delete on close test succeeded.\n");
4226 /* Test 10 ... */
4228 status = cli_ntcreate(cli1, fname, 0,
4229 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4230 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4231 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4232 0, &fnum1, NULL);
4233 if (!NT_STATUS_IS_OK(status)) {
4234 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4235 goto fail;
4238 /* This should delete the file. */
4239 status = cli_close(cli1, fnum1);
4240 if (!NT_STATUS_IS_OK(status)) {
4241 printf("[10] close failed (%s)\n", nt_errstr(status));
4242 goto fail;
4245 /* This should fail.. */
4246 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4247 if (NT_STATUS_IS_OK(status)) {
4248 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4249 goto fail;
4252 printf("tenth delete on close test succeeded.\n");
4254 /* Test 11 ... */
4256 cli_setatr(cli1, fname, 0, 0);
4257 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4259 /* Can we open a read-only file with delete access? */
4261 /* Create a readonly file. */
4262 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4263 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4264 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4265 if (!NT_STATUS_IS_OK(status)) {
4266 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4267 goto fail;
4270 status = cli_close(cli1, fnum1);
4271 if (!NT_STATUS_IS_OK(status)) {
4272 printf("[11] close failed (%s)\n", nt_errstr(status));
4273 goto fail;
4276 /* Now try open for delete access. */
4277 status = cli_ntcreate(cli1, fname, 0,
4278 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4280 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4281 FILE_OPEN, 0, 0, &fnum1, NULL);
4282 if (!NT_STATUS_IS_OK(status)) {
4283 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
4284 goto fail;
4287 cli_close(cli1, fnum1);
4289 printf("eleventh delete on close test succeeded.\n");
4292 * Test 12
4293 * like test 4 but with initial delete on close
4296 cli_setatr(cli1, fname, 0, 0);
4297 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4299 status = cli_ntcreate(cli1, fname, 0,
4300 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4301 FILE_ATTRIBUTE_NORMAL,
4302 FILE_SHARE_READ|FILE_SHARE_WRITE,
4303 FILE_OVERWRITE_IF,
4304 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4305 if (!NT_STATUS_IS_OK(status)) {
4306 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4307 goto fail;
4310 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4311 FILE_ATTRIBUTE_NORMAL,
4312 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4313 FILE_OPEN, 0, 0, &fnum2, NULL);
4314 if (!NT_STATUS_IS_OK(status)) {
4315 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
4316 goto fail;
4319 status = cli_close(cli1, fnum2);
4320 if (!NT_STATUS_IS_OK(status)) {
4321 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
4322 goto fail;
4325 status = cli_nt_delete_on_close(cli1, fnum1, true);
4326 if (!NT_STATUS_IS_OK(status)) {
4327 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
4328 goto fail;
4331 /* This should fail - no more opens once delete on close set. */
4332 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4333 FILE_ATTRIBUTE_NORMAL,
4334 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4335 FILE_OPEN, 0, 0, &fnum2, NULL);
4336 if (NT_STATUS_IS_OK(status)) {
4337 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
4338 goto fail;
4341 status = cli_nt_delete_on_close(cli1, fnum1, false);
4342 if (!NT_STATUS_IS_OK(status)) {
4343 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
4344 goto fail;
4347 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4348 FILE_ATTRIBUTE_NORMAL,
4349 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4350 FILE_OPEN, 0, 0, &fnum2, NULL);
4351 if (!NT_STATUS_IS_OK(status)) {
4352 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
4353 goto fail;
4356 status = cli_close(cli1, fnum2);
4357 if (!NT_STATUS_IS_OK(status)) {
4358 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
4359 goto fail;
4362 status = cli_close(cli1, fnum1);
4363 if (!NT_STATUS_IS_OK(status)) {
4364 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
4365 goto fail;
4369 * setting delete on close on the handle does
4370 * not unset the initial delete on close...
4372 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4373 FILE_ATTRIBUTE_NORMAL,
4374 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4375 FILE_OPEN, 0, 0, &fnum2, NULL);
4376 if (NT_STATUS_IS_OK(status)) {
4377 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
4378 goto fail;
4379 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4380 printf("ntcreate returned %s, expected "
4381 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
4382 nt_errstr(status));
4383 goto fail;
4386 printf("twelfth delete on close test succeeded.\n");
4389 printf("finished delete test\n");
4391 correct = true;
4393 fail:
4394 /* FIXME: This will crash if we aborted before cli2 got
4395 * intialized, because these functions don't handle
4396 * uninitialized connections. */
4398 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4399 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4400 cli_setatr(cli1, fname, 0, 0);
4401 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4403 if (cli1 && !torture_close_connection(cli1)) {
4404 correct = False;
4406 if (cli2 && !torture_close_connection(cli2)) {
4407 correct = False;
4409 return correct;
4412 static bool run_deletetest_ln(int dummy)
4414 struct cli_state *cli;
4415 const char *fname = "\\delete1";
4416 const char *fname_ln = "\\delete1_ln";
4417 uint16_t fnum;
4418 uint16_t fnum1;
4419 NTSTATUS status;
4420 bool correct = true;
4421 time_t t;
4423 printf("starting deletetest-ln\n");
4425 if (!torture_open_connection(&cli, 0)) {
4426 return false;
4429 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4430 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4432 smbXcli_conn_set_sockopt(cli->conn, sockops);
4434 /* Create the file. */
4435 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4436 if (!NT_STATUS_IS_OK(status)) {
4437 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4438 return false;
4441 status = cli_close(cli, fnum);
4442 if (!NT_STATUS_IS_OK(status)) {
4443 printf("close1 failed (%s)\n", nt_errstr(status));
4444 return false;
4447 /* Now create a hardlink. */
4448 status = cli_nt_hardlink(cli, fname, fname_ln);
4449 if (!NT_STATUS_IS_OK(status)) {
4450 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4451 return false;
4454 /* Open the original file. */
4455 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4456 FILE_ATTRIBUTE_NORMAL,
4457 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4458 FILE_OPEN_IF, 0, 0, &fnum, NULL);
4459 if (!NT_STATUS_IS_OK(status)) {
4460 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4461 return false;
4464 /* Unlink the hard link path. */
4465 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4466 FILE_ATTRIBUTE_NORMAL,
4467 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4468 FILE_OPEN_IF, 0, 0, &fnum1, NULL);
4469 if (!NT_STATUS_IS_OK(status)) {
4470 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4471 return false;
4473 status = cli_nt_delete_on_close(cli, fnum1, true);
4474 if (!NT_STATUS_IS_OK(status)) {
4475 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4476 __location__, fname_ln, nt_errstr(status));
4477 return false;
4480 status = cli_close(cli, fnum1);
4481 if (!NT_STATUS_IS_OK(status)) {
4482 printf("close %s failed (%s)\n",
4483 fname_ln, nt_errstr(status));
4484 return false;
4487 status = cli_close(cli, fnum);
4488 if (!NT_STATUS_IS_OK(status)) {
4489 printf("close %s failed (%s)\n",
4490 fname, nt_errstr(status));
4491 return false;
4494 /* Ensure the original file is still there. */
4495 status = cli_getatr(cli, fname, NULL, NULL, &t);
4496 if (!NT_STATUS_IS_OK(status)) {
4497 printf("%s getatr on file %s failed (%s)\n",
4498 __location__,
4499 fname,
4500 nt_errstr(status));
4501 correct = False;
4504 /* Ensure the link path is gone. */
4505 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4506 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4507 printf("%s, getatr for file %s returned wrong error code %s "
4508 "- should have been deleted\n",
4509 __location__,
4510 fname_ln, nt_errstr(status));
4511 correct = False;
4514 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4515 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4517 if (!torture_close_connection(cli)) {
4518 correct = false;
4521 printf("finished deletetest-ln\n");
4523 return correct;
4527 print out server properties
4529 static bool run_properties(int dummy)
4531 struct cli_state *cli;
4532 bool correct = True;
4534 printf("starting properties test\n");
4536 ZERO_STRUCT(cli);
4538 if (!torture_open_connection(&cli, 0)) {
4539 return False;
4542 smbXcli_conn_set_sockopt(cli->conn, sockops);
4544 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
4546 if (!torture_close_connection(cli)) {
4547 correct = False;
4550 return correct;
4555 /* FIRST_DESIRED_ACCESS 0xf019f */
4556 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4557 FILE_READ_EA| /* 0xf */ \
4558 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
4559 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
4560 DELETE_ACCESS|READ_CONTROL_ACCESS|\
4561 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
4562 /* SECOND_DESIRED_ACCESS 0xe0080 */
4563 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4564 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4565 WRITE_OWNER_ACCESS /* 0xe0000 */
4567 #if 0
4568 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4569 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4570 FILE_READ_DATA|\
4571 WRITE_OWNER_ACCESS /* */
4572 #endif
4575 Test ntcreate calls made by xcopy
4577 static bool run_xcopy(int dummy)
4579 static struct cli_state *cli1;
4580 const char *fname = "\\test.txt";
4581 bool correct = True;
4582 uint16_t fnum1, fnum2;
4583 NTSTATUS status;
4585 printf("starting xcopy test\n");
4587 if (!torture_open_connection(&cli1, 0)) {
4588 return False;
4591 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4592 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4593 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
4594 if (!NT_STATUS_IS_OK(status)) {
4595 printf("First open failed - %s\n", nt_errstr(status));
4596 return False;
4599 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4600 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4601 FILE_OPEN, 0x200000, 0, &fnum2, NULL);
4602 if (!NT_STATUS_IS_OK(status)) {
4603 printf("second open failed - %s\n", nt_errstr(status));
4604 return False;
4607 if (!torture_close_connection(cli1)) {
4608 correct = False;
4611 return correct;
4615 Test rename on files open with share delete and no share delete.
4617 static bool run_rename(int dummy)
4619 static struct cli_state *cli1;
4620 const char *fname = "\\test.txt";
4621 const char *fname1 = "\\test1.txt";
4622 bool correct = True;
4623 uint16_t fnum1;
4624 uint16_t attr;
4625 NTSTATUS status;
4627 printf("starting rename test\n");
4629 if (!torture_open_connection(&cli1, 0)) {
4630 return False;
4633 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4634 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4636 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4637 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4638 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4639 if (!NT_STATUS_IS_OK(status)) {
4640 printf("First open failed - %s\n", nt_errstr(status));
4641 return False;
4644 status = cli_rename(cli1, fname, fname1);
4645 if (!NT_STATUS_IS_OK(status)) {
4646 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4647 } else {
4648 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4649 correct = False;
4652 status = cli_close(cli1, fnum1);
4653 if (!NT_STATUS_IS_OK(status)) {
4654 printf("close - 1 failed (%s)\n", nt_errstr(status));
4655 return False;
4658 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4659 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4660 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4661 #if 0
4662 FILE_SHARE_DELETE|FILE_SHARE_NONE,
4663 #else
4664 FILE_SHARE_DELETE|FILE_SHARE_READ,
4665 #endif
4666 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4667 if (!NT_STATUS_IS_OK(status)) {
4668 printf("Second open failed - %s\n", nt_errstr(status));
4669 return False;
4672 status = cli_rename(cli1, fname, fname1);
4673 if (!NT_STATUS_IS_OK(status)) {
4674 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4675 correct = False;
4676 } else {
4677 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4680 status = cli_close(cli1, fnum1);
4681 if (!NT_STATUS_IS_OK(status)) {
4682 printf("close - 2 failed (%s)\n", nt_errstr(status));
4683 return False;
4686 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4687 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4689 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4690 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4691 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4692 if (!NT_STATUS_IS_OK(status)) {
4693 printf("Third open failed - %s\n", nt_errstr(status));
4694 return False;
4698 #if 0
4700 uint16_t fnum2;
4702 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4703 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
4704 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4705 return False;
4707 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4708 printf("[8] setting delete_on_close on file failed !\n");
4709 return False;
4712 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4713 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4714 return False;
4717 #endif
4719 status = cli_rename(cli1, fname, fname1);
4720 if (!NT_STATUS_IS_OK(status)) {
4721 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4722 correct = False;
4723 } else {
4724 printf("Third rename succeeded (SHARE_NONE)\n");
4727 status = cli_close(cli1, fnum1);
4728 if (!NT_STATUS_IS_OK(status)) {
4729 printf("close - 3 failed (%s)\n", nt_errstr(status));
4730 return False;
4733 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4734 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4736 /*----*/
4738 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4739 FILE_ATTRIBUTE_NORMAL,
4740 FILE_SHARE_READ | FILE_SHARE_WRITE,
4741 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4742 if (!NT_STATUS_IS_OK(status)) {
4743 printf("Fourth open failed - %s\n", nt_errstr(status));
4744 return False;
4747 status = cli_rename(cli1, fname, fname1);
4748 if (!NT_STATUS_IS_OK(status)) {
4749 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4750 } else {
4751 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4752 correct = False;
4755 status = cli_close(cli1, fnum1);
4756 if (!NT_STATUS_IS_OK(status)) {
4757 printf("close - 4 failed (%s)\n", nt_errstr(status));
4758 return False;
4761 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4762 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4764 /*--*/
4766 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4767 FILE_ATTRIBUTE_NORMAL,
4768 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4769 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4770 if (!NT_STATUS_IS_OK(status)) {
4771 printf("Fifth open failed - %s\n", nt_errstr(status));
4772 return False;
4775 status = cli_rename(cli1, fname, fname1);
4776 if (!NT_STATUS_IS_OK(status)) {
4777 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4778 correct = False;
4779 } else {
4780 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4784 * Now check if the first name still exists ...
4787 /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4788 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4789 FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
4790 printf("Opening original file after rename of open file fails: %s\n",
4791 cli_errstr(cli1));
4793 else {
4794 printf("Opening original file after rename of open file works ...\n");
4795 (void)cli_close(cli1, fnum2);
4796 } */
4798 /*--*/
4799 status = cli_close(cli1, fnum1);
4800 if (!NT_STATUS_IS_OK(status)) {
4801 printf("close - 5 failed (%s)\n", nt_errstr(status));
4802 return False;
4805 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4806 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4807 if (!NT_STATUS_IS_OK(status)) {
4808 printf("getatr on file %s failed - %s ! \n",
4809 fname1, nt_errstr(status));
4810 correct = False;
4811 } else {
4812 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4813 printf("Renamed file %s has wrong attr 0x%x "
4814 "(should be 0x%x)\n",
4815 fname1,
4816 attr,
4817 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4818 correct = False;
4819 } else {
4820 printf("Renamed file %s has archive bit set\n", fname1);
4824 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4825 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4827 if (!torture_close_connection(cli1)) {
4828 correct = False;
4831 return correct;
4834 static bool run_pipe_number(int dummy)
4836 struct cli_state *cli1;
4837 const char *pipe_name = "\\SPOOLSS";
4838 uint16_t fnum;
4839 int num_pipes = 0;
4840 NTSTATUS status;
4842 printf("starting pipenumber test\n");
4843 if (!torture_open_connection(&cli1, 0)) {
4844 return False;
4847 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4848 while(1) {
4849 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
4850 FILE_ATTRIBUTE_NORMAL,
4851 FILE_SHARE_READ|FILE_SHARE_WRITE,
4852 FILE_OPEN_IF, 0, 0, &fnum, NULL);
4853 if (!NT_STATUS_IS_OK(status)) {
4854 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
4855 break;
4857 num_pipes++;
4858 printf("\r%6d", num_pipes);
4861 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4862 torture_close_connection(cli1);
4863 return True;
4867 Test open mode returns on read-only files.
4869 static bool run_opentest(int dummy)
4871 static struct cli_state *cli1;
4872 static struct cli_state *cli2;
4873 const char *fname = "\\readonly.file";
4874 uint16_t fnum1, fnum2;
4875 char buf[20];
4876 off_t fsize;
4877 bool correct = True;
4878 char *tmp_path;
4879 NTSTATUS status;
4881 printf("starting open test\n");
4883 if (!torture_open_connection(&cli1, 0)) {
4884 return False;
4887 cli_setatr(cli1, fname, 0, 0);
4888 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4890 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4892 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4893 if (!NT_STATUS_IS_OK(status)) {
4894 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4895 return False;
4898 status = cli_close(cli1, fnum1);
4899 if (!NT_STATUS_IS_OK(status)) {
4900 printf("close2 failed (%s)\n", nt_errstr(status));
4901 return False;
4904 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
4905 if (!NT_STATUS_IS_OK(status)) {
4906 printf("cli_setatr failed (%s)\n", nt_errstr(status));
4907 return False;
4910 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4911 if (!NT_STATUS_IS_OK(status)) {
4912 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4913 return False;
4916 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4917 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4919 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
4920 NT_STATUS_ACCESS_DENIED)) {
4921 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4924 printf("finished open test 1\n");
4926 cli_close(cli1, fnum1);
4928 /* Now try not readonly and ensure ERRbadshare is returned. */
4930 cli_setatr(cli1, fname, 0, 0);
4932 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4933 if (!NT_STATUS_IS_OK(status)) {
4934 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4935 return False;
4938 /* This will fail - but the error should be ERRshare. */
4939 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4941 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
4942 NT_STATUS_SHARING_VIOLATION)) {
4943 printf("correct error code ERRDOS/ERRbadshare returned\n");
4946 status = cli_close(cli1, fnum1);
4947 if (!NT_STATUS_IS_OK(status)) {
4948 printf("close2 failed (%s)\n", nt_errstr(status));
4949 return False;
4952 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4954 printf("finished open test 2\n");
4956 /* Test truncate open disposition on file opened for read. */
4957 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4958 if (!NT_STATUS_IS_OK(status)) {
4959 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
4960 return False;
4963 /* write 20 bytes. */
4965 memset(buf, '\0', 20);
4967 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
4968 if (!NT_STATUS_IS_OK(status)) {
4969 printf("write failed (%s)\n", nt_errstr(status));
4970 correct = False;
4973 status = cli_close(cli1, fnum1);
4974 if (!NT_STATUS_IS_OK(status)) {
4975 printf("(3) close1 failed (%s)\n", nt_errstr(status));
4976 return False;
4979 /* Ensure size == 20. */
4980 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4981 if (!NT_STATUS_IS_OK(status)) {
4982 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4983 return False;
4986 if (fsize != 20) {
4987 printf("(3) file size != 20\n");
4988 return False;
4991 /* Now test if we can truncate a file opened for readonly. */
4992 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
4993 if (!NT_STATUS_IS_OK(status)) {
4994 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
4995 return False;
4998 status = cli_close(cli1, fnum1);
4999 if (!NT_STATUS_IS_OK(status)) {
5000 printf("close2 failed (%s)\n", nt_errstr(status));
5001 return False;
5004 /* Ensure size == 0. */
5005 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5006 if (!NT_STATUS_IS_OK(status)) {
5007 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5008 return False;
5011 if (fsize != 0) {
5012 printf("(3) file size != 0\n");
5013 return False;
5015 printf("finished open test 3\n");
5017 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5019 printf("Do ctemp tests\n");
5020 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
5021 if (!NT_STATUS_IS_OK(status)) {
5022 printf("ctemp failed (%s)\n", nt_errstr(status));
5023 return False;
5026 printf("ctemp gave path %s\n", tmp_path);
5027 status = cli_close(cli1, fnum1);
5028 if (!NT_STATUS_IS_OK(status)) {
5029 printf("close of temp failed (%s)\n", nt_errstr(status));
5032 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5033 if (!NT_STATUS_IS_OK(status)) {
5034 printf("unlink of temp failed (%s)\n", nt_errstr(status));
5037 /* Test the non-io opens... */
5039 if (!torture_open_connection(&cli2, 1)) {
5040 return False;
5043 cli_setatr(cli2, fname, 0, 0);
5044 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5046 smbXcli_conn_set_sockopt(cli2->conn, sockops);
5048 printf("TEST #1 testing 2 non-io opens (no delete)\n");
5049 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5050 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5051 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5052 if (!NT_STATUS_IS_OK(status)) {
5053 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5054 return False;
5057 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5058 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5059 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5060 if (!NT_STATUS_IS_OK(status)) {
5061 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5062 return False;
5065 status = cli_close(cli1, fnum1);
5066 if (!NT_STATUS_IS_OK(status)) {
5067 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5068 return False;
5071 status = cli_close(cli2, fnum2);
5072 if (!NT_STATUS_IS_OK(status)) {
5073 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5074 return False;
5077 printf("non-io open test #1 passed.\n");
5079 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5081 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5083 status = cli_ntcreate(cli1, fname, 0,
5084 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5085 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5086 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5087 if (!NT_STATUS_IS_OK(status)) {
5088 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5089 return False;
5092 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5093 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5094 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5095 if (!NT_STATUS_IS_OK(status)) {
5096 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5097 return False;
5100 status = cli_close(cli1, fnum1);
5101 if (!NT_STATUS_IS_OK(status)) {
5102 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5103 return False;
5106 status = cli_close(cli2, fnum2);
5107 if (!NT_STATUS_IS_OK(status)) {
5108 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5109 return False;
5112 printf("non-io open test #2 passed.\n");
5114 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5116 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5118 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5119 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5120 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5121 if (!NT_STATUS_IS_OK(status)) {
5122 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5123 return False;
5126 status = cli_ntcreate(cli2, fname, 0,
5127 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5128 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5129 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5130 if (!NT_STATUS_IS_OK(status)) {
5131 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5132 return False;
5135 status = cli_close(cli1, fnum1);
5136 if (!NT_STATUS_IS_OK(status)) {
5137 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5138 return False;
5141 status = cli_close(cli2, fnum2);
5142 if (!NT_STATUS_IS_OK(status)) {
5143 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5144 return False;
5147 printf("non-io open test #3 passed.\n");
5149 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5151 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5153 status = cli_ntcreate(cli1, fname, 0,
5154 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5155 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5156 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5157 if (!NT_STATUS_IS_OK(status)) {
5158 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5159 return False;
5162 status = cli_ntcreate(cli2, fname, 0,
5163 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5164 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5165 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5166 if (NT_STATUS_IS_OK(status)) {
5167 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5168 return False;
5171 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5173 status = cli_close(cli1, fnum1);
5174 if (!NT_STATUS_IS_OK(status)) {
5175 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5176 return False;
5179 printf("non-io open test #4 passed.\n");
5181 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5183 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5185 status = cli_ntcreate(cli1, fname, 0,
5186 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5187 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5188 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5189 if (!NT_STATUS_IS_OK(status)) {
5190 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5191 return False;
5194 status = cli_ntcreate(cli2, fname, 0,
5195 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5196 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5197 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5198 if (!NT_STATUS_IS_OK(status)) {
5199 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5200 return False;
5203 status = cli_close(cli1, fnum1);
5204 if (!NT_STATUS_IS_OK(status)) {
5205 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5206 return False;
5209 status = cli_close(cli2, fnum2);
5210 if (!NT_STATUS_IS_OK(status)) {
5211 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5212 return False;
5215 printf("non-io open test #5 passed.\n");
5217 printf("TEST #6 testing 1 non-io open, one io open\n");
5219 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5221 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5222 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5223 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5224 if (!NT_STATUS_IS_OK(status)) {
5225 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5226 return False;
5229 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5230 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5231 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5232 if (!NT_STATUS_IS_OK(status)) {
5233 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5234 return False;
5237 status = cli_close(cli1, fnum1);
5238 if (!NT_STATUS_IS_OK(status)) {
5239 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5240 return False;
5243 status = cli_close(cli2, fnum2);
5244 if (!NT_STATUS_IS_OK(status)) {
5245 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5246 return False;
5249 printf("non-io open test #6 passed.\n");
5251 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5253 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5255 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5256 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5257 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5258 if (!NT_STATUS_IS_OK(status)) {
5259 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5260 return False;
5263 status = cli_ntcreate(cli2, fname, 0,
5264 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5265 FILE_ATTRIBUTE_NORMAL,
5266 FILE_SHARE_READ|FILE_SHARE_DELETE,
5267 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5268 if (NT_STATUS_IS_OK(status)) {
5269 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5270 return False;
5273 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5275 status = cli_close(cli1, fnum1);
5276 if (!NT_STATUS_IS_OK(status)) {
5277 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5278 return False;
5281 printf("non-io open test #7 passed.\n");
5283 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5285 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5286 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5287 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5288 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5289 if (!NT_STATUS_IS_OK(status)) {
5290 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5291 correct = false;
5292 goto out;
5295 /* Write to ensure we have to update the file time. */
5296 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5297 NULL);
5298 if (!NT_STATUS_IS_OK(status)) {
5299 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5300 correct = false;
5301 goto out;
5304 status = cli_close(cli1, fnum1);
5305 if (!NT_STATUS_IS_OK(status)) {
5306 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5307 correct = false;
5310 out:
5312 if (!torture_close_connection(cli1)) {
5313 correct = False;
5315 if (!torture_close_connection(cli2)) {
5316 correct = False;
5319 return correct;
5322 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5324 uint16_t major, minor;
5325 uint32_t caplow, caphigh;
5326 NTSTATUS status;
5328 if (!SERVER_HAS_UNIX_CIFS(cli)) {
5329 printf("Server doesn't support UNIX CIFS extensions.\n");
5330 return NT_STATUS_NOT_SUPPORTED;
5333 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5334 &caphigh);
5335 if (!NT_STATUS_IS_OK(status)) {
5336 printf("Server didn't return UNIX CIFS extensions: %s\n",
5337 nt_errstr(status));
5338 return status;
5341 status = cli_set_unix_extensions_capabilities(cli, major, minor,
5342 caplow, caphigh);
5343 if (!NT_STATUS_IS_OK(status)) {
5344 printf("Server doesn't support setting UNIX CIFS extensions: "
5345 "%s.\n", nt_errstr(status));
5346 return status;
5349 return NT_STATUS_OK;
5353 Test POSIX open /mkdir calls.
5355 static bool run_simple_posix_open_test(int dummy)
5357 static struct cli_state *cli1;
5358 const char *fname = "posix:file";
5359 const char *hname = "posix:hlink";
5360 const char *sname = "posix:symlink";
5361 const char *dname = "posix:dir";
5362 char buf[10];
5363 char namebuf[11];
5364 uint16_t fnum1 = (uint16_t)-1;
5365 SMB_STRUCT_STAT sbuf;
5366 bool correct = false;
5367 NTSTATUS status;
5368 size_t nread;
5369 const char *fname_windows = "windows_file";
5370 uint16_t fnum2 = (uint16_t)-1;
5372 printf("Starting simple POSIX open test\n");
5374 if (!torture_open_connection(&cli1, 0)) {
5375 return false;
5378 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5380 status = torture_setup_unix_extensions(cli1);
5381 if (!NT_STATUS_IS_OK(status)) {
5382 return false;
5385 cli_setatr(cli1, fname, 0, 0);
5386 cli_posix_unlink(cli1, fname);
5387 cli_setatr(cli1, dname, 0, 0);
5388 cli_posix_rmdir(cli1, dname);
5389 cli_setatr(cli1, hname, 0, 0);
5390 cli_posix_unlink(cli1, hname);
5391 cli_setatr(cli1, sname, 0, 0);
5392 cli_posix_unlink(cli1, sname);
5393 cli_setatr(cli1, fname_windows, 0, 0);
5394 cli_posix_unlink(cli1, fname_windows);
5396 /* Create a directory. */
5397 status = cli_posix_mkdir(cli1, dname, 0777);
5398 if (!NT_STATUS_IS_OK(status)) {
5399 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5400 goto out;
5403 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5404 0600, &fnum1);
5405 if (!NT_STATUS_IS_OK(status)) {
5406 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5407 goto out;
5410 /* Test ftruncate - set file size. */
5411 status = cli_ftruncate(cli1, fnum1, 1000);
5412 if (!NT_STATUS_IS_OK(status)) {
5413 printf("ftruncate failed (%s)\n", nt_errstr(status));
5414 goto out;
5417 /* Ensure st_size == 1000 */
5418 status = cli_posix_stat(cli1, fname, &sbuf);
5419 if (!NT_STATUS_IS_OK(status)) {
5420 printf("stat failed (%s)\n", nt_errstr(status));
5421 goto out;
5424 if (sbuf.st_ex_size != 1000) {
5425 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5426 goto out;
5429 /* Ensure st_mode == 0600 */
5430 if ((sbuf.st_ex_mode & 07777) != 0600) {
5431 printf("posix_open - bad permissions 0%o != 0600\n",
5432 (unsigned int)(sbuf.st_ex_mode & 07777));
5433 goto out;
5436 /* Test ftruncate - set file size back to zero. */
5437 status = cli_ftruncate(cli1, fnum1, 0);
5438 if (!NT_STATUS_IS_OK(status)) {
5439 printf("ftruncate failed (%s)\n", nt_errstr(status));
5440 goto out;
5443 status = cli_close(cli1, fnum1);
5444 if (!NT_STATUS_IS_OK(status)) {
5445 printf("close failed (%s)\n", nt_errstr(status));
5446 goto out;
5449 /* Now open the file again for read only. */
5450 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5451 if (!NT_STATUS_IS_OK(status)) {
5452 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5453 goto out;
5456 /* Now unlink while open. */
5457 status = cli_posix_unlink(cli1, fname);
5458 if (!NT_STATUS_IS_OK(status)) {
5459 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5460 goto out;
5463 status = cli_close(cli1, fnum1);
5464 if (!NT_STATUS_IS_OK(status)) {
5465 printf("close(2) failed (%s)\n", nt_errstr(status));
5466 goto out;
5469 /* Ensure the file has gone. */
5470 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5471 if (NT_STATUS_IS_OK(status)) {
5472 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5473 goto out;
5476 /* Create again to test open with O_TRUNC. */
5477 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
5478 if (!NT_STATUS_IS_OK(status)) {
5479 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5480 goto out;
5483 /* Test ftruncate - set file size. */
5484 status = cli_ftruncate(cli1, fnum1, 1000);
5485 if (!NT_STATUS_IS_OK(status)) {
5486 printf("ftruncate failed (%s)\n", nt_errstr(status));
5487 goto out;
5490 /* Ensure st_size == 1000 */
5491 status = cli_posix_stat(cli1, fname, &sbuf);
5492 if (!NT_STATUS_IS_OK(status)) {
5493 printf("stat failed (%s)\n", nt_errstr(status));
5494 goto out;
5497 if (sbuf.st_ex_size != 1000) {
5498 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5499 goto out;
5502 status = cli_close(cli1, fnum1);
5503 if (!NT_STATUS_IS_OK(status)) {
5504 printf("close(2) failed (%s)\n", nt_errstr(status));
5505 goto out;
5508 /* Re-open with O_TRUNC. */
5509 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
5510 if (!NT_STATUS_IS_OK(status)) {
5511 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5512 goto out;
5515 /* Ensure st_size == 0 */
5516 status = cli_posix_stat(cli1, fname, &sbuf);
5517 if (!NT_STATUS_IS_OK(status)) {
5518 printf("stat failed (%s)\n", nt_errstr(status));
5519 goto out;
5522 if (sbuf.st_ex_size != 0) {
5523 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5524 goto out;
5527 status = cli_close(cli1, fnum1);
5528 if (!NT_STATUS_IS_OK(status)) {
5529 printf("close failed (%s)\n", nt_errstr(status));
5530 goto out;
5533 status = cli_posix_unlink(cli1, fname);
5534 if (!NT_STATUS_IS_OK(status)) {
5535 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5536 goto out;
5539 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
5540 if (!NT_STATUS_IS_OK(status)) {
5541 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5542 dname, nt_errstr(status));
5543 goto out;
5546 cli_close(cli1, fnum1);
5548 /* What happens when we try and POSIX open a directory for write ? */
5549 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
5550 if (NT_STATUS_IS_OK(status)) {
5551 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5552 goto out;
5553 } else {
5554 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
5555 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5556 goto out;
5560 /* Create the file. */
5561 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5562 0600, &fnum1);
5563 if (!NT_STATUS_IS_OK(status)) {
5564 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5565 goto out;
5568 /* Write some data into it. */
5569 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5570 NULL);
5571 if (!NT_STATUS_IS_OK(status)) {
5572 printf("cli_write failed: %s\n", nt_errstr(status));
5573 goto out;
5576 cli_close(cli1, fnum1);
5578 /* Now create a hardlink. */
5579 status = cli_posix_hardlink(cli1, fname, hname);
5580 if (!NT_STATUS_IS_OK(status)) {
5581 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5582 goto out;
5585 /* Now create a symlink. */
5586 status = cli_posix_symlink(cli1, fname, sname);
5587 if (!NT_STATUS_IS_OK(status)) {
5588 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5589 goto out;
5592 /* Open the hardlink for read. */
5593 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5594 if (!NT_STATUS_IS_OK(status)) {
5595 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5596 goto out;
5599 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
5600 if (!NT_STATUS_IS_OK(status)) {
5601 printf("POSIX read of %s failed (%s)\n", hname,
5602 nt_errstr(status));
5603 goto out;
5604 } else if (nread != 10) {
5605 printf("POSIX read of %s failed. Received %ld, expected %d\n",
5606 hname, (unsigned long)nread, 10);
5607 goto out;
5610 if (memcmp(buf, "TEST DATA\n", 10)) {
5611 printf("invalid data read from hardlink\n");
5612 goto out;
5615 /* Do a POSIX lock/unlock. */
5616 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5617 if (!NT_STATUS_IS_OK(status)) {
5618 printf("POSIX lock failed %s\n", nt_errstr(status));
5619 goto out;
5622 /* Punch a hole in the locked area. */
5623 status = cli_posix_unlock(cli1, fnum1, 10, 80);
5624 if (!NT_STATUS_IS_OK(status)) {
5625 printf("POSIX unlock failed %s\n", nt_errstr(status));
5626 goto out;
5629 cli_close(cli1, fnum1);
5631 /* Open the symlink for read - this should fail. A POSIX
5632 client should not be doing opens on a symlink. */
5633 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5634 if (NT_STATUS_IS_OK(status)) {
5635 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5636 goto out;
5637 } else {
5638 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
5639 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5640 printf("POSIX open of %s should have failed "
5641 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5642 "failed with %s instead.\n",
5643 sname, nt_errstr(status));
5644 goto out;
5648 status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5649 if (!NT_STATUS_IS_OK(status)) {
5650 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5651 goto out;
5654 if (strcmp(namebuf, fname) != 0) {
5655 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5656 sname, fname, namebuf);
5657 goto out;
5660 status = cli_posix_rmdir(cli1, dname);
5661 if (!NT_STATUS_IS_OK(status)) {
5662 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5663 goto out;
5666 /* Check directory opens with a specific permission. */
5667 status = cli_posix_mkdir(cli1, dname, 0700);
5668 if (!NT_STATUS_IS_OK(status)) {
5669 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5670 goto out;
5673 /* Ensure st_mode == 0700 */
5674 status = cli_posix_stat(cli1, dname, &sbuf);
5675 if (!NT_STATUS_IS_OK(status)) {
5676 printf("stat failed (%s)\n", nt_errstr(status));
5677 goto out;
5680 if ((sbuf.st_ex_mode & 07777) != 0700) {
5681 printf("posix_mkdir - bad permissions 0%o != 0700\n",
5682 (unsigned int)(sbuf.st_ex_mode & 07777));
5683 goto out;
5687 * Now create a Windows file, and attempt a POSIX unlink.
5688 * This should fail with a sharing violation but due to:
5690 * [Bug 9571] Unlink after open causes smbd to panic
5692 * ensure we've fixed the lock ordering violation.
5695 status = cli_ntcreate(cli1, fname_windows, 0,
5696 FILE_READ_DATA|FILE_WRITE_DATA, 0,
5697 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5698 FILE_CREATE,
5699 0x0, 0x0, &fnum2, NULL);
5700 if (!NT_STATUS_IS_OK(status)) {
5701 printf("Windows create of %s failed (%s)\n", fname_windows,
5702 nt_errstr(status));
5703 goto out;
5706 /* Now try posix_unlink. */
5707 status = cli_posix_unlink(cli1, fname_windows);
5708 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5709 printf("POSIX unlink of %s should fail "
5710 "with NT_STATUS_SHARING_VIOLATION "
5711 "got %s instead !\n",
5712 fname_windows,
5713 nt_errstr(status));
5714 goto out;
5717 cli_close(cli1, fnum2);
5719 printf("Simple POSIX open test passed\n");
5720 correct = true;
5722 out:
5724 if (fnum1 != (uint16_t)-1) {
5725 cli_close(cli1, fnum1);
5726 fnum1 = (uint16_t)-1;
5729 if (fnum2 != (uint16_t)-1) {
5730 cli_close(cli1, fnum2);
5731 fnum2 = (uint16_t)-1;
5734 cli_setatr(cli1, sname, 0, 0);
5735 cli_posix_unlink(cli1, sname);
5736 cli_setatr(cli1, hname, 0, 0);
5737 cli_posix_unlink(cli1, hname);
5738 cli_setatr(cli1, fname, 0, 0);
5739 cli_posix_unlink(cli1, fname);
5740 cli_setatr(cli1, dname, 0, 0);
5741 cli_posix_rmdir(cli1, dname);
5742 cli_setatr(cli1, fname_windows, 0, 0);
5743 cli_posix_unlink(cli1, fname_windows);
5745 if (!torture_close_connection(cli1)) {
5746 correct = false;
5749 return correct;
5753 static uint32_t open_attrs_table[] = {
5754 FILE_ATTRIBUTE_NORMAL,
5755 FILE_ATTRIBUTE_ARCHIVE,
5756 FILE_ATTRIBUTE_READONLY,
5757 FILE_ATTRIBUTE_HIDDEN,
5758 FILE_ATTRIBUTE_SYSTEM,
5760 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
5761 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
5762 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
5763 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5764 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5765 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5767 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5768 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5769 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5770 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
5773 struct trunc_open_results {
5774 unsigned int num;
5775 uint32_t init_attr;
5776 uint32_t trunc_attr;
5777 uint32_t result_attr;
5780 static struct trunc_open_results attr_results[] = {
5781 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5782 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5783 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5784 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5785 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5786 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5787 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5788 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5789 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5790 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5791 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5792 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5793 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5794 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5795 { 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 },
5796 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5797 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5798 { 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 },
5799 { 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 },
5800 { 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 },
5801 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5802 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5803 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5804 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5805 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5806 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
5809 static bool run_openattrtest(int dummy)
5811 static struct cli_state *cli1;
5812 const char *fname = "\\openattr.file";
5813 uint16_t fnum1;
5814 bool correct = True;
5815 uint16_t attr;
5816 unsigned int i, j, k, l;
5817 NTSTATUS status;
5819 printf("starting open attr test\n");
5821 if (!torture_open_connection(&cli1, 0)) {
5822 return False;
5825 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5827 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
5828 cli_setatr(cli1, fname, 0, 0);
5829 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5831 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
5832 open_attrs_table[i], FILE_SHARE_NONE,
5833 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5834 if (!NT_STATUS_IS_OK(status)) {
5835 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5836 return False;
5839 status = cli_close(cli1, fnum1);
5840 if (!NT_STATUS_IS_OK(status)) {
5841 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5842 return False;
5845 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
5846 status = cli_ntcreate(cli1, fname, 0,
5847 FILE_READ_DATA|FILE_WRITE_DATA,
5848 open_attrs_table[j],
5849 FILE_SHARE_NONE, FILE_OVERWRITE,
5850 0, 0, &fnum1, NULL);
5851 if (!NT_STATUS_IS_OK(status)) {
5852 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5853 if (attr_results[l].num == k) {
5854 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5855 k, open_attrs_table[i],
5856 open_attrs_table[j],
5857 fname, NT_STATUS_V(status), nt_errstr(status));
5858 correct = False;
5862 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5863 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5864 k, open_attrs_table[i], open_attrs_table[j],
5865 nt_errstr(status));
5866 correct = False;
5868 #if 0
5869 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5870 #endif
5871 k++;
5872 continue;
5875 status = cli_close(cli1, fnum1);
5876 if (!NT_STATUS_IS_OK(status)) {
5877 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
5878 return False;
5881 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
5882 if (!NT_STATUS_IS_OK(status)) {
5883 printf("getatr(2) failed (%s)\n", nt_errstr(status));
5884 return False;
5887 #if 0
5888 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5889 k, open_attrs_table[i], open_attrs_table[j], attr );
5890 #endif
5892 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5893 if (attr_results[l].num == k) {
5894 if (attr != attr_results[l].result_attr ||
5895 open_attrs_table[i] != attr_results[l].init_attr ||
5896 open_attrs_table[j] != attr_results[l].trunc_attr) {
5897 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5898 open_attrs_table[i],
5899 open_attrs_table[j],
5900 (unsigned int)attr,
5901 attr_results[l].result_attr);
5902 correct = False;
5904 break;
5907 k++;
5911 cli_setatr(cli1, fname, 0, 0);
5912 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5914 printf("open attr test %s.\n", correct ? "passed" : "failed");
5916 if (!torture_close_connection(cli1)) {
5917 correct = False;
5919 return correct;
5922 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5923 const char *name, void *state)
5925 int *matched = (int *)state;
5926 if (matched != NULL) {
5927 *matched += 1;
5929 return NT_STATUS_OK;
5933 test directory listing speed
5935 static bool run_dirtest(int dummy)
5937 int i;
5938 static struct cli_state *cli;
5939 uint16_t fnum;
5940 struct timeval core_start;
5941 bool correct = True;
5942 int matched;
5944 printf("starting directory test\n");
5946 if (!torture_open_connection(&cli, 0)) {
5947 return False;
5950 smbXcli_conn_set_sockopt(cli->conn, sockops);
5952 srandom(0);
5953 for (i=0;i<torture_numops;i++) {
5954 fstring fname;
5955 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5956 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5957 fprintf(stderr,"Failed to open %s\n", fname);
5958 return False;
5960 cli_close(cli, fnum);
5963 core_start = timeval_current();
5965 matched = 0;
5966 cli_list(cli, "a*.*", 0, list_fn, &matched);
5967 printf("Matched %d\n", matched);
5969 matched = 0;
5970 cli_list(cli, "b*.*", 0, list_fn, &matched);
5971 printf("Matched %d\n", matched);
5973 matched = 0;
5974 cli_list(cli, "xyzabc", 0, list_fn, &matched);
5975 printf("Matched %d\n", matched);
5977 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5979 srandom(0);
5980 for (i=0;i<torture_numops;i++) {
5981 fstring fname;
5982 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5983 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5986 if (!torture_close_connection(cli)) {
5987 correct = False;
5990 printf("finished dirtest\n");
5992 return correct;
5995 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5996 void *state)
5998 struct cli_state *pcli = (struct cli_state *)state;
5999 fstring fname;
6000 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
6002 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
6003 return NT_STATUS_OK;
6005 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
6006 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
6007 printf("del_fn: failed to rmdir %s\n,", fname );
6008 } else {
6009 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
6010 printf("del_fn: failed to unlink %s\n,", fname );
6012 return NT_STATUS_OK;
6017 sees what IOCTLs are supported
6019 bool torture_ioctl_test(int dummy)
6021 static struct cli_state *cli;
6022 uint16_t device, function;
6023 uint16_t fnum;
6024 const char *fname = "\\ioctl.dat";
6025 DATA_BLOB blob;
6026 NTSTATUS status;
6028 if (!torture_open_connection(&cli, 0)) {
6029 return False;
6032 printf("starting ioctl test\n");
6034 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6036 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6037 if (!NT_STATUS_IS_OK(status)) {
6038 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6039 return False;
6042 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
6043 printf("ioctl device info: %s\n", nt_errstr(status));
6045 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
6046 printf("ioctl job info: %s\n", nt_errstr(status));
6048 for (device=0;device<0x100;device++) {
6049 printf("ioctl test with device = 0x%x\n", device);
6050 for (function=0;function<0x100;function++) {
6051 uint32_t code = (device<<16) | function;
6053 status = cli_raw_ioctl(cli, fnum, code, &blob);
6055 if (NT_STATUS_IS_OK(status)) {
6056 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
6057 (int)blob.length);
6058 data_blob_free(&blob);
6063 if (!torture_close_connection(cli)) {
6064 return False;
6067 return True;
6072 tries varients of chkpath
6074 bool torture_chkpath_test(int dummy)
6076 static struct cli_state *cli;
6077 uint16_t fnum;
6078 bool ret;
6079 NTSTATUS status;
6081 if (!torture_open_connection(&cli, 0)) {
6082 return False;
6085 printf("starting chkpath test\n");
6087 /* cleanup from an old run */
6088 cli_rmdir(cli, "\\chkpath.dir\\dir2");
6089 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6090 cli_rmdir(cli, "\\chkpath.dir");
6092 status = cli_mkdir(cli, "\\chkpath.dir");
6093 if (!NT_STATUS_IS_OK(status)) {
6094 printf("mkdir1 failed : %s\n", nt_errstr(status));
6095 return False;
6098 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
6099 if (!NT_STATUS_IS_OK(status)) {
6100 printf("mkdir2 failed : %s\n", nt_errstr(status));
6101 return False;
6104 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
6105 DENY_NONE, &fnum);
6106 if (!NT_STATUS_IS_OK(status)) {
6107 printf("open1 failed (%s)\n", nt_errstr(status));
6108 return False;
6110 cli_close(cli, fnum);
6112 status = cli_chkpath(cli, "\\chkpath.dir");
6113 if (!NT_STATUS_IS_OK(status)) {
6114 printf("chkpath1 failed: %s\n", nt_errstr(status));
6115 ret = False;
6118 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
6119 if (!NT_STATUS_IS_OK(status)) {
6120 printf("chkpath2 failed: %s\n", nt_errstr(status));
6121 ret = False;
6124 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
6125 if (!NT_STATUS_IS_OK(status)) {
6126 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6127 NT_STATUS_NOT_A_DIRECTORY);
6128 } else {
6129 printf("* chkpath on a file should fail\n");
6130 ret = False;
6133 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
6134 if (!NT_STATUS_IS_OK(status)) {
6135 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
6136 NT_STATUS_OBJECT_NAME_NOT_FOUND);
6137 } else {
6138 printf("* chkpath on a non existent file should fail\n");
6139 ret = False;
6142 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
6143 if (!NT_STATUS_IS_OK(status)) {
6144 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6145 NT_STATUS_OBJECT_PATH_NOT_FOUND);
6146 } else {
6147 printf("* chkpath on a non existent component should fail\n");
6148 ret = False;
6151 cli_rmdir(cli, "\\chkpath.dir\\dir2");
6152 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6153 cli_rmdir(cli, "\\chkpath.dir");
6155 if (!torture_close_connection(cli)) {
6156 return False;
6159 return ret;
6162 static bool run_eatest(int dummy)
6164 static struct cli_state *cli;
6165 const char *fname = "\\eatest.txt";
6166 bool correct = True;
6167 uint16_t fnum;
6168 int i;
6169 size_t num_eas;
6170 struct ea_struct *ea_list = NULL;
6171 TALLOC_CTX *mem_ctx = talloc_init("eatest");
6172 NTSTATUS status;
6174 printf("starting eatest\n");
6176 if (!torture_open_connection(&cli, 0)) {
6177 talloc_destroy(mem_ctx);
6178 return False;
6181 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6183 status = cli_ntcreate(cli, fname, 0,
6184 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6185 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
6186 0x4044, 0, &fnum, NULL);
6187 if (!NT_STATUS_IS_OK(status)) {
6188 printf("open failed - %s\n", nt_errstr(status));
6189 talloc_destroy(mem_ctx);
6190 return False;
6193 for (i = 0; i < 10; i++) {
6194 fstring ea_name, ea_val;
6196 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
6197 memset(ea_val, (char)i+1, i+1);
6198 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
6199 if (!NT_STATUS_IS_OK(status)) {
6200 printf("ea_set of name %s failed - %s\n", ea_name,
6201 nt_errstr(status));
6202 talloc_destroy(mem_ctx);
6203 return False;
6207 cli_close(cli, fnum);
6208 for (i = 0; i < 10; i++) {
6209 fstring ea_name, ea_val;
6211 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
6212 memset(ea_val, (char)i+1, i+1);
6213 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
6214 if (!NT_STATUS_IS_OK(status)) {
6215 printf("ea_set of name %s failed - %s\n", ea_name,
6216 nt_errstr(status));
6217 talloc_destroy(mem_ctx);
6218 return False;
6222 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6223 if (!NT_STATUS_IS_OK(status)) {
6224 printf("ea_get list failed - %s\n", nt_errstr(status));
6225 correct = False;
6228 printf("num_eas = %d\n", (int)num_eas);
6230 if (num_eas != 20) {
6231 printf("Should be 20 EA's stored... failing.\n");
6232 correct = False;
6235 for (i = 0; i < num_eas; i++) {
6236 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6237 dump_data(0, ea_list[i].value.data,
6238 ea_list[i].value.length);
6241 /* Setting EA's to zero length deletes them. Test this */
6242 printf("Now deleting all EA's - case indepenent....\n");
6244 #if 1
6245 cli_set_ea_path(cli, fname, "", "", 0);
6246 #else
6247 for (i = 0; i < 20; i++) {
6248 fstring ea_name;
6249 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
6250 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
6251 if (!NT_STATUS_IS_OK(status)) {
6252 printf("ea_set of name %s failed - %s\n", ea_name,
6253 nt_errstr(status));
6254 talloc_destroy(mem_ctx);
6255 return False;
6258 #endif
6260 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6261 if (!NT_STATUS_IS_OK(status)) {
6262 printf("ea_get list failed - %s\n", nt_errstr(status));
6263 correct = False;
6266 printf("num_eas = %d\n", (int)num_eas);
6267 for (i = 0; i < num_eas; i++) {
6268 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6269 dump_data(0, ea_list[i].value.data,
6270 ea_list[i].value.length);
6273 if (num_eas != 0) {
6274 printf("deleting EA's failed.\n");
6275 correct = False;
6278 /* Try and delete a non existent EA. */
6279 status = cli_set_ea_path(cli, fname, "foo", "", 0);
6280 if (!NT_STATUS_IS_OK(status)) {
6281 printf("deleting non-existent EA 'foo' should succeed. %s\n",
6282 nt_errstr(status));
6283 correct = False;
6286 talloc_destroy(mem_ctx);
6287 if (!torture_close_connection(cli)) {
6288 correct = False;
6291 return correct;
6294 static bool run_dirtest1(int dummy)
6296 int i;
6297 static struct cli_state *cli;
6298 uint16_t fnum;
6299 int num_seen;
6300 bool correct = True;
6302 printf("starting directory test\n");
6304 if (!torture_open_connection(&cli, 0)) {
6305 return False;
6308 smbXcli_conn_set_sockopt(cli->conn, sockops);
6310 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6311 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6312 cli_rmdir(cli, "\\LISTDIR");
6313 cli_mkdir(cli, "\\LISTDIR");
6315 /* Create 1000 files and 1000 directories. */
6316 for (i=0;i<1000;i++) {
6317 fstring fname;
6318 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6319 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6320 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
6321 0, 0, &fnum, NULL))) {
6322 fprintf(stderr,"Failed to open %s\n", fname);
6323 return False;
6325 cli_close(cli, fnum);
6327 for (i=0;i<1000;i++) {
6328 fstring fname;
6329 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6330 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6331 fprintf(stderr,"Failed to open %s\n", fname);
6332 return False;
6336 /* Now ensure that doing an old list sees both files and directories. */
6337 num_seen = 0;
6338 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6339 printf("num_seen = %d\n", num_seen );
6340 /* We should see 100 files + 1000 directories + . and .. */
6341 if (num_seen != 2002)
6342 correct = False;
6344 /* Ensure if we have the "must have" bits we only see the
6345 * relevent entries.
6347 num_seen = 0;
6348 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6349 printf("num_seen = %d\n", num_seen );
6350 if (num_seen != 1002)
6351 correct = False;
6353 num_seen = 0;
6354 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6355 printf("num_seen = %d\n", num_seen );
6356 if (num_seen != 1000)
6357 correct = False;
6359 /* Delete everything. */
6360 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6361 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6362 cli_rmdir(cli, "\\LISTDIR");
6364 #if 0
6365 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6366 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6367 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6368 #endif
6370 if (!torture_close_connection(cli)) {
6371 correct = False;
6374 printf("finished dirtest1\n");
6376 return correct;
6379 static bool run_error_map_extract(int dummy) {
6381 static struct cli_state *c_dos;
6382 static struct cli_state *c_nt;
6383 NTSTATUS status;
6385 uint32_t error;
6387 uint32_t errnum;
6388 uint8_t errclass;
6390 NTSTATUS nt_status;
6392 fstring user;
6394 /* NT-Error connection */
6396 disable_spnego = true;
6397 if (!(c_nt = open_nbt_connection())) {
6398 disable_spnego = false;
6399 return False;
6401 disable_spnego = false;
6403 status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
6404 PROTOCOL_NT1);
6406 if (!NT_STATUS_IS_OK(status)) {
6407 printf("%s rejected the NT-error negprot (%s)\n", host,
6408 nt_errstr(status));
6409 cli_shutdown(c_nt);
6410 return False;
6413 status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6414 if (!NT_STATUS_IS_OK(status)) {
6415 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6416 return False;
6419 /* DOS-Error connection */
6421 disable_spnego = true;
6422 force_dos_errors = true;
6423 if (!(c_dos = open_nbt_connection())) {
6424 disable_spnego = false;
6425 force_dos_errors = false;
6426 return False;
6428 disable_spnego = false;
6429 force_dos_errors = false;
6431 status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
6432 PROTOCOL_NT1);
6433 if (!NT_STATUS_IS_OK(status)) {
6434 printf("%s rejected the DOS-error negprot (%s)\n", host,
6435 nt_errstr(status));
6436 cli_shutdown(c_dos);
6437 return False;
6440 status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
6441 if (!NT_STATUS_IS_OK(status)) {
6442 printf("%s rejected the DOS-error initial session setup (%s)\n",
6443 host, nt_errstr(status));
6444 return False;
6447 c_nt->map_dos_errors = false;
6448 c_dos->map_dos_errors = false;
6450 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
6451 fstr_sprintf(user, "%X", error);
6453 status = cli_session_setup(c_nt, user,
6454 password, strlen(password),
6455 password, strlen(password),
6456 workgroup);
6457 if (NT_STATUS_IS_OK(status)) {
6458 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6461 /* Case #1: 32-bit NT errors */
6462 if (!NT_STATUS_IS_DOS(status)) {
6463 nt_status = status;
6464 } else {
6465 printf("/** Dos error on NT connection! (%s) */\n",
6466 nt_errstr(status));
6467 nt_status = NT_STATUS(0xc0000000);
6470 status = cli_session_setup(c_dos, user,
6471 password, strlen(password),
6472 password, strlen(password),
6473 workgroup);
6474 if (NT_STATUS_IS_OK(status)) {
6475 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6478 /* Case #1: 32-bit NT errors */
6479 if (NT_STATUS_IS_DOS(status)) {
6480 printf("/** NT error on DOS connection! (%s) */\n",
6481 nt_errstr(status));
6482 errnum = errclass = 0;
6483 } else {
6484 errclass = NT_STATUS_DOS_CLASS(status);
6485 errnum = NT_STATUS_DOS_CODE(status);
6488 if (NT_STATUS_V(nt_status) != error) {
6489 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
6490 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
6491 get_nt_error_c_code(talloc_tos(), nt_status));
6494 printf("\t{%s,\t%s,\t%s},\n",
6495 smb_dos_err_class(errclass),
6496 smb_dos_err_name(errclass, errnum),
6497 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
6499 return True;
6502 static bool run_sesssetup_bench(int dummy)
6504 static struct cli_state *c;
6505 const char *fname = "\\file.dat";
6506 uint16_t fnum;
6507 NTSTATUS status;
6508 int i;
6510 if (!torture_open_connection(&c, 0)) {
6511 return false;
6514 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6515 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6516 FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
6517 if (!NT_STATUS_IS_OK(status)) {
6518 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6519 return false;
6522 for (i=0; i<torture_numops; i++) {
6523 status = cli_session_setup(
6524 c, username,
6525 password, strlen(password),
6526 password, strlen(password),
6527 workgroup);
6528 if (!NT_STATUS_IS_OK(status)) {
6529 d_printf("(%s) cli_session_setup failed: %s\n",
6530 __location__, nt_errstr(status));
6531 return false;
6534 d_printf("\r%d ", (int)cli_state_get_uid(c));
6536 status = cli_ulogoff(c);
6537 if (!NT_STATUS_IS_OK(status)) {
6538 d_printf("(%s) cli_ulogoff failed: %s\n",
6539 __location__, nt_errstr(status));
6540 return false;
6544 return true;
6547 static bool subst_test(const char *str, const char *user, const char *domain,
6548 uid_t uid, gid_t gid, const char *expected)
6550 char *subst;
6551 bool result = true;
6553 subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
6555 if (strcmp(subst, expected) != 0) {
6556 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
6557 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
6558 expected);
6559 result = false;
6562 TALLOC_FREE(subst);
6563 return result;
6566 static void chain1_open_completion(struct tevent_req *req)
6568 uint16_t fnum;
6569 NTSTATUS status;
6570 status = cli_openx_recv(req, &fnum);
6571 TALLOC_FREE(req);
6573 d_printf("cli_openx_recv returned %s: %d\n",
6574 nt_errstr(status),
6575 NT_STATUS_IS_OK(status) ? fnum : -1);
6578 static void chain1_write_completion(struct tevent_req *req)
6580 size_t written;
6581 NTSTATUS status;
6582 status = cli_write_andx_recv(req, &written);
6583 TALLOC_FREE(req);
6585 d_printf("cli_write_andx_recv returned %s: %d\n",
6586 nt_errstr(status),
6587 NT_STATUS_IS_OK(status) ? (int)written : -1);
6590 static void chain1_close_completion(struct tevent_req *req)
6592 NTSTATUS status;
6593 bool *done = (bool *)tevent_req_callback_data_void(req);
6595 status = cli_close_recv(req);
6596 *done = true;
6598 TALLOC_FREE(req);
6600 d_printf("cli_close returned %s\n", nt_errstr(status));
6603 static bool run_chain1(int dummy)
6605 struct cli_state *cli1;
6606 struct tevent_context *evt = samba_tevent_context_init(NULL);
6607 struct tevent_req *reqs[3], *smbreqs[3];
6608 bool done = false;
6609 const char *str = "foobar";
6610 NTSTATUS status;
6612 printf("starting chain1 test\n");
6613 if (!torture_open_connection(&cli1, 0)) {
6614 return False;
6617 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6619 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, "\\test",
6620 O_CREAT|O_RDWR, 0, &smbreqs[0]);
6621 if (reqs[0] == NULL) return false;
6622 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
6625 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
6626 (const uint8_t *)str, 0, strlen(str)+1,
6627 smbreqs, 1, &smbreqs[1]);
6628 if (reqs[1] == NULL) return false;
6629 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
6631 reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
6632 if (reqs[2] == NULL) return false;
6633 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
6635 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
6636 if (!NT_STATUS_IS_OK(status)) {
6637 return false;
6640 while (!done) {
6641 tevent_loop_once(evt);
6644 torture_close_connection(cli1);
6645 return True;
6648 static void chain2_sesssetup_completion(struct tevent_req *req)
6650 NTSTATUS status;
6651 status = cli_session_setup_guest_recv(req);
6652 d_printf("sesssetup returned %s\n", nt_errstr(status));
6655 static void chain2_tcon_completion(struct tevent_req *req)
6657 bool *done = (bool *)tevent_req_callback_data_void(req);
6658 NTSTATUS status;
6659 status = cli_tcon_andx_recv(req);
6660 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
6661 *done = true;
6664 static bool run_chain2(int dummy)
6666 struct cli_state *cli1;
6667 struct tevent_context *evt = samba_tevent_context_init(NULL);
6668 struct tevent_req *reqs[2], *smbreqs[2];
6669 bool done = false;
6670 NTSTATUS status;
6672 printf("starting chain2 test\n");
6673 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
6674 port_to_use, SMB_SIGNING_DEFAULT, 0);
6675 if (!NT_STATUS_IS_OK(status)) {
6676 return False;
6679 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6681 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
6682 &smbreqs[0]);
6683 if (reqs[0] == NULL) return false;
6684 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
6686 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
6687 "?????", NULL, 0, &smbreqs[1]);
6688 if (reqs[1] == NULL) return false;
6689 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
6691 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
6692 if (!NT_STATUS_IS_OK(status)) {
6693 return false;
6696 while (!done) {
6697 tevent_loop_once(evt);
6700 torture_close_connection(cli1);
6701 return True;
6705 struct torture_createdel_state {
6706 struct tevent_context *ev;
6707 struct cli_state *cli;
6710 static void torture_createdel_created(struct tevent_req *subreq);
6711 static void torture_createdel_closed(struct tevent_req *subreq);
6713 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
6714 struct tevent_context *ev,
6715 struct cli_state *cli,
6716 const char *name)
6718 struct tevent_req *req, *subreq;
6719 struct torture_createdel_state *state;
6721 req = tevent_req_create(mem_ctx, &state,
6722 struct torture_createdel_state);
6723 if (req == NULL) {
6724 return NULL;
6726 state->ev = ev;
6727 state->cli = cli;
6729 subreq = cli_ntcreate_send(
6730 state, ev, cli, name, 0,
6731 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
6732 FILE_ATTRIBUTE_NORMAL,
6733 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6734 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
6736 if (tevent_req_nomem(subreq, req)) {
6737 return tevent_req_post(req, ev);
6739 tevent_req_set_callback(subreq, torture_createdel_created, req);
6740 return req;
6743 static void torture_createdel_created(struct tevent_req *subreq)
6745 struct tevent_req *req = tevent_req_callback_data(
6746 subreq, struct tevent_req);
6747 struct torture_createdel_state *state = tevent_req_data(
6748 req, struct torture_createdel_state);
6749 NTSTATUS status;
6750 uint16_t fnum;
6752 status = cli_ntcreate_recv(subreq, &fnum, NULL);
6753 TALLOC_FREE(subreq);
6754 if (tevent_req_nterror(req, status)) {
6755 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
6756 nt_errstr(status)));
6757 return;
6760 subreq = cli_close_send(state, state->ev, state->cli, fnum);
6761 if (tevent_req_nomem(subreq, req)) {
6762 return;
6764 tevent_req_set_callback(subreq, torture_createdel_closed, req);
6767 static void torture_createdel_closed(struct tevent_req *subreq)
6769 struct tevent_req *req = tevent_req_callback_data(
6770 subreq, struct tevent_req);
6771 NTSTATUS status;
6773 status = cli_close_recv(subreq);
6774 if (tevent_req_nterror(req, status)) {
6775 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
6776 return;
6778 tevent_req_done(req);
6781 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
6783 return tevent_req_simple_recv_ntstatus(req);
6786 struct torture_createdels_state {
6787 struct tevent_context *ev;
6788 struct cli_state *cli;
6789 const char *base_name;
6790 int sent;
6791 int received;
6792 int num_files;
6793 struct tevent_req **reqs;
6796 static void torture_createdels_done(struct tevent_req *subreq);
6798 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
6799 struct tevent_context *ev,
6800 struct cli_state *cli,
6801 const char *base_name,
6802 int num_parallel,
6803 int num_files)
6805 struct tevent_req *req;
6806 struct torture_createdels_state *state;
6807 int i;
6809 req = tevent_req_create(mem_ctx, &state,
6810 struct torture_createdels_state);
6811 if (req == NULL) {
6812 return NULL;
6814 state->ev = ev;
6815 state->cli = cli;
6816 state->base_name = talloc_strdup(state, base_name);
6817 if (tevent_req_nomem(state->base_name, req)) {
6818 return tevent_req_post(req, ev);
6820 state->num_files = MAX(num_parallel, num_files);
6821 state->sent = 0;
6822 state->received = 0;
6824 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
6825 if (tevent_req_nomem(state->reqs, req)) {
6826 return tevent_req_post(req, ev);
6829 for (i=0; i<num_parallel; i++) {
6830 char *name;
6832 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6833 state->sent);
6834 if (tevent_req_nomem(name, req)) {
6835 return tevent_req_post(req, ev);
6837 state->reqs[i] = torture_createdel_send(
6838 state->reqs, state->ev, state->cli, name);
6839 if (tevent_req_nomem(state->reqs[i], req)) {
6840 return tevent_req_post(req, ev);
6842 name = talloc_move(state->reqs[i], &name);
6843 tevent_req_set_callback(state->reqs[i],
6844 torture_createdels_done, req);
6845 state->sent += 1;
6847 return req;
6850 static void torture_createdels_done(struct tevent_req *subreq)
6852 struct tevent_req *req = tevent_req_callback_data(
6853 subreq, struct tevent_req);
6854 struct torture_createdels_state *state = tevent_req_data(
6855 req, struct torture_createdels_state);
6856 size_t num_parallel = talloc_array_length(state->reqs);
6857 NTSTATUS status;
6858 char *name;
6859 int i;
6861 status = torture_createdel_recv(subreq);
6862 if (!NT_STATUS_IS_OK(status)){
6863 DEBUG(10, ("torture_createdel_recv returned %s\n",
6864 nt_errstr(status)));
6865 TALLOC_FREE(subreq);
6866 tevent_req_nterror(req, status);
6867 return;
6870 for (i=0; i<num_parallel; i++) {
6871 if (subreq == state->reqs[i]) {
6872 break;
6875 if (i == num_parallel) {
6876 DEBUG(10, ("received something we did not send\n"));
6877 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6878 return;
6880 TALLOC_FREE(state->reqs[i]);
6882 if (state->sent >= state->num_files) {
6883 tevent_req_done(req);
6884 return;
6887 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6888 state->sent);
6889 if (tevent_req_nomem(name, req)) {
6890 return;
6892 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
6893 state->cli, name);
6894 if (tevent_req_nomem(state->reqs[i], req)) {
6895 return;
6897 name = talloc_move(state->reqs[i], &name);
6898 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
6899 state->sent += 1;
6902 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
6904 return tevent_req_simple_recv_ntstatus(req);
6907 struct swallow_notify_state {
6908 struct tevent_context *ev;
6909 struct cli_state *cli;
6910 uint16_t fnum;
6911 uint32_t completion_filter;
6912 bool recursive;
6913 bool (*fn)(uint32_t action, const char *name, void *priv);
6914 void *priv;
6917 static void swallow_notify_done(struct tevent_req *subreq);
6919 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
6920 struct tevent_context *ev,
6921 struct cli_state *cli,
6922 uint16_t fnum,
6923 uint32_t completion_filter,
6924 bool recursive,
6925 bool (*fn)(uint32_t action,
6926 const char *name,
6927 void *priv),
6928 void *priv)
6930 struct tevent_req *req, *subreq;
6931 struct swallow_notify_state *state;
6933 req = tevent_req_create(mem_ctx, &state,
6934 struct swallow_notify_state);
6935 if (req == NULL) {
6936 return NULL;
6938 state->ev = ev;
6939 state->cli = cli;
6940 state->fnum = fnum;
6941 state->completion_filter = completion_filter;
6942 state->recursive = recursive;
6943 state->fn = fn;
6944 state->priv = priv;
6946 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6947 0xffff, state->completion_filter,
6948 state->recursive);
6949 if (tevent_req_nomem(subreq, req)) {
6950 return tevent_req_post(req, ev);
6952 tevent_req_set_callback(subreq, swallow_notify_done, req);
6953 return req;
6956 static void swallow_notify_done(struct tevent_req *subreq)
6958 struct tevent_req *req = tevent_req_callback_data(
6959 subreq, struct tevent_req);
6960 struct swallow_notify_state *state = tevent_req_data(
6961 req, struct swallow_notify_state);
6962 NTSTATUS status;
6963 uint32_t i, num_changes;
6964 struct notify_change *changes;
6966 status = cli_notify_recv(subreq, state, &num_changes, &changes);
6967 TALLOC_FREE(subreq);
6968 if (!NT_STATUS_IS_OK(status)) {
6969 DEBUG(10, ("cli_notify_recv returned %s\n",
6970 nt_errstr(status)));
6971 tevent_req_nterror(req, status);
6972 return;
6975 for (i=0; i<num_changes; i++) {
6976 state->fn(changes[i].action, changes[i].name, state->priv);
6978 TALLOC_FREE(changes);
6980 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6981 0xffff, state->completion_filter,
6982 state->recursive);
6983 if (tevent_req_nomem(subreq, req)) {
6984 return;
6986 tevent_req_set_callback(subreq, swallow_notify_done, req);
6989 static bool print_notifies(uint32_t action, const char *name, void *priv)
6991 if (DEBUGLEVEL > 5) {
6992 d_printf("%d %s\n", (int)action, name);
6994 return true;
6997 static void notify_bench_done(struct tevent_req *req)
6999 int *num_finished = (int *)tevent_req_callback_data_void(req);
7000 *num_finished += 1;
7003 static bool run_notify_bench(int dummy)
7005 const char *dname = "\\notify-bench";
7006 struct tevent_context *ev;
7007 NTSTATUS status;
7008 uint16_t dnum;
7009 struct tevent_req *req1;
7010 struct tevent_req *req2 = NULL;
7011 int i, num_unc_names;
7012 int num_finished = 0;
7014 printf("starting notify-bench test\n");
7016 if (use_multishare_conn) {
7017 char **unc_list;
7018 unc_list = file_lines_load(multishare_conn_fname,
7019 &num_unc_names, 0, NULL);
7020 if (!unc_list || num_unc_names <= 0) {
7021 d_printf("Failed to load unc names list from '%s'\n",
7022 multishare_conn_fname);
7023 return false;
7025 TALLOC_FREE(unc_list);
7026 } else {
7027 num_unc_names = 1;
7030 ev = samba_tevent_context_init(talloc_tos());
7031 if (ev == NULL) {
7032 d_printf("tevent_context_init failed\n");
7033 return false;
7036 for (i=0; i<num_unc_names; i++) {
7037 struct cli_state *cli;
7038 char *base_fname;
7040 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
7041 dname, i);
7042 if (base_fname == NULL) {
7043 return false;
7046 if (!torture_open_connection(&cli, i)) {
7047 return false;
7050 status = cli_ntcreate(cli, dname, 0,
7051 MAXIMUM_ALLOWED_ACCESS,
7052 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
7053 FILE_SHARE_DELETE,
7054 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
7055 &dnum, NULL);
7057 if (!NT_STATUS_IS_OK(status)) {
7058 d_printf("Could not create %s: %s\n", dname,
7059 nt_errstr(status));
7060 return false;
7063 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
7064 FILE_NOTIFY_CHANGE_FILE_NAME |
7065 FILE_NOTIFY_CHANGE_DIR_NAME |
7066 FILE_NOTIFY_CHANGE_ATTRIBUTES |
7067 FILE_NOTIFY_CHANGE_LAST_WRITE,
7068 false, print_notifies, NULL);
7069 if (req1 == NULL) {
7070 d_printf("Could not create notify request\n");
7071 return false;
7074 req2 = torture_createdels_send(talloc_tos(), ev, cli,
7075 base_fname, 10, torture_numops);
7076 if (req2 == NULL) {
7077 d_printf("Could not create createdels request\n");
7078 return false;
7080 TALLOC_FREE(base_fname);
7082 tevent_req_set_callback(req2, notify_bench_done,
7083 &num_finished);
7086 while (num_finished < num_unc_names) {
7087 int ret;
7088 ret = tevent_loop_once(ev);
7089 if (ret != 0) {
7090 d_printf("tevent_loop_once failed\n");
7091 return false;
7095 if (!tevent_req_poll(req2, ev)) {
7096 d_printf("tevent_req_poll failed\n");
7099 status = torture_createdels_recv(req2);
7100 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
7102 return true;
7105 static bool run_mangle1(int dummy)
7107 struct cli_state *cli;
7108 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
7109 uint16_t fnum;
7110 fstring alt_name;
7111 NTSTATUS status;
7112 time_t change_time, access_time, write_time;
7113 off_t size;
7114 uint16_t mode;
7116 printf("starting mangle1 test\n");
7117 if (!torture_open_connection(&cli, 0)) {
7118 return False;
7121 smbXcli_conn_set_sockopt(cli->conn, sockops);
7123 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7124 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7125 0, 0, &fnum, NULL);
7126 if (!NT_STATUS_IS_OK(status)) {
7127 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7128 return false;
7130 cli_close(cli, fnum);
7132 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
7133 if (!NT_STATUS_IS_OK(status)) {
7134 d_printf("cli_qpathinfo_alt_name failed: %s\n",
7135 nt_errstr(status));
7136 return false;
7138 d_printf("alt_name: %s\n", alt_name);
7140 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
7141 if (!NT_STATUS_IS_OK(status)) {
7142 d_printf("cli_openx(%s) failed: %s\n", alt_name,
7143 nt_errstr(status));
7144 return false;
7146 cli_close(cli, fnum);
7148 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
7149 &write_time, &size, &mode);
7150 if (!NT_STATUS_IS_OK(status)) {
7151 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
7152 nt_errstr(status));
7153 return false;
7156 return true;
7159 static size_t null_source(uint8_t *buf, size_t n, void *priv)
7161 size_t *to_pull = (size_t *)priv;
7162 size_t thistime = *to_pull;
7164 thistime = MIN(thistime, n);
7165 if (thistime == 0) {
7166 return 0;
7169 memset(buf, 0, thistime);
7170 *to_pull -= thistime;
7171 return thistime;
7174 static bool run_windows_write(int dummy)
7176 struct cli_state *cli1;
7177 uint16_t fnum;
7178 int i;
7179 bool ret = false;
7180 const char *fname = "\\writetest.txt";
7181 struct timeval start_time;
7182 double seconds;
7183 double kbytes;
7184 NTSTATUS status;
7186 printf("starting windows_write test\n");
7187 if (!torture_open_connection(&cli1, 0)) {
7188 return False;
7191 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7192 if (!NT_STATUS_IS_OK(status)) {
7193 printf("open failed (%s)\n", nt_errstr(status));
7194 return False;
7197 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7199 start_time = timeval_current();
7201 for (i=0; i<torture_numops; i++) {
7202 uint8_t c = 0;
7203 off_t start = i * torture_blocksize;
7204 size_t to_pull = torture_blocksize - 1;
7206 status = cli_writeall(cli1, fnum, 0, &c,
7207 start + torture_blocksize - 1, 1, NULL);
7208 if (!NT_STATUS_IS_OK(status)) {
7209 printf("cli_write failed: %s\n", nt_errstr(status));
7210 goto fail;
7213 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
7214 null_source, &to_pull);
7215 if (!NT_STATUS_IS_OK(status)) {
7216 printf("cli_push returned: %s\n", nt_errstr(status));
7217 goto fail;
7221 seconds = timeval_elapsed(&start_time);
7222 kbytes = (double)torture_blocksize * torture_numops;
7223 kbytes /= 1024;
7225 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
7226 (double)seconds, (int)(kbytes/seconds));
7228 ret = true;
7229 fail:
7230 cli_close(cli1, fnum);
7231 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7232 torture_close_connection(cli1);
7233 return ret;
7236 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
7238 size_t max_pdu = 0x1FFFF;
7240 if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
7241 max_pdu = 0xFFFFFF;
7244 if (smb1cli_conn_signing_is_active(cli->conn)) {
7245 max_pdu = 0x1FFFF;
7248 if (smb1cli_conn_encryption_on(cli->conn)) {
7249 max_pdu = CLI_BUFFER_SIZE;
7252 if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
7253 len_requested &= 0xFFFF;
7256 return MIN(len_requested,
7257 max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
7260 static bool check_read_call(struct cli_state *cli,
7261 uint16_t fnum,
7262 uint8_t *buf,
7263 size_t len_requested)
7265 NTSTATUS status;
7266 struct tevent_req *subreq = NULL;
7267 ssize_t len_read = 0;
7268 size_t len_expected = 0;
7269 struct tevent_context *ev = NULL;
7271 ev = samba_tevent_context_init(talloc_tos());
7272 if (ev == NULL) {
7273 return false;
7276 subreq = cli_read_andx_send(talloc_tos(),
7278 cli,
7279 fnum,
7281 len_requested);
7283 if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
7284 return false;
7287 status = cli_read_andx_recv(subreq, &len_read, &buf);
7288 if (!NT_STATUS_IS_OK(status)) {
7289 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
7290 return false;
7293 TALLOC_FREE(subreq);
7294 TALLOC_FREE(ev);
7296 len_expected = calc_expected_return(cli, len_requested);
7298 if (len_expected > 0x10000 && len_read == 0x10000) {
7299 /* Windows servers only return a max of 0x10000,
7300 doesn't matter if you set CAP_LARGE_READX in
7301 the client sessionsetupX call or not. */
7302 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
7303 (unsigned int)len_requested);
7304 } else if (len_read != len_expected) {
7305 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
7306 (unsigned int)len_requested,
7307 (unsigned int)len_read,
7308 (unsigned int)len_expected);
7309 return false;
7310 } else {
7311 d_printf("Correct read reply.\n");
7314 return true;
7317 /* Test large readX variants. */
7318 static bool large_readx_tests(struct cli_state *cli,
7319 uint16_t fnum,
7320 uint8_t *buf)
7322 /* A read of 0xFFFF0001 should *always* return 1 byte. */
7323 if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
7324 return false;
7326 /* A read of 0x10000 should return 0x10000 bytes. */
7327 if (check_read_call(cli, fnum, buf, 0x10000) == false) {
7328 return false;
7330 /* A read of 0x10000 should return 0x10001 bytes. */
7331 if (check_read_call(cli, fnum, buf, 0x10001) == false) {
7332 return false;
7334 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
7335 the requested number of bytes. */
7336 if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
7337 return false;
7339 /* A read of 1MB should return 1MB bytes (on Samba). */
7340 if (check_read_call(cli, fnum, buf, 0x100000) == false) {
7341 return false;
7344 if (check_read_call(cli, fnum, buf, 0x20001) == false) {
7345 return false;
7347 if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
7348 return false;
7350 if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
7351 return false;
7353 return true;
7356 static bool run_large_readx(int dummy)
7358 uint8_t *buf = NULL;
7359 struct cli_state *cli1 = NULL;
7360 struct cli_state *cli2 = NULL;
7361 bool correct = false;
7362 const char *fname = "\\large_readx.dat";
7363 NTSTATUS status;
7364 uint16_t fnum1 = UINT16_MAX;
7365 uint32_t normal_caps = 0;
7366 size_t file_size = 20*1024*1024;
7367 TALLOC_CTX *frame = talloc_stackframe();
7368 size_t i;
7369 struct {
7370 const char *name;
7371 enum smb_signing_setting signing_setting;
7372 enum protocol_types protocol;
7373 } runs[] = {
7375 .name = "NT1",
7376 .signing_setting = SMB_SIGNING_IF_REQUIRED,
7377 .protocol = PROTOCOL_NT1,
7379 .name = "NT1 - SIGNING_REQUIRED",
7380 .signing_setting = SMB_SIGNING_REQUIRED,
7381 .protocol = PROTOCOL_NT1,
7385 printf("starting large_readx test\n");
7387 if (!torture_open_connection(&cli1, 0)) {
7388 goto out;
7391 normal_caps = smb1cli_conn_capabilities(cli1->conn);
7393 if (!(normal_caps & CAP_LARGE_READX)) {
7394 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
7395 (unsigned int)normal_caps);
7396 goto out;
7399 /* Create a file of size 4MB. */
7400 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
7401 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7402 0, 0, &fnum1, NULL);
7404 if (!NT_STATUS_IS_OK(status)) {
7405 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7406 goto out;
7409 /* Write file_size bytes. */
7410 buf = talloc_zero_array(frame, uint8_t, file_size);
7411 if (buf == NULL) {
7412 goto out;
7415 status = cli_writeall(cli1,
7416 fnum1,
7418 buf,
7420 file_size,
7421 NULL);
7422 if (!NT_STATUS_IS_OK(status)) {
7423 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
7424 goto out;
7427 status = cli_close(cli1, fnum1);
7428 if (!NT_STATUS_IS_OK(status)) {
7429 d_printf("cli_close failed: %s\n", nt_errstr(status));
7430 goto out;
7433 fnum1 = UINT16_MAX;
7435 for (i=0; i < ARRAY_SIZE(runs); i++) {
7436 enum smb_signing_setting saved_signing_setting = signing_state;
7437 uint16_t fnum2 = -1;
7439 if (do_encrypt &&
7440 (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
7442 d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
7443 continue;
7446 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
7448 signing_state = runs[i].signing_setting;
7449 cli2 = open_nbt_connection();
7450 signing_state = saved_signing_setting;
7451 if (cli2 == NULL) {
7452 goto out;
7455 status = smbXcli_negprot(cli2->conn,
7456 cli2->timeout,
7457 runs[i].protocol,
7458 runs[i].protocol);
7459 if (!NT_STATUS_IS_OK(status)) {
7460 goto out;
7463 status = cli_session_setup(cli2,
7464 username,
7465 password,
7466 strlen(password)+1,
7467 password,
7468 strlen(password)+1,
7469 workgroup);
7470 if (!NT_STATUS_IS_OK(status)) {
7471 goto out;
7474 status = cli_tree_connect(cli2,
7475 share,
7476 "?????",
7477 password,
7478 strlen(password)+1);
7479 if (!NT_STATUS_IS_OK(status)) {
7480 goto out;
7483 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
7485 normal_caps = smb1cli_conn_capabilities(cli2->conn);
7487 if (!(normal_caps & CAP_LARGE_READX)) {
7488 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
7489 (unsigned int)normal_caps);
7490 goto out;
7493 if (do_encrypt) {
7494 if (force_cli_encryption(cli2, share) == false) {
7495 goto out;
7497 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
7498 uint16_t major, minor;
7499 uint32_t caplow, caphigh;
7501 status = cli_unix_extensions_version(cli2,
7502 &major, &minor,
7503 &caplow, &caphigh);
7504 if (!NT_STATUS_IS_OK(status)) {
7505 goto out;
7509 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
7510 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
7511 0, 0, &fnum2, NULL);
7512 if (!NT_STATUS_IS_OK(status)) {
7513 d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
7514 goto out;
7517 /* All reads must return less than file_size bytes. */
7518 if (!large_readx_tests(cli2, fnum2, buf)) {
7519 goto out;
7522 status = cli_close(cli2, fnum2);
7523 if (!NT_STATUS_IS_OK(status)) {
7524 d_printf("cli_close failed: %s\n", nt_errstr(status));
7525 goto out;
7527 fnum2 = -1;
7529 if (!torture_close_connection(cli2)) {
7530 goto out;
7532 cli2 = NULL;
7535 correct = true;
7536 printf("Success on large_readx test\n");
7538 out:
7540 if (cli2) {
7541 if (!torture_close_connection(cli2)) {
7542 correct = false;
7546 if (cli1) {
7547 if (fnum1 != UINT16_MAX) {
7548 status = cli_close(cli1, fnum1);
7549 if (!NT_STATUS_IS_OK(status)) {
7550 d_printf("cli_close failed: %s\n", nt_errstr(status));
7552 fnum1 = UINT16_MAX;
7555 status = cli_unlink(cli1, fname,
7556 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7557 if (!NT_STATUS_IS_OK(status)) {
7558 printf("unlink failed (%s)\n", nt_errstr(status));
7561 if (!torture_close_connection(cli1)) {
7562 correct = false;
7566 TALLOC_FREE(frame);
7568 printf("finished large_readx test\n");
7569 return correct;
7572 static bool run_cli_echo(int dummy)
7574 struct cli_state *cli;
7575 NTSTATUS status;
7577 printf("starting cli_echo test\n");
7578 if (!torture_open_connection(&cli, 0)) {
7579 return false;
7581 smbXcli_conn_set_sockopt(cli->conn, sockops);
7583 status = cli_echo(cli, 5, data_blob_const("hello", 5));
7585 d_printf("cli_echo returned %s\n", nt_errstr(status));
7587 torture_close_connection(cli);
7588 return NT_STATUS_IS_OK(status);
7591 static bool run_uid_regression_test(int dummy)
7593 static struct cli_state *cli;
7594 int16_t old_vuid;
7595 int16_t old_cnum;
7596 bool correct = True;
7597 NTSTATUS status;
7599 printf("starting uid regression test\n");
7601 if (!torture_open_connection(&cli, 0)) {
7602 return False;
7605 smbXcli_conn_set_sockopt(cli->conn, sockops);
7607 /* Ok - now save then logoff our current user. */
7608 old_vuid = cli_state_get_uid(cli);
7610 status = cli_ulogoff(cli);
7611 if (!NT_STATUS_IS_OK(status)) {
7612 d_printf("(%s) cli_ulogoff failed: %s\n",
7613 __location__, nt_errstr(status));
7614 correct = false;
7615 goto out;
7618 cli_state_set_uid(cli, old_vuid);
7620 /* Try an operation. */
7621 status = cli_mkdir(cli, "\\uid_reg_test");
7622 if (NT_STATUS_IS_OK(status)) {
7623 d_printf("(%s) cli_mkdir succeeded\n",
7624 __location__);
7625 correct = false;
7626 goto out;
7627 } else {
7628 /* Should be bad uid. */
7629 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
7630 NT_STATUS_USER_SESSION_DELETED)) {
7631 correct = false;
7632 goto out;
7636 old_cnum = cli_state_get_tid(cli);
7638 /* Now try a SMBtdis with the invald vuid set to zero. */
7639 cli_state_set_uid(cli, 0);
7641 /* This should succeed. */
7642 status = cli_tdis(cli);
7644 if (NT_STATUS_IS_OK(status)) {
7645 d_printf("First tdis with invalid vuid should succeed.\n");
7646 } else {
7647 d_printf("First tdis failed (%s)\n", nt_errstr(status));
7648 correct = false;
7649 goto out;
7652 cli_state_set_uid(cli, old_vuid);
7653 cli_state_set_tid(cli, old_cnum);
7655 /* This should fail. */
7656 status = cli_tdis(cli);
7657 if (NT_STATUS_IS_OK(status)) {
7658 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
7659 correct = false;
7660 goto out;
7661 } else {
7662 /* Should be bad tid. */
7663 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
7664 NT_STATUS_NETWORK_NAME_DELETED)) {
7665 correct = false;
7666 goto out;
7670 cli_rmdir(cli, "\\uid_reg_test");
7672 out:
7674 cli_shutdown(cli);
7675 return correct;
7679 static const char *illegal_chars = "*\\/?<>|\":";
7680 static char force_shortname_chars[] = " +,.[];=\177";
7682 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
7683 const char *mask, void *state)
7685 struct cli_state *pcli = (struct cli_state *)state;
7686 fstring fname;
7687 NTSTATUS status = NT_STATUS_OK;
7689 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
7691 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7692 return NT_STATUS_OK;
7694 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7695 status = cli_rmdir(pcli, fname);
7696 if (!NT_STATUS_IS_OK(status)) {
7697 printf("del_fn: failed to rmdir %s\n,", fname );
7699 } else {
7700 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7701 if (!NT_STATUS_IS_OK(status)) {
7702 printf("del_fn: failed to unlink %s\n,", fname );
7705 return status;
7708 struct sn_state {
7709 int matched;
7710 int i;
7711 bool val;
7714 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
7715 const char *name, void *state)
7717 struct sn_state *s = (struct sn_state *)state;
7718 int i = s->i;
7720 #if 0
7721 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
7722 i, finfo->name, finfo->short_name);
7723 #endif
7725 if (strchr(force_shortname_chars, i)) {
7726 if (!finfo->short_name) {
7727 /* Shortname not created when it should be. */
7728 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
7729 __location__, finfo->name, i);
7730 s->val = true;
7732 } else if (finfo->short_name){
7733 /* Shortname created when it should not be. */
7734 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
7735 __location__, finfo->short_name, finfo->name);
7736 s->val = true;
7738 s->matched += 1;
7739 return NT_STATUS_OK;
7742 static bool run_shortname_test(int dummy)
7744 static struct cli_state *cli;
7745 bool correct = True;
7746 int i;
7747 struct sn_state s;
7748 char fname[40];
7749 NTSTATUS status;
7751 printf("starting shortname test\n");
7753 if (!torture_open_connection(&cli, 0)) {
7754 return False;
7757 smbXcli_conn_set_sockopt(cli->conn, sockops);
7759 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7760 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7761 cli_rmdir(cli, "\\shortname");
7763 status = cli_mkdir(cli, "\\shortname");
7764 if (!NT_STATUS_IS_OK(status)) {
7765 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
7766 __location__, nt_errstr(status));
7767 correct = false;
7768 goto out;
7771 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
7772 correct = false;
7773 goto out;
7775 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
7776 correct = false;
7777 goto out;
7780 s.val = false;
7782 for (i = 32; i < 128; i++) {
7783 uint16_t fnum = (uint16_t)-1;
7785 s.i = i;
7787 if (strchr(illegal_chars, i)) {
7788 continue;
7790 fname[15] = i;
7792 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
7793 FILE_SHARE_READ|FILE_SHARE_WRITE,
7794 FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
7795 if (!NT_STATUS_IS_OK(status)) {
7796 d_printf("(%s) cli_nt_create of %s failed: %s\n",
7797 __location__, fname, nt_errstr(status));
7798 correct = false;
7799 goto out;
7801 cli_close(cli, fnum);
7803 s.matched = 0;
7804 status = cli_list(cli, "\\shortname\\test*.*", 0,
7805 shortname_list_fn, &s);
7806 if (s.matched != 1) {
7807 d_printf("(%s) failed to list %s: %s\n",
7808 __location__, fname, nt_errstr(status));
7809 correct = false;
7810 goto out;
7813 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7814 if (!NT_STATUS_IS_OK(status)) {
7815 d_printf("(%s) failed to delete %s: %s\n",
7816 __location__, fname, nt_errstr(status));
7817 correct = false;
7818 goto out;
7821 if (s.val) {
7822 correct = false;
7823 goto out;
7827 out:
7829 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7830 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7831 cli_rmdir(cli, "\\shortname");
7832 torture_close_connection(cli);
7833 return correct;
7836 static void pagedsearch_cb(struct tevent_req *req)
7838 int rc;
7839 struct tldap_message *msg;
7840 char *dn;
7842 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
7843 if (rc != TLDAP_SUCCESS) {
7844 d_printf("tldap_search_paged_recv failed: %s\n",
7845 tldap_err2string(rc));
7846 return;
7848 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
7849 TALLOC_FREE(msg);
7850 return;
7852 if (!tldap_entry_dn(msg, &dn)) {
7853 d_printf("tldap_entry_dn failed\n");
7854 return;
7856 d_printf("%s\n", dn);
7857 TALLOC_FREE(msg);
7860 static bool run_tldap(int dummy)
7862 struct tldap_context *ld;
7863 int fd, rc;
7864 NTSTATUS status;
7865 struct sockaddr_storage addr;
7866 struct tevent_context *ev;
7867 struct tevent_req *req;
7868 char *basedn;
7869 const char *filter;
7871 if (!resolve_name(host, &addr, 0, false)) {
7872 d_printf("could not find host %s\n", host);
7873 return false;
7875 status = open_socket_out(&addr, 389, 9999, &fd);
7876 if (!NT_STATUS_IS_OK(status)) {
7877 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
7878 return false;
7881 ld = tldap_context_create(talloc_tos(), fd);
7882 if (ld == NULL) {
7883 close(fd);
7884 d_printf("tldap_context_create failed\n");
7885 return false;
7888 rc = tldap_fetch_rootdse(ld);
7889 if (rc != TLDAP_SUCCESS) {
7890 d_printf("tldap_fetch_rootdse failed: %s\n",
7891 tldap_errstr(talloc_tos(), ld, rc));
7892 return false;
7895 basedn = tldap_talloc_single_attribute(
7896 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
7897 if (basedn == NULL) {
7898 d_printf("no defaultNamingContext\n");
7899 return false;
7901 d_printf("defaultNamingContext: %s\n", basedn);
7903 ev = samba_tevent_context_init(talloc_tos());
7904 if (ev == NULL) {
7905 d_printf("tevent_context_init failed\n");
7906 return false;
7909 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
7910 TLDAP_SCOPE_SUB, "(objectclass=*)",
7911 NULL, 0, 0,
7912 NULL, 0, NULL, 0, 0, 0, 0, 5);
7913 if (req == NULL) {
7914 d_printf("tldap_search_paged_send failed\n");
7915 return false;
7917 tevent_req_set_callback(req, pagedsearch_cb, NULL);
7919 tevent_req_poll(req, ev);
7921 TALLOC_FREE(req);
7923 /* test search filters against rootDSE */
7924 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
7925 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
7927 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
7928 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
7929 talloc_tos(), NULL, NULL);
7930 if (rc != TLDAP_SUCCESS) {
7931 d_printf("tldap_search with complex filter failed: %s\n",
7932 tldap_errstr(talloc_tos(), ld, rc));
7933 return false;
7936 TALLOC_FREE(ld);
7937 return true;
7940 /* Torture test to ensure no regression of :
7941 https://bugzilla.samba.org/show_bug.cgi?id=7084
7944 static bool run_dir_createtime(int dummy)
7946 struct cli_state *cli;
7947 const char *dname = "\\testdir";
7948 const char *fname = "\\testdir\\testfile";
7949 NTSTATUS status;
7950 struct timespec create_time;
7951 struct timespec create_time1;
7952 uint16_t fnum;
7953 bool ret = false;
7955 if (!torture_open_connection(&cli, 0)) {
7956 return false;
7959 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7960 cli_rmdir(cli, dname);
7962 status = cli_mkdir(cli, dname);
7963 if (!NT_STATUS_IS_OK(status)) {
7964 printf("mkdir failed: %s\n", nt_errstr(status));
7965 goto out;
7968 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
7969 NULL, NULL, NULL);
7970 if (!NT_STATUS_IS_OK(status)) {
7971 printf("cli_qpathinfo2 returned %s\n",
7972 nt_errstr(status));
7973 goto out;
7976 /* Sleep 3 seconds, then create a file. */
7977 sleep(3);
7979 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
7980 DENY_NONE, &fnum);
7981 if (!NT_STATUS_IS_OK(status)) {
7982 printf("cli_openx failed: %s\n", nt_errstr(status));
7983 goto out;
7986 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
7987 NULL, NULL, NULL);
7988 if (!NT_STATUS_IS_OK(status)) {
7989 printf("cli_qpathinfo2 (2) returned %s\n",
7990 nt_errstr(status));
7991 goto out;
7994 if (timespec_compare(&create_time1, &create_time)) {
7995 printf("run_dir_createtime: create time was updated (error)\n");
7996 } else {
7997 printf("run_dir_createtime: create time was not updated (correct)\n");
7998 ret = true;
8001 out:
8003 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8004 cli_rmdir(cli, dname);
8005 if (!torture_close_connection(cli)) {
8006 ret = false;
8008 return ret;
8012 static bool run_streamerror(int dummy)
8014 struct cli_state *cli;
8015 const char *dname = "\\testdir";
8016 const char *streamname =
8017 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
8018 NTSTATUS status;
8019 time_t change_time, access_time, write_time;
8020 off_t size;
8021 uint16_t mode, fnum;
8022 bool ret = true;
8024 if (!torture_open_connection(&cli, 0)) {
8025 return false;
8028 cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8029 cli_rmdir(cli, dname);
8031 status = cli_mkdir(cli, dname);
8032 if (!NT_STATUS_IS_OK(status)) {
8033 printf("mkdir failed: %s\n", nt_errstr(status));
8034 return false;
8037 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
8038 &write_time, &size, &mode);
8039 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
8040 printf("pathinfo returned %s, expected "
8041 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
8042 nt_errstr(status));
8043 ret = false;
8046 status = cli_ntcreate(cli, streamname, 0x16,
8047 FILE_READ_DATA|FILE_READ_EA|
8048 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
8049 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
8050 FILE_OPEN, 0, 0, &fnum, NULL);
8052 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
8053 printf("ntcreate returned %s, expected "
8054 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
8055 nt_errstr(status));
8056 ret = false;
8060 cli_rmdir(cli, dname);
8061 return ret;
8064 static bool run_local_substitute(int dummy)
8066 bool ok = true;
8068 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
8069 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
8070 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
8071 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
8072 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
8073 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
8074 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
8075 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
8077 /* Different captialization rules in sub_basic... */
8079 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
8080 "blaDOM") == 0);
8082 return ok;
8085 static bool run_local_base64(int dummy)
8087 int i;
8088 bool ret = true;
8090 for (i=1; i<2000; i++) {
8091 DATA_BLOB blob1, blob2;
8092 char *b64;
8094 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
8095 blob1.length = i;
8096 generate_random_buffer(blob1.data, blob1.length);
8098 b64 = base64_encode_data_blob(talloc_tos(), blob1);
8099 if (b64 == NULL) {
8100 d_fprintf(stderr, "base64_encode_data_blob failed "
8101 "for %d bytes\n", i);
8102 ret = false;
8104 blob2 = base64_decode_data_blob(b64);
8105 TALLOC_FREE(b64);
8107 if (data_blob_cmp(&blob1, &blob2)) {
8108 d_fprintf(stderr, "data_blob_cmp failed for %d "
8109 "bytes\n", i);
8110 ret = false;
8112 TALLOC_FREE(blob1.data);
8113 data_blob_free(&blob2);
8115 return ret;
8118 static void parse_fn(time_t timeout, DATA_BLOB blob, void *private_data)
8120 return;
8123 static bool run_local_gencache(int dummy)
8125 char *val;
8126 time_t tm;
8127 DATA_BLOB blob;
8128 char v;
8129 struct memcache *mem;
8130 int i;
8132 mem = memcache_init(NULL, 0);
8133 if (mem == NULL) {
8134 d_printf("%s: memcache_init failed\n", __location__);
8135 return false;
8137 memcache_set_global(mem);
8139 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
8140 d_printf("%s: gencache_set() failed\n", __location__);
8141 return False;
8144 if (!gencache_get("foo", NULL, NULL, NULL)) {
8145 d_printf("%s: gencache_get() failed\n", __location__);
8146 return False;
8149 for (i=0; i<1000000; i++) {
8150 gencache_parse("foo", parse_fn, NULL);
8153 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
8154 d_printf("%s: gencache_get() failed\n", __location__);
8155 return False;
8157 TALLOC_FREE(val);
8159 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
8160 d_printf("%s: gencache_get() failed\n", __location__);
8161 return False;
8164 if (strcmp(val, "bar") != 0) {
8165 d_printf("%s: gencache_get() returned %s, expected %s\n",
8166 __location__, val, "bar");
8167 TALLOC_FREE(val);
8168 return False;
8171 TALLOC_FREE(val);
8173 if (!gencache_del("foo")) {
8174 d_printf("%s: gencache_del() failed\n", __location__);
8175 return False;
8177 if (gencache_del("foo")) {
8178 d_printf("%s: second gencache_del() succeeded\n",
8179 __location__);
8180 return False;
8183 if (gencache_get("foo", talloc_tos(), &val, &tm)) {
8184 d_printf("%s: gencache_get() on deleted entry "
8185 "succeeded\n", __location__);
8186 return False;
8189 blob = data_blob_string_const_null("bar");
8190 tm = time(NULL) + 60;
8192 if (!gencache_set_data_blob("foo", &blob, tm)) {
8193 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
8194 return False;
8197 if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
8198 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
8199 return False;
8202 if (strcmp((const char *)blob.data, "bar") != 0) {
8203 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
8204 __location__, (const char *)blob.data, "bar");
8205 data_blob_free(&blob);
8206 return False;
8209 data_blob_free(&blob);
8211 if (!gencache_del("foo")) {
8212 d_printf("%s: gencache_del() failed\n", __location__);
8213 return False;
8215 if (gencache_del("foo")) {
8216 d_printf("%s: second gencache_del() succeeded\n",
8217 __location__);
8218 return False;
8221 if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
8222 d_printf("%s: gencache_get_data_blob() on deleted entry "
8223 "succeeded\n", __location__);
8224 return False;
8227 v = 1;
8228 blob.data = (uint8_t *)&v;
8229 blob.length = sizeof(v);
8231 if (!gencache_set_data_blob("blob", &blob, tm)) {
8232 d_printf("%s: gencache_set_data_blob() failed\n",
8233 __location__);
8234 return false;
8236 if (gencache_get("blob", talloc_tos(), &val, &tm)) {
8237 d_printf("%s: gencache_get succeeded\n", __location__);
8238 return false;
8241 return True;
8244 static bool rbt_testval(struct db_context *db, const char *key,
8245 const char *value)
8247 struct db_record *rec;
8248 TDB_DATA data = string_tdb_data(value);
8249 bool ret = false;
8250 NTSTATUS status;
8251 TDB_DATA dbvalue;
8253 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
8254 if (rec == NULL) {
8255 d_fprintf(stderr, "fetch_locked failed\n");
8256 goto done;
8258 status = dbwrap_record_store(rec, data, 0);
8259 if (!NT_STATUS_IS_OK(status)) {
8260 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
8261 goto done;
8263 TALLOC_FREE(rec);
8265 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
8266 if (rec == NULL) {
8267 d_fprintf(stderr, "second fetch_locked failed\n");
8268 goto done;
8271 dbvalue = dbwrap_record_get_value(rec);
8272 if ((dbvalue.dsize != data.dsize)
8273 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
8274 d_fprintf(stderr, "Got wrong data back\n");
8275 goto done;
8278 ret = true;
8279 done:
8280 TALLOC_FREE(rec);
8281 return ret;
8284 static bool run_local_rbtree(int dummy)
8286 struct db_context *db;
8287 bool ret = false;
8288 int i;
8290 db = db_open_rbt(NULL);
8292 if (db == NULL) {
8293 d_fprintf(stderr, "db_open_rbt failed\n");
8294 return false;
8297 for (i=0; i<1000; i++) {
8298 char *key, *value;
8300 if (asprintf(&key, "key%ld", random()) == -1) {
8301 goto done;
8303 if (asprintf(&value, "value%ld", random()) == -1) {
8304 SAFE_FREE(key);
8305 goto done;
8308 if (!rbt_testval(db, key, value)) {
8309 SAFE_FREE(key);
8310 SAFE_FREE(value);
8311 goto done;
8314 SAFE_FREE(value);
8315 if (asprintf(&value, "value%ld", random()) == -1) {
8316 SAFE_FREE(key);
8317 goto done;
8320 if (!rbt_testval(db, key, value)) {
8321 SAFE_FREE(key);
8322 SAFE_FREE(value);
8323 goto done;
8326 SAFE_FREE(key);
8327 SAFE_FREE(value);
8330 ret = true;
8332 done:
8333 TALLOC_FREE(db);
8334 return ret;
8339 local test for character set functions
8341 This is a very simple test for the functionality in convert_string_error()
8343 static bool run_local_convert_string(int dummy)
8345 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
8346 const char *test_strings[2] = { "March", "M\303\244rz" };
8347 char dst[7];
8348 int i;
8350 for (i=0; i<2; i++) {
8351 const char *str = test_strings[i];
8352 int len = strlen(str);
8353 size_t converted_size;
8354 bool ret;
8356 memset(dst, 'X', sizeof(dst));
8358 /* first try with real source length */
8359 ret = convert_string_error(CH_UNIX, CH_UTF8,
8360 str, len,
8361 dst, sizeof(dst),
8362 &converted_size);
8363 if (ret != true) {
8364 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
8365 goto failed;
8368 if (converted_size != len) {
8369 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
8370 str, len, (int)converted_size);
8371 goto failed;
8374 if (strncmp(str, dst, converted_size) != 0) {
8375 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
8376 goto failed;
8379 if (strlen(str) != converted_size) {
8380 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
8381 (int)strlen(str), (int)converted_size);
8382 goto failed;
8385 if (dst[converted_size] != 'X') {
8386 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
8387 goto failed;
8390 /* now with srclen==-1, this causes the nul to be
8391 * converted too */
8392 ret = convert_string_error(CH_UNIX, CH_UTF8,
8393 str, -1,
8394 dst, sizeof(dst),
8395 &converted_size);
8396 if (ret != true) {
8397 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
8398 goto failed;
8401 if (converted_size != len+1) {
8402 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
8403 str, len, (int)converted_size);
8404 goto failed;
8407 if (strncmp(str, dst, converted_size) != 0) {
8408 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
8409 goto failed;
8412 if (len+1 != converted_size) {
8413 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
8414 len+1, (int)converted_size);
8415 goto failed;
8418 if (dst[converted_size] != 'X') {
8419 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
8420 goto failed;
8426 TALLOC_FREE(tmp_ctx);
8427 return true;
8428 failed:
8429 TALLOC_FREE(tmp_ctx);
8430 return false;
8434 struct talloc_dict_test {
8435 int content;
8438 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
8440 int *count = (int *)priv;
8441 *count += 1;
8442 return 0;
8445 static bool run_local_talloc_dict(int dummy)
8447 struct talloc_dict *dict;
8448 struct talloc_dict_test *t;
8449 int key, count, res;
8450 bool ok;
8452 dict = talloc_dict_init(talloc_tos());
8453 if (dict == NULL) {
8454 return false;
8457 t = talloc(talloc_tos(), struct talloc_dict_test);
8458 if (t == NULL) {
8459 return false;
8462 key = 1;
8463 t->content = 1;
8464 ok = talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), &t);
8465 if (!ok) {
8466 return false;
8469 count = 0;
8470 res = talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count);
8471 if (res == -1) {
8472 return false;
8475 if (count != 1) {
8476 return false;
8479 if (count != res) {
8480 return false;
8483 TALLOC_FREE(dict);
8485 return true;
8488 static bool run_local_string_to_sid(int dummy) {
8489 struct dom_sid sid;
8491 if (string_to_sid(&sid, "S--1-5-32-545")) {
8492 printf("allowing S--1-5-32-545\n");
8493 return false;
8495 if (string_to_sid(&sid, "S-1-5-32-+545")) {
8496 printf("allowing S-1-5-32-+545\n");
8497 return false;
8499 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")) {
8500 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
8501 return false;
8503 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
8504 printf("allowing S-1-5-32-545-abc\n");
8505 return false;
8507 if (string_to_sid(&sid, "S-300-5-32-545")) {
8508 printf("allowing S-300-5-32-545\n");
8509 return false;
8511 if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
8512 printf("allowing S-1-0xfffffffffffffe-32-545\n");
8513 return false;
8515 if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
8516 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
8517 return false;
8519 if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
8520 printf("could not parse S-1-0xfffffffffffe-32-545\n");
8521 return false;
8523 if (!string_to_sid(&sid, "S-1-5-32-545")) {
8524 printf("could not parse S-1-5-32-545\n");
8525 return false;
8527 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
8528 printf("mis-parsed S-1-5-32-545 as %s\n",
8529 sid_string_tos(&sid));
8530 return false;
8532 return true;
8535 static bool sid_to_string_test(const char *expected) {
8536 char *str;
8537 bool res = true;
8538 struct dom_sid sid;
8540 if (!string_to_sid(&sid, expected)) {
8541 printf("could not parse %s\n", expected);
8542 return false;
8545 str = dom_sid_string(NULL, &sid);
8546 if (strcmp(str, expected)) {
8547 printf("Comparison failed (%s != %s)\n", str, expected);
8548 res = false;
8550 TALLOC_FREE(str);
8551 return res;
8554 static bool run_local_sid_to_string(int dummy) {
8555 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
8556 return false;
8557 if (!sid_to_string_test("S-1-545"))
8558 return false;
8559 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
8560 return false;
8561 return true;
8564 static bool run_local_binary_to_sid(int dummy) {
8565 struct dom_sid *sid = talloc(NULL, struct dom_sid);
8566 static const char good_binary_sid[] = {
8567 0x1, /* revision number */
8568 15, /* num auths */
8569 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8570 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8571 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8572 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8573 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8574 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8575 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8576 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8577 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8578 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8579 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8580 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8581 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8582 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8583 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8584 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8587 static const char long_binary_sid[] = {
8588 0x1, /* revision number */
8589 15, /* num auths */
8590 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8591 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8592 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8593 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8594 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8595 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8596 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8597 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8598 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8599 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8600 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8601 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8602 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8603 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8604 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8605 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8606 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8607 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8608 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8611 static const char long_binary_sid2[] = {
8612 0x1, /* revision number */
8613 32, /* num auths */
8614 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8615 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8616 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8617 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8618 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8619 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8620 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8621 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8622 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8623 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8624 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8625 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8626 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8627 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8628 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8629 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8630 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8631 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8632 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8633 0x1, 0x1, 0x1, 0x1, /* auth[18] */
8634 0x1, 0x1, 0x1, 0x1, /* auth[19] */
8635 0x1, 0x1, 0x1, 0x1, /* auth[20] */
8636 0x1, 0x1, 0x1, 0x1, /* auth[21] */
8637 0x1, 0x1, 0x1, 0x1, /* auth[22] */
8638 0x1, 0x1, 0x1, 0x1, /* auth[23] */
8639 0x1, 0x1, 0x1, 0x1, /* auth[24] */
8640 0x1, 0x1, 0x1, 0x1, /* auth[25] */
8641 0x1, 0x1, 0x1, 0x1, /* auth[26] */
8642 0x1, 0x1, 0x1, 0x1, /* auth[27] */
8643 0x1, 0x1, 0x1, 0x1, /* auth[28] */
8644 0x1, 0x1, 0x1, 0x1, /* auth[29] */
8645 0x1, 0x1, 0x1, 0x1, /* auth[30] */
8646 0x1, 0x1, 0x1, 0x1, /* auth[31] */
8649 if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
8650 return false;
8652 if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
8653 return false;
8655 if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
8656 return false;
8658 return true;
8661 /* Split a path name into filename and stream name components. Canonicalise
8662 * such that an implicit $DATA token is always explicit.
8664 * The "specification" of this function can be found in the
8665 * run_local_stream_name() function in torture.c, I've tried those
8666 * combinations against a W2k3 server.
8669 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
8670 char **pbase, char **pstream)
8672 char *base = NULL;
8673 char *stream = NULL;
8674 char *sname; /* stream name */
8675 const char *stype; /* stream type */
8677 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
8679 sname = strchr_m(fname, ':');
8681 if (lp_posix_pathnames() || (sname == NULL)) {
8682 if (pbase != NULL) {
8683 base = talloc_strdup(mem_ctx, fname);
8684 NT_STATUS_HAVE_NO_MEMORY(base);
8686 goto done;
8689 if (pbase != NULL) {
8690 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
8691 NT_STATUS_HAVE_NO_MEMORY(base);
8694 sname += 1;
8696 stype = strchr_m(sname, ':');
8698 if (stype == NULL) {
8699 sname = talloc_strdup(mem_ctx, sname);
8700 stype = "$DATA";
8702 else {
8703 if (strcasecmp_m(stype, ":$DATA") != 0) {
8705 * If there is an explicit stream type, so far we only
8706 * allow $DATA. Is there anything else allowed? -- vl
8708 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
8709 TALLOC_FREE(base);
8710 return NT_STATUS_OBJECT_NAME_INVALID;
8712 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
8713 stype += 1;
8716 if (sname == NULL) {
8717 TALLOC_FREE(base);
8718 return NT_STATUS_NO_MEMORY;
8721 if (sname[0] == '\0') {
8723 * no stream name, so no stream
8725 goto done;
8728 if (pstream != NULL) {
8729 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
8730 if (stream == NULL) {
8731 TALLOC_FREE(sname);
8732 TALLOC_FREE(base);
8733 return NT_STATUS_NO_MEMORY;
8736 * upper-case the type field
8738 (void)strupper_m(strchr_m(stream, ':')+1);
8741 done:
8742 if (pbase != NULL) {
8743 *pbase = base;
8745 if (pstream != NULL) {
8746 *pstream = stream;
8748 return NT_STATUS_OK;
8751 static bool test_stream_name(const char *fname, const char *expected_base,
8752 const char *expected_stream,
8753 NTSTATUS expected_status)
8755 NTSTATUS status;
8756 char *base = NULL;
8757 char *stream = NULL;
8759 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
8760 if (!NT_STATUS_EQUAL(status, expected_status)) {
8761 goto error;
8764 if (!NT_STATUS_IS_OK(status)) {
8765 return true;
8768 if (base == NULL) goto error;
8770 if (strcmp(expected_base, base) != 0) goto error;
8772 if ((expected_stream != NULL) && (stream == NULL)) goto error;
8773 if ((expected_stream == NULL) && (stream != NULL)) goto error;
8775 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
8776 goto error;
8778 TALLOC_FREE(base);
8779 TALLOC_FREE(stream);
8780 return true;
8782 error:
8783 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
8784 fname, expected_base ? expected_base : "<NULL>",
8785 expected_stream ? expected_stream : "<NULL>",
8786 nt_errstr(expected_status));
8787 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
8788 base ? base : "<NULL>", stream ? stream : "<NULL>",
8789 nt_errstr(status));
8790 TALLOC_FREE(base);
8791 TALLOC_FREE(stream);
8792 return false;
8795 static bool run_local_stream_name(int dummy)
8797 bool ret = true;
8799 ret &= test_stream_name(
8800 "bla", "bla", NULL, NT_STATUS_OK);
8801 ret &= test_stream_name(
8802 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
8803 ret &= test_stream_name(
8804 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8805 ret &= test_stream_name(
8806 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
8807 ret &= test_stream_name(
8808 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8809 ret &= test_stream_name(
8810 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
8811 ret &= test_stream_name(
8812 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
8813 ret &= test_stream_name(
8814 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
8816 return ret;
8819 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
8821 if (a.length != b.length) {
8822 printf("a.length=%d != b.length=%d\n",
8823 (int)a.length, (int)b.length);
8824 return false;
8826 if (memcmp(a.data, b.data, a.length) != 0) {
8827 printf("a.data and b.data differ\n");
8828 return false;
8830 return true;
8833 static bool run_local_memcache(int dummy)
8835 struct memcache *cache;
8836 DATA_BLOB k1, k2;
8837 DATA_BLOB d1, d2, d3;
8838 DATA_BLOB v1, v2, v3;
8840 TALLOC_CTX *mem_ctx;
8841 char *str1, *str2;
8842 size_t size1, size2;
8843 bool ret = false;
8845 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
8847 if (cache == NULL) {
8848 printf("memcache_init failed\n");
8849 return false;
8852 d1 = data_blob_const("d1", 2);
8853 d2 = data_blob_const("d2", 2);
8854 d3 = data_blob_const("d3", 2);
8856 k1 = data_blob_const("d1", 2);
8857 k2 = data_blob_const("d2", 2);
8859 memcache_add(cache, STAT_CACHE, k1, d1);
8860 memcache_add(cache, GETWD_CACHE, k2, d2);
8862 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
8863 printf("could not find k1\n");
8864 return false;
8866 if (!data_blob_equal(d1, v1)) {
8867 return false;
8870 if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8871 printf("could not find k2\n");
8872 return false;
8874 if (!data_blob_equal(d2, v2)) {
8875 return false;
8878 memcache_add(cache, STAT_CACHE, k1, d3);
8880 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
8881 printf("could not find replaced k1\n");
8882 return false;
8884 if (!data_blob_equal(d3, v3)) {
8885 return false;
8888 memcache_add(cache, GETWD_CACHE, k1, d1);
8890 if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8891 printf("Did find k2, should have been purged\n");
8892 return false;
8895 TALLOC_FREE(cache);
8897 cache = memcache_init(NULL, 0);
8899 mem_ctx = talloc_init("foo");
8901 str1 = talloc_strdup(mem_ctx, "string1");
8902 str2 = talloc_strdup(mem_ctx, "string2");
8904 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8905 data_blob_string_const("torture"), &str1);
8906 size1 = talloc_total_size(cache);
8908 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8909 data_blob_string_const("torture"), &str2);
8910 size2 = talloc_total_size(cache);
8912 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
8914 if (size2 > size1) {
8915 printf("memcache leaks memory!\n");
8916 goto fail;
8919 ret = true;
8920 fail:
8921 TALLOC_FREE(cache);
8922 return ret;
8925 static void wbclient_done(struct tevent_req *req)
8927 wbcErr wbc_err;
8928 struct winbindd_response *wb_resp;
8929 int *i = (int *)tevent_req_callback_data_void(req);
8931 wbc_err = wb_trans_recv(req, req, &wb_resp);
8932 TALLOC_FREE(req);
8933 *i += 1;
8934 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
8937 static bool run_wbclient_multi_ping(int dummy)
8939 struct tevent_context *ev;
8940 struct wb_context **wb_ctx;
8941 struct winbindd_request wb_req;
8942 bool result = false;
8943 int i, j;
8945 BlockSignals(True, SIGPIPE);
8947 ev = tevent_context_init(talloc_tos());
8948 if (ev == NULL) {
8949 goto fail;
8952 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
8953 if (wb_ctx == NULL) {
8954 goto fail;
8957 ZERO_STRUCT(wb_req);
8958 wb_req.cmd = WINBINDD_PING;
8960 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
8962 for (i=0; i<torture_nprocs; i++) {
8963 wb_ctx[i] = wb_context_init(ev, NULL);
8964 if (wb_ctx[i] == NULL) {
8965 goto fail;
8967 for (j=0; j<torture_numops; j++) {
8968 struct tevent_req *req;
8969 req = wb_trans_send(ev, ev, wb_ctx[i],
8970 (j % 2) == 0, &wb_req);
8971 if (req == NULL) {
8972 goto fail;
8974 tevent_req_set_callback(req, wbclient_done, &i);
8978 i = 0;
8980 while (i < torture_nprocs * torture_numops) {
8981 tevent_loop_once(ev);
8984 result = true;
8985 fail:
8986 TALLOC_FREE(ev);
8987 return result;
8990 static void getaddrinfo_finished(struct tevent_req *req)
8992 char *name = (char *)tevent_req_callback_data_void(req);
8993 struct addrinfo *ainfo;
8994 int res;
8996 res = getaddrinfo_recv(req, &ainfo);
8997 if (res != 0) {
8998 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
8999 return;
9001 d_printf("gai(%s) succeeded\n", name);
9002 freeaddrinfo(ainfo);
9005 static bool run_getaddrinfo_send(int dummy)
9007 TALLOC_CTX *frame = talloc_stackframe();
9008 struct fncall_context *ctx;
9009 struct tevent_context *ev;
9010 bool result = false;
9011 const char *names[4] = { "www.samba.org", "notfound.samba.org",
9012 "www.slashdot.org", "heise.de" };
9013 struct tevent_req *reqs[4];
9014 int i;
9016 ev = samba_tevent_context_init(frame);
9017 if (ev == NULL) {
9018 goto fail;
9021 ctx = fncall_context_init(frame, 4);
9023 for (i=0; i<ARRAY_SIZE(names); i++) {
9024 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
9025 NULL);
9026 if (reqs[i] == NULL) {
9027 goto fail;
9029 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
9030 discard_const_p(void, names[i]));
9033 for (i=0; i<ARRAY_SIZE(reqs); i++) {
9034 tevent_loop_once(ev);
9037 result = true;
9038 fail:
9039 TALLOC_FREE(frame);
9040 return result;
9043 static bool dbtrans_inc(struct db_context *db)
9045 struct db_record *rec;
9046 uint32_t val;
9047 bool ret = false;
9048 NTSTATUS status;
9049 TDB_DATA value;
9051 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
9052 if (rec == NULL) {
9053 printf(__location__ "fetch_lock failed\n");
9054 return false;
9057 value = dbwrap_record_get_value(rec);
9059 if (value.dsize != sizeof(uint32_t)) {
9060 printf(__location__ "value.dsize = %d\n",
9061 (int)value.dsize);
9062 goto fail;
9065 memcpy(&val, value.dptr, sizeof(val));
9066 val += 1;
9068 status = dbwrap_record_store(
9069 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
9070 if (!NT_STATUS_IS_OK(status)) {
9071 printf(__location__ "store failed: %s\n",
9072 nt_errstr(status));
9073 goto fail;
9076 ret = true;
9077 fail:
9078 TALLOC_FREE(rec);
9079 return ret;
9082 static bool run_local_dbtrans(int dummy)
9084 struct db_context *db;
9085 struct db_record *rec;
9086 NTSTATUS status;
9087 uint32_t initial;
9088 int res;
9089 TDB_DATA value;
9091 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
9092 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
9093 DBWRAP_FLAG_NONE);
9094 if (db == NULL) {
9095 printf("Could not open transtest.db\n");
9096 return false;
9099 res = dbwrap_transaction_start(db);
9100 if (res != 0) {
9101 printf(__location__ "transaction_start failed\n");
9102 return false;
9105 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
9106 if (rec == NULL) {
9107 printf(__location__ "fetch_lock failed\n");
9108 return false;
9111 value = dbwrap_record_get_value(rec);
9113 if (value.dptr == NULL) {
9114 initial = 0;
9115 status = dbwrap_record_store(
9116 rec, make_tdb_data((uint8_t *)&initial,
9117 sizeof(initial)),
9119 if (!NT_STATUS_IS_OK(status)) {
9120 printf(__location__ "store returned %s\n",
9121 nt_errstr(status));
9122 return false;
9126 TALLOC_FREE(rec);
9128 res = dbwrap_transaction_commit(db);
9129 if (res != 0) {
9130 printf(__location__ "transaction_commit failed\n");
9131 return false;
9134 while (true) {
9135 uint32_t val, val2;
9136 int i;
9138 res = dbwrap_transaction_start(db);
9139 if (res != 0) {
9140 printf(__location__ "transaction_start failed\n");
9141 break;
9144 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
9145 if (!NT_STATUS_IS_OK(status)) {
9146 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
9147 nt_errstr(status));
9148 break;
9151 for (i=0; i<10; i++) {
9152 if (!dbtrans_inc(db)) {
9153 return false;
9157 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
9158 if (!NT_STATUS_IS_OK(status)) {
9159 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
9160 nt_errstr(status));
9161 break;
9164 if (val2 != val + 10) {
9165 printf(__location__ "val=%d, val2=%d\n",
9166 (int)val, (int)val2);
9167 break;
9170 printf("val2=%d\r", val2);
9172 res = dbwrap_transaction_commit(db);
9173 if (res != 0) {
9174 printf(__location__ "transaction_commit failed\n");
9175 break;
9179 TALLOC_FREE(db);
9180 return true;
9184 * Just a dummy test to be run under a debugger. There's no real way
9185 * to inspect the tevent_select specific function from outside of
9186 * tevent_select.c.
9189 static bool run_local_tevent_select(int dummy)
9191 struct tevent_context *ev;
9192 struct tevent_fd *fd1, *fd2;
9193 bool result = false;
9195 ev = tevent_context_init_byname(NULL, "select");
9196 if (ev == NULL) {
9197 d_fprintf(stderr, "tevent_context_init_byname failed\n");
9198 goto fail;
9201 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
9202 if (fd1 == NULL) {
9203 d_fprintf(stderr, "tevent_add_fd failed\n");
9204 goto fail;
9206 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
9207 if (fd2 == NULL) {
9208 d_fprintf(stderr, "tevent_add_fd failed\n");
9209 goto fail;
9211 TALLOC_FREE(fd2);
9213 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
9214 if (fd2 == NULL) {
9215 d_fprintf(stderr, "tevent_add_fd failed\n");
9216 goto fail;
9219 result = true;
9220 fail:
9221 TALLOC_FREE(ev);
9222 return result;
9225 static bool run_local_hex_encode_buf(int dummy)
9227 char buf[17];
9228 uint8_t src[8];
9229 int i;
9231 for (i=0; i<sizeof(src); i++) {
9232 src[i] = i;
9234 hex_encode_buf(buf, src, sizeof(src));
9235 if (strcmp(buf, "0001020304050607") != 0) {
9236 return false;
9238 hex_encode_buf(buf, NULL, 0);
9239 if (buf[0] != '\0') {
9240 return false;
9242 return true;
9245 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
9246 "0.0.0.0",
9247 "::0",
9248 "1.2.3.1",
9249 "0.0.0.0",
9250 "0.0.0.0",
9251 "1.2.3.2",
9252 "1.2.3.3",
9253 "1.2.3.4",
9254 "1.2.3.5",
9255 "::0",
9256 "1.2.3.6",
9257 "1.2.3.7",
9258 "::0",
9259 "::0",
9260 "::0",
9261 "1.2.3.8",
9262 "1.2.3.9",
9263 "1.2.3.10",
9264 "1.2.3.11",
9265 "1.2.3.12",
9266 "1.2.3.13",
9267 "1001:1111:1111:1000:0:1111:1111:1111",
9268 "1.2.3.1",
9269 "1.2.3.2",
9270 "1.2.3.3",
9271 "1.2.3.12",
9272 "::0",
9273 "::0"
9276 static const char *remove_duplicate_addrs2_test_strings_result[] = {
9277 "1.2.3.1",
9278 "1.2.3.2",
9279 "1.2.3.3",
9280 "1.2.3.4",
9281 "1.2.3.5",
9282 "1.2.3.6",
9283 "1.2.3.7",
9284 "1.2.3.8",
9285 "1.2.3.9",
9286 "1.2.3.10",
9287 "1.2.3.11",
9288 "1.2.3.12",
9289 "1.2.3.13",
9290 "1001:1111:1111:1000:0:1111:1111:1111"
9293 static bool run_local_remove_duplicate_addrs2(int dummy)
9295 struct ip_service test_vector[28];
9296 int count, i;
9298 /* Construct the sockaddr_storage test vector. */
9299 for (i = 0; i < 28; i++) {
9300 struct addrinfo hints;
9301 struct addrinfo *res = NULL;
9302 int ret;
9304 memset(&hints, '\0', sizeof(hints));
9305 hints.ai_flags = AI_NUMERICHOST;
9306 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
9307 NULL,
9308 &hints,
9309 &res);
9310 if (ret) {
9311 fprintf(stderr, "getaddrinfo failed on [%s]\n",
9312 remove_duplicate_addrs2_test_strings_vector[i]);
9313 return false;
9315 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
9316 memcpy(&test_vector[i].ss,
9317 res->ai_addr,
9318 res->ai_addrlen);
9319 freeaddrinfo(res);
9322 count = remove_duplicate_addrs2(test_vector, i);
9324 if (count != 14) {
9325 fprintf(stderr, "count wrong (%d) should be 14\n",
9326 count);
9327 return false;
9330 for (i = 0; i < count; i++) {
9331 char addr[INET6_ADDRSTRLEN];
9333 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
9335 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
9336 fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
9338 addr,
9339 remove_duplicate_addrs2_test_strings_result[i]);
9340 return false;
9344 printf("run_local_remove_duplicate_addrs2: success\n");
9345 return true;
9348 static bool run_local_tdb_opener(int dummy)
9350 TDB_CONTEXT *t;
9351 unsigned v = 0;
9353 while (1) {
9354 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
9355 O_RDWR|O_CREAT, 0755);
9356 if (t == NULL) {
9357 perror("tdb_open failed");
9358 return false;
9360 tdb_close(t);
9362 v += 1;
9363 printf("\r%u", v);
9365 return true;
9368 static bool run_local_tdb_writer(int dummy)
9370 TDB_CONTEXT *t;
9371 unsigned v = 0;
9372 TDB_DATA val;
9374 t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
9375 if (t == 0) {
9376 perror("tdb_open failed");
9377 return 1;
9380 val.dptr = (uint8_t *)&v;
9381 val.dsize = sizeof(v);
9383 while (1) {
9384 TDB_DATA data;
9385 int ret;
9387 ret = tdb_store(t, val, val, 0);
9388 if (ret != 0) {
9389 printf("%s\n", tdb_errorstr(t));
9391 v += 1;
9392 printf("\r%u", v);
9394 data = tdb_fetch(t, val);
9395 if (data.dptr != NULL) {
9396 SAFE_FREE(data.dptr);
9399 return true;
9402 static double create_procs(bool (*fn)(int), bool *result)
9404 int i, status;
9405 volatile pid_t *child_status;
9406 volatile bool *child_status_out;
9407 int synccount;
9408 int tries = 8;
9409 struct timeval start;
9411 synccount = 0;
9413 child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
9414 if (!child_status) {
9415 printf("Failed to setup shared memory\n");
9416 return -1;
9419 child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
9420 if (!child_status_out) {
9421 printf("Failed to setup result status shared memory\n");
9422 return -1;
9425 for (i = 0; i < torture_nprocs; i++) {
9426 child_status[i] = 0;
9427 child_status_out[i] = True;
9430 start = timeval_current();
9432 for (i=0;i<torture_nprocs;i++) {
9433 procnum = i;
9434 if (fork() == 0) {
9435 pid_t mypid = getpid();
9436 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
9438 slprintf(myname,sizeof(myname),"CLIENT%d", i);
9440 while (1) {
9441 if (torture_open_connection(&current_cli, i)) break;
9442 if (tries-- == 0) {
9443 printf("pid %d failed to start\n", (int)getpid());
9444 _exit(1);
9446 smb_msleep(10);
9449 child_status[i] = getpid();
9451 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
9453 child_status_out[i] = fn(i);
9454 _exit(0);
9458 do {
9459 synccount = 0;
9460 for (i=0;i<torture_nprocs;i++) {
9461 if (child_status[i]) synccount++;
9463 if (synccount == torture_nprocs) break;
9464 smb_msleep(10);
9465 } while (timeval_elapsed(&start) < 30);
9467 if (synccount != torture_nprocs) {
9468 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
9469 *result = False;
9470 return timeval_elapsed(&start);
9473 /* start the client load */
9474 start = timeval_current();
9476 for (i=0;i<torture_nprocs;i++) {
9477 child_status[i] = 0;
9480 printf("%d clients started\n", torture_nprocs);
9482 for (i=0;i<torture_nprocs;i++) {
9483 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
9486 printf("\n");
9488 for (i=0;i<torture_nprocs;i++) {
9489 if (!child_status_out[i]) {
9490 *result = False;
9493 return timeval_elapsed(&start);
9496 #define FLAG_MULTIPROC 1
9498 static struct {
9499 const char *name;
9500 bool (*fn)(int);
9501 unsigned flags;
9502 } torture_ops[] = {
9503 {"FDPASS", run_fdpasstest, 0},
9504 {"LOCK1", run_locktest1, 0},
9505 {"LOCK2", run_locktest2, 0},
9506 {"LOCK3", run_locktest3, 0},
9507 {"LOCK4", run_locktest4, 0},
9508 {"LOCK5", run_locktest5, 0},
9509 {"LOCK6", run_locktest6, 0},
9510 {"LOCK7", run_locktest7, 0},
9511 {"LOCK8", run_locktest8, 0},
9512 {"LOCK9", run_locktest9, 0},
9513 {"UNLINK", run_unlinktest, 0},
9514 {"BROWSE", run_browsetest, 0},
9515 {"ATTR", run_attrtest, 0},
9516 {"TRANS2", run_trans2test, 0},
9517 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
9518 {"TORTURE",run_torture, FLAG_MULTIPROC},
9519 {"RANDOMIPC", run_randomipc, 0},
9520 {"NEGNOWAIT", run_negprot_nowait, 0},
9521 {"NBENCH", run_nbench, 0},
9522 {"NBENCH2", run_nbench2, 0},
9523 {"OPLOCK1", run_oplock1, 0},
9524 {"OPLOCK2", run_oplock2, 0},
9525 {"OPLOCK4", run_oplock4, 0},
9526 {"DIR", run_dirtest, 0},
9527 {"DIR1", run_dirtest1, 0},
9528 {"DIR-CREATETIME", run_dir_createtime, 0},
9529 {"DENY1", torture_denytest1, 0},
9530 {"DENY2", torture_denytest2, 0},
9531 {"TCON", run_tcon_test, 0},
9532 {"TCONDEV", run_tcon_devtype_test, 0},
9533 {"RW1", run_readwritetest, 0},
9534 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
9535 {"RW3", run_readwritelarge, 0},
9536 {"RW-SIGNING", run_readwritelarge_signtest, 0},
9537 {"OPEN", run_opentest, 0},
9538 {"POSIX", run_simple_posix_open_test, 0},
9539 {"POSIX-APPEND", run_posix_append, 0},
9540 {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
9541 {"ASYNC-ECHO", run_async_echo, 0},
9542 { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
9543 { "SHORTNAME-TEST", run_shortname_test, 0},
9544 { "ADDRCHANGE", run_addrchange, 0},
9545 #if 1
9546 {"OPENATTR", run_openattrtest, 0},
9547 #endif
9548 {"XCOPY", run_xcopy, 0},
9549 {"RENAME", run_rename, 0},
9550 {"DELETE", run_deletetest, 0},
9551 {"DELETE-LN", run_deletetest_ln, 0},
9552 {"PROPERTIES", run_properties, 0},
9553 {"MANGLE", torture_mangle, 0},
9554 {"MANGLE1", run_mangle1, 0},
9555 {"W2K", run_w2ktest, 0},
9556 {"TRANS2SCAN", torture_trans2_scan, 0},
9557 {"NTTRANSSCAN", torture_nttrans_scan, 0},
9558 {"UTABLE", torture_utable, 0},
9559 {"CASETABLE", torture_casetable, 0},
9560 {"ERRMAPEXTRACT", run_error_map_extract, 0},
9561 {"PIPE_NUMBER", run_pipe_number, 0},
9562 {"TCON2", run_tcon2_test, 0},
9563 {"IOCTL", torture_ioctl_test, 0},
9564 {"CHKPATH", torture_chkpath_test, 0},
9565 {"FDSESS", run_fdsesstest, 0},
9566 { "EATEST", run_eatest, 0},
9567 { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
9568 { "CHAIN1", run_chain1, 0},
9569 { "CHAIN2", run_chain2, 0},
9570 { "CHAIN3", run_chain3, 0},
9571 { "WINDOWS-WRITE", run_windows_write, 0},
9572 { "LARGE_READX", run_large_readx, 0},
9573 { "NTTRANS-CREATE", run_nttrans_create, 0},
9574 { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
9575 { "CLI_ECHO", run_cli_echo, 0},
9576 { "GETADDRINFO", run_getaddrinfo_send, 0},
9577 { "TLDAP", run_tldap },
9578 { "STREAMERROR", run_streamerror },
9579 { "NOTIFY-BENCH", run_notify_bench },
9580 { "NOTIFY-BENCH2", run_notify_bench2 },
9581 { "NOTIFY-BENCH3", run_notify_bench3 },
9582 { "BAD-NBT-SESSION", run_bad_nbt_session },
9583 { "SMB-ANY-CONNECT", run_smb_any_connect },
9584 { "NOTIFY-ONLINE", run_notify_online },
9585 { "SMB2-BASIC", run_smb2_basic },
9586 { "SMB2-NEGPROT", run_smb2_negprot },
9587 { "SMB2-SESSION-RECONNECT", run_smb2_session_reconnect },
9588 { "SMB2-TCON-DEPENDENCE", run_smb2_tcon_dependence },
9589 { "SMB2-MULTI-CHANNEL", run_smb2_multi_channel },
9590 { "SMB2-SESSION-REAUTH", run_smb2_session_reauth },
9591 { "CLEANUP1", run_cleanup1 },
9592 { "CLEANUP2", run_cleanup2 },
9593 { "CLEANUP3", run_cleanup3 },
9594 { "CLEANUP4", run_cleanup4 },
9595 { "OPLOCK-CANCEL", run_oplock_cancel },
9596 { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
9597 { "LOCAL-GENCACHE", run_local_gencache, 0},
9598 { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
9599 { "LOCAL-DBWRAP-WATCH1", run_dbwrap_watch1, 0 },
9600 { "LOCAL-MESSAGING-READ1", run_messaging_read1, 0 },
9601 { "LOCAL-MESSAGING-READ2", run_messaging_read2, 0 },
9602 { "LOCAL-MESSAGING-READ3", run_messaging_read3, 0 },
9603 { "LOCAL-MESSAGING-READ4", run_messaging_read4, 0 },
9604 { "LOCAL-MESSAGING-FDPASS1", run_messaging_fdpass1, 0 },
9605 { "LOCAL-MESSAGING-FDPASS2", run_messaging_fdpass2, 0 },
9606 { "LOCAL-MESSAGING-FDPASS2a", run_messaging_fdpass2a, 0 },
9607 { "LOCAL-MESSAGING-FDPASS2b", run_messaging_fdpass2b, 0 },
9608 { "LOCAL-BASE64", run_local_base64, 0},
9609 { "LOCAL-RBTREE", run_local_rbtree, 0},
9610 { "LOCAL-MEMCACHE", run_local_memcache, 0},
9611 { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
9612 { "WBCLIENT-MULTI-PING", run_wbclient_multi_ping, 0},
9613 { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
9614 { "LOCAL-sid_to_string", run_local_sid_to_string, 0},
9615 { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
9616 { "LOCAL-DBTRANS", run_local_dbtrans, 0},
9617 { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
9618 { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
9619 { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
9620 { "LOCAL-sprintf_append", run_local_sprintf_append, 0},
9621 { "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0},
9622 { "LOCAL-IDMAP-TDB-COMMON", run_idmap_tdb_common_test, 0},
9623 { "LOCAL-remove_duplicate_addrs2", run_local_remove_duplicate_addrs2, 0},
9624 { "local-tdb-opener", run_local_tdb_opener, 0 },
9625 { "local-tdb-writer", run_local_tdb_writer, 0 },
9626 { "LOCAL-DBWRAP-CTDB", run_local_dbwrap_ctdb, 0 },
9627 { "LOCAL-BENCH-PTHREADPOOL", run_bench_pthreadpool, 0 },
9628 { "qpathinfo-bufsize", run_qpathinfo_bufsize, 0 },
9629 {NULL, NULL, 0}};
9632 * dummy function to satisfy linker dependency
9634 struct tevent_context *winbind_event_context(void);
9635 struct tevent_context *winbind_event_context(void)
9637 return NULL;
9640 /****************************************************************************
9641 run a specified test or "ALL"
9642 ****************************************************************************/
9643 static bool run_test(const char *name)
9645 bool ret = True;
9646 bool result = True;
9647 bool found = False;
9648 int i;
9649 double t;
9650 if (strequal(name,"ALL")) {
9651 for (i=0;torture_ops[i].name;i++) {
9652 run_test(torture_ops[i].name);
9654 found = True;
9657 for (i=0;torture_ops[i].name;i++) {
9658 fstr_sprintf(randomfname, "\\XX%x",
9659 (unsigned)random());
9661 if (strequal(name, torture_ops[i].name)) {
9662 found = True;
9663 printf("Running %s\n", name);
9664 if (torture_ops[i].flags & FLAG_MULTIPROC) {
9665 t = create_procs(torture_ops[i].fn, &result);
9666 if (!result) {
9667 ret = False;
9668 printf("TEST %s FAILED!\n", name);
9670 } else {
9671 struct timeval start;
9672 start = timeval_current();
9673 if (!torture_ops[i].fn(0)) {
9674 ret = False;
9675 printf("TEST %s FAILED!\n", name);
9677 t = timeval_elapsed(&start);
9679 printf("%s took %g secs\n\n", name, t);
9683 if (!found) {
9684 printf("Did not find a test named %s\n", name);
9685 ret = False;
9688 return ret;
9692 static void usage(void)
9694 int i;
9696 printf("WARNING samba4 test suite is much more complete nowadays.\n");
9697 printf("Please use samba4 torture.\n\n");
9699 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
9701 printf("\t-d debuglevel\n");
9702 printf("\t-U user%%pass\n");
9703 printf("\t-k use kerberos\n");
9704 printf("\t-N numprocs\n");
9705 printf("\t-n my_netbios_name\n");
9706 printf("\t-W workgroup\n");
9707 printf("\t-o num_operations\n");
9708 printf("\t-O socket_options\n");
9709 printf("\t-m maximum protocol\n");
9710 printf("\t-L use oplocks\n");
9711 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
9712 printf("\t-A showall\n");
9713 printf("\t-p port\n");
9714 printf("\t-s seed\n");
9715 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
9716 printf("\t-f filename filename to test\n");
9717 printf("\t-e encrypt\n");
9718 printf("\n\n");
9720 printf("tests are:");
9721 for (i=0;torture_ops[i].name;i++) {
9722 printf(" %s", torture_ops[i].name);
9724 printf("\n");
9726 printf("default test is ALL\n");
9728 exit(1);
9731 /****************************************************************************
9732 main program
9733 ****************************************************************************/
9734 int main(int argc,char *argv[])
9736 int opt, i;
9737 char *p;
9738 int gotuser = 0;
9739 int gotpass = 0;
9740 bool correct = True;
9741 TALLOC_CTX *frame = talloc_stackframe();
9742 int seed = time(NULL);
9744 #ifdef HAVE_SETBUFFER
9745 setbuffer(stdout, NULL, 0);
9746 #endif
9748 setup_logging("smbtorture", DEBUG_STDOUT);
9750 smb_init_locale();
9751 fault_setup();
9753 if (is_default_dyn_CONFIGFILE()) {
9754 if(getenv("SMB_CONF_PATH")) {
9755 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
9758 lp_load_global(get_dyn_CONFIGFILE());
9759 load_interfaces();
9761 if (argc < 2) {
9762 usage();
9765 for(p = argv[1]; *p; p++)
9766 if(*p == '\\')
9767 *p = '/';
9769 if (strncmp(argv[1], "//", 2)) {
9770 usage();
9773 fstrcpy(host, &argv[1][2]);
9774 p = strchr_m(&host[2],'/');
9775 if (!p) {
9776 usage();
9778 *p = 0;
9779 fstrcpy(share, p+1);
9781 fstrcpy(myname, get_myname(talloc_tos()));
9782 if (!*myname) {
9783 fprintf(stderr, "Failed to get my hostname.\n");
9784 return 1;
9787 if (*username == 0 && getenv("LOGNAME")) {
9788 fstrcpy(username,getenv("LOGNAME"));
9791 argc--;
9792 argv++;
9794 fstrcpy(workgroup, lp_workgroup());
9796 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
9797 != EOF) {
9798 switch (opt) {
9799 case 'p':
9800 port_to_use = atoi(optarg);
9801 break;
9802 case 's':
9803 seed = atoi(optarg);
9804 break;
9805 case 'W':
9806 fstrcpy(workgroup,optarg);
9807 break;
9808 case 'm':
9809 lp_set_cmdline("client max protocol", optarg);
9810 break;
9811 case 'N':
9812 torture_nprocs = atoi(optarg);
9813 break;
9814 case 'o':
9815 torture_numops = atoi(optarg);
9816 break;
9817 case 'd':
9818 lp_set_cmdline("log level", optarg);
9819 break;
9820 case 'O':
9821 sockops = optarg;
9822 break;
9823 case 'L':
9824 use_oplocks = True;
9825 break;
9826 case 'l':
9827 local_path = optarg;
9828 break;
9829 case 'A':
9830 torture_showall = True;
9831 break;
9832 case 'n':
9833 fstrcpy(myname, optarg);
9834 break;
9835 case 'c':
9836 client_txt = optarg;
9837 break;
9838 case 'e':
9839 do_encrypt = true;
9840 break;
9841 case 'k':
9842 #ifdef HAVE_KRB5
9843 use_kerberos = True;
9844 #else
9845 d_printf("No kerberos support compiled in\n");
9846 exit(1);
9847 #endif
9848 break;
9849 case 'U':
9850 gotuser = 1;
9851 fstrcpy(username,optarg);
9852 p = strchr_m(username,'%');
9853 if (p) {
9854 *p = 0;
9855 fstrcpy(password, p+1);
9856 gotpass = 1;
9858 break;
9859 case 'b':
9860 fstrcpy(multishare_conn_fname, optarg);
9861 use_multishare_conn = True;
9862 break;
9863 case 'B':
9864 torture_blocksize = atoi(optarg);
9865 break;
9866 case 'f':
9867 test_filename = SMB_STRDUP(optarg);
9868 break;
9869 default:
9870 printf("Unknown option %c (%d)\n", (char)opt, opt);
9871 usage();
9875 d_printf("using seed %d\n", seed);
9877 srandom(seed);
9879 if(use_kerberos && !gotuser) gotpass = True;
9881 while (!gotpass) {
9882 char pwd[256] = {0};
9883 int rc;
9885 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
9886 if (rc == 0) {
9887 fstrcpy(password, pwd);
9888 gotpass = 1;
9892 printf("host=%s share=%s user=%s myname=%s\n",
9893 host, share, username, myname);
9895 if (argc == optind) {
9896 correct = run_test("ALL");
9897 } else {
9898 for (i=optind;i<argc;i++) {
9899 if (!run_test(argv[i])) {
9900 correct = False;
9905 TALLOC_FREE(frame);
9907 if (correct) {
9908 return(0);
9909 } else {
9910 return(1);