python: Print the finddcs error message
[Samba.git] / source3 / torture / torture.c
blobae502f280feeafd13702167ec87aaaacd1fc6bf1
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 "async_smb.h"
35 #include "libsmb/libsmb.h"
36 #include "libsmb/clirap.h"
37 #include "trans2.h"
38 #include "libsmb/nmblib.h"
39 #include "../lib/util/tevent_ntstatus.h"
40 #include "util_tdb.h"
41 #include "../libcli/smb/read_smb.h"
42 #include "../libcli/smb/smbXcli_base.h"
43 #include "lib/util/sys_rw_data.h"
44 #include "lib/util/base64.h"
45 #include "lib/util/time.h"
47 extern char *optarg;
48 extern int optind;
50 fstring host, workgroup, share, password, username, myname;
51 struct cli_credentials *torture_creds;
52 static const char *sockops="TCP_NODELAY";
53 int torture_nprocs=1;
54 static int port_to_use=0;
55 int torture_numops=100;
56 int torture_blocksize=1024*1024;
57 static int procnum; /* records process count number when forking */
58 static struct cli_state *current_cli;
59 static fstring randomfname;
60 static bool use_oplocks;
61 static bool use_level_II_oplocks;
62 static const char *client_txt = "client_oplocks.txt";
63 static bool disable_spnego;
64 static bool use_kerberos;
65 static bool force_dos_errors;
66 static fstring multishare_conn_fname;
67 static bool use_multishare_conn = False;
68 static bool do_encrypt;
69 static const char *local_path = NULL;
70 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
71 char *test_filename;
73 bool torture_showall = False;
75 static double create_procs(bool (*fn)(int), bool *result);
77 /********************************************************************
78 Ensure a connection is encrypted.
79 ********************************************************************/
81 static bool force_cli_encryption(struct cli_state *c,
82 const char *sharename)
84 uint16_t major, minor;
85 uint32_t caplow, caphigh;
86 NTSTATUS status;
88 if (!SERVER_HAS_UNIX_CIFS(c)) {
89 d_printf("Encryption required and "
90 "server that doesn't support "
91 "UNIX extensions - failing connect\n");
92 return false;
95 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
96 &caphigh);
97 if (!NT_STATUS_IS_OK(status)) {
98 d_printf("Encryption required and "
99 "can't get UNIX CIFS extensions "
100 "version from server: %s\n", nt_errstr(status));
101 return false;
104 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
105 d_printf("Encryption required and "
106 "share %s doesn't support "
107 "encryption.\n", sharename);
108 return false;
111 status = cli_smb1_setup_encryption(c, torture_creds);
112 if (!NT_STATUS_IS_OK(status)) {
113 d_printf("Encryption required and "
114 "setup failed with error %s.\n",
115 nt_errstr(status));
116 return false;
119 return true;
123 static struct cli_state *open_nbt_connection(void)
125 struct cli_state *c;
126 NTSTATUS status;
127 int flags = 0;
129 if (disable_spnego) {
130 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
133 if (use_oplocks) {
134 flags |= CLI_FULL_CONNECTION_OPLOCKS;
137 if (use_level_II_oplocks) {
138 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
141 if (use_kerberos) {
142 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
145 if (force_dos_errors) {
146 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
149 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
150 signing_state, flags, &c);
151 if (!NT_STATUS_IS_OK(status)) {
152 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
153 return NULL;
156 cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
158 return c;
161 /****************************************************************************
162 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
163 ****************************************************************************/
165 static bool cli_bad_session_request(int fd,
166 struct nmb_name *calling, struct nmb_name *called)
168 TALLOC_CTX *frame;
169 uint8_t len_buf[4];
170 struct iovec iov[3];
171 ssize_t len;
172 uint8_t *inbuf;
173 int err;
174 bool ret = false;
175 uint8_t message_type;
176 uint8_t error;
177 struct tevent_context *ev;
178 struct tevent_req *req;
180 frame = talloc_stackframe();
182 iov[0].iov_base = len_buf;
183 iov[0].iov_len = sizeof(len_buf);
185 /* put in the destination name */
187 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
188 called->name_type);
189 if (iov[1].iov_base == NULL) {
190 goto fail;
192 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
193 talloc_get_size(iov[1].iov_base));
195 /* and my name */
197 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
198 calling->name_type);
199 if (iov[2].iov_base == NULL) {
200 goto fail;
202 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
203 talloc_get_size(iov[2].iov_base));
205 /* Deliberately corrupt the name len (first byte) */
206 *((uint8_t *)iov[2].iov_base) = 100;
208 /* send a session request (RFC 1002) */
209 /* setup the packet length
210 * Remove four bytes from the length count, since the length
211 * field in the NBT Session Service header counts the number
212 * of bytes which follow. The cli_send_smb() function knows
213 * about this and accounts for those four bytes.
214 * CRH.
217 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
218 SCVAL(len_buf,0,0x81);
220 len = write_data_iov(fd, iov, 3);
221 if (len == -1) {
222 goto fail;
225 ev = samba_tevent_context_init(frame);
226 if (ev == NULL) {
227 goto fail;
229 req = read_smb_send(frame, ev, fd);
230 if (req == NULL) {
231 goto fail;
233 if (!tevent_req_poll(req, ev)) {
234 goto fail;
236 len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
237 if (len == -1) {
238 errno = err;
239 goto fail;
241 TALLOC_FREE(ev);
243 message_type = CVAL(inbuf, 0);
244 if (message_type != 0x83) {
245 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
246 message_type);
247 goto fail;
250 if (smb_len(inbuf) != 1) {
251 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
252 (int)smb_len(inbuf));
253 goto fail;
256 error = CVAL(inbuf, 4);
257 if (error != 0x82) {
258 d_fprintf(stderr, "Expected error 0x82, got %d\n",
259 (int)error);
260 goto fail;
263 ret = true;
264 fail:
265 TALLOC_FREE(frame);
266 return ret;
269 /* Insert a NULL at the first separator of the given path and return a pointer
270 * to the remainder of the string.
272 static char *
273 terminate_path_at_separator(char * path)
275 char * p;
277 if (!path) {
278 return NULL;
281 if ((p = strchr_m(path, '/'))) {
282 *p = '\0';
283 return p + 1;
286 if ((p = strchr_m(path, '\\'))) {
287 *p = '\0';
288 return p + 1;
291 /* No separator. */
292 return NULL;
296 parse a //server/share type UNC name
298 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
299 char **hostname, char **sharename)
301 char *p;
303 *hostname = *sharename = NULL;
305 if (strncmp(unc_name, "\\\\", 2) &&
306 strncmp(unc_name, "//", 2)) {
307 return False;
310 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
311 p = terminate_path_at_separator(*hostname);
313 if (p && *p) {
314 *sharename = talloc_strdup(mem_ctx, p);
315 terminate_path_at_separator(*sharename);
318 if (*hostname && *sharename) {
319 return True;
322 TALLOC_FREE(*hostname);
323 TALLOC_FREE(*sharename);
324 return False;
327 static bool torture_open_connection_share(struct cli_state **c,
328 const char *hostname,
329 const char *sharename,
330 int flags)
332 NTSTATUS status;
334 status = cli_full_connection_creds(c,
335 myname,
336 hostname,
337 NULL, /* dest_ss */
338 port_to_use,
339 sharename,
340 "?????",
341 torture_creds,
342 flags,
343 signing_state);
344 if (!NT_STATUS_IS_OK(status)) {
345 printf("failed to open share connection: //%s/%s port:%d - %s\n",
346 hostname, sharename, port_to_use, nt_errstr(status));
347 return False;
350 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
352 if (do_encrypt) {
353 return force_cli_encryption(*c,
354 sharename);
356 return True;
359 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
361 char **unc_list = NULL;
362 int num_unc_names = 0;
363 bool result;
365 if (use_multishare_conn==True) {
366 char *h, *s;
367 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
368 if (!unc_list || num_unc_names <= 0) {
369 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
370 exit(1);
373 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
374 NULL, &h, &s)) {
375 printf("Failed to parse UNC name %s\n",
376 unc_list[conn_index % num_unc_names]);
377 TALLOC_FREE(unc_list);
378 exit(1);
381 result = torture_open_connection_share(c, h, s, flags);
383 /* h, s were copied earlier */
384 TALLOC_FREE(unc_list);
385 return result;
388 return torture_open_connection_share(c, host, share, flags);
391 bool torture_open_connection(struct cli_state **c, int conn_index)
393 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
395 if (use_oplocks) {
396 flags |= CLI_FULL_CONNECTION_OPLOCKS;
398 if (use_level_II_oplocks) {
399 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
402 return torture_open_connection_flags(c, conn_index, flags);
405 bool torture_init_connection(struct cli_state **pcli)
407 struct cli_state *cli;
409 cli = open_nbt_connection();
410 if (cli == NULL) {
411 return false;
414 *pcli = cli;
415 return true;
418 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
420 uint16_t old_vuid = cli_state_get_uid(cli);
421 NTSTATUS status;
422 bool ret;
424 cli_state_set_uid(cli, 0);
425 status = cli_session_setup_creds(cli, torture_creds);
426 ret = NT_STATUS_IS_OK(status);
427 *new_vuid = cli_state_get_uid(cli);
428 cli_state_set_uid(cli, old_vuid);
429 return ret;
433 bool torture_close_connection(struct cli_state *c)
435 bool ret = True;
436 NTSTATUS status;
438 status = cli_tdis(c);
439 if (!NT_STATUS_IS_OK(status)) {
440 printf("tdis failed (%s)\n", nt_errstr(status));
441 ret = False;
444 cli_shutdown(c);
446 return ret;
450 /* check if the server produced the expected dos or nt error code */
451 static bool check_both_error(int line, NTSTATUS status,
452 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
454 if (NT_STATUS_IS_DOS(status)) {
455 uint8_t cclass;
456 uint32_t num;
458 /* Check DOS error */
459 cclass = NT_STATUS_DOS_CLASS(status);
460 num = NT_STATUS_DOS_CODE(status);
462 if (eclass != cclass || ecode != num) {
463 printf("unexpected error code class=%d code=%d\n",
464 (int)cclass, (int)num);
465 printf(" expected %d/%d %s (line=%d)\n",
466 (int)eclass, (int)ecode, nt_errstr(nterr), line);
467 return false;
469 } else {
470 /* Check NT error */
471 if (!NT_STATUS_EQUAL(nterr, status)) {
472 printf("unexpected error code %s\n",
473 nt_errstr(status));
474 printf(" expected %s (line=%d)\n",
475 nt_errstr(nterr), line);
476 return false;
480 return true;
484 /* check if the server produced the expected error code */
485 static bool check_error(int line, NTSTATUS status,
486 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
488 if (NT_STATUS_IS_DOS(status)) {
489 uint8_t cclass;
490 uint32_t num;
492 /* Check DOS error */
494 cclass = NT_STATUS_DOS_CLASS(status);
495 num = NT_STATUS_DOS_CODE(status);
497 if (eclass != cclass || ecode != num) {
498 printf("unexpected error code class=%d code=%d\n",
499 (int)cclass, (int)num);
500 printf(" expected %d/%d %s (line=%d)\n",
501 (int)eclass, (int)ecode, nt_errstr(nterr),
502 line);
503 return False;
506 } else {
507 /* Check NT error */
509 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
510 printf("unexpected error code %s\n",
511 nt_errstr(status));
512 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
513 line);
514 return False;
518 return True;
522 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
524 NTSTATUS status;
526 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
528 while (!NT_STATUS_IS_OK(status)) {
529 if (!check_both_error(__LINE__, status, ERRDOS,
530 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
531 return false;
534 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
537 return true;
541 static bool rw_torture(struct cli_state *c)
543 const char *lockfname = "\\torture.lck";
544 fstring fname;
545 uint16_t fnum;
546 uint16_t fnum2;
547 pid_t pid2, pid = getpid();
548 int i, j;
549 char buf[1024];
550 bool correct = True;
551 size_t nread = 0;
552 NTSTATUS status;
554 memset(buf, '\0', sizeof(buf));
556 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
557 DENY_NONE, &fnum2);
558 if (!NT_STATUS_IS_OK(status)) {
559 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
561 if (!NT_STATUS_IS_OK(status)) {
562 printf("open of %s failed (%s)\n",
563 lockfname, nt_errstr(status));
564 return False;
567 for (i=0;i<torture_numops;i++) {
568 unsigned n = (unsigned)sys_random()%10;
570 if (i % 10 == 0) {
571 printf("%d\r", i); fflush(stdout);
573 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
575 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
576 return False;
579 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
580 DENY_ALL, &fnum);
581 if (!NT_STATUS_IS_OK(status)) {
582 printf("open failed (%s)\n", nt_errstr(status));
583 correct = False;
584 break;
587 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
588 sizeof(pid), NULL);
589 if (!NT_STATUS_IS_OK(status)) {
590 printf("write failed (%s)\n", nt_errstr(status));
591 correct = False;
594 for (j=0;j<50;j++) {
595 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
596 sizeof(pid)+(j*sizeof(buf)),
597 sizeof(buf), NULL);
598 if (!NT_STATUS_IS_OK(status)) {
599 printf("write failed (%s)\n",
600 nt_errstr(status));
601 correct = False;
605 pid2 = 0;
607 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
608 &nread);
609 if (!NT_STATUS_IS_OK(status)) {
610 printf("read failed (%s)\n", nt_errstr(status));
611 correct = false;
612 } else if (nread != sizeof(pid)) {
613 printf("read/write compare failed: "
614 "recv %ld req %ld\n", (unsigned long)nread,
615 (unsigned long)sizeof(pid));
616 correct = false;
619 if (pid2 != pid) {
620 printf("data corruption!\n");
621 correct = False;
624 status = cli_close(c, fnum);
625 if (!NT_STATUS_IS_OK(status)) {
626 printf("close failed (%s)\n", nt_errstr(status));
627 correct = False;
630 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
631 if (!NT_STATUS_IS_OK(status)) {
632 printf("unlink failed (%s)\n", nt_errstr(status));
633 correct = False;
636 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
637 if (!NT_STATUS_IS_OK(status)) {
638 printf("unlock failed (%s)\n", nt_errstr(status));
639 correct = False;
643 cli_close(c, fnum2);
644 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
646 printf("%d\n", i);
648 return correct;
651 static bool run_torture(int dummy)
653 struct cli_state *cli;
654 bool ret;
656 cli = current_cli;
658 smbXcli_conn_set_sockopt(cli->conn, sockops);
660 ret = rw_torture(cli);
662 if (!torture_close_connection(cli)) {
663 ret = False;
666 return ret;
669 static bool rw_torture3(struct cli_state *c, char *lockfname)
671 uint16_t fnum = (uint16_t)-1;
672 unsigned int i = 0;
673 char buf[131072];
674 char buf_rd[131072];
675 unsigned count;
676 unsigned countprev = 0;
677 size_t sent = 0;
678 bool correct = True;
679 NTSTATUS status = NT_STATUS_OK;
681 srandom(1);
682 for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
684 SIVAL(buf, i, sys_random());
687 if (procnum == 0)
689 status = cli_unlink(
690 c, lockfname,
691 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
692 if (!NT_STATUS_IS_OK(status)) {
693 printf("unlink failed (%s) (normal, this file should "
694 "not exist)\n", nt_errstr(status));
697 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
698 DENY_NONE, &fnum);
699 if (!NT_STATUS_IS_OK(status)) {
700 printf("first open read/write of %s failed (%s)\n",
701 lockfname, nt_errstr(status));
702 return False;
705 else
707 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
709 status = cli_openx(c, lockfname, O_RDONLY,
710 DENY_NONE, &fnum);
711 if (NT_STATUS_IS_OK(status)) {
712 break;
714 smb_msleep(10);
716 if (!NT_STATUS_IS_OK(status)) {
717 printf("second open read-only of %s failed (%s)\n",
718 lockfname, nt_errstr(status));
719 return False;
723 i = 0;
724 for (count = 0; count < sizeof(buf); count += sent)
726 if (count >= countprev) {
727 printf("%d %8d\r", i, count);
728 fflush(stdout);
729 i++;
730 countprev += (sizeof(buf) / 20);
733 if (procnum == 0)
735 sent = ((unsigned)sys_random()%(20))+ 1;
736 if (sent > sizeof(buf) - count)
738 sent = sizeof(buf) - count;
741 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
742 count, sent, NULL);
743 if (!NT_STATUS_IS_OK(status)) {
744 printf("write failed (%s)\n",
745 nt_errstr(status));
746 correct = False;
749 else
751 status = cli_read(c, fnum, buf_rd+count, count,
752 sizeof(buf)-count, &sent);
753 if(!NT_STATUS_IS_OK(status)) {
754 printf("read failed offset:%d size:%ld (%s)\n",
755 count, (unsigned long)sizeof(buf)-count,
756 nt_errstr(status));
757 correct = False;
758 sent = 0;
759 } else if (sent > 0) {
760 if (memcmp(buf_rd+count, buf+count, sent) != 0)
762 printf("read/write compare failed\n");
763 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
764 correct = False;
765 break;
772 status = cli_close(c, fnum);
773 if (!NT_STATUS_IS_OK(status)) {
774 printf("close failed (%s)\n", nt_errstr(status));
775 correct = False;
778 return correct;
781 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
783 const char *lockfname = "\\torture2.lck";
784 uint16_t fnum1;
785 uint16_t fnum2;
786 int i;
787 char buf[131072];
788 char buf_rd[131072];
789 bool correct = True;
790 size_t bytes_read;
791 NTSTATUS status;
793 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
794 if (!NT_STATUS_IS_OK(status)) {
795 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
798 status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
799 DENY_NONE, &fnum1);
800 if (!NT_STATUS_IS_OK(status)) {
801 printf("first open read/write of %s failed (%s)\n",
802 lockfname, nt_errstr(status));
803 return False;
806 status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
807 if (!NT_STATUS_IS_OK(status)) {
808 printf("second open read-only of %s failed (%s)\n",
809 lockfname, nt_errstr(status));
810 cli_close(c1, fnum1);
811 return False;
814 for (i = 0; i < torture_numops; i++)
816 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
817 if (i % 10 == 0) {
818 printf("%d\r", i); fflush(stdout);
821 generate_random_buffer((unsigned char *)buf, buf_size);
823 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
824 buf_size, NULL);
825 if (!NT_STATUS_IS_OK(status)) {
826 printf("write failed (%s)\n", nt_errstr(status));
827 correct = False;
828 break;
831 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
832 if(!NT_STATUS_IS_OK(status)) {
833 printf("read failed (%s)\n", nt_errstr(status));
834 correct = false;
835 break;
836 } else if (bytes_read != buf_size) {
837 printf("read failed\n");
838 printf("read %ld, expected %ld\n",
839 (unsigned long)bytes_read,
840 (unsigned long)buf_size);
841 correct = False;
842 break;
845 if (memcmp(buf_rd, buf, buf_size) != 0)
847 printf("read/write compare failed\n");
848 correct = False;
849 break;
853 status = cli_close(c2, fnum2);
854 if (!NT_STATUS_IS_OK(status)) {
855 printf("close failed (%s)\n", nt_errstr(status));
856 correct = False;
859 status = cli_close(c1, fnum1);
860 if (!NT_STATUS_IS_OK(status)) {
861 printf("close failed (%s)\n", nt_errstr(status));
862 correct = False;
865 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
866 if (!NT_STATUS_IS_OK(status)) {
867 printf("unlink failed (%s)\n", nt_errstr(status));
868 correct = False;
871 return correct;
874 static bool run_readwritetest(int dummy)
876 struct cli_state *cli1, *cli2;
877 bool test1, test2 = False;
879 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
880 return False;
882 smbXcli_conn_set_sockopt(cli1->conn, sockops);
883 smbXcli_conn_set_sockopt(cli2->conn, sockops);
885 printf("starting readwritetest\n");
887 test1 = rw_torture2(cli1, cli2);
888 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
890 if (test1) {
891 test2 = rw_torture2(cli1, cli1);
892 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
895 if (!torture_close_connection(cli1)) {
896 test1 = False;
899 if (!torture_close_connection(cli2)) {
900 test2 = False;
903 return (test1 && test2);
906 static bool run_readwritemulti(int dummy)
908 struct cli_state *cli;
909 bool test;
911 cli = current_cli;
913 smbXcli_conn_set_sockopt(cli->conn, sockops);
915 printf("run_readwritemulti: fname %s\n", randomfname);
916 test = rw_torture3(cli, randomfname);
918 if (!torture_close_connection(cli)) {
919 test = False;
922 return test;
925 static bool run_readwritelarge_internal(void)
927 static struct cli_state *cli1;
928 uint16_t fnum1;
929 const char *lockfname = "\\large.dat";
930 off_t fsize;
931 char buf[126*1024];
932 bool correct = True;
933 NTSTATUS status;
935 if (!torture_open_connection(&cli1, 0)) {
936 return False;
938 smbXcli_conn_set_sockopt(cli1->conn, sockops);
939 memset(buf,'\0',sizeof(buf));
941 printf("starting readwritelarge_internal\n");
943 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
945 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
946 DENY_NONE, &fnum1);
947 if (!NT_STATUS_IS_OK(status)) {
948 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
949 return False;
952 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
954 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
955 NULL, NULL, NULL);
956 if (!NT_STATUS_IS_OK(status)) {
957 printf("qfileinfo failed (%s)\n", nt_errstr(status));
958 correct = False;
961 if (fsize == sizeof(buf))
962 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
963 (unsigned long)fsize);
964 else {
965 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
966 (unsigned long)fsize);
967 correct = False;
970 status = cli_close(cli1, fnum1);
971 if (!NT_STATUS_IS_OK(status)) {
972 printf("close failed (%s)\n", nt_errstr(status));
973 correct = False;
976 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
977 if (!NT_STATUS_IS_OK(status)) {
978 printf("unlink failed (%s)\n", nt_errstr(status));
979 correct = False;
982 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
983 DENY_NONE, &fnum1);
984 if (!NT_STATUS_IS_OK(status)) {
985 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
986 return False;
989 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
991 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
992 NULL, NULL, NULL);
993 if (!NT_STATUS_IS_OK(status)) {
994 printf("qfileinfo failed (%s)\n", nt_errstr(status));
995 correct = False;
998 if (fsize == sizeof(buf))
999 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1000 (unsigned long)fsize);
1001 else {
1002 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1003 (unsigned long)fsize);
1004 correct = False;
1007 #if 0
1008 /* ToDo - set allocation. JRA */
1009 if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1010 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1011 return False;
1013 if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1014 NULL, NULL)) {
1015 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1016 correct = False;
1018 if (fsize != 0)
1019 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1020 #endif
1022 status = cli_close(cli1, fnum1);
1023 if (!NT_STATUS_IS_OK(status)) {
1024 printf("close failed (%s)\n", nt_errstr(status));
1025 correct = False;
1028 if (!torture_close_connection(cli1)) {
1029 correct = False;
1031 return correct;
1034 static bool run_readwritelarge(int dummy)
1036 return run_readwritelarge_internal();
1039 static bool run_readwritelarge_signtest(int dummy)
1041 bool ret;
1042 signing_state = SMB_SIGNING_REQUIRED;
1043 ret = run_readwritelarge_internal();
1044 signing_state = SMB_SIGNING_DEFAULT;
1045 return ret;
1048 int line_count = 0;
1049 int nbio_id;
1051 #define ival(s) strtol(s, NULL, 0)
1053 /* run a test that simulates an approximate netbench client load */
1054 static bool run_netbench(int client)
1056 struct cli_state *cli;
1057 int i;
1058 char line[1024];
1059 char cname[20];
1060 FILE *f;
1061 const char *params[20];
1062 bool correct = True;
1064 cli = current_cli;
1066 nbio_id = client;
1068 smbXcli_conn_set_sockopt(cli->conn, sockops);
1070 nb_setup(cli);
1072 slprintf(cname,sizeof(cname)-1, "client%d", client);
1074 f = fopen(client_txt, "r");
1076 if (!f) {
1077 perror(client_txt);
1078 return False;
1081 while (fgets(line, sizeof(line)-1, f)) {
1082 char *saveptr;
1083 line_count++;
1085 line[strlen(line)-1] = 0;
1087 /* printf("[%d] %s\n", line_count, line); */
1089 all_string_sub(line,"client1", cname, sizeof(line));
1091 /* parse the command parameters */
1092 params[0] = strtok_r(line, " ", &saveptr);
1093 i = 0;
1094 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1096 params[i] = "";
1098 if (i < 2) continue;
1100 if (!strncmp(params[0],"SMB", 3)) {
1101 printf("ERROR: You are using a dbench 1 load file\n");
1102 exit(1);
1105 if (!strcmp(params[0],"NTCreateX")) {
1106 nb_createx(params[1], ival(params[2]), ival(params[3]),
1107 ival(params[4]));
1108 } else if (!strcmp(params[0],"Close")) {
1109 nb_close(ival(params[1]));
1110 } else if (!strcmp(params[0],"Rename")) {
1111 nb_rename(params[1], params[2]);
1112 } else if (!strcmp(params[0],"Unlink")) {
1113 nb_unlink(params[1]);
1114 } else if (!strcmp(params[0],"Deltree")) {
1115 nb_deltree(params[1]);
1116 } else if (!strcmp(params[0],"Rmdir")) {
1117 nb_rmdir(params[1]);
1118 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1119 nb_qpathinfo(params[1]);
1120 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1121 nb_qfileinfo(ival(params[1]));
1122 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1123 nb_qfsinfo(ival(params[1]));
1124 } else if (!strcmp(params[0],"FIND_FIRST")) {
1125 nb_findfirst(params[1]);
1126 } else if (!strcmp(params[0],"WriteX")) {
1127 nb_writex(ival(params[1]),
1128 ival(params[2]), ival(params[3]), ival(params[4]));
1129 } else if (!strcmp(params[0],"ReadX")) {
1130 nb_readx(ival(params[1]),
1131 ival(params[2]), ival(params[3]), ival(params[4]));
1132 } else if (!strcmp(params[0],"Flush")) {
1133 nb_flush(ival(params[1]));
1134 } else {
1135 printf("Unknown operation %s\n", params[0]);
1136 exit(1);
1139 fclose(f);
1141 nb_cleanup();
1143 if (!torture_close_connection(cli)) {
1144 correct = False;
1147 return correct;
1151 /* run a test that simulates an approximate netbench client load */
1152 static bool run_nbench(int dummy)
1154 double t;
1155 bool correct = True;
1157 nbio_shmem(torture_nprocs);
1159 nbio_id = -1;
1161 signal(SIGALRM, nb_alarm);
1162 alarm(1);
1163 t = create_procs(run_netbench, &correct);
1164 alarm(0);
1166 printf("\nThroughput %g MB/sec\n",
1167 1.0e-6 * nbio_total() / t);
1168 return correct;
1173 This test checks for two things:
1175 1) correct support for retaining locks over a close (ie. the server
1176 must not use posix semantics)
1177 2) support for lock timeouts
1179 static bool run_locktest1(int dummy)
1181 struct cli_state *cli1, *cli2;
1182 const char *fname = "\\lockt1.lck";
1183 uint16_t fnum1, fnum2, fnum3;
1184 time_t t1, t2;
1185 unsigned lock_timeout;
1186 NTSTATUS status;
1188 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1189 return False;
1191 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1192 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1194 printf("starting locktest1\n");
1196 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1198 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1199 &fnum1);
1200 if (!NT_STATUS_IS_OK(status)) {
1201 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1202 return False;
1205 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1206 if (!NT_STATUS_IS_OK(status)) {
1207 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1208 return False;
1211 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1212 if (!NT_STATUS_IS_OK(status)) {
1213 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1214 return False;
1217 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1218 if (!NT_STATUS_IS_OK(status)) {
1219 printf("lock1 failed (%s)\n", nt_errstr(status));
1220 return false;
1223 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1224 if (NT_STATUS_IS_OK(status)) {
1225 printf("lock2 succeeded! This is a locking bug\n");
1226 return false;
1227 } else {
1228 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1229 NT_STATUS_LOCK_NOT_GRANTED)) {
1230 return false;
1234 lock_timeout = (1 + (random() % 20));
1235 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1236 t1 = time(NULL);
1237 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1238 if (NT_STATUS_IS_OK(status)) {
1239 printf("lock3 succeeded! This is a locking bug\n");
1240 return false;
1241 } else {
1242 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1243 NT_STATUS_FILE_LOCK_CONFLICT)) {
1244 return false;
1247 t2 = time(NULL);
1249 if (ABS(t2 - t1) < lock_timeout-1) {
1250 printf("error: This server appears not to support timed lock requests\n");
1253 printf("server slept for %u seconds for a %u second timeout\n",
1254 (unsigned int)(t2-t1), lock_timeout);
1256 status = cli_close(cli1, fnum2);
1257 if (!NT_STATUS_IS_OK(status)) {
1258 printf("close1 failed (%s)\n", nt_errstr(status));
1259 return False;
1262 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1263 if (NT_STATUS_IS_OK(status)) {
1264 printf("lock4 succeeded! This is a locking bug\n");
1265 return false;
1266 } else {
1267 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1268 NT_STATUS_FILE_LOCK_CONFLICT)) {
1269 return false;
1273 status = cli_close(cli1, fnum1);
1274 if (!NT_STATUS_IS_OK(status)) {
1275 printf("close2 failed (%s)\n", nt_errstr(status));
1276 return False;
1279 status = cli_close(cli2, fnum3);
1280 if (!NT_STATUS_IS_OK(status)) {
1281 printf("close3 failed (%s)\n", nt_errstr(status));
1282 return False;
1285 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1286 if (!NT_STATUS_IS_OK(status)) {
1287 printf("unlink failed (%s)\n", nt_errstr(status));
1288 return False;
1292 if (!torture_close_connection(cli1)) {
1293 return False;
1296 if (!torture_close_connection(cli2)) {
1297 return False;
1300 printf("Passed locktest1\n");
1301 return True;
1305 this checks to see if a secondary tconx can use open files from an
1306 earlier tconx
1308 static bool run_tcon_test(int dummy)
1310 static struct cli_state *cli;
1311 const char *fname = "\\tcontest.tmp";
1312 uint16_t fnum1;
1313 uint32_t cnum1, cnum2, cnum3;
1314 struct smbXcli_tcon *orig_tcon = NULL;
1315 uint16_t vuid1, vuid2;
1316 char buf[4];
1317 bool ret = True;
1318 NTSTATUS status;
1320 memset(buf, '\0', sizeof(buf));
1322 if (!torture_open_connection(&cli, 0)) {
1323 return False;
1325 smbXcli_conn_set_sockopt(cli->conn, sockops);
1327 printf("starting tcontest\n");
1329 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1331 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1332 if (!NT_STATUS_IS_OK(status)) {
1333 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1334 return False;
1337 cnum1 = cli_state_get_tid(cli);
1338 vuid1 = cli_state_get_uid(cli);
1340 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1341 if (!NT_STATUS_IS_OK(status)) {
1342 printf("initial write failed (%s)", nt_errstr(status));
1343 return False;
1346 orig_tcon = cli_state_save_tcon(cli);
1347 if (orig_tcon == NULL) {
1348 return false;
1351 status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1352 if (!NT_STATUS_IS_OK(status)) {
1353 printf("%s refused 2nd tree connect (%s)\n", host,
1354 nt_errstr(status));
1355 cli_shutdown(cli);
1356 return False;
1359 cnum2 = cli_state_get_tid(cli);
1360 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1361 vuid2 = cli_state_get_uid(cli) + 1;
1363 /* try a write with the wrong tid */
1364 cli_state_set_tid(cli, cnum2);
1366 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1367 if (NT_STATUS_IS_OK(status)) {
1368 printf("* server allows write with wrong TID\n");
1369 ret = False;
1370 } else {
1371 printf("server fails write with wrong TID : %s\n",
1372 nt_errstr(status));
1376 /* try a write with an invalid tid */
1377 cli_state_set_tid(cli, cnum3);
1379 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1380 if (NT_STATUS_IS_OK(status)) {
1381 printf("* server allows write with invalid TID\n");
1382 ret = False;
1383 } else {
1384 printf("server fails write with invalid TID : %s\n",
1385 nt_errstr(status));
1388 /* try a write with an invalid vuid */
1389 cli_state_set_uid(cli, vuid2);
1390 cli_state_set_tid(cli, cnum1);
1392 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1393 if (NT_STATUS_IS_OK(status)) {
1394 printf("* server allows write with invalid VUID\n");
1395 ret = False;
1396 } else {
1397 printf("server fails write with invalid VUID : %s\n",
1398 nt_errstr(status));
1401 cli_state_set_tid(cli, cnum1);
1402 cli_state_set_uid(cli, vuid1);
1404 status = cli_close(cli, fnum1);
1405 if (!NT_STATUS_IS_OK(status)) {
1406 printf("close failed (%s)\n", nt_errstr(status));
1407 return False;
1410 cli_state_set_tid(cli, cnum2);
1412 status = cli_tdis(cli);
1413 if (!NT_STATUS_IS_OK(status)) {
1414 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1415 return False;
1418 cli_state_restore_tcon(cli, orig_tcon);
1420 cli_state_set_tid(cli, cnum1);
1422 if (!torture_close_connection(cli)) {
1423 return False;
1426 return ret;
1431 checks for old style tcon support
1433 static bool run_tcon2_test(int dummy)
1435 static struct cli_state *cli;
1436 uint16_t cnum, max_xmit;
1437 char *service;
1438 NTSTATUS status;
1440 if (!torture_open_connection(&cli, 0)) {
1441 return False;
1443 smbXcli_conn_set_sockopt(cli->conn, sockops);
1445 printf("starting tcon2 test\n");
1447 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1448 return false;
1451 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1453 SAFE_FREE(service);
1455 if (!NT_STATUS_IS_OK(status)) {
1456 printf("tcon2 failed : %s\n", nt_errstr(status));
1457 } else {
1458 printf("tcon OK : max_xmit=%d cnum=%d\n",
1459 (int)max_xmit, (int)cnum);
1462 if (!torture_close_connection(cli)) {
1463 return False;
1466 printf("Passed tcon2 test\n");
1467 return True;
1470 static bool tcon_devtest(struct cli_state *cli,
1471 const char *myshare, const char *devtype,
1472 const char *return_devtype,
1473 NTSTATUS expected_error)
1475 NTSTATUS status;
1476 bool ret;
1478 status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1480 if (NT_STATUS_IS_OK(expected_error)) {
1481 if (NT_STATUS_IS_OK(status)) {
1482 if (return_devtype != NULL &&
1483 strequal(cli->dev, return_devtype)) {
1484 ret = True;
1485 } else {
1486 printf("tconX to share %s with type %s "
1487 "succeeded but returned the wrong "
1488 "device type (got [%s] but should have got [%s])\n",
1489 myshare, devtype, cli->dev, return_devtype);
1490 ret = False;
1492 } else {
1493 printf("tconX to share %s with type %s "
1494 "should have succeeded but failed\n",
1495 myshare, devtype);
1496 ret = False;
1498 cli_tdis(cli);
1499 } else {
1500 if (NT_STATUS_IS_OK(status)) {
1501 printf("tconx to share %s with type %s "
1502 "should have failed but succeeded\n",
1503 myshare, devtype);
1504 ret = False;
1505 } else {
1506 if (NT_STATUS_EQUAL(status, expected_error)) {
1507 ret = True;
1508 } else {
1509 printf("Returned unexpected error\n");
1510 ret = False;
1514 return ret;
1518 checks for correct tconX support
1520 static bool run_tcon_devtype_test(int dummy)
1522 static struct cli_state *cli1 = NULL;
1523 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1524 NTSTATUS status;
1525 bool ret = True;
1527 status = cli_full_connection_creds(&cli1,
1528 myname,
1529 host,
1530 NULL, /* dest_ss */
1531 port_to_use,
1532 NULL, /* service */
1533 NULL, /* service_type */
1534 torture_creds,
1535 flags,
1536 signing_state);
1538 if (!NT_STATUS_IS_OK(status)) {
1539 printf("could not open connection\n");
1540 return False;
1543 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1544 ret = False;
1546 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1547 ret = False;
1549 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1550 ret = False;
1552 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1553 ret = False;
1555 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1556 ret = False;
1558 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1559 ret = False;
1561 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1562 ret = False;
1564 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1565 ret = False;
1567 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1568 ret = False;
1570 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1571 ret = False;
1573 cli_shutdown(cli1);
1575 if (ret)
1576 printf("Passed tcondevtest\n");
1578 return ret;
1583 This test checks that
1585 1) the server supports multiple locking contexts on the one SMB
1586 connection, distinguished by PID.
1588 2) the server correctly fails overlapping locks made by the same PID (this
1589 goes against POSIX behaviour, which is why it is tricky to implement)
1591 3) the server denies unlock requests by an incorrect client PID
1593 static bool run_locktest2(int dummy)
1595 static struct cli_state *cli;
1596 const char *fname = "\\lockt2.lck";
1597 uint16_t fnum1, fnum2, fnum3;
1598 bool correct = True;
1599 NTSTATUS status;
1601 if (!torture_open_connection(&cli, 0)) {
1602 return False;
1605 smbXcli_conn_set_sockopt(cli->conn, sockops);
1607 printf("starting locktest2\n");
1609 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1611 cli_setpid(cli, 1);
1613 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1614 if (!NT_STATUS_IS_OK(status)) {
1615 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1616 return False;
1619 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1620 if (!NT_STATUS_IS_OK(status)) {
1621 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1622 return False;
1625 cli_setpid(cli, 2);
1627 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1628 if (!NT_STATUS_IS_OK(status)) {
1629 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1630 return False;
1633 cli_setpid(cli, 1);
1635 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1636 if (!NT_STATUS_IS_OK(status)) {
1637 printf("lock1 failed (%s)\n", nt_errstr(status));
1638 return false;
1641 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1642 if (NT_STATUS_IS_OK(status)) {
1643 printf("WRITE lock1 succeeded! This is a locking bug\n");
1644 correct = false;
1645 } else {
1646 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1647 NT_STATUS_LOCK_NOT_GRANTED)) {
1648 return false;
1652 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1653 if (NT_STATUS_IS_OK(status)) {
1654 printf("WRITE lock2 succeeded! This is a locking bug\n");
1655 correct = false;
1656 } else {
1657 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1658 NT_STATUS_LOCK_NOT_GRANTED)) {
1659 return false;
1663 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1664 if (NT_STATUS_IS_OK(status)) {
1665 printf("READ lock2 succeeded! This is a locking bug\n");
1666 correct = false;
1667 } else {
1668 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1669 NT_STATUS_FILE_LOCK_CONFLICT)) {
1670 return false;
1674 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1675 if (!NT_STATUS_IS_OK(status)) {
1676 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1678 cli_setpid(cli, 2);
1679 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1680 printf("unlock at 100 succeeded! This is a locking bug\n");
1681 correct = False;
1684 status = cli_unlock(cli, fnum1, 0, 4);
1685 if (NT_STATUS_IS_OK(status)) {
1686 printf("unlock1 succeeded! This is a locking bug\n");
1687 correct = false;
1688 } else {
1689 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1690 NT_STATUS_RANGE_NOT_LOCKED)) {
1691 return false;
1695 status = cli_unlock(cli, fnum1, 0, 8);
1696 if (NT_STATUS_IS_OK(status)) {
1697 printf("unlock2 succeeded! This is a locking bug\n");
1698 correct = false;
1699 } else {
1700 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1701 NT_STATUS_RANGE_NOT_LOCKED)) {
1702 return false;
1706 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1707 if (NT_STATUS_IS_OK(status)) {
1708 printf("lock3 succeeded! This is a locking bug\n");
1709 correct = false;
1710 } else {
1711 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1712 NT_STATUS_LOCK_NOT_GRANTED)) {
1713 return false;
1717 cli_setpid(cli, 1);
1719 status = cli_close(cli, fnum1);
1720 if (!NT_STATUS_IS_OK(status)) {
1721 printf("close1 failed (%s)\n", nt_errstr(status));
1722 return False;
1725 status = cli_close(cli, fnum2);
1726 if (!NT_STATUS_IS_OK(status)) {
1727 printf("close2 failed (%s)\n", nt_errstr(status));
1728 return False;
1731 status = cli_close(cli, fnum3);
1732 if (!NT_STATUS_IS_OK(status)) {
1733 printf("close3 failed (%s)\n", nt_errstr(status));
1734 return False;
1737 if (!torture_close_connection(cli)) {
1738 correct = False;
1741 printf("locktest2 finished\n");
1743 return correct;
1748 This test checks that
1750 1) the server supports the full offset range in lock requests
1752 static bool run_locktest3(int dummy)
1754 static struct cli_state *cli1, *cli2;
1755 const char *fname = "\\lockt3.lck";
1756 uint16_t fnum1, fnum2;
1757 int i;
1758 uint32_t offset;
1759 bool correct = True;
1760 NTSTATUS status;
1762 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1764 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1765 return False;
1767 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1768 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1770 printf("starting locktest3\n");
1772 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1774 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1775 &fnum1);
1776 if (!NT_STATUS_IS_OK(status)) {
1777 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1778 return False;
1781 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1782 if (!NT_STATUS_IS_OK(status)) {
1783 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1784 return False;
1787 for (offset=i=0;i<torture_numops;i++) {
1788 NEXT_OFFSET;
1790 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1791 if (!NT_STATUS_IS_OK(status)) {
1792 printf("lock1 %d failed (%s)\n",
1794 nt_errstr(status));
1795 return False;
1798 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1799 if (!NT_STATUS_IS_OK(status)) {
1800 printf("lock2 %d failed (%s)\n",
1802 nt_errstr(status));
1803 return False;
1807 for (offset=i=0;i<torture_numops;i++) {
1808 NEXT_OFFSET;
1810 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1811 if (NT_STATUS_IS_OK(status)) {
1812 printf("error: lock1 %d succeeded!\n", i);
1813 return False;
1816 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1817 if (NT_STATUS_IS_OK(status)) {
1818 printf("error: lock2 %d succeeded!\n", i);
1819 return False;
1822 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1823 if (NT_STATUS_IS_OK(status)) {
1824 printf("error: lock3 %d succeeded!\n", i);
1825 return False;
1828 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1829 if (NT_STATUS_IS_OK(status)) {
1830 printf("error: lock4 %d succeeded!\n", i);
1831 return False;
1835 for (offset=i=0;i<torture_numops;i++) {
1836 NEXT_OFFSET;
1838 status = cli_unlock(cli1, fnum1, offset-1, 1);
1839 if (!NT_STATUS_IS_OK(status)) {
1840 printf("unlock1 %d failed (%s)\n",
1842 nt_errstr(status));
1843 return False;
1846 status = cli_unlock(cli2, fnum2, offset-2, 1);
1847 if (!NT_STATUS_IS_OK(status)) {
1848 printf("unlock2 %d failed (%s)\n",
1850 nt_errstr(status));
1851 return False;
1855 status = cli_close(cli1, fnum1);
1856 if (!NT_STATUS_IS_OK(status)) {
1857 printf("close1 failed (%s)\n", nt_errstr(status));
1858 return False;
1861 status = cli_close(cli2, fnum2);
1862 if (!NT_STATUS_IS_OK(status)) {
1863 printf("close2 failed (%s)\n", nt_errstr(status));
1864 return False;
1867 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1868 if (!NT_STATUS_IS_OK(status)) {
1869 printf("unlink failed (%s)\n", nt_errstr(status));
1870 return False;
1873 if (!torture_close_connection(cli1)) {
1874 correct = False;
1877 if (!torture_close_connection(cli2)) {
1878 correct = False;
1881 printf("finished locktest3\n");
1883 return correct;
1886 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1887 char *buf, off_t offset, size_t size,
1888 size_t *nread, size_t expect)
1890 NTSTATUS status;
1891 size_t l_nread;
1893 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1895 if(!NT_STATUS_IS_OK(status)) {
1896 return false;
1897 } else if (l_nread != expect) {
1898 return false;
1901 if (nread) {
1902 *nread = l_nread;
1905 return true;
1908 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1909 printf("** "); correct = False; \
1913 looks at overlapping locks
1915 static bool run_locktest4(int dummy)
1917 static struct cli_state *cli1, *cli2;
1918 const char *fname = "\\lockt4.lck";
1919 uint16_t fnum1, fnum2, f;
1920 bool ret;
1921 char buf[1000];
1922 bool correct = True;
1923 NTSTATUS status;
1925 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1926 return False;
1929 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1930 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1932 printf("starting locktest4\n");
1934 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1936 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1937 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1939 memset(buf, 0, sizeof(buf));
1941 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1942 NULL);
1943 if (!NT_STATUS_IS_OK(status)) {
1944 printf("Failed to create file: %s\n", nt_errstr(status));
1945 correct = False;
1946 goto fail;
1949 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1950 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1951 EXPECTED(ret, False);
1952 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1954 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1955 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1956 EXPECTED(ret, True);
1957 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1959 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1960 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1961 EXPECTED(ret, False);
1962 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1964 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1965 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1966 EXPECTED(ret, True);
1967 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1969 ret = (cli_setpid(cli1, 1),
1970 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1971 (cli_setpid(cli1, 2),
1972 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1973 EXPECTED(ret, False);
1974 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1976 ret = (cli_setpid(cli1, 1),
1977 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1978 (cli_setpid(cli1, 2),
1979 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1980 EXPECTED(ret, True);
1981 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1983 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1984 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1985 EXPECTED(ret, True);
1986 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1988 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1989 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1990 EXPECTED(ret, False);
1991 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1993 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1994 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1995 EXPECTED(ret, False);
1996 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1998 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1999 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2000 EXPECTED(ret, True);
2001 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2003 ret = (cli_setpid(cli1, 1),
2004 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2005 (cli_setpid(cli1, 2),
2006 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2007 EXPECTED(ret, False);
2008 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2010 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2011 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2012 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2013 EXPECTED(ret, False);
2014 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2017 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2018 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2019 EXPECTED(ret, False);
2020 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2022 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2023 ret = NT_STATUS_IS_OK(status);
2024 if (ret) {
2025 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2026 NULL);
2027 ret = NT_STATUS_IS_OK(status);
2029 EXPECTED(ret, False);
2030 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2033 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2034 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2035 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2036 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2037 EXPECTED(ret, True);
2038 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2041 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2042 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2043 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2044 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2045 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2046 150, 4, NULL))) &&
2047 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2048 EXPECTED(ret, True);
2049 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2051 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2052 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2053 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2054 160, 4, NULL)) &&
2055 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2056 EXPECTED(ret, True);
2057 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2059 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2060 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2061 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2062 170, 4, NULL)) &&
2063 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2064 EXPECTED(ret, True);
2065 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2067 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2068 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2069 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2070 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2071 190, 4, NULL)) &&
2072 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2073 EXPECTED(ret, True);
2074 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2076 cli_close(cli1, fnum1);
2077 cli_close(cli2, fnum2);
2078 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2079 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2080 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2081 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2082 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2083 NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2084 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2085 cli_close(cli1, f);
2086 cli_close(cli1, fnum1);
2087 EXPECTED(ret, True);
2088 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2090 fail:
2091 cli_close(cli1, fnum1);
2092 cli_close(cli2, fnum2);
2093 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2094 torture_close_connection(cli1);
2095 torture_close_connection(cli2);
2097 printf("finished locktest4\n");
2098 return correct;
2102 looks at lock upgrade/downgrade.
2104 static bool run_locktest5(int dummy)
2106 static struct cli_state *cli1, *cli2;
2107 const char *fname = "\\lockt5.lck";
2108 uint16_t fnum1, fnum2, fnum3;
2109 bool ret;
2110 char buf[1000];
2111 bool correct = True;
2112 NTSTATUS status;
2114 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2115 return False;
2118 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2119 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2121 printf("starting locktest5\n");
2123 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2125 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2126 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2127 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2129 memset(buf, 0, sizeof(buf));
2131 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2132 NULL);
2133 if (!NT_STATUS_IS_OK(status)) {
2134 printf("Failed to create file: %s\n", nt_errstr(status));
2135 correct = False;
2136 goto fail;
2139 /* Check for NT bug... */
2140 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2141 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2142 cli_close(cli1, fnum1);
2143 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2144 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2145 ret = NT_STATUS_IS_OK(status);
2146 EXPECTED(ret, True);
2147 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2148 cli_close(cli1, fnum1);
2149 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2150 cli_unlock(cli1, fnum3, 0, 1);
2152 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2153 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2154 EXPECTED(ret, True);
2155 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2157 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2158 ret = NT_STATUS_IS_OK(status);
2159 EXPECTED(ret, False);
2161 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2163 /* Unlock the process 2 lock. */
2164 cli_unlock(cli2, fnum2, 0, 4);
2166 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2167 ret = NT_STATUS_IS_OK(status);
2168 EXPECTED(ret, False);
2170 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2172 /* Unlock the process 1 fnum3 lock. */
2173 cli_unlock(cli1, fnum3, 0, 4);
2175 /* Stack 2 more locks here. */
2176 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2177 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2179 EXPECTED(ret, True);
2180 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2182 /* Unlock the first process lock, then check this was the WRITE lock that was
2183 removed. */
2185 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2186 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2188 EXPECTED(ret, True);
2189 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2191 /* Unlock the process 2 lock. */
2192 cli_unlock(cli2, fnum2, 0, 4);
2194 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2196 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2197 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2198 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2200 EXPECTED(ret, True);
2201 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2203 /* Ensure the next unlock fails. */
2204 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2205 EXPECTED(ret, False);
2206 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2208 /* Ensure connection 2 can get a write lock. */
2209 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2210 ret = NT_STATUS_IS_OK(status);
2211 EXPECTED(ret, True);
2213 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2216 fail:
2217 cli_close(cli1, fnum1);
2218 cli_close(cli2, fnum2);
2219 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2220 if (!torture_close_connection(cli1)) {
2221 correct = False;
2223 if (!torture_close_connection(cli2)) {
2224 correct = False;
2227 printf("finished locktest5\n");
2229 return correct;
2233 tries the unusual lockingX locktype bits
2235 static bool run_locktest6(int dummy)
2237 static struct cli_state *cli;
2238 const char *fname[1] = { "\\lock6.txt" };
2239 int i;
2240 uint16_t fnum;
2241 NTSTATUS status;
2243 if (!torture_open_connection(&cli, 0)) {
2244 return False;
2247 smbXcli_conn_set_sockopt(cli->conn, sockops);
2249 printf("starting locktest6\n");
2251 for (i=0;i<1;i++) {
2252 printf("Testing %s\n", fname[i]);
2254 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2256 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2257 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2258 cli_close(cli, fnum);
2259 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2261 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2262 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2263 cli_close(cli, fnum);
2264 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2266 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2269 torture_close_connection(cli);
2271 printf("finished locktest6\n");
2272 return True;
2275 static bool run_locktest7(int dummy)
2277 struct cli_state *cli1;
2278 const char *fname = "\\lockt7.lck";
2279 uint16_t fnum1;
2280 char buf[200];
2281 bool correct = False;
2282 size_t nread;
2283 NTSTATUS status;
2285 if (!torture_open_connection(&cli1, 0)) {
2286 return False;
2289 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2291 printf("starting locktest7\n");
2293 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2295 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2297 memset(buf, 0, sizeof(buf));
2299 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2300 NULL);
2301 if (!NT_STATUS_IS_OK(status)) {
2302 printf("Failed to create file: %s\n", nt_errstr(status));
2303 goto fail;
2306 cli_setpid(cli1, 1);
2308 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2309 if (!NT_STATUS_IS_OK(status)) {
2310 printf("Unable to apply read lock on range 130:4, "
2311 "error was %s\n", nt_errstr(status));
2312 goto fail;
2313 } else {
2314 printf("pid1 successfully locked range 130:4 for READ\n");
2317 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2318 if (!NT_STATUS_IS_OK(status)) {
2319 printf("pid1 unable to read the range 130:4, error was %s\n",
2320 nt_errstr(status));
2321 goto fail;
2322 } else if (nread != 4) {
2323 printf("pid1 unable to read the range 130:4, "
2324 "recv %ld req %d\n", (unsigned long)nread, 4);
2325 goto fail;
2326 } else {
2327 printf("pid1 successfully read the range 130:4\n");
2330 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2331 if (!NT_STATUS_IS_OK(status)) {
2332 printf("pid1 unable to write to the range 130:4, error was "
2333 "%s\n", nt_errstr(status));
2334 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2335 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2336 goto fail;
2338 } else {
2339 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2340 goto fail;
2343 cli_setpid(cli1, 2);
2345 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2346 if (!NT_STATUS_IS_OK(status)) {
2347 printf("pid2 unable to read the range 130:4, error was %s\n",
2348 nt_errstr(status));
2349 goto fail;
2350 } else if (nread != 4) {
2351 printf("pid2 unable to read the range 130:4, "
2352 "recv %ld req %d\n", (unsigned long)nread, 4);
2353 goto fail;
2354 } else {
2355 printf("pid2 successfully read the range 130:4\n");
2358 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2359 if (!NT_STATUS_IS_OK(status)) {
2360 printf("pid2 unable to write to the range 130:4, error was "
2361 "%s\n", nt_errstr(status));
2362 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2363 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2364 goto fail;
2366 } else {
2367 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2368 goto fail;
2371 cli_setpid(cli1, 1);
2372 cli_unlock(cli1, fnum1, 130, 4);
2374 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2375 if (!NT_STATUS_IS_OK(status)) {
2376 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2377 goto fail;
2378 } else {
2379 printf("pid1 successfully locked range 130:4 for WRITE\n");
2382 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2383 if (!NT_STATUS_IS_OK(status)) {
2384 printf("pid1 unable to read the range 130:4, error was %s\n",
2385 nt_errstr(status));
2386 goto fail;
2387 } else if (nread != 4) {
2388 printf("pid1 unable to read the range 130:4, "
2389 "recv %ld req %d\n", (unsigned long)nread, 4);
2390 goto fail;
2391 } else {
2392 printf("pid1 successfully read the range 130:4\n");
2395 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2396 if (!NT_STATUS_IS_OK(status)) {
2397 printf("pid1 unable to write to the range 130:4, error was "
2398 "%s\n", nt_errstr(status));
2399 goto fail;
2400 } else {
2401 printf("pid1 successfully wrote to the range 130:4\n");
2404 cli_setpid(cli1, 2);
2406 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2407 if (!NT_STATUS_IS_OK(status)) {
2408 printf("pid2 unable to read 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 read the range 130:4 (should be denied) recv %ld\n",
2416 (unsigned long)nread);
2417 goto fail;
2420 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2421 if (!NT_STATUS_IS_OK(status)) {
2422 printf("pid2 unable to write to the range 130:4, error was "
2423 "%s\n", nt_errstr(status));
2424 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2425 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2426 goto fail;
2428 } else {
2429 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2430 goto fail;
2433 cli_unlock(cli1, fnum1, 130, 0);
2434 correct = True;
2436 fail:
2437 cli_close(cli1, fnum1);
2438 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2439 torture_close_connection(cli1);
2441 printf("finished locktest7\n");
2442 return correct;
2446 * This demonstrates a problem with our use of GPFS share modes: A file
2447 * descriptor sitting in the pending close queue holding a GPFS share mode
2448 * blocks opening a file another time. Happens with Word 2007 temp files.
2449 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2450 * open is denied with NT_STATUS_SHARING_VIOLATION.
2453 static bool run_locktest8(int dummy)
2455 struct cli_state *cli1;
2456 const char *fname = "\\lockt8.lck";
2457 uint16_t fnum1, fnum2;
2458 char buf[200];
2459 bool correct = False;
2460 NTSTATUS status;
2462 if (!torture_open_connection(&cli1, 0)) {
2463 return False;
2466 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2468 printf("starting locktest8\n");
2470 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2472 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2473 &fnum1);
2474 if (!NT_STATUS_IS_OK(status)) {
2475 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2476 return false;
2479 memset(buf, 0, sizeof(buf));
2481 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2482 if (!NT_STATUS_IS_OK(status)) {
2483 d_fprintf(stderr, "cli_openx second time returned %s\n",
2484 nt_errstr(status));
2485 goto fail;
2488 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2489 if (!NT_STATUS_IS_OK(status)) {
2490 printf("Unable to apply read lock on range 1:1, error was "
2491 "%s\n", nt_errstr(status));
2492 goto fail;
2495 status = cli_close(cli1, fnum1);
2496 if (!NT_STATUS_IS_OK(status)) {
2497 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2498 goto fail;
2501 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2502 if (!NT_STATUS_IS_OK(status)) {
2503 d_fprintf(stderr, "cli_openx third time returned %s\n",
2504 nt_errstr(status));
2505 goto fail;
2508 correct = true;
2510 fail:
2511 cli_close(cli1, fnum1);
2512 cli_close(cli1, fnum2);
2513 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2514 torture_close_connection(cli1);
2516 printf("finished locktest8\n");
2517 return correct;
2521 * This test is designed to be run in conjunction with
2522 * external NFS or POSIX locks taken in the filesystem.
2523 * It checks that the smbd server will block until the
2524 * lock is released and then acquire it. JRA.
2527 static bool got_alarm;
2528 static struct cli_state *alarm_cli;
2530 static void alarm_handler(int dummy)
2532 got_alarm = True;
2535 static void alarm_handler_parent(int dummy)
2537 smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_OK);
2540 static void do_local_lock(int read_fd, int write_fd)
2542 int fd;
2543 char c = '\0';
2544 struct flock lock;
2545 const char *local_pathname = NULL;
2546 int ret;
2548 local_pathname = talloc_asprintf(talloc_tos(),
2549 "%s/lockt9.lck", local_path);
2550 if (!local_pathname) {
2551 printf("child: alloc fail\n");
2552 exit(1);
2555 unlink(local_pathname);
2556 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2557 if (fd == -1) {
2558 printf("child: open of %s failed %s.\n",
2559 local_pathname, strerror(errno));
2560 exit(1);
2563 /* Now take a fcntl lock. */
2564 lock.l_type = F_WRLCK;
2565 lock.l_whence = SEEK_SET;
2566 lock.l_start = 0;
2567 lock.l_len = 4;
2568 lock.l_pid = getpid();
2570 ret = fcntl(fd,F_SETLK,&lock);
2571 if (ret == -1) {
2572 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2573 local_pathname, strerror(errno));
2574 exit(1);
2575 } else {
2576 printf("child: got lock 0:4 on file %s.\n",
2577 local_pathname );
2578 fflush(stdout);
2581 CatchSignal(SIGALRM, alarm_handler);
2582 alarm(5);
2583 /* Signal the parent. */
2584 if (write(write_fd, &c, 1) != 1) {
2585 printf("child: start signal fail %s.\n",
2586 strerror(errno));
2587 exit(1);
2589 alarm(0);
2591 alarm(10);
2592 /* Wait for the parent to be ready. */
2593 if (read(read_fd, &c, 1) != 1) {
2594 printf("child: reply signal fail %s.\n",
2595 strerror(errno));
2596 exit(1);
2598 alarm(0);
2600 sleep(5);
2601 close(fd);
2602 printf("child: released lock 0:4 on file %s.\n",
2603 local_pathname );
2604 fflush(stdout);
2605 exit(0);
2608 static bool run_locktest9(int dummy)
2610 struct cli_state *cli1;
2611 const char *fname = "\\lockt9.lck";
2612 uint16_t fnum;
2613 bool correct = False;
2614 int pipe_in[2], pipe_out[2];
2615 pid_t child_pid;
2616 char c = '\0';
2617 int ret;
2618 struct timeval start;
2619 double seconds;
2620 NTSTATUS status;
2622 printf("starting locktest9\n");
2624 if (local_path == NULL) {
2625 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2626 return false;
2629 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2630 return false;
2633 child_pid = fork();
2634 if (child_pid == -1) {
2635 return false;
2638 if (child_pid == 0) {
2639 /* Child. */
2640 do_local_lock(pipe_out[0], pipe_in[1]);
2641 exit(0);
2644 close(pipe_out[0]);
2645 close(pipe_in[1]);
2646 pipe_out[0] = -1;
2647 pipe_in[1] = -1;
2649 /* Parent. */
2650 ret = read(pipe_in[0], &c, 1);
2651 if (ret != 1) {
2652 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2653 strerror(errno));
2654 return false;
2657 if (!torture_open_connection(&cli1, 0)) {
2658 return false;
2661 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2663 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE,
2664 &fnum);
2665 if (!NT_STATUS_IS_OK(status)) {
2666 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2667 return false;
2670 /* Ensure the child has the lock. */
2671 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2672 if (NT_STATUS_IS_OK(status)) {
2673 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2674 goto fail;
2675 } else {
2676 d_printf("Child has the lock.\n");
2679 /* Tell the child to wait 5 seconds then exit. */
2680 ret = write(pipe_out[1], &c, 1);
2681 if (ret != 1) {
2682 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2683 strerror(errno));
2684 goto fail;
2687 /* Wait 20 seconds for the lock. */
2688 alarm_cli = cli1;
2689 CatchSignal(SIGALRM, alarm_handler_parent);
2690 alarm(20);
2692 start = timeval_current();
2694 status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2695 if (!NT_STATUS_IS_OK(status)) {
2696 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2697 "%s\n", nt_errstr(status));
2698 goto fail_nofd;
2700 alarm(0);
2702 seconds = timeval_elapsed(&start);
2704 printf("Parent got the lock after %.2f seconds.\n",
2705 seconds);
2707 status = cli_close(cli1, fnum);
2708 if (!NT_STATUS_IS_OK(status)) {
2709 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2710 goto fail;
2713 correct = true;
2715 fail:
2716 cli_close(cli1, fnum);
2717 torture_close_connection(cli1);
2719 fail_nofd:
2721 printf("finished locktest9\n");
2722 return correct;
2726 test whether fnums and tids open on one VC are available on another (a major
2727 security hole)
2729 static bool run_fdpasstest(int dummy)
2731 struct cli_state *cli1, *cli2;
2732 const char *fname = "\\fdpass.tst";
2733 uint16_t fnum1;
2734 char buf[1024];
2735 NTSTATUS status;
2737 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2738 return False;
2740 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2741 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2743 printf("starting fdpasstest\n");
2745 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2747 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2748 &fnum1);
2749 if (!NT_STATUS_IS_OK(status)) {
2750 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2751 return False;
2754 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2755 13, NULL);
2756 if (!NT_STATUS_IS_OK(status)) {
2757 printf("write failed (%s)\n", nt_errstr(status));
2758 return False;
2761 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
2762 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2763 cli_setpid(cli2, cli_getpid(cli1));
2765 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
2766 printf("read succeeded! nasty security hole [%s]\n", buf);
2767 return false;
2770 cli_close(cli1, fnum1);
2771 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2773 torture_close_connection(cli1);
2774 torture_close_connection(cli2);
2776 printf("finished fdpasstest\n");
2777 return True;
2780 static bool run_fdsesstest(int dummy)
2782 struct cli_state *cli;
2783 uint16_t new_vuid;
2784 uint16_t saved_vuid;
2785 uint32_t new_cnum;
2786 uint32_t saved_cnum;
2787 const char *fname = "\\fdsess.tst";
2788 const char *fname1 = "\\fdsess1.tst";
2789 uint16_t fnum1;
2790 uint16_t fnum2;
2791 char buf[1024];
2792 bool ret = True;
2793 NTSTATUS status;
2795 if (!torture_open_connection(&cli, 0))
2796 return False;
2797 smbXcli_conn_set_sockopt(cli->conn, sockops);
2799 if (!torture_cli_session_setup2(cli, &new_vuid))
2800 return False;
2802 saved_cnum = cli_state_get_tid(cli);
2803 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
2804 return False;
2805 new_cnum = cli_state_get_tid(cli);
2806 cli_state_set_tid(cli, saved_cnum);
2808 printf("starting fdsesstest\n");
2810 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2811 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2813 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2814 if (!NT_STATUS_IS_OK(status)) {
2815 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2816 return False;
2819 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2820 NULL);
2821 if (!NT_STATUS_IS_OK(status)) {
2822 printf("write failed (%s)\n", nt_errstr(status));
2823 return False;
2826 saved_vuid = cli_state_get_uid(cli);
2827 cli_state_set_uid(cli, new_vuid);
2829 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2830 printf("read succeeded with different vuid! "
2831 "nasty security hole [%s]\n", buf);
2832 ret = false;
2834 /* Try to open a file with different vuid, samba cnum. */
2835 if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2836 printf("create with different vuid, same cnum succeeded.\n");
2837 cli_close(cli, fnum2);
2838 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2839 } else {
2840 printf("create with different vuid, same cnum failed.\n");
2841 printf("This will cause problems with service clients.\n");
2842 ret = False;
2845 cli_state_set_uid(cli, saved_vuid);
2847 /* Try with same vuid, different cnum. */
2848 cli_state_set_tid(cli, new_cnum);
2850 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2851 printf("read succeeded with different cnum![%s]\n", buf);
2852 ret = false;
2855 cli_state_set_tid(cli, saved_cnum);
2856 cli_close(cli, fnum1);
2857 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2859 torture_close_connection(cli);
2861 printf("finished fdsesstest\n");
2862 return ret;
2866 This test checks that
2868 1) the server does not allow an unlink on a file that is open
2870 static bool run_unlinktest(int dummy)
2872 struct cli_state *cli;
2873 const char *fname = "\\unlink.tst";
2874 uint16_t fnum;
2875 bool correct = True;
2876 NTSTATUS status;
2878 if (!torture_open_connection(&cli, 0)) {
2879 return False;
2882 smbXcli_conn_set_sockopt(cli->conn, sockops);
2884 printf("starting unlink test\n");
2886 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2888 cli_setpid(cli, 1);
2890 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2891 if (!NT_STATUS_IS_OK(status)) {
2892 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2893 return False;
2896 status = cli_unlink(cli, fname,
2897 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2898 if (NT_STATUS_IS_OK(status)) {
2899 printf("error: server allowed unlink on an open file\n");
2900 correct = False;
2901 } else {
2902 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
2903 NT_STATUS_SHARING_VIOLATION);
2906 cli_close(cli, fnum);
2907 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2909 if (!torture_close_connection(cli)) {
2910 correct = False;
2913 printf("unlink test finished\n");
2915 return correct;
2920 test how many open files this server supports on the one socket
2922 static bool run_maxfidtest(int dummy)
2924 struct cli_state *cli;
2925 fstring fname;
2926 uint16_t fnums[0x11000];
2927 int i;
2928 int retries=4;
2929 bool correct = True;
2930 NTSTATUS status;
2932 cli = current_cli;
2934 if (retries <= 0) {
2935 printf("failed to connect\n");
2936 return False;
2939 smbXcli_conn_set_sockopt(cli->conn, sockops);
2941 for (i=0; i<0x11000; i++) {
2942 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2943 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2944 &fnums[i]);
2945 if (!NT_STATUS_IS_OK(status)) {
2946 printf("open of %s failed (%s)\n",
2947 fname, nt_errstr(status));
2948 printf("maximum fnum is %d\n", i);
2949 break;
2951 printf("%6d\r", i);
2953 printf("%6d\n", i);
2954 i--;
2956 printf("cleaning up\n");
2957 for (;i>=0;i--) {
2958 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2959 cli_close(cli, fnums[i]);
2961 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2962 if (!NT_STATUS_IS_OK(status)) {
2963 printf("unlink of %s failed (%s)\n",
2964 fname, nt_errstr(status));
2965 correct = False;
2967 printf("%6d\r", i);
2969 printf("%6d\n", 0);
2971 printf("maxfid test finished\n");
2972 if (!torture_close_connection(cli)) {
2973 correct = False;
2975 return correct;
2978 /* generate a random buffer */
2979 static void rand_buf(char *buf, int len)
2981 while (len--) {
2982 *buf = (char)sys_random();
2983 buf++;
2987 /* send smb negprot commands, not reading the response */
2988 static bool run_negprot_nowait(int dummy)
2990 struct tevent_context *ev;
2991 int i;
2992 struct cli_state *cli;
2993 bool correct = True;
2995 printf("starting negprot nowait test\n");
2997 ev = samba_tevent_context_init(talloc_tos());
2998 if (ev == NULL) {
2999 return false;
3002 if (!(cli = open_nbt_connection())) {
3003 TALLOC_FREE(ev);
3004 return False;
3007 for (i=0;i<50000;i++) {
3008 struct tevent_req *req;
3010 req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
3011 PROTOCOL_CORE, PROTOCOL_NT1, 0);
3012 if (req == NULL) {
3013 TALLOC_FREE(ev);
3014 return false;
3016 if (!tevent_req_poll(req, ev)) {
3017 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3018 strerror(errno));
3019 TALLOC_FREE(ev);
3020 return false;
3022 TALLOC_FREE(req);
3025 if (torture_close_connection(cli)) {
3026 correct = False;
3029 printf("finished negprot nowait test\n");
3031 return correct;
3034 /* send smb negprot commands, not reading the response */
3035 static bool run_bad_nbt_session(int dummy)
3037 struct nmb_name called, calling;
3038 struct sockaddr_storage ss;
3039 NTSTATUS status;
3040 int fd;
3041 bool ret;
3043 printf("starting bad nbt session test\n");
3045 make_nmb_name(&calling, myname, 0x0);
3046 make_nmb_name(&called , host, 0x20);
3048 if (!resolve_name(host, &ss, 0x20, true)) {
3049 d_fprintf(stderr, "Could not resolve name %s\n", host);
3050 return false;
3053 status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3054 if (!NT_STATUS_IS_OK(status)) {
3055 d_fprintf(stderr, "open_socket_out failed: %s\n",
3056 nt_errstr(status));
3057 return false;
3060 ret = cli_bad_session_request(fd, &calling, &called);
3061 close(fd);
3062 if (!ret) {
3063 d_fprintf(stderr, "open_socket_out failed: %s\n",
3064 nt_errstr(status));
3065 return false;
3068 printf("finished bad nbt session test\n");
3069 return true;
3072 /* send random IPC commands */
3073 static bool run_randomipc(int dummy)
3075 char *rparam = NULL;
3076 char *rdata = NULL;
3077 unsigned int rdrcnt,rprcnt;
3078 char param[1024];
3079 int api, param_len, i;
3080 struct cli_state *cli;
3081 bool correct = True;
3082 int count = 50000;
3084 printf("starting random ipc test\n");
3086 if (!torture_open_connection(&cli, 0)) {
3087 return False;
3090 for (i=0;i<count;i++) {
3091 api = sys_random() % 500;
3092 param_len = (sys_random() % 64);
3094 rand_buf(param, param_len);
3096 SSVAL(param,0,api);
3098 cli_api(cli,
3099 param, param_len, 8,
3100 NULL, 0, CLI_BUFFER_SIZE,
3101 &rparam, &rprcnt,
3102 &rdata, &rdrcnt);
3103 if (i % 100 == 0) {
3104 printf("%d/%d\r", i,count);
3107 printf("%d/%d\n", i, count);
3109 if (!torture_close_connection(cli)) {
3110 correct = False;
3113 SAFE_FREE(rparam);
3114 SAFE_FREE(rdata);
3116 printf("finished random ipc test\n");
3118 return correct;
3123 static void browse_callback(const char *sname, uint32_t stype,
3124 const char *comment, void *state)
3126 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3132 This test checks the browse list code
3135 static bool run_browsetest(int dummy)
3137 static struct cli_state *cli;
3138 bool correct = True;
3140 printf("starting browse test\n");
3142 if (!torture_open_connection(&cli, 0)) {
3143 return False;
3146 printf("domain list:\n");
3147 cli_NetServerEnum(cli, cli->server_domain,
3148 SV_TYPE_DOMAIN_ENUM,
3149 browse_callback, NULL);
3151 printf("machine list:\n");
3152 cli_NetServerEnum(cli, cli->server_domain,
3153 SV_TYPE_ALL,
3154 browse_callback, NULL);
3156 if (!torture_close_connection(cli)) {
3157 correct = False;
3160 printf("browse test finished\n");
3162 return correct;
3166 static bool check_attributes(struct cli_state *cli,
3167 const char *fname,
3168 uint16_t expected_attrs)
3170 uint16_t attrs = 0;
3171 NTSTATUS status = cli_getatr(cli,
3172 fname,
3173 &attrs,
3174 NULL,
3175 NULL);
3176 if (!NT_STATUS_IS_OK(status)) {
3177 printf("cli_getatr failed with %s\n",
3178 nt_errstr(status));
3179 return false;
3181 if (attrs != expected_attrs) {
3182 printf("Attributes incorrect 0x%x, should be 0x%x\n",
3183 (unsigned int)attrs,
3184 (unsigned int)expected_attrs);
3185 return false;
3187 return true;
3191 This checks how the getatr calls works
3193 static bool run_attrtest(int dummy)
3195 struct cli_state *cli;
3196 uint16_t fnum;
3197 time_t t, t2;
3198 const char *fname = "\\attrib123456789.tst";
3199 bool correct = True;
3200 NTSTATUS status;
3202 printf("starting attrib test\n");
3204 if (!torture_open_connection(&cli, 0)) {
3205 return False;
3208 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3209 cli_openx(cli, fname,
3210 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3211 cli_close(cli, fnum);
3213 status = cli_getatr(cli, fname, NULL, NULL, &t);
3214 if (!NT_STATUS_IS_OK(status)) {
3215 printf("getatr failed (%s)\n", nt_errstr(status));
3216 correct = False;
3219 if (labs(t - time(NULL)) > 60*60*24*10) {
3220 printf("ERROR: SMBgetatr bug. time is %s",
3221 ctime(&t));
3222 t = time(NULL);
3223 correct = True;
3226 t2 = t-60*60*24; /* 1 day ago */
3228 status = cli_setatr(cli, fname, 0, t2);
3229 if (!NT_STATUS_IS_OK(status)) {
3230 printf("setatr failed (%s)\n", nt_errstr(status));
3231 correct = True;
3234 status = cli_getatr(cli, fname, NULL, NULL, &t);
3235 if (!NT_STATUS_IS_OK(status)) {
3236 printf("getatr failed (%s)\n", nt_errstr(status));
3237 correct = True;
3240 if (t != t2) {
3241 printf("ERROR: getatr/setatr bug. times are\n%s",
3242 ctime(&t));
3243 printf("%s", ctime(&t2));
3244 correct = True;
3247 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3249 /* Check cli_setpathinfo_basic() */
3250 /* Re-create the file. */
3251 status = cli_openx(cli, fname,
3252 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3253 if (!NT_STATUS_IS_OK(status)) {
3254 printf("Failed to recreate %s (%s)\n",
3255 fname, nt_errstr(status));
3256 correct = false;
3258 cli_close(cli, fnum);
3260 status = cli_setpathinfo_basic(cli,
3261 fname,
3262 0, /* create */
3263 0, /* access */
3264 0, /* write */
3265 0, /* change */
3266 FILE_ATTRIBUTE_SYSTEM |
3267 FILE_ATTRIBUTE_HIDDEN |
3268 FILE_ATTRIBUTE_READONLY);
3269 if (!NT_STATUS_IS_OK(status)) {
3270 printf("cli_setpathinfo_basic failed with %s\n",
3271 nt_errstr(status));
3272 correct = false;
3275 /* Check attributes are correct. */
3276 correct = check_attributes(cli,
3277 fname,
3278 FILE_ATTRIBUTE_SYSTEM |
3279 FILE_ATTRIBUTE_HIDDEN |
3280 FILE_ATTRIBUTE_READONLY);
3281 if (correct == false) {
3282 goto out;
3285 /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
3286 status = cli_setpathinfo_basic(cli,
3287 fname,
3288 0, /* create */
3289 0, /* access */
3290 0, /* write */
3291 0, /* change */
3292 FILE_ATTRIBUTE_NORMAL);
3293 if (!NT_STATUS_IS_OK(status)) {
3294 printf("cli_setpathinfo_basic failed with %s\n",
3295 nt_errstr(status));
3296 correct = false;
3299 /* Check attributes are correct. */
3300 correct = check_attributes(cli,
3301 fname,
3302 FILE_ATTRIBUTE_SYSTEM |
3303 FILE_ATTRIBUTE_HIDDEN |
3304 FILE_ATTRIBUTE_READONLY);
3305 if (correct == false) {
3306 goto out;
3309 /* Setting to (uint16_t)-1 should also be ignored. */
3310 status = cli_setpathinfo_basic(cli,
3311 fname,
3312 0, /* create */
3313 0, /* access */
3314 0, /* write */
3315 0, /* change */
3316 (uint16_t)-1);
3317 if (!NT_STATUS_IS_OK(status)) {
3318 printf("cli_setpathinfo_basic failed with %s\n",
3319 nt_errstr(status));
3320 correct = false;
3323 /* Check attributes are correct. */
3324 correct = check_attributes(cli,
3325 fname,
3326 FILE_ATTRIBUTE_SYSTEM |
3327 FILE_ATTRIBUTE_HIDDEN |
3328 FILE_ATTRIBUTE_READONLY);
3329 if (correct == false) {
3330 goto out;
3333 /* Setting to 0 should clear them all. */
3334 status = cli_setpathinfo_basic(cli,
3335 fname,
3336 0, /* create */
3337 0, /* access */
3338 0, /* write */
3339 0, /* change */
3341 if (!NT_STATUS_IS_OK(status)) {
3342 printf("cli_setpathinfo_basic failed with %s\n",
3343 nt_errstr(status));
3344 correct = false;
3347 /* Check attributes are correct. */
3348 correct = check_attributes(cli,
3349 fname,
3350 FILE_ATTRIBUTE_NORMAL);
3351 if (correct == false) {
3352 goto out;
3355 out:
3357 cli_unlink(cli,
3358 fname,
3359 FILE_ATTRIBUTE_SYSTEM |
3360 FILE_ATTRIBUTE_HIDDEN|
3361 FILE_ATTRIBUTE_READONLY);
3363 if (!torture_close_connection(cli)) {
3364 correct = False;
3367 printf("attrib test finished\n");
3369 return correct;
3374 This checks a couple of trans2 calls
3376 static bool run_trans2test(int dummy)
3378 struct cli_state *cli;
3379 uint16_t fnum;
3380 off_t size;
3381 time_t c_time, a_time, m_time;
3382 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3383 const char *fname = "\\trans2.tst";
3384 const char *dname = "\\trans2";
3385 const char *fname2 = "\\trans2\\trans2.tst";
3386 char *pname;
3387 bool correct = True;
3388 NTSTATUS status;
3389 uint32_t fs_attr;
3391 printf("starting trans2 test\n");
3393 if (!torture_open_connection(&cli, 0)) {
3394 return False;
3397 status = cli_get_fs_attr_info(cli, &fs_attr);
3398 if (!NT_STATUS_IS_OK(status)) {
3399 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3400 nt_errstr(status));
3401 correct = false;
3404 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3405 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3406 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3407 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3408 if (!NT_STATUS_IS_OK(status)) {
3409 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3410 correct = False;
3413 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3414 if (!NT_STATUS_IS_OK(status)) {
3415 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3416 correct = False;
3418 else if (strcmp(pname, fname)) {
3419 printf("qfilename gave different name? [%s] [%s]\n",
3420 fname, pname);
3421 correct = False;
3424 cli_close(cli, fnum);
3426 sleep(2);
3428 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3429 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3430 &fnum);
3431 if (!NT_STATUS_IS_OK(status)) {
3432 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3433 return False;
3435 cli_close(cli, fnum);
3437 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3438 NULL);
3439 if (!NT_STATUS_IS_OK(status)) {
3440 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3441 correct = False;
3442 } else {
3443 time_t t = time(NULL);
3445 if (c_time != m_time) {
3446 printf("create time=%s", ctime(&c_time));
3447 printf("modify time=%s", ctime(&m_time));
3448 printf("This system appears to have sticky create times\n");
3450 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
3451 printf("access time=%s", ctime(&a_time));
3452 printf("This system appears to set a midnight access time\n");
3453 correct = False;
3456 if (labs(m_time - t) > 60*60*24*7) {
3457 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3458 correct = False;
3463 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3464 cli_openx(cli, fname,
3465 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3466 cli_close(cli, fnum);
3467 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3468 &m_time_ts, &size, NULL, NULL);
3469 if (!NT_STATUS_IS_OK(status)) {
3470 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3471 correct = False;
3472 } else {
3473 if (w_time_ts.tv_sec < 60*60*24*2) {
3474 printf("write time=%s", ctime(&w_time_ts.tv_sec));
3475 printf("This system appears to set a initial 0 write time\n");
3476 correct = False;
3480 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3483 /* check if the server updates the directory modification time
3484 when creating a new file */
3485 status = cli_mkdir(cli, dname);
3486 if (!NT_STATUS_IS_OK(status)) {
3487 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3488 correct = False;
3490 sleep(3);
3491 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3492 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3493 if (!NT_STATUS_IS_OK(status)) {
3494 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3495 correct = False;
3498 cli_openx(cli, fname2,
3499 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3500 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3501 cli_close(cli, fnum);
3502 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3503 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3504 if (!NT_STATUS_IS_OK(status)) {
3505 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3506 correct = False;
3507 } else {
3508 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3509 == 0) {
3510 printf("This system does not update directory modification times\n");
3511 correct = False;
3514 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3515 cli_rmdir(cli, dname);
3517 if (!torture_close_connection(cli)) {
3518 correct = False;
3521 printf("trans2 test finished\n");
3523 return correct;
3527 This checks new W2K calls.
3530 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3532 uint8_t *buf = NULL;
3533 uint32_t len;
3534 NTSTATUS status;
3536 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3537 CLI_BUFFER_SIZE, NULL, &buf, &len);
3538 if (!NT_STATUS_IS_OK(status)) {
3539 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3540 nt_errstr(status));
3541 } else {
3542 printf("qfileinfo: level %d, len = %u\n", level, len);
3543 dump_data(0, (uint8_t *)buf, len);
3544 printf("\n");
3546 TALLOC_FREE(buf);
3547 return status;
3550 static bool run_w2ktest(int dummy)
3552 struct cli_state *cli;
3553 uint16_t fnum;
3554 const char *fname = "\\w2ktest\\w2k.tst";
3555 int level;
3556 bool correct = True;
3558 printf("starting w2k test\n");
3560 if (!torture_open_connection(&cli, 0)) {
3561 return False;
3564 cli_openx(cli, fname,
3565 O_RDWR | O_CREAT , DENY_NONE, &fnum);
3567 for (level = 1004; level < 1040; level++) {
3568 new_trans(cli, fnum, level);
3571 cli_close(cli, fnum);
3573 if (!torture_close_connection(cli)) {
3574 correct = False;
3577 printf("w2k test finished\n");
3579 return correct;
3584 this is a harness for some oplock tests
3586 static bool run_oplock1(int dummy)
3588 struct cli_state *cli1;
3589 const char *fname = "\\lockt1.lck";
3590 uint16_t fnum1;
3591 bool correct = True;
3592 NTSTATUS status;
3594 printf("starting oplock test 1\n");
3596 if (!torture_open_connection(&cli1, 0)) {
3597 return False;
3600 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3602 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3604 cli1->use_oplocks = True;
3606 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3607 &fnum1);
3608 if (!NT_STATUS_IS_OK(status)) {
3609 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3610 return False;
3613 cli1->use_oplocks = False;
3615 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3616 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3618 status = cli_close(cli1, fnum1);
3619 if (!NT_STATUS_IS_OK(status)) {
3620 printf("close2 failed (%s)\n", nt_errstr(status));
3621 return False;
3624 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3625 if (!NT_STATUS_IS_OK(status)) {
3626 printf("unlink failed (%s)\n", nt_errstr(status));
3627 return False;
3630 if (!torture_close_connection(cli1)) {
3631 correct = False;
3634 printf("finished oplock test 1\n");
3636 return correct;
3639 static bool run_oplock2(int dummy)
3641 struct cli_state *cli1, *cli2;
3642 const char *fname = "\\lockt2.lck";
3643 uint16_t fnum1, fnum2;
3644 int saved_use_oplocks = use_oplocks;
3645 char buf[4];
3646 bool correct = True;
3647 volatile bool *shared_correct;
3648 size_t nread;
3649 NTSTATUS status;
3651 shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
3652 *shared_correct = True;
3654 use_level_II_oplocks = True;
3655 use_oplocks = True;
3657 printf("starting oplock test 2\n");
3659 if (!torture_open_connection(&cli1, 0)) {
3660 use_level_II_oplocks = False;
3661 use_oplocks = saved_use_oplocks;
3662 return False;
3665 if (!torture_open_connection(&cli2, 1)) {
3666 use_level_II_oplocks = False;
3667 use_oplocks = saved_use_oplocks;
3668 return False;
3671 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3673 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3674 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3676 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3677 &fnum1);
3678 if (!NT_STATUS_IS_OK(status)) {
3679 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3680 return False;
3683 /* Don't need the globals any more. */
3684 use_level_II_oplocks = False;
3685 use_oplocks = saved_use_oplocks;
3687 if (fork() == 0) {
3688 /* Child code */
3689 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3690 if (!NT_STATUS_IS_OK(status)) {
3691 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3692 *shared_correct = False;
3693 exit(0);
3696 sleep(2);
3698 status = cli_close(cli2, fnum2);
3699 if (!NT_STATUS_IS_OK(status)) {
3700 printf("close2 failed (%s)\n", nt_errstr(status));
3701 *shared_correct = False;
3704 exit(0);
3707 sleep(2);
3709 /* Ensure cli1 processes the break. Empty file should always return 0
3710 * bytes. */
3711 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
3712 if (!NT_STATUS_IS_OK(status)) {
3713 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
3714 correct = false;
3715 } else if (nread != 0) {
3716 printf("read on empty fnum1 failed. recv %ld expected %d\n",
3717 (unsigned long)nread, 0);
3718 correct = false;
3721 /* Should now be at level II. */
3722 /* Test if sending a write locks causes a break to none. */
3723 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3724 if (!NT_STATUS_IS_OK(status)) {
3725 printf("lock failed (%s)\n", nt_errstr(status));
3726 correct = False;
3729 cli_unlock(cli1, fnum1, 0, 4);
3731 sleep(2);
3733 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3734 if (!NT_STATUS_IS_OK(status)) {
3735 printf("lock failed (%s)\n", nt_errstr(status));
3736 correct = False;
3739 cli_unlock(cli1, fnum1, 0, 4);
3741 sleep(2);
3743 cli_read(cli1, fnum1, buf, 0, 4, NULL);
3745 status = cli_close(cli1, fnum1);
3746 if (!NT_STATUS_IS_OK(status)) {
3747 printf("close1 failed (%s)\n", nt_errstr(status));
3748 correct = False;
3751 sleep(4);
3753 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3754 if (!NT_STATUS_IS_OK(status)) {
3755 printf("unlink failed (%s)\n", nt_errstr(status));
3756 correct = False;
3759 if (!torture_close_connection(cli1)) {
3760 correct = False;
3763 if (!*shared_correct) {
3764 correct = False;
3767 printf("finished oplock test 2\n");
3769 return correct;
3772 struct oplock4_state {
3773 struct tevent_context *ev;
3774 struct cli_state *cli;
3775 bool *got_break;
3776 uint16_t *fnum2;
3779 static void oplock4_got_break(struct tevent_req *req);
3780 static void oplock4_got_open(struct tevent_req *req);
3782 static bool run_oplock4(int dummy)
3784 struct tevent_context *ev;
3785 struct cli_state *cli1, *cli2;
3786 struct tevent_req *oplock_req, *open_req;
3787 const char *fname = "\\lockt4.lck";
3788 const char *fname_ln = "\\lockt4_ln.lck";
3789 uint16_t fnum1, fnum2;
3790 int saved_use_oplocks = use_oplocks;
3791 NTSTATUS status;
3792 bool correct = true;
3794 bool got_break;
3796 struct oplock4_state *state;
3798 printf("starting oplock test 4\n");
3800 if (!torture_open_connection(&cli1, 0)) {
3801 use_level_II_oplocks = false;
3802 use_oplocks = saved_use_oplocks;
3803 return false;
3806 if (!torture_open_connection(&cli2, 1)) {
3807 use_level_II_oplocks = false;
3808 use_oplocks = saved_use_oplocks;
3809 return false;
3812 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3813 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3815 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3816 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3818 /* Create the file. */
3819 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3820 &fnum1);
3821 if (!NT_STATUS_IS_OK(status)) {
3822 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3823 return false;
3826 status = cli_close(cli1, fnum1);
3827 if (!NT_STATUS_IS_OK(status)) {
3828 printf("close1 failed (%s)\n", nt_errstr(status));
3829 return false;
3832 /* Now create a hardlink. */
3833 status = cli_nt_hardlink(cli1, fname, fname_ln);
3834 if (!NT_STATUS_IS_OK(status)) {
3835 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3836 return false;
3839 /* Prove that opening hardlinks cause deny modes to conflict. */
3840 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3841 if (!NT_STATUS_IS_OK(status)) {
3842 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3843 return false;
3846 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3847 if (NT_STATUS_IS_OK(status)) {
3848 printf("open of %s succeeded - should fail with sharing violation.\n",
3849 fname_ln);
3850 return false;
3853 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3854 printf("open of %s should fail with sharing violation. Got %s\n",
3855 fname_ln, nt_errstr(status));
3856 return false;
3859 status = cli_close(cli1, fnum1);
3860 if (!NT_STATUS_IS_OK(status)) {
3861 printf("close1 failed (%s)\n", nt_errstr(status));
3862 return false;
3865 cli1->use_oplocks = true;
3866 cli2->use_oplocks = true;
3868 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3869 if (!NT_STATUS_IS_OK(status)) {
3870 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3871 return false;
3874 ev = samba_tevent_context_init(talloc_tos());
3875 if (ev == NULL) {
3876 printf("tevent_context_init failed\n");
3877 return false;
3880 state = talloc(ev, struct oplock4_state);
3881 if (state == NULL) {
3882 printf("talloc failed\n");
3883 return false;
3885 state->ev = ev;
3886 state->cli = cli1;
3887 state->got_break = &got_break;
3888 state->fnum2 = &fnum2;
3890 oplock_req = cli_smb_oplock_break_waiter_send(
3891 talloc_tos(), ev, cli1);
3892 if (oplock_req == NULL) {
3893 printf("cli_smb_oplock_break_waiter_send failed\n");
3894 return false;
3896 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3898 open_req = cli_openx_send(
3899 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3900 if (open_req == NULL) {
3901 printf("cli_openx_send failed\n");
3902 return false;
3904 tevent_req_set_callback(open_req, oplock4_got_open, state);
3906 got_break = false;
3907 fnum2 = 0xffff;
3909 while (!got_break || fnum2 == 0xffff) {
3910 int ret;
3911 ret = tevent_loop_once(ev);
3912 if (ret == -1) {
3913 printf("tevent_loop_once failed: %s\n",
3914 strerror(errno));
3915 return false;
3919 status = cli_close(cli2, fnum2);
3920 if (!NT_STATUS_IS_OK(status)) {
3921 printf("close2 failed (%s)\n", nt_errstr(status));
3922 correct = false;
3925 status = cli_close(cli1, fnum1);
3926 if (!NT_STATUS_IS_OK(status)) {
3927 printf("close1 failed (%s)\n", nt_errstr(status));
3928 correct = false;
3931 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3932 if (!NT_STATUS_IS_OK(status)) {
3933 printf("unlink failed (%s)\n", nt_errstr(status));
3934 correct = false;
3937 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3938 if (!NT_STATUS_IS_OK(status)) {
3939 printf("unlink failed (%s)\n", nt_errstr(status));
3940 correct = false;
3943 if (!torture_close_connection(cli1)) {
3944 correct = false;
3947 if (!got_break) {
3948 correct = false;
3951 printf("finished oplock test 4\n");
3953 return correct;
3956 static void oplock4_got_break(struct tevent_req *req)
3958 struct oplock4_state *state = tevent_req_callback_data(
3959 req, struct oplock4_state);
3960 uint16_t fnum;
3961 uint8_t level;
3962 NTSTATUS status;
3964 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3965 TALLOC_FREE(req);
3966 if (!NT_STATUS_IS_OK(status)) {
3967 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3968 nt_errstr(status));
3969 return;
3971 *state->got_break = true;
3973 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3974 NO_OPLOCK);
3975 if (req == NULL) {
3976 printf("cli_oplock_ack_send failed\n");
3977 return;
3981 static void oplock4_got_open(struct tevent_req *req)
3983 struct oplock4_state *state = tevent_req_callback_data(
3984 req, struct oplock4_state);
3985 NTSTATUS status;
3987 status = cli_openx_recv(req, state->fnum2);
3988 if (!NT_STATUS_IS_OK(status)) {
3989 printf("cli_openx_recv returned %s\n", nt_errstr(status));
3990 *state->fnum2 = 0xffff;
3995 Test delete on close semantics.
3997 static bool run_deletetest(int dummy)
3999 struct cli_state *cli1 = NULL;
4000 struct cli_state *cli2 = NULL;
4001 const char *fname = "\\delete.file";
4002 uint16_t fnum1 = (uint16_t)-1;
4003 uint16_t fnum2 = (uint16_t)-1;
4004 bool correct = false;
4005 NTSTATUS status;
4007 printf("starting delete test\n");
4009 if (!torture_open_connection(&cli1, 0)) {
4010 return False;
4013 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4015 /* Test 1 - this should delete the file on close. */
4017 cli_setatr(cli1, fname, 0, 0);
4018 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4020 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
4021 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4022 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4023 if (!NT_STATUS_IS_OK(status)) {
4024 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
4025 goto fail;
4028 status = cli_close(cli1, fnum1);
4029 if (!NT_STATUS_IS_OK(status)) {
4030 printf("[1] close failed (%s)\n", nt_errstr(status));
4031 goto fail;
4034 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4035 if (NT_STATUS_IS_OK(status)) {
4036 printf("[1] open of %s succeeded (should fail)\n", fname);
4037 goto fail;
4040 printf("first delete on close test succeeded.\n");
4042 /* Test 2 - this should delete the file on close. */
4044 cli_setatr(cli1, fname, 0, 0);
4045 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4047 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
4048 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4049 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4050 if (!NT_STATUS_IS_OK(status)) {
4051 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
4052 goto fail;
4055 status = cli_nt_delete_on_close(cli1, fnum1, true);
4056 if (!NT_STATUS_IS_OK(status)) {
4057 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
4058 goto fail;
4061 status = cli_close(cli1, fnum1);
4062 if (!NT_STATUS_IS_OK(status)) {
4063 printf("[2] close failed (%s)\n", nt_errstr(status));
4064 goto fail;
4067 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4068 if (NT_STATUS_IS_OK(status)) {
4069 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
4070 status = cli_close(cli1, fnum1);
4071 if (!NT_STATUS_IS_OK(status)) {
4072 printf("[2] close failed (%s)\n", nt_errstr(status));
4074 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4075 goto fail;
4078 printf("second delete on close test succeeded.\n");
4080 /* Test 3 - ... */
4081 cli_setatr(cli1, fname, 0, 0);
4082 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4084 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
4085 FILE_ATTRIBUTE_NORMAL,
4086 FILE_SHARE_READ|FILE_SHARE_WRITE,
4087 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4088 if (!NT_STATUS_IS_OK(status)) {
4089 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
4090 goto fail;
4093 /* This should fail with a sharing violation - open for delete is only compatible
4094 with SHARE_DELETE. */
4096 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4097 FILE_ATTRIBUTE_NORMAL,
4098 FILE_SHARE_READ|FILE_SHARE_WRITE,
4099 FILE_OPEN, 0, 0, &fnum2, NULL);
4100 if (NT_STATUS_IS_OK(status)) {
4101 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
4102 goto fail;
4105 /* This should succeed. */
4106 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4107 FILE_ATTRIBUTE_NORMAL,
4108 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4109 FILE_OPEN, 0, 0, &fnum2, NULL);
4110 if (!NT_STATUS_IS_OK(status)) {
4111 printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
4112 goto fail;
4115 status = cli_nt_delete_on_close(cli1, fnum1, true);
4116 if (!NT_STATUS_IS_OK(status)) {
4117 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
4118 goto fail;
4121 status = cli_close(cli1, fnum1);
4122 if (!NT_STATUS_IS_OK(status)) {
4123 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
4124 goto fail;
4127 status = cli_close(cli1, fnum2);
4128 if (!NT_STATUS_IS_OK(status)) {
4129 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
4130 goto fail;
4133 /* This should fail - file should no longer be there. */
4135 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4136 if (NT_STATUS_IS_OK(status)) {
4137 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
4138 status = cli_close(cli1, fnum1);
4139 if (!NT_STATUS_IS_OK(status)) {
4140 printf("[3] close failed (%s)\n", nt_errstr(status));
4142 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4143 goto fail;
4146 printf("third delete on close test succeeded.\n");
4148 /* Test 4 ... */
4149 cli_setatr(cli1, fname, 0, 0);
4150 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4152 status = cli_ntcreate(cli1, fname, 0,
4153 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4154 FILE_ATTRIBUTE_NORMAL,
4155 FILE_SHARE_READ|FILE_SHARE_WRITE,
4156 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4157 if (!NT_STATUS_IS_OK(status)) {
4158 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4159 goto fail;
4162 /* This should succeed. */
4163 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4164 FILE_ATTRIBUTE_NORMAL,
4165 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4166 FILE_OPEN, 0, 0, &fnum2, NULL);
4167 if (!NT_STATUS_IS_OK(status)) {
4168 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4169 goto fail;
4172 status = cli_close(cli1, fnum2);
4173 if (!NT_STATUS_IS_OK(status)) {
4174 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4175 goto fail;
4178 status = cli_nt_delete_on_close(cli1, fnum1, true);
4179 if (!NT_STATUS_IS_OK(status)) {
4180 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4181 goto fail;
4184 /* This should fail - no more opens once delete on close set. */
4185 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4186 FILE_ATTRIBUTE_NORMAL,
4187 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4188 FILE_OPEN, 0, 0, &fnum2, NULL);
4189 if (NT_STATUS_IS_OK(status)) {
4190 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
4191 goto fail;
4194 status = cli_close(cli1, fnum1);
4195 if (!NT_STATUS_IS_OK(status)) {
4196 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4197 goto fail;
4200 printf("fourth delete on close test succeeded.\n");
4202 /* Test 5 ... */
4203 cli_setatr(cli1, fname, 0, 0);
4204 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4206 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4207 if (!NT_STATUS_IS_OK(status)) {
4208 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4209 goto fail;
4212 /* This should fail - only allowed on NT opens with DELETE access. */
4214 status = cli_nt_delete_on_close(cli1, fnum1, true);
4215 if (NT_STATUS_IS_OK(status)) {
4216 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4217 goto fail;
4220 status = cli_close(cli1, fnum1);
4221 if (!NT_STATUS_IS_OK(status)) {
4222 printf("[5] close failed (%s)\n", nt_errstr(status));
4223 goto fail;
4226 printf("fifth delete on close test succeeded.\n");
4228 /* Test 6 ... */
4229 cli_setatr(cli1, fname, 0, 0);
4230 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4232 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4233 FILE_ATTRIBUTE_NORMAL,
4234 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4235 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4236 if (!NT_STATUS_IS_OK(status)) {
4237 printf("[6] open of %s failed (%s)\n", fname,
4238 nt_errstr(status));
4239 goto fail;
4242 /* This should fail - only allowed on NT opens with DELETE access. */
4244 status = cli_nt_delete_on_close(cli1, fnum1, true);
4245 if (NT_STATUS_IS_OK(status)) {
4246 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4247 goto fail;
4250 status = cli_close(cli1, fnum1);
4251 if (!NT_STATUS_IS_OK(status)) {
4252 printf("[6] close failed (%s)\n", nt_errstr(status));
4253 goto fail;
4256 printf("sixth delete on close test succeeded.\n");
4258 /* Test 7 ... */
4259 cli_setatr(cli1, fname, 0, 0);
4260 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4262 status = cli_ntcreate(cli1, fname, 0,
4263 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4264 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4265 0, 0, &fnum1, NULL);
4266 if (!NT_STATUS_IS_OK(status)) {
4267 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4268 goto fail;
4271 status = cli_nt_delete_on_close(cli1, fnum1, true);
4272 if (!NT_STATUS_IS_OK(status)) {
4273 printf("[7] setting delete_on_close on file failed !\n");
4274 goto fail;
4277 status = cli_nt_delete_on_close(cli1, fnum1, false);
4278 if (!NT_STATUS_IS_OK(status)) {
4279 printf("[7] unsetting delete_on_close on file failed !\n");
4280 goto fail;
4283 status = cli_close(cli1, fnum1);
4284 if (!NT_STATUS_IS_OK(status)) {
4285 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
4286 goto fail;
4289 /* This next open should succeed - we reset the flag. */
4290 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4291 if (!NT_STATUS_IS_OK(status)) {
4292 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4293 goto fail;
4296 status = cli_close(cli1, fnum1);
4297 if (!NT_STATUS_IS_OK(status)) {
4298 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4299 goto fail;
4302 printf("seventh delete on close test succeeded.\n");
4304 /* Test 8 ... */
4305 cli_setatr(cli1, fname, 0, 0);
4306 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4308 if (!torture_open_connection(&cli2, 1)) {
4309 printf("[8] failed to open second connection.\n");
4310 goto fail;
4313 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4315 status = cli_ntcreate(cli1, fname, 0,
4316 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4317 FILE_ATTRIBUTE_NORMAL,
4318 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4319 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4320 if (!NT_STATUS_IS_OK(status)) {
4321 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4322 goto fail;
4325 status = cli_ntcreate(cli2, fname, 0,
4326 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4327 FILE_ATTRIBUTE_NORMAL,
4328 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4329 FILE_OPEN, 0, 0, &fnum2, NULL);
4330 if (!NT_STATUS_IS_OK(status)) {
4331 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4332 goto fail;
4335 status = cli_nt_delete_on_close(cli1, fnum1, true);
4336 if (!NT_STATUS_IS_OK(status)) {
4337 printf("[8] setting delete_on_close on file failed !\n");
4338 goto fail;
4341 status = cli_close(cli1, fnum1);
4342 if (!NT_STATUS_IS_OK(status)) {
4343 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4344 goto fail;
4347 status = cli_close(cli2, fnum2);
4348 if (!NT_STATUS_IS_OK(status)) {
4349 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4350 goto fail;
4353 /* This should fail.. */
4354 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4355 if (NT_STATUS_IS_OK(status)) {
4356 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4357 goto fail;
4360 printf("eighth delete on close test succeeded.\n");
4362 /* Test 9 ... */
4364 /* This should fail - we need to set DELETE_ACCESS. */
4365 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4366 FILE_ATTRIBUTE_NORMAL,
4367 FILE_SHARE_NONE,
4368 FILE_OVERWRITE_IF,
4369 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4370 if (NT_STATUS_IS_OK(status)) {
4371 printf("[9] open of %s succeeded should have failed!\n", fname);
4372 goto fail;
4375 printf("ninth delete on close test succeeded.\n");
4377 /* Test 10 ... */
4379 status = cli_ntcreate(cli1, fname, 0,
4380 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4381 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4382 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4383 0, &fnum1, NULL);
4384 if (!NT_STATUS_IS_OK(status)) {
4385 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4386 goto fail;
4389 /* This should delete the file. */
4390 status = cli_close(cli1, fnum1);
4391 if (!NT_STATUS_IS_OK(status)) {
4392 printf("[10] close failed (%s)\n", nt_errstr(status));
4393 goto fail;
4396 /* This should fail.. */
4397 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4398 if (NT_STATUS_IS_OK(status)) {
4399 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4400 goto fail;
4403 printf("tenth delete on close test succeeded.\n");
4405 /* Test 11 ... */
4407 cli_setatr(cli1, fname, 0, 0);
4408 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4410 /* Can we open a read-only file with delete access? */
4412 /* Create a readonly file. */
4413 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4414 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4415 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4416 if (!NT_STATUS_IS_OK(status)) {
4417 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4418 goto fail;
4421 status = cli_close(cli1, fnum1);
4422 if (!NT_STATUS_IS_OK(status)) {
4423 printf("[11] close failed (%s)\n", nt_errstr(status));
4424 goto fail;
4427 /* Now try open for delete access. */
4428 status = cli_ntcreate(cli1, fname, 0,
4429 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4431 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4432 FILE_OPEN, 0, 0, &fnum1, NULL);
4433 if (!NT_STATUS_IS_OK(status)) {
4434 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
4435 goto fail;
4438 cli_close(cli1, fnum1);
4440 printf("eleventh delete on close test succeeded.\n");
4443 * Test 12
4444 * like test 4 but with initial delete on close
4447 cli_setatr(cli1, fname, 0, 0);
4448 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4450 status = cli_ntcreate(cli1, fname, 0,
4451 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4452 FILE_ATTRIBUTE_NORMAL,
4453 FILE_SHARE_READ|FILE_SHARE_WRITE,
4454 FILE_OVERWRITE_IF,
4455 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4456 if (!NT_STATUS_IS_OK(status)) {
4457 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4458 goto fail;
4461 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4462 FILE_ATTRIBUTE_NORMAL,
4463 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4464 FILE_OPEN, 0, 0, &fnum2, NULL);
4465 if (!NT_STATUS_IS_OK(status)) {
4466 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
4467 goto fail;
4470 status = cli_close(cli1, fnum2);
4471 if (!NT_STATUS_IS_OK(status)) {
4472 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
4473 goto fail;
4476 status = cli_nt_delete_on_close(cli1, fnum1, true);
4477 if (!NT_STATUS_IS_OK(status)) {
4478 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
4479 goto fail;
4482 /* This should fail - no more opens once delete on close set. */
4483 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4484 FILE_ATTRIBUTE_NORMAL,
4485 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4486 FILE_OPEN, 0, 0, &fnum2, NULL);
4487 if (NT_STATUS_IS_OK(status)) {
4488 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
4489 goto fail;
4492 status = cli_nt_delete_on_close(cli1, fnum1, false);
4493 if (!NT_STATUS_IS_OK(status)) {
4494 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
4495 goto fail;
4498 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4499 FILE_ATTRIBUTE_NORMAL,
4500 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4501 FILE_OPEN, 0, 0, &fnum2, NULL);
4502 if (!NT_STATUS_IS_OK(status)) {
4503 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
4504 goto fail;
4507 status = cli_close(cli1, fnum2);
4508 if (!NT_STATUS_IS_OK(status)) {
4509 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
4510 goto fail;
4513 status = cli_close(cli1, fnum1);
4514 if (!NT_STATUS_IS_OK(status)) {
4515 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
4516 goto fail;
4520 * setting delete on close on the handle does
4521 * not unset the initial delete on close...
4523 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4524 FILE_ATTRIBUTE_NORMAL,
4525 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4526 FILE_OPEN, 0, 0, &fnum2, NULL);
4527 if (NT_STATUS_IS_OK(status)) {
4528 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
4529 goto fail;
4530 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4531 printf("ntcreate returned %s, expected "
4532 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
4533 nt_errstr(status));
4534 goto fail;
4537 printf("twelfth delete on close test succeeded.\n");
4540 printf("finished delete test\n");
4542 correct = true;
4544 fail:
4545 /* FIXME: This will crash if we aborted before cli2 got
4546 * intialized, because these functions don't handle
4547 * uninitialized connections. */
4549 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4550 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4551 cli_setatr(cli1, fname, 0, 0);
4552 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4554 if (cli1 && !torture_close_connection(cli1)) {
4555 correct = False;
4557 if (cli2 && !torture_close_connection(cli2)) {
4558 correct = False;
4560 return correct;
4565 Test wildcard delete.
4567 static bool run_wild_deletetest(int dummy)
4569 struct cli_state *cli = NULL;
4570 const char *dname = "\\WTEST";
4571 const char *fname = "\\WTEST\\A";
4572 const char *wunlink_name = "\\WTEST\\*";
4573 uint16_t fnum1 = (uint16_t)-1;
4574 bool correct = false;
4575 NTSTATUS status;
4577 printf("starting wildcard delete test\n");
4579 if (!torture_open_connection(&cli, 0)) {
4580 return false;
4583 smbXcli_conn_set_sockopt(cli->conn, sockops);
4585 cli_unlink(cli, fname, 0);
4586 cli_rmdir(cli, dname);
4587 status = cli_mkdir(cli, dname);
4588 if (!NT_STATUS_IS_OK(status)) {
4589 printf("mkdir of %s failed %s!\n", dname, nt_errstr(status));
4590 goto fail;
4592 status = cli_openx(cli, fname, O_CREAT|O_RDONLY, DENY_NONE, &fnum1);
4593 if (!NT_STATUS_IS_OK(status)) {
4594 printf("open of %s failed %s!\n", fname, nt_errstr(status));
4595 goto fail;
4597 status = cli_close(cli, fnum1);
4598 fnum1 = -1;
4601 * Note the unlink attribute-type of zero. This should
4602 * map into FILE_ATTRIBUTE_NORMAL at the server even
4603 * on a wildcard delete.
4606 status = cli_unlink(cli, wunlink_name, 0);
4607 if (!NT_STATUS_IS_OK(status)) {
4608 printf("unlink of %s failed %s!\n",
4609 wunlink_name, nt_errstr(status));
4610 goto fail;
4613 printf("finished wildcard delete test\n");
4615 correct = true;
4617 fail:
4619 if (fnum1 != (uint16_t)-1) cli_close(cli, fnum1);
4620 cli_unlink(cli, fname, 0);
4621 cli_rmdir(cli, dname);
4623 if (cli && !torture_close_connection(cli)) {
4624 correct = false;
4626 return correct;
4629 static bool run_deletetest_ln(int dummy)
4631 struct cli_state *cli;
4632 const char *fname = "\\delete1";
4633 const char *fname_ln = "\\delete1_ln";
4634 uint16_t fnum;
4635 uint16_t fnum1;
4636 NTSTATUS status;
4637 bool correct = true;
4638 time_t t;
4640 printf("starting deletetest-ln\n");
4642 if (!torture_open_connection(&cli, 0)) {
4643 return false;
4646 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4647 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4649 smbXcli_conn_set_sockopt(cli->conn, sockops);
4651 /* Create the file. */
4652 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4653 if (!NT_STATUS_IS_OK(status)) {
4654 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4655 return false;
4658 status = cli_close(cli, fnum);
4659 if (!NT_STATUS_IS_OK(status)) {
4660 printf("close1 failed (%s)\n", nt_errstr(status));
4661 return false;
4664 /* Now create a hardlink. */
4665 status = cli_nt_hardlink(cli, fname, fname_ln);
4666 if (!NT_STATUS_IS_OK(status)) {
4667 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4668 return false;
4671 /* Open the original file. */
4672 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4673 FILE_ATTRIBUTE_NORMAL,
4674 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4675 FILE_OPEN_IF, 0, 0, &fnum, NULL);
4676 if (!NT_STATUS_IS_OK(status)) {
4677 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4678 return false;
4681 /* Unlink the hard link path. */
4682 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4683 FILE_ATTRIBUTE_NORMAL,
4684 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4685 FILE_OPEN_IF, 0, 0, &fnum1, NULL);
4686 if (!NT_STATUS_IS_OK(status)) {
4687 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4688 return false;
4690 status = cli_nt_delete_on_close(cli, fnum1, true);
4691 if (!NT_STATUS_IS_OK(status)) {
4692 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4693 __location__, fname_ln, nt_errstr(status));
4694 return false;
4697 status = cli_close(cli, fnum1);
4698 if (!NT_STATUS_IS_OK(status)) {
4699 printf("close %s failed (%s)\n",
4700 fname_ln, nt_errstr(status));
4701 return false;
4704 status = cli_close(cli, fnum);
4705 if (!NT_STATUS_IS_OK(status)) {
4706 printf("close %s failed (%s)\n",
4707 fname, nt_errstr(status));
4708 return false;
4711 /* Ensure the original file is still there. */
4712 status = cli_getatr(cli, fname, NULL, NULL, &t);
4713 if (!NT_STATUS_IS_OK(status)) {
4714 printf("%s getatr on file %s failed (%s)\n",
4715 __location__,
4716 fname,
4717 nt_errstr(status));
4718 correct = False;
4721 /* Ensure the link path is gone. */
4722 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4723 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4724 printf("%s, getatr for file %s returned wrong error code %s "
4725 "- should have been deleted\n",
4726 __location__,
4727 fname_ln, nt_errstr(status));
4728 correct = False;
4731 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4732 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4734 if (!torture_close_connection(cli)) {
4735 correct = false;
4738 printf("finished deletetest-ln\n");
4740 return correct;
4744 print out server properties
4746 static bool run_properties(int dummy)
4748 struct cli_state *cli;
4749 bool correct = True;
4751 printf("starting properties test\n");
4753 ZERO_STRUCT(cli);
4755 if (!torture_open_connection(&cli, 0)) {
4756 return False;
4759 smbXcli_conn_set_sockopt(cli->conn, sockops);
4761 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
4763 if (!torture_close_connection(cli)) {
4764 correct = False;
4767 return correct;
4772 /* FIRST_DESIRED_ACCESS 0xf019f */
4773 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4774 FILE_READ_EA| /* 0xf */ \
4775 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
4776 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
4777 DELETE_ACCESS|READ_CONTROL_ACCESS|\
4778 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
4779 /* SECOND_DESIRED_ACCESS 0xe0080 */
4780 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4781 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4782 WRITE_OWNER_ACCESS /* 0xe0000 */
4784 #if 0
4785 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4786 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4787 FILE_READ_DATA|\
4788 WRITE_OWNER_ACCESS /* */
4789 #endif
4792 Test ntcreate calls made by xcopy
4794 static bool run_xcopy(int dummy)
4796 static struct cli_state *cli1;
4797 const char *fname = "\\test.txt";
4798 bool correct = True;
4799 uint16_t fnum1, fnum2;
4800 NTSTATUS status;
4802 printf("starting xcopy test\n");
4804 if (!torture_open_connection(&cli1, 0)) {
4805 return False;
4808 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4809 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4810 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
4811 if (!NT_STATUS_IS_OK(status)) {
4812 printf("First open failed - %s\n", nt_errstr(status));
4813 return False;
4816 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4817 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4818 FILE_OPEN, 0x200000, 0, &fnum2, NULL);
4819 if (!NT_STATUS_IS_OK(status)) {
4820 printf("second open failed - %s\n", nt_errstr(status));
4821 return False;
4824 if (!torture_close_connection(cli1)) {
4825 correct = False;
4828 return correct;
4832 Test rename on files open with share delete and no share delete.
4834 static bool run_rename(int dummy)
4836 static struct cli_state *cli1;
4837 const char *fname = "\\test.txt";
4838 const char *fname1 = "\\test1.txt";
4839 bool correct = True;
4840 uint16_t fnum1;
4841 uint16_t attr;
4842 NTSTATUS status;
4844 printf("starting rename test\n");
4846 if (!torture_open_connection(&cli1, 0)) {
4847 return False;
4850 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4851 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4853 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4854 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4855 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4856 if (!NT_STATUS_IS_OK(status)) {
4857 printf("First open failed - %s\n", nt_errstr(status));
4858 return False;
4861 status = cli_rename(cli1, fname, fname1, false);
4862 if (!NT_STATUS_IS_OK(status)) {
4863 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4864 } else {
4865 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4866 correct = False;
4869 status = cli_close(cli1, fnum1);
4870 if (!NT_STATUS_IS_OK(status)) {
4871 printf("close - 1 failed (%s)\n", nt_errstr(status));
4872 return False;
4875 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4876 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4877 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4878 #if 0
4879 FILE_SHARE_DELETE|FILE_SHARE_NONE,
4880 #else
4881 FILE_SHARE_DELETE|FILE_SHARE_READ,
4882 #endif
4883 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4884 if (!NT_STATUS_IS_OK(status)) {
4885 printf("Second open failed - %s\n", nt_errstr(status));
4886 return False;
4889 status = cli_rename(cli1, fname, fname1, false);
4890 if (!NT_STATUS_IS_OK(status)) {
4891 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4892 correct = False;
4893 } else {
4894 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4897 status = cli_close(cli1, fnum1);
4898 if (!NT_STATUS_IS_OK(status)) {
4899 printf("close - 2 failed (%s)\n", nt_errstr(status));
4900 return False;
4903 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4904 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4906 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4907 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4908 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4909 if (!NT_STATUS_IS_OK(status)) {
4910 printf("Third open failed - %s\n", nt_errstr(status));
4911 return False;
4915 #if 0
4917 uint16_t fnum2;
4919 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4920 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
4921 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4922 return False;
4924 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4925 printf("[8] setting delete_on_close on file failed !\n");
4926 return False;
4929 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4930 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4931 return False;
4934 #endif
4936 status = cli_rename(cli1, fname, fname1, false);
4937 if (!NT_STATUS_IS_OK(status)) {
4938 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4939 correct = False;
4940 } else {
4941 printf("Third rename succeeded (SHARE_NONE)\n");
4944 status = cli_close(cli1, fnum1);
4945 if (!NT_STATUS_IS_OK(status)) {
4946 printf("close - 3 failed (%s)\n", nt_errstr(status));
4947 return False;
4950 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4951 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4953 /*----*/
4955 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4956 FILE_ATTRIBUTE_NORMAL,
4957 FILE_SHARE_READ | FILE_SHARE_WRITE,
4958 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4959 if (!NT_STATUS_IS_OK(status)) {
4960 printf("Fourth open failed - %s\n", nt_errstr(status));
4961 return False;
4964 status = cli_rename(cli1, fname, fname1, false);
4965 if (!NT_STATUS_IS_OK(status)) {
4966 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4967 } else {
4968 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4969 correct = False;
4972 status = cli_close(cli1, fnum1);
4973 if (!NT_STATUS_IS_OK(status)) {
4974 printf("close - 4 failed (%s)\n", nt_errstr(status));
4975 return False;
4978 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4979 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4981 /*--*/
4983 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4984 FILE_ATTRIBUTE_NORMAL,
4985 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4986 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4987 if (!NT_STATUS_IS_OK(status)) {
4988 printf("Fifth open failed - %s\n", nt_errstr(status));
4989 return False;
4992 status = cli_rename(cli1, fname, fname1, false);
4993 if (!NT_STATUS_IS_OK(status)) {
4994 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4995 correct = False;
4996 } else {
4997 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
5001 * Now check if the first name still exists ...
5004 /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
5005 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
5006 FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
5007 printf("Opening original file after rename of open file fails: %s\n",
5008 cli_errstr(cli1));
5010 else {
5011 printf("Opening original file after rename of open file works ...\n");
5012 (void)cli_close(cli1, fnum2);
5013 } */
5015 /*--*/
5016 status = cli_close(cli1, fnum1);
5017 if (!NT_STATUS_IS_OK(status)) {
5018 printf("close - 5 failed (%s)\n", nt_errstr(status));
5019 return False;
5022 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
5023 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
5024 if (!NT_STATUS_IS_OK(status)) {
5025 printf("getatr on file %s failed - %s ! \n",
5026 fname1, nt_errstr(status));
5027 correct = False;
5028 } else {
5029 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
5030 printf("Renamed file %s has wrong attr 0x%x "
5031 "(should be 0x%x)\n",
5032 fname1,
5033 attr,
5034 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
5035 correct = False;
5036 } else {
5037 printf("Renamed file %s has archive bit set\n", fname1);
5041 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5042 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5044 if (!torture_close_connection(cli1)) {
5045 correct = False;
5048 return correct;
5052 Test rename into a directory with an ACL denying it.
5054 static bool run_rename_access(int dummy)
5056 static struct cli_state *cli = NULL;
5057 static struct cli_state *posix_cli = NULL;
5058 const char *src = "test.txt";
5059 const char *dname = "dir";
5060 const char *dst = "dir\\test.txt";
5061 const char *dsrc = "test.dir";
5062 const char *ddst = "dir\\test.dir";
5063 uint16_t fnum = (uint16_t)-1;
5064 struct security_descriptor *sd = NULL;
5065 struct security_descriptor *newsd = NULL;
5066 NTSTATUS status;
5067 TALLOC_CTX *frame = NULL;
5069 frame = talloc_stackframe();
5070 printf("starting rename access test\n");
5072 /* Windows connection. */
5073 if (!torture_open_connection(&cli, 0)) {
5074 goto fail;
5077 smbXcli_conn_set_sockopt(cli->conn, sockops);
5079 /* Posix connection. */
5080 if (!torture_open_connection(&posix_cli, 0)) {
5081 goto fail;
5084 smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
5086 status = torture_setup_unix_extensions(posix_cli);
5087 if (!NT_STATUS_IS_OK(status)) {
5088 goto fail;
5091 /* Start with a clean slate. */
5092 cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5093 cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5094 cli_rmdir(cli, dsrc);
5095 cli_rmdir(cli, ddst);
5096 cli_rmdir(cli, dname);
5099 * Setup the destination directory with a DENY ACE to
5100 * prevent new files within it.
5102 status = cli_ntcreate(cli,
5103 dname,
5105 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
5106 WRITE_DAC_ACCESS|FILE_READ_DATA|
5107 WRITE_OWNER_ACCESS,
5108 FILE_ATTRIBUTE_DIRECTORY,
5109 FILE_SHARE_READ|FILE_SHARE_WRITE,
5110 FILE_CREATE,
5111 FILE_DIRECTORY_FILE,
5113 &fnum,
5114 NULL);
5115 if (!NT_STATUS_IS_OK(status)) {
5116 printf("Create of %s - %s\n", dname, nt_errstr(status));
5117 goto fail;
5120 status = cli_query_secdesc(cli,
5121 fnum,
5122 frame,
5123 &sd);
5124 if (!NT_STATUS_IS_OK(status)) {
5125 printf("cli_query_secdesc failed for %s (%s)\n",
5126 dname, nt_errstr(status));
5127 goto fail;
5130 newsd = security_descriptor_dacl_create(frame,
5132 NULL,
5133 NULL,
5134 SID_WORLD,
5135 SEC_ACE_TYPE_ACCESS_DENIED,
5136 SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
5138 NULL);
5139 if (newsd == NULL) {
5140 goto fail;
5142 sd->dacl = security_acl_concatenate(frame,
5143 newsd->dacl,
5144 sd->dacl);
5145 if (sd->dacl == NULL) {
5146 goto fail;
5148 status = cli_set_secdesc(cli, fnum, sd);
5149 if (!NT_STATUS_IS_OK(status)) {
5150 printf("cli_set_secdesc failed for %s (%s)\n",
5151 dname, nt_errstr(status));
5152 goto fail;
5154 status = cli_close(cli, fnum);
5155 if (!NT_STATUS_IS_OK(status)) {
5156 printf("close failed for %s (%s)\n",
5157 dname, nt_errstr(status));
5158 goto fail;
5160 /* Now go around the back and chmod to 777 via POSIX. */
5161 status = cli_posix_chmod(posix_cli, dname, 0777);
5162 if (!NT_STATUS_IS_OK(status)) {
5163 printf("cli_posix_chmod failed for %s (%s)\n",
5164 dname, nt_errstr(status));
5165 goto fail;
5168 /* Check we can't create a file within dname via Windows. */
5169 status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5170 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5171 cli_close(posix_cli, fnum);
5172 printf("Create of %s should be ACCESS denied, was %s\n",
5173 dst, nt_errstr(status));
5174 goto fail;
5177 /* Make the sample file/directory. */
5178 status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5179 if (!NT_STATUS_IS_OK(status)) {
5180 printf("open of %s failed (%s)\n", src, nt_errstr(status));
5181 goto fail;
5183 status = cli_close(cli, fnum);
5184 if (!NT_STATUS_IS_OK(status)) {
5185 printf("cli_close failed (%s)\n", nt_errstr(status));
5186 goto fail;
5189 status = cli_mkdir(cli, dsrc);
5190 if (!NT_STATUS_IS_OK(status)) {
5191 printf("cli_mkdir of %s failed (%s)\n",
5192 dsrc, nt_errstr(status));
5193 goto fail;
5197 * OK - renames of the new file and directory into the
5198 * dst directory should fail.
5201 status = cli_rename(cli, src, dst, false);
5202 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5203 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
5204 src, dst, nt_errstr(status));
5205 goto fail;
5207 status = cli_rename(cli, dsrc, ddst, false);
5208 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5209 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
5210 src, dst, nt_errstr(status));
5211 goto fail;
5214 TALLOC_FREE(frame);
5215 return true;
5217 fail:
5219 if (posix_cli) {
5220 torture_close_connection(posix_cli);
5223 if (cli) {
5224 if (fnum != (uint16_t)-1) {
5225 cli_close(cli, fnum);
5227 cli_unlink(cli, src,
5228 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5229 cli_unlink(cli, dst,
5230 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5231 cli_rmdir(cli, dsrc);
5232 cli_rmdir(cli, ddst);
5233 cli_rmdir(cli, dname);
5235 torture_close_connection(cli);
5238 TALLOC_FREE(frame);
5239 return false;
5243 Test owner rights ACE.
5245 static bool run_owner_rights(int dummy)
5247 static struct cli_state *cli = NULL;
5248 const char *fname = "owner_rights.txt";
5249 uint16_t fnum = (uint16_t)-1;
5250 struct security_descriptor *sd = NULL;
5251 struct security_descriptor *newsd = NULL;
5252 NTSTATUS status;
5253 TALLOC_CTX *frame = NULL;
5255 frame = talloc_stackframe();
5256 printf("starting owner rights test\n");
5258 /* Windows connection. */
5259 if (!torture_open_connection(&cli, 0)) {
5260 goto fail;
5263 smbXcli_conn_set_sockopt(cli->conn, sockops);
5265 /* Start with a clean slate. */
5266 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5268 /* Create the test file. */
5269 /* Now try and open for read and write-dac. */
5270 status = cli_ntcreate(cli,
5271 fname,
5273 GENERIC_ALL_ACCESS,
5274 FILE_ATTRIBUTE_NORMAL,
5275 FILE_SHARE_READ|FILE_SHARE_WRITE|
5276 FILE_SHARE_DELETE,
5277 FILE_CREATE,
5280 &fnum,
5281 NULL);
5282 if (!NT_STATUS_IS_OK(status)) {
5283 printf("Create of %s - %s\n", fname, nt_errstr(status));
5284 goto fail;
5287 /* Get the original SD. */
5288 status = cli_query_secdesc(cli,
5289 fnum,
5290 frame,
5291 &sd);
5292 if (!NT_STATUS_IS_OK(status)) {
5293 printf("cli_query_secdesc failed for %s (%s)\n",
5294 fname, nt_errstr(status));
5295 goto fail;
5299 * Add an "owner-rights" ACE denying WRITE_DATA,
5300 * and an "owner-rights" ACE allowing READ_DATA.
5303 newsd = security_descriptor_dacl_create(frame,
5305 NULL,
5306 NULL,
5307 SID_OWNER_RIGHTS,
5308 SEC_ACE_TYPE_ACCESS_DENIED,
5309 FILE_WRITE_DATA,
5311 SID_OWNER_RIGHTS,
5312 SEC_ACE_TYPE_ACCESS_ALLOWED,
5313 FILE_READ_DATA,
5315 NULL);
5316 if (newsd == NULL) {
5317 goto fail;
5319 sd->dacl = security_acl_concatenate(frame,
5320 newsd->dacl,
5321 sd->dacl);
5322 if (sd->dacl == NULL) {
5323 goto fail;
5325 status = cli_set_secdesc(cli, fnum, sd);
5326 if (!NT_STATUS_IS_OK(status)) {
5327 printf("cli_set_secdesc failed for %s (%s)\n",
5328 fname, nt_errstr(status));
5329 goto fail;
5331 status = cli_close(cli, fnum);
5332 if (!NT_STATUS_IS_OK(status)) {
5333 printf("close failed for %s (%s)\n",
5334 fname, nt_errstr(status));
5335 goto fail;
5337 fnum = (uint16_t)-1;
5339 /* Try and open for FILE_WRITE_DATA */
5340 status = cli_ntcreate(cli,
5341 fname,
5343 FILE_WRITE_DATA,
5344 FILE_ATTRIBUTE_NORMAL,
5345 FILE_SHARE_READ|FILE_SHARE_WRITE|
5346 FILE_SHARE_DELETE,
5347 FILE_OPEN,
5350 &fnum,
5351 NULL);
5352 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5353 printf("Open of %s - %s\n", fname, nt_errstr(status));
5354 goto fail;
5357 /* Now try and open for FILE_READ_DATA */
5358 status = cli_ntcreate(cli,
5359 fname,
5361 FILE_READ_DATA,
5362 FILE_ATTRIBUTE_NORMAL,
5363 FILE_SHARE_READ|FILE_SHARE_WRITE|
5364 FILE_SHARE_DELETE,
5365 FILE_OPEN,
5368 &fnum,
5369 NULL);
5370 if (!NT_STATUS_IS_OK(status)) {
5371 printf("Open of %s - %s\n", fname, nt_errstr(status));
5372 goto fail;
5375 status = cli_close(cli, fnum);
5376 if (!NT_STATUS_IS_OK(status)) {
5377 printf("close failed for %s (%s)\n",
5378 fname, nt_errstr(status));
5379 goto fail;
5382 /* Restore clean slate. */
5383 TALLOC_FREE(sd);
5384 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5386 /* Create the test file. */
5387 status = cli_ntcreate(cli,
5388 fname,
5390 GENERIC_ALL_ACCESS,
5391 FILE_ATTRIBUTE_NORMAL,
5392 FILE_SHARE_READ|FILE_SHARE_WRITE|
5393 FILE_SHARE_DELETE,
5394 FILE_CREATE,
5397 &fnum,
5398 NULL);
5399 if (!NT_STATUS_IS_OK(status)) {
5400 printf("Create of %s - %s\n", fname, nt_errstr(status));
5401 goto fail;
5404 /* Get the original SD. */
5405 status = cli_query_secdesc(cli,
5406 fnum,
5407 frame,
5408 &sd);
5409 if (!NT_STATUS_IS_OK(status)) {
5410 printf("cli_query_secdesc failed for %s (%s)\n",
5411 fname, nt_errstr(status));
5412 goto fail;
5416 * Add an "owner-rights ACE denying WRITE_DATA,
5417 * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
5420 newsd = security_descriptor_dacl_create(frame,
5422 NULL,
5423 NULL,
5424 SID_OWNER_RIGHTS,
5425 SEC_ACE_TYPE_ACCESS_DENIED,
5426 FILE_WRITE_DATA,
5428 SID_OWNER_RIGHTS,
5429 SEC_ACE_TYPE_ACCESS_ALLOWED,
5430 FILE_READ_DATA|FILE_WRITE_DATA,
5432 NULL);
5433 if (newsd == NULL) {
5434 goto fail;
5436 sd->dacl = security_acl_concatenate(frame,
5437 newsd->dacl,
5438 sd->dacl);
5439 if (sd->dacl == NULL) {
5440 goto fail;
5442 status = cli_set_secdesc(cli, fnum, sd);
5443 if (!NT_STATUS_IS_OK(status)) {
5444 printf("cli_set_secdesc failed for %s (%s)\n",
5445 fname, nt_errstr(status));
5446 goto fail;
5448 status = cli_close(cli, fnum);
5449 if (!NT_STATUS_IS_OK(status)) {
5450 printf("close failed for %s (%s)\n",
5451 fname, nt_errstr(status));
5452 goto fail;
5454 fnum = (uint16_t)-1;
5456 /* Try and open for FILE_WRITE_DATA */
5457 status = cli_ntcreate(cli,
5458 fname,
5460 FILE_WRITE_DATA,
5461 FILE_ATTRIBUTE_NORMAL,
5462 FILE_SHARE_READ|FILE_SHARE_WRITE|
5463 FILE_SHARE_DELETE,
5464 FILE_OPEN,
5467 &fnum,
5468 NULL);
5469 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5470 printf("Open of %s - %s\n", fname, nt_errstr(status));
5471 goto fail;
5474 /* Now try and open for FILE_READ_DATA */
5475 status = cli_ntcreate(cli,
5476 fname,
5478 FILE_READ_DATA,
5479 FILE_ATTRIBUTE_NORMAL,
5480 FILE_SHARE_READ|FILE_SHARE_WRITE|
5481 FILE_SHARE_DELETE,
5482 FILE_OPEN,
5485 &fnum,
5486 NULL);
5487 if (!NT_STATUS_IS_OK(status)) {
5488 printf("Open of %s - %s\n", fname, nt_errstr(status));
5489 goto fail;
5492 status = cli_close(cli, fnum);
5493 if (!NT_STATUS_IS_OK(status)) {
5494 printf("close failed for %s (%s)\n",
5495 fname, nt_errstr(status));
5496 goto fail;
5499 /* Restore clean slate. */
5500 TALLOC_FREE(sd);
5501 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5504 /* Create the test file. */
5505 status = cli_ntcreate(cli,
5506 fname,
5508 GENERIC_ALL_ACCESS,
5509 FILE_ATTRIBUTE_NORMAL,
5510 FILE_SHARE_READ|FILE_SHARE_WRITE|
5511 FILE_SHARE_DELETE,
5512 FILE_CREATE,
5515 &fnum,
5516 NULL);
5517 if (!NT_STATUS_IS_OK(status)) {
5518 printf("Create of %s - %s\n", fname, nt_errstr(status));
5519 goto fail;
5522 /* Get the original SD. */
5523 status = cli_query_secdesc(cli,
5524 fnum,
5525 frame,
5526 &sd);
5527 if (!NT_STATUS_IS_OK(status)) {
5528 printf("cli_query_secdesc failed for %s (%s)\n",
5529 fname, nt_errstr(status));
5530 goto fail;
5534 * Add an "authenticated users" ACE allowing READ_DATA,
5535 * add an "owner-rights" denying READ_DATA,
5536 * and an "authenticated users" ACE allowing WRITE_DATA.
5539 newsd = security_descriptor_dacl_create(frame,
5541 NULL,
5542 NULL,
5543 SID_NT_AUTHENTICATED_USERS,
5544 SEC_ACE_TYPE_ACCESS_ALLOWED,
5545 FILE_READ_DATA,
5547 SID_OWNER_RIGHTS,
5548 SEC_ACE_TYPE_ACCESS_DENIED,
5549 FILE_READ_DATA,
5551 SID_NT_AUTHENTICATED_USERS,
5552 SEC_ACE_TYPE_ACCESS_ALLOWED,
5553 FILE_WRITE_DATA,
5555 NULL);
5556 if (newsd == NULL) {
5557 printf("newsd == NULL\n");
5558 goto fail;
5560 sd->dacl = security_acl_concatenate(frame,
5561 newsd->dacl,
5562 sd->dacl);
5563 if (sd->dacl == NULL) {
5564 printf("sd->dacl == NULL\n");
5565 goto fail;
5567 status = cli_set_secdesc(cli, fnum, sd);
5568 if (!NT_STATUS_IS_OK(status)) {
5569 printf("cli_set_secdesc failed for %s (%s)\n",
5570 fname, nt_errstr(status));
5571 goto fail;
5573 status = cli_close(cli, fnum);
5574 if (!NT_STATUS_IS_OK(status)) {
5575 printf("close failed for %s (%s)\n",
5576 fname, nt_errstr(status));
5577 goto fail;
5579 fnum = (uint16_t)-1;
5581 /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
5582 status = cli_ntcreate(cli,
5583 fname,
5585 FILE_READ_DATA|FILE_WRITE_DATA,
5586 FILE_ATTRIBUTE_NORMAL,
5587 FILE_SHARE_READ|FILE_SHARE_WRITE|
5588 FILE_SHARE_DELETE,
5589 FILE_OPEN,
5592 &fnum,
5593 NULL);
5594 if (!NT_STATUS_IS_OK(status)) {
5595 printf("Open of %s - %s\n", fname, nt_errstr(status));
5596 goto fail;
5599 status = cli_close(cli, fnum);
5600 if (!NT_STATUS_IS_OK(status)) {
5601 printf("close failed for %s (%s)\n",
5602 fname, nt_errstr(status));
5603 goto fail;
5606 cli_unlink(cli, fname,
5607 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5609 TALLOC_FREE(frame);
5610 return true;
5612 fail:
5614 if (cli) {
5615 if (fnum != (uint16_t)-1) {
5616 cli_close(cli, fnum);
5618 cli_unlink(cli, fname,
5619 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5620 torture_close_connection(cli);
5623 TALLOC_FREE(frame);
5624 return false;
5627 static bool run_pipe_number(int dummy)
5629 struct cli_state *cli1;
5630 const char *pipe_name = "\\SPOOLSS";
5631 uint16_t fnum;
5632 int num_pipes = 0;
5633 NTSTATUS status;
5635 printf("starting pipenumber test\n");
5636 if (!torture_open_connection(&cli1, 0)) {
5637 return False;
5640 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5641 while(1) {
5642 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
5643 FILE_ATTRIBUTE_NORMAL,
5644 FILE_SHARE_READ|FILE_SHARE_WRITE,
5645 FILE_OPEN_IF, 0, 0, &fnum, NULL);
5646 if (!NT_STATUS_IS_OK(status)) {
5647 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
5648 break;
5650 num_pipes++;
5651 printf("\r%6d", num_pipes);
5654 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
5655 torture_close_connection(cli1);
5656 return True;
5660 Test open mode returns on read-only files.
5662 static bool run_opentest(int dummy)
5664 static struct cli_state *cli1;
5665 static struct cli_state *cli2;
5666 const char *fname = "\\readonly.file";
5667 uint16_t fnum1, fnum2;
5668 char buf[20];
5669 off_t fsize;
5670 bool correct = True;
5671 char *tmp_path;
5672 NTSTATUS status;
5674 printf("starting open test\n");
5676 if (!torture_open_connection(&cli1, 0)) {
5677 return False;
5680 cli_setatr(cli1, fname, 0, 0);
5681 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5683 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5685 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
5686 if (!NT_STATUS_IS_OK(status)) {
5687 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5688 return False;
5691 status = cli_close(cli1, fnum1);
5692 if (!NT_STATUS_IS_OK(status)) {
5693 printf("close2 failed (%s)\n", nt_errstr(status));
5694 return False;
5697 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
5698 if (!NT_STATUS_IS_OK(status)) {
5699 printf("cli_setatr failed (%s)\n", nt_errstr(status));
5700 return False;
5703 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
5704 if (!NT_STATUS_IS_OK(status)) {
5705 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5706 return False;
5709 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
5710 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
5712 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
5713 NT_STATUS_ACCESS_DENIED)) {
5714 printf("correct error code ERRDOS/ERRnoaccess returned\n");
5717 printf("finished open test 1\n");
5719 cli_close(cli1, fnum1);
5721 /* Now try not readonly and ensure ERRbadshare is returned. */
5723 cli_setatr(cli1, fname, 0, 0);
5725 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
5726 if (!NT_STATUS_IS_OK(status)) {
5727 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5728 return False;
5731 /* This will fail - but the error should be ERRshare. */
5732 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
5734 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
5735 NT_STATUS_SHARING_VIOLATION)) {
5736 printf("correct error code ERRDOS/ERRbadshare returned\n");
5739 status = cli_close(cli1, fnum1);
5740 if (!NT_STATUS_IS_OK(status)) {
5741 printf("close2 failed (%s)\n", nt_errstr(status));
5742 return False;
5745 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5747 printf("finished open test 2\n");
5749 /* Test truncate open disposition on file opened for read. */
5750 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
5751 if (!NT_STATUS_IS_OK(status)) {
5752 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
5753 return False;
5756 /* write 20 bytes. */
5758 memset(buf, '\0', 20);
5760 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
5761 if (!NT_STATUS_IS_OK(status)) {
5762 printf("write failed (%s)\n", nt_errstr(status));
5763 correct = False;
5766 status = cli_close(cli1, fnum1);
5767 if (!NT_STATUS_IS_OK(status)) {
5768 printf("(3) close1 failed (%s)\n", nt_errstr(status));
5769 return False;
5772 /* Ensure size == 20. */
5773 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5774 if (!NT_STATUS_IS_OK(status)) {
5775 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5776 return False;
5779 if (fsize != 20) {
5780 printf("(3) file size != 20\n");
5781 return False;
5784 /* Now test if we can truncate a file opened for readonly. */
5785 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
5786 if (!NT_STATUS_IS_OK(status)) {
5787 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
5788 return False;
5791 status = cli_close(cli1, fnum1);
5792 if (!NT_STATUS_IS_OK(status)) {
5793 printf("close2 failed (%s)\n", nt_errstr(status));
5794 return False;
5797 /* Ensure size == 0. */
5798 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5799 if (!NT_STATUS_IS_OK(status)) {
5800 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5801 return False;
5804 if (fsize != 0) {
5805 printf("(3) file size != 0\n");
5806 return False;
5808 printf("finished open test 3\n");
5810 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5812 printf("Do ctemp tests\n");
5813 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
5814 if (!NT_STATUS_IS_OK(status)) {
5815 printf("ctemp failed (%s)\n", nt_errstr(status));
5816 return False;
5819 printf("ctemp gave path %s\n", tmp_path);
5820 status = cli_close(cli1, fnum1);
5821 if (!NT_STATUS_IS_OK(status)) {
5822 printf("close of temp failed (%s)\n", nt_errstr(status));
5825 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5826 if (!NT_STATUS_IS_OK(status)) {
5827 printf("unlink of temp failed (%s)\n", nt_errstr(status));
5830 /* Test the non-io opens... */
5832 if (!torture_open_connection(&cli2, 1)) {
5833 return False;
5836 cli_setatr(cli2, fname, 0, 0);
5837 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5839 smbXcli_conn_set_sockopt(cli2->conn, sockops);
5841 printf("TEST #1 testing 2 non-io opens (no delete)\n");
5842 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5843 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5844 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5845 if (!NT_STATUS_IS_OK(status)) {
5846 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5847 return False;
5850 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5851 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5852 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5853 if (!NT_STATUS_IS_OK(status)) {
5854 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5855 return False;
5858 status = cli_close(cli1, fnum1);
5859 if (!NT_STATUS_IS_OK(status)) {
5860 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5861 return False;
5864 status = cli_close(cli2, fnum2);
5865 if (!NT_STATUS_IS_OK(status)) {
5866 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5867 return False;
5870 printf("non-io open test #1 passed.\n");
5872 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5874 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5876 status = cli_ntcreate(cli1, fname, 0,
5877 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5878 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5879 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5880 if (!NT_STATUS_IS_OK(status)) {
5881 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5882 return False;
5885 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5886 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5887 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5888 if (!NT_STATUS_IS_OK(status)) {
5889 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5890 return False;
5893 status = cli_close(cli1, fnum1);
5894 if (!NT_STATUS_IS_OK(status)) {
5895 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5896 return False;
5899 status = cli_close(cli2, fnum2);
5900 if (!NT_STATUS_IS_OK(status)) {
5901 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5902 return False;
5905 printf("non-io open test #2 passed.\n");
5907 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5909 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5911 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5912 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5913 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5914 if (!NT_STATUS_IS_OK(status)) {
5915 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5916 return False;
5919 status = cli_ntcreate(cli2, fname, 0,
5920 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5921 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5922 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5923 if (!NT_STATUS_IS_OK(status)) {
5924 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5925 return False;
5928 status = cli_close(cli1, fnum1);
5929 if (!NT_STATUS_IS_OK(status)) {
5930 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5931 return False;
5934 status = cli_close(cli2, fnum2);
5935 if (!NT_STATUS_IS_OK(status)) {
5936 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5937 return False;
5940 printf("non-io open test #3 passed.\n");
5942 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5944 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5946 status = cli_ntcreate(cli1, fname, 0,
5947 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5948 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5949 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5950 if (!NT_STATUS_IS_OK(status)) {
5951 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5952 return False;
5955 status = cli_ntcreate(cli2, fname, 0,
5956 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5957 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5958 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5959 if (NT_STATUS_IS_OK(status)) {
5960 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5961 return False;
5964 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5966 status = cli_close(cli1, fnum1);
5967 if (!NT_STATUS_IS_OK(status)) {
5968 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5969 return False;
5972 printf("non-io open test #4 passed.\n");
5974 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5976 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5978 status = cli_ntcreate(cli1, fname, 0,
5979 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5980 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5981 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5982 if (!NT_STATUS_IS_OK(status)) {
5983 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5984 return False;
5987 status = cli_ntcreate(cli2, fname, 0,
5988 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5989 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5990 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5991 if (!NT_STATUS_IS_OK(status)) {
5992 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5993 return False;
5996 status = cli_close(cli1, fnum1);
5997 if (!NT_STATUS_IS_OK(status)) {
5998 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5999 return False;
6002 status = cli_close(cli2, fnum2);
6003 if (!NT_STATUS_IS_OK(status)) {
6004 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
6005 return False;
6008 printf("non-io open test #5 passed.\n");
6010 printf("TEST #6 testing 1 non-io open, one io open\n");
6012 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6014 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
6015 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6016 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6017 if (!NT_STATUS_IS_OK(status)) {
6018 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
6019 return False;
6022 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
6023 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6024 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
6025 if (!NT_STATUS_IS_OK(status)) {
6026 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
6027 return False;
6030 status = cli_close(cli1, fnum1);
6031 if (!NT_STATUS_IS_OK(status)) {
6032 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
6033 return False;
6036 status = cli_close(cli2, fnum2);
6037 if (!NT_STATUS_IS_OK(status)) {
6038 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
6039 return False;
6042 printf("non-io open test #6 passed.\n");
6044 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
6046 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6048 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
6049 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6050 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6051 if (!NT_STATUS_IS_OK(status)) {
6052 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
6053 return False;
6056 status = cli_ntcreate(cli2, fname, 0,
6057 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
6058 FILE_ATTRIBUTE_NORMAL,
6059 FILE_SHARE_READ|FILE_SHARE_DELETE,
6060 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
6061 if (NT_STATUS_IS_OK(status)) {
6062 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
6063 return False;
6066 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
6068 status = cli_close(cli1, fnum1);
6069 if (!NT_STATUS_IS_OK(status)) {
6070 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
6071 return False;
6074 printf("non-io open test #7 passed.\n");
6076 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6078 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
6079 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
6080 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6081 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6082 if (!NT_STATUS_IS_OK(status)) {
6083 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
6084 correct = false;
6085 goto out;
6088 /* Write to ensure we have to update the file time. */
6089 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
6090 NULL);
6091 if (!NT_STATUS_IS_OK(status)) {
6092 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
6093 correct = false;
6094 goto out;
6097 status = cli_close(cli1, fnum1);
6098 if (!NT_STATUS_IS_OK(status)) {
6099 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
6100 correct = false;
6103 out:
6105 if (!torture_close_connection(cli1)) {
6106 correct = False;
6108 if (!torture_close_connection(cli2)) {
6109 correct = False;
6112 return correct;
6115 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
6117 uint16_t major, minor;
6118 uint32_t caplow, caphigh;
6119 NTSTATUS status;
6121 if (!SERVER_HAS_UNIX_CIFS(cli)) {
6122 printf("Server doesn't support UNIX CIFS extensions.\n");
6123 return NT_STATUS_NOT_SUPPORTED;
6126 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
6127 &caphigh);
6128 if (!NT_STATUS_IS_OK(status)) {
6129 printf("Server didn't return UNIX CIFS extensions: %s\n",
6130 nt_errstr(status));
6131 return status;
6134 status = cli_set_unix_extensions_capabilities(cli, major, minor,
6135 caplow, caphigh);
6136 if (!NT_STATUS_IS_OK(status)) {
6137 printf("Server doesn't support setting UNIX CIFS extensions: "
6138 "%s.\n", nt_errstr(status));
6139 return status;
6142 return NT_STATUS_OK;
6146 Test POSIX open /mkdir calls.
6148 static bool run_simple_posix_open_test(int dummy)
6150 static struct cli_state *cli1;
6151 const char *fname = "posix:file";
6152 const char *hname = "posix:hlink";
6153 const char *sname = "posix:symlink";
6154 const char *dname = "posix:dir";
6155 char buf[10];
6156 char namebuf[11];
6157 uint16_t fnum1 = (uint16_t)-1;
6158 SMB_STRUCT_STAT sbuf;
6159 bool correct = false;
6160 NTSTATUS status;
6161 size_t nread;
6162 const char *fname_windows = "windows_file";
6163 uint16_t fnum2 = (uint16_t)-1;
6165 printf("Starting simple POSIX open test\n");
6167 if (!torture_open_connection(&cli1, 0)) {
6168 return false;
6171 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6173 status = torture_setup_unix_extensions(cli1);
6174 if (!NT_STATUS_IS_OK(status)) {
6175 return false;
6178 cli_setatr(cli1, fname, 0, 0);
6179 cli_posix_unlink(cli1, fname);
6180 cli_setatr(cli1, dname, 0, 0);
6181 cli_posix_rmdir(cli1, dname);
6182 cli_setatr(cli1, hname, 0, 0);
6183 cli_posix_unlink(cli1, hname);
6184 cli_setatr(cli1, sname, 0, 0);
6185 cli_posix_unlink(cli1, sname);
6186 cli_setatr(cli1, fname_windows, 0, 0);
6187 cli_posix_unlink(cli1, fname_windows);
6189 /* Create a directory. */
6190 status = cli_posix_mkdir(cli1, dname, 0777);
6191 if (!NT_STATUS_IS_OK(status)) {
6192 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
6193 goto out;
6196 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
6197 0600, &fnum1);
6198 if (!NT_STATUS_IS_OK(status)) {
6199 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6200 goto out;
6203 /* Test ftruncate - set file size. */
6204 status = cli_ftruncate(cli1, fnum1, 1000);
6205 if (!NT_STATUS_IS_OK(status)) {
6206 printf("ftruncate failed (%s)\n", nt_errstr(status));
6207 goto out;
6210 /* Ensure st_size == 1000 */
6211 status = cli_posix_stat(cli1, fname, &sbuf);
6212 if (!NT_STATUS_IS_OK(status)) {
6213 printf("stat failed (%s)\n", nt_errstr(status));
6214 goto out;
6217 if (sbuf.st_ex_size != 1000) {
6218 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
6219 goto out;
6222 /* Ensure st_mode == 0600 */
6223 if ((sbuf.st_ex_mode & 07777) != 0600) {
6224 printf("posix_open - bad permissions 0%o != 0600\n",
6225 (unsigned int)(sbuf.st_ex_mode & 07777));
6226 goto out;
6229 /* Test ftruncate - set file size back to zero. */
6230 status = cli_ftruncate(cli1, fnum1, 0);
6231 if (!NT_STATUS_IS_OK(status)) {
6232 printf("ftruncate failed (%s)\n", nt_errstr(status));
6233 goto out;
6236 status = cli_close(cli1, fnum1);
6237 if (!NT_STATUS_IS_OK(status)) {
6238 printf("close failed (%s)\n", nt_errstr(status));
6239 goto out;
6242 /* Now open the file again for read only. */
6243 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
6244 if (!NT_STATUS_IS_OK(status)) {
6245 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
6246 goto out;
6249 /* Now unlink while open. */
6250 status = cli_posix_unlink(cli1, fname);
6251 if (!NT_STATUS_IS_OK(status)) {
6252 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
6253 goto out;
6256 status = cli_close(cli1, fnum1);
6257 if (!NT_STATUS_IS_OK(status)) {
6258 printf("close(2) failed (%s)\n", nt_errstr(status));
6259 goto out;
6262 /* Ensure the file has gone. */
6263 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
6264 if (NT_STATUS_IS_OK(status)) {
6265 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
6266 goto out;
6269 /* Create again to test open with O_TRUNC. */
6270 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
6271 if (!NT_STATUS_IS_OK(status)) {
6272 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6273 goto out;
6276 /* Test ftruncate - set file size. */
6277 status = cli_ftruncate(cli1, fnum1, 1000);
6278 if (!NT_STATUS_IS_OK(status)) {
6279 printf("ftruncate failed (%s)\n", nt_errstr(status));
6280 goto out;
6283 /* Ensure st_size == 1000 */
6284 status = cli_posix_stat(cli1, fname, &sbuf);
6285 if (!NT_STATUS_IS_OK(status)) {
6286 printf("stat failed (%s)\n", nt_errstr(status));
6287 goto out;
6290 if (sbuf.st_ex_size != 1000) {
6291 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
6292 goto out;
6295 status = cli_close(cli1, fnum1);
6296 if (!NT_STATUS_IS_OK(status)) {
6297 printf("close(2) failed (%s)\n", nt_errstr(status));
6298 goto out;
6301 /* Re-open with O_TRUNC. */
6302 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
6303 if (!NT_STATUS_IS_OK(status)) {
6304 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6305 goto out;
6308 /* Ensure st_size == 0 */
6309 status = cli_posix_stat(cli1, fname, &sbuf);
6310 if (!NT_STATUS_IS_OK(status)) {
6311 printf("stat failed (%s)\n", nt_errstr(status));
6312 goto out;
6315 if (sbuf.st_ex_size != 0) {
6316 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
6317 goto out;
6320 status = cli_close(cli1, fnum1);
6321 if (!NT_STATUS_IS_OK(status)) {
6322 printf("close failed (%s)\n", nt_errstr(status));
6323 goto out;
6326 status = cli_posix_unlink(cli1, fname);
6327 if (!NT_STATUS_IS_OK(status)) {
6328 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
6329 goto out;
6332 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
6333 if (!NT_STATUS_IS_OK(status)) {
6334 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
6335 dname, nt_errstr(status));
6336 goto out;
6339 cli_close(cli1, fnum1);
6341 /* What happens when we try and POSIX open a directory for write ? */
6342 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
6343 if (NT_STATUS_IS_OK(status)) {
6344 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
6345 goto out;
6346 } else {
6347 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
6348 NT_STATUS_FILE_IS_A_DIRECTORY)) {
6349 goto out;
6353 /* Create the file. */
6354 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
6355 0600, &fnum1);
6356 if (!NT_STATUS_IS_OK(status)) {
6357 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6358 goto out;
6361 /* Write some data into it. */
6362 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
6363 NULL);
6364 if (!NT_STATUS_IS_OK(status)) {
6365 printf("cli_write failed: %s\n", nt_errstr(status));
6366 goto out;
6369 cli_close(cli1, fnum1);
6371 /* Now create a hardlink. */
6372 status = cli_posix_hardlink(cli1, fname, hname);
6373 if (!NT_STATUS_IS_OK(status)) {
6374 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
6375 goto out;
6378 /* Now create a symlink. */
6379 status = cli_posix_symlink(cli1, fname, sname);
6380 if (!NT_STATUS_IS_OK(status)) {
6381 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
6382 goto out;
6385 /* Open the hardlink for read. */
6386 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
6387 if (!NT_STATUS_IS_OK(status)) {
6388 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
6389 goto out;
6392 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
6393 if (!NT_STATUS_IS_OK(status)) {
6394 printf("POSIX read of %s failed (%s)\n", hname,
6395 nt_errstr(status));
6396 goto out;
6397 } else if (nread != 10) {
6398 printf("POSIX read of %s failed. Received %ld, expected %d\n",
6399 hname, (unsigned long)nread, 10);
6400 goto out;
6403 if (memcmp(buf, "TEST DATA\n", 10)) {
6404 printf("invalid data read from hardlink\n");
6405 goto out;
6408 /* Do a POSIX lock/unlock. */
6409 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
6410 if (!NT_STATUS_IS_OK(status)) {
6411 printf("POSIX lock failed %s\n", nt_errstr(status));
6412 goto out;
6415 /* Punch a hole in the locked area. */
6416 status = cli_posix_unlock(cli1, fnum1, 10, 80);
6417 if (!NT_STATUS_IS_OK(status)) {
6418 printf("POSIX unlock failed %s\n", nt_errstr(status));
6419 goto out;
6422 cli_close(cli1, fnum1);
6424 /* Open the symlink for read - this should fail. A POSIX
6425 client should not be doing opens on a symlink. */
6426 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
6427 if (NT_STATUS_IS_OK(status)) {
6428 printf("POSIX open of %s succeeded (should have failed)\n", sname);
6429 goto out;
6430 } else {
6431 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
6432 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
6433 printf("POSIX open of %s should have failed "
6434 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
6435 "failed with %s instead.\n",
6436 sname, nt_errstr(status));
6437 goto out;
6441 status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
6442 if (!NT_STATUS_IS_OK(status)) {
6443 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
6444 goto out;
6447 if (strcmp(namebuf, fname) != 0) {
6448 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
6449 sname, fname, namebuf);
6450 goto out;
6453 status = cli_posix_rmdir(cli1, dname);
6454 if (!NT_STATUS_IS_OK(status)) {
6455 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
6456 goto out;
6459 /* Check directory opens with a specific permission. */
6460 status = cli_posix_mkdir(cli1, dname, 0700);
6461 if (!NT_STATUS_IS_OK(status)) {
6462 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
6463 goto out;
6466 /* Ensure st_mode == 0700 */
6467 status = cli_posix_stat(cli1, dname, &sbuf);
6468 if (!NT_STATUS_IS_OK(status)) {
6469 printf("stat failed (%s)\n", nt_errstr(status));
6470 goto out;
6473 if ((sbuf.st_ex_mode & 07777) != 0700) {
6474 printf("posix_mkdir - bad permissions 0%o != 0700\n",
6475 (unsigned int)(sbuf.st_ex_mode & 07777));
6476 goto out;
6480 * Now create a Windows file, and attempt a POSIX unlink.
6481 * This should fail with a sharing violation but due to:
6483 * [Bug 9571] Unlink after open causes smbd to panic
6485 * ensure we've fixed the lock ordering violation.
6488 status = cli_ntcreate(cli1, fname_windows, 0,
6489 FILE_READ_DATA|FILE_WRITE_DATA, 0,
6490 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6491 FILE_CREATE,
6492 0x0, 0x0, &fnum2, NULL);
6493 if (!NT_STATUS_IS_OK(status)) {
6494 printf("Windows create of %s failed (%s)\n", fname_windows,
6495 nt_errstr(status));
6496 goto out;
6499 /* Now try posix_unlink. */
6500 status = cli_posix_unlink(cli1, fname_windows);
6501 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6502 printf("POSIX unlink of %s should fail "
6503 "with NT_STATUS_SHARING_VIOLATION "
6504 "got %s instead !\n",
6505 fname_windows,
6506 nt_errstr(status));
6507 goto out;
6510 cli_close(cli1, fnum2);
6512 printf("Simple POSIX open test passed\n");
6513 correct = true;
6515 out:
6517 if (fnum1 != (uint16_t)-1) {
6518 cli_close(cli1, fnum1);
6519 fnum1 = (uint16_t)-1;
6522 if (fnum2 != (uint16_t)-1) {
6523 cli_close(cli1, fnum2);
6524 fnum2 = (uint16_t)-1;
6527 cli_setatr(cli1, sname, 0, 0);
6528 cli_posix_unlink(cli1, sname);
6529 cli_setatr(cli1, hname, 0, 0);
6530 cli_posix_unlink(cli1, hname);
6531 cli_setatr(cli1, fname, 0, 0);
6532 cli_posix_unlink(cli1, fname);
6533 cli_setatr(cli1, dname, 0, 0);
6534 cli_posix_rmdir(cli1, dname);
6535 cli_setatr(cli1, fname_windows, 0, 0);
6536 cli_posix_unlink(cli1, fname_windows);
6538 if (!torture_close_connection(cli1)) {
6539 correct = false;
6542 return correct;
6546 Test POSIX and Windows ACLs are rejected on symlinks.
6548 static bool run_acl_symlink_test(int dummy)
6550 static struct cli_state *cli;
6551 const char *fname = "posix_file";
6552 const char *sname = "posix_symlink";
6553 uint16_t fnum = (uint16_t)-1;
6554 bool correct = false;
6555 NTSTATUS status;
6556 char *posix_acl = NULL;
6557 size_t posix_acl_len = 0;
6558 char *posix_acl_sym = NULL;
6559 size_t posix_acl_len_sym = 0;
6560 struct security_descriptor *sd = NULL;
6561 struct security_descriptor *sd_sym = NULL;
6562 TALLOC_CTX *frame = NULL;
6564 frame = talloc_stackframe();
6566 printf("Starting acl symlink test\n");
6568 if (!torture_open_connection(&cli, 0)) {
6569 TALLOC_FREE(frame);
6570 return false;
6573 smbXcli_conn_set_sockopt(cli->conn, sockops);
6575 status = torture_setup_unix_extensions(cli);
6576 if (!NT_STATUS_IS_OK(status)) {
6577 TALLOC_FREE(frame);
6578 return false;
6581 cli_setatr(cli, fname, 0, 0);
6582 cli_posix_unlink(cli, fname);
6583 cli_setatr(cli, sname, 0, 0);
6584 cli_posix_unlink(cli, sname);
6586 status = cli_ntcreate(cli,
6587 fname,
6589 READ_CONTROL_ACCESS,
6591 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6592 FILE_CREATE,
6593 0x0,
6594 0x0,
6595 &fnum,
6596 NULL);
6598 if (!NT_STATUS_IS_OK(status)) {
6599 printf("cli_ntcreate of %s failed (%s)\n",
6600 fname,
6601 nt_errstr(status));
6602 goto out;
6605 /* Get the Windows ACL on the file. */
6606 status = cli_query_secdesc(cli,
6607 fnum,
6608 frame,
6609 &sd);
6610 if (!NT_STATUS_IS_OK(status)) {
6611 printf("cli_query_secdesc failed (%s)\n",
6612 nt_errstr(status));
6613 goto out;
6616 /* Get the POSIX ACL on the file. */
6617 status = cli_posix_getacl(cli,
6618 fname,
6619 frame,
6620 &posix_acl_len,
6621 &posix_acl);
6623 if (!NT_STATUS_IS_OK(status)) {
6624 printf("cli_posix_getacl failed (%s)\n",
6625 nt_errstr(status));
6626 goto out;
6629 status = cli_close(cli, fnum);
6630 if (!NT_STATUS_IS_OK(status)) {
6631 printf("close failed (%s)\n", nt_errstr(status));
6632 goto out;
6634 fnum = (uint16_t)-1;
6636 /* Now create a symlink. */
6637 status = cli_posix_symlink(cli, fname, sname);
6638 if (!NT_STATUS_IS_OK(status)) {
6639 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
6640 sname,
6641 fname,
6642 nt_errstr(status));
6643 goto out;
6646 /* Open a handle on the symlink. */
6647 status = cli_ntcreate(cli,
6648 sname,
6650 READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
6652 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6653 FILE_OPEN,
6654 0x0,
6655 0x0,
6656 &fnum,
6657 NULL);
6659 if (!NT_STATUS_IS_OK(status)) {
6660 printf("cli_posix_open of %s failed (%s)\n",
6661 sname,
6662 nt_errstr(status));
6663 goto out;
6666 /* Get the Windows ACL on the symlink handle. Should fail */
6667 status = cli_query_secdesc(cli,
6668 fnum,
6669 frame,
6670 &sd_sym);
6672 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6673 printf("cli_query_secdesc on a symlink gave %s. "
6674 "Should be NT_STATUS_ACCESS_DENIED.\n",
6675 nt_errstr(status));
6676 goto out;
6679 /* Get the POSIX ACL on the symlink pathname. Should fail. */
6680 status = cli_posix_getacl(cli,
6681 sname,
6682 frame,
6683 &posix_acl_len_sym,
6684 &posix_acl_sym);
6686 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6687 printf("cli_posix_getacl on a symlink gave %s. "
6688 "Should be NT_STATUS_ACCESS_DENIED.\n",
6689 nt_errstr(status));
6690 goto out;
6693 /* Set the Windows ACL on the symlink handle. Should fail */
6694 status = cli_set_security_descriptor(cli,
6695 fnum,
6696 SECINFO_DACL,
6697 sd);
6699 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6700 printf("cli_query_secdesc on a symlink gave %s. "
6701 "Should be NT_STATUS_ACCESS_DENIED.\n",
6702 nt_errstr(status));
6703 goto out;
6706 /* Set the POSIX ACL on the symlink pathname. Should fail. */
6707 status = cli_posix_setacl(cli,
6708 sname,
6709 posix_acl,
6710 posix_acl_len);
6712 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6713 printf("cli_posix_getacl on a symlink gave %s. "
6714 "Should be NT_STATUS_ACCESS_DENIED.\n",
6715 nt_errstr(status));
6716 goto out;
6719 printf("ACL symlink test passed\n");
6720 correct = true;
6722 out:
6724 if (fnum != (uint16_t)-1) {
6725 cli_close(cli, fnum);
6726 fnum = (uint16_t)-1;
6729 cli_setatr(cli, sname, 0, 0);
6730 cli_posix_unlink(cli, sname);
6731 cli_setatr(cli, fname, 0, 0);
6732 cli_posix_unlink(cli, fname);
6734 if (!torture_close_connection(cli)) {
6735 correct = false;
6738 TALLOC_FREE(frame);
6739 return correct;
6743 Test POSIX can delete a file containing streams.
6745 static bool run_posix_stream_delete(int dummy)
6747 struct cli_state *cli1 = NULL;
6748 struct cli_state *cli2 = NULL;
6749 const char *fname = "streamfile";
6750 const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
6751 uint16_t fnum1 = (uint16_t)-1;
6752 bool correct = false;
6753 NTSTATUS status;
6754 TALLOC_CTX *frame = NULL;
6756 frame = talloc_stackframe();
6758 printf("Starting POSIX stream delete test\n");
6760 if (!torture_open_connection(&cli1, 0) ||
6761 !torture_open_connection(&cli2, 1)) {
6762 TALLOC_FREE(frame);
6763 return false;
6766 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6767 smbXcli_conn_set_sockopt(cli2->conn, sockops);
6769 status = torture_setup_unix_extensions(cli2);
6770 if (!NT_STATUS_IS_OK(status)) {
6771 goto out;
6774 cli_setatr(cli1, fname, 0, 0);
6775 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6777 /* Create the file. */
6778 status = cli_ntcreate(cli1,
6779 fname,
6781 READ_CONTROL_ACCESS,
6783 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6784 FILE_CREATE,
6785 0x0,
6786 0x0,
6787 &fnum1,
6788 NULL);
6790 if (!NT_STATUS_IS_OK(status)) {
6791 printf("cli_ntcreate of %s failed (%s)\n",
6792 fname,
6793 nt_errstr(status));
6794 goto out;
6797 status = cli_close(cli1, fnum1);
6798 if (!NT_STATUS_IS_OK(status)) {
6799 printf("cli_close of %s failed (%s)\n",
6800 fname,
6801 nt_errstr(status));
6802 goto out;
6804 fnum1 = (uint16_t)-1;
6806 /* Now create the stream. */
6807 status = cli_ntcreate(cli1,
6808 stream_fname,
6810 FILE_WRITE_DATA,
6812 FILE_SHARE_READ|FILE_SHARE_WRITE,
6813 FILE_CREATE,
6814 0x0,
6815 0x0,
6816 &fnum1,
6817 NULL);
6819 if (!NT_STATUS_IS_OK(status)) {
6820 printf("cli_ntcreate of %s failed (%s)\n",
6821 stream_fname,
6822 nt_errstr(status));
6823 goto out;
6826 /* Leave the stream handle open... */
6828 /* POSIX unlink should fail. */
6829 status = cli_posix_unlink(cli2, fname);
6830 if (NT_STATUS_IS_OK(status)) {
6831 printf("cli_posix_unlink of %s succeeded, should have failed\n",
6832 fname);
6833 goto out;
6836 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6837 printf("cli_posix_unlink of %s failed with (%s) "
6838 "should have been NT_STATUS_SHARING_VIOLATION\n",
6839 fname,
6840 nt_errstr(status));
6841 goto out;
6844 /* Close the stream handle. */
6845 status = cli_close(cli1, fnum1);
6846 if (!NT_STATUS_IS_OK(status)) {
6847 printf("cli_close of %s failed (%s)\n",
6848 stream_fname,
6849 nt_errstr(status));
6850 goto out;
6852 fnum1 = (uint16_t)-1;
6854 /* POSIX unlink after stream handle closed should succeed. */
6855 status = cli_posix_unlink(cli2, fname);
6856 if (!NT_STATUS_IS_OK(status)) {
6857 printf("cli_posix_unlink of %s failed (%s)\n",
6858 fname,
6859 nt_errstr(status));
6860 goto out;
6863 printf("POSIX stream delete test passed\n");
6864 correct = true;
6866 out:
6868 if (fnum1 != (uint16_t)-1) {
6869 cli_close(cli1, fnum1);
6870 fnum1 = (uint16_t)-1;
6873 cli_setatr(cli1, fname, 0, 0);
6874 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6876 if (!torture_close_connection(cli1)) {
6877 correct = false;
6879 if (!torture_close_connection(cli2)) {
6880 correct = false;
6883 TALLOC_FREE(frame);
6884 return correct;
6888 Test setting EA's are rejected on symlinks.
6890 static bool run_ea_symlink_test(int dummy)
6892 static struct cli_state *cli;
6893 const char *fname = "posix_file_ea";
6894 const char *sname = "posix_symlink_ea";
6895 const char *ea_name = "testea_name";
6896 const char *ea_value = "testea_value";
6897 uint16_t fnum = (uint16_t)-1;
6898 bool correct = false;
6899 NTSTATUS status;
6900 size_t i, num_eas;
6901 struct ea_struct *eas = NULL;
6902 TALLOC_CTX *frame = NULL;
6904 frame = talloc_stackframe();
6906 printf("Starting EA symlink test\n");
6908 if (!torture_open_connection(&cli, 0)) {
6909 TALLOC_FREE(frame);
6910 return false;
6913 smbXcli_conn_set_sockopt(cli->conn, sockops);
6915 status = torture_setup_unix_extensions(cli);
6916 if (!NT_STATUS_IS_OK(status)) {
6917 TALLOC_FREE(frame);
6918 return false;
6921 cli_setatr(cli, fname, 0, 0);
6922 cli_posix_unlink(cli, fname);
6923 cli_setatr(cli, sname, 0, 0);
6924 cli_posix_unlink(cli, sname);
6926 status = cli_ntcreate(cli,
6927 fname,
6929 READ_CONTROL_ACCESS,
6931 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6932 FILE_CREATE,
6933 0x0,
6934 0x0,
6935 &fnum,
6936 NULL);
6938 if (!NT_STATUS_IS_OK(status)) {
6939 printf("cli_ntcreate of %s failed (%s)\n",
6940 fname,
6941 nt_errstr(status));
6942 goto out;
6945 status = cli_close(cli, fnum);
6946 if (!NT_STATUS_IS_OK(status)) {
6947 printf("close failed (%s)\n",
6948 nt_errstr(status));
6949 goto out;
6951 fnum = (uint16_t)-1;
6953 /* Set an EA on the path. */
6954 status = cli_set_ea_path(cli,
6955 fname,
6956 ea_name,
6957 ea_value,
6958 strlen(ea_value)+1);
6960 if (!NT_STATUS_IS_OK(status)) {
6961 printf("cli_set_ea_path failed (%s)\n",
6962 nt_errstr(status));
6963 goto out;
6966 /* Now create a symlink. */
6967 status = cli_posix_symlink(cli, fname, sname);
6968 if (!NT_STATUS_IS_OK(status)) {
6969 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
6970 sname,
6971 fname,
6972 nt_errstr(status));
6973 goto out;
6976 /* Get the EA list on the path. Should return value set. */
6977 status = cli_get_ea_list_path(cli,
6978 fname,
6979 frame,
6980 &num_eas,
6981 &eas);
6983 if (!NT_STATUS_IS_OK(status)) {
6984 printf("cli_get_ea_list_path failed (%s)\n",
6985 nt_errstr(status));
6986 goto out;
6989 /* Ensure the EA we set is there. */
6990 for (i=0; i<num_eas; i++) {
6991 if (strcmp(eas[i].name, ea_name) == 0 &&
6992 eas[i].value.length == strlen(ea_value)+1 &&
6993 memcmp(eas[i].value.data,
6994 ea_value,
6995 eas[i].value.length) == 0) {
6996 break;
7000 if (i == num_eas) {
7001 printf("Didn't find EA on pathname %s\n",
7002 fname);
7003 goto out;
7006 num_eas = 0;
7007 TALLOC_FREE(eas);
7009 /* Get the EA list on the symlink. Should return empty list. */
7010 status = cli_get_ea_list_path(cli,
7011 sname,
7012 frame,
7013 &num_eas,
7014 &eas);
7016 if (!NT_STATUS_IS_OK(status)) {
7017 printf("cli_get_ea_list_path failed (%s)\n",
7018 nt_errstr(status));
7019 goto out;
7022 if (num_eas != 0) {
7023 printf("cli_get_ea_list_path failed (%s)\n",
7024 nt_errstr(status));
7025 goto out;
7028 /* Set an EA on the symlink. Should fail. */
7029 status = cli_set_ea_path(cli,
7030 sname,
7031 ea_name,
7032 ea_value,
7033 strlen(ea_value)+1);
7035 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7036 printf("cli_set_ea_path on a symlink gave %s. "
7037 "Should be NT_STATUS_ACCESS_DENIED.\n",
7038 nt_errstr(status));
7039 goto out;
7042 printf("EA symlink test passed\n");
7043 correct = true;
7045 out:
7047 if (fnum != (uint16_t)-1) {
7048 cli_close(cli, fnum);
7049 fnum = (uint16_t)-1;
7052 cli_setatr(cli, sname, 0, 0);
7053 cli_posix_unlink(cli, sname);
7054 cli_setatr(cli, fname, 0, 0);
7055 cli_posix_unlink(cli, fname);
7057 if (!torture_close_connection(cli)) {
7058 correct = false;
7061 TALLOC_FREE(frame);
7062 return correct;
7066 Test POSIX locks are OFD-locks.
7068 static bool run_posix_ofd_lock_test(int dummy)
7070 static struct cli_state *cli;
7071 const char *fname = "posix_file";
7072 uint16_t fnum1 = (uint16_t)-1;
7073 uint16_t fnum2 = (uint16_t)-1;
7074 bool correct = false;
7075 NTSTATUS status;
7076 TALLOC_CTX *frame = NULL;
7078 frame = talloc_stackframe();
7080 printf("Starting POSIX ofd-lock test\n");
7082 if (!torture_open_connection(&cli, 0)) {
7083 TALLOC_FREE(frame);
7084 return false;
7087 smbXcli_conn_set_sockopt(cli->conn, sockops);
7089 status = torture_setup_unix_extensions(cli);
7090 if (!NT_STATUS_IS_OK(status)) {
7091 TALLOC_FREE(frame);
7092 return false;
7095 cli_setatr(cli, fname, 0, 0);
7096 cli_posix_unlink(cli, fname);
7098 /* Open the file twice. */
7099 status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
7100 0600, &fnum1);
7101 if (!NT_STATUS_IS_OK(status)) {
7102 printf("First POSIX open of %s failed\n", fname);
7103 goto out;
7106 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
7107 if (!NT_STATUS_IS_OK(status)) {
7108 printf("First POSIX open of %s failed\n", fname);
7109 goto out;
7112 /* Set a 0-50 lock on fnum1. */
7113 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
7114 if (!NT_STATUS_IS_OK(status)) {
7115 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
7116 goto out;
7119 /* Set a 60-100 lock on fnum2. */
7120 status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
7121 if (!NT_STATUS_IS_OK(status)) {
7122 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
7123 goto out;
7126 /* close fnum1 - 0-50 lock should go away. */
7127 status = cli_close(cli, fnum1);
7128 if (!NT_STATUS_IS_OK(status)) {
7129 printf("close failed (%s)\n",
7130 nt_errstr(status));
7131 goto out;
7133 fnum1 = (uint16_t)-1;
7135 /* Change the lock context. */
7136 cli_setpid(cli, cli_getpid(cli) + 1);
7138 /* Re-open fnum1. */
7139 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
7140 if (!NT_STATUS_IS_OK(status)) {
7141 printf("Third POSIX open of %s failed\n", fname);
7142 goto out;
7145 /* 60-100 lock should still be there. */
7146 status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
7147 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
7148 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
7149 goto out;
7152 /* 0-50 lock should be gone. */
7153 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
7154 if (!NT_STATUS_IS_OK(status)) {
7155 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
7156 goto out;
7159 printf("POSIX OFD lock test passed\n");
7160 correct = true;
7162 out:
7164 if (fnum1 != (uint16_t)-1) {
7165 cli_close(cli, fnum1);
7166 fnum1 = (uint16_t)-1;
7168 if (fnum2 != (uint16_t)-1) {
7169 cli_close(cli, fnum2);
7170 fnum2 = (uint16_t)-1;
7173 cli_setatr(cli, fname, 0, 0);
7174 cli_posix_unlink(cli, fname);
7176 if (!torture_close_connection(cli)) {
7177 correct = false;
7180 TALLOC_FREE(frame);
7181 return correct;
7184 static uint32_t open_attrs_table[] = {
7185 FILE_ATTRIBUTE_NORMAL,
7186 FILE_ATTRIBUTE_ARCHIVE,
7187 FILE_ATTRIBUTE_READONLY,
7188 FILE_ATTRIBUTE_HIDDEN,
7189 FILE_ATTRIBUTE_SYSTEM,
7191 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
7192 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
7193 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
7194 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
7195 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
7196 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
7198 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
7199 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
7200 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
7201 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
7204 struct trunc_open_results {
7205 unsigned int num;
7206 uint32_t init_attr;
7207 uint32_t trunc_attr;
7208 uint32_t result_attr;
7211 static struct trunc_open_results attr_results[] = {
7212 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
7213 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
7214 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
7215 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
7216 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
7217 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
7218 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7219 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7220 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
7221 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7222 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7223 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
7224 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7225 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7226 { 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 },
7227 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7228 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7229 { 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 },
7230 { 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 },
7231 { 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 },
7232 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7233 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7234 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
7235 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7236 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7237 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
7240 static bool run_openattrtest(int dummy)
7242 static struct cli_state *cli1;
7243 const char *fname = "\\openattr.file";
7244 uint16_t fnum1;
7245 bool correct = True;
7246 uint16_t attr;
7247 unsigned int i, j, k, l;
7248 NTSTATUS status;
7250 printf("starting open attr test\n");
7252 if (!torture_open_connection(&cli1, 0)) {
7253 return False;
7256 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7258 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
7259 cli_setatr(cli1, fname, 0, 0);
7260 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7262 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
7263 open_attrs_table[i], FILE_SHARE_NONE,
7264 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7265 if (!NT_STATUS_IS_OK(status)) {
7266 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
7267 return False;
7270 status = cli_close(cli1, fnum1);
7271 if (!NT_STATUS_IS_OK(status)) {
7272 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
7273 return False;
7276 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
7277 status = cli_ntcreate(cli1, fname, 0,
7278 FILE_READ_DATA|FILE_WRITE_DATA,
7279 open_attrs_table[j],
7280 FILE_SHARE_NONE, FILE_OVERWRITE,
7281 0, 0, &fnum1, NULL);
7282 if (!NT_STATUS_IS_OK(status)) {
7283 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
7284 if (attr_results[l].num == k) {
7285 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
7286 k, open_attrs_table[i],
7287 open_attrs_table[j],
7288 fname, NT_STATUS_V(status), nt_errstr(status));
7289 correct = False;
7293 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7294 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
7295 k, open_attrs_table[i], open_attrs_table[j],
7296 nt_errstr(status));
7297 correct = False;
7299 #if 0
7300 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
7301 #endif
7302 k++;
7303 continue;
7306 status = cli_close(cli1, fnum1);
7307 if (!NT_STATUS_IS_OK(status)) {
7308 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
7309 return False;
7312 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
7313 if (!NT_STATUS_IS_OK(status)) {
7314 printf("getatr(2) failed (%s)\n", nt_errstr(status));
7315 return False;
7318 #if 0
7319 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
7320 k, open_attrs_table[i], open_attrs_table[j], attr );
7321 #endif
7323 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
7324 if (attr_results[l].num == k) {
7325 if (attr != attr_results[l].result_attr ||
7326 open_attrs_table[i] != attr_results[l].init_attr ||
7327 open_attrs_table[j] != attr_results[l].trunc_attr) {
7328 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
7329 open_attrs_table[i],
7330 open_attrs_table[j],
7331 (unsigned int)attr,
7332 attr_results[l].result_attr);
7333 correct = False;
7335 break;
7338 k++;
7342 cli_setatr(cli1, fname, 0, 0);
7343 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7345 printf("open attr test %s.\n", correct ? "passed" : "failed");
7347 if (!torture_close_connection(cli1)) {
7348 correct = False;
7350 return correct;
7353 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
7354 const char *name, void *state)
7356 int *matched = (int *)state;
7357 if (matched != NULL) {
7358 *matched += 1;
7360 return NT_STATUS_OK;
7364 test directory listing speed
7366 static bool run_dirtest(int dummy)
7368 int i;
7369 static struct cli_state *cli;
7370 uint16_t fnum;
7371 struct timeval core_start;
7372 bool correct = True;
7373 int matched;
7375 printf("starting directory test\n");
7377 if (!torture_open_connection(&cli, 0)) {
7378 return False;
7381 smbXcli_conn_set_sockopt(cli->conn, sockops);
7383 srandom(0);
7384 for (i=0;i<torture_numops;i++) {
7385 fstring fname;
7386 slprintf(fname, sizeof(fname), "\\%x", (int)random());
7387 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
7388 fprintf(stderr,"Failed to open %s\n", fname);
7389 return False;
7391 cli_close(cli, fnum);
7394 core_start = timeval_current();
7396 matched = 0;
7397 cli_list(cli, "a*.*", 0, list_fn, &matched);
7398 printf("Matched %d\n", matched);
7400 matched = 0;
7401 cli_list(cli, "b*.*", 0, list_fn, &matched);
7402 printf("Matched %d\n", matched);
7404 matched = 0;
7405 cli_list(cli, "xyzabc", 0, list_fn, &matched);
7406 printf("Matched %d\n", matched);
7408 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
7410 srandom(0);
7411 for (i=0;i<torture_numops;i++) {
7412 fstring fname;
7413 slprintf(fname, sizeof(fname), "\\%x", (int)random());
7414 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7417 if (!torture_close_connection(cli)) {
7418 correct = False;
7421 printf("finished dirtest\n");
7423 return correct;
7426 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
7427 void *state)
7429 struct cli_state *pcli = (struct cli_state *)state;
7430 fstring fname;
7431 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
7433 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7434 return NT_STATUS_OK;
7436 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7437 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
7438 printf("del_fn: failed to rmdir %s\n,", fname );
7439 } else {
7440 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
7441 printf("del_fn: failed to unlink %s\n,", fname );
7443 return NT_STATUS_OK;
7448 sees what IOCTLs are supported
7450 bool torture_ioctl_test(int dummy)
7452 static struct cli_state *cli;
7453 uint16_t device, function;
7454 uint16_t fnum;
7455 const char *fname = "\\ioctl.dat";
7456 DATA_BLOB blob;
7457 NTSTATUS status;
7459 if (!torture_open_connection(&cli, 0)) {
7460 return False;
7463 printf("starting ioctl test\n");
7465 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7467 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7468 if (!NT_STATUS_IS_OK(status)) {
7469 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7470 return False;
7473 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
7474 printf("ioctl device info: %s\n", nt_errstr(status));
7476 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
7477 printf("ioctl job info: %s\n", nt_errstr(status));
7479 for (device=0;device<0x100;device++) {
7480 printf("ioctl test with device = 0x%x\n", device);
7481 for (function=0;function<0x100;function++) {
7482 uint32_t code = (device<<16) | function;
7484 status = cli_raw_ioctl(cli, fnum, code, &blob);
7486 if (NT_STATUS_IS_OK(status)) {
7487 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
7488 (int)blob.length);
7489 data_blob_free(&blob);
7494 if (!torture_close_connection(cli)) {
7495 return False;
7498 return True;
7503 tries varients of chkpath
7505 bool torture_chkpath_test(int dummy)
7507 static struct cli_state *cli;
7508 uint16_t fnum;
7509 bool ret;
7510 NTSTATUS status;
7512 if (!torture_open_connection(&cli, 0)) {
7513 return False;
7516 printf("starting chkpath test\n");
7518 /* cleanup from an old run */
7519 cli_rmdir(cli, "\\chkpath.dir\\dir2");
7520 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7521 cli_rmdir(cli, "\\chkpath.dir");
7523 status = cli_mkdir(cli, "\\chkpath.dir");
7524 if (!NT_STATUS_IS_OK(status)) {
7525 printf("mkdir1 failed : %s\n", nt_errstr(status));
7526 return False;
7529 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
7530 if (!NT_STATUS_IS_OK(status)) {
7531 printf("mkdir2 failed : %s\n", nt_errstr(status));
7532 return False;
7535 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
7536 DENY_NONE, &fnum);
7537 if (!NT_STATUS_IS_OK(status)) {
7538 printf("open1 failed (%s)\n", nt_errstr(status));
7539 return False;
7541 cli_close(cli, fnum);
7543 status = cli_chkpath(cli, "\\chkpath.dir");
7544 if (!NT_STATUS_IS_OK(status)) {
7545 printf("chkpath1 failed: %s\n", nt_errstr(status));
7546 ret = False;
7549 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
7550 if (!NT_STATUS_IS_OK(status)) {
7551 printf("chkpath2 failed: %s\n", nt_errstr(status));
7552 ret = False;
7555 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
7556 if (!NT_STATUS_IS_OK(status)) {
7557 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
7558 NT_STATUS_NOT_A_DIRECTORY);
7559 } else {
7560 printf("* chkpath on a file should fail\n");
7561 ret = False;
7564 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
7565 if (!NT_STATUS_IS_OK(status)) {
7566 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
7567 NT_STATUS_OBJECT_NAME_NOT_FOUND);
7568 } else {
7569 printf("* chkpath on a non existent file should fail\n");
7570 ret = False;
7573 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
7574 if (!NT_STATUS_IS_OK(status)) {
7575 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
7576 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7577 } else {
7578 printf("* chkpath on a non existent component should fail\n");
7579 ret = False;
7582 cli_rmdir(cli, "\\chkpath.dir\\dir2");
7583 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7584 cli_rmdir(cli, "\\chkpath.dir");
7586 if (!torture_close_connection(cli)) {
7587 return False;
7590 return ret;
7593 static bool run_eatest(int dummy)
7595 static struct cli_state *cli;
7596 const char *fname = "\\eatest.txt";
7597 bool correct = True;
7598 uint16_t fnum;
7599 int i;
7600 size_t num_eas;
7601 struct ea_struct *ea_list = NULL;
7602 TALLOC_CTX *mem_ctx = talloc_init("eatest");
7603 NTSTATUS status;
7605 printf("starting eatest\n");
7607 if (!torture_open_connection(&cli, 0)) {
7608 talloc_destroy(mem_ctx);
7609 return False;
7612 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7614 status = cli_ntcreate(cli, fname, 0,
7615 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
7616 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
7617 0x4044, 0, &fnum, NULL);
7618 if (!NT_STATUS_IS_OK(status)) {
7619 printf("open failed - %s\n", nt_errstr(status));
7620 talloc_destroy(mem_ctx);
7621 return False;
7624 for (i = 0; i < 10; i++) {
7625 fstring ea_name, ea_val;
7627 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
7628 memset(ea_val, (char)i+1, i+1);
7629 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
7630 if (!NT_STATUS_IS_OK(status)) {
7631 printf("ea_set of name %s failed - %s\n", ea_name,
7632 nt_errstr(status));
7633 talloc_destroy(mem_ctx);
7634 return False;
7638 cli_close(cli, fnum);
7639 for (i = 0; i < 10; i++) {
7640 fstring ea_name, ea_val;
7642 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
7643 memset(ea_val, (char)i+1, i+1);
7644 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
7645 if (!NT_STATUS_IS_OK(status)) {
7646 printf("ea_set of name %s failed - %s\n", ea_name,
7647 nt_errstr(status));
7648 talloc_destroy(mem_ctx);
7649 return False;
7653 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
7654 if (!NT_STATUS_IS_OK(status)) {
7655 printf("ea_get list failed - %s\n", nt_errstr(status));
7656 correct = False;
7659 printf("num_eas = %d\n", (int)num_eas);
7661 if (num_eas != 20) {
7662 printf("Should be 20 EA's stored... failing.\n");
7663 correct = False;
7666 for (i = 0; i < num_eas; i++) {
7667 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
7668 dump_data(0, ea_list[i].value.data,
7669 ea_list[i].value.length);
7672 /* Setting EA's to zero length deletes them. Test this */
7673 printf("Now deleting all EA's - case indepenent....\n");
7675 #if 1
7676 cli_set_ea_path(cli, fname, "", "", 0);
7677 #else
7678 for (i = 0; i < 20; i++) {
7679 fstring ea_name;
7680 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
7681 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
7682 if (!NT_STATUS_IS_OK(status)) {
7683 printf("ea_set of name %s failed - %s\n", ea_name,
7684 nt_errstr(status));
7685 talloc_destroy(mem_ctx);
7686 return False;
7689 #endif
7691 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
7692 if (!NT_STATUS_IS_OK(status)) {
7693 printf("ea_get list failed - %s\n", nt_errstr(status));
7694 correct = False;
7697 printf("num_eas = %d\n", (int)num_eas);
7698 for (i = 0; i < num_eas; i++) {
7699 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
7700 dump_data(0, ea_list[i].value.data,
7701 ea_list[i].value.length);
7704 if (num_eas != 0) {
7705 printf("deleting EA's failed.\n");
7706 correct = False;
7709 /* Try and delete a non existent EA. */
7710 status = cli_set_ea_path(cli, fname, "foo", "", 0);
7711 if (!NT_STATUS_IS_OK(status)) {
7712 printf("deleting non-existent EA 'foo' should succeed. %s\n",
7713 nt_errstr(status));
7714 correct = False;
7717 talloc_destroy(mem_ctx);
7718 if (!torture_close_connection(cli)) {
7719 correct = False;
7722 return correct;
7725 static bool run_dirtest1(int dummy)
7727 int i;
7728 static struct cli_state *cli;
7729 uint16_t fnum;
7730 int num_seen;
7731 bool correct = True;
7733 printf("starting directory test\n");
7735 if (!torture_open_connection(&cli, 0)) {
7736 return False;
7739 smbXcli_conn_set_sockopt(cli->conn, sockops);
7741 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
7742 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
7743 cli_rmdir(cli, "\\LISTDIR");
7744 cli_mkdir(cli, "\\LISTDIR");
7746 /* Create 1000 files and 1000 directories. */
7747 for (i=0;i<1000;i++) {
7748 fstring fname;
7749 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
7750 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
7751 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
7752 0, 0, &fnum, NULL))) {
7753 fprintf(stderr,"Failed to open %s\n", fname);
7754 return False;
7756 cli_close(cli, fnum);
7758 for (i=0;i<1000;i++) {
7759 fstring fname;
7760 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
7761 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
7762 fprintf(stderr,"Failed to open %s\n", fname);
7763 return False;
7767 /* Now ensure that doing an old list sees both files and directories. */
7768 num_seen = 0;
7769 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7770 printf("num_seen = %d\n", num_seen );
7771 /* We should see 100 files + 1000 directories + . and .. */
7772 if (num_seen != 2002)
7773 correct = False;
7775 /* Ensure if we have the "must have" bits we only see the
7776 * relevent entries.
7778 num_seen = 0;
7779 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7780 printf("num_seen = %d\n", num_seen );
7781 if (num_seen != 1002)
7782 correct = False;
7784 num_seen = 0;
7785 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7786 printf("num_seen = %d\n", num_seen );
7787 if (num_seen != 1000)
7788 correct = False;
7790 /* Delete everything. */
7791 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
7792 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
7793 cli_rmdir(cli, "\\LISTDIR");
7795 #if 0
7796 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
7797 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
7798 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
7799 #endif
7801 if (!torture_close_connection(cli)) {
7802 correct = False;
7805 printf("finished dirtest1\n");
7807 return correct;
7810 static bool run_error_map_extract(int dummy) {
7812 static struct cli_state *c_dos;
7813 static struct cli_state *c_nt;
7814 NTSTATUS status;
7816 uint32_t error;
7818 uint32_t errnum;
7819 uint8_t errclass;
7821 NTSTATUS nt_status;
7823 fstring user;
7825 /* NT-Error connection */
7827 disable_spnego = true;
7828 if (!(c_nt = open_nbt_connection())) {
7829 disable_spnego = false;
7830 return False;
7832 disable_spnego = false;
7834 status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
7835 PROTOCOL_NT1);
7837 if (!NT_STATUS_IS_OK(status)) {
7838 printf("%s rejected the NT-error negprot (%s)\n", host,
7839 nt_errstr(status));
7840 cli_shutdown(c_nt);
7841 return False;
7844 status = cli_session_setup_anon(c_nt);
7845 if (!NT_STATUS_IS_OK(status)) {
7846 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
7847 return False;
7850 /* DOS-Error connection */
7852 disable_spnego = true;
7853 force_dos_errors = true;
7854 if (!(c_dos = open_nbt_connection())) {
7855 disable_spnego = false;
7856 force_dos_errors = false;
7857 return False;
7859 disable_spnego = false;
7860 force_dos_errors = false;
7862 status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
7863 PROTOCOL_NT1);
7864 if (!NT_STATUS_IS_OK(status)) {
7865 printf("%s rejected the DOS-error negprot (%s)\n", host,
7866 nt_errstr(status));
7867 cli_shutdown(c_dos);
7868 return False;
7871 status = cli_session_setup_anon(c_dos);
7872 if (!NT_STATUS_IS_OK(status)) {
7873 printf("%s rejected the DOS-error initial session setup (%s)\n",
7874 host, nt_errstr(status));
7875 return False;
7878 c_nt->map_dos_errors = false;
7879 c_dos->map_dos_errors = false;
7881 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
7882 struct cli_credentials *user_creds = NULL;
7884 fstr_sprintf(user, "%X", error);
7886 user_creds = cli_session_creds_init(talloc_tos(),
7887 user,
7888 workgroup,
7889 NULL, /* realm */
7890 password,
7891 false, /* use_kerberos */
7892 false, /* fallback_after_kerberos */
7893 false, /* use_ccache */
7894 false); /* password_is_nt_hash */
7895 if (user_creds == NULL) {
7896 printf("cli_session_creds_init(%s) failed\n", user);
7897 return false;
7900 status = cli_session_setup_creds(c_nt, user_creds);
7901 if (NT_STATUS_IS_OK(status)) {
7902 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
7905 /* Case #1: 32-bit NT errors */
7906 if (!NT_STATUS_IS_DOS(status)) {
7907 nt_status = status;
7908 } else {
7909 printf("/** Dos error on NT connection! (%s) */\n",
7910 nt_errstr(status));
7911 nt_status = NT_STATUS(0xc0000000);
7914 status = cli_session_setup_creds(c_dos, user_creds);
7915 if (NT_STATUS_IS_OK(status)) {
7916 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
7919 /* Case #1: 32-bit NT errors */
7920 if (NT_STATUS_IS_DOS(status)) {
7921 printf("/** NT error on DOS connection! (%s) */\n",
7922 nt_errstr(status));
7923 errnum = errclass = 0;
7924 } else {
7925 errclass = NT_STATUS_DOS_CLASS(status);
7926 errnum = NT_STATUS_DOS_CODE(status);
7929 if (NT_STATUS_V(nt_status) != error) {
7930 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
7931 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
7932 get_nt_error_c_code(talloc_tos(), nt_status));
7935 printf("\t{%s,\t%s,\t%s},\n",
7936 smb_dos_err_class(errclass),
7937 smb_dos_err_name(errclass, errnum),
7938 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
7940 TALLOC_FREE(user_creds);
7942 return True;
7945 static bool run_sesssetup_bench(int dummy)
7947 static struct cli_state *c;
7948 const char *fname = "\\file.dat";
7949 uint16_t fnum;
7950 NTSTATUS status;
7951 int i;
7953 if (!torture_open_connection(&c, 0)) {
7954 return false;
7957 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7958 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7959 FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
7960 if (!NT_STATUS_IS_OK(status)) {
7961 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7962 return false;
7965 for (i=0; i<torture_numops; i++) {
7966 status = cli_session_setup_creds(c, torture_creds);
7967 if (!NT_STATUS_IS_OK(status)) {
7968 d_printf("(%s) cli_session_setup_creds failed: %s\n",
7969 __location__, nt_errstr(status));
7970 return false;
7973 d_printf("\r%d ", (int)cli_state_get_uid(c));
7975 status = cli_ulogoff(c);
7976 if (!NT_STATUS_IS_OK(status)) {
7977 d_printf("(%s) cli_ulogoff failed: %s\n",
7978 __location__, nt_errstr(status));
7979 return false;
7983 return true;
7986 static bool subst_test(const char *str, const char *user, const char *domain,
7987 uid_t uid, gid_t gid, const char *expected)
7989 char *subst;
7990 bool result = true;
7992 subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
7994 if (strcmp(subst, expected) != 0) {
7995 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
7996 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
7997 expected);
7998 result = false;
8001 TALLOC_FREE(subst);
8002 return result;
8005 static void chain1_open_completion(struct tevent_req *req)
8007 uint16_t fnum;
8008 NTSTATUS status;
8009 status = cli_openx_recv(req, &fnum);
8010 TALLOC_FREE(req);
8012 d_printf("cli_openx_recv returned %s: %d\n",
8013 nt_errstr(status),
8014 NT_STATUS_IS_OK(status) ? fnum : -1);
8017 static void chain1_write_completion(struct tevent_req *req)
8019 size_t written;
8020 NTSTATUS status;
8021 status = cli_write_andx_recv(req, &written);
8022 TALLOC_FREE(req);
8024 d_printf("cli_write_andx_recv returned %s: %d\n",
8025 nt_errstr(status),
8026 NT_STATUS_IS_OK(status) ? (int)written : -1);
8029 static void chain1_close_completion(struct tevent_req *req)
8031 NTSTATUS status;
8032 bool *done = (bool *)tevent_req_callback_data_void(req);
8034 status = cli_close_recv(req);
8035 *done = true;
8037 TALLOC_FREE(req);
8039 d_printf("cli_close returned %s\n", nt_errstr(status));
8042 static bool run_chain1(int dummy)
8044 struct cli_state *cli1;
8045 struct tevent_context *evt = samba_tevent_context_init(NULL);
8046 struct tevent_req *reqs[3], *smbreqs[3];
8047 bool done = false;
8048 const char *str = "foobar";
8049 NTSTATUS status;
8051 printf("starting chain1 test\n");
8052 if (!torture_open_connection(&cli1, 0)) {
8053 return False;
8056 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8058 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, "\\test",
8059 O_CREAT|O_RDWR, 0, &smbreqs[0]);
8060 if (reqs[0] == NULL) return false;
8061 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
8064 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
8065 (const uint8_t *)str, 0, strlen(str)+1,
8066 smbreqs, 1, &smbreqs[1]);
8067 if (reqs[1] == NULL) return false;
8068 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
8070 reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
8071 if (reqs[2] == NULL) return false;
8072 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
8074 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
8075 if (!NT_STATUS_IS_OK(status)) {
8076 return false;
8079 while (!done) {
8080 tevent_loop_once(evt);
8083 torture_close_connection(cli1);
8084 return True;
8087 static void chain2_sesssetup_completion(struct tevent_req *req)
8089 NTSTATUS status;
8090 status = cli_session_setup_guest_recv(req);
8091 d_printf("sesssetup returned %s\n", nt_errstr(status));
8094 static void chain2_tcon_completion(struct tevent_req *req)
8096 bool *done = (bool *)tevent_req_callback_data_void(req);
8097 NTSTATUS status;
8098 status = cli_tcon_andx_recv(req);
8099 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
8100 *done = true;
8103 static bool run_chain2(int dummy)
8105 struct cli_state *cli1;
8106 struct tevent_context *evt = samba_tevent_context_init(NULL);
8107 struct tevent_req *reqs[2], *smbreqs[2];
8108 bool done = false;
8109 NTSTATUS status;
8110 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
8112 printf("starting chain2 test\n");
8113 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
8114 port_to_use, SMB_SIGNING_DEFAULT, flags);
8115 if (!NT_STATUS_IS_OK(status)) {
8116 return False;
8119 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8121 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
8122 &smbreqs[0]);
8123 if (reqs[0] == NULL) return false;
8124 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
8126 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
8127 "?????", NULL, 0, &smbreqs[1]);
8128 if (reqs[1] == NULL) return false;
8129 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
8131 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
8132 if (!NT_STATUS_IS_OK(status)) {
8133 return false;
8136 while (!done) {
8137 tevent_loop_once(evt);
8140 torture_close_connection(cli1);
8141 return True;
8145 struct torture_createdel_state {
8146 struct tevent_context *ev;
8147 struct cli_state *cli;
8150 static void torture_createdel_created(struct tevent_req *subreq);
8151 static void torture_createdel_closed(struct tevent_req *subreq);
8153 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
8154 struct tevent_context *ev,
8155 struct cli_state *cli,
8156 const char *name)
8158 struct tevent_req *req, *subreq;
8159 struct torture_createdel_state *state;
8161 req = tevent_req_create(mem_ctx, &state,
8162 struct torture_createdel_state);
8163 if (req == NULL) {
8164 return NULL;
8166 state->ev = ev;
8167 state->cli = cli;
8169 subreq = cli_ntcreate_send(
8170 state, ev, cli, name, 0,
8171 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
8172 FILE_ATTRIBUTE_NORMAL,
8173 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8174 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
8176 if (tevent_req_nomem(subreq, req)) {
8177 return tevent_req_post(req, ev);
8179 tevent_req_set_callback(subreq, torture_createdel_created, req);
8180 return req;
8183 static void torture_createdel_created(struct tevent_req *subreq)
8185 struct tevent_req *req = tevent_req_callback_data(
8186 subreq, struct tevent_req);
8187 struct torture_createdel_state *state = tevent_req_data(
8188 req, struct torture_createdel_state);
8189 NTSTATUS status;
8190 uint16_t fnum;
8192 status = cli_ntcreate_recv(subreq, &fnum, NULL);
8193 TALLOC_FREE(subreq);
8194 if (tevent_req_nterror(req, status)) {
8195 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
8196 nt_errstr(status)));
8197 return;
8200 subreq = cli_close_send(state, state->ev, state->cli, fnum);
8201 if (tevent_req_nomem(subreq, req)) {
8202 return;
8204 tevent_req_set_callback(subreq, torture_createdel_closed, req);
8207 static void torture_createdel_closed(struct tevent_req *subreq)
8209 struct tevent_req *req = tevent_req_callback_data(
8210 subreq, struct tevent_req);
8211 NTSTATUS status;
8213 status = cli_close_recv(subreq);
8214 if (tevent_req_nterror(req, status)) {
8215 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
8216 return;
8218 tevent_req_done(req);
8221 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
8223 return tevent_req_simple_recv_ntstatus(req);
8226 struct torture_createdels_state {
8227 struct tevent_context *ev;
8228 struct cli_state *cli;
8229 const char *base_name;
8230 int sent;
8231 int received;
8232 int num_files;
8233 struct tevent_req **reqs;
8236 static void torture_createdels_done(struct tevent_req *subreq);
8238 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
8239 struct tevent_context *ev,
8240 struct cli_state *cli,
8241 const char *base_name,
8242 int num_parallel,
8243 int num_files)
8245 struct tevent_req *req;
8246 struct torture_createdels_state *state;
8247 int i;
8249 req = tevent_req_create(mem_ctx, &state,
8250 struct torture_createdels_state);
8251 if (req == NULL) {
8252 return NULL;
8254 state->ev = ev;
8255 state->cli = cli;
8256 state->base_name = talloc_strdup(state, base_name);
8257 if (tevent_req_nomem(state->base_name, req)) {
8258 return tevent_req_post(req, ev);
8260 state->num_files = MAX(num_parallel, num_files);
8261 state->sent = 0;
8262 state->received = 0;
8264 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
8265 if (tevent_req_nomem(state->reqs, req)) {
8266 return tevent_req_post(req, ev);
8269 for (i=0; i<num_parallel; i++) {
8270 char *name;
8272 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
8273 state->sent);
8274 if (tevent_req_nomem(name, req)) {
8275 return tevent_req_post(req, ev);
8277 state->reqs[i] = torture_createdel_send(
8278 state->reqs, state->ev, state->cli, name);
8279 if (tevent_req_nomem(state->reqs[i], req)) {
8280 return tevent_req_post(req, ev);
8282 name = talloc_move(state->reqs[i], &name);
8283 tevent_req_set_callback(state->reqs[i],
8284 torture_createdels_done, req);
8285 state->sent += 1;
8287 return req;
8290 static void torture_createdels_done(struct tevent_req *subreq)
8292 struct tevent_req *req = tevent_req_callback_data(
8293 subreq, struct tevent_req);
8294 struct torture_createdels_state *state = tevent_req_data(
8295 req, struct torture_createdels_state);
8296 size_t num_parallel = talloc_array_length(state->reqs);
8297 NTSTATUS status;
8298 char *name;
8299 int i;
8301 status = torture_createdel_recv(subreq);
8302 if (!NT_STATUS_IS_OK(status)){
8303 DEBUG(10, ("torture_createdel_recv returned %s\n",
8304 nt_errstr(status)));
8305 TALLOC_FREE(subreq);
8306 tevent_req_nterror(req, status);
8307 return;
8310 for (i=0; i<num_parallel; i++) {
8311 if (subreq == state->reqs[i]) {
8312 break;
8315 if (i == num_parallel) {
8316 DEBUG(10, ("received something we did not send\n"));
8317 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
8318 return;
8320 TALLOC_FREE(state->reqs[i]);
8322 if (state->sent >= state->num_files) {
8323 tevent_req_done(req);
8324 return;
8327 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
8328 state->sent);
8329 if (tevent_req_nomem(name, req)) {
8330 return;
8332 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
8333 state->cli, name);
8334 if (tevent_req_nomem(state->reqs[i], req)) {
8335 return;
8337 name = talloc_move(state->reqs[i], &name);
8338 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
8339 state->sent += 1;
8342 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
8344 return tevent_req_simple_recv_ntstatus(req);
8347 struct swallow_notify_state {
8348 struct tevent_context *ev;
8349 struct cli_state *cli;
8350 uint16_t fnum;
8351 uint32_t completion_filter;
8352 bool recursive;
8353 bool (*fn)(uint32_t action, const char *name, void *priv);
8354 void *priv;
8357 static void swallow_notify_done(struct tevent_req *subreq);
8359 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
8360 struct tevent_context *ev,
8361 struct cli_state *cli,
8362 uint16_t fnum,
8363 uint32_t completion_filter,
8364 bool recursive,
8365 bool (*fn)(uint32_t action,
8366 const char *name,
8367 void *priv),
8368 void *priv)
8370 struct tevent_req *req, *subreq;
8371 struct swallow_notify_state *state;
8373 req = tevent_req_create(mem_ctx, &state,
8374 struct swallow_notify_state);
8375 if (req == NULL) {
8376 return NULL;
8378 state->ev = ev;
8379 state->cli = cli;
8380 state->fnum = fnum;
8381 state->completion_filter = completion_filter;
8382 state->recursive = recursive;
8383 state->fn = fn;
8384 state->priv = priv;
8386 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
8387 0xffff, state->completion_filter,
8388 state->recursive);
8389 if (tevent_req_nomem(subreq, req)) {
8390 return tevent_req_post(req, ev);
8392 tevent_req_set_callback(subreq, swallow_notify_done, req);
8393 return req;
8396 static void swallow_notify_done(struct tevent_req *subreq)
8398 struct tevent_req *req = tevent_req_callback_data(
8399 subreq, struct tevent_req);
8400 struct swallow_notify_state *state = tevent_req_data(
8401 req, struct swallow_notify_state);
8402 NTSTATUS status;
8403 uint32_t i, num_changes;
8404 struct notify_change *changes;
8406 status = cli_notify_recv(subreq, state, &num_changes, &changes);
8407 TALLOC_FREE(subreq);
8408 if (!NT_STATUS_IS_OK(status)) {
8409 DEBUG(10, ("cli_notify_recv returned %s\n",
8410 nt_errstr(status)));
8411 tevent_req_nterror(req, status);
8412 return;
8415 for (i=0; i<num_changes; i++) {
8416 state->fn(changes[i].action, changes[i].name, state->priv);
8418 TALLOC_FREE(changes);
8420 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
8421 0xffff, state->completion_filter,
8422 state->recursive);
8423 if (tevent_req_nomem(subreq, req)) {
8424 return;
8426 tevent_req_set_callback(subreq, swallow_notify_done, req);
8429 static bool print_notifies(uint32_t action, const char *name, void *priv)
8431 if (DEBUGLEVEL > 5) {
8432 d_printf("%d %s\n", (int)action, name);
8434 return true;
8437 static void notify_bench_done(struct tevent_req *req)
8439 int *num_finished = (int *)tevent_req_callback_data_void(req);
8440 *num_finished += 1;
8443 static bool run_notify_bench(int dummy)
8445 const char *dname = "\\notify-bench";
8446 struct tevent_context *ev;
8447 NTSTATUS status;
8448 uint16_t dnum;
8449 struct tevent_req *req1;
8450 struct tevent_req *req2 = NULL;
8451 int i, num_unc_names;
8452 int num_finished = 0;
8454 printf("starting notify-bench test\n");
8456 if (use_multishare_conn) {
8457 char **unc_list;
8458 unc_list = file_lines_load(multishare_conn_fname,
8459 &num_unc_names, 0, NULL);
8460 if (!unc_list || num_unc_names <= 0) {
8461 d_printf("Failed to load unc names list from '%s'\n",
8462 multishare_conn_fname);
8463 return false;
8465 TALLOC_FREE(unc_list);
8466 } else {
8467 num_unc_names = 1;
8470 ev = samba_tevent_context_init(talloc_tos());
8471 if (ev == NULL) {
8472 d_printf("tevent_context_init failed\n");
8473 return false;
8476 for (i=0; i<num_unc_names; i++) {
8477 struct cli_state *cli;
8478 char *base_fname;
8480 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
8481 dname, i);
8482 if (base_fname == NULL) {
8483 return false;
8486 if (!torture_open_connection(&cli, i)) {
8487 return false;
8490 status = cli_ntcreate(cli, dname, 0,
8491 MAXIMUM_ALLOWED_ACCESS,
8492 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
8493 FILE_SHARE_DELETE,
8494 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
8495 &dnum, NULL);
8497 if (!NT_STATUS_IS_OK(status)) {
8498 d_printf("Could not create %s: %s\n", dname,
8499 nt_errstr(status));
8500 return false;
8503 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
8504 FILE_NOTIFY_CHANGE_FILE_NAME |
8505 FILE_NOTIFY_CHANGE_DIR_NAME |
8506 FILE_NOTIFY_CHANGE_ATTRIBUTES |
8507 FILE_NOTIFY_CHANGE_LAST_WRITE,
8508 false, print_notifies, NULL);
8509 if (req1 == NULL) {
8510 d_printf("Could not create notify request\n");
8511 return false;
8514 req2 = torture_createdels_send(talloc_tos(), ev, cli,
8515 base_fname, 10, torture_numops);
8516 if (req2 == NULL) {
8517 d_printf("Could not create createdels request\n");
8518 return false;
8520 TALLOC_FREE(base_fname);
8522 tevent_req_set_callback(req2, notify_bench_done,
8523 &num_finished);
8526 while (num_finished < num_unc_names) {
8527 int ret;
8528 ret = tevent_loop_once(ev);
8529 if (ret != 0) {
8530 d_printf("tevent_loop_once failed\n");
8531 return false;
8535 if (!tevent_req_poll(req2, ev)) {
8536 d_printf("tevent_req_poll failed\n");
8539 status = torture_createdels_recv(req2);
8540 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
8542 return true;
8545 static bool run_mangle1(int dummy)
8547 struct cli_state *cli;
8548 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
8549 uint16_t fnum;
8550 fstring alt_name;
8551 NTSTATUS status;
8552 time_t change_time, access_time, write_time;
8553 off_t size;
8554 uint16_t mode;
8556 printf("starting mangle1 test\n");
8557 if (!torture_open_connection(&cli, 0)) {
8558 return False;
8561 smbXcli_conn_set_sockopt(cli->conn, sockops);
8563 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8564 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8565 0, 0, &fnum, NULL);
8566 if (!NT_STATUS_IS_OK(status)) {
8567 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8568 return false;
8570 cli_close(cli, fnum);
8572 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
8573 if (!NT_STATUS_IS_OK(status)) {
8574 d_printf("cli_qpathinfo_alt_name failed: %s\n",
8575 nt_errstr(status));
8576 return false;
8578 d_printf("alt_name: %s\n", alt_name);
8580 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
8581 if (!NT_STATUS_IS_OK(status)) {
8582 d_printf("cli_openx(%s) failed: %s\n", alt_name,
8583 nt_errstr(status));
8584 return false;
8586 cli_close(cli, fnum);
8588 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
8589 &write_time, &size, &mode);
8590 if (!NT_STATUS_IS_OK(status)) {
8591 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
8592 nt_errstr(status));
8593 return false;
8596 return true;
8599 static NTSTATUS mangle_illegal_list_shortname_fn(const char *mntpoint,
8600 struct file_info *f,
8601 const char *mask,
8602 void *state)
8604 if (f->short_name == NULL) {
8605 return NT_STATUS_OK;
8608 if (strlen(f->short_name) == 0) {
8609 return NT_STATUS_OK;
8612 printf("unexpected shortname: %s\n", f->short_name);
8614 return NT_STATUS_OBJECT_NAME_INVALID;
8617 static NTSTATUS mangle_illegal_list_name_fn(const char *mntpoint,
8618 struct file_info *f,
8619 const char *mask,
8620 void *state)
8622 char *name = state;
8624 printf("name: %s\n", f->name);
8625 fstrcpy(name, f->name);
8626 return NT_STATUS_OK;
8629 static bool run_mangle_illegal(int dummy)
8631 struct cli_state *cli = NULL;
8632 struct cli_state *cli_posix = NULL;
8633 const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
8634 const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
8635 char *mangled_path = NULL;
8636 uint16_t fnum;
8637 fstring name;
8638 fstring alt_name;
8639 NTSTATUS status;
8641 printf("starting mangle-illegal test\n");
8643 if (!torture_open_connection(&cli, 0)) {
8644 return False;
8647 smbXcli_conn_set_sockopt(cli->conn, sockops);
8649 if (!torture_open_connection(&cli_posix, 0)) {
8650 return false;
8653 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
8655 status = torture_setup_unix_extensions(cli_posix);
8656 if (!NT_STATUS_IS_OK(status)) {
8657 return false;
8660 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
8661 status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
8662 if (!NT_STATUS_IS_OK(status)) {
8663 printf("mkdir1 failed : %s\n", nt_errstr(status));
8664 return False;
8668 * Create a file with illegal NTFS characters and test that we
8669 * get a usable mangled name
8672 cli_setatr(cli_posix, illegal_fname, 0, 0);
8673 cli_posix_unlink(cli_posix, illegal_fname);
8675 status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
8676 0600, &fnum);
8677 if (!NT_STATUS_IS_OK(status)) {
8678 printf("POSIX create of %s failed (%s)\n",
8679 illegal_fname, nt_errstr(status));
8680 return false;
8683 status = cli_close(cli_posix, fnum);
8684 if (!NT_STATUS_IS_OK(status)) {
8685 printf("close failed (%s)\n", nt_errstr(status));
8686 return false;
8689 status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
8690 if (!NT_STATUS_IS_OK(status)) {
8691 d_printf("cli_list failed: %s\n", nt_errstr(status));
8692 return false;
8695 mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
8696 if (mangled_path == NULL) {
8697 return false;
8700 status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
8701 if (!NT_STATUS_IS_OK(status)) {
8702 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
8703 TALLOC_FREE(mangled_path);
8704 return false;
8706 TALLOC_FREE(mangled_path);
8707 cli_close(cli, fnum);
8709 cli_setatr(cli_posix, illegal_fname, 0, 0);
8710 cli_posix_unlink(cli_posix, illegal_fname);
8713 * Create a file with a long name and check that we got *no* short name.
8716 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8717 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8718 0, 0, &fnum, NULL);
8719 if (!NT_STATUS_IS_OK(status)) {
8720 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8721 return false;
8723 cli_close(cli, fnum);
8725 status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
8726 if (!NT_STATUS_IS_OK(status)) {
8727 d_printf("cli_list failed\n");
8728 return false;
8731 cli_unlink(cli, fname, 0);
8732 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
8734 if (!torture_close_connection(cli_posix)) {
8735 return false;
8738 if (!torture_close_connection(cli)) {
8739 return false;
8742 return true;
8745 static size_t null_source(uint8_t *buf, size_t n, void *priv)
8747 size_t *to_pull = (size_t *)priv;
8748 size_t thistime = *to_pull;
8750 thistime = MIN(thistime, n);
8751 if (thistime == 0) {
8752 return 0;
8755 memset(buf, 0, thistime);
8756 *to_pull -= thistime;
8757 return thistime;
8760 static bool run_windows_write(int dummy)
8762 struct cli_state *cli1;
8763 uint16_t fnum;
8764 int i;
8765 bool ret = false;
8766 const char *fname = "\\writetest.txt";
8767 struct timeval start_time;
8768 double seconds;
8769 double kbytes;
8770 NTSTATUS status;
8772 printf("starting windows_write test\n");
8773 if (!torture_open_connection(&cli1, 0)) {
8774 return False;
8777 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
8778 if (!NT_STATUS_IS_OK(status)) {
8779 printf("open failed (%s)\n", nt_errstr(status));
8780 return False;
8783 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8785 start_time = timeval_current();
8787 for (i=0; i<torture_numops; i++) {
8788 uint8_t c = 0;
8789 off_t start = i * torture_blocksize;
8790 size_t to_pull = torture_blocksize - 1;
8792 status = cli_writeall(cli1, fnum, 0, &c,
8793 start + torture_blocksize - 1, 1, NULL);
8794 if (!NT_STATUS_IS_OK(status)) {
8795 printf("cli_write failed: %s\n", nt_errstr(status));
8796 goto fail;
8799 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
8800 null_source, &to_pull);
8801 if (!NT_STATUS_IS_OK(status)) {
8802 printf("cli_push returned: %s\n", nt_errstr(status));
8803 goto fail;
8807 seconds = timeval_elapsed(&start_time);
8808 kbytes = (double)torture_blocksize * torture_numops;
8809 kbytes /= 1024;
8811 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
8812 (double)seconds, (int)(kbytes/seconds));
8814 ret = true;
8815 fail:
8816 cli_close(cli1, fnum);
8817 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8818 torture_close_connection(cli1);
8819 return ret;
8822 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
8824 size_t max_pdu = 0x1FFFF;
8826 if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
8827 max_pdu = 0xFFFFFF;
8830 if (smb1cli_conn_signing_is_active(cli->conn)) {
8831 max_pdu = 0x1FFFF;
8834 if (smb1cli_conn_encryption_on(cli->conn)) {
8835 max_pdu = CLI_BUFFER_SIZE;
8838 if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
8839 len_requested &= 0xFFFF;
8842 return MIN(len_requested,
8843 max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
8846 static bool check_read_call(struct cli_state *cli,
8847 uint16_t fnum,
8848 uint8_t *buf,
8849 size_t len_requested)
8851 NTSTATUS status;
8852 struct tevent_req *subreq = NULL;
8853 ssize_t len_read = 0;
8854 size_t len_expected = 0;
8855 struct tevent_context *ev = NULL;
8857 ev = samba_tevent_context_init(talloc_tos());
8858 if (ev == NULL) {
8859 return false;
8862 subreq = cli_read_andx_send(talloc_tos(),
8864 cli,
8865 fnum,
8867 len_requested);
8869 if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
8870 return false;
8873 status = cli_read_andx_recv(subreq, &len_read, &buf);
8874 if (!NT_STATUS_IS_OK(status)) {
8875 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
8876 return false;
8879 TALLOC_FREE(subreq);
8880 TALLOC_FREE(ev);
8882 len_expected = calc_expected_return(cli, len_requested);
8884 if (len_expected > 0x10000 && len_read == 0x10000) {
8885 /* Windows servers only return a max of 0x10000,
8886 doesn't matter if you set CAP_LARGE_READX in
8887 the client sessionsetupX call or not. */
8888 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
8889 (unsigned int)len_requested);
8890 } else if (len_read != len_expected) {
8891 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
8892 (unsigned int)len_requested,
8893 (unsigned int)len_read,
8894 (unsigned int)len_expected);
8895 return false;
8896 } else {
8897 d_printf("Correct read reply.\n");
8900 return true;
8903 /* Test large readX variants. */
8904 static bool large_readx_tests(struct cli_state *cli,
8905 uint16_t fnum,
8906 uint8_t *buf)
8908 /* A read of 0xFFFF0001 should *always* return 1 byte. */
8909 if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
8910 return false;
8912 /* A read of 0x10000 should return 0x10000 bytes. */
8913 if (check_read_call(cli, fnum, buf, 0x10000) == false) {
8914 return false;
8916 /* A read of 0x10000 should return 0x10001 bytes. */
8917 if (check_read_call(cli, fnum, buf, 0x10001) == false) {
8918 return false;
8920 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
8921 the requested number of bytes. */
8922 if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
8923 return false;
8925 /* A read of 1MB should return 1MB bytes (on Samba). */
8926 if (check_read_call(cli, fnum, buf, 0x100000) == false) {
8927 return false;
8930 if (check_read_call(cli, fnum, buf, 0x20001) == false) {
8931 return false;
8933 if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
8934 return false;
8936 if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
8937 return false;
8939 return true;
8942 static bool run_large_readx(int dummy)
8944 uint8_t *buf = NULL;
8945 struct cli_state *cli1 = NULL;
8946 struct cli_state *cli2 = NULL;
8947 bool correct = false;
8948 const char *fname = "\\large_readx.dat";
8949 NTSTATUS status;
8950 uint16_t fnum1 = UINT16_MAX;
8951 uint32_t normal_caps = 0;
8952 size_t file_size = 20*1024*1024;
8953 TALLOC_CTX *frame = talloc_stackframe();
8954 size_t i;
8955 struct {
8956 const char *name;
8957 enum smb_signing_setting signing_setting;
8958 enum protocol_types protocol;
8959 } runs[] = {
8961 .name = "NT1",
8962 .signing_setting = SMB_SIGNING_IF_REQUIRED,
8963 .protocol = PROTOCOL_NT1,
8965 .name = "NT1 - SIGNING_REQUIRED",
8966 .signing_setting = SMB_SIGNING_REQUIRED,
8967 .protocol = PROTOCOL_NT1,
8971 printf("starting large_readx test\n");
8973 if (!torture_open_connection(&cli1, 0)) {
8974 goto out;
8977 normal_caps = smb1cli_conn_capabilities(cli1->conn);
8979 if (!(normal_caps & CAP_LARGE_READX)) {
8980 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
8981 (unsigned int)normal_caps);
8982 goto out;
8985 /* Create a file of size 4MB. */
8986 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
8987 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8988 0, 0, &fnum1, NULL);
8990 if (!NT_STATUS_IS_OK(status)) {
8991 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8992 goto out;
8995 /* Write file_size bytes. */
8996 buf = talloc_zero_array(frame, uint8_t, file_size);
8997 if (buf == NULL) {
8998 goto out;
9001 status = cli_writeall(cli1,
9002 fnum1,
9004 buf,
9006 file_size,
9007 NULL);
9008 if (!NT_STATUS_IS_OK(status)) {
9009 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
9010 goto out;
9013 status = cli_close(cli1, fnum1);
9014 if (!NT_STATUS_IS_OK(status)) {
9015 d_printf("cli_close failed: %s\n", nt_errstr(status));
9016 goto out;
9019 fnum1 = UINT16_MAX;
9021 for (i=0; i < ARRAY_SIZE(runs); i++) {
9022 enum smb_signing_setting saved_signing_setting = signing_state;
9023 uint16_t fnum2 = -1;
9025 if (do_encrypt &&
9026 (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
9028 d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
9029 continue;
9032 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
9034 signing_state = runs[i].signing_setting;
9035 cli2 = open_nbt_connection();
9036 signing_state = saved_signing_setting;
9037 if (cli2 == NULL) {
9038 goto out;
9041 status = smbXcli_negprot(cli2->conn,
9042 cli2->timeout,
9043 runs[i].protocol,
9044 runs[i].protocol);
9045 if (!NT_STATUS_IS_OK(status)) {
9046 goto out;
9049 status = cli_session_setup_creds(cli2, torture_creds);
9050 if (!NT_STATUS_IS_OK(status)) {
9051 goto out;
9054 status = cli_tree_connect(cli2,
9055 share,
9056 "?????",
9057 password);
9058 if (!NT_STATUS_IS_OK(status)) {
9059 goto out;
9062 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
9064 normal_caps = smb1cli_conn_capabilities(cli2->conn);
9066 if (!(normal_caps & CAP_LARGE_READX)) {
9067 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
9068 (unsigned int)normal_caps);
9069 goto out;
9072 if (do_encrypt) {
9073 if (force_cli_encryption(cli2, share) == false) {
9074 goto out;
9076 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
9077 uint16_t major, minor;
9078 uint32_t caplow, caphigh;
9080 status = cli_unix_extensions_version(cli2,
9081 &major, &minor,
9082 &caplow, &caphigh);
9083 if (!NT_STATUS_IS_OK(status)) {
9084 goto out;
9088 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
9089 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
9090 0, 0, &fnum2, NULL);
9091 if (!NT_STATUS_IS_OK(status)) {
9092 d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
9093 goto out;
9096 /* All reads must return less than file_size bytes. */
9097 if (!large_readx_tests(cli2, fnum2, buf)) {
9098 goto out;
9101 status = cli_close(cli2, fnum2);
9102 if (!NT_STATUS_IS_OK(status)) {
9103 d_printf("cli_close failed: %s\n", nt_errstr(status));
9104 goto out;
9106 fnum2 = -1;
9108 if (!torture_close_connection(cli2)) {
9109 goto out;
9111 cli2 = NULL;
9114 correct = true;
9115 printf("Success on large_readx test\n");
9117 out:
9119 if (cli2) {
9120 if (!torture_close_connection(cli2)) {
9121 correct = false;
9125 if (cli1) {
9126 if (fnum1 != UINT16_MAX) {
9127 status = cli_close(cli1, fnum1);
9128 if (!NT_STATUS_IS_OK(status)) {
9129 d_printf("cli_close failed: %s\n", nt_errstr(status));
9131 fnum1 = UINT16_MAX;
9134 status = cli_unlink(cli1, fname,
9135 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9136 if (!NT_STATUS_IS_OK(status)) {
9137 printf("unlink failed (%s)\n", nt_errstr(status));
9140 if (!torture_close_connection(cli1)) {
9141 correct = false;
9145 TALLOC_FREE(frame);
9147 printf("finished large_readx test\n");
9148 return correct;
9151 static bool run_cli_echo(int dummy)
9153 struct cli_state *cli;
9154 NTSTATUS status;
9156 printf("starting cli_echo test\n");
9157 if (!torture_open_connection(&cli, 0)) {
9158 return false;
9160 smbXcli_conn_set_sockopt(cli->conn, sockops);
9162 status = cli_echo(cli, 5, data_blob_const("hello", 5));
9164 d_printf("cli_echo returned %s\n", nt_errstr(status));
9166 torture_close_connection(cli);
9167 return NT_STATUS_IS_OK(status);
9170 static bool run_uid_regression_test(int dummy)
9172 static struct cli_state *cli;
9173 int16_t old_vuid;
9174 int32_t old_cnum;
9175 bool correct = True;
9176 struct smbXcli_tcon *orig_tcon = NULL;
9177 NTSTATUS status;
9179 printf("starting uid regression test\n");
9181 if (!torture_open_connection(&cli, 0)) {
9182 return False;
9185 smbXcli_conn_set_sockopt(cli->conn, sockops);
9187 /* Ok - now save then logoff our current user. */
9188 old_vuid = cli_state_get_uid(cli);
9190 status = cli_ulogoff(cli);
9191 if (!NT_STATUS_IS_OK(status)) {
9192 d_printf("(%s) cli_ulogoff failed: %s\n",
9193 __location__, nt_errstr(status));
9194 correct = false;
9195 goto out;
9198 cli_state_set_uid(cli, old_vuid);
9200 /* Try an operation. */
9201 status = cli_mkdir(cli, "\\uid_reg_test");
9202 if (NT_STATUS_IS_OK(status)) {
9203 d_printf("(%s) cli_mkdir succeeded\n",
9204 __location__);
9205 correct = false;
9206 goto out;
9207 } else {
9208 /* Should be bad uid. */
9209 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
9210 NT_STATUS_USER_SESSION_DELETED)) {
9211 correct = false;
9212 goto out;
9216 old_cnum = cli_state_get_tid(cli);
9217 orig_tcon = cli_state_save_tcon(cli);
9218 if (orig_tcon == NULL) {
9219 correct = false;
9220 goto out;
9223 /* Now try a SMBtdis with the invald vuid set to zero. */
9224 cli_state_set_uid(cli, 0);
9226 /* This should succeed. */
9227 status = cli_tdis(cli);
9229 if (NT_STATUS_IS_OK(status)) {
9230 d_printf("First tdis with invalid vuid should succeed.\n");
9231 } else {
9232 d_printf("First tdis failed (%s)\n", nt_errstr(status));
9233 correct = false;
9234 cli_state_restore_tcon(cli, orig_tcon);
9235 goto out;
9238 cli_state_restore_tcon(cli, orig_tcon);
9239 cli_state_set_uid(cli, old_vuid);
9240 cli_state_set_tid(cli, old_cnum);
9242 /* This should fail. */
9243 status = cli_tdis(cli);
9244 if (NT_STATUS_IS_OK(status)) {
9245 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
9246 correct = false;
9247 goto out;
9248 } else {
9249 /* Should be bad tid. */
9250 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
9251 NT_STATUS_NETWORK_NAME_DELETED)) {
9252 correct = false;
9253 goto out;
9257 cli_rmdir(cli, "\\uid_reg_test");
9259 out:
9261 cli_shutdown(cli);
9262 return correct;
9266 static const char *illegal_chars = "*\\/?<>|\":";
9267 static char force_shortname_chars[] = " +,.[];=\177";
9269 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
9270 const char *mask, void *state)
9272 struct cli_state *pcli = (struct cli_state *)state;
9273 fstring fname;
9274 NTSTATUS status = NT_STATUS_OK;
9276 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
9278 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9279 return NT_STATUS_OK;
9281 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
9282 status = cli_rmdir(pcli, fname);
9283 if (!NT_STATUS_IS_OK(status)) {
9284 printf("del_fn: failed to rmdir %s\n,", fname );
9286 } else {
9287 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9288 if (!NT_STATUS_IS_OK(status)) {
9289 printf("del_fn: failed to unlink %s\n,", fname );
9292 return status;
9295 struct sn_state {
9296 int matched;
9297 int i;
9298 bool val;
9301 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
9302 const char *name, void *state)
9304 struct sn_state *s = (struct sn_state *)state;
9305 int i = s->i;
9307 #if 0
9308 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
9309 i, finfo->name, finfo->short_name);
9310 #endif
9312 if (strchr(force_shortname_chars, i)) {
9313 if (!finfo->short_name) {
9314 /* Shortname not created when it should be. */
9315 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
9316 __location__, finfo->name, i);
9317 s->val = true;
9319 } else if (finfo->short_name){
9320 /* Shortname created when it should not be. */
9321 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
9322 __location__, finfo->short_name, finfo->name);
9323 s->val = true;
9325 s->matched += 1;
9326 return NT_STATUS_OK;
9329 static bool run_shortname_test(int dummy)
9331 static struct cli_state *cli;
9332 bool correct = True;
9333 int i;
9334 struct sn_state s;
9335 char fname[40];
9336 NTSTATUS status;
9338 printf("starting shortname test\n");
9340 if (!torture_open_connection(&cli, 0)) {
9341 return False;
9344 smbXcli_conn_set_sockopt(cli->conn, sockops);
9346 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
9347 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
9348 cli_rmdir(cli, "\\shortname");
9350 status = cli_mkdir(cli, "\\shortname");
9351 if (!NT_STATUS_IS_OK(status)) {
9352 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
9353 __location__, nt_errstr(status));
9354 correct = false;
9355 goto out;
9358 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
9359 correct = false;
9360 goto out;
9362 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
9363 correct = false;
9364 goto out;
9367 s.val = false;
9369 for (i = 32; i < 128; i++) {
9370 uint16_t fnum = (uint16_t)-1;
9372 s.i = i;
9374 if (strchr(illegal_chars, i)) {
9375 continue;
9377 fname[15] = i;
9379 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
9380 FILE_SHARE_READ|FILE_SHARE_WRITE,
9381 FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
9382 if (!NT_STATUS_IS_OK(status)) {
9383 d_printf("(%s) cli_nt_create of %s failed: %s\n",
9384 __location__, fname, nt_errstr(status));
9385 correct = false;
9386 goto out;
9388 cli_close(cli, fnum);
9390 s.matched = 0;
9391 status = cli_list(cli, "\\shortname\\test*.*", 0,
9392 shortname_list_fn, &s);
9393 if (s.matched != 1) {
9394 d_printf("(%s) failed to list %s: %s\n",
9395 __location__, fname, nt_errstr(status));
9396 correct = false;
9397 goto out;
9400 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9401 if (!NT_STATUS_IS_OK(status)) {
9402 d_printf("(%s) failed to delete %s: %s\n",
9403 __location__, fname, nt_errstr(status));
9404 correct = false;
9405 goto out;
9408 if (s.val) {
9409 correct = false;
9410 goto out;
9414 out:
9416 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
9417 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
9418 cli_rmdir(cli, "\\shortname");
9419 torture_close_connection(cli);
9420 return correct;
9423 static void pagedsearch_cb(struct tevent_req *req)
9425 TLDAPRC rc;
9426 struct tldap_message *msg;
9427 char *dn;
9429 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
9430 if (!TLDAP_RC_IS_SUCCESS(rc)) {
9431 d_printf("tldap_search_paged_recv failed: %s\n",
9432 tldap_rc2string(rc));
9433 return;
9435 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
9436 TALLOC_FREE(msg);
9437 return;
9439 if (!tldap_entry_dn(msg, &dn)) {
9440 d_printf("tldap_entry_dn failed\n");
9441 return;
9443 d_printf("%s\n", dn);
9444 TALLOC_FREE(msg);
9447 static bool run_tldap(int dummy)
9449 struct tldap_context *ld;
9450 int fd;
9451 TLDAPRC rc;
9452 NTSTATUS status;
9453 struct sockaddr_storage addr;
9454 struct tevent_context *ev;
9455 struct tevent_req *req;
9456 char *basedn;
9457 const char *filter;
9459 if (!resolve_name(host, &addr, 0, false)) {
9460 d_printf("could not find host %s\n", host);
9461 return false;
9463 status = open_socket_out(&addr, 389, 9999, &fd);
9464 if (!NT_STATUS_IS_OK(status)) {
9465 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
9466 return false;
9469 ld = tldap_context_create(talloc_tos(), fd);
9470 if (ld == NULL) {
9471 close(fd);
9472 d_printf("tldap_context_create failed\n");
9473 return false;
9476 rc = tldap_fetch_rootdse(ld);
9477 if (!TLDAP_RC_IS_SUCCESS(rc)) {
9478 d_printf("tldap_fetch_rootdse failed: %s\n",
9479 tldap_errstr(talloc_tos(), ld, rc));
9480 return false;
9483 basedn = tldap_talloc_single_attribute(
9484 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
9485 if (basedn == NULL) {
9486 d_printf("no defaultNamingContext\n");
9487 return false;
9489 d_printf("defaultNamingContext: %s\n", basedn);
9491 ev = samba_tevent_context_init(talloc_tos());
9492 if (ev == NULL) {
9493 d_printf("tevent_context_init failed\n");
9494 return false;
9497 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
9498 TLDAP_SCOPE_SUB, "(objectclass=*)",
9499 NULL, 0, 0,
9500 NULL, 0, NULL, 0, 0, 0, 0, 5);
9501 if (req == NULL) {
9502 d_printf("tldap_search_paged_send failed\n");
9503 return false;
9505 tevent_req_set_callback(req, pagedsearch_cb, NULL);
9507 tevent_req_poll(req, ev);
9509 TALLOC_FREE(req);
9511 /* test search filters against rootDSE */
9512 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
9513 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
9515 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
9516 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
9517 talloc_tos(), NULL);
9518 if (!TLDAP_RC_IS_SUCCESS(rc)) {
9519 d_printf("tldap_search with complex filter failed: %s\n",
9520 tldap_errstr(talloc_tos(), ld, rc));
9521 return false;
9524 TALLOC_FREE(ld);
9525 return true;
9528 /* Torture test to ensure no regression of :
9529 https://bugzilla.samba.org/show_bug.cgi?id=7084
9532 static bool run_dir_createtime(int dummy)
9534 struct cli_state *cli;
9535 const char *dname = "\\testdir";
9536 const char *fname = "\\testdir\\testfile";
9537 NTSTATUS status;
9538 struct timespec create_time;
9539 struct timespec create_time1;
9540 uint16_t fnum;
9541 bool ret = false;
9543 if (!torture_open_connection(&cli, 0)) {
9544 return false;
9547 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9548 cli_rmdir(cli, dname);
9550 status = cli_mkdir(cli, dname);
9551 if (!NT_STATUS_IS_OK(status)) {
9552 printf("mkdir failed: %s\n", nt_errstr(status));
9553 goto out;
9556 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
9557 NULL, NULL, NULL);
9558 if (!NT_STATUS_IS_OK(status)) {
9559 printf("cli_qpathinfo2 returned %s\n",
9560 nt_errstr(status));
9561 goto out;
9564 /* Sleep 3 seconds, then create a file. */
9565 sleep(3);
9567 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
9568 DENY_NONE, &fnum);
9569 if (!NT_STATUS_IS_OK(status)) {
9570 printf("cli_openx failed: %s\n", nt_errstr(status));
9571 goto out;
9574 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
9575 NULL, NULL, NULL);
9576 if (!NT_STATUS_IS_OK(status)) {
9577 printf("cli_qpathinfo2 (2) returned %s\n",
9578 nt_errstr(status));
9579 goto out;
9582 if (timespec_compare(&create_time1, &create_time)) {
9583 printf("run_dir_createtime: create time was updated (error)\n");
9584 } else {
9585 printf("run_dir_createtime: create time was not updated (correct)\n");
9586 ret = true;
9589 out:
9591 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9592 cli_rmdir(cli, dname);
9593 if (!torture_close_connection(cli)) {
9594 ret = false;
9596 return ret;
9600 static bool run_streamerror(int dummy)
9602 struct cli_state *cli;
9603 const char *dname = "\\testdir";
9604 const char *streamname =
9605 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
9606 NTSTATUS status;
9607 time_t change_time, access_time, write_time;
9608 off_t size;
9609 uint16_t mode, fnum;
9610 bool ret = true;
9612 if (!torture_open_connection(&cli, 0)) {
9613 return false;
9616 cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9617 cli_rmdir(cli, dname);
9619 status = cli_mkdir(cli, dname);
9620 if (!NT_STATUS_IS_OK(status)) {
9621 printf("mkdir failed: %s\n", nt_errstr(status));
9622 return false;
9625 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
9626 &write_time, &size, &mode);
9627 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
9628 printf("pathinfo returned %s, expected "
9629 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
9630 nt_errstr(status));
9631 ret = false;
9634 status = cli_ntcreate(cli, streamname, 0x16,
9635 FILE_READ_DATA|FILE_READ_EA|
9636 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
9637 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
9638 FILE_OPEN, 0, 0, &fnum, NULL);
9640 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
9641 printf("ntcreate returned %s, expected "
9642 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
9643 nt_errstr(status));
9644 ret = false;
9648 cli_rmdir(cli, dname);
9649 return ret;
9652 struct pidtest_state {
9653 bool success;
9654 uint16_t vwv[1];
9655 DATA_BLOB data;
9658 static void pid_echo_done(struct tevent_req *subreq);
9660 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
9661 struct tevent_context *ev,
9662 struct cli_state *cli)
9664 struct tevent_req *req, *subreq;
9665 struct pidtest_state *state;
9667 req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
9668 if (req == NULL) {
9669 return NULL;
9672 SSVAL(state->vwv, 0, 1);
9673 state->data = data_blob_const("hello", 5);
9675 subreq = smb1cli_req_send(state,
9677 cli->conn,
9678 SMBecho,
9679 0, 0, /* *_flags */
9680 0, 0, /* *_flags2 */
9681 cli->timeout,
9682 0xDEADBEEF, /* pid */
9683 NULL, /* tcon */
9684 NULL, /* session */
9685 ARRAY_SIZE(state->vwv), state->vwv,
9686 state->data.length, state->data.data);
9688 if (tevent_req_nomem(subreq, req)) {
9689 return tevent_req_post(req, ev);
9691 tevent_req_set_callback(subreq, pid_echo_done, req);
9692 return req;
9695 static void pid_echo_done(struct tevent_req *subreq)
9697 struct tevent_req *req = tevent_req_callback_data(
9698 subreq, struct tevent_req);
9699 struct pidtest_state *state = tevent_req_data(
9700 req, struct pidtest_state);
9701 NTSTATUS status;
9702 uint32_t num_bytes;
9703 uint8_t *bytes = NULL;
9704 struct iovec *recv_iov = NULL;
9705 uint8_t *phdr = NULL;
9706 uint16_t pidlow = 0;
9707 uint16_t pidhigh = 0;
9708 struct smb1cli_req_expected_response expected[] = {
9710 .status = NT_STATUS_OK,
9711 .wct = 1,
9715 status = smb1cli_req_recv(subreq, state,
9716 &recv_iov,
9717 &phdr,
9718 NULL, /* pwct */
9719 NULL, /* pvwv */
9720 NULL, /* pvwv_offset */
9721 &num_bytes,
9722 &bytes,
9723 NULL, /* pbytes_offset */
9724 NULL, /* pinbuf */
9725 expected, ARRAY_SIZE(expected));
9727 TALLOC_FREE(subreq);
9729 if (!NT_STATUS_IS_OK(status)) {
9730 tevent_req_nterror(req, status);
9731 return;
9734 if (num_bytes != state->data.length) {
9735 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9736 return;
9739 if (memcmp(bytes, state->data.data, num_bytes) != 0) {
9740 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9741 return;
9744 /* Check pid low/high == DEADBEEF */
9745 pidlow = SVAL(phdr, HDR_PID);
9746 if (pidlow != 0xBEEF){
9747 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
9748 (unsigned int)pidlow);
9749 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9750 return;
9752 pidhigh = SVAL(phdr, HDR_PIDHIGH);
9753 if (pidhigh != 0xDEAD){
9754 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
9755 (unsigned int)pidhigh);
9756 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9757 return;
9760 tevent_req_done(req);
9763 static NTSTATUS pid_echo_recv(struct tevent_req *req)
9765 return tevent_req_simple_recv_ntstatus(req);
9768 static bool run_pidhigh(int dummy)
9770 bool success = false;
9771 struct cli_state *cli = NULL;
9772 NTSTATUS status;
9773 struct tevent_context *ev = NULL;
9774 struct tevent_req *req = NULL;
9775 TALLOC_CTX *frame = talloc_stackframe();
9777 printf("starting pid high test\n");
9778 if (!torture_open_connection(&cli, 0)) {
9779 return false;
9781 smbXcli_conn_set_sockopt(cli->conn, sockops);
9783 ev = samba_tevent_context_init(frame);
9784 if (ev == NULL) {
9785 goto fail;
9788 req = pid_echo_send(frame, ev, cli);
9789 if (req == NULL) {
9790 goto fail;
9793 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
9794 goto fail;
9797 status = pid_echo_recv(req);
9798 if (NT_STATUS_IS_OK(status)) {
9799 printf("pid high test ok\n");
9800 success = true;
9803 fail:
9805 TALLOC_FREE(frame);
9806 torture_close_connection(cli);
9807 return success;
9811 Test Windows open on a bad POSIX symlink.
9813 static bool run_symlink_open_test(int dummy)
9815 static struct cli_state *cli;
9816 const char *fname = "non_existant_file";
9817 const char *sname = "dangling_symlink";
9818 uint16_t fnum = (uint16_t)-1;
9819 bool correct = false;
9820 NTSTATUS status;
9821 TALLOC_CTX *frame = NULL;
9823 frame = talloc_stackframe();
9825 printf("Starting Windows bad symlink open test\n");
9827 if (!torture_open_connection(&cli, 0)) {
9828 TALLOC_FREE(frame);
9829 return false;
9832 smbXcli_conn_set_sockopt(cli->conn, sockops);
9834 status = torture_setup_unix_extensions(cli);
9835 if (!NT_STATUS_IS_OK(status)) {
9836 TALLOC_FREE(frame);
9837 return false;
9840 /* Ensure nothing exists. */
9841 cli_setatr(cli, fname, 0, 0);
9842 cli_posix_unlink(cli, fname);
9843 cli_setatr(cli, sname, 0, 0);
9844 cli_posix_unlink(cli, sname);
9846 /* Create a symlink pointing nowhere. */
9847 status = cli_posix_symlink(cli, fname, sname);
9848 if (!NT_STATUS_IS_OK(status)) {
9849 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
9850 sname,
9851 fname,
9852 nt_errstr(status));
9853 goto out;
9856 /* Now ensure that a Windows open doesn't hang. */
9857 status = cli_ntcreate(cli,
9858 sname,
9860 FILE_READ_DATA|FILE_WRITE_DATA,
9862 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9863 FILE_OPEN_IF,
9864 0x0,
9865 0x0,
9866 &fnum,
9867 NULL);
9870 * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
9871 * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
9872 * we use O_NOFOLLOW on the server or not.
9874 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
9875 NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
9877 correct = true;
9878 } else {
9879 printf("cli_ntcreate of %s returned %s - should return"
9880 " either (%s) or (%s)\n",
9881 sname,
9882 nt_errstr(status),
9883 nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
9884 nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
9885 goto out;
9888 correct = true;
9890 out:
9892 if (fnum != (uint16_t)-1) {
9893 cli_close(cli, fnum);
9894 fnum = (uint16_t)-1;
9897 cli_setatr(cli, sname, 0, 0);
9898 cli_posix_unlink(cli, sname);
9899 cli_setatr(cli, fname, 0, 0);
9900 cli_posix_unlink(cli, fname);
9902 if (!torture_close_connection(cli)) {
9903 correct = false;
9906 TALLOC_FREE(frame);
9907 return correct;
9911 * Only testing minimal time strings, as the others
9912 * need (locale-dependent) guessing at what strftime does and
9913 * even may differ in builds.
9915 static bool timesubst_test(void)
9917 TALLOC_CTX *ctx = NULL;
9918 /* Sa 23. Dez 04:33:20 CET 2017 */
9919 const struct timeval tv = { 1514000000, 123 };
9920 const char* expect_minimal = "20171223_033320";
9921 const char* expect_minus = "20171223_033320_000123";
9922 char *s;
9923 char *env_tz, *orig_tz = NULL;
9924 bool result = true;
9926 ctx = talloc_new(NULL);
9928 env_tz = getenv("TZ");
9929 if(env_tz) {
9930 orig_tz = talloc_strdup(ctx, env_tz);
9932 setenv("TZ", "UTC", 1);
9934 s = minimal_timeval_string(ctx, &tv, false);
9936 if(!s || strcmp(s, expect_minimal)) {
9937 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
9938 "[%s]\n", s ? s : "<nil>", expect_minimal);
9939 result = false;
9941 TALLOC_FREE(s);
9942 s = minimal_timeval_string(ctx, &tv, true);
9943 if(!s || strcmp(s, expect_minus)) {
9944 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
9945 "[%s]\n", s ? s : "<nil>", expect_minus);
9946 result = false;
9948 TALLOC_FREE(s);
9950 if(orig_tz) {
9951 setenv("TZ", orig_tz, 1);
9954 TALLOC_FREE(ctx);
9955 return result;
9958 static bool run_local_substitute(int dummy)
9960 bool ok = true;
9962 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
9963 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
9964 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
9965 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
9966 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
9967 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
9968 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
9969 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
9970 ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
9971 /* Substitution depends on current time, so better test the underlying
9972 formatting function. At least covers %t. */
9973 ok &= timesubst_test();
9975 /* Different captialization rules in sub_basic... */
9977 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
9978 "blaDOM") == 0);
9980 return ok;
9983 static bool run_local_base64(int dummy)
9985 int i;
9986 bool ret = true;
9988 for (i=1; i<2000; i++) {
9989 DATA_BLOB blob1, blob2;
9990 char *b64;
9992 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
9993 blob1.length = i;
9994 generate_random_buffer(blob1.data, blob1.length);
9996 b64 = base64_encode_data_blob(talloc_tos(), blob1);
9997 if (b64 == NULL) {
9998 d_fprintf(stderr, "base64_encode_data_blob failed "
9999 "for %d bytes\n", i);
10000 ret = false;
10002 blob2 = base64_decode_data_blob(b64);
10003 TALLOC_FREE(b64);
10005 if (data_blob_cmp(&blob1, &blob2)) {
10006 d_fprintf(stderr, "data_blob_cmp failed for %d "
10007 "bytes\n", i);
10008 ret = false;
10010 TALLOC_FREE(blob1.data);
10011 data_blob_free(&blob2);
10013 return ret;
10016 static void parse_fn(time_t timeout, DATA_BLOB blob, void *private_data)
10018 return;
10021 static bool run_local_gencache(int dummy)
10023 char *val;
10024 time_t tm;
10025 DATA_BLOB blob;
10026 char v;
10027 struct memcache *mem;
10028 int i;
10030 mem = memcache_init(NULL, 0);
10031 if (mem == NULL) {
10032 d_printf("%s: memcache_init failed\n", __location__);
10033 return false;
10035 memcache_set_global(mem);
10037 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
10038 d_printf("%s: gencache_set() failed\n", __location__);
10039 return False;
10042 if (!gencache_get("foo", NULL, NULL, NULL)) {
10043 d_printf("%s: gencache_get() failed\n", __location__);
10044 return False;
10047 for (i=0; i<1000000; i++) {
10048 gencache_parse("foo", parse_fn, NULL);
10051 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
10052 d_printf("%s: gencache_get() failed\n", __location__);
10053 return False;
10055 TALLOC_FREE(val);
10057 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
10058 d_printf("%s: gencache_get() failed\n", __location__);
10059 return False;
10062 if (strcmp(val, "bar") != 0) {
10063 d_printf("%s: gencache_get() returned %s, expected %s\n",
10064 __location__, val, "bar");
10065 TALLOC_FREE(val);
10066 return False;
10069 TALLOC_FREE(val);
10071 if (!gencache_del("foo")) {
10072 d_printf("%s: gencache_del() failed\n", __location__);
10073 return False;
10075 if (gencache_del("foo")) {
10076 d_printf("%s: second gencache_del() succeeded\n",
10077 __location__);
10078 return False;
10081 if (gencache_get("foo", talloc_tos(), &val, &tm)) {
10082 d_printf("%s: gencache_get() on deleted entry "
10083 "succeeded\n", __location__);
10084 return False;
10087 blob = data_blob_string_const_null("bar");
10088 tm = time(NULL) + 60;
10090 if (!gencache_set_data_blob("foo", blob, tm)) {
10091 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
10092 return False;
10095 if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
10096 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
10097 return False;
10100 if (strcmp((const char *)blob.data, "bar") != 0) {
10101 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
10102 __location__, (const char *)blob.data, "bar");
10103 data_blob_free(&blob);
10104 return False;
10107 data_blob_free(&blob);
10109 if (!gencache_del("foo")) {
10110 d_printf("%s: gencache_del() failed\n", __location__);
10111 return False;
10113 if (gencache_del("foo")) {
10114 d_printf("%s: second gencache_del() succeeded\n",
10115 __location__);
10116 return False;
10119 if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
10120 d_printf("%s: gencache_get_data_blob() on deleted entry "
10121 "succeeded\n", __location__);
10122 return False;
10125 v = 1;
10126 blob.data = (uint8_t *)&v;
10127 blob.length = sizeof(v);
10129 if (!gencache_set_data_blob("blob", blob, tm)) {
10130 d_printf("%s: gencache_set_data_blob() failed\n",
10131 __location__);
10132 return false;
10134 if (gencache_get("blob", talloc_tos(), &val, &tm)) {
10135 d_printf("%s: gencache_get succeeded\n", __location__);
10136 return false;
10139 return True;
10142 static bool rbt_testval(struct db_context *db, const char *key,
10143 const char *value)
10145 struct db_record *rec;
10146 TDB_DATA data = string_tdb_data(value);
10147 bool ret = false;
10148 NTSTATUS status;
10149 TDB_DATA dbvalue;
10151 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
10152 if (rec == NULL) {
10153 d_fprintf(stderr, "fetch_locked failed\n");
10154 goto done;
10156 status = dbwrap_record_store(rec, data, 0);
10157 if (!NT_STATUS_IS_OK(status)) {
10158 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
10159 goto done;
10161 TALLOC_FREE(rec);
10163 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
10164 if (rec == NULL) {
10165 d_fprintf(stderr, "second fetch_locked failed\n");
10166 goto done;
10169 dbvalue = dbwrap_record_get_value(rec);
10170 if ((dbvalue.dsize != data.dsize)
10171 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
10172 d_fprintf(stderr, "Got wrong data back\n");
10173 goto done;
10176 ret = true;
10177 done:
10178 TALLOC_FREE(rec);
10179 return ret;
10182 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
10184 int *count2 = (int *)private_data;
10185 (*count2)++;
10186 return 0;
10189 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
10191 int *count2 = (int *)private_data;
10192 (*count2)++;
10193 dbwrap_record_delete(rec);
10194 return 0;
10197 static bool run_local_rbtree(int dummy)
10199 struct db_context *db;
10200 bool ret = false;
10201 int i;
10202 NTSTATUS status;
10203 int count = 0;
10204 int count2 = 0;
10206 db = db_open_rbt(NULL);
10208 if (db == NULL) {
10209 d_fprintf(stderr, "db_open_rbt failed\n");
10210 return false;
10213 for (i=0; i<1000; i++) {
10214 char *key, *value;
10216 if (asprintf(&key, "key%ld", random()) == -1) {
10217 goto done;
10219 if (asprintf(&value, "value%ld", random()) == -1) {
10220 SAFE_FREE(key);
10221 goto done;
10224 if (!rbt_testval(db, key, value)) {
10225 SAFE_FREE(key);
10226 SAFE_FREE(value);
10227 goto done;
10230 SAFE_FREE(value);
10231 if (asprintf(&value, "value%ld", random()) == -1) {
10232 SAFE_FREE(key);
10233 goto done;
10236 if (!rbt_testval(db, key, value)) {
10237 SAFE_FREE(key);
10238 SAFE_FREE(value);
10239 goto done;
10242 SAFE_FREE(key);
10243 SAFE_FREE(value);
10246 ret = true;
10247 count = 0; count2 = 0;
10248 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
10249 &count2, &count);
10250 printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10251 if ((count != count2) || (count != 1000)) {
10252 ret = false;
10254 count = 0; count2 = 0;
10255 status = dbwrap_traverse(db, local_rbtree_traverse_delete,
10256 &count2, &count);
10257 printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10258 if ((count != count2) || (count != 1000)) {
10259 ret = false;
10261 count = 0; count2 = 0;
10262 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
10263 &count2, &count);
10264 printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10265 if ((count != count2) || (count != 0)) {
10266 ret = false;
10269 done:
10270 TALLOC_FREE(db);
10271 return ret;
10276 local test for character set functions
10278 This is a very simple test for the functionality in convert_string_error()
10280 static bool run_local_convert_string(int dummy)
10282 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
10283 const char *test_strings[2] = { "March", "M\303\244rz" };
10284 char dst[7];
10285 int i;
10287 for (i=0; i<2; i++) {
10288 const char *str = test_strings[i];
10289 int len = strlen(str);
10290 size_t converted_size;
10291 bool ret;
10293 memset(dst, 'X', sizeof(dst));
10295 /* first try with real source length */
10296 ret = convert_string_error(CH_UNIX, CH_UTF8,
10297 str, len,
10298 dst, sizeof(dst),
10299 &converted_size);
10300 if (ret != true) {
10301 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
10302 goto failed;
10305 if (converted_size != len) {
10306 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
10307 str, len, (int)converted_size);
10308 goto failed;
10311 if (strncmp(str, dst, converted_size) != 0) {
10312 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
10313 goto failed;
10316 if (strlen(str) != converted_size) {
10317 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
10318 (int)strlen(str), (int)converted_size);
10319 goto failed;
10322 if (dst[converted_size] != 'X') {
10323 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
10324 goto failed;
10327 /* now with srclen==-1, this causes the nul to be
10328 * converted too */
10329 ret = convert_string_error(CH_UNIX, CH_UTF8,
10330 str, -1,
10331 dst, sizeof(dst),
10332 &converted_size);
10333 if (ret != true) {
10334 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
10335 goto failed;
10338 if (converted_size != len+1) {
10339 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
10340 str, len, (int)converted_size);
10341 goto failed;
10344 if (strncmp(str, dst, converted_size) != 0) {
10345 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
10346 goto failed;
10349 if (len+1 != converted_size) {
10350 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
10351 len+1, (int)converted_size);
10352 goto failed;
10355 if (dst[converted_size] != 'X') {
10356 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
10357 goto failed;
10363 TALLOC_FREE(tmp_ctx);
10364 return true;
10365 failed:
10366 TALLOC_FREE(tmp_ctx);
10367 return false;
10370 static bool run_local_string_to_sid(int dummy) {
10371 struct dom_sid sid;
10373 if (string_to_sid(&sid, "S--1-5-32-545")) {
10374 printf("allowing S--1-5-32-545\n");
10375 return false;
10377 if (string_to_sid(&sid, "S-1-5-32-+545")) {
10378 printf("allowing S-1-5-32-+545\n");
10379 return false;
10381 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")) {
10382 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
10383 return false;
10385 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
10386 printf("allowing S-1-5-32-545-abc\n");
10387 return false;
10389 if (string_to_sid(&sid, "S-300-5-32-545")) {
10390 printf("allowing S-300-5-32-545\n");
10391 return false;
10393 if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
10394 printf("allowing S-1-0xfffffffffffffe-32-545\n");
10395 return false;
10397 if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
10398 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
10399 return false;
10401 if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
10402 printf("could not parse S-1-0xfffffffffffe-32-545\n");
10403 return false;
10405 if (!string_to_sid(&sid, "S-1-5-32-545")) {
10406 printf("could not parse S-1-5-32-545\n");
10407 return false;
10409 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
10410 printf("mis-parsed S-1-5-32-545 as %s\n",
10411 sid_string_tos(&sid));
10412 return false;
10414 return true;
10417 static bool sid_to_string_test(const char *expected) {
10418 char *str;
10419 bool res = true;
10420 struct dom_sid sid;
10422 if (!string_to_sid(&sid, expected)) {
10423 printf("could not parse %s\n", expected);
10424 return false;
10427 str = dom_sid_string(NULL, &sid);
10428 if (strcmp(str, expected)) {
10429 printf("Comparison failed (%s != %s)\n", str, expected);
10430 res = false;
10432 TALLOC_FREE(str);
10433 return res;
10436 static bool run_local_sid_to_string(int dummy) {
10437 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
10438 return false;
10439 if (!sid_to_string_test("S-1-545"))
10440 return false;
10441 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
10442 return false;
10443 return true;
10446 static bool run_local_binary_to_sid(int dummy) {
10447 struct dom_sid *sid = talloc(NULL, struct dom_sid);
10448 static const uint8_t good_binary_sid[] = {
10449 0x1, /* revision number */
10450 15, /* num auths */
10451 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10452 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10453 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10454 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10455 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10456 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10457 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10458 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10459 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10460 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10461 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10462 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10463 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10464 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10465 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10466 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10469 static const uint8_t long_binary_sid[] = {
10470 0x1, /* revision number */
10471 15, /* num auths */
10472 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10473 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10474 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10475 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10476 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10477 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10478 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10479 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10480 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10481 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10482 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10483 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10484 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10485 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10486 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10487 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10488 0x1, 0x1, 0x1, 0x1, /* auth[15] */
10489 0x1, 0x1, 0x1, 0x1, /* auth[16] */
10490 0x1, 0x1, 0x1, 0x1, /* auth[17] */
10493 static const uint8_t long_binary_sid2[] = {
10494 0x1, /* revision number */
10495 32, /* num auths */
10496 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10497 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10498 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10499 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10500 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10501 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10502 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10503 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10504 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10505 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10506 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10507 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10508 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10509 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10510 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10511 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10512 0x1, 0x1, 0x1, 0x1, /* auth[15] */
10513 0x1, 0x1, 0x1, 0x1, /* auth[16] */
10514 0x1, 0x1, 0x1, 0x1, /* auth[17] */
10515 0x1, 0x1, 0x1, 0x1, /* auth[18] */
10516 0x1, 0x1, 0x1, 0x1, /* auth[19] */
10517 0x1, 0x1, 0x1, 0x1, /* auth[20] */
10518 0x1, 0x1, 0x1, 0x1, /* auth[21] */
10519 0x1, 0x1, 0x1, 0x1, /* auth[22] */
10520 0x1, 0x1, 0x1, 0x1, /* auth[23] */
10521 0x1, 0x1, 0x1, 0x1, /* auth[24] */
10522 0x1, 0x1, 0x1, 0x1, /* auth[25] */
10523 0x1, 0x1, 0x1, 0x1, /* auth[26] */
10524 0x1, 0x1, 0x1, 0x1, /* auth[27] */
10525 0x1, 0x1, 0x1, 0x1, /* auth[28] */
10526 0x1, 0x1, 0x1, 0x1, /* auth[29] */
10527 0x1, 0x1, 0x1, 0x1, /* auth[30] */
10528 0x1, 0x1, 0x1, 0x1, /* auth[31] */
10531 if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
10532 return false;
10534 if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
10535 return false;
10537 if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
10538 return false;
10540 return true;
10543 /* Split a path name into filename and stream name components. Canonicalise
10544 * such that an implicit $DATA token is always explicit.
10546 * The "specification" of this function can be found in the
10547 * run_local_stream_name() function in torture.c, I've tried those
10548 * combinations against a W2k3 server.
10551 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
10552 char **pbase, char **pstream)
10554 char *base = NULL;
10555 char *stream = NULL;
10556 char *sname; /* stream name */
10557 const char *stype; /* stream type */
10559 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
10561 sname = strchr_m(fname, ':');
10563 if (sname == NULL) {
10564 if (pbase != NULL) {
10565 base = talloc_strdup(mem_ctx, fname);
10566 NT_STATUS_HAVE_NO_MEMORY(base);
10568 goto done;
10571 if (pbase != NULL) {
10572 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
10573 NT_STATUS_HAVE_NO_MEMORY(base);
10576 sname += 1;
10578 stype = strchr_m(sname, ':');
10580 if (stype == NULL) {
10581 sname = talloc_strdup(mem_ctx, sname);
10582 stype = "$DATA";
10584 else {
10585 if (strcasecmp_m(stype, ":$DATA") != 0) {
10587 * If there is an explicit stream type, so far we only
10588 * allow $DATA. Is there anything else allowed? -- vl
10590 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
10591 TALLOC_FREE(base);
10592 return NT_STATUS_OBJECT_NAME_INVALID;
10594 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
10595 stype += 1;
10598 if (sname == NULL) {
10599 TALLOC_FREE(base);
10600 return NT_STATUS_NO_MEMORY;
10603 if (sname[0] == '\0') {
10605 * no stream name, so no stream
10607 goto done;
10610 if (pstream != NULL) {
10611 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
10612 if (stream == NULL) {
10613 TALLOC_FREE(sname);
10614 TALLOC_FREE(base);
10615 return NT_STATUS_NO_MEMORY;
10618 * upper-case the type field
10620 (void)strupper_m(strchr_m(stream, ':')+1);
10623 done:
10624 if (pbase != NULL) {
10625 *pbase = base;
10627 if (pstream != NULL) {
10628 *pstream = stream;
10630 return NT_STATUS_OK;
10633 static bool test_stream_name(const char *fname, const char *expected_base,
10634 const char *expected_stream,
10635 NTSTATUS expected_status)
10637 NTSTATUS status;
10638 char *base = NULL;
10639 char *stream = NULL;
10641 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
10642 if (!NT_STATUS_EQUAL(status, expected_status)) {
10643 goto error;
10646 if (!NT_STATUS_IS_OK(status)) {
10647 return true;
10650 if (base == NULL) goto error;
10652 if (strcmp(expected_base, base) != 0) goto error;
10654 if ((expected_stream != NULL) && (stream == NULL)) goto error;
10655 if ((expected_stream == NULL) && (stream != NULL)) goto error;
10657 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
10658 goto error;
10660 TALLOC_FREE(base);
10661 TALLOC_FREE(stream);
10662 return true;
10664 error:
10665 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
10666 fname, expected_base ? expected_base : "<NULL>",
10667 expected_stream ? expected_stream : "<NULL>",
10668 nt_errstr(expected_status));
10669 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
10670 base ? base : "<NULL>", stream ? stream : "<NULL>",
10671 nt_errstr(status));
10672 TALLOC_FREE(base);
10673 TALLOC_FREE(stream);
10674 return false;
10677 static bool run_local_stream_name(int dummy)
10679 bool ret = true;
10681 ret &= test_stream_name(
10682 "bla", "bla", NULL, NT_STATUS_OK);
10683 ret &= test_stream_name(
10684 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
10685 ret &= test_stream_name(
10686 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
10687 ret &= test_stream_name(
10688 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
10689 ret &= test_stream_name(
10690 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
10691 ret &= test_stream_name(
10692 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
10693 ret &= test_stream_name(
10694 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
10695 ret &= test_stream_name(
10696 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
10698 return ret;
10701 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
10703 if (a.length != b.length) {
10704 printf("a.length=%d != b.length=%d\n",
10705 (int)a.length, (int)b.length);
10706 return false;
10708 if (memcmp(a.data, b.data, a.length) != 0) {
10709 printf("a.data and b.data differ\n");
10710 return false;
10712 return true;
10715 static bool run_local_memcache(int dummy)
10717 struct memcache *cache;
10718 DATA_BLOB k1, k2, k3;
10719 DATA_BLOB d1, d3;
10720 DATA_BLOB v1, v3;
10722 TALLOC_CTX *mem_ctx;
10723 char *ptr1 = NULL;
10724 char *ptr2 = NULL;
10726 char *str1, *str2;
10727 size_t size1, size2;
10728 bool ret = false;
10730 mem_ctx = talloc_init("foo");
10731 if (mem_ctx == NULL) {
10732 return false;
10735 /* STAT_CACHE TESTS */
10737 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
10739 if (cache == NULL) {
10740 printf("memcache_init failed\n");
10741 return false;
10744 d1 = data_blob_const("d1", 2);
10745 d3 = data_blob_const("d3", 2);
10747 k1 = data_blob_const("d1", 2);
10748 k2 = data_blob_const("d2", 2);
10749 k3 = data_blob_const("d3", 2);
10751 memcache_add(cache, STAT_CACHE, k1, d1);
10753 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
10754 printf("could not find k1\n");
10755 return false;
10757 if (!data_blob_equal(d1, v1)) {
10758 return false;
10761 memcache_add(cache, STAT_CACHE, k1, d3);
10763 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
10764 printf("could not find replaced k1\n");
10765 return false;
10767 if (!data_blob_equal(d3, v3)) {
10768 return false;
10771 TALLOC_FREE(cache);
10773 /* GETWD_CACHE TESTS */
10774 str1 = talloc_strdup(mem_ctx, "string1");
10775 if (str1 == NULL) {
10776 return false;
10778 ptr2 = str1; /* Keep an alias for comparison. */
10780 str2 = talloc_strdup(mem_ctx, "string2");
10781 if (str2 == NULL) {
10782 return false;
10785 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
10786 if (cache == NULL) {
10787 printf("memcache_init failed\n");
10788 return false;
10791 memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
10792 /* str1 == NULL now. */
10793 ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
10794 if (ptr1 == NULL) {
10795 printf("could not find k2\n");
10796 return false;
10798 if (ptr1 != ptr2) {
10799 printf("fetch of k2 got wrong string\n");
10800 return false;
10803 /* Add a blob to ensure k2 gets purged. */
10804 d3 = data_blob_talloc_zero(mem_ctx, 180);
10805 memcache_add(cache, STAT_CACHE, k3, d3);
10807 ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
10808 if (ptr2 != NULL) {
10809 printf("Did find k2, should have been purged\n");
10810 return false;
10813 TALLOC_FREE(cache);
10814 TALLOC_FREE(mem_ctx);
10816 mem_ctx = talloc_init("foo");
10817 if (mem_ctx == NULL) {
10818 return false;
10821 cache = memcache_init(NULL, 0);
10822 if (cache == NULL) {
10823 return false;
10826 str1 = talloc_strdup(mem_ctx, "string1");
10827 if (str1 == NULL) {
10828 return false;
10830 str2 = talloc_strdup(mem_ctx, "string2");
10831 if (str2 == NULL) {
10832 return false;
10834 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
10835 data_blob_string_const("torture"), &str1);
10836 size1 = talloc_total_size(cache);
10838 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
10839 data_blob_string_const("torture"), &str2);
10840 size2 = talloc_total_size(cache);
10842 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
10844 if (size2 > size1) {
10845 printf("memcache leaks memory!\n");
10846 goto fail;
10849 ret = true;
10850 fail:
10851 TALLOC_FREE(cache);
10852 return ret;
10855 static void wbclient_done(struct tevent_req *req)
10857 wbcErr wbc_err;
10858 struct winbindd_response *wb_resp;
10859 int *i = (int *)tevent_req_callback_data_void(req);
10861 wbc_err = wb_trans_recv(req, req, &wb_resp);
10862 TALLOC_FREE(req);
10863 *i += 1;
10864 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
10867 static bool run_wbclient_multi_ping(int dummy)
10869 struct tevent_context *ev;
10870 struct wb_context **wb_ctx;
10871 struct winbindd_request wb_req;
10872 bool result = false;
10873 int i, j;
10875 BlockSignals(True, SIGPIPE);
10877 ev = tevent_context_init(talloc_tos());
10878 if (ev == NULL) {
10879 goto fail;
10882 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
10883 if (wb_ctx == NULL) {
10884 goto fail;
10887 ZERO_STRUCT(wb_req);
10888 wb_req.cmd = WINBINDD_PING;
10890 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
10892 for (i=0; i<torture_nprocs; i++) {
10893 wb_ctx[i] = wb_context_init(ev, NULL);
10894 if (wb_ctx[i] == NULL) {
10895 goto fail;
10897 for (j=0; j<torture_numops; j++) {
10898 struct tevent_req *req;
10899 req = wb_trans_send(ev, ev, wb_ctx[i],
10900 (j % 2) == 0, &wb_req);
10901 if (req == NULL) {
10902 goto fail;
10904 tevent_req_set_callback(req, wbclient_done, &i);
10908 i = 0;
10910 while (i < torture_nprocs * torture_numops) {
10911 tevent_loop_once(ev);
10914 result = true;
10915 fail:
10916 TALLOC_FREE(ev);
10917 return result;
10920 static bool dbtrans_inc(struct db_context *db)
10922 struct db_record *rec;
10923 uint32_t val;
10924 bool ret = false;
10925 NTSTATUS status;
10926 TDB_DATA value;
10928 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
10929 if (rec == NULL) {
10930 printf(__location__ "fetch_lock failed\n");
10931 return false;
10934 value = dbwrap_record_get_value(rec);
10936 if (value.dsize != sizeof(uint32_t)) {
10937 printf(__location__ "value.dsize = %d\n",
10938 (int)value.dsize);
10939 goto fail;
10942 memcpy(&val, value.dptr, sizeof(val));
10943 val += 1;
10945 status = dbwrap_record_store(
10946 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
10947 if (!NT_STATUS_IS_OK(status)) {
10948 printf(__location__ "store failed: %s\n",
10949 nt_errstr(status));
10950 goto fail;
10953 ret = true;
10954 fail:
10955 TALLOC_FREE(rec);
10956 return ret;
10959 static bool run_local_dbtrans(int dummy)
10961 struct db_context *db;
10962 struct db_record *rec;
10963 NTSTATUS status;
10964 uint32_t initial;
10965 int res;
10966 TDB_DATA value;
10968 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
10969 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
10970 DBWRAP_FLAG_NONE);
10971 if (db == NULL) {
10972 printf("Could not open transtest.db\n");
10973 return false;
10976 res = dbwrap_transaction_start(db);
10977 if (res != 0) {
10978 printf(__location__ "transaction_start failed\n");
10979 return false;
10982 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
10983 if (rec == NULL) {
10984 printf(__location__ "fetch_lock failed\n");
10985 return false;
10988 value = dbwrap_record_get_value(rec);
10990 if (value.dptr == NULL) {
10991 initial = 0;
10992 status = dbwrap_record_store(
10993 rec, make_tdb_data((uint8_t *)&initial,
10994 sizeof(initial)),
10996 if (!NT_STATUS_IS_OK(status)) {
10997 printf(__location__ "store returned %s\n",
10998 nt_errstr(status));
10999 return false;
11003 TALLOC_FREE(rec);
11005 res = dbwrap_transaction_commit(db);
11006 if (res != 0) {
11007 printf(__location__ "transaction_commit failed\n");
11008 return false;
11011 while (true) {
11012 uint32_t val, val2;
11013 int i;
11015 res = dbwrap_transaction_start(db);
11016 if (res != 0) {
11017 printf(__location__ "transaction_start failed\n");
11018 break;
11021 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
11022 if (!NT_STATUS_IS_OK(status)) {
11023 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
11024 nt_errstr(status));
11025 break;
11028 for (i=0; i<10; i++) {
11029 if (!dbtrans_inc(db)) {
11030 return false;
11034 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
11035 if (!NT_STATUS_IS_OK(status)) {
11036 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
11037 nt_errstr(status));
11038 break;
11041 if (val2 != val + 10) {
11042 printf(__location__ "val=%d, val2=%d\n",
11043 (int)val, (int)val2);
11044 break;
11047 printf("val2=%d\r", val2);
11049 res = dbwrap_transaction_commit(db);
11050 if (res != 0) {
11051 printf(__location__ "transaction_commit failed\n");
11052 break;
11056 TALLOC_FREE(db);
11057 return true;
11061 * Just a dummy test to be run under a debugger. There's no real way
11062 * to inspect the tevent_poll specific function from outside of
11063 * tevent_poll.c.
11066 static bool run_local_tevent_poll(int dummy)
11068 struct tevent_context *ev;
11069 struct tevent_fd *fd1, *fd2;
11070 bool result = false;
11072 ev = tevent_context_init_byname(NULL, "poll");
11073 if (ev == NULL) {
11074 d_fprintf(stderr, "tevent_context_init_byname failed\n");
11075 goto fail;
11078 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
11079 if (fd1 == NULL) {
11080 d_fprintf(stderr, "tevent_add_fd failed\n");
11081 goto fail;
11083 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
11084 if (fd2 == NULL) {
11085 d_fprintf(stderr, "tevent_add_fd failed\n");
11086 goto fail;
11088 TALLOC_FREE(fd2);
11090 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
11091 if (fd2 == NULL) {
11092 d_fprintf(stderr, "tevent_add_fd failed\n");
11093 goto fail;
11096 result = true;
11097 fail:
11098 TALLOC_FREE(ev);
11099 return result;
11102 static bool run_local_hex_encode_buf(int dummy)
11104 char buf[17];
11105 uint8_t src[8];
11106 int i;
11108 for (i=0; i<sizeof(src); i++) {
11109 src[i] = i;
11111 hex_encode_buf(buf, src, sizeof(src));
11112 if (strcmp(buf, "0001020304050607") != 0) {
11113 return false;
11115 hex_encode_buf(buf, NULL, 0);
11116 if (buf[0] != '\0') {
11117 return false;
11119 return true;
11122 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
11123 "0.0.0.0",
11124 "::0",
11125 "1.2.3.1",
11126 "0.0.0.0",
11127 "0.0.0.0",
11128 "1.2.3.2",
11129 "1.2.3.3",
11130 "1.2.3.4",
11131 "1.2.3.5",
11132 "::0",
11133 "1.2.3.6",
11134 "1.2.3.7",
11135 "::0",
11136 "::0",
11137 "::0",
11138 "1.2.3.8",
11139 "1.2.3.9",
11140 "1.2.3.10",
11141 "1.2.3.11",
11142 "1.2.3.12",
11143 "1.2.3.13",
11144 "1001:1111:1111:1000:0:1111:1111:1111",
11145 "1.2.3.1",
11146 "1.2.3.2",
11147 "1.2.3.3",
11148 "1.2.3.12",
11149 "::0",
11150 "::0"
11153 static const char *remove_duplicate_addrs2_test_strings_result[] = {
11154 "1.2.3.1",
11155 "1.2.3.2",
11156 "1.2.3.3",
11157 "1.2.3.4",
11158 "1.2.3.5",
11159 "1.2.3.6",
11160 "1.2.3.7",
11161 "1.2.3.8",
11162 "1.2.3.9",
11163 "1.2.3.10",
11164 "1.2.3.11",
11165 "1.2.3.12",
11166 "1.2.3.13",
11167 "1001:1111:1111:1000:0:1111:1111:1111"
11170 static bool run_local_remove_duplicate_addrs2(int dummy)
11172 struct ip_service test_vector[28];
11173 int count, i;
11175 /* Construct the sockaddr_storage test vector. */
11176 for (i = 0; i < 28; i++) {
11177 struct addrinfo hints;
11178 struct addrinfo *res = NULL;
11179 int ret;
11181 memset(&hints, '\0', sizeof(hints));
11182 hints.ai_flags = AI_NUMERICHOST;
11183 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
11184 NULL,
11185 &hints,
11186 &res);
11187 if (ret) {
11188 fprintf(stderr, "getaddrinfo failed on [%s]\n",
11189 remove_duplicate_addrs2_test_strings_vector[i]);
11190 return false;
11192 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
11193 memcpy(&test_vector[i].ss,
11194 res->ai_addr,
11195 res->ai_addrlen);
11196 freeaddrinfo(res);
11199 count = remove_duplicate_addrs2(test_vector, i);
11201 if (count != 14) {
11202 fprintf(stderr, "count wrong (%d) should be 14\n",
11203 count);
11204 return false;
11207 for (i = 0; i < count; i++) {
11208 char addr[INET6_ADDRSTRLEN];
11210 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
11212 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
11213 fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
11215 addr,
11216 remove_duplicate_addrs2_test_strings_result[i]);
11217 return false;
11221 printf("run_local_remove_duplicate_addrs2: success\n");
11222 return true;
11225 static bool run_local_tdb_opener(int dummy)
11227 TDB_CONTEXT *t;
11228 unsigned v = 0;
11230 while (1) {
11231 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
11232 O_RDWR|O_CREAT, 0755);
11233 if (t == NULL) {
11234 perror("tdb_open failed");
11235 return false;
11237 tdb_close(t);
11239 v += 1;
11240 printf("\r%u", v);
11242 return true;
11245 static bool run_local_tdb_writer(int dummy)
11247 TDB_CONTEXT *t;
11248 unsigned v = 0;
11249 TDB_DATA val;
11251 t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
11252 if (t == 0) {
11253 perror("tdb_open failed");
11254 return 1;
11257 val.dptr = (uint8_t *)&v;
11258 val.dsize = sizeof(v);
11260 while (1) {
11261 TDB_DATA data;
11262 int ret;
11264 ret = tdb_store(t, val, val, 0);
11265 if (ret != 0) {
11266 printf("%s\n", tdb_errorstr(t));
11268 v += 1;
11269 printf("\r%u", v);
11271 data = tdb_fetch(t, val);
11272 if (data.dptr != NULL) {
11273 SAFE_FREE(data.dptr);
11276 return true;
11279 static bool run_local_canonicalize_path(int dummy)
11281 const char *src[] = {
11282 "/foo/..",
11283 "/..",
11284 "/foo/bar/../baz",
11285 "/foo/././",
11286 "/../foo",
11287 ".././././",
11288 ".././././../../../boo",
11289 "./..",
11290 NULL
11292 const char *dst[] = {
11293 "/",
11294 "/",
11295 "/foo/baz",
11296 "/foo",
11297 "/foo",
11298 "/",
11299 "/boo",
11300 "/",
11301 NULL
11303 unsigned int i;
11305 for (i = 0; src[i] != NULL; i++) {
11306 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
11307 if (d == NULL) {
11308 perror("talloc fail\n");
11309 return false;
11311 if (strcmp(d, dst[i]) != 0) {
11312 d_fprintf(stderr,
11313 "canonicalize missmatch %s -> %s != %s",
11314 src[i], d, dst[i]);
11315 return false;
11317 talloc_free(d);
11319 return true;
11322 static bool run_ign_bad_negprot(int dummy)
11324 struct tevent_context *ev;
11325 struct tevent_req *req;
11326 struct smbXcli_conn *conn;
11327 struct sockaddr_storage ss;
11328 NTSTATUS status;
11329 int fd;
11330 bool ok;
11332 printf("starting ignore bad negprot\n");
11334 ok = resolve_name(host, &ss, 0x20, true);
11335 if (!ok) {
11336 d_fprintf(stderr, "Could not resolve name %s\n", host);
11337 return false;
11340 status = open_socket_out(&ss, 445, 10000, &fd);
11341 if (!NT_STATUS_IS_OK(status)) {
11342 d_fprintf(stderr, "open_socket_out failed: %s\n",
11343 nt_errstr(status));
11344 return false;
11347 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
11348 NULL, 0);
11349 if (conn == NULL) {
11350 d_fprintf(stderr, "smbXcli_conn_create failed\n");
11351 return false;
11354 status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
11355 if (NT_STATUS_IS_OK(status)) {
11356 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
11357 return false;
11360 ev = samba_tevent_context_init(talloc_tos());
11361 if (ev == NULL) {
11362 d_fprintf(stderr, "samba_tevent_context_init failed\n");
11363 return false;
11366 req = smb1cli_session_setup_nt1_send(
11367 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
11368 data_blob_null, data_blob_null, 0x40,
11369 "Windows 2000 2195", "Windows 2000 5.0");
11370 if (req == NULL) {
11371 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
11372 return false;
11375 ok = tevent_req_poll_ntstatus(req, ev, &status);
11376 if (!ok) {
11377 d_fprintf(stderr, "tevent_req_poll failed\n");
11378 return false;
11381 status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
11382 NULL, NULL);
11383 if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
11384 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
11385 "%s, expected NT_STATUS_CONNECTION_RESET\n",
11386 nt_errstr(status));
11387 return false;
11390 TALLOC_FREE(conn);
11392 printf("starting ignore bad negprot\n");
11394 return true;
11397 static double create_procs(bool (*fn)(int), bool *result)
11399 int i, status;
11400 volatile pid_t *child_status;
11401 volatile bool *child_status_out;
11402 int synccount;
11403 int tries = 8;
11404 struct timeval start;
11406 synccount = 0;
11408 child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
11409 if (!child_status) {
11410 printf("Failed to setup shared memory\n");
11411 return -1;
11414 child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
11415 if (!child_status_out) {
11416 printf("Failed to setup result status shared memory\n");
11417 return -1;
11420 for (i = 0; i < torture_nprocs; i++) {
11421 child_status[i] = 0;
11422 child_status_out[i] = True;
11425 start = timeval_current();
11427 for (i=0;i<torture_nprocs;i++) {
11428 procnum = i;
11429 if (fork() == 0) {
11430 pid_t mypid = getpid();
11431 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
11433 slprintf(myname,sizeof(myname),"CLIENT%d", i);
11435 while (1) {
11436 if (torture_open_connection(&current_cli, i)) break;
11437 if (tries-- == 0) {
11438 printf("pid %d failed to start\n", (int)getpid());
11439 _exit(1);
11441 smb_msleep(10);
11444 child_status[i] = getpid();
11446 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
11448 child_status_out[i] = fn(i);
11449 _exit(0);
11453 do {
11454 synccount = 0;
11455 for (i=0;i<torture_nprocs;i++) {
11456 if (child_status[i]) synccount++;
11458 if (synccount == torture_nprocs) break;
11459 smb_msleep(10);
11460 } while (timeval_elapsed(&start) < 30);
11462 if (synccount != torture_nprocs) {
11463 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
11464 *result = False;
11465 return timeval_elapsed(&start);
11468 /* start the client load */
11469 start = timeval_current();
11471 for (i=0;i<torture_nprocs;i++) {
11472 child_status[i] = 0;
11475 printf("%d clients started\n", torture_nprocs);
11477 for (i=0;i<torture_nprocs;i++) {
11478 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
11481 printf("\n");
11483 for (i=0;i<torture_nprocs;i++) {
11484 if (!child_status_out[i]) {
11485 *result = False;
11488 return timeval_elapsed(&start);
11491 #define FLAG_MULTIPROC 1
11493 static struct {
11494 const char *name;
11495 bool (*fn)(int);
11496 unsigned flags;
11497 } torture_ops[] = {
11498 {"FDPASS", run_fdpasstest, 0},
11499 {"LOCK1", run_locktest1, 0},
11500 {"LOCK2", run_locktest2, 0},
11501 {"LOCK3", run_locktest3, 0},
11502 {"LOCK4", run_locktest4, 0},
11503 {"LOCK5", run_locktest5, 0},
11504 {"LOCK6", run_locktest6, 0},
11505 {"LOCK7", run_locktest7, 0},
11506 {"LOCK8", run_locktest8, 0},
11507 {"LOCK9", run_locktest9, 0},
11508 {"UNLINK", run_unlinktest, 0},
11509 {"BROWSE", run_browsetest, 0},
11510 {"ATTR", run_attrtest, 0},
11511 {"TRANS2", run_trans2test, 0},
11512 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
11513 {"TORTURE",run_torture, FLAG_MULTIPROC},
11514 {"RANDOMIPC", run_randomipc, 0},
11515 {"NEGNOWAIT", run_negprot_nowait, 0},
11516 {"NBENCH", run_nbench, 0},
11517 {"NBENCH2", run_nbench2, 0},
11518 {"OPLOCK1", run_oplock1, 0},
11519 {"OPLOCK2", run_oplock2, 0},
11520 {"OPLOCK4", run_oplock4, 0},
11521 {"DIR", run_dirtest, 0},
11522 {"DIR1", run_dirtest1, 0},
11523 {"DIR-CREATETIME", run_dir_createtime, 0},
11524 {"DENY1", torture_denytest1, 0},
11525 {"DENY2", torture_denytest2, 0},
11526 {"TCON", run_tcon_test, 0},
11527 {"TCONDEV", run_tcon_devtype_test, 0},
11528 {"RW1", run_readwritetest, 0},
11529 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
11530 {"RW3", run_readwritelarge, 0},
11531 {"RW-SIGNING", run_readwritelarge_signtest, 0},
11532 {"OPEN", run_opentest, 0},
11533 {"POSIX", run_simple_posix_open_test, 0},
11534 {"POSIX-APPEND", run_posix_append, 0},
11535 {"POSIX-SYMLINK-ACL", run_acl_symlink_test, 0},
11536 {"POSIX-SYMLINK-EA", run_ea_symlink_test, 0},
11537 {"POSIX-STREAM-DELETE", run_posix_stream_delete, 0},
11538 {"POSIX-OFD-LOCK", run_posix_ofd_lock_test, 0},
11539 {"WINDOWS-BAD-SYMLINK", run_symlink_open_test, 0},
11540 {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
11541 {"ASYNC-ECHO", run_async_echo, 0},
11542 { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
11543 { "SHORTNAME-TEST", run_shortname_test, 0},
11544 { "ADDRCHANGE", run_addrchange, 0},
11545 #if 1
11546 {"OPENATTR", run_openattrtest, 0},
11547 #endif
11548 {"XCOPY", run_xcopy, 0},
11549 {"RENAME", run_rename, 0},
11550 {"RENAME-ACCESS", run_rename_access, 0},
11551 {"OWNER-RIGHTS", run_owner_rights, 0},
11552 {"DELETE", run_deletetest, 0},
11553 {"WILDDELETE", run_wild_deletetest, 0},
11554 {"DELETE-LN", run_deletetest_ln, 0},
11555 {"PROPERTIES", run_properties, 0},
11556 {"MANGLE", torture_mangle, 0},
11557 {"MANGLE1", run_mangle1, 0},
11558 {"MANGLE-ILLEGAL", run_mangle_illegal, 0},
11559 {"W2K", run_w2ktest, 0},
11560 {"TRANS2SCAN", torture_trans2_scan, 0},
11561 {"NTTRANSSCAN", torture_nttrans_scan, 0},
11562 {"UTABLE", torture_utable, 0},
11563 {"CASETABLE", torture_casetable, 0},
11564 {"ERRMAPEXTRACT", run_error_map_extract, 0},
11565 {"PIPE_NUMBER", run_pipe_number, 0},
11566 {"TCON2", run_tcon2_test, 0},
11567 {"IOCTL", torture_ioctl_test, 0},
11568 {"CHKPATH", torture_chkpath_test, 0},
11569 {"FDSESS", run_fdsesstest, 0},
11570 { "EATEST", run_eatest, 0},
11571 { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
11572 { "CHAIN1", run_chain1, 0},
11573 { "CHAIN2", run_chain2, 0},
11574 { "CHAIN3", run_chain3, 0},
11575 { "WINDOWS-WRITE", run_windows_write, 0},
11576 { "LARGE_READX", run_large_readx, 0},
11577 { "NTTRANS-CREATE", run_nttrans_create, 0},
11578 { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
11579 { "CLI_ECHO", run_cli_echo, 0},
11580 { "TLDAP", run_tldap },
11581 { "STREAMERROR", run_streamerror },
11582 { "NOTIFY-BENCH", run_notify_bench },
11583 { "NOTIFY-BENCH2", run_notify_bench2 },
11584 { "NOTIFY-BENCH3", run_notify_bench3 },
11585 { "BAD-NBT-SESSION", run_bad_nbt_session },
11586 { "IGN-BAD-NEGPROT", run_ign_bad_negprot },
11587 { "SMB-ANY-CONNECT", run_smb_any_connect },
11588 { "NOTIFY-ONLINE", run_notify_online },
11589 { "SMB2-BASIC", run_smb2_basic },
11590 { "SMB2-NEGPROT", run_smb2_negprot },
11591 { "SMB2-SESSION-RECONNECT", run_smb2_session_reconnect },
11592 { "SMB2-TCON-DEPENDENCE", run_smb2_tcon_dependence },
11593 { "SMB2-MULTI-CHANNEL", run_smb2_multi_channel },
11594 { "SMB2-SESSION-REAUTH", run_smb2_session_reauth },
11595 { "SMB2-FTRUNCATE", run_smb2_ftruncate },
11596 { "CLEANUP1", run_cleanup1 },
11597 { "CLEANUP2", run_cleanup2 },
11598 { "CLEANUP3", run_cleanup3 },
11599 { "CLEANUP4", run_cleanup4 },
11600 { "OPLOCK-CANCEL", run_oplock_cancel },
11601 { "PIDHIGH", run_pidhigh },
11602 { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
11603 { "LOCAL-GENCACHE", run_local_gencache, 0},
11604 { "LOCAL-DBWRAP-WATCH1", run_dbwrap_watch1, 0 },
11605 { "LOCAL-DBWRAP-WATCH2", run_dbwrap_watch2, 0 },
11606 { "LOCAL-DBWRAP-DO-LOCKED1", run_dbwrap_do_locked1, 0 },
11607 { "LOCAL-MESSAGING-READ1", run_messaging_read1, 0 },
11608 { "LOCAL-MESSAGING-READ2", run_messaging_read2, 0 },
11609 { "LOCAL-MESSAGING-READ3", run_messaging_read3, 0 },
11610 { "LOCAL-MESSAGING-READ4", run_messaging_read4, 0 },
11611 { "LOCAL-MESSAGING-FDPASS1", run_messaging_fdpass1, 0 },
11612 { "LOCAL-MESSAGING-FDPASS2", run_messaging_fdpass2, 0 },
11613 { "LOCAL-MESSAGING-FDPASS2a", run_messaging_fdpass2a, 0 },
11614 { "LOCAL-MESSAGING-FDPASS2b", run_messaging_fdpass2b, 0 },
11615 { "LOCAL-MESSAGING-SEND-ALL", run_messaging_send_all, 0 },
11616 { "LOCAL-BASE64", run_local_base64, 0},
11617 { "LOCAL-RBTREE", run_local_rbtree, 0},
11618 { "LOCAL-MEMCACHE", run_local_memcache, 0},
11619 { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
11620 { "WBCLIENT-MULTI-PING", run_wbclient_multi_ping, 0},
11621 { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
11622 { "LOCAL-sid_to_string", run_local_sid_to_string, 0},
11623 { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
11624 { "LOCAL-DBTRANS", run_local_dbtrans, 0},
11625 { "LOCAL-TEVENT-POLL", run_local_tevent_poll, 0},
11626 { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
11627 { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
11628 { "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0},
11629 { "LOCAL-IDMAP-TDB-COMMON", run_idmap_tdb_common_test, 0},
11630 { "LOCAL-remove_duplicate_addrs2", run_local_remove_duplicate_addrs2, 0},
11631 { "local-tdb-opener", run_local_tdb_opener, 0 },
11632 { "local-tdb-writer", run_local_tdb_writer, 0 },
11633 { "LOCAL-DBWRAP-CTDB", run_local_dbwrap_ctdb, 0 },
11634 { "LOCAL-BENCH-PTHREADPOOL", run_bench_pthreadpool, 0 },
11635 { "LOCAL-PTHREADPOOL-TEVENT", run_pthreadpool_tevent, 0 },
11636 { "LOCAL-G-LOCK1", run_g_lock1, 0 },
11637 { "LOCAL-G-LOCK2", run_g_lock2, 0 },
11638 { "LOCAL-G-LOCK3", run_g_lock3, 0 },
11639 { "LOCAL-G-LOCK4", run_g_lock4, 0 },
11640 { "LOCAL-G-LOCK5", run_g_lock5, 0 },
11641 { "LOCAL-G-LOCK6", run_g_lock6, 0 },
11642 { "LOCAL-G-LOCK-PING-PONG", run_g_lock_ping_pong, 0 },
11643 { "LOCAL-CANONICALIZE-PATH", run_local_canonicalize_path, 0 },
11644 { "LOCAL-NAMEMAP-CACHE1", run_local_namemap_cache1, 0 },
11645 { "qpathinfo-bufsize", run_qpathinfo_bufsize, 0 },
11646 {NULL, NULL, 0}};
11648 /****************************************************************************
11649 run a specified test or "ALL"
11650 ****************************************************************************/
11651 static bool run_test(const char *name)
11653 bool ret = True;
11654 bool result = True;
11655 bool found = False;
11656 int i;
11657 double t;
11658 if (strequal(name,"ALL")) {
11659 for (i=0;torture_ops[i].name;i++) {
11660 run_test(torture_ops[i].name);
11662 found = True;
11665 for (i=0;torture_ops[i].name;i++) {
11666 fstr_sprintf(randomfname, "\\XX%x",
11667 (unsigned)random());
11669 if (strequal(name, torture_ops[i].name)) {
11670 found = True;
11671 printf("Running %s\n", name);
11672 if (torture_ops[i].flags & FLAG_MULTIPROC) {
11673 t = create_procs(torture_ops[i].fn, &result);
11674 if (!result) {
11675 ret = False;
11676 printf("TEST %s FAILED!\n", name);
11678 } else {
11679 struct timeval start;
11680 start = timeval_current();
11681 if (!torture_ops[i].fn(0)) {
11682 ret = False;
11683 printf("TEST %s FAILED!\n", name);
11685 t = timeval_elapsed(&start);
11687 printf("%s took %g secs\n\n", name, t);
11691 if (!found) {
11692 printf("Did not find a test named %s\n", name);
11693 ret = False;
11696 return ret;
11700 static void usage(void)
11702 int i;
11704 printf("WARNING samba4 test suite is much more complete nowadays.\n");
11705 printf("Please use samba4 torture.\n\n");
11707 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
11709 printf("\t-d debuglevel\n");
11710 printf("\t-U user%%pass\n");
11711 printf("\t-k use kerberos\n");
11712 printf("\t-N numprocs\n");
11713 printf("\t-n my_netbios_name\n");
11714 printf("\t-W workgroup\n");
11715 printf("\t-o num_operations\n");
11716 printf("\t-O socket_options\n");
11717 printf("\t-m maximum protocol\n");
11718 printf("\t-L use oplocks\n");
11719 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
11720 printf("\t-A showall\n");
11721 printf("\t-p port\n");
11722 printf("\t-s seed\n");
11723 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
11724 printf("\t-f filename filename to test\n");
11725 printf("\t-e encrypt\n");
11726 printf("\n\n");
11728 printf("tests are:");
11729 for (i=0;torture_ops[i].name;i++) {
11730 printf(" %s", torture_ops[i].name);
11732 printf("\n");
11734 printf("default test is ALL\n");
11736 exit(1);
11739 /****************************************************************************
11740 main program
11741 ****************************************************************************/
11742 int main(int argc,char *argv[])
11744 int opt, i;
11745 char *p;
11746 int gotuser = 0;
11747 int gotpass = 0;
11748 bool correct = True;
11749 TALLOC_CTX *frame = talloc_stackframe();
11750 int seed = time(NULL);
11752 #ifdef HAVE_SETBUFFER
11753 setbuffer(stdout, NULL, 0);
11754 #endif
11756 setup_logging("smbtorture", DEBUG_STDOUT);
11758 smb_init_locale();
11759 fault_setup();
11761 if (is_default_dyn_CONFIGFILE()) {
11762 if(getenv("SMB_CONF_PATH")) {
11763 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
11766 lp_load_global(get_dyn_CONFIGFILE());
11767 load_interfaces();
11769 if (argc < 2) {
11770 usage();
11773 for(p = argv[1]; *p; p++)
11774 if(*p == '\\')
11775 *p = '/';
11777 if (strncmp(argv[1], "//", 2)) {
11778 usage();
11781 fstrcpy(host, &argv[1][2]);
11782 p = strchr_m(&host[2],'/');
11783 if (!p) {
11784 usage();
11786 *p = 0;
11787 fstrcpy(share, p+1);
11789 fstrcpy(myname, get_myname(talloc_tos()));
11790 if (!*myname) {
11791 fprintf(stderr, "Failed to get my hostname.\n");
11792 return 1;
11795 if (*username == 0 && getenv("LOGNAME")) {
11796 fstrcpy(username,getenv("LOGNAME"));
11799 argc--;
11800 argv++;
11802 fstrcpy(workgroup, lp_workgroup());
11804 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
11805 != EOF) {
11806 switch (opt) {
11807 case 'p':
11808 port_to_use = atoi(optarg);
11809 break;
11810 case 's':
11811 seed = atoi(optarg);
11812 break;
11813 case 'W':
11814 fstrcpy(workgroup,optarg);
11815 break;
11816 case 'm':
11817 lp_set_cmdline("client max protocol", optarg);
11818 break;
11819 case 'N':
11820 torture_nprocs = atoi(optarg);
11821 break;
11822 case 'o':
11823 torture_numops = atoi(optarg);
11824 break;
11825 case 'd':
11826 lp_set_cmdline("log level", optarg);
11827 break;
11828 case 'O':
11829 sockops = optarg;
11830 break;
11831 case 'L':
11832 use_oplocks = True;
11833 break;
11834 case 'l':
11835 local_path = optarg;
11836 break;
11837 case 'A':
11838 torture_showall = True;
11839 break;
11840 case 'n':
11841 fstrcpy(myname, optarg);
11842 break;
11843 case 'c':
11844 client_txt = optarg;
11845 break;
11846 case 'e':
11847 do_encrypt = true;
11848 break;
11849 case 'k':
11850 #ifdef HAVE_KRB5
11851 use_kerberos = True;
11852 #else
11853 d_printf("No kerberos support compiled in\n");
11854 exit(1);
11855 #endif
11856 break;
11857 case 'U':
11858 gotuser = 1;
11859 fstrcpy(username,optarg);
11860 p = strchr_m(username,'%');
11861 if (p) {
11862 *p = 0;
11863 fstrcpy(password, p+1);
11864 gotpass = 1;
11866 break;
11867 case 'b':
11868 fstrcpy(multishare_conn_fname, optarg);
11869 use_multishare_conn = True;
11870 break;
11871 case 'B':
11872 torture_blocksize = atoi(optarg);
11873 break;
11874 case 'f':
11875 test_filename = SMB_STRDUP(optarg);
11876 break;
11877 default:
11878 printf("Unknown option %c (%d)\n", (char)opt, opt);
11879 usage();
11883 d_printf("using seed %d\n", seed);
11885 srandom(seed);
11887 if(use_kerberos && !gotuser) gotpass = True;
11889 while (!gotpass) {
11890 char pwd[256] = {0};
11891 int rc;
11893 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
11894 if (rc == 0) {
11895 fstrcpy(password, pwd);
11896 gotpass = 1;
11900 printf("host=%s share=%s user=%s myname=%s\n",
11901 host, share, username, myname);
11903 torture_creds = cli_session_creds_init(frame,
11904 username,
11905 workgroup,
11906 NULL, /* realm */
11907 password,
11908 use_kerberos,
11909 false, /* fallback_after_kerberos */
11910 false, /* use_ccache */
11911 false); /* password_is_nt_hash */
11912 if (torture_creds == NULL) {
11913 d_printf("cli_session_creds_init() failed.\n");
11914 exit(1);
11917 if (argc == optind) {
11918 correct = run_test("ALL");
11919 } else {
11920 for (i=optind;i<argc;i++) {
11921 if (!run_test(argv[i])) {
11922 correct = False;
11927 TALLOC_FREE(frame);
11929 if (correct) {
11930 return(0);
11931 } else {
11932 return(1);