wafsamba: add MODE_{744,_777}
[Samba.git] / source3 / torture / torture.c
blob22810f081b843a10089053459245f6b0c52bed88
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 "libsmb/namequery.h"
24 #include "wbc_async.h"
25 #include "torture/proto.h"
26 #include "libcli/security/security.h"
27 #include "tldap.h"
28 #include "tldap_util.h"
29 #include "../librpc/gen_ndr/svcctl.h"
30 #include "../lib/util/memcache.h"
31 #include "nsswitch/winbind_client.h"
32 #include "dbwrap/dbwrap.h"
33 #include "dbwrap/dbwrap_open.h"
34 #include "dbwrap/dbwrap_rbt.h"
35 #include "async_smb.h"
36 #include "libsmb/libsmb.h"
37 #include "libsmb/clirap.h"
38 #include "trans2.h"
39 #include "libsmb/nmblib.h"
40 #include "../lib/util/tevent_ntstatus.h"
41 #include "util_tdb.h"
42 #include "../libcli/smb/read_smb.h"
43 #include "../libcli/smb/smbXcli_base.h"
44 #include "lib/util/sys_rw_data.h"
45 #include "lib/util/base64.h"
46 #include "lib/util/time.h"
47 #include "lib/crypto/md5.h"
48 #include "lib/gencache.h"
50 extern char *optarg;
51 extern int optind;
53 fstring host, workgroup, share, password, username, myname;
54 struct cli_credentials *torture_creds;
55 static const char *sockops="TCP_NODELAY";
56 int torture_nprocs=1;
57 static int port_to_use=0;
58 int torture_numops=100;
59 int torture_blocksize=1024*1024;
60 static int procnum; /* records process count number when forking */
61 static struct cli_state *current_cli;
62 static fstring randomfname;
63 static bool use_oplocks;
64 static bool use_level_II_oplocks;
65 static const char *client_txt = "client_oplocks.txt";
66 static bool disable_spnego;
67 static bool use_kerberos;
68 static bool force_dos_errors;
69 static fstring multishare_conn_fname;
70 static bool use_multishare_conn = False;
71 static bool do_encrypt;
72 static const char *local_path = NULL;
73 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
74 char *test_filename;
76 bool torture_showall = False;
78 static double create_procs(bool (*fn)(int), bool *result);
80 /********************************************************************
81 Ensure a connection is encrypted.
82 ********************************************************************/
84 static bool force_cli_encryption(struct cli_state *c,
85 const char *sharename)
87 uint16_t major, minor;
88 uint32_t caplow, caphigh;
89 NTSTATUS status;
91 if (!SERVER_HAS_UNIX_CIFS(c)) {
92 d_printf("Encryption required and "
93 "server that doesn't support "
94 "UNIX extensions - failing connect\n");
95 return false;
98 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
99 &caphigh);
100 if (!NT_STATUS_IS_OK(status)) {
101 d_printf("Encryption required and "
102 "can't get UNIX CIFS extensions "
103 "version from server: %s\n", nt_errstr(status));
104 return false;
107 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
108 d_printf("Encryption required and "
109 "share %s doesn't support "
110 "encryption.\n", sharename);
111 return false;
114 status = cli_smb1_setup_encryption(c, torture_creds);
115 if (!NT_STATUS_IS_OK(status)) {
116 d_printf("Encryption required and "
117 "setup failed with error %s.\n",
118 nt_errstr(status));
119 return false;
122 return true;
126 static struct cli_state *open_nbt_connection(void)
128 struct cli_state *c;
129 NTSTATUS status;
130 int flags = 0;
132 if (disable_spnego) {
133 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
136 if (use_oplocks) {
137 flags |= CLI_FULL_CONNECTION_OPLOCKS;
140 if (use_level_II_oplocks) {
141 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
144 if (use_kerberos) {
145 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
148 if (force_dos_errors) {
149 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
152 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
153 signing_state, flags, &c);
154 if (!NT_STATUS_IS_OK(status)) {
155 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
156 return NULL;
159 cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
161 return c;
164 /****************************************************************************
165 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
166 ****************************************************************************/
168 static bool cli_bad_session_request(int fd,
169 struct nmb_name *calling, struct nmb_name *called)
171 TALLOC_CTX *frame;
172 uint8_t len_buf[4];
173 struct iovec iov[3];
174 ssize_t len;
175 uint8_t *inbuf;
176 int err;
177 bool ret = false;
178 uint8_t message_type;
179 uint8_t error;
180 struct tevent_context *ev;
181 struct tevent_req *req;
183 frame = talloc_stackframe();
185 iov[0].iov_base = len_buf;
186 iov[0].iov_len = sizeof(len_buf);
188 /* put in the destination name */
190 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
191 called->name_type);
192 if (iov[1].iov_base == NULL) {
193 goto fail;
195 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
196 talloc_get_size(iov[1].iov_base));
198 /* and my name */
200 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
201 calling->name_type);
202 if (iov[2].iov_base == NULL) {
203 goto fail;
205 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
206 talloc_get_size(iov[2].iov_base));
208 /* Deliberately corrupt the name len (first byte) */
209 *((uint8_t *)iov[2].iov_base) = 100;
211 /* send a session request (RFC 1002) */
212 /* setup the packet length
213 * Remove four bytes from the length count, since the length
214 * field in the NBT Session Service header counts the number
215 * of bytes which follow. The cli_send_smb() function knows
216 * about this and accounts for those four bytes.
217 * CRH.
220 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
221 SCVAL(len_buf,0,0x81);
223 len = write_data_iov(fd, iov, 3);
224 if (len == -1) {
225 goto fail;
228 ev = samba_tevent_context_init(frame);
229 if (ev == NULL) {
230 goto fail;
232 req = read_smb_send(frame, ev, fd);
233 if (req == NULL) {
234 goto fail;
236 if (!tevent_req_poll(req, ev)) {
237 goto fail;
239 len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
240 if (len == -1) {
241 errno = err;
242 goto fail;
244 TALLOC_FREE(ev);
246 message_type = CVAL(inbuf, 0);
247 if (message_type != 0x83) {
248 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
249 message_type);
250 goto fail;
253 if (smb_len(inbuf) != 1) {
254 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
255 (int)smb_len(inbuf));
256 goto fail;
259 error = CVAL(inbuf, 4);
260 if (error != 0x82) {
261 d_fprintf(stderr, "Expected error 0x82, got %d\n",
262 (int)error);
263 goto fail;
266 ret = true;
267 fail:
268 TALLOC_FREE(frame);
269 return ret;
272 /* Insert a NULL at the first separator of the given path and return a pointer
273 * to the remainder of the string.
275 static char *
276 terminate_path_at_separator(char * path)
278 char * p;
280 if (!path) {
281 return NULL;
284 if ((p = strchr_m(path, '/'))) {
285 *p = '\0';
286 return p + 1;
289 if ((p = strchr_m(path, '\\'))) {
290 *p = '\0';
291 return p + 1;
294 /* No separator. */
295 return NULL;
299 parse a //server/share type UNC name
301 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
302 char **hostname, char **sharename)
304 char *p;
306 *hostname = *sharename = NULL;
308 if (strncmp(unc_name, "\\\\", 2) &&
309 strncmp(unc_name, "//", 2)) {
310 return False;
313 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
314 p = terminate_path_at_separator(*hostname);
316 if (p && *p) {
317 *sharename = talloc_strdup(mem_ctx, p);
318 terminate_path_at_separator(*sharename);
321 if (*hostname && *sharename) {
322 return True;
325 TALLOC_FREE(*hostname);
326 TALLOC_FREE(*sharename);
327 return False;
330 static bool torture_open_connection_share(struct cli_state **c,
331 const char *hostname,
332 const char *sharename,
333 int flags)
335 NTSTATUS status;
337 status = cli_full_connection_creds(c,
338 myname,
339 hostname,
340 NULL, /* dest_ss */
341 port_to_use,
342 sharename,
343 "?????",
344 torture_creds,
345 flags,
346 signing_state);
347 if (!NT_STATUS_IS_OK(status)) {
348 printf("failed to open share connection: //%s/%s port:%d - %s\n",
349 hostname, sharename, port_to_use, nt_errstr(status));
350 return False;
353 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
355 if (do_encrypt) {
356 return force_cli_encryption(*c,
357 sharename);
359 return True;
362 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
364 char **unc_list = NULL;
365 int num_unc_names = 0;
366 bool result;
368 if (use_multishare_conn==True) {
369 char *h, *s;
370 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
371 if (!unc_list || num_unc_names <= 0) {
372 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
373 exit(1);
376 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
377 NULL, &h, &s)) {
378 printf("Failed to parse UNC name %s\n",
379 unc_list[conn_index % num_unc_names]);
380 TALLOC_FREE(unc_list);
381 exit(1);
384 result = torture_open_connection_share(c, h, s, flags);
386 /* h, s were copied earlier */
387 TALLOC_FREE(unc_list);
388 return result;
391 return torture_open_connection_share(c, host, share, flags);
394 bool torture_open_connection(struct cli_state **c, int conn_index)
396 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
398 if (use_oplocks) {
399 flags |= CLI_FULL_CONNECTION_OPLOCKS;
401 if (use_level_II_oplocks) {
402 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
405 return torture_open_connection_flags(c, conn_index, flags);
408 bool torture_init_connection(struct cli_state **pcli)
410 struct cli_state *cli;
412 cli = open_nbt_connection();
413 if (cli == NULL) {
414 return false;
417 *pcli = cli;
418 return true;
421 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
423 uint16_t old_vuid = cli_state_get_uid(cli);
424 NTSTATUS status;
425 bool ret;
427 cli_state_set_uid(cli, 0);
428 status = cli_session_setup_creds(cli, torture_creds);
429 ret = NT_STATUS_IS_OK(status);
430 *new_vuid = cli_state_get_uid(cli);
431 cli_state_set_uid(cli, old_vuid);
432 return ret;
436 bool torture_close_connection(struct cli_state *c)
438 bool ret = True;
439 NTSTATUS status;
441 status = cli_tdis(c);
442 if (!NT_STATUS_IS_OK(status)) {
443 printf("tdis failed (%s)\n", nt_errstr(status));
444 ret = False;
447 cli_shutdown(c);
449 return ret;
453 /* check if the server produced the expected dos or nt error code */
454 static bool check_both_error(int line, NTSTATUS status,
455 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
457 if (NT_STATUS_IS_DOS(status)) {
458 uint8_t cclass;
459 uint32_t num;
461 /* Check DOS error */
462 cclass = NT_STATUS_DOS_CLASS(status);
463 num = NT_STATUS_DOS_CODE(status);
465 if (eclass != cclass || ecode != num) {
466 printf("unexpected error code class=%d code=%d\n",
467 (int)cclass, (int)num);
468 printf(" expected %d/%d %s (line=%d)\n",
469 (int)eclass, (int)ecode, nt_errstr(nterr), line);
470 return false;
472 } else {
473 /* Check NT error */
474 if (!NT_STATUS_EQUAL(nterr, status)) {
475 printf("unexpected error code %s\n",
476 nt_errstr(status));
477 printf(" expected %s (line=%d)\n",
478 nt_errstr(nterr), line);
479 return false;
483 return true;
487 /* check if the server produced the expected error code */
488 static bool check_error(int line, NTSTATUS status,
489 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
491 if (NT_STATUS_IS_DOS(status)) {
492 uint8_t cclass;
493 uint32_t num;
495 /* Check DOS error */
497 cclass = NT_STATUS_DOS_CLASS(status);
498 num = NT_STATUS_DOS_CODE(status);
500 if (eclass != cclass || ecode != num) {
501 printf("unexpected error code class=%d code=%d\n",
502 (int)cclass, (int)num);
503 printf(" expected %d/%d %s (line=%d)\n",
504 (int)eclass, (int)ecode, nt_errstr(nterr),
505 line);
506 return False;
509 } else {
510 /* Check NT error */
512 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
513 printf("unexpected error code %s\n",
514 nt_errstr(status));
515 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
516 line);
517 return False;
521 return True;
525 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
527 NTSTATUS status;
529 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
531 while (!NT_STATUS_IS_OK(status)) {
532 if (!check_both_error(__LINE__, status, ERRDOS,
533 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
534 return false;
537 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
540 return true;
544 static bool rw_torture(struct cli_state *c)
546 const char *lockfname = "\\torture.lck";
547 fstring fname;
548 uint16_t fnum;
549 uint16_t fnum2;
550 pid_t pid2, pid = getpid();
551 int i, j;
552 char buf[1024];
553 bool correct = True;
554 size_t nread = 0;
555 NTSTATUS status;
557 memset(buf, '\0', sizeof(buf));
559 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
560 DENY_NONE, &fnum2);
561 if (!NT_STATUS_IS_OK(status)) {
562 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
564 if (!NT_STATUS_IS_OK(status)) {
565 printf("open of %s failed (%s)\n",
566 lockfname, nt_errstr(status));
567 return False;
570 for (i=0;i<torture_numops;i++) {
571 unsigned n = (unsigned)sys_random()%10;
573 if (i % 10 == 0) {
574 printf("%d\r", i); fflush(stdout);
576 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
578 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
579 return False;
582 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
583 DENY_ALL, &fnum);
584 if (!NT_STATUS_IS_OK(status)) {
585 printf("open failed (%s)\n", nt_errstr(status));
586 correct = False;
587 break;
590 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
591 sizeof(pid), NULL);
592 if (!NT_STATUS_IS_OK(status)) {
593 printf("write failed (%s)\n", nt_errstr(status));
594 correct = False;
597 for (j=0;j<50;j++) {
598 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
599 sizeof(pid)+(j*sizeof(buf)),
600 sizeof(buf), NULL);
601 if (!NT_STATUS_IS_OK(status)) {
602 printf("write failed (%s)\n",
603 nt_errstr(status));
604 correct = False;
608 pid2 = 0;
610 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
611 &nread);
612 if (!NT_STATUS_IS_OK(status)) {
613 printf("read failed (%s)\n", nt_errstr(status));
614 correct = false;
615 } else if (nread != sizeof(pid)) {
616 printf("read/write compare failed: "
617 "recv %ld req %ld\n", (unsigned long)nread,
618 (unsigned long)sizeof(pid));
619 correct = false;
622 if (pid2 != pid) {
623 printf("data corruption!\n");
624 correct = False;
627 status = cli_close(c, fnum);
628 if (!NT_STATUS_IS_OK(status)) {
629 printf("close failed (%s)\n", nt_errstr(status));
630 correct = False;
633 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
634 if (!NT_STATUS_IS_OK(status)) {
635 printf("unlink failed (%s)\n", nt_errstr(status));
636 correct = False;
639 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
640 if (!NT_STATUS_IS_OK(status)) {
641 printf("unlock failed (%s)\n", nt_errstr(status));
642 correct = False;
646 cli_close(c, fnum2);
647 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
649 printf("%d\n", i);
651 return correct;
654 static bool run_torture(int dummy)
656 struct cli_state *cli;
657 bool ret;
659 cli = current_cli;
661 smbXcli_conn_set_sockopt(cli->conn, sockops);
663 ret = rw_torture(cli);
665 if (!torture_close_connection(cli)) {
666 ret = False;
669 return ret;
672 static bool rw_torture3(struct cli_state *c, char *lockfname)
674 uint16_t fnum = (uint16_t)-1;
675 unsigned int i = 0;
676 char buf[131072];
677 char buf_rd[131072];
678 unsigned count;
679 unsigned countprev = 0;
680 size_t sent = 0;
681 bool correct = True;
682 NTSTATUS status = NT_STATUS_OK;
684 srandom(1);
685 for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
687 SIVAL(buf, i, sys_random());
690 if (procnum == 0)
692 status = cli_unlink(
693 c, lockfname,
694 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
695 if (!NT_STATUS_IS_OK(status)) {
696 printf("unlink failed (%s) (normal, this file should "
697 "not exist)\n", nt_errstr(status));
700 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
701 DENY_NONE, &fnum);
702 if (!NT_STATUS_IS_OK(status)) {
703 printf("first open read/write of %s failed (%s)\n",
704 lockfname, nt_errstr(status));
705 return False;
708 else
710 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
712 status = cli_openx(c, lockfname, O_RDONLY,
713 DENY_NONE, &fnum);
714 if (NT_STATUS_IS_OK(status)) {
715 break;
717 smb_msleep(10);
719 if (!NT_STATUS_IS_OK(status)) {
720 printf("second open read-only of %s failed (%s)\n",
721 lockfname, nt_errstr(status));
722 return False;
726 i = 0;
727 for (count = 0; count < sizeof(buf); count += sent)
729 if (count >= countprev) {
730 printf("%d %8d\r", i, count);
731 fflush(stdout);
732 i++;
733 countprev += (sizeof(buf) / 20);
736 if (procnum == 0)
738 sent = ((unsigned)sys_random()%(20))+ 1;
739 if (sent > sizeof(buf) - count)
741 sent = sizeof(buf) - count;
744 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
745 count, sent, NULL);
746 if (!NT_STATUS_IS_OK(status)) {
747 printf("write failed (%s)\n",
748 nt_errstr(status));
749 correct = False;
752 else
754 status = cli_read(c, fnum, buf_rd+count, count,
755 sizeof(buf)-count, &sent);
756 if(!NT_STATUS_IS_OK(status)) {
757 printf("read failed offset:%d size:%ld (%s)\n",
758 count, (unsigned long)sizeof(buf)-count,
759 nt_errstr(status));
760 correct = False;
761 sent = 0;
762 } else if (sent > 0) {
763 if (memcmp(buf_rd+count, buf+count, sent) != 0)
765 printf("read/write compare failed\n");
766 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
767 correct = False;
768 break;
775 status = cli_close(c, fnum);
776 if (!NT_STATUS_IS_OK(status)) {
777 printf("close failed (%s)\n", nt_errstr(status));
778 correct = False;
781 return correct;
784 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
786 const char *lockfname = "\\torture2.lck";
787 uint16_t fnum1;
788 uint16_t fnum2;
789 int i;
790 char buf[131072];
791 char buf_rd[131072];
792 bool correct = True;
793 size_t bytes_read;
794 NTSTATUS status;
796 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
797 if (!NT_STATUS_IS_OK(status)) {
798 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
801 status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
802 DENY_NONE, &fnum1);
803 if (!NT_STATUS_IS_OK(status)) {
804 printf("first open read/write of %s failed (%s)\n",
805 lockfname, nt_errstr(status));
806 return False;
809 status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
810 if (!NT_STATUS_IS_OK(status)) {
811 printf("second open read-only of %s failed (%s)\n",
812 lockfname, nt_errstr(status));
813 cli_close(c1, fnum1);
814 return False;
817 for (i = 0; i < torture_numops; i++)
819 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
820 if (i % 10 == 0) {
821 printf("%d\r", i); fflush(stdout);
824 generate_random_buffer((unsigned char *)buf, buf_size);
826 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
827 buf_size, NULL);
828 if (!NT_STATUS_IS_OK(status)) {
829 printf("write failed (%s)\n", nt_errstr(status));
830 correct = False;
831 break;
834 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
835 if(!NT_STATUS_IS_OK(status)) {
836 printf("read failed (%s)\n", nt_errstr(status));
837 correct = false;
838 break;
839 } else if (bytes_read != buf_size) {
840 printf("read failed\n");
841 printf("read %ld, expected %ld\n",
842 (unsigned long)bytes_read,
843 (unsigned long)buf_size);
844 correct = False;
845 break;
848 if (memcmp(buf_rd, buf, buf_size) != 0)
850 printf("read/write compare failed\n");
851 correct = False;
852 break;
856 status = cli_close(c2, fnum2);
857 if (!NT_STATUS_IS_OK(status)) {
858 printf("close failed (%s)\n", nt_errstr(status));
859 correct = False;
862 status = cli_close(c1, fnum1);
863 if (!NT_STATUS_IS_OK(status)) {
864 printf("close failed (%s)\n", nt_errstr(status));
865 correct = False;
868 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
869 if (!NT_STATUS_IS_OK(status)) {
870 printf("unlink failed (%s)\n", nt_errstr(status));
871 correct = False;
874 return correct;
877 static bool run_readwritetest(int dummy)
879 struct cli_state *cli1, *cli2;
880 bool test1, test2 = False;
882 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
883 return False;
885 smbXcli_conn_set_sockopt(cli1->conn, sockops);
886 smbXcli_conn_set_sockopt(cli2->conn, sockops);
888 printf("starting readwritetest\n");
890 test1 = rw_torture2(cli1, cli2);
891 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
893 if (test1) {
894 test2 = rw_torture2(cli1, cli1);
895 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
898 if (!torture_close_connection(cli1)) {
899 test1 = False;
902 if (!torture_close_connection(cli2)) {
903 test2 = False;
906 return (test1 && test2);
909 static bool run_readwritemulti(int dummy)
911 struct cli_state *cli;
912 bool test;
914 cli = current_cli;
916 smbXcli_conn_set_sockopt(cli->conn, sockops);
918 printf("run_readwritemulti: fname %s\n", randomfname);
919 test = rw_torture3(cli, randomfname);
921 if (!torture_close_connection(cli)) {
922 test = False;
925 return test;
928 static bool run_readwritelarge_internal(void)
930 static struct cli_state *cli1;
931 uint16_t fnum1;
932 const char *lockfname = "\\large.dat";
933 off_t fsize;
934 char buf[126*1024];
935 bool correct = True;
936 NTSTATUS status;
938 if (!torture_open_connection(&cli1, 0)) {
939 return False;
941 smbXcli_conn_set_sockopt(cli1->conn, sockops);
942 memset(buf,'\0',sizeof(buf));
944 printf("starting readwritelarge_internal\n");
946 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
948 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
949 DENY_NONE, &fnum1);
950 if (!NT_STATUS_IS_OK(status)) {
951 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
952 return False;
955 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
957 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
958 NULL, NULL, NULL);
959 if (!NT_STATUS_IS_OK(status)) {
960 printf("qfileinfo failed (%s)\n", nt_errstr(status));
961 correct = False;
964 if (fsize == sizeof(buf))
965 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
966 (unsigned long)fsize);
967 else {
968 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
969 (unsigned long)fsize);
970 correct = False;
973 status = cli_close(cli1, fnum1);
974 if (!NT_STATUS_IS_OK(status)) {
975 printf("close failed (%s)\n", nt_errstr(status));
976 correct = False;
979 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
980 if (!NT_STATUS_IS_OK(status)) {
981 printf("unlink failed (%s)\n", nt_errstr(status));
982 correct = False;
985 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
986 DENY_NONE, &fnum1);
987 if (!NT_STATUS_IS_OK(status)) {
988 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
989 return False;
992 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
994 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
995 NULL, NULL, NULL);
996 if (!NT_STATUS_IS_OK(status)) {
997 printf("qfileinfo failed (%s)\n", nt_errstr(status));
998 correct = False;
1001 if (fsize == sizeof(buf))
1002 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1003 (unsigned long)fsize);
1004 else {
1005 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1006 (unsigned long)fsize);
1007 correct = False;
1010 #if 0
1011 /* ToDo - set allocation. JRA */
1012 if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1013 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1014 return False;
1016 if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1017 NULL, NULL)) {
1018 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1019 correct = False;
1021 if (fsize != 0)
1022 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1023 #endif
1025 status = cli_close(cli1, fnum1);
1026 if (!NT_STATUS_IS_OK(status)) {
1027 printf("close failed (%s)\n", nt_errstr(status));
1028 correct = False;
1031 if (!torture_close_connection(cli1)) {
1032 correct = False;
1034 return correct;
1037 static bool run_readwritelarge(int dummy)
1039 return run_readwritelarge_internal();
1042 static bool run_readwritelarge_signtest(int dummy)
1044 bool ret;
1045 signing_state = SMB_SIGNING_REQUIRED;
1046 ret = run_readwritelarge_internal();
1047 signing_state = SMB_SIGNING_DEFAULT;
1048 return ret;
1051 int line_count = 0;
1052 int nbio_id;
1054 #define ival(s) strtol(s, NULL, 0)
1056 /* run a test that simulates an approximate netbench client load */
1057 static bool run_netbench(int client)
1059 struct cli_state *cli;
1060 int i;
1061 char line[1024];
1062 char cname[20];
1063 FILE *f;
1064 const char *params[20];
1065 bool correct = True;
1067 cli = current_cli;
1069 nbio_id = client;
1071 smbXcli_conn_set_sockopt(cli->conn, sockops);
1073 nb_setup(cli);
1075 slprintf(cname,sizeof(cname)-1, "client%d", client);
1077 f = fopen(client_txt, "r");
1079 if (!f) {
1080 perror(client_txt);
1081 return False;
1084 while (fgets(line, sizeof(line)-1, f)) {
1085 char *saveptr;
1086 line_count++;
1088 line[strlen(line)-1] = 0;
1090 /* printf("[%d] %s\n", line_count, line); */
1092 all_string_sub(line,"client1", cname, sizeof(line));
1094 /* parse the command parameters */
1095 params[0] = strtok_r(line, " ", &saveptr);
1096 i = 0;
1097 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1099 params[i] = "";
1101 if (i < 2) continue;
1103 if (!strncmp(params[0],"SMB", 3)) {
1104 printf("ERROR: You are using a dbench 1 load file\n");
1105 exit(1);
1108 if (!strcmp(params[0],"NTCreateX")) {
1109 nb_createx(params[1], ival(params[2]), ival(params[3]),
1110 ival(params[4]));
1111 } else if (!strcmp(params[0],"Close")) {
1112 nb_close(ival(params[1]));
1113 } else if (!strcmp(params[0],"Rename")) {
1114 nb_rename(params[1], params[2]);
1115 } else if (!strcmp(params[0],"Unlink")) {
1116 nb_unlink(params[1]);
1117 } else if (!strcmp(params[0],"Deltree")) {
1118 nb_deltree(params[1]);
1119 } else if (!strcmp(params[0],"Rmdir")) {
1120 nb_rmdir(params[1]);
1121 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1122 nb_qpathinfo(params[1]);
1123 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1124 nb_qfileinfo(ival(params[1]));
1125 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1126 nb_qfsinfo(ival(params[1]));
1127 } else if (!strcmp(params[0],"FIND_FIRST")) {
1128 nb_findfirst(params[1]);
1129 } else if (!strcmp(params[0],"WriteX")) {
1130 nb_writex(ival(params[1]),
1131 ival(params[2]), ival(params[3]), ival(params[4]));
1132 } else if (!strcmp(params[0],"ReadX")) {
1133 nb_readx(ival(params[1]),
1134 ival(params[2]), ival(params[3]), ival(params[4]));
1135 } else if (!strcmp(params[0],"Flush")) {
1136 nb_flush(ival(params[1]));
1137 } else {
1138 printf("Unknown operation %s\n", params[0]);
1139 exit(1);
1142 fclose(f);
1144 nb_cleanup();
1146 if (!torture_close_connection(cli)) {
1147 correct = False;
1150 return correct;
1154 /* run a test that simulates an approximate netbench client load */
1155 static bool run_nbench(int dummy)
1157 double t;
1158 bool correct = True;
1160 nbio_shmem(torture_nprocs);
1162 nbio_id = -1;
1164 signal(SIGALRM, nb_alarm);
1165 alarm(1);
1166 t = create_procs(run_netbench, &correct);
1167 alarm(0);
1169 printf("\nThroughput %g MB/sec\n",
1170 1.0e-6 * nbio_total() / t);
1171 return correct;
1176 This test checks for two things:
1178 1) correct support for retaining locks over a close (ie. the server
1179 must not use posix semantics)
1180 2) support for lock timeouts
1182 static bool run_locktest1(int dummy)
1184 struct cli_state *cli1, *cli2;
1185 const char *fname = "\\lockt1.lck";
1186 uint16_t fnum1, fnum2, fnum3;
1187 time_t t1, t2;
1188 unsigned lock_timeout;
1189 NTSTATUS status;
1191 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1192 return False;
1194 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1195 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1197 printf("starting locktest1\n");
1199 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1201 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1202 &fnum1);
1203 if (!NT_STATUS_IS_OK(status)) {
1204 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1205 return False;
1208 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1209 if (!NT_STATUS_IS_OK(status)) {
1210 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1211 return False;
1214 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1215 if (!NT_STATUS_IS_OK(status)) {
1216 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1217 return False;
1220 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1221 if (!NT_STATUS_IS_OK(status)) {
1222 printf("lock1 failed (%s)\n", nt_errstr(status));
1223 return false;
1226 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1227 if (NT_STATUS_IS_OK(status)) {
1228 printf("lock2 succeeded! This is a locking bug\n");
1229 return false;
1230 } else {
1231 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1232 NT_STATUS_LOCK_NOT_GRANTED)) {
1233 return false;
1237 lock_timeout = (1 + (random() % 20));
1238 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1239 t1 = time(NULL);
1240 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1241 if (NT_STATUS_IS_OK(status)) {
1242 printf("lock3 succeeded! This is a locking bug\n");
1243 return false;
1244 } else {
1245 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1246 NT_STATUS_FILE_LOCK_CONFLICT)) {
1247 return false;
1250 t2 = time(NULL);
1252 if (ABS(t2 - t1) < lock_timeout-1) {
1253 printf("error: This server appears not to support timed lock requests\n");
1256 printf("server slept for %u seconds for a %u second timeout\n",
1257 (unsigned int)(t2-t1), lock_timeout);
1259 status = cli_close(cli1, fnum2);
1260 if (!NT_STATUS_IS_OK(status)) {
1261 printf("close1 failed (%s)\n", nt_errstr(status));
1262 return False;
1265 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1266 if (NT_STATUS_IS_OK(status)) {
1267 printf("lock4 succeeded! This is a locking bug\n");
1268 return false;
1269 } else {
1270 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1271 NT_STATUS_FILE_LOCK_CONFLICT)) {
1272 return false;
1276 status = cli_close(cli1, fnum1);
1277 if (!NT_STATUS_IS_OK(status)) {
1278 printf("close2 failed (%s)\n", nt_errstr(status));
1279 return False;
1282 status = cli_close(cli2, fnum3);
1283 if (!NT_STATUS_IS_OK(status)) {
1284 printf("close3 failed (%s)\n", nt_errstr(status));
1285 return False;
1288 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1289 if (!NT_STATUS_IS_OK(status)) {
1290 printf("unlink failed (%s)\n", nt_errstr(status));
1291 return False;
1295 if (!torture_close_connection(cli1)) {
1296 return False;
1299 if (!torture_close_connection(cli2)) {
1300 return False;
1303 printf("Passed locktest1\n");
1304 return True;
1308 this checks to see if a secondary tconx can use open files from an
1309 earlier tconx
1311 static bool run_tcon_test(int dummy)
1313 static struct cli_state *cli;
1314 const char *fname = "\\tcontest.tmp";
1315 uint16_t fnum1;
1316 uint32_t cnum1, cnum2, cnum3;
1317 struct smbXcli_tcon *orig_tcon = NULL;
1318 uint16_t vuid1, vuid2;
1319 char buf[4];
1320 bool ret = True;
1321 NTSTATUS status;
1323 memset(buf, '\0', sizeof(buf));
1325 if (!torture_open_connection(&cli, 0)) {
1326 return False;
1328 smbXcli_conn_set_sockopt(cli->conn, sockops);
1330 printf("starting tcontest\n");
1332 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1334 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1335 if (!NT_STATUS_IS_OK(status)) {
1336 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1337 return False;
1340 cnum1 = cli_state_get_tid(cli);
1341 vuid1 = cli_state_get_uid(cli);
1343 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1344 if (!NT_STATUS_IS_OK(status)) {
1345 printf("initial write failed (%s)", nt_errstr(status));
1346 return False;
1349 orig_tcon = cli_state_save_tcon(cli);
1350 if (orig_tcon == NULL) {
1351 return false;
1354 status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1355 if (!NT_STATUS_IS_OK(status)) {
1356 printf("%s refused 2nd tree connect (%s)\n", host,
1357 nt_errstr(status));
1358 cli_shutdown(cli);
1359 return False;
1362 cnum2 = cli_state_get_tid(cli);
1363 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1364 vuid2 = cli_state_get_uid(cli) + 1;
1366 /* try a write with the wrong tid */
1367 cli_state_set_tid(cli, cnum2);
1369 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1370 if (NT_STATUS_IS_OK(status)) {
1371 printf("* server allows write with wrong TID\n");
1372 ret = False;
1373 } else {
1374 printf("server fails write with wrong TID : %s\n",
1375 nt_errstr(status));
1379 /* try a write with an invalid tid */
1380 cli_state_set_tid(cli, cnum3);
1382 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1383 if (NT_STATUS_IS_OK(status)) {
1384 printf("* server allows write with invalid TID\n");
1385 ret = False;
1386 } else {
1387 printf("server fails write with invalid TID : %s\n",
1388 nt_errstr(status));
1391 /* try a write with an invalid vuid */
1392 cli_state_set_uid(cli, vuid2);
1393 cli_state_set_tid(cli, cnum1);
1395 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1396 if (NT_STATUS_IS_OK(status)) {
1397 printf("* server allows write with invalid VUID\n");
1398 ret = False;
1399 } else {
1400 printf("server fails write with invalid VUID : %s\n",
1401 nt_errstr(status));
1404 cli_state_set_tid(cli, cnum1);
1405 cli_state_set_uid(cli, vuid1);
1407 status = cli_close(cli, fnum1);
1408 if (!NT_STATUS_IS_OK(status)) {
1409 printf("close failed (%s)\n", nt_errstr(status));
1410 return False;
1413 cli_state_set_tid(cli, cnum2);
1415 status = cli_tdis(cli);
1416 if (!NT_STATUS_IS_OK(status)) {
1417 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1418 return False;
1421 cli_state_restore_tcon(cli, orig_tcon);
1423 cli_state_set_tid(cli, cnum1);
1425 if (!torture_close_connection(cli)) {
1426 return False;
1429 return ret;
1434 checks for old style tcon support
1436 static bool run_tcon2_test(int dummy)
1438 static struct cli_state *cli;
1439 uint16_t cnum, max_xmit;
1440 char *service;
1441 NTSTATUS status;
1443 if (!torture_open_connection(&cli, 0)) {
1444 return False;
1446 smbXcli_conn_set_sockopt(cli->conn, sockops);
1448 printf("starting tcon2 test\n");
1450 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1451 return false;
1454 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1456 SAFE_FREE(service);
1458 if (!NT_STATUS_IS_OK(status)) {
1459 printf("tcon2 failed : %s\n", nt_errstr(status));
1460 } else {
1461 printf("tcon OK : max_xmit=%d cnum=%d\n",
1462 (int)max_xmit, (int)cnum);
1465 if (!torture_close_connection(cli)) {
1466 return False;
1469 printf("Passed tcon2 test\n");
1470 return True;
1473 static bool tcon_devtest(struct cli_state *cli,
1474 const char *myshare, const char *devtype,
1475 const char *return_devtype,
1476 NTSTATUS expected_error)
1478 NTSTATUS status;
1479 bool ret;
1481 status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1483 if (NT_STATUS_IS_OK(expected_error)) {
1484 if (NT_STATUS_IS_OK(status)) {
1485 if (return_devtype != NULL &&
1486 strequal(cli->dev, return_devtype)) {
1487 ret = True;
1488 } else {
1489 printf("tconX to share %s with type %s "
1490 "succeeded but returned the wrong "
1491 "device type (got [%s] but should have got [%s])\n",
1492 myshare, devtype, cli->dev, return_devtype);
1493 ret = False;
1495 } else {
1496 printf("tconX to share %s with type %s "
1497 "should have succeeded but failed\n",
1498 myshare, devtype);
1499 ret = False;
1501 cli_tdis(cli);
1502 } else {
1503 if (NT_STATUS_IS_OK(status)) {
1504 printf("tconx to share %s with type %s "
1505 "should have failed but succeeded\n",
1506 myshare, devtype);
1507 ret = False;
1508 } else {
1509 if (NT_STATUS_EQUAL(status, expected_error)) {
1510 ret = True;
1511 } else {
1512 printf("Returned unexpected error\n");
1513 ret = False;
1517 return ret;
1521 checks for correct tconX support
1523 static bool run_tcon_devtype_test(int dummy)
1525 static struct cli_state *cli1 = NULL;
1526 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1527 NTSTATUS status;
1528 bool ret = True;
1530 status = cli_full_connection_creds(&cli1,
1531 myname,
1532 host,
1533 NULL, /* dest_ss */
1534 port_to_use,
1535 NULL, /* service */
1536 NULL, /* service_type */
1537 torture_creds,
1538 flags,
1539 signing_state);
1541 if (!NT_STATUS_IS_OK(status)) {
1542 printf("could not open connection\n");
1543 return False;
1546 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1547 ret = False;
1549 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1550 ret = False;
1552 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1553 ret = False;
1555 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1556 ret = False;
1558 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1559 ret = False;
1561 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1562 ret = False;
1564 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1565 ret = False;
1567 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1568 ret = False;
1570 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1571 ret = False;
1573 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1574 ret = False;
1576 cli_shutdown(cli1);
1578 if (ret)
1579 printf("Passed tcondevtest\n");
1581 return ret;
1586 This test checks that
1588 1) the server supports multiple locking contexts on the one SMB
1589 connection, distinguished by PID.
1591 2) the server correctly fails overlapping locks made by the same PID (this
1592 goes against POSIX behaviour, which is why it is tricky to implement)
1594 3) the server denies unlock requests by an incorrect client PID
1596 static bool run_locktest2(int dummy)
1598 static struct cli_state *cli;
1599 const char *fname = "\\lockt2.lck";
1600 uint16_t fnum1, fnum2, fnum3;
1601 bool correct = True;
1602 NTSTATUS status;
1604 if (!torture_open_connection(&cli, 0)) {
1605 return False;
1608 smbXcli_conn_set_sockopt(cli->conn, sockops);
1610 printf("starting locktest2\n");
1612 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1614 cli_setpid(cli, 1);
1616 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1617 if (!NT_STATUS_IS_OK(status)) {
1618 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1619 return False;
1622 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1623 if (!NT_STATUS_IS_OK(status)) {
1624 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1625 return False;
1628 cli_setpid(cli, 2);
1630 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1631 if (!NT_STATUS_IS_OK(status)) {
1632 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1633 return False;
1636 cli_setpid(cli, 1);
1638 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1639 if (!NT_STATUS_IS_OK(status)) {
1640 printf("lock1 failed (%s)\n", nt_errstr(status));
1641 return false;
1644 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1645 if (NT_STATUS_IS_OK(status)) {
1646 printf("WRITE lock1 succeeded! This is a locking bug\n");
1647 correct = false;
1648 } else {
1649 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1650 NT_STATUS_LOCK_NOT_GRANTED)) {
1651 return false;
1655 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1656 if (NT_STATUS_IS_OK(status)) {
1657 printf("WRITE lock2 succeeded! This is a locking bug\n");
1658 correct = false;
1659 } else {
1660 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1661 NT_STATUS_LOCK_NOT_GRANTED)) {
1662 return false;
1666 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1667 if (NT_STATUS_IS_OK(status)) {
1668 printf("READ lock2 succeeded! This is a locking bug\n");
1669 correct = false;
1670 } else {
1671 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1672 NT_STATUS_FILE_LOCK_CONFLICT)) {
1673 return false;
1677 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1678 if (!NT_STATUS_IS_OK(status)) {
1679 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1681 cli_setpid(cli, 2);
1682 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1683 printf("unlock at 100 succeeded! This is a locking bug\n");
1684 correct = False;
1687 status = cli_unlock(cli, fnum1, 0, 4);
1688 if (NT_STATUS_IS_OK(status)) {
1689 printf("unlock1 succeeded! This is a locking bug\n");
1690 correct = false;
1691 } else {
1692 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1693 NT_STATUS_RANGE_NOT_LOCKED)) {
1694 return false;
1698 status = cli_unlock(cli, fnum1, 0, 8);
1699 if (NT_STATUS_IS_OK(status)) {
1700 printf("unlock2 succeeded! This is a locking bug\n");
1701 correct = false;
1702 } else {
1703 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1704 NT_STATUS_RANGE_NOT_LOCKED)) {
1705 return false;
1709 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1710 if (NT_STATUS_IS_OK(status)) {
1711 printf("lock3 succeeded! This is a locking bug\n");
1712 correct = false;
1713 } else {
1714 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1715 NT_STATUS_LOCK_NOT_GRANTED)) {
1716 return false;
1720 cli_setpid(cli, 1);
1722 status = cli_close(cli, fnum1);
1723 if (!NT_STATUS_IS_OK(status)) {
1724 printf("close1 failed (%s)\n", nt_errstr(status));
1725 return False;
1728 status = cli_close(cli, fnum2);
1729 if (!NT_STATUS_IS_OK(status)) {
1730 printf("close2 failed (%s)\n", nt_errstr(status));
1731 return False;
1734 status = cli_close(cli, fnum3);
1735 if (!NT_STATUS_IS_OK(status)) {
1736 printf("close3 failed (%s)\n", nt_errstr(status));
1737 return False;
1740 if (!torture_close_connection(cli)) {
1741 correct = False;
1744 printf("locktest2 finished\n");
1746 return correct;
1751 This test checks that
1753 1) the server supports the full offset range in lock requests
1755 static bool run_locktest3(int dummy)
1757 static struct cli_state *cli1, *cli2;
1758 const char *fname = "\\lockt3.lck";
1759 uint16_t fnum1, fnum2;
1760 int i;
1761 uint32_t offset;
1762 bool correct = True;
1763 NTSTATUS status;
1765 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1767 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1768 return False;
1770 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1771 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1773 printf("starting locktest3\n");
1775 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1777 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1778 &fnum1);
1779 if (!NT_STATUS_IS_OK(status)) {
1780 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1781 return False;
1784 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1785 if (!NT_STATUS_IS_OK(status)) {
1786 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1787 return False;
1790 for (offset=i=0;i<torture_numops;i++) {
1791 NEXT_OFFSET;
1793 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1794 if (!NT_STATUS_IS_OK(status)) {
1795 printf("lock1 %d failed (%s)\n",
1797 nt_errstr(status));
1798 return False;
1801 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1802 if (!NT_STATUS_IS_OK(status)) {
1803 printf("lock2 %d failed (%s)\n",
1805 nt_errstr(status));
1806 return False;
1810 for (offset=i=0;i<torture_numops;i++) {
1811 NEXT_OFFSET;
1813 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1814 if (NT_STATUS_IS_OK(status)) {
1815 printf("error: lock1 %d succeeded!\n", i);
1816 return False;
1819 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1820 if (NT_STATUS_IS_OK(status)) {
1821 printf("error: lock2 %d succeeded!\n", i);
1822 return False;
1825 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1826 if (NT_STATUS_IS_OK(status)) {
1827 printf("error: lock3 %d succeeded!\n", i);
1828 return False;
1831 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1832 if (NT_STATUS_IS_OK(status)) {
1833 printf("error: lock4 %d succeeded!\n", i);
1834 return False;
1838 for (offset=i=0;i<torture_numops;i++) {
1839 NEXT_OFFSET;
1841 status = cli_unlock(cli1, fnum1, offset-1, 1);
1842 if (!NT_STATUS_IS_OK(status)) {
1843 printf("unlock1 %d failed (%s)\n",
1845 nt_errstr(status));
1846 return False;
1849 status = cli_unlock(cli2, fnum2, offset-2, 1);
1850 if (!NT_STATUS_IS_OK(status)) {
1851 printf("unlock2 %d failed (%s)\n",
1853 nt_errstr(status));
1854 return False;
1858 status = cli_close(cli1, fnum1);
1859 if (!NT_STATUS_IS_OK(status)) {
1860 printf("close1 failed (%s)\n", nt_errstr(status));
1861 return False;
1864 status = cli_close(cli2, fnum2);
1865 if (!NT_STATUS_IS_OK(status)) {
1866 printf("close2 failed (%s)\n", nt_errstr(status));
1867 return False;
1870 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1871 if (!NT_STATUS_IS_OK(status)) {
1872 printf("unlink failed (%s)\n", nt_errstr(status));
1873 return False;
1876 if (!torture_close_connection(cli1)) {
1877 correct = False;
1880 if (!torture_close_connection(cli2)) {
1881 correct = False;
1884 printf("finished locktest3\n");
1886 return correct;
1889 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1890 char *buf, off_t offset, size_t size,
1891 size_t *nread, size_t expect)
1893 NTSTATUS status;
1894 size_t l_nread;
1896 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1898 if(!NT_STATUS_IS_OK(status)) {
1899 return false;
1900 } else if (l_nread != expect) {
1901 return false;
1904 if (nread) {
1905 *nread = l_nread;
1908 return true;
1911 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1912 printf("** "); correct = False; \
1916 looks at overlapping locks
1918 static bool run_locktest4(int dummy)
1920 static struct cli_state *cli1, *cli2;
1921 const char *fname = "\\lockt4.lck";
1922 uint16_t fnum1, fnum2, f;
1923 bool ret;
1924 char buf[1000];
1925 bool correct = True;
1926 NTSTATUS status;
1928 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1929 return False;
1932 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1933 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1935 printf("starting locktest4\n");
1937 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1939 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1940 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1942 memset(buf, 0, sizeof(buf));
1944 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1945 NULL);
1946 if (!NT_STATUS_IS_OK(status)) {
1947 printf("Failed to create file: %s\n", nt_errstr(status));
1948 correct = False;
1949 goto fail;
1952 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1953 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1954 EXPECTED(ret, False);
1955 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1957 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1958 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1959 EXPECTED(ret, True);
1960 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1962 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1963 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1964 EXPECTED(ret, False);
1965 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1967 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1968 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1969 EXPECTED(ret, True);
1970 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1972 ret = (cli_setpid(cli1, 1),
1973 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1974 (cli_setpid(cli1, 2),
1975 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1976 EXPECTED(ret, False);
1977 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1979 ret = (cli_setpid(cli1, 1),
1980 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1981 (cli_setpid(cli1, 2),
1982 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1983 EXPECTED(ret, True);
1984 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1986 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1987 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1988 EXPECTED(ret, True);
1989 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1991 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1992 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1993 EXPECTED(ret, False);
1994 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1996 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1997 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1998 EXPECTED(ret, False);
1999 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2001 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2002 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2003 EXPECTED(ret, True);
2004 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2006 ret = (cli_setpid(cli1, 1),
2007 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2008 (cli_setpid(cli1, 2),
2009 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2010 EXPECTED(ret, False);
2011 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2013 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2014 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2015 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2016 EXPECTED(ret, False);
2017 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2020 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2021 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2022 EXPECTED(ret, False);
2023 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2025 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2026 ret = NT_STATUS_IS_OK(status);
2027 if (ret) {
2028 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2029 NULL);
2030 ret = NT_STATUS_IS_OK(status);
2032 EXPECTED(ret, False);
2033 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2036 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2037 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2038 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2039 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2040 EXPECTED(ret, True);
2041 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2044 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2045 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2046 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2047 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2048 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2049 150, 4, NULL))) &&
2050 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2051 EXPECTED(ret, True);
2052 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2054 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2055 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2056 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2057 160, 4, NULL)) &&
2058 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2059 EXPECTED(ret, True);
2060 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2062 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2063 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2064 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2065 170, 4, NULL)) &&
2066 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2067 EXPECTED(ret, True);
2068 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2070 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2071 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2072 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2073 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2074 190, 4, NULL)) &&
2075 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2076 EXPECTED(ret, True);
2077 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2079 cli_close(cli1, fnum1);
2080 cli_close(cli2, fnum2);
2081 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2082 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2083 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2084 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2085 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2086 NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2087 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2088 cli_close(cli1, f);
2089 cli_close(cli1, fnum1);
2090 EXPECTED(ret, True);
2091 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2093 fail:
2094 cli_close(cli1, fnum1);
2095 cli_close(cli2, fnum2);
2096 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2097 torture_close_connection(cli1);
2098 torture_close_connection(cli2);
2100 printf("finished locktest4\n");
2101 return correct;
2105 looks at lock upgrade/downgrade.
2107 static bool run_locktest5(int dummy)
2109 static struct cli_state *cli1, *cli2;
2110 const char *fname = "\\lockt5.lck";
2111 uint16_t fnum1, fnum2, fnum3;
2112 bool ret;
2113 char buf[1000];
2114 bool correct = True;
2115 NTSTATUS status;
2117 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2118 return False;
2121 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2122 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2124 printf("starting locktest5\n");
2126 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2128 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2129 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2130 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2132 memset(buf, 0, sizeof(buf));
2134 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2135 NULL);
2136 if (!NT_STATUS_IS_OK(status)) {
2137 printf("Failed to create file: %s\n", nt_errstr(status));
2138 correct = False;
2139 goto fail;
2142 /* Check for NT bug... */
2143 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2144 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2145 cli_close(cli1, fnum1);
2146 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2147 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2148 ret = NT_STATUS_IS_OK(status);
2149 EXPECTED(ret, True);
2150 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2151 cli_close(cli1, fnum1);
2152 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2153 cli_unlock(cli1, fnum3, 0, 1);
2155 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2156 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2157 EXPECTED(ret, True);
2158 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2160 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2161 ret = NT_STATUS_IS_OK(status);
2162 EXPECTED(ret, False);
2164 printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2166 /* Unlock the process 2 lock. */
2167 cli_unlock(cli2, fnum2, 0, 4);
2169 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2170 ret = NT_STATUS_IS_OK(status);
2171 EXPECTED(ret, False);
2173 printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2175 /* Unlock the process 1 fnum3 lock. */
2176 cli_unlock(cli1, fnum3, 0, 4);
2178 /* Stack 2 more locks here. */
2179 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2180 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2182 EXPECTED(ret, True);
2183 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2185 /* Unlock the first process lock, then check this was the WRITE lock that was
2186 removed. */
2188 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2189 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2191 EXPECTED(ret, True);
2192 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2194 /* Unlock the process 2 lock. */
2195 cli_unlock(cli2, fnum2, 0, 4);
2197 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2199 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2200 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2201 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2203 EXPECTED(ret, True);
2204 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2206 /* Ensure the next unlock fails. */
2207 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2208 EXPECTED(ret, False);
2209 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2211 /* Ensure connection 2 can get a write lock. */
2212 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2213 ret = NT_STATUS_IS_OK(status);
2214 EXPECTED(ret, True);
2216 printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2219 fail:
2220 cli_close(cli1, fnum1);
2221 cli_close(cli2, fnum2);
2222 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2223 if (!torture_close_connection(cli1)) {
2224 correct = False;
2226 if (!torture_close_connection(cli2)) {
2227 correct = False;
2230 printf("finished locktest5\n");
2232 return correct;
2236 tries the unusual lockingX locktype bits
2238 static bool run_locktest6(int dummy)
2240 static struct cli_state *cli;
2241 const char *fname[1] = { "\\lock6.txt" };
2242 int i;
2243 uint16_t fnum;
2244 NTSTATUS status;
2246 if (!torture_open_connection(&cli, 0)) {
2247 return False;
2250 smbXcli_conn_set_sockopt(cli->conn, sockops);
2252 printf("starting locktest6\n");
2254 for (i=0;i<1;i++) {
2255 printf("Testing %s\n", fname[i]);
2257 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2259 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2260 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2261 cli_close(cli, fnum);
2262 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2264 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2265 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2266 cli_close(cli, fnum);
2267 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2269 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2272 torture_close_connection(cli);
2274 printf("finished locktest6\n");
2275 return True;
2278 static bool run_locktest7(int dummy)
2280 struct cli_state *cli1;
2281 const char *fname = "\\lockt7.lck";
2282 uint16_t fnum1;
2283 char buf[200];
2284 bool correct = False;
2285 size_t nread;
2286 NTSTATUS status;
2288 if (!torture_open_connection(&cli1, 0)) {
2289 return False;
2292 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2294 printf("starting locktest7\n");
2296 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2298 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2300 memset(buf, 0, sizeof(buf));
2302 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2303 NULL);
2304 if (!NT_STATUS_IS_OK(status)) {
2305 printf("Failed to create file: %s\n", nt_errstr(status));
2306 goto fail;
2309 cli_setpid(cli1, 1);
2311 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2312 if (!NT_STATUS_IS_OK(status)) {
2313 printf("Unable to apply read lock on range 130:4, "
2314 "error was %s\n", nt_errstr(status));
2315 goto fail;
2316 } else {
2317 printf("pid1 successfully locked range 130:4 for READ\n");
2320 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2321 if (!NT_STATUS_IS_OK(status)) {
2322 printf("pid1 unable to read the range 130:4, error was %s\n",
2323 nt_errstr(status));
2324 goto fail;
2325 } else if (nread != 4) {
2326 printf("pid1 unable to read the range 130:4, "
2327 "recv %ld req %d\n", (unsigned long)nread, 4);
2328 goto fail;
2329 } else {
2330 printf("pid1 successfully read the range 130:4\n");
2333 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2334 if (!NT_STATUS_IS_OK(status)) {
2335 printf("pid1 unable to write to the range 130:4, error was "
2336 "%s\n", nt_errstr(status));
2337 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2338 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2339 goto fail;
2341 } else {
2342 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2343 goto fail;
2346 cli_setpid(cli1, 2);
2348 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2349 if (!NT_STATUS_IS_OK(status)) {
2350 printf("pid2 unable to read the range 130:4, error was %s\n",
2351 nt_errstr(status));
2352 goto fail;
2353 } else if (nread != 4) {
2354 printf("pid2 unable to read the range 130:4, "
2355 "recv %ld req %d\n", (unsigned long)nread, 4);
2356 goto fail;
2357 } else {
2358 printf("pid2 successfully read the range 130:4\n");
2361 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2362 if (!NT_STATUS_IS_OK(status)) {
2363 printf("pid2 unable to write to the range 130:4, error was "
2364 "%s\n", nt_errstr(status));
2365 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2366 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2367 goto fail;
2369 } else {
2370 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2371 goto fail;
2374 cli_setpid(cli1, 1);
2375 cli_unlock(cli1, fnum1, 130, 4);
2377 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2378 if (!NT_STATUS_IS_OK(status)) {
2379 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2380 goto fail;
2381 } else {
2382 printf("pid1 successfully locked range 130:4 for WRITE\n");
2385 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2386 if (!NT_STATUS_IS_OK(status)) {
2387 printf("pid1 unable to read the range 130:4, error was %s\n",
2388 nt_errstr(status));
2389 goto fail;
2390 } else if (nread != 4) {
2391 printf("pid1 unable to read the range 130:4, "
2392 "recv %ld req %d\n", (unsigned long)nread, 4);
2393 goto fail;
2394 } else {
2395 printf("pid1 successfully read the range 130:4\n");
2398 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2399 if (!NT_STATUS_IS_OK(status)) {
2400 printf("pid1 unable to write to the range 130:4, error was "
2401 "%s\n", nt_errstr(status));
2402 goto fail;
2403 } else {
2404 printf("pid1 successfully wrote to the range 130:4\n");
2407 cli_setpid(cli1, 2);
2409 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2410 if (!NT_STATUS_IS_OK(status)) {
2411 printf("pid2 unable to read the range 130:4, error was "
2412 "%s\n", nt_errstr(status));
2413 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2414 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2415 goto fail;
2417 } else {
2418 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2419 (unsigned long)nread);
2420 goto fail;
2423 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2424 if (!NT_STATUS_IS_OK(status)) {
2425 printf("pid2 unable to write to the range 130:4, error was "
2426 "%s\n", nt_errstr(status));
2427 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2428 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2429 goto fail;
2431 } else {
2432 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2433 goto fail;
2436 cli_unlock(cli1, fnum1, 130, 0);
2437 correct = True;
2439 fail:
2440 cli_close(cli1, fnum1);
2441 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2442 torture_close_connection(cli1);
2444 printf("finished locktest7\n");
2445 return correct;
2449 * This demonstrates a problem with our use of GPFS share modes: A file
2450 * descriptor sitting in the pending close queue holding a GPFS share mode
2451 * blocks opening a file another time. Happens with Word 2007 temp files.
2452 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2453 * open is denied with NT_STATUS_SHARING_VIOLATION.
2456 static bool run_locktest8(int dummy)
2458 struct cli_state *cli1;
2459 const char *fname = "\\lockt8.lck";
2460 uint16_t fnum1, fnum2;
2461 char buf[200];
2462 bool correct = False;
2463 NTSTATUS status;
2465 if (!torture_open_connection(&cli1, 0)) {
2466 return False;
2469 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2471 printf("starting locktest8\n");
2473 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2475 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2476 &fnum1);
2477 if (!NT_STATUS_IS_OK(status)) {
2478 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2479 return false;
2482 memset(buf, 0, sizeof(buf));
2484 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2485 if (!NT_STATUS_IS_OK(status)) {
2486 d_fprintf(stderr, "cli_openx second time returned %s\n",
2487 nt_errstr(status));
2488 goto fail;
2491 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2492 if (!NT_STATUS_IS_OK(status)) {
2493 printf("Unable to apply read lock on range 1:1, error was "
2494 "%s\n", nt_errstr(status));
2495 goto fail;
2498 status = cli_close(cli1, fnum1);
2499 if (!NT_STATUS_IS_OK(status)) {
2500 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2501 goto fail;
2504 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2505 if (!NT_STATUS_IS_OK(status)) {
2506 d_fprintf(stderr, "cli_openx third time returned %s\n",
2507 nt_errstr(status));
2508 goto fail;
2511 correct = true;
2513 fail:
2514 cli_close(cli1, fnum1);
2515 cli_close(cli1, fnum2);
2516 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2517 torture_close_connection(cli1);
2519 printf("finished locktest8\n");
2520 return correct;
2524 * This test is designed to be run in conjunction with
2525 * external NFS or POSIX locks taken in the filesystem.
2526 * It checks that the smbd server will block until the
2527 * lock is released and then acquire it. JRA.
2530 static bool got_alarm;
2531 static struct cli_state *alarm_cli;
2533 static void alarm_handler(int dummy)
2535 got_alarm = True;
2538 static void alarm_handler_parent(int dummy)
2540 smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_OK);
2543 static void do_local_lock(int read_fd, int write_fd)
2545 int fd;
2546 char c = '\0';
2547 struct flock lock;
2548 const char *local_pathname = NULL;
2549 int ret;
2551 local_pathname = talloc_asprintf(talloc_tos(),
2552 "%s/lockt9.lck", local_path);
2553 if (!local_pathname) {
2554 printf("child: alloc fail\n");
2555 exit(1);
2558 unlink(local_pathname);
2559 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2560 if (fd == -1) {
2561 printf("child: open of %s failed %s.\n",
2562 local_pathname, strerror(errno));
2563 exit(1);
2566 /* Now take a fcntl lock. */
2567 lock.l_type = F_WRLCK;
2568 lock.l_whence = SEEK_SET;
2569 lock.l_start = 0;
2570 lock.l_len = 4;
2571 lock.l_pid = getpid();
2573 ret = fcntl(fd,F_SETLK,&lock);
2574 if (ret == -1) {
2575 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2576 local_pathname, strerror(errno));
2577 exit(1);
2578 } else {
2579 printf("child: got lock 0:4 on file %s.\n",
2580 local_pathname );
2581 fflush(stdout);
2584 CatchSignal(SIGALRM, alarm_handler);
2585 alarm(5);
2586 /* Signal the parent. */
2587 if (write(write_fd, &c, 1) != 1) {
2588 printf("child: start signal fail %s.\n",
2589 strerror(errno));
2590 exit(1);
2592 alarm(0);
2594 alarm(10);
2595 /* Wait for the parent to be ready. */
2596 if (read(read_fd, &c, 1) != 1) {
2597 printf("child: reply signal fail %s.\n",
2598 strerror(errno));
2599 exit(1);
2601 alarm(0);
2603 sleep(5);
2604 close(fd);
2605 printf("child: released lock 0:4 on file %s.\n",
2606 local_pathname );
2607 fflush(stdout);
2608 exit(0);
2611 static bool run_locktest9(int dummy)
2613 struct cli_state *cli1;
2614 const char *fname = "\\lockt9.lck";
2615 uint16_t fnum;
2616 bool correct = False;
2617 int pipe_in[2], pipe_out[2];
2618 pid_t child_pid;
2619 char c = '\0';
2620 int ret;
2621 struct timeval start;
2622 double seconds;
2623 NTSTATUS status;
2625 printf("starting locktest9\n");
2627 if (local_path == NULL) {
2628 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2629 return false;
2632 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2633 return false;
2636 child_pid = fork();
2637 if (child_pid == -1) {
2638 return false;
2641 if (child_pid == 0) {
2642 /* Child. */
2643 do_local_lock(pipe_out[0], pipe_in[1]);
2644 exit(0);
2647 close(pipe_out[0]);
2648 close(pipe_in[1]);
2649 pipe_out[0] = -1;
2650 pipe_in[1] = -1;
2652 /* Parent. */
2653 ret = read(pipe_in[0], &c, 1);
2654 if (ret != 1) {
2655 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2656 strerror(errno));
2657 return false;
2660 if (!torture_open_connection(&cli1, 0)) {
2661 return false;
2664 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2666 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE,
2667 &fnum);
2668 if (!NT_STATUS_IS_OK(status)) {
2669 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2670 return false;
2673 /* Ensure the child has the lock. */
2674 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2675 if (NT_STATUS_IS_OK(status)) {
2676 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2677 goto fail;
2678 } else {
2679 d_printf("Child has the lock.\n");
2682 /* Tell the child to wait 5 seconds then exit. */
2683 ret = write(pipe_out[1], &c, 1);
2684 if (ret != 1) {
2685 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2686 strerror(errno));
2687 goto fail;
2690 /* Wait 20 seconds for the lock. */
2691 alarm_cli = cli1;
2692 CatchSignal(SIGALRM, alarm_handler_parent);
2693 alarm(20);
2695 start = timeval_current();
2697 status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2698 if (!NT_STATUS_IS_OK(status)) {
2699 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2700 "%s\n", nt_errstr(status));
2701 goto fail_nofd;
2703 alarm(0);
2705 seconds = timeval_elapsed(&start);
2707 printf("Parent got the lock after %.2f seconds.\n",
2708 seconds);
2710 status = cli_close(cli1, fnum);
2711 if (!NT_STATUS_IS_OK(status)) {
2712 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2713 goto fail;
2716 correct = true;
2718 fail:
2719 cli_close(cli1, fnum);
2720 torture_close_connection(cli1);
2722 fail_nofd:
2724 printf("finished locktest9\n");
2725 return correct;
2729 test whether fnums and tids open on one VC are available on another (a major
2730 security hole)
2732 static bool run_fdpasstest(int dummy)
2734 struct cli_state *cli1, *cli2;
2735 const char *fname = "\\fdpass.tst";
2736 uint16_t fnum1;
2737 char buf[1024];
2738 NTSTATUS status;
2740 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2741 return False;
2743 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2744 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2746 printf("starting fdpasstest\n");
2748 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2750 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2751 &fnum1);
2752 if (!NT_STATUS_IS_OK(status)) {
2753 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2754 return False;
2757 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2758 13, NULL);
2759 if (!NT_STATUS_IS_OK(status)) {
2760 printf("write failed (%s)\n", nt_errstr(status));
2761 return False;
2764 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
2765 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2766 cli_setpid(cli2, cli_getpid(cli1));
2768 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
2769 printf("read succeeded! nasty security hole [%s]\n", buf);
2770 return false;
2773 cli_close(cli1, fnum1);
2774 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2776 torture_close_connection(cli1);
2777 torture_close_connection(cli2);
2779 printf("finished fdpasstest\n");
2780 return True;
2783 static bool run_fdsesstest(int dummy)
2785 struct cli_state *cli;
2786 uint16_t new_vuid;
2787 uint16_t saved_vuid;
2788 uint32_t new_cnum;
2789 uint32_t saved_cnum;
2790 const char *fname = "\\fdsess.tst";
2791 const char *fname1 = "\\fdsess1.tst";
2792 uint16_t fnum1;
2793 uint16_t fnum2;
2794 char buf[1024];
2795 bool ret = True;
2796 NTSTATUS status;
2798 if (!torture_open_connection(&cli, 0))
2799 return False;
2800 smbXcli_conn_set_sockopt(cli->conn, sockops);
2802 if (!torture_cli_session_setup2(cli, &new_vuid))
2803 return False;
2805 saved_cnum = cli_state_get_tid(cli);
2806 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
2807 return False;
2808 new_cnum = cli_state_get_tid(cli);
2809 cli_state_set_tid(cli, saved_cnum);
2811 printf("starting fdsesstest\n");
2813 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2814 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2816 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2817 if (!NT_STATUS_IS_OK(status)) {
2818 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2819 return False;
2822 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2823 NULL);
2824 if (!NT_STATUS_IS_OK(status)) {
2825 printf("write failed (%s)\n", nt_errstr(status));
2826 return False;
2829 saved_vuid = cli_state_get_uid(cli);
2830 cli_state_set_uid(cli, new_vuid);
2832 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2833 printf("read succeeded with different vuid! "
2834 "nasty security hole [%s]\n", buf);
2835 ret = false;
2837 /* Try to open a file with different vuid, samba cnum. */
2838 if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2839 printf("create with different vuid, same cnum succeeded.\n");
2840 cli_close(cli, fnum2);
2841 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2842 } else {
2843 printf("create with different vuid, same cnum failed.\n");
2844 printf("This will cause problems with service clients.\n");
2845 ret = False;
2848 cli_state_set_uid(cli, saved_vuid);
2850 /* Try with same vuid, different cnum. */
2851 cli_state_set_tid(cli, new_cnum);
2853 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2854 printf("read succeeded with different cnum![%s]\n", buf);
2855 ret = false;
2858 cli_state_set_tid(cli, saved_cnum);
2859 cli_close(cli, fnum1);
2860 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2862 torture_close_connection(cli);
2864 printf("finished fdsesstest\n");
2865 return ret;
2869 This test checks that
2871 1) the server does not allow an unlink on a file that is open
2873 static bool run_unlinktest(int dummy)
2875 struct cli_state *cli;
2876 const char *fname = "\\unlink.tst";
2877 uint16_t fnum;
2878 bool correct = True;
2879 NTSTATUS status;
2881 if (!torture_open_connection(&cli, 0)) {
2882 return False;
2885 smbXcli_conn_set_sockopt(cli->conn, sockops);
2887 printf("starting unlink test\n");
2889 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2891 cli_setpid(cli, 1);
2893 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2894 if (!NT_STATUS_IS_OK(status)) {
2895 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2896 return False;
2899 status = cli_unlink(cli, fname,
2900 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2901 if (NT_STATUS_IS_OK(status)) {
2902 printf("error: server allowed unlink on an open file\n");
2903 correct = False;
2904 } else {
2905 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
2906 NT_STATUS_SHARING_VIOLATION);
2909 cli_close(cli, fnum);
2910 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2912 if (!torture_close_connection(cli)) {
2913 correct = False;
2916 printf("unlink test finished\n");
2918 return correct;
2923 test how many open files this server supports on the one socket
2925 static bool run_maxfidtest(int dummy)
2927 struct cli_state *cli;
2928 fstring fname;
2929 uint16_t fnums[0x11000];
2930 int i;
2931 int retries=4;
2932 bool correct = True;
2933 NTSTATUS status;
2935 cli = current_cli;
2937 if (retries <= 0) {
2938 printf("failed to connect\n");
2939 return False;
2942 smbXcli_conn_set_sockopt(cli->conn, sockops);
2944 for (i=0; i<0x11000; i++) {
2945 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2946 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2947 &fnums[i]);
2948 if (!NT_STATUS_IS_OK(status)) {
2949 printf("open of %s failed (%s)\n",
2950 fname, nt_errstr(status));
2951 printf("maximum fnum is %d\n", i);
2952 break;
2954 printf("%6d\r", i);
2956 printf("%6d\n", i);
2957 i--;
2959 printf("cleaning up\n");
2960 for (;i>=0;i--) {
2961 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2962 cli_close(cli, fnums[i]);
2964 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2965 if (!NT_STATUS_IS_OK(status)) {
2966 printf("unlink of %s failed (%s)\n",
2967 fname, nt_errstr(status));
2968 correct = False;
2970 printf("%6d\r", i);
2972 printf("%6d\n", 0);
2974 printf("maxfid test finished\n");
2975 if (!torture_close_connection(cli)) {
2976 correct = False;
2978 return correct;
2981 /* generate a random buffer */
2982 static void rand_buf(char *buf, int len)
2984 while (len--) {
2985 *buf = (char)sys_random();
2986 buf++;
2990 /* send smb negprot commands, not reading the response */
2991 static bool run_negprot_nowait(int dummy)
2993 struct tevent_context *ev;
2994 int i;
2995 struct cli_state *cli;
2996 bool correct = True;
2998 printf("starting negprot nowait test\n");
3000 ev = samba_tevent_context_init(talloc_tos());
3001 if (ev == NULL) {
3002 return false;
3005 if (!(cli = open_nbt_connection())) {
3006 TALLOC_FREE(ev);
3007 return False;
3010 for (i=0;i<50000;i++) {
3011 struct tevent_req *req;
3013 req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
3014 PROTOCOL_CORE, PROTOCOL_NT1, 0);
3015 if (req == NULL) {
3016 TALLOC_FREE(ev);
3017 return false;
3019 if (!tevent_req_poll(req, ev)) {
3020 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3021 strerror(errno));
3022 TALLOC_FREE(ev);
3023 return false;
3025 TALLOC_FREE(req);
3028 if (torture_close_connection(cli)) {
3029 correct = False;
3032 printf("finished negprot nowait test\n");
3034 return correct;
3037 /* send smb negprot commands, not reading the response */
3038 static bool run_bad_nbt_session(int dummy)
3040 struct nmb_name called, calling;
3041 struct sockaddr_storage ss;
3042 NTSTATUS status;
3043 int fd;
3044 bool ret;
3046 printf("starting bad nbt session test\n");
3048 make_nmb_name(&calling, myname, 0x0);
3049 make_nmb_name(&called , host, 0x20);
3051 if (!resolve_name(host, &ss, 0x20, true)) {
3052 d_fprintf(stderr, "Could not resolve name %s\n", host);
3053 return false;
3056 status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3057 if (!NT_STATUS_IS_OK(status)) {
3058 d_fprintf(stderr, "open_socket_out failed: %s\n",
3059 nt_errstr(status));
3060 return false;
3063 ret = cli_bad_session_request(fd, &calling, &called);
3064 close(fd);
3065 if (!ret) {
3066 d_fprintf(stderr, "open_socket_out failed: %s\n",
3067 nt_errstr(status));
3068 return false;
3071 printf("finished bad nbt session test\n");
3072 return true;
3075 /* send random IPC commands */
3076 static bool run_randomipc(int dummy)
3078 char *rparam = NULL;
3079 char *rdata = NULL;
3080 unsigned int rdrcnt,rprcnt;
3081 char param[1024];
3082 int api, param_len, i;
3083 struct cli_state *cli;
3084 bool correct = True;
3085 int count = 50000;
3087 printf("starting random ipc test\n");
3089 if (!torture_open_connection(&cli, 0)) {
3090 return False;
3093 for (i=0;i<count;i++) {
3094 api = sys_random() % 500;
3095 param_len = (sys_random() % 64);
3097 rand_buf(param, param_len);
3099 SSVAL(param,0,api);
3101 cli_api(cli,
3102 param, param_len, 8,
3103 NULL, 0, CLI_BUFFER_SIZE,
3104 &rparam, &rprcnt,
3105 &rdata, &rdrcnt);
3106 if (i % 100 == 0) {
3107 printf("%d/%d\r", i,count);
3110 printf("%d/%d\n", i, count);
3112 if (!torture_close_connection(cli)) {
3113 correct = False;
3116 SAFE_FREE(rparam);
3117 SAFE_FREE(rdata);
3119 printf("finished random ipc test\n");
3121 return correct;
3126 static void browse_callback(const char *sname, uint32_t stype,
3127 const char *comment, void *state)
3129 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3135 This test checks the browse list code
3138 static bool run_browsetest(int dummy)
3140 static struct cli_state *cli;
3141 bool correct = True;
3143 printf("starting browse test\n");
3145 if (!torture_open_connection(&cli, 0)) {
3146 return False;
3149 printf("domain list:\n");
3150 cli_NetServerEnum(cli, cli->server_domain,
3151 SV_TYPE_DOMAIN_ENUM,
3152 browse_callback, NULL);
3154 printf("machine list:\n");
3155 cli_NetServerEnum(cli, cli->server_domain,
3156 SV_TYPE_ALL,
3157 browse_callback, NULL);
3159 if (!torture_close_connection(cli)) {
3160 correct = False;
3163 printf("browse test finished\n");
3165 return correct;
3169 static bool check_attributes(struct cli_state *cli,
3170 const char *fname,
3171 uint16_t expected_attrs)
3173 uint16_t attrs = 0;
3174 NTSTATUS status = cli_getatr(cli,
3175 fname,
3176 &attrs,
3177 NULL,
3178 NULL);
3179 if (!NT_STATUS_IS_OK(status)) {
3180 printf("cli_getatr failed with %s\n",
3181 nt_errstr(status));
3182 return false;
3184 if (attrs != expected_attrs) {
3185 printf("Attributes incorrect 0x%x, should be 0x%x\n",
3186 (unsigned int)attrs,
3187 (unsigned int)expected_attrs);
3188 return false;
3190 return true;
3194 This checks how the getatr calls works
3196 static bool run_attrtest(int dummy)
3198 struct cli_state *cli;
3199 uint16_t fnum;
3200 time_t t, t2;
3201 const char *fname = "\\attrib123456789.tst";
3202 bool correct = True;
3203 NTSTATUS status;
3205 printf("starting attrib test\n");
3207 if (!torture_open_connection(&cli, 0)) {
3208 return False;
3211 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3212 cli_openx(cli, fname,
3213 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3214 cli_close(cli, fnum);
3216 status = cli_getatr(cli, fname, NULL, NULL, &t);
3217 if (!NT_STATUS_IS_OK(status)) {
3218 printf("getatr failed (%s)\n", nt_errstr(status));
3219 correct = False;
3222 if (labs(t - time(NULL)) > 60*60*24*10) {
3223 printf("ERROR: SMBgetatr bug. time is %s",
3224 ctime(&t));
3225 t = time(NULL);
3226 correct = True;
3229 t2 = t-60*60*24; /* 1 day ago */
3231 status = cli_setatr(cli, fname, 0, t2);
3232 if (!NT_STATUS_IS_OK(status)) {
3233 printf("setatr failed (%s)\n", nt_errstr(status));
3234 correct = True;
3237 status = cli_getatr(cli, fname, NULL, NULL, &t);
3238 if (!NT_STATUS_IS_OK(status)) {
3239 printf("getatr failed (%s)\n", nt_errstr(status));
3240 correct = True;
3243 if (t != t2) {
3244 printf("ERROR: getatr/setatr bug. times are\n%s",
3245 ctime(&t));
3246 printf("%s", ctime(&t2));
3247 correct = True;
3250 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3252 /* Check cli_setpathinfo_basic() */
3253 /* Re-create the file. */
3254 status = cli_openx(cli, fname,
3255 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3256 if (!NT_STATUS_IS_OK(status)) {
3257 printf("Failed to recreate %s (%s)\n",
3258 fname, nt_errstr(status));
3259 correct = false;
3261 cli_close(cli, fnum);
3263 status = cli_setpathinfo_basic(cli,
3264 fname,
3265 0, /* create */
3266 0, /* access */
3267 0, /* write */
3268 0, /* change */
3269 FILE_ATTRIBUTE_SYSTEM |
3270 FILE_ATTRIBUTE_HIDDEN |
3271 FILE_ATTRIBUTE_READONLY);
3272 if (!NT_STATUS_IS_OK(status)) {
3273 printf("cli_setpathinfo_basic failed with %s\n",
3274 nt_errstr(status));
3275 correct = false;
3278 /* Check attributes are correct. */
3279 correct = check_attributes(cli,
3280 fname,
3281 FILE_ATTRIBUTE_SYSTEM |
3282 FILE_ATTRIBUTE_HIDDEN |
3283 FILE_ATTRIBUTE_READONLY);
3284 if (correct == false) {
3285 goto out;
3288 /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
3289 status = cli_setpathinfo_basic(cli,
3290 fname,
3291 0, /* create */
3292 0, /* access */
3293 0, /* write */
3294 0, /* change */
3295 FILE_ATTRIBUTE_NORMAL);
3296 if (!NT_STATUS_IS_OK(status)) {
3297 printf("cli_setpathinfo_basic failed with %s\n",
3298 nt_errstr(status));
3299 correct = false;
3302 /* Check attributes are correct. */
3303 correct = check_attributes(cli,
3304 fname,
3305 FILE_ATTRIBUTE_SYSTEM |
3306 FILE_ATTRIBUTE_HIDDEN |
3307 FILE_ATTRIBUTE_READONLY);
3308 if (correct == false) {
3309 goto out;
3312 /* Setting to (uint16_t)-1 should also be ignored. */
3313 status = cli_setpathinfo_basic(cli,
3314 fname,
3315 0, /* create */
3316 0, /* access */
3317 0, /* write */
3318 0, /* change */
3319 (uint16_t)-1);
3320 if (!NT_STATUS_IS_OK(status)) {
3321 printf("cli_setpathinfo_basic failed with %s\n",
3322 nt_errstr(status));
3323 correct = false;
3326 /* Check attributes are correct. */
3327 correct = check_attributes(cli,
3328 fname,
3329 FILE_ATTRIBUTE_SYSTEM |
3330 FILE_ATTRIBUTE_HIDDEN |
3331 FILE_ATTRIBUTE_READONLY);
3332 if (correct == false) {
3333 goto out;
3336 /* Setting to 0 should clear them all. */
3337 status = cli_setpathinfo_basic(cli,
3338 fname,
3339 0, /* create */
3340 0, /* access */
3341 0, /* write */
3342 0, /* change */
3344 if (!NT_STATUS_IS_OK(status)) {
3345 printf("cli_setpathinfo_basic failed with %s\n",
3346 nt_errstr(status));
3347 correct = false;
3350 /* Check attributes are correct. */
3351 correct = check_attributes(cli,
3352 fname,
3353 FILE_ATTRIBUTE_NORMAL);
3354 if (correct == false) {
3355 goto out;
3358 out:
3360 cli_unlink(cli,
3361 fname,
3362 FILE_ATTRIBUTE_SYSTEM |
3363 FILE_ATTRIBUTE_HIDDEN|
3364 FILE_ATTRIBUTE_READONLY);
3366 if (!torture_close_connection(cli)) {
3367 correct = False;
3370 printf("attrib test finished\n");
3372 return correct;
3377 This checks a couple of trans2 calls
3379 static bool run_trans2test(int dummy)
3381 struct cli_state *cli;
3382 uint16_t fnum;
3383 off_t size;
3384 time_t c_time, a_time, m_time;
3385 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3386 const char *fname = "\\trans2.tst";
3387 const char *dname = "\\trans2";
3388 const char *fname2 = "\\trans2\\trans2.tst";
3389 char *pname;
3390 bool correct = True;
3391 NTSTATUS status;
3392 uint32_t fs_attr;
3394 printf("starting trans2 test\n");
3396 if (!torture_open_connection(&cli, 0)) {
3397 return False;
3400 status = cli_get_fs_attr_info(cli, &fs_attr);
3401 if (!NT_STATUS_IS_OK(status)) {
3402 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3403 nt_errstr(status));
3404 correct = false;
3407 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3408 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3409 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3410 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3411 if (!NT_STATUS_IS_OK(status)) {
3412 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3413 correct = False;
3416 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3417 if (!NT_STATUS_IS_OK(status)) {
3418 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3419 correct = False;
3421 else if (strcmp(pname, fname)) {
3422 printf("qfilename gave different name? [%s] [%s]\n",
3423 fname, pname);
3424 correct = False;
3427 cli_close(cli, fnum);
3429 sleep(2);
3431 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3432 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3433 &fnum);
3434 if (!NT_STATUS_IS_OK(status)) {
3435 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3436 return False;
3438 cli_close(cli, fnum);
3440 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3441 NULL);
3442 if (!NT_STATUS_IS_OK(status)) {
3443 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3444 correct = False;
3445 } else {
3446 time_t t = time(NULL);
3448 if (c_time != m_time) {
3449 printf("create time=%s", ctime(&c_time));
3450 printf("modify time=%s", ctime(&m_time));
3451 printf("This system appears to have sticky create times\n");
3453 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
3454 printf("access time=%s", ctime(&a_time));
3455 printf("This system appears to set a midnight access time\n");
3456 correct = False;
3459 if (labs(m_time - t) > 60*60*24*7) {
3460 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3461 correct = False;
3466 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3467 cli_openx(cli, fname,
3468 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3469 cli_close(cli, fnum);
3470 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3471 &m_time_ts, &size, NULL, NULL);
3472 if (!NT_STATUS_IS_OK(status)) {
3473 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3474 correct = False;
3475 } else {
3476 if (w_time_ts.tv_sec < 60*60*24*2) {
3477 printf("write time=%s", ctime(&w_time_ts.tv_sec));
3478 printf("This system appears to set a initial 0 write time\n");
3479 correct = False;
3483 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3486 /* check if the server updates the directory modification time
3487 when creating a new file */
3488 status = cli_mkdir(cli, dname);
3489 if (!NT_STATUS_IS_OK(status)) {
3490 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3491 correct = False;
3493 sleep(3);
3494 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3495 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3496 if (!NT_STATUS_IS_OK(status)) {
3497 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3498 correct = False;
3501 cli_openx(cli, fname2,
3502 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3503 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3504 cli_close(cli, fnum);
3505 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3506 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3507 if (!NT_STATUS_IS_OK(status)) {
3508 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3509 correct = False;
3510 } else {
3511 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3512 == 0) {
3513 printf("This system does not update directory modification times\n");
3514 correct = False;
3517 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3518 cli_rmdir(cli, dname);
3520 if (!torture_close_connection(cli)) {
3521 correct = False;
3524 printf("trans2 test finished\n");
3526 return correct;
3530 This checks new W2K calls.
3533 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3535 uint8_t *buf = NULL;
3536 uint32_t len;
3537 NTSTATUS status;
3539 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3540 CLI_BUFFER_SIZE, NULL, &buf, &len);
3541 if (!NT_STATUS_IS_OK(status)) {
3542 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3543 nt_errstr(status));
3544 } else {
3545 printf("qfileinfo: level %d, len = %u\n", level, len);
3546 dump_data(0, (uint8_t *)buf, len);
3547 printf("\n");
3549 TALLOC_FREE(buf);
3550 return status;
3553 static bool run_w2ktest(int dummy)
3555 struct cli_state *cli;
3556 uint16_t fnum;
3557 const char *fname = "\\w2ktest\\w2k.tst";
3558 int level;
3559 bool correct = True;
3561 printf("starting w2k test\n");
3563 if (!torture_open_connection(&cli, 0)) {
3564 return False;
3567 cli_openx(cli, fname,
3568 O_RDWR | O_CREAT , DENY_NONE, &fnum);
3570 for (level = 1004; level < 1040; level++) {
3571 new_trans(cli, fnum, level);
3574 cli_close(cli, fnum);
3576 if (!torture_close_connection(cli)) {
3577 correct = False;
3580 printf("w2k test finished\n");
3582 return correct;
3587 this is a harness for some oplock tests
3589 static bool run_oplock1(int dummy)
3591 struct cli_state *cli1;
3592 const char *fname = "\\lockt1.lck";
3593 uint16_t fnum1;
3594 bool correct = True;
3595 NTSTATUS status;
3597 printf("starting oplock test 1\n");
3599 if (!torture_open_connection(&cli1, 0)) {
3600 return False;
3603 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3605 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3607 cli1->use_oplocks = True;
3609 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3610 &fnum1);
3611 if (!NT_STATUS_IS_OK(status)) {
3612 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3613 return False;
3616 cli1->use_oplocks = False;
3618 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3619 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3621 status = cli_close(cli1, fnum1);
3622 if (!NT_STATUS_IS_OK(status)) {
3623 printf("close2 failed (%s)\n", nt_errstr(status));
3624 return False;
3627 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3628 if (!NT_STATUS_IS_OK(status)) {
3629 printf("unlink failed (%s)\n", nt_errstr(status));
3630 return False;
3633 if (!torture_close_connection(cli1)) {
3634 correct = False;
3637 printf("finished oplock test 1\n");
3639 return correct;
3642 static bool run_oplock2(int dummy)
3644 struct cli_state *cli1, *cli2;
3645 const char *fname = "\\lockt2.lck";
3646 uint16_t fnum1, fnum2;
3647 int saved_use_oplocks = use_oplocks;
3648 char buf[4];
3649 bool correct = True;
3650 volatile bool *shared_correct;
3651 size_t nread;
3652 NTSTATUS status;
3654 shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
3655 *shared_correct = True;
3657 use_level_II_oplocks = True;
3658 use_oplocks = True;
3660 printf("starting oplock test 2\n");
3662 if (!torture_open_connection(&cli1, 0)) {
3663 use_level_II_oplocks = False;
3664 use_oplocks = saved_use_oplocks;
3665 return False;
3668 if (!torture_open_connection(&cli2, 1)) {
3669 use_level_II_oplocks = False;
3670 use_oplocks = saved_use_oplocks;
3671 return False;
3674 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3676 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3677 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3679 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3680 &fnum1);
3681 if (!NT_STATUS_IS_OK(status)) {
3682 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3683 return False;
3686 /* Don't need the globals any more. */
3687 use_level_II_oplocks = False;
3688 use_oplocks = saved_use_oplocks;
3690 if (fork() == 0) {
3691 /* Child code */
3692 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3693 if (!NT_STATUS_IS_OK(status)) {
3694 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3695 *shared_correct = False;
3696 exit(0);
3699 sleep(2);
3701 status = cli_close(cli2, fnum2);
3702 if (!NT_STATUS_IS_OK(status)) {
3703 printf("close2 failed (%s)\n", nt_errstr(status));
3704 *shared_correct = False;
3707 exit(0);
3710 sleep(2);
3712 /* Ensure cli1 processes the break. Empty file should always return 0
3713 * bytes. */
3714 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
3715 if (!NT_STATUS_IS_OK(status)) {
3716 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
3717 correct = false;
3718 } else if (nread != 0) {
3719 printf("read on empty fnum1 failed. recv %ld expected %d\n",
3720 (unsigned long)nread, 0);
3721 correct = false;
3724 /* Should now be at level II. */
3725 /* Test if sending a write locks causes a break to none. */
3726 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3727 if (!NT_STATUS_IS_OK(status)) {
3728 printf("lock failed (%s)\n", nt_errstr(status));
3729 correct = False;
3732 cli_unlock(cli1, fnum1, 0, 4);
3734 sleep(2);
3736 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3737 if (!NT_STATUS_IS_OK(status)) {
3738 printf("lock failed (%s)\n", nt_errstr(status));
3739 correct = False;
3742 cli_unlock(cli1, fnum1, 0, 4);
3744 sleep(2);
3746 cli_read(cli1, fnum1, buf, 0, 4, NULL);
3748 status = cli_close(cli1, fnum1);
3749 if (!NT_STATUS_IS_OK(status)) {
3750 printf("close1 failed (%s)\n", nt_errstr(status));
3751 correct = False;
3754 sleep(4);
3756 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3757 if (!NT_STATUS_IS_OK(status)) {
3758 printf("unlink failed (%s)\n", nt_errstr(status));
3759 correct = False;
3762 if (!torture_close_connection(cli1)) {
3763 correct = False;
3766 if (!*shared_correct) {
3767 correct = False;
3770 printf("finished oplock test 2\n");
3772 return correct;
3775 struct oplock4_state {
3776 struct tevent_context *ev;
3777 struct cli_state *cli;
3778 bool *got_break;
3779 uint16_t *fnum2;
3782 static void oplock4_got_break(struct tevent_req *req);
3783 static void oplock4_got_open(struct tevent_req *req);
3785 static bool run_oplock4(int dummy)
3787 struct tevent_context *ev;
3788 struct cli_state *cli1, *cli2;
3789 struct tevent_req *oplock_req, *open_req;
3790 const char *fname = "\\lockt4.lck";
3791 const char *fname_ln = "\\lockt4_ln.lck";
3792 uint16_t fnum1, fnum2;
3793 int saved_use_oplocks = use_oplocks;
3794 NTSTATUS status;
3795 bool correct = true;
3797 bool got_break;
3799 struct oplock4_state *state;
3801 printf("starting oplock test 4\n");
3803 if (!torture_open_connection(&cli1, 0)) {
3804 use_level_II_oplocks = false;
3805 use_oplocks = saved_use_oplocks;
3806 return false;
3809 if (!torture_open_connection(&cli2, 1)) {
3810 use_level_II_oplocks = false;
3811 use_oplocks = saved_use_oplocks;
3812 return false;
3815 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3816 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3818 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3819 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3821 /* Create the file. */
3822 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3823 &fnum1);
3824 if (!NT_STATUS_IS_OK(status)) {
3825 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3826 return false;
3829 status = cli_close(cli1, fnum1);
3830 if (!NT_STATUS_IS_OK(status)) {
3831 printf("close1 failed (%s)\n", nt_errstr(status));
3832 return false;
3835 /* Now create a hardlink. */
3836 status = cli_nt_hardlink(cli1, fname, fname_ln);
3837 if (!NT_STATUS_IS_OK(status)) {
3838 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3839 return false;
3842 /* Prove that opening hardlinks cause deny modes to conflict. */
3843 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3844 if (!NT_STATUS_IS_OK(status)) {
3845 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3846 return false;
3849 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3850 if (NT_STATUS_IS_OK(status)) {
3851 printf("open of %s succeeded - should fail with sharing violation.\n",
3852 fname_ln);
3853 return false;
3856 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3857 printf("open of %s should fail with sharing violation. Got %s\n",
3858 fname_ln, nt_errstr(status));
3859 return false;
3862 status = cli_close(cli1, fnum1);
3863 if (!NT_STATUS_IS_OK(status)) {
3864 printf("close1 failed (%s)\n", nt_errstr(status));
3865 return false;
3868 cli1->use_oplocks = true;
3869 cli2->use_oplocks = true;
3871 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3872 if (!NT_STATUS_IS_OK(status)) {
3873 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3874 return false;
3877 ev = samba_tevent_context_init(talloc_tos());
3878 if (ev == NULL) {
3879 printf("tevent_context_init failed\n");
3880 return false;
3883 state = talloc(ev, struct oplock4_state);
3884 if (state == NULL) {
3885 printf("talloc failed\n");
3886 return false;
3888 state->ev = ev;
3889 state->cli = cli1;
3890 state->got_break = &got_break;
3891 state->fnum2 = &fnum2;
3893 oplock_req = cli_smb_oplock_break_waiter_send(
3894 talloc_tos(), ev, cli1);
3895 if (oplock_req == NULL) {
3896 printf("cli_smb_oplock_break_waiter_send failed\n");
3897 return false;
3899 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3901 open_req = cli_openx_send(
3902 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3903 if (open_req == NULL) {
3904 printf("cli_openx_send failed\n");
3905 return false;
3907 tevent_req_set_callback(open_req, oplock4_got_open, state);
3909 got_break = false;
3910 fnum2 = 0xffff;
3912 while (!got_break || fnum2 == 0xffff) {
3913 int ret;
3914 ret = tevent_loop_once(ev);
3915 if (ret == -1) {
3916 printf("tevent_loop_once failed: %s\n",
3917 strerror(errno));
3918 return false;
3922 status = cli_close(cli2, fnum2);
3923 if (!NT_STATUS_IS_OK(status)) {
3924 printf("close2 failed (%s)\n", nt_errstr(status));
3925 correct = false;
3928 status = cli_close(cli1, fnum1);
3929 if (!NT_STATUS_IS_OK(status)) {
3930 printf("close1 failed (%s)\n", nt_errstr(status));
3931 correct = false;
3934 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3935 if (!NT_STATUS_IS_OK(status)) {
3936 printf("unlink failed (%s)\n", nt_errstr(status));
3937 correct = false;
3940 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3941 if (!NT_STATUS_IS_OK(status)) {
3942 printf("unlink failed (%s)\n", nt_errstr(status));
3943 correct = false;
3946 if (!torture_close_connection(cli1)) {
3947 correct = false;
3950 if (!got_break) {
3951 correct = false;
3954 printf("finished oplock test 4\n");
3956 return correct;
3959 static void oplock4_got_break(struct tevent_req *req)
3961 struct oplock4_state *state = tevent_req_callback_data(
3962 req, struct oplock4_state);
3963 uint16_t fnum;
3964 uint8_t level;
3965 NTSTATUS status;
3967 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3968 TALLOC_FREE(req);
3969 if (!NT_STATUS_IS_OK(status)) {
3970 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3971 nt_errstr(status));
3972 return;
3974 *state->got_break = true;
3976 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3977 NO_OPLOCK);
3978 if (req == NULL) {
3979 printf("cli_oplock_ack_send failed\n");
3980 return;
3984 static void oplock4_got_open(struct tevent_req *req)
3986 struct oplock4_state *state = tevent_req_callback_data(
3987 req, struct oplock4_state);
3988 NTSTATUS status;
3990 status = cli_openx_recv(req, state->fnum2);
3991 if (!NT_STATUS_IS_OK(status)) {
3992 printf("cli_openx_recv returned %s\n", nt_errstr(status));
3993 *state->fnum2 = 0xffff;
3998 Test delete on close semantics.
4000 static bool run_deletetest(int dummy)
4002 struct cli_state *cli1 = NULL;
4003 struct cli_state *cli2 = NULL;
4004 const char *fname = "\\delete.file";
4005 uint16_t fnum1 = (uint16_t)-1;
4006 uint16_t fnum2 = (uint16_t)-1;
4007 bool correct = false;
4008 NTSTATUS status;
4010 printf("starting delete test\n");
4012 if (!torture_open_connection(&cli1, 0)) {
4013 return False;
4016 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4018 /* Test 1 - this should delete the file on close. */
4020 cli_setatr(cli1, fname, 0, 0);
4021 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4023 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
4024 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4025 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4026 if (!NT_STATUS_IS_OK(status)) {
4027 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
4028 goto fail;
4031 status = cli_close(cli1, fnum1);
4032 if (!NT_STATUS_IS_OK(status)) {
4033 printf("[1] close failed (%s)\n", nt_errstr(status));
4034 goto fail;
4037 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4038 if (NT_STATUS_IS_OK(status)) {
4039 printf("[1] open of %s succeeded (should fail)\n", fname);
4040 goto fail;
4043 printf("first delete on close test succeeded.\n");
4045 /* Test 2 - this should delete the file on close. */
4047 cli_setatr(cli1, fname, 0, 0);
4048 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4050 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
4051 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4052 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4053 if (!NT_STATUS_IS_OK(status)) {
4054 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
4055 goto fail;
4058 status = cli_nt_delete_on_close(cli1, fnum1, true);
4059 if (!NT_STATUS_IS_OK(status)) {
4060 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
4061 goto fail;
4064 status = cli_close(cli1, fnum1);
4065 if (!NT_STATUS_IS_OK(status)) {
4066 printf("[2] close failed (%s)\n", nt_errstr(status));
4067 goto fail;
4070 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4071 if (NT_STATUS_IS_OK(status)) {
4072 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
4073 status = cli_close(cli1, fnum1);
4074 if (!NT_STATUS_IS_OK(status)) {
4075 printf("[2] close failed (%s)\n", nt_errstr(status));
4077 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4078 goto fail;
4081 printf("second delete on close test succeeded.\n");
4083 /* Test 3 - ... */
4084 cli_setatr(cli1, fname, 0, 0);
4085 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4087 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
4088 FILE_ATTRIBUTE_NORMAL,
4089 FILE_SHARE_READ|FILE_SHARE_WRITE,
4090 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4091 if (!NT_STATUS_IS_OK(status)) {
4092 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
4093 goto fail;
4096 /* This should fail with a sharing violation - open for delete is only compatible
4097 with SHARE_DELETE. */
4099 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4100 FILE_ATTRIBUTE_NORMAL,
4101 FILE_SHARE_READ|FILE_SHARE_WRITE,
4102 FILE_OPEN, 0, 0, &fnum2, NULL);
4103 if (NT_STATUS_IS_OK(status)) {
4104 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
4105 goto fail;
4108 /* This should succeed. */
4109 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4110 FILE_ATTRIBUTE_NORMAL,
4111 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4112 FILE_OPEN, 0, 0, &fnum2, NULL);
4113 if (!NT_STATUS_IS_OK(status)) {
4114 printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
4115 goto fail;
4118 status = cli_nt_delete_on_close(cli1, fnum1, true);
4119 if (!NT_STATUS_IS_OK(status)) {
4120 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
4121 goto fail;
4124 status = cli_close(cli1, fnum1);
4125 if (!NT_STATUS_IS_OK(status)) {
4126 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
4127 goto fail;
4130 status = cli_close(cli1, fnum2);
4131 if (!NT_STATUS_IS_OK(status)) {
4132 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
4133 goto fail;
4136 /* This should fail - file should no longer be there. */
4138 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4139 if (NT_STATUS_IS_OK(status)) {
4140 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
4141 status = cli_close(cli1, fnum1);
4142 if (!NT_STATUS_IS_OK(status)) {
4143 printf("[3] close failed (%s)\n", nt_errstr(status));
4145 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4146 goto fail;
4149 printf("third delete on close test succeeded.\n");
4151 /* Test 4 ... */
4152 cli_setatr(cli1, fname, 0, 0);
4153 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4155 status = cli_ntcreate(cli1, fname, 0,
4156 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4157 FILE_ATTRIBUTE_NORMAL,
4158 FILE_SHARE_READ|FILE_SHARE_WRITE,
4159 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4160 if (!NT_STATUS_IS_OK(status)) {
4161 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4162 goto fail;
4165 /* This should succeed. */
4166 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4167 FILE_ATTRIBUTE_NORMAL,
4168 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4169 FILE_OPEN, 0, 0, &fnum2, NULL);
4170 if (!NT_STATUS_IS_OK(status)) {
4171 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4172 goto fail;
4175 status = cli_close(cli1, fnum2);
4176 if (!NT_STATUS_IS_OK(status)) {
4177 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4178 goto fail;
4181 status = cli_nt_delete_on_close(cli1, fnum1, true);
4182 if (!NT_STATUS_IS_OK(status)) {
4183 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4184 goto fail;
4187 /* This should fail - no more opens once delete on close set. */
4188 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4189 FILE_ATTRIBUTE_NORMAL,
4190 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4191 FILE_OPEN, 0, 0, &fnum2, NULL);
4192 if (NT_STATUS_IS_OK(status)) {
4193 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
4194 goto fail;
4197 status = cli_close(cli1, fnum1);
4198 if (!NT_STATUS_IS_OK(status)) {
4199 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4200 goto fail;
4203 printf("fourth delete on close test succeeded.\n");
4205 /* Test 5 ... */
4206 cli_setatr(cli1, fname, 0, 0);
4207 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4209 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4210 if (!NT_STATUS_IS_OK(status)) {
4211 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4212 goto fail;
4215 /* This should fail - only allowed on NT opens with DELETE access. */
4217 status = cli_nt_delete_on_close(cli1, fnum1, true);
4218 if (NT_STATUS_IS_OK(status)) {
4219 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4220 goto fail;
4223 status = cli_close(cli1, fnum1);
4224 if (!NT_STATUS_IS_OK(status)) {
4225 printf("[5] close failed (%s)\n", nt_errstr(status));
4226 goto fail;
4229 printf("fifth delete on close test succeeded.\n");
4231 /* Test 6 ... */
4232 cli_setatr(cli1, fname, 0, 0);
4233 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4235 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4236 FILE_ATTRIBUTE_NORMAL,
4237 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4238 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4239 if (!NT_STATUS_IS_OK(status)) {
4240 printf("[6] open of %s failed (%s)\n", fname,
4241 nt_errstr(status));
4242 goto fail;
4245 /* This should fail - only allowed on NT opens with DELETE access. */
4247 status = cli_nt_delete_on_close(cli1, fnum1, true);
4248 if (NT_STATUS_IS_OK(status)) {
4249 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4250 goto fail;
4253 status = cli_close(cli1, fnum1);
4254 if (!NT_STATUS_IS_OK(status)) {
4255 printf("[6] close failed (%s)\n", nt_errstr(status));
4256 goto fail;
4259 printf("sixth delete on close test succeeded.\n");
4261 /* Test 7 ... */
4262 cli_setatr(cli1, fname, 0, 0);
4263 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4265 status = cli_ntcreate(cli1, fname, 0,
4266 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4267 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4268 0, 0, &fnum1, NULL);
4269 if (!NT_STATUS_IS_OK(status)) {
4270 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4271 goto fail;
4274 status = cli_nt_delete_on_close(cli1, fnum1, true);
4275 if (!NT_STATUS_IS_OK(status)) {
4276 printf("[7] setting delete_on_close on file failed !\n");
4277 goto fail;
4280 status = cli_nt_delete_on_close(cli1, fnum1, false);
4281 if (!NT_STATUS_IS_OK(status)) {
4282 printf("[7] unsetting delete_on_close on file failed !\n");
4283 goto fail;
4286 status = cli_close(cli1, fnum1);
4287 if (!NT_STATUS_IS_OK(status)) {
4288 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
4289 goto fail;
4292 /* This next open should succeed - we reset the flag. */
4293 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4294 if (!NT_STATUS_IS_OK(status)) {
4295 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4296 goto fail;
4299 status = cli_close(cli1, fnum1);
4300 if (!NT_STATUS_IS_OK(status)) {
4301 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4302 goto fail;
4305 printf("seventh delete on close test succeeded.\n");
4307 /* Test 8 ... */
4308 cli_setatr(cli1, fname, 0, 0);
4309 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4311 if (!torture_open_connection(&cli2, 1)) {
4312 printf("[8] failed to open second connection.\n");
4313 goto fail;
4316 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4318 status = cli_ntcreate(cli1, fname, 0,
4319 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4320 FILE_ATTRIBUTE_NORMAL,
4321 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4322 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4323 if (!NT_STATUS_IS_OK(status)) {
4324 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4325 goto fail;
4328 status = cli_ntcreate(cli2, fname, 0,
4329 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4330 FILE_ATTRIBUTE_NORMAL,
4331 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4332 FILE_OPEN, 0, 0, &fnum2, NULL);
4333 if (!NT_STATUS_IS_OK(status)) {
4334 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4335 goto fail;
4338 status = cli_nt_delete_on_close(cli1, fnum1, true);
4339 if (!NT_STATUS_IS_OK(status)) {
4340 printf("[8] setting delete_on_close on file failed !\n");
4341 goto fail;
4344 status = cli_close(cli1, fnum1);
4345 if (!NT_STATUS_IS_OK(status)) {
4346 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4347 goto fail;
4350 status = cli_close(cli2, fnum2);
4351 if (!NT_STATUS_IS_OK(status)) {
4352 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4353 goto fail;
4356 /* This should fail.. */
4357 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4358 if (NT_STATUS_IS_OK(status)) {
4359 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4360 goto fail;
4363 printf("eighth delete on close test succeeded.\n");
4365 /* Test 9 ... */
4367 /* This should fail - we need to set DELETE_ACCESS. */
4368 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4369 FILE_ATTRIBUTE_NORMAL,
4370 FILE_SHARE_NONE,
4371 FILE_OVERWRITE_IF,
4372 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4373 if (NT_STATUS_IS_OK(status)) {
4374 printf("[9] open of %s succeeded should have failed!\n", fname);
4375 goto fail;
4378 printf("ninth delete on close test succeeded.\n");
4380 /* Test 10 ... */
4382 status = cli_ntcreate(cli1, fname, 0,
4383 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4384 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4385 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4386 0, &fnum1, NULL);
4387 if (!NT_STATUS_IS_OK(status)) {
4388 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4389 goto fail;
4392 /* This should delete the file. */
4393 status = cli_close(cli1, fnum1);
4394 if (!NT_STATUS_IS_OK(status)) {
4395 printf("[10] close failed (%s)\n", nt_errstr(status));
4396 goto fail;
4399 /* This should fail.. */
4400 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4401 if (NT_STATUS_IS_OK(status)) {
4402 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4403 goto fail;
4406 printf("tenth delete on close test succeeded.\n");
4408 /* Test 11 ... */
4410 cli_setatr(cli1, fname, 0, 0);
4411 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4413 /* Can we open a read-only file with delete access? */
4415 /* Create a readonly file. */
4416 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4417 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4418 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4419 if (!NT_STATUS_IS_OK(status)) {
4420 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4421 goto fail;
4424 status = cli_close(cli1, fnum1);
4425 if (!NT_STATUS_IS_OK(status)) {
4426 printf("[11] close failed (%s)\n", nt_errstr(status));
4427 goto fail;
4430 /* Now try open for delete access. */
4431 status = cli_ntcreate(cli1, fname, 0,
4432 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4434 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4435 FILE_OPEN, 0, 0, &fnum1, NULL);
4436 if (!NT_STATUS_IS_OK(status)) {
4437 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
4438 goto fail;
4441 cli_close(cli1, fnum1);
4443 printf("eleventh delete on close test succeeded.\n");
4446 * Test 12
4447 * like test 4 but with initial delete on close
4450 cli_setatr(cli1, fname, 0, 0);
4451 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4453 status = cli_ntcreate(cli1, fname, 0,
4454 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4455 FILE_ATTRIBUTE_NORMAL,
4456 FILE_SHARE_READ|FILE_SHARE_WRITE,
4457 FILE_OVERWRITE_IF,
4458 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4459 if (!NT_STATUS_IS_OK(status)) {
4460 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4461 goto fail;
4464 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4465 FILE_ATTRIBUTE_NORMAL,
4466 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4467 FILE_OPEN, 0, 0, &fnum2, NULL);
4468 if (!NT_STATUS_IS_OK(status)) {
4469 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
4470 goto fail;
4473 status = cli_close(cli1, fnum2);
4474 if (!NT_STATUS_IS_OK(status)) {
4475 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
4476 goto fail;
4479 status = cli_nt_delete_on_close(cli1, fnum1, true);
4480 if (!NT_STATUS_IS_OK(status)) {
4481 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
4482 goto fail;
4485 /* This should fail - no more opens once delete on close set. */
4486 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4487 FILE_ATTRIBUTE_NORMAL,
4488 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4489 FILE_OPEN, 0, 0, &fnum2, NULL);
4490 if (NT_STATUS_IS_OK(status)) {
4491 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
4492 goto fail;
4495 status = cli_nt_delete_on_close(cli1, fnum1, false);
4496 if (!NT_STATUS_IS_OK(status)) {
4497 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
4498 goto fail;
4501 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4502 FILE_ATTRIBUTE_NORMAL,
4503 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4504 FILE_OPEN, 0, 0, &fnum2, NULL);
4505 if (!NT_STATUS_IS_OK(status)) {
4506 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
4507 goto fail;
4510 status = cli_close(cli1, fnum2);
4511 if (!NT_STATUS_IS_OK(status)) {
4512 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
4513 goto fail;
4516 status = cli_close(cli1, fnum1);
4517 if (!NT_STATUS_IS_OK(status)) {
4518 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
4519 goto fail;
4523 * setting delete on close on the handle does
4524 * not unset the initial delete on close...
4526 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4527 FILE_ATTRIBUTE_NORMAL,
4528 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4529 FILE_OPEN, 0, 0, &fnum2, NULL);
4530 if (NT_STATUS_IS_OK(status)) {
4531 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
4532 goto fail;
4533 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4534 printf("ntcreate returned %s, expected "
4535 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
4536 nt_errstr(status));
4537 goto fail;
4540 printf("twelfth delete on close test succeeded.\n");
4543 printf("finished delete test\n");
4545 correct = true;
4547 fail:
4548 /* FIXME: This will crash if we aborted before cli2 got
4549 * intialized, because these functions don't handle
4550 * uninitialized connections. */
4552 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4553 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4554 cli_setatr(cli1, fname, 0, 0);
4555 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4557 if (cli1 && !torture_close_connection(cli1)) {
4558 correct = False;
4560 if (cli2 && !torture_close_connection(cli2)) {
4561 correct = False;
4563 return correct;
4567 Exercise delete on close semantics - use on the PRINT1 share in torture
4568 testing.
4570 static bool run_delete_print_test(int dummy)
4572 struct cli_state *cli1 = NULL;
4573 const char *fname = "print_delete.file";
4574 uint16_t fnum1 = (uint16_t)-1;
4575 bool correct = false;
4576 const char *buf = "print file data\n";
4577 NTSTATUS status;
4579 printf("starting print delete test\n");
4581 if (!torture_open_connection(&cli1, 0)) {
4582 return false;
4585 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4587 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
4588 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4589 0, 0, &fnum1, NULL);
4590 if (!NT_STATUS_IS_OK(status)) {
4591 printf("open of %s failed (%s)\n",
4592 fname,
4593 nt_errstr(status));
4594 goto fail;
4597 status = cli_writeall(cli1,
4598 fnum1,
4600 (const uint8_t *)buf,
4601 0, /* offset */
4602 strlen(buf), /* size */
4603 NULL);
4604 if (!NT_STATUS_IS_OK(status)) {
4605 printf("writing print file data failed (%s)\n",
4606 nt_errstr(status));
4607 goto fail;
4610 status = cli_nt_delete_on_close(cli1, fnum1, true);
4611 if (!NT_STATUS_IS_OK(status)) {
4612 printf("setting delete_on_close failed (%s)\n",
4613 nt_errstr(status));
4614 goto fail;
4617 status = cli_close(cli1, fnum1);
4618 if (!NT_STATUS_IS_OK(status)) {
4619 printf("close failed (%s)\n", nt_errstr(status));
4620 goto fail;
4623 printf("finished print delete test\n");
4625 correct = true;
4627 fail:
4629 if (fnum1 != (uint16_t)-1) {
4630 cli_close(cli1, fnum1);
4633 if (cli1 && !torture_close_connection(cli1)) {
4634 correct = false;
4636 return correct;
4640 Test wildcard delete.
4642 static bool run_wild_deletetest(int dummy)
4644 struct cli_state *cli = NULL;
4645 const char *dname = "\\WTEST";
4646 const char *fname = "\\WTEST\\A";
4647 const char *wunlink_name = "\\WTEST\\*";
4648 uint16_t fnum1 = (uint16_t)-1;
4649 bool correct = false;
4650 NTSTATUS status;
4652 printf("starting wildcard delete test\n");
4654 if (!torture_open_connection(&cli, 0)) {
4655 return false;
4658 smbXcli_conn_set_sockopt(cli->conn, sockops);
4660 cli_unlink(cli, fname, 0);
4661 cli_rmdir(cli, dname);
4662 status = cli_mkdir(cli, dname);
4663 if (!NT_STATUS_IS_OK(status)) {
4664 printf("mkdir of %s failed %s!\n", dname, nt_errstr(status));
4665 goto fail;
4667 status = cli_openx(cli, fname, O_CREAT|O_RDONLY, DENY_NONE, &fnum1);
4668 if (!NT_STATUS_IS_OK(status)) {
4669 printf("open of %s failed %s!\n", fname, nt_errstr(status));
4670 goto fail;
4672 status = cli_close(cli, fnum1);
4673 fnum1 = -1;
4676 * Note the unlink attribute-type of zero. This should
4677 * map into FILE_ATTRIBUTE_NORMAL at the server even
4678 * on a wildcard delete.
4681 status = cli_unlink(cli, wunlink_name, 0);
4682 if (!NT_STATUS_IS_OK(status)) {
4683 printf("unlink of %s failed %s!\n",
4684 wunlink_name, nt_errstr(status));
4685 goto fail;
4688 printf("finished wildcard delete test\n");
4690 correct = true;
4692 fail:
4694 if (fnum1 != (uint16_t)-1) cli_close(cli, fnum1);
4695 cli_unlink(cli, fname, 0);
4696 cli_rmdir(cli, dname);
4698 if (cli && !torture_close_connection(cli)) {
4699 correct = false;
4701 return correct;
4704 static bool run_deletetest_ln(int dummy)
4706 struct cli_state *cli;
4707 const char *fname = "\\delete1";
4708 const char *fname_ln = "\\delete1_ln";
4709 uint16_t fnum;
4710 uint16_t fnum1;
4711 NTSTATUS status;
4712 bool correct = true;
4713 time_t t;
4715 printf("starting deletetest-ln\n");
4717 if (!torture_open_connection(&cli, 0)) {
4718 return false;
4721 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4722 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4724 smbXcli_conn_set_sockopt(cli->conn, sockops);
4726 /* Create the file. */
4727 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4728 if (!NT_STATUS_IS_OK(status)) {
4729 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4730 return false;
4733 status = cli_close(cli, fnum);
4734 if (!NT_STATUS_IS_OK(status)) {
4735 printf("close1 failed (%s)\n", nt_errstr(status));
4736 return false;
4739 /* Now create a hardlink. */
4740 status = cli_nt_hardlink(cli, fname, fname_ln);
4741 if (!NT_STATUS_IS_OK(status)) {
4742 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4743 return false;
4746 /* Open the original file. */
4747 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4748 FILE_ATTRIBUTE_NORMAL,
4749 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4750 FILE_OPEN_IF, 0, 0, &fnum, NULL);
4751 if (!NT_STATUS_IS_OK(status)) {
4752 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4753 return false;
4756 /* Unlink the hard link path. */
4757 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4758 FILE_ATTRIBUTE_NORMAL,
4759 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4760 FILE_OPEN_IF, 0, 0, &fnum1, NULL);
4761 if (!NT_STATUS_IS_OK(status)) {
4762 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4763 return false;
4765 status = cli_nt_delete_on_close(cli, fnum1, true);
4766 if (!NT_STATUS_IS_OK(status)) {
4767 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4768 __location__, fname_ln, nt_errstr(status));
4769 return false;
4772 status = cli_close(cli, fnum1);
4773 if (!NT_STATUS_IS_OK(status)) {
4774 printf("close %s failed (%s)\n",
4775 fname_ln, nt_errstr(status));
4776 return false;
4779 status = cli_close(cli, fnum);
4780 if (!NT_STATUS_IS_OK(status)) {
4781 printf("close %s failed (%s)\n",
4782 fname, nt_errstr(status));
4783 return false;
4786 /* Ensure the original file is still there. */
4787 status = cli_getatr(cli, fname, NULL, NULL, &t);
4788 if (!NT_STATUS_IS_OK(status)) {
4789 printf("%s getatr on file %s failed (%s)\n",
4790 __location__,
4791 fname,
4792 nt_errstr(status));
4793 correct = False;
4796 /* Ensure the link path is gone. */
4797 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4798 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4799 printf("%s, getatr for file %s returned wrong error code %s "
4800 "- should have been deleted\n",
4801 __location__,
4802 fname_ln, nt_errstr(status));
4803 correct = False;
4806 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4807 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4809 if (!torture_close_connection(cli)) {
4810 correct = false;
4813 printf("finished deletetest-ln\n");
4815 return correct;
4819 print out server properties
4821 static bool run_properties(int dummy)
4823 struct cli_state *cli;
4824 bool correct = True;
4826 printf("starting properties test\n");
4828 ZERO_STRUCT(cli);
4830 if (!torture_open_connection(&cli, 0)) {
4831 return False;
4834 smbXcli_conn_set_sockopt(cli->conn, sockops);
4836 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
4838 if (!torture_close_connection(cli)) {
4839 correct = False;
4842 return correct;
4847 /* FIRST_DESIRED_ACCESS 0xf019f */
4848 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4849 FILE_READ_EA| /* 0xf */ \
4850 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
4851 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
4852 DELETE_ACCESS|READ_CONTROL_ACCESS|\
4853 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
4854 /* SECOND_DESIRED_ACCESS 0xe0080 */
4855 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4856 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4857 WRITE_OWNER_ACCESS /* 0xe0000 */
4859 #if 0
4860 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4861 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4862 FILE_READ_DATA|\
4863 WRITE_OWNER_ACCESS /* */
4864 #endif
4867 Test ntcreate calls made by xcopy
4869 static bool run_xcopy(int dummy)
4871 static struct cli_state *cli1;
4872 const char *fname = "\\test.txt";
4873 bool correct = True;
4874 uint16_t fnum1, fnum2;
4875 NTSTATUS status;
4877 printf("starting xcopy test\n");
4879 if (!torture_open_connection(&cli1, 0)) {
4880 return False;
4883 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4884 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4885 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
4886 if (!NT_STATUS_IS_OK(status)) {
4887 printf("First open failed - %s\n", nt_errstr(status));
4888 return False;
4891 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4892 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4893 FILE_OPEN, 0x200000, 0, &fnum2, NULL);
4894 if (!NT_STATUS_IS_OK(status)) {
4895 printf("second open failed - %s\n", nt_errstr(status));
4896 return False;
4899 if (!torture_close_connection(cli1)) {
4900 correct = False;
4903 return correct;
4907 Test rename on files open with share delete and no share delete.
4909 static bool run_rename(int dummy)
4911 static struct cli_state *cli1;
4912 const char *fname = "\\test.txt";
4913 const char *fname1 = "\\test1.txt";
4914 bool correct = True;
4915 uint16_t fnum1;
4916 uint16_t attr;
4917 NTSTATUS status;
4919 printf("starting rename test\n");
4921 if (!torture_open_connection(&cli1, 0)) {
4922 return False;
4925 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4926 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4928 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4929 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4930 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4931 if (!NT_STATUS_IS_OK(status)) {
4932 printf("First open failed - %s\n", nt_errstr(status));
4933 return False;
4936 status = cli_rename(cli1, fname, fname1, false);
4937 if (!NT_STATUS_IS_OK(status)) {
4938 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4939 } else {
4940 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4941 correct = False;
4944 status = cli_close(cli1, fnum1);
4945 if (!NT_STATUS_IS_OK(status)) {
4946 printf("close - 1 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);
4952 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4953 #if 0
4954 FILE_SHARE_DELETE|FILE_SHARE_NONE,
4955 #else
4956 FILE_SHARE_DELETE|FILE_SHARE_READ,
4957 #endif
4958 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4959 if (!NT_STATUS_IS_OK(status)) {
4960 printf("Second 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("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4967 correct = False;
4968 } else {
4969 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4972 status = cli_close(cli1, fnum1);
4973 if (!NT_STATUS_IS_OK(status)) {
4974 printf("close - 2 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 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4982 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4983 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4984 if (!NT_STATUS_IS_OK(status)) {
4985 printf("Third open failed - %s\n", nt_errstr(status));
4986 return False;
4990 #if 0
4992 uint16_t fnum2;
4994 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4995 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
4996 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4997 return False;
4999 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
5000 printf("[8] setting delete_on_close on file failed !\n");
5001 return False;
5004 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
5005 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
5006 return False;
5009 #endif
5011 status = cli_rename(cli1, fname, fname1, false);
5012 if (!NT_STATUS_IS_OK(status)) {
5013 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
5014 correct = False;
5015 } else {
5016 printf("Third rename succeeded (SHARE_NONE)\n");
5019 status = cli_close(cli1, fnum1);
5020 if (!NT_STATUS_IS_OK(status)) {
5021 printf("close - 3 failed (%s)\n", nt_errstr(status));
5022 return False;
5025 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5026 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5028 /*----*/
5030 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5031 FILE_ATTRIBUTE_NORMAL,
5032 FILE_SHARE_READ | FILE_SHARE_WRITE,
5033 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5034 if (!NT_STATUS_IS_OK(status)) {
5035 printf("Fourth open failed - %s\n", nt_errstr(status));
5036 return False;
5039 status = cli_rename(cli1, fname, fname1, false);
5040 if (!NT_STATUS_IS_OK(status)) {
5041 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
5042 } else {
5043 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
5044 correct = False;
5047 status = cli_close(cli1, fnum1);
5048 if (!NT_STATUS_IS_OK(status)) {
5049 printf("close - 4 failed (%s)\n", nt_errstr(status));
5050 return False;
5053 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5054 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5056 /*--*/
5058 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5059 FILE_ATTRIBUTE_NORMAL,
5060 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
5061 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5062 if (!NT_STATUS_IS_OK(status)) {
5063 printf("Fifth open failed - %s\n", nt_errstr(status));
5064 return False;
5067 status = cli_rename(cli1, fname, fname1, false);
5068 if (!NT_STATUS_IS_OK(status)) {
5069 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
5070 correct = False;
5071 } else {
5072 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
5076 * Now check if the first name still exists ...
5079 /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
5080 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
5081 FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
5082 printf("Opening original file after rename of open file fails: %s\n",
5083 cli_errstr(cli1));
5085 else {
5086 printf("Opening original file after rename of open file works ...\n");
5087 (void)cli_close(cli1, fnum2);
5088 } */
5090 /*--*/
5091 status = cli_close(cli1, fnum1);
5092 if (!NT_STATUS_IS_OK(status)) {
5093 printf("close - 5 failed (%s)\n", nt_errstr(status));
5094 return False;
5097 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
5098 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
5099 if (!NT_STATUS_IS_OK(status)) {
5100 printf("getatr on file %s failed - %s ! \n",
5101 fname1, nt_errstr(status));
5102 correct = False;
5103 } else {
5104 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
5105 printf("Renamed file %s has wrong attr 0x%x "
5106 "(should be 0x%x)\n",
5107 fname1,
5108 attr,
5109 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
5110 correct = False;
5111 } else {
5112 printf("Renamed file %s has archive bit set\n", fname1);
5116 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5117 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5119 if (!torture_close_connection(cli1)) {
5120 correct = False;
5123 return correct;
5127 Test rename into a directory with an ACL denying it.
5129 static bool run_rename_access(int dummy)
5131 static struct cli_state *cli = NULL;
5132 static struct cli_state *posix_cli = NULL;
5133 const char *src = "test.txt";
5134 const char *dname = "dir";
5135 const char *dst = "dir\\test.txt";
5136 const char *dsrc = "test.dir";
5137 const char *ddst = "dir\\test.dir";
5138 uint16_t fnum = (uint16_t)-1;
5139 struct security_descriptor *sd = NULL;
5140 struct security_descriptor *newsd = NULL;
5141 NTSTATUS status;
5142 TALLOC_CTX *frame = NULL;
5144 frame = talloc_stackframe();
5145 printf("starting rename access test\n");
5147 /* Windows connection. */
5148 if (!torture_open_connection(&cli, 0)) {
5149 goto fail;
5152 smbXcli_conn_set_sockopt(cli->conn, sockops);
5154 /* Posix connection. */
5155 if (!torture_open_connection(&posix_cli, 0)) {
5156 goto fail;
5159 smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
5161 status = torture_setup_unix_extensions(posix_cli);
5162 if (!NT_STATUS_IS_OK(status)) {
5163 goto fail;
5166 /* Start with a clean slate. */
5167 cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5168 cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5169 cli_rmdir(cli, dsrc);
5170 cli_rmdir(cli, ddst);
5171 cli_rmdir(cli, dname);
5174 * Setup the destination directory with a DENY ACE to
5175 * prevent new files within it.
5177 status = cli_ntcreate(cli,
5178 dname,
5180 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
5181 WRITE_DAC_ACCESS|FILE_READ_DATA|
5182 WRITE_OWNER_ACCESS,
5183 FILE_ATTRIBUTE_DIRECTORY,
5184 FILE_SHARE_READ|FILE_SHARE_WRITE,
5185 FILE_CREATE,
5186 FILE_DIRECTORY_FILE,
5188 &fnum,
5189 NULL);
5190 if (!NT_STATUS_IS_OK(status)) {
5191 printf("Create of %s - %s\n", dname, nt_errstr(status));
5192 goto fail;
5195 status = cli_query_secdesc(cli,
5196 fnum,
5197 frame,
5198 &sd);
5199 if (!NT_STATUS_IS_OK(status)) {
5200 printf("cli_query_secdesc failed for %s (%s)\n",
5201 dname, nt_errstr(status));
5202 goto fail;
5205 newsd = security_descriptor_dacl_create(frame,
5207 NULL,
5208 NULL,
5209 SID_WORLD,
5210 SEC_ACE_TYPE_ACCESS_DENIED,
5211 SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
5213 NULL);
5214 if (newsd == NULL) {
5215 goto fail;
5217 sd->dacl = security_acl_concatenate(frame,
5218 newsd->dacl,
5219 sd->dacl);
5220 if (sd->dacl == NULL) {
5221 goto fail;
5223 status = cli_set_secdesc(cli, fnum, sd);
5224 if (!NT_STATUS_IS_OK(status)) {
5225 printf("cli_set_secdesc failed for %s (%s)\n",
5226 dname, nt_errstr(status));
5227 goto fail;
5229 status = cli_close(cli, fnum);
5230 if (!NT_STATUS_IS_OK(status)) {
5231 printf("close failed for %s (%s)\n",
5232 dname, nt_errstr(status));
5233 goto fail;
5235 /* Now go around the back and chmod to 777 via POSIX. */
5236 status = cli_posix_chmod(posix_cli, dname, 0777);
5237 if (!NT_STATUS_IS_OK(status)) {
5238 printf("cli_posix_chmod failed for %s (%s)\n",
5239 dname, nt_errstr(status));
5240 goto fail;
5243 /* Check we can't create a file within dname via Windows. */
5244 status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5245 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5246 cli_close(posix_cli, fnum);
5247 printf("Create of %s should be ACCESS denied, was %s\n",
5248 dst, nt_errstr(status));
5249 goto fail;
5252 /* Make the sample file/directory. */
5253 status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5254 if (!NT_STATUS_IS_OK(status)) {
5255 printf("open of %s failed (%s)\n", src, nt_errstr(status));
5256 goto fail;
5258 status = cli_close(cli, fnum);
5259 if (!NT_STATUS_IS_OK(status)) {
5260 printf("cli_close failed (%s)\n", nt_errstr(status));
5261 goto fail;
5264 status = cli_mkdir(cli, dsrc);
5265 if (!NT_STATUS_IS_OK(status)) {
5266 printf("cli_mkdir of %s failed (%s)\n",
5267 dsrc, nt_errstr(status));
5268 goto fail;
5272 * OK - renames of the new file and directory into the
5273 * dst directory should fail.
5276 status = cli_rename(cli, src, dst, false);
5277 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5278 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
5279 src, dst, nt_errstr(status));
5280 goto fail;
5282 status = cli_rename(cli, dsrc, ddst, false);
5283 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5284 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
5285 src, dst, nt_errstr(status));
5286 goto fail;
5289 TALLOC_FREE(frame);
5290 return true;
5292 fail:
5294 if (posix_cli) {
5295 torture_close_connection(posix_cli);
5298 if (cli) {
5299 if (fnum != (uint16_t)-1) {
5300 cli_close(cli, fnum);
5302 cli_unlink(cli, src,
5303 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5304 cli_unlink(cli, dst,
5305 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5306 cli_rmdir(cli, dsrc);
5307 cli_rmdir(cli, ddst);
5308 cli_rmdir(cli, dname);
5310 torture_close_connection(cli);
5313 TALLOC_FREE(frame);
5314 return false;
5318 Test owner rights ACE.
5320 static bool run_owner_rights(int dummy)
5322 static struct cli_state *cli = NULL;
5323 const char *fname = "owner_rights.txt";
5324 uint16_t fnum = (uint16_t)-1;
5325 struct security_descriptor *sd = NULL;
5326 struct security_descriptor *newsd = NULL;
5327 NTSTATUS status;
5328 TALLOC_CTX *frame = NULL;
5330 frame = talloc_stackframe();
5331 printf("starting owner rights test\n");
5333 /* Windows connection. */
5334 if (!torture_open_connection(&cli, 0)) {
5335 goto fail;
5338 smbXcli_conn_set_sockopt(cli->conn, sockops);
5340 /* Start with a clean slate. */
5341 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5343 /* Create the test file. */
5344 /* Now try and open for read and write-dac. */
5345 status = cli_ntcreate(cli,
5346 fname,
5348 GENERIC_ALL_ACCESS,
5349 FILE_ATTRIBUTE_NORMAL,
5350 FILE_SHARE_READ|FILE_SHARE_WRITE|
5351 FILE_SHARE_DELETE,
5352 FILE_CREATE,
5355 &fnum,
5356 NULL);
5357 if (!NT_STATUS_IS_OK(status)) {
5358 printf("Create of %s - %s\n", fname, nt_errstr(status));
5359 goto fail;
5362 /* Get the original SD. */
5363 status = cli_query_secdesc(cli,
5364 fnum,
5365 frame,
5366 &sd);
5367 if (!NT_STATUS_IS_OK(status)) {
5368 printf("cli_query_secdesc failed for %s (%s)\n",
5369 fname, nt_errstr(status));
5370 goto fail;
5374 * Add an "owner-rights" ACE denying WRITE_DATA,
5375 * and an "owner-rights" ACE allowing READ_DATA.
5378 newsd = security_descriptor_dacl_create(frame,
5380 NULL,
5381 NULL,
5382 SID_OWNER_RIGHTS,
5383 SEC_ACE_TYPE_ACCESS_DENIED,
5384 FILE_WRITE_DATA,
5386 SID_OWNER_RIGHTS,
5387 SEC_ACE_TYPE_ACCESS_ALLOWED,
5388 FILE_READ_DATA,
5390 NULL);
5391 if (newsd == NULL) {
5392 goto fail;
5394 sd->dacl = security_acl_concatenate(frame,
5395 newsd->dacl,
5396 sd->dacl);
5397 if (sd->dacl == NULL) {
5398 goto fail;
5400 status = cli_set_secdesc(cli, fnum, sd);
5401 if (!NT_STATUS_IS_OK(status)) {
5402 printf("cli_set_secdesc failed for %s (%s)\n",
5403 fname, nt_errstr(status));
5404 goto fail;
5406 status = cli_close(cli, fnum);
5407 if (!NT_STATUS_IS_OK(status)) {
5408 printf("close failed for %s (%s)\n",
5409 fname, nt_errstr(status));
5410 goto fail;
5412 fnum = (uint16_t)-1;
5414 /* Try and open for FILE_WRITE_DATA */
5415 status = cli_ntcreate(cli,
5416 fname,
5418 FILE_WRITE_DATA,
5419 FILE_ATTRIBUTE_NORMAL,
5420 FILE_SHARE_READ|FILE_SHARE_WRITE|
5421 FILE_SHARE_DELETE,
5422 FILE_OPEN,
5425 &fnum,
5426 NULL);
5427 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5428 printf("Open of %s - %s\n", fname, nt_errstr(status));
5429 goto fail;
5432 /* Now try and open for FILE_READ_DATA */
5433 status = cli_ntcreate(cli,
5434 fname,
5436 FILE_READ_DATA,
5437 FILE_ATTRIBUTE_NORMAL,
5438 FILE_SHARE_READ|FILE_SHARE_WRITE|
5439 FILE_SHARE_DELETE,
5440 FILE_OPEN,
5443 &fnum,
5444 NULL);
5445 if (!NT_STATUS_IS_OK(status)) {
5446 printf("Open of %s - %s\n", fname, nt_errstr(status));
5447 goto fail;
5450 status = cli_close(cli, fnum);
5451 if (!NT_STATUS_IS_OK(status)) {
5452 printf("close failed for %s (%s)\n",
5453 fname, nt_errstr(status));
5454 goto fail;
5457 /* Restore clean slate. */
5458 TALLOC_FREE(sd);
5459 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5461 /* Create the test file. */
5462 status = cli_ntcreate(cli,
5463 fname,
5465 GENERIC_ALL_ACCESS,
5466 FILE_ATTRIBUTE_NORMAL,
5467 FILE_SHARE_READ|FILE_SHARE_WRITE|
5468 FILE_SHARE_DELETE,
5469 FILE_CREATE,
5472 &fnum,
5473 NULL);
5474 if (!NT_STATUS_IS_OK(status)) {
5475 printf("Create of %s - %s\n", fname, nt_errstr(status));
5476 goto fail;
5479 /* Get the original SD. */
5480 status = cli_query_secdesc(cli,
5481 fnum,
5482 frame,
5483 &sd);
5484 if (!NT_STATUS_IS_OK(status)) {
5485 printf("cli_query_secdesc failed for %s (%s)\n",
5486 fname, nt_errstr(status));
5487 goto fail;
5491 * Add an "owner-rights ACE denying WRITE_DATA,
5492 * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
5495 newsd = security_descriptor_dacl_create(frame,
5497 NULL,
5498 NULL,
5499 SID_OWNER_RIGHTS,
5500 SEC_ACE_TYPE_ACCESS_DENIED,
5501 FILE_WRITE_DATA,
5503 SID_OWNER_RIGHTS,
5504 SEC_ACE_TYPE_ACCESS_ALLOWED,
5505 FILE_READ_DATA|FILE_WRITE_DATA,
5507 NULL);
5508 if (newsd == NULL) {
5509 goto fail;
5511 sd->dacl = security_acl_concatenate(frame,
5512 newsd->dacl,
5513 sd->dacl);
5514 if (sd->dacl == NULL) {
5515 goto fail;
5517 status = cli_set_secdesc(cli, fnum, sd);
5518 if (!NT_STATUS_IS_OK(status)) {
5519 printf("cli_set_secdesc failed for %s (%s)\n",
5520 fname, nt_errstr(status));
5521 goto fail;
5523 status = cli_close(cli, fnum);
5524 if (!NT_STATUS_IS_OK(status)) {
5525 printf("close failed for %s (%s)\n",
5526 fname, nt_errstr(status));
5527 goto fail;
5529 fnum = (uint16_t)-1;
5531 /* Try and open for FILE_WRITE_DATA */
5532 status = cli_ntcreate(cli,
5533 fname,
5535 FILE_WRITE_DATA,
5536 FILE_ATTRIBUTE_NORMAL,
5537 FILE_SHARE_READ|FILE_SHARE_WRITE|
5538 FILE_SHARE_DELETE,
5539 FILE_OPEN,
5542 &fnum,
5543 NULL);
5544 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5545 printf("Open of %s - %s\n", fname, nt_errstr(status));
5546 goto fail;
5549 /* Now try and open for FILE_READ_DATA */
5550 status = cli_ntcreate(cli,
5551 fname,
5553 FILE_READ_DATA,
5554 FILE_ATTRIBUTE_NORMAL,
5555 FILE_SHARE_READ|FILE_SHARE_WRITE|
5556 FILE_SHARE_DELETE,
5557 FILE_OPEN,
5560 &fnum,
5561 NULL);
5562 if (!NT_STATUS_IS_OK(status)) {
5563 printf("Open of %s - %s\n", fname, nt_errstr(status));
5564 goto fail;
5567 status = cli_close(cli, fnum);
5568 if (!NT_STATUS_IS_OK(status)) {
5569 printf("close failed for %s (%s)\n",
5570 fname, nt_errstr(status));
5571 goto fail;
5574 /* Restore clean slate. */
5575 TALLOC_FREE(sd);
5576 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5579 /* Create the test file. */
5580 status = cli_ntcreate(cli,
5581 fname,
5583 GENERIC_ALL_ACCESS,
5584 FILE_ATTRIBUTE_NORMAL,
5585 FILE_SHARE_READ|FILE_SHARE_WRITE|
5586 FILE_SHARE_DELETE,
5587 FILE_CREATE,
5590 &fnum,
5591 NULL);
5592 if (!NT_STATUS_IS_OK(status)) {
5593 printf("Create of %s - %s\n", fname, nt_errstr(status));
5594 goto fail;
5597 /* Get the original SD. */
5598 status = cli_query_secdesc(cli,
5599 fnum,
5600 frame,
5601 &sd);
5602 if (!NT_STATUS_IS_OK(status)) {
5603 printf("cli_query_secdesc failed for %s (%s)\n",
5604 fname, nt_errstr(status));
5605 goto fail;
5609 * Add an "authenticated users" ACE allowing READ_DATA,
5610 * add an "owner-rights" denying READ_DATA,
5611 * and an "authenticated users" ACE allowing WRITE_DATA.
5614 newsd = security_descriptor_dacl_create(frame,
5616 NULL,
5617 NULL,
5618 SID_NT_AUTHENTICATED_USERS,
5619 SEC_ACE_TYPE_ACCESS_ALLOWED,
5620 FILE_READ_DATA,
5622 SID_OWNER_RIGHTS,
5623 SEC_ACE_TYPE_ACCESS_DENIED,
5624 FILE_READ_DATA,
5626 SID_NT_AUTHENTICATED_USERS,
5627 SEC_ACE_TYPE_ACCESS_ALLOWED,
5628 FILE_WRITE_DATA,
5630 NULL);
5631 if (newsd == NULL) {
5632 printf("newsd == NULL\n");
5633 goto fail;
5635 sd->dacl = security_acl_concatenate(frame,
5636 newsd->dacl,
5637 sd->dacl);
5638 if (sd->dacl == NULL) {
5639 printf("sd->dacl == NULL\n");
5640 goto fail;
5642 status = cli_set_secdesc(cli, fnum, sd);
5643 if (!NT_STATUS_IS_OK(status)) {
5644 printf("cli_set_secdesc failed for %s (%s)\n",
5645 fname, nt_errstr(status));
5646 goto fail;
5648 status = cli_close(cli, fnum);
5649 if (!NT_STATUS_IS_OK(status)) {
5650 printf("close failed for %s (%s)\n",
5651 fname, nt_errstr(status));
5652 goto fail;
5654 fnum = (uint16_t)-1;
5656 /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
5657 status = cli_ntcreate(cli,
5658 fname,
5660 FILE_READ_DATA|FILE_WRITE_DATA,
5661 FILE_ATTRIBUTE_NORMAL,
5662 FILE_SHARE_READ|FILE_SHARE_WRITE|
5663 FILE_SHARE_DELETE,
5664 FILE_OPEN,
5667 &fnum,
5668 NULL);
5669 if (!NT_STATUS_IS_OK(status)) {
5670 printf("Open of %s - %s\n", fname, nt_errstr(status));
5671 goto fail;
5674 status = cli_close(cli, fnum);
5675 if (!NT_STATUS_IS_OK(status)) {
5676 printf("close failed for %s (%s)\n",
5677 fname, nt_errstr(status));
5678 goto fail;
5681 cli_unlink(cli, fname,
5682 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5684 TALLOC_FREE(frame);
5685 return true;
5687 fail:
5689 if (cli) {
5690 if (fnum != (uint16_t)-1) {
5691 cli_close(cli, fnum);
5693 cli_unlink(cli, fname,
5694 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5695 torture_close_connection(cli);
5698 TALLOC_FREE(frame);
5699 return false;
5702 static bool run_pipe_number(int dummy)
5704 struct cli_state *cli1;
5705 const char *pipe_name = "\\SPOOLSS";
5706 uint16_t fnum;
5707 int num_pipes = 0;
5708 NTSTATUS status;
5710 printf("starting pipenumber test\n");
5711 if (!torture_open_connection(&cli1, 0)) {
5712 return False;
5715 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5716 while(1) {
5717 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
5718 FILE_ATTRIBUTE_NORMAL,
5719 FILE_SHARE_READ|FILE_SHARE_WRITE,
5720 FILE_OPEN_IF, 0, 0, &fnum, NULL);
5721 if (!NT_STATUS_IS_OK(status)) {
5722 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
5723 break;
5725 num_pipes++;
5726 printf("\r%6d", num_pipes);
5729 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
5730 torture_close_connection(cli1);
5731 return True;
5735 Test open mode returns on read-only files.
5737 static bool run_opentest(int dummy)
5739 static struct cli_state *cli1;
5740 static struct cli_state *cli2;
5741 const char *fname = "\\readonly.file";
5742 uint16_t fnum1, fnum2;
5743 char buf[20];
5744 off_t fsize;
5745 bool correct = True;
5746 char *tmp_path;
5747 NTSTATUS status;
5749 printf("starting open test\n");
5751 if (!torture_open_connection(&cli1, 0)) {
5752 return False;
5755 cli_setatr(cli1, fname, 0, 0);
5756 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5758 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5760 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
5761 if (!NT_STATUS_IS_OK(status)) {
5762 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5763 return False;
5766 status = cli_close(cli1, fnum1);
5767 if (!NT_STATUS_IS_OK(status)) {
5768 printf("close2 failed (%s)\n", nt_errstr(status));
5769 return False;
5772 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
5773 if (!NT_STATUS_IS_OK(status)) {
5774 printf("cli_setatr failed (%s)\n", nt_errstr(status));
5775 return False;
5778 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
5779 if (!NT_STATUS_IS_OK(status)) {
5780 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5781 return False;
5784 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
5785 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
5787 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
5788 NT_STATUS_ACCESS_DENIED)) {
5789 printf("correct error code ERRDOS/ERRnoaccess returned\n");
5792 printf("finished open test 1\n");
5794 cli_close(cli1, fnum1);
5796 /* Now try not readonly and ensure ERRbadshare is returned. */
5798 cli_setatr(cli1, fname, 0, 0);
5800 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
5801 if (!NT_STATUS_IS_OK(status)) {
5802 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5803 return False;
5806 /* This will fail - but the error should be ERRshare. */
5807 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
5809 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
5810 NT_STATUS_SHARING_VIOLATION)) {
5811 printf("correct error code ERRDOS/ERRbadshare returned\n");
5814 status = cli_close(cli1, fnum1);
5815 if (!NT_STATUS_IS_OK(status)) {
5816 printf("close2 failed (%s)\n", nt_errstr(status));
5817 return False;
5820 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5822 printf("finished open test 2\n");
5824 /* Test truncate open disposition on file opened for read. */
5825 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
5826 if (!NT_STATUS_IS_OK(status)) {
5827 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
5828 return False;
5831 /* write 20 bytes. */
5833 memset(buf, '\0', 20);
5835 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
5836 if (!NT_STATUS_IS_OK(status)) {
5837 printf("write failed (%s)\n", nt_errstr(status));
5838 correct = False;
5841 status = cli_close(cli1, fnum1);
5842 if (!NT_STATUS_IS_OK(status)) {
5843 printf("(3) close1 failed (%s)\n", nt_errstr(status));
5844 return False;
5847 /* Ensure size == 20. */
5848 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5849 if (!NT_STATUS_IS_OK(status)) {
5850 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5851 return False;
5854 if (fsize != 20) {
5855 printf("(3) file size != 20\n");
5856 return False;
5859 /* Now test if we can truncate a file opened for readonly. */
5860 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
5861 if (!NT_STATUS_IS_OK(status)) {
5862 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
5863 return False;
5866 status = cli_close(cli1, fnum1);
5867 if (!NT_STATUS_IS_OK(status)) {
5868 printf("close2 failed (%s)\n", nt_errstr(status));
5869 return False;
5872 /* Ensure size == 0. */
5873 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5874 if (!NT_STATUS_IS_OK(status)) {
5875 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5876 return False;
5879 if (fsize != 0) {
5880 printf("(3) file size != 0\n");
5881 return False;
5883 printf("finished open test 3\n");
5885 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5887 printf("Do ctemp tests\n");
5888 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
5889 if (!NT_STATUS_IS_OK(status)) {
5890 printf("ctemp failed (%s)\n", nt_errstr(status));
5891 return False;
5894 printf("ctemp gave path %s\n", tmp_path);
5895 status = cli_close(cli1, fnum1);
5896 if (!NT_STATUS_IS_OK(status)) {
5897 printf("close of temp failed (%s)\n", nt_errstr(status));
5900 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5901 if (!NT_STATUS_IS_OK(status)) {
5902 printf("unlink of temp failed (%s)\n", nt_errstr(status));
5905 /* Test the non-io opens... */
5907 if (!torture_open_connection(&cli2, 1)) {
5908 return False;
5911 cli_setatr(cli2, fname, 0, 0);
5912 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5914 smbXcli_conn_set_sockopt(cli2->conn, sockops);
5916 printf("TEST #1 testing 2 non-io opens (no delete)\n");
5917 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5918 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5919 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5920 if (!NT_STATUS_IS_OK(status)) {
5921 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5922 return False;
5925 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5926 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5927 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5928 if (!NT_STATUS_IS_OK(status)) {
5929 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5930 return False;
5933 status = cli_close(cli1, fnum1);
5934 if (!NT_STATUS_IS_OK(status)) {
5935 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5936 return False;
5939 status = cli_close(cli2, fnum2);
5940 if (!NT_STATUS_IS_OK(status)) {
5941 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5942 return False;
5945 printf("non-io open test #1 passed.\n");
5947 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5949 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5951 status = cli_ntcreate(cli1, fname, 0,
5952 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5953 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5954 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5955 if (!NT_STATUS_IS_OK(status)) {
5956 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5957 return False;
5960 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5961 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5962 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5963 if (!NT_STATUS_IS_OK(status)) {
5964 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5965 return False;
5968 status = cli_close(cli1, fnum1);
5969 if (!NT_STATUS_IS_OK(status)) {
5970 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5971 return False;
5974 status = cli_close(cli2, fnum2);
5975 if (!NT_STATUS_IS_OK(status)) {
5976 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5977 return False;
5980 printf("non-io open test #2 passed.\n");
5982 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5984 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5986 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5987 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5988 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5989 if (!NT_STATUS_IS_OK(status)) {
5990 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5991 return False;
5994 status = cli_ntcreate(cli2, fname, 0,
5995 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5996 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5997 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5998 if (!NT_STATUS_IS_OK(status)) {
5999 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
6000 return False;
6003 status = cli_close(cli1, fnum1);
6004 if (!NT_STATUS_IS_OK(status)) {
6005 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
6006 return False;
6009 status = cli_close(cli2, fnum2);
6010 if (!NT_STATUS_IS_OK(status)) {
6011 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
6012 return False;
6015 printf("non-io open test #3 passed.\n");
6017 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6019 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
6021 status = cli_ntcreate(cli1, fname, 0,
6022 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
6023 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6024 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6025 if (!NT_STATUS_IS_OK(status)) {
6026 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
6027 return False;
6030 status = cli_ntcreate(cli2, fname, 0,
6031 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
6032 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6033 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
6034 if (NT_STATUS_IS_OK(status)) {
6035 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
6036 return False;
6039 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
6041 status = cli_close(cli1, fnum1);
6042 if (!NT_STATUS_IS_OK(status)) {
6043 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
6044 return False;
6047 printf("non-io open test #4 passed.\n");
6049 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6051 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
6053 status = cli_ntcreate(cli1, fname, 0,
6054 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
6055 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
6056 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6057 if (!NT_STATUS_IS_OK(status)) {
6058 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
6059 return False;
6062 status = cli_ntcreate(cli2, fname, 0,
6063 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
6064 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
6065 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
6066 if (!NT_STATUS_IS_OK(status)) {
6067 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
6068 return False;
6071 status = cli_close(cli1, fnum1);
6072 if (!NT_STATUS_IS_OK(status)) {
6073 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
6074 return False;
6077 status = cli_close(cli2, fnum2);
6078 if (!NT_STATUS_IS_OK(status)) {
6079 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
6080 return False;
6083 printf("non-io open test #5 passed.\n");
6085 printf("TEST #6 testing 1 non-io open, one io open\n");
6087 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6089 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
6090 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6091 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6092 if (!NT_STATUS_IS_OK(status)) {
6093 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
6094 return False;
6097 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
6098 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6099 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
6100 if (!NT_STATUS_IS_OK(status)) {
6101 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
6102 return False;
6105 status = cli_close(cli1, fnum1);
6106 if (!NT_STATUS_IS_OK(status)) {
6107 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
6108 return False;
6111 status = cli_close(cli2, fnum2);
6112 if (!NT_STATUS_IS_OK(status)) {
6113 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
6114 return False;
6117 printf("non-io open test #6 passed.\n");
6119 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
6121 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6123 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
6124 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6125 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6126 if (!NT_STATUS_IS_OK(status)) {
6127 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
6128 return False;
6131 status = cli_ntcreate(cli2, fname, 0,
6132 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
6133 FILE_ATTRIBUTE_NORMAL,
6134 FILE_SHARE_READ|FILE_SHARE_DELETE,
6135 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
6136 if (NT_STATUS_IS_OK(status)) {
6137 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
6138 return False;
6141 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
6143 status = cli_close(cli1, fnum1);
6144 if (!NT_STATUS_IS_OK(status)) {
6145 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
6146 return False;
6149 printf("non-io open test #7 passed.\n");
6151 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6153 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
6154 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
6155 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6156 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6157 if (!NT_STATUS_IS_OK(status)) {
6158 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
6159 correct = false;
6160 goto out;
6163 /* Write to ensure we have to update the file time. */
6164 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
6165 NULL);
6166 if (!NT_STATUS_IS_OK(status)) {
6167 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
6168 correct = false;
6169 goto out;
6172 status = cli_close(cli1, fnum1);
6173 if (!NT_STATUS_IS_OK(status)) {
6174 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
6175 correct = false;
6178 out:
6180 if (!torture_close_connection(cli1)) {
6181 correct = False;
6183 if (!torture_close_connection(cli2)) {
6184 correct = False;
6187 return correct;
6190 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
6192 uint16_t major, minor;
6193 uint32_t caplow, caphigh;
6194 NTSTATUS status;
6196 if (!SERVER_HAS_UNIX_CIFS(cli)) {
6197 printf("Server doesn't support UNIX CIFS extensions.\n");
6198 return NT_STATUS_NOT_SUPPORTED;
6201 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
6202 &caphigh);
6203 if (!NT_STATUS_IS_OK(status)) {
6204 printf("Server didn't return UNIX CIFS extensions: %s\n",
6205 nt_errstr(status));
6206 return status;
6209 status = cli_set_unix_extensions_capabilities(cli, major, minor,
6210 caplow, caphigh);
6211 if (!NT_STATUS_IS_OK(status)) {
6212 printf("Server doesn't support setting UNIX CIFS extensions: "
6213 "%s.\n", nt_errstr(status));
6214 return status;
6217 return NT_STATUS_OK;
6221 Test POSIX open /mkdir calls.
6223 static bool run_simple_posix_open_test(int dummy)
6225 static struct cli_state *cli1;
6226 const char *fname = "posix:file";
6227 const char *hname = "posix:hlink";
6228 const char *sname = "posix:symlink";
6229 const char *dname = "posix:dir";
6230 char buf[10];
6231 char namebuf[11];
6232 uint16_t fnum1 = (uint16_t)-1;
6233 SMB_STRUCT_STAT sbuf;
6234 bool correct = false;
6235 NTSTATUS status;
6236 size_t nread;
6237 const char *fname_windows = "windows_file";
6238 uint16_t fnum2 = (uint16_t)-1;
6240 printf("Starting simple POSIX open test\n");
6242 if (!torture_open_connection(&cli1, 0)) {
6243 return false;
6246 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6248 status = torture_setup_unix_extensions(cli1);
6249 if (!NT_STATUS_IS_OK(status)) {
6250 return false;
6253 cli_setatr(cli1, fname, 0, 0);
6254 cli_posix_unlink(cli1, fname);
6255 cli_setatr(cli1, dname, 0, 0);
6256 cli_posix_rmdir(cli1, dname);
6257 cli_setatr(cli1, hname, 0, 0);
6258 cli_posix_unlink(cli1, hname);
6259 cli_setatr(cli1, sname, 0, 0);
6260 cli_posix_unlink(cli1, sname);
6261 cli_setatr(cli1, fname_windows, 0, 0);
6262 cli_posix_unlink(cli1, fname_windows);
6264 /* Create a directory. */
6265 status = cli_posix_mkdir(cli1, dname, 0777);
6266 if (!NT_STATUS_IS_OK(status)) {
6267 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
6268 goto out;
6271 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
6272 0600, &fnum1);
6273 if (!NT_STATUS_IS_OK(status)) {
6274 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6275 goto out;
6278 /* Test ftruncate - set file size. */
6279 status = cli_ftruncate(cli1, fnum1, 1000);
6280 if (!NT_STATUS_IS_OK(status)) {
6281 printf("ftruncate failed (%s)\n", nt_errstr(status));
6282 goto out;
6285 /* Ensure st_size == 1000 */
6286 status = cli_posix_stat(cli1, fname, &sbuf);
6287 if (!NT_STATUS_IS_OK(status)) {
6288 printf("stat failed (%s)\n", nt_errstr(status));
6289 goto out;
6292 if (sbuf.st_ex_size != 1000) {
6293 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
6294 goto out;
6297 /* Ensure st_mode == 0600 */
6298 if ((sbuf.st_ex_mode & 07777) != 0600) {
6299 printf("posix_open - bad permissions 0%o != 0600\n",
6300 (unsigned int)(sbuf.st_ex_mode & 07777));
6301 goto out;
6304 /* Test ftruncate - set file size back to zero. */
6305 status = cli_ftruncate(cli1, fnum1, 0);
6306 if (!NT_STATUS_IS_OK(status)) {
6307 printf("ftruncate failed (%s)\n", nt_errstr(status));
6308 goto out;
6311 status = cli_close(cli1, fnum1);
6312 if (!NT_STATUS_IS_OK(status)) {
6313 printf("close failed (%s)\n", nt_errstr(status));
6314 goto out;
6317 /* Now open the file again for read only. */
6318 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
6319 if (!NT_STATUS_IS_OK(status)) {
6320 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
6321 goto out;
6324 /* Now unlink while open. */
6325 status = cli_posix_unlink(cli1, fname);
6326 if (!NT_STATUS_IS_OK(status)) {
6327 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
6328 goto out;
6331 status = cli_close(cli1, fnum1);
6332 if (!NT_STATUS_IS_OK(status)) {
6333 printf("close(2) failed (%s)\n", nt_errstr(status));
6334 goto out;
6337 /* Ensure the file has gone. */
6338 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
6339 if (NT_STATUS_IS_OK(status)) {
6340 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
6341 goto out;
6344 /* Create again to test open with O_TRUNC. */
6345 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
6346 if (!NT_STATUS_IS_OK(status)) {
6347 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6348 goto out;
6351 /* Test ftruncate - set file size. */
6352 status = cli_ftruncate(cli1, fnum1, 1000);
6353 if (!NT_STATUS_IS_OK(status)) {
6354 printf("ftruncate failed (%s)\n", nt_errstr(status));
6355 goto out;
6358 /* Ensure st_size == 1000 */
6359 status = cli_posix_stat(cli1, fname, &sbuf);
6360 if (!NT_STATUS_IS_OK(status)) {
6361 printf("stat failed (%s)\n", nt_errstr(status));
6362 goto out;
6365 if (sbuf.st_ex_size != 1000) {
6366 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
6367 goto out;
6370 status = cli_close(cli1, fnum1);
6371 if (!NT_STATUS_IS_OK(status)) {
6372 printf("close(2) failed (%s)\n", nt_errstr(status));
6373 goto out;
6376 /* Re-open with O_TRUNC. */
6377 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
6378 if (!NT_STATUS_IS_OK(status)) {
6379 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6380 goto out;
6383 /* Ensure st_size == 0 */
6384 status = cli_posix_stat(cli1, fname, &sbuf);
6385 if (!NT_STATUS_IS_OK(status)) {
6386 printf("stat failed (%s)\n", nt_errstr(status));
6387 goto out;
6390 if (sbuf.st_ex_size != 0) {
6391 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
6392 goto out;
6395 status = cli_close(cli1, fnum1);
6396 if (!NT_STATUS_IS_OK(status)) {
6397 printf("close failed (%s)\n", nt_errstr(status));
6398 goto out;
6401 status = cli_posix_unlink(cli1, fname);
6402 if (!NT_STATUS_IS_OK(status)) {
6403 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
6404 goto out;
6407 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
6408 if (!NT_STATUS_IS_OK(status)) {
6409 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
6410 dname, nt_errstr(status));
6411 goto out;
6414 cli_close(cli1, fnum1);
6416 /* What happens when we try and POSIX open a directory for write ? */
6417 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
6418 if (NT_STATUS_IS_OK(status)) {
6419 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
6420 goto out;
6421 } else {
6422 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
6423 NT_STATUS_FILE_IS_A_DIRECTORY)) {
6424 goto out;
6428 /* Create the file. */
6429 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
6430 0600, &fnum1);
6431 if (!NT_STATUS_IS_OK(status)) {
6432 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6433 goto out;
6436 /* Write some data into it. */
6437 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
6438 NULL);
6439 if (!NT_STATUS_IS_OK(status)) {
6440 printf("cli_write failed: %s\n", nt_errstr(status));
6441 goto out;
6444 cli_close(cli1, fnum1);
6446 /* Now create a hardlink. */
6447 status = cli_posix_hardlink(cli1, fname, hname);
6448 if (!NT_STATUS_IS_OK(status)) {
6449 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
6450 goto out;
6453 /* Now create a symlink. */
6454 status = cli_posix_symlink(cli1, fname, sname);
6455 if (!NT_STATUS_IS_OK(status)) {
6456 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
6457 goto out;
6460 /* Open the hardlink for read. */
6461 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
6462 if (!NT_STATUS_IS_OK(status)) {
6463 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
6464 goto out;
6467 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
6468 if (!NT_STATUS_IS_OK(status)) {
6469 printf("POSIX read of %s failed (%s)\n", hname,
6470 nt_errstr(status));
6471 goto out;
6472 } else if (nread != 10) {
6473 printf("POSIX read of %s failed. Received %ld, expected %d\n",
6474 hname, (unsigned long)nread, 10);
6475 goto out;
6478 if (memcmp(buf, "TEST DATA\n", 10)) {
6479 printf("invalid data read from hardlink\n");
6480 goto out;
6483 /* Do a POSIX lock/unlock. */
6484 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
6485 if (!NT_STATUS_IS_OK(status)) {
6486 printf("POSIX lock failed %s\n", nt_errstr(status));
6487 goto out;
6490 /* Punch a hole in the locked area. */
6491 status = cli_posix_unlock(cli1, fnum1, 10, 80);
6492 if (!NT_STATUS_IS_OK(status)) {
6493 printf("POSIX unlock failed %s\n", nt_errstr(status));
6494 goto out;
6497 cli_close(cli1, fnum1);
6499 /* Open the symlink for read - this should fail. A POSIX
6500 client should not be doing opens on a symlink. */
6501 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
6502 if (NT_STATUS_IS_OK(status)) {
6503 printf("POSIX open of %s succeeded (should have failed)\n", sname);
6504 goto out;
6505 } else {
6506 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
6507 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
6508 printf("POSIX open of %s should have failed "
6509 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
6510 "failed with %s instead.\n",
6511 sname, nt_errstr(status));
6512 goto out;
6516 status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
6517 if (!NT_STATUS_IS_OK(status)) {
6518 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
6519 goto out;
6522 if (strcmp(namebuf, fname) != 0) {
6523 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
6524 sname, fname, namebuf);
6525 goto out;
6528 status = cli_posix_rmdir(cli1, dname);
6529 if (!NT_STATUS_IS_OK(status)) {
6530 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
6531 goto out;
6534 /* Check directory opens with a specific permission. */
6535 status = cli_posix_mkdir(cli1, dname, 0700);
6536 if (!NT_STATUS_IS_OK(status)) {
6537 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
6538 goto out;
6541 /* Ensure st_mode == 0700 */
6542 status = cli_posix_stat(cli1, dname, &sbuf);
6543 if (!NT_STATUS_IS_OK(status)) {
6544 printf("stat failed (%s)\n", nt_errstr(status));
6545 goto out;
6548 if ((sbuf.st_ex_mode & 07777) != 0700) {
6549 printf("posix_mkdir - bad permissions 0%o != 0700\n",
6550 (unsigned int)(sbuf.st_ex_mode & 07777));
6551 goto out;
6555 * Now create a Windows file, and attempt a POSIX unlink.
6556 * This should fail with a sharing violation but due to:
6558 * [Bug 9571] Unlink after open causes smbd to panic
6560 * ensure we've fixed the lock ordering violation.
6563 status = cli_ntcreate(cli1, fname_windows, 0,
6564 FILE_READ_DATA|FILE_WRITE_DATA, 0,
6565 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6566 FILE_CREATE,
6567 0x0, 0x0, &fnum2, NULL);
6568 if (!NT_STATUS_IS_OK(status)) {
6569 printf("Windows create of %s failed (%s)\n", fname_windows,
6570 nt_errstr(status));
6571 goto out;
6574 /* Now try posix_unlink. */
6575 status = cli_posix_unlink(cli1, fname_windows);
6576 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6577 printf("POSIX unlink of %s should fail "
6578 "with NT_STATUS_SHARING_VIOLATION "
6579 "got %s instead !\n",
6580 fname_windows,
6581 nt_errstr(status));
6582 goto out;
6585 cli_close(cli1, fnum2);
6587 printf("Simple POSIX open test passed\n");
6588 correct = true;
6590 out:
6592 if (fnum1 != (uint16_t)-1) {
6593 cli_close(cli1, fnum1);
6594 fnum1 = (uint16_t)-1;
6597 if (fnum2 != (uint16_t)-1) {
6598 cli_close(cli1, fnum2);
6599 fnum2 = (uint16_t)-1;
6602 cli_setatr(cli1, sname, 0, 0);
6603 cli_posix_unlink(cli1, sname);
6604 cli_setatr(cli1, hname, 0, 0);
6605 cli_posix_unlink(cli1, hname);
6606 cli_setatr(cli1, fname, 0, 0);
6607 cli_posix_unlink(cli1, fname);
6608 cli_setatr(cli1, dname, 0, 0);
6609 cli_posix_rmdir(cli1, dname);
6610 cli_setatr(cli1, fname_windows, 0, 0);
6611 cli_posix_unlink(cli1, fname_windows);
6613 if (!torture_close_connection(cli1)) {
6614 correct = false;
6617 return correct;
6621 Test POSIX and Windows ACLs are rejected on symlinks.
6623 static bool run_acl_symlink_test(int dummy)
6625 static struct cli_state *cli;
6626 const char *fname = "posix_file";
6627 const char *sname = "posix_symlink";
6628 uint16_t fnum = (uint16_t)-1;
6629 bool correct = false;
6630 NTSTATUS status;
6631 char *posix_acl = NULL;
6632 size_t posix_acl_len = 0;
6633 char *posix_acl_sym = NULL;
6634 size_t posix_acl_len_sym = 0;
6635 struct security_descriptor *sd = NULL;
6636 struct security_descriptor *sd_sym = NULL;
6637 TALLOC_CTX *frame = NULL;
6639 frame = talloc_stackframe();
6641 printf("Starting acl symlink test\n");
6643 if (!torture_open_connection(&cli, 0)) {
6644 TALLOC_FREE(frame);
6645 return false;
6648 smbXcli_conn_set_sockopt(cli->conn, sockops);
6650 status = torture_setup_unix_extensions(cli);
6651 if (!NT_STATUS_IS_OK(status)) {
6652 TALLOC_FREE(frame);
6653 return false;
6656 cli_setatr(cli, fname, 0, 0);
6657 cli_posix_unlink(cli, fname);
6658 cli_setatr(cli, sname, 0, 0);
6659 cli_posix_unlink(cli, sname);
6661 status = cli_ntcreate(cli,
6662 fname,
6664 READ_CONTROL_ACCESS,
6666 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6667 FILE_CREATE,
6668 0x0,
6669 0x0,
6670 &fnum,
6671 NULL);
6673 if (!NT_STATUS_IS_OK(status)) {
6674 printf("cli_ntcreate of %s failed (%s)\n",
6675 fname,
6676 nt_errstr(status));
6677 goto out;
6680 /* Get the Windows ACL on the file. */
6681 status = cli_query_secdesc(cli,
6682 fnum,
6683 frame,
6684 &sd);
6685 if (!NT_STATUS_IS_OK(status)) {
6686 printf("cli_query_secdesc failed (%s)\n",
6687 nt_errstr(status));
6688 goto out;
6691 /* Get the POSIX ACL on the file. */
6692 status = cli_posix_getacl(cli,
6693 fname,
6694 frame,
6695 &posix_acl_len,
6696 &posix_acl);
6698 if (!NT_STATUS_IS_OK(status)) {
6699 printf("cli_posix_getacl failed (%s)\n",
6700 nt_errstr(status));
6701 goto out;
6704 status = cli_close(cli, fnum);
6705 if (!NT_STATUS_IS_OK(status)) {
6706 printf("close failed (%s)\n", nt_errstr(status));
6707 goto out;
6709 fnum = (uint16_t)-1;
6711 /* Now create a symlink. */
6712 status = cli_posix_symlink(cli, fname, sname);
6713 if (!NT_STATUS_IS_OK(status)) {
6714 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
6715 sname,
6716 fname,
6717 nt_errstr(status));
6718 goto out;
6721 /* Open a handle on the symlink. */
6722 status = cli_ntcreate(cli,
6723 sname,
6725 READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
6727 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6728 FILE_OPEN,
6729 0x0,
6730 0x0,
6731 &fnum,
6732 NULL);
6734 if (!NT_STATUS_IS_OK(status)) {
6735 printf("cli_posix_open of %s failed (%s)\n",
6736 sname,
6737 nt_errstr(status));
6738 goto out;
6741 /* Get the Windows ACL on the symlink handle. Should fail */
6742 status = cli_query_secdesc(cli,
6743 fnum,
6744 frame,
6745 &sd_sym);
6747 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6748 printf("cli_query_secdesc on a symlink gave %s. "
6749 "Should be NT_STATUS_ACCESS_DENIED.\n",
6750 nt_errstr(status));
6751 goto out;
6754 /* Get the POSIX ACL on the symlink pathname. Should fail. */
6755 status = cli_posix_getacl(cli,
6756 sname,
6757 frame,
6758 &posix_acl_len_sym,
6759 &posix_acl_sym);
6761 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6762 printf("cli_posix_getacl on a symlink gave %s. "
6763 "Should be NT_STATUS_ACCESS_DENIED.\n",
6764 nt_errstr(status));
6765 goto out;
6768 /* Set the Windows ACL on the symlink handle. Should fail */
6769 status = cli_set_security_descriptor(cli,
6770 fnum,
6771 SECINFO_DACL,
6772 sd);
6774 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6775 printf("cli_query_secdesc on a symlink gave %s. "
6776 "Should be NT_STATUS_ACCESS_DENIED.\n",
6777 nt_errstr(status));
6778 goto out;
6781 /* Set the POSIX ACL on the symlink pathname. Should fail. */
6782 status = cli_posix_setacl(cli,
6783 sname,
6784 posix_acl,
6785 posix_acl_len);
6787 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6788 printf("cli_posix_getacl on a symlink gave %s. "
6789 "Should be NT_STATUS_ACCESS_DENIED.\n",
6790 nt_errstr(status));
6791 goto out;
6794 printf("ACL symlink test passed\n");
6795 correct = true;
6797 out:
6799 if (fnum != (uint16_t)-1) {
6800 cli_close(cli, fnum);
6801 fnum = (uint16_t)-1;
6804 cli_setatr(cli, sname, 0, 0);
6805 cli_posix_unlink(cli, sname);
6806 cli_setatr(cli, fname, 0, 0);
6807 cli_posix_unlink(cli, fname);
6809 if (!torture_close_connection(cli)) {
6810 correct = false;
6813 TALLOC_FREE(frame);
6814 return correct;
6818 Test POSIX can delete a file containing streams.
6820 static bool run_posix_stream_delete(int dummy)
6822 struct cli_state *cli1 = NULL;
6823 struct cli_state *cli2 = NULL;
6824 const char *fname = "streamfile";
6825 const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
6826 uint16_t fnum1 = (uint16_t)-1;
6827 bool correct = false;
6828 NTSTATUS status;
6829 TALLOC_CTX *frame = NULL;
6831 frame = talloc_stackframe();
6833 printf("Starting POSIX stream delete test\n");
6835 if (!torture_open_connection(&cli1, 0) ||
6836 !torture_open_connection(&cli2, 1)) {
6837 TALLOC_FREE(frame);
6838 return false;
6841 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6842 smbXcli_conn_set_sockopt(cli2->conn, sockops);
6844 status = torture_setup_unix_extensions(cli2);
6845 if (!NT_STATUS_IS_OK(status)) {
6846 goto out;
6849 cli_setatr(cli1, fname, 0, 0);
6850 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6852 /* Create the file. */
6853 status = cli_ntcreate(cli1,
6854 fname,
6856 READ_CONTROL_ACCESS,
6858 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6859 FILE_CREATE,
6860 0x0,
6861 0x0,
6862 &fnum1,
6863 NULL);
6865 if (!NT_STATUS_IS_OK(status)) {
6866 printf("cli_ntcreate of %s failed (%s)\n",
6867 fname,
6868 nt_errstr(status));
6869 goto out;
6872 status = cli_close(cli1, fnum1);
6873 if (!NT_STATUS_IS_OK(status)) {
6874 printf("cli_close of %s failed (%s)\n",
6875 fname,
6876 nt_errstr(status));
6877 goto out;
6879 fnum1 = (uint16_t)-1;
6881 /* Now create the stream. */
6882 status = cli_ntcreate(cli1,
6883 stream_fname,
6885 FILE_WRITE_DATA,
6887 FILE_SHARE_READ|FILE_SHARE_WRITE,
6888 FILE_CREATE,
6889 0x0,
6890 0x0,
6891 &fnum1,
6892 NULL);
6894 if (!NT_STATUS_IS_OK(status)) {
6895 printf("cli_ntcreate of %s failed (%s)\n",
6896 stream_fname,
6897 nt_errstr(status));
6898 goto out;
6901 /* Leave the stream handle open... */
6903 /* POSIX unlink should fail. */
6904 status = cli_posix_unlink(cli2, fname);
6905 if (NT_STATUS_IS_OK(status)) {
6906 printf("cli_posix_unlink of %s succeeded, should have failed\n",
6907 fname);
6908 goto out;
6911 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6912 printf("cli_posix_unlink of %s failed with (%s) "
6913 "should have been NT_STATUS_SHARING_VIOLATION\n",
6914 fname,
6915 nt_errstr(status));
6916 goto out;
6919 /* Close the stream handle. */
6920 status = cli_close(cli1, fnum1);
6921 if (!NT_STATUS_IS_OK(status)) {
6922 printf("cli_close of %s failed (%s)\n",
6923 stream_fname,
6924 nt_errstr(status));
6925 goto out;
6927 fnum1 = (uint16_t)-1;
6929 /* POSIX unlink after stream handle closed should succeed. */
6930 status = cli_posix_unlink(cli2, fname);
6931 if (!NT_STATUS_IS_OK(status)) {
6932 printf("cli_posix_unlink of %s failed (%s)\n",
6933 fname,
6934 nt_errstr(status));
6935 goto out;
6938 printf("POSIX stream delete test passed\n");
6939 correct = true;
6941 out:
6943 if (fnum1 != (uint16_t)-1) {
6944 cli_close(cli1, fnum1);
6945 fnum1 = (uint16_t)-1;
6948 cli_setatr(cli1, fname, 0, 0);
6949 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6951 if (!torture_close_connection(cli1)) {
6952 correct = false;
6954 if (!torture_close_connection(cli2)) {
6955 correct = false;
6958 TALLOC_FREE(frame);
6959 return correct;
6963 Test setting EA's are rejected on symlinks.
6965 static bool run_ea_symlink_test(int dummy)
6967 static struct cli_state *cli;
6968 const char *fname = "posix_file_ea";
6969 const char *sname = "posix_symlink_ea";
6970 const char *ea_name = "testea_name";
6971 const char *ea_value = "testea_value";
6972 uint16_t fnum = (uint16_t)-1;
6973 bool correct = false;
6974 NTSTATUS status;
6975 size_t i, num_eas;
6976 struct ea_struct *eas = NULL;
6977 TALLOC_CTX *frame = NULL;
6979 frame = talloc_stackframe();
6981 printf("Starting EA symlink test\n");
6983 if (!torture_open_connection(&cli, 0)) {
6984 TALLOC_FREE(frame);
6985 return false;
6988 smbXcli_conn_set_sockopt(cli->conn, sockops);
6990 status = torture_setup_unix_extensions(cli);
6991 if (!NT_STATUS_IS_OK(status)) {
6992 TALLOC_FREE(frame);
6993 return false;
6996 cli_setatr(cli, fname, 0, 0);
6997 cli_posix_unlink(cli, fname);
6998 cli_setatr(cli, sname, 0, 0);
6999 cli_posix_unlink(cli, sname);
7001 status = cli_ntcreate(cli,
7002 fname,
7004 READ_CONTROL_ACCESS,
7006 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7007 FILE_CREATE,
7008 0x0,
7009 0x0,
7010 &fnum,
7011 NULL);
7013 if (!NT_STATUS_IS_OK(status)) {
7014 printf("cli_ntcreate of %s failed (%s)\n",
7015 fname,
7016 nt_errstr(status));
7017 goto out;
7020 status = cli_close(cli, fnum);
7021 if (!NT_STATUS_IS_OK(status)) {
7022 printf("close failed (%s)\n",
7023 nt_errstr(status));
7024 goto out;
7026 fnum = (uint16_t)-1;
7028 /* Set an EA on the path. */
7029 status = cli_set_ea_path(cli,
7030 fname,
7031 ea_name,
7032 ea_value,
7033 strlen(ea_value)+1);
7035 if (!NT_STATUS_IS_OK(status)) {
7036 printf("cli_set_ea_path failed (%s)\n",
7037 nt_errstr(status));
7038 goto out;
7041 /* Now create a symlink. */
7042 status = cli_posix_symlink(cli, fname, sname);
7043 if (!NT_STATUS_IS_OK(status)) {
7044 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
7045 sname,
7046 fname,
7047 nt_errstr(status));
7048 goto out;
7051 /* Get the EA list on the path. Should return value set. */
7052 status = cli_get_ea_list_path(cli,
7053 fname,
7054 frame,
7055 &num_eas,
7056 &eas);
7058 if (!NT_STATUS_IS_OK(status)) {
7059 printf("cli_get_ea_list_path failed (%s)\n",
7060 nt_errstr(status));
7061 goto out;
7064 /* Ensure the EA we set is there. */
7065 for (i=0; i<num_eas; i++) {
7066 if (strcmp(eas[i].name, ea_name) == 0 &&
7067 eas[i].value.length == strlen(ea_value)+1 &&
7068 memcmp(eas[i].value.data,
7069 ea_value,
7070 eas[i].value.length) == 0) {
7071 break;
7075 if (i == num_eas) {
7076 printf("Didn't find EA on pathname %s\n",
7077 fname);
7078 goto out;
7081 num_eas = 0;
7082 TALLOC_FREE(eas);
7084 /* Get the EA list on the symlink. Should return empty list. */
7085 status = cli_get_ea_list_path(cli,
7086 sname,
7087 frame,
7088 &num_eas,
7089 &eas);
7091 if (!NT_STATUS_IS_OK(status)) {
7092 printf("cli_get_ea_list_path failed (%s)\n",
7093 nt_errstr(status));
7094 goto out;
7097 if (num_eas != 0) {
7098 printf("cli_get_ea_list_path failed (%s)\n",
7099 nt_errstr(status));
7100 goto out;
7103 /* Set an EA on the symlink. Should fail. */
7104 status = cli_set_ea_path(cli,
7105 sname,
7106 ea_name,
7107 ea_value,
7108 strlen(ea_value)+1);
7110 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7111 printf("cli_set_ea_path on a symlink gave %s. "
7112 "Should be NT_STATUS_ACCESS_DENIED.\n",
7113 nt_errstr(status));
7114 goto out;
7117 printf("EA symlink test passed\n");
7118 correct = true;
7120 out:
7122 if (fnum != (uint16_t)-1) {
7123 cli_close(cli, fnum);
7124 fnum = (uint16_t)-1;
7127 cli_setatr(cli, sname, 0, 0);
7128 cli_posix_unlink(cli, sname);
7129 cli_setatr(cli, fname, 0, 0);
7130 cli_posix_unlink(cli, fname);
7132 if (!torture_close_connection(cli)) {
7133 correct = false;
7136 TALLOC_FREE(frame);
7137 return correct;
7141 Test POSIX locks are OFD-locks.
7143 static bool run_posix_ofd_lock_test(int dummy)
7145 static struct cli_state *cli;
7146 const char *fname = "posix_file";
7147 uint16_t fnum1 = (uint16_t)-1;
7148 uint16_t fnum2 = (uint16_t)-1;
7149 bool correct = false;
7150 NTSTATUS status;
7151 TALLOC_CTX *frame = NULL;
7153 frame = talloc_stackframe();
7155 printf("Starting POSIX ofd-lock test\n");
7157 if (!torture_open_connection(&cli, 0)) {
7158 TALLOC_FREE(frame);
7159 return false;
7162 smbXcli_conn_set_sockopt(cli->conn, sockops);
7164 status = torture_setup_unix_extensions(cli);
7165 if (!NT_STATUS_IS_OK(status)) {
7166 TALLOC_FREE(frame);
7167 return false;
7170 cli_setatr(cli, fname, 0, 0);
7171 cli_posix_unlink(cli, fname);
7173 /* Open the file twice. */
7174 status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
7175 0600, &fnum1);
7176 if (!NT_STATUS_IS_OK(status)) {
7177 printf("First POSIX open of %s failed\n", fname);
7178 goto out;
7181 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
7182 if (!NT_STATUS_IS_OK(status)) {
7183 printf("First POSIX open of %s failed\n", fname);
7184 goto out;
7187 /* Set a 0-50 lock on fnum1. */
7188 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
7189 if (!NT_STATUS_IS_OK(status)) {
7190 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
7191 goto out;
7194 /* Set a 60-100 lock on fnum2. */
7195 status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
7196 if (!NT_STATUS_IS_OK(status)) {
7197 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
7198 goto out;
7201 /* close fnum1 - 0-50 lock should go away. */
7202 status = cli_close(cli, fnum1);
7203 if (!NT_STATUS_IS_OK(status)) {
7204 printf("close failed (%s)\n",
7205 nt_errstr(status));
7206 goto out;
7208 fnum1 = (uint16_t)-1;
7210 /* Change the lock context. */
7211 cli_setpid(cli, cli_getpid(cli) + 1);
7213 /* Re-open fnum1. */
7214 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
7215 if (!NT_STATUS_IS_OK(status)) {
7216 printf("Third POSIX open of %s failed\n", fname);
7217 goto out;
7220 /* 60-100 lock should still be there. */
7221 status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
7222 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
7223 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
7224 goto out;
7227 /* 0-50 lock should be gone. */
7228 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
7229 if (!NT_STATUS_IS_OK(status)) {
7230 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
7231 goto out;
7234 printf("POSIX OFD lock test passed\n");
7235 correct = true;
7237 out:
7239 if (fnum1 != (uint16_t)-1) {
7240 cli_close(cli, fnum1);
7241 fnum1 = (uint16_t)-1;
7243 if (fnum2 != (uint16_t)-1) {
7244 cli_close(cli, fnum2);
7245 fnum2 = (uint16_t)-1;
7248 cli_setatr(cli, fname, 0, 0);
7249 cli_posix_unlink(cli, fname);
7251 if (!torture_close_connection(cli)) {
7252 correct = false;
7255 TALLOC_FREE(frame);
7256 return correct;
7259 static uint32_t open_attrs_table[] = {
7260 FILE_ATTRIBUTE_NORMAL,
7261 FILE_ATTRIBUTE_ARCHIVE,
7262 FILE_ATTRIBUTE_READONLY,
7263 FILE_ATTRIBUTE_HIDDEN,
7264 FILE_ATTRIBUTE_SYSTEM,
7266 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
7267 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
7268 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
7269 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
7270 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
7271 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
7273 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
7274 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
7275 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
7276 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
7279 struct trunc_open_results {
7280 unsigned int num;
7281 uint32_t init_attr;
7282 uint32_t trunc_attr;
7283 uint32_t result_attr;
7286 static struct trunc_open_results attr_results[] = {
7287 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
7288 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
7289 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
7290 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
7291 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
7292 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
7293 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7294 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7295 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
7296 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7297 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7298 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
7299 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7300 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7301 { 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 },
7302 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7303 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7304 { 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 },
7305 { 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 },
7306 { 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 },
7307 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7308 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7309 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
7310 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7311 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7312 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
7315 static bool run_openattrtest(int dummy)
7317 static struct cli_state *cli1;
7318 const char *fname = "\\openattr.file";
7319 uint16_t fnum1;
7320 bool correct = True;
7321 uint16_t attr;
7322 unsigned int i, j, k, l;
7323 NTSTATUS status;
7325 printf("starting open attr test\n");
7327 if (!torture_open_connection(&cli1, 0)) {
7328 return False;
7331 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7333 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
7334 cli_setatr(cli1, fname, 0, 0);
7335 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7337 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
7338 open_attrs_table[i], FILE_SHARE_NONE,
7339 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7340 if (!NT_STATUS_IS_OK(status)) {
7341 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
7342 return False;
7345 status = cli_close(cli1, fnum1);
7346 if (!NT_STATUS_IS_OK(status)) {
7347 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
7348 return False;
7351 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
7352 status = cli_ntcreate(cli1, fname, 0,
7353 FILE_READ_DATA|FILE_WRITE_DATA,
7354 open_attrs_table[j],
7355 FILE_SHARE_NONE, FILE_OVERWRITE,
7356 0, 0, &fnum1, NULL);
7357 if (!NT_STATUS_IS_OK(status)) {
7358 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
7359 if (attr_results[l].num == k) {
7360 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
7361 k, open_attrs_table[i],
7362 open_attrs_table[j],
7363 fname, NT_STATUS_V(status), nt_errstr(status));
7364 correct = False;
7368 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7369 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
7370 k, open_attrs_table[i], open_attrs_table[j],
7371 nt_errstr(status));
7372 correct = False;
7374 #if 0
7375 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
7376 #endif
7377 k++;
7378 continue;
7381 status = cli_close(cli1, fnum1);
7382 if (!NT_STATUS_IS_OK(status)) {
7383 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
7384 return False;
7387 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
7388 if (!NT_STATUS_IS_OK(status)) {
7389 printf("getatr(2) failed (%s)\n", nt_errstr(status));
7390 return False;
7393 #if 0
7394 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
7395 k, open_attrs_table[i], open_attrs_table[j], attr );
7396 #endif
7398 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
7399 if (attr_results[l].num == k) {
7400 if (attr != attr_results[l].result_attr ||
7401 open_attrs_table[i] != attr_results[l].init_attr ||
7402 open_attrs_table[j] != attr_results[l].trunc_attr) {
7403 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
7404 open_attrs_table[i],
7405 open_attrs_table[j],
7406 (unsigned int)attr,
7407 attr_results[l].result_attr);
7408 correct = False;
7410 break;
7413 k++;
7417 cli_setatr(cli1, fname, 0, 0);
7418 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7420 printf("open attr test %s.\n", correct ? "passed" : "failed");
7422 if (!torture_close_connection(cli1)) {
7423 correct = False;
7425 return correct;
7428 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
7429 const char *name, void *state)
7431 int *matched = (int *)state;
7432 if (matched != NULL) {
7433 *matched += 1;
7435 return NT_STATUS_OK;
7439 test directory listing speed
7441 static bool run_dirtest(int dummy)
7443 int i;
7444 static struct cli_state *cli;
7445 uint16_t fnum;
7446 struct timeval core_start;
7447 bool correct = True;
7448 int matched;
7450 printf("starting directory test\n");
7452 if (!torture_open_connection(&cli, 0)) {
7453 return False;
7456 smbXcli_conn_set_sockopt(cli->conn, sockops);
7458 srandom(0);
7459 for (i=0;i<torture_numops;i++) {
7460 fstring fname;
7461 slprintf(fname, sizeof(fname), "\\%x", (int)random());
7462 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
7463 fprintf(stderr,"Failed to open %s\n", fname);
7464 return False;
7466 cli_close(cli, fnum);
7469 core_start = timeval_current();
7471 matched = 0;
7472 cli_list(cli, "a*.*", 0, list_fn, &matched);
7473 printf("Matched %d\n", matched);
7475 matched = 0;
7476 cli_list(cli, "b*.*", 0, list_fn, &matched);
7477 printf("Matched %d\n", matched);
7479 matched = 0;
7480 cli_list(cli, "xyzabc", 0, list_fn, &matched);
7481 printf("Matched %d\n", matched);
7483 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
7485 srandom(0);
7486 for (i=0;i<torture_numops;i++) {
7487 fstring fname;
7488 slprintf(fname, sizeof(fname), "\\%x", (int)random());
7489 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7492 if (!torture_close_connection(cli)) {
7493 correct = False;
7496 printf("finished dirtest\n");
7498 return correct;
7501 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
7502 void *state)
7504 struct cli_state *pcli = (struct cli_state *)state;
7505 fstring fname;
7506 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
7508 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7509 return NT_STATUS_OK;
7511 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7512 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
7513 printf("del_fn: failed to rmdir %s\n,", fname );
7514 } else {
7515 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
7516 printf("del_fn: failed to unlink %s\n,", fname );
7518 return NT_STATUS_OK;
7523 sees what IOCTLs are supported
7525 bool torture_ioctl_test(int dummy)
7527 static struct cli_state *cli;
7528 uint16_t device, function;
7529 uint16_t fnum;
7530 const char *fname = "\\ioctl.dat";
7531 DATA_BLOB blob;
7532 NTSTATUS status;
7534 if (!torture_open_connection(&cli, 0)) {
7535 return False;
7538 printf("starting ioctl test\n");
7540 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7542 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7543 if (!NT_STATUS_IS_OK(status)) {
7544 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7545 return False;
7548 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
7549 printf("ioctl device info: %s\n", nt_errstr(status));
7551 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
7552 printf("ioctl job info: %s\n", nt_errstr(status));
7554 for (device=0;device<0x100;device++) {
7555 printf("ioctl test with device = 0x%x\n", device);
7556 for (function=0;function<0x100;function++) {
7557 uint32_t code = (device<<16) | function;
7559 status = cli_raw_ioctl(cli, fnum, code, &blob);
7561 if (NT_STATUS_IS_OK(status)) {
7562 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
7563 (int)blob.length);
7564 data_blob_free(&blob);
7569 if (!torture_close_connection(cli)) {
7570 return False;
7573 return True;
7578 tries varients of chkpath
7580 bool torture_chkpath_test(int dummy)
7582 static struct cli_state *cli;
7583 uint16_t fnum;
7584 bool ret;
7585 NTSTATUS status;
7587 if (!torture_open_connection(&cli, 0)) {
7588 return False;
7591 printf("starting chkpath test\n");
7593 /* cleanup from an old run */
7594 cli_rmdir(cli, "\\chkpath.dir\\dir2");
7595 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7596 cli_rmdir(cli, "\\chkpath.dir");
7598 status = cli_mkdir(cli, "\\chkpath.dir");
7599 if (!NT_STATUS_IS_OK(status)) {
7600 printf("mkdir1 failed : %s\n", nt_errstr(status));
7601 return False;
7604 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
7605 if (!NT_STATUS_IS_OK(status)) {
7606 printf("mkdir2 failed : %s\n", nt_errstr(status));
7607 return False;
7610 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
7611 DENY_NONE, &fnum);
7612 if (!NT_STATUS_IS_OK(status)) {
7613 printf("open1 failed (%s)\n", nt_errstr(status));
7614 return False;
7616 cli_close(cli, fnum);
7618 status = cli_chkpath(cli, "\\chkpath.dir");
7619 if (!NT_STATUS_IS_OK(status)) {
7620 printf("chkpath1 failed: %s\n", nt_errstr(status));
7621 ret = False;
7624 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
7625 if (!NT_STATUS_IS_OK(status)) {
7626 printf("chkpath2 failed: %s\n", nt_errstr(status));
7627 ret = False;
7630 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
7631 if (!NT_STATUS_IS_OK(status)) {
7632 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
7633 NT_STATUS_NOT_A_DIRECTORY);
7634 } else {
7635 printf("* chkpath on a file should fail\n");
7636 ret = False;
7639 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
7640 if (!NT_STATUS_IS_OK(status)) {
7641 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
7642 NT_STATUS_OBJECT_NAME_NOT_FOUND);
7643 } else {
7644 printf("* chkpath on a non existent file should fail\n");
7645 ret = False;
7648 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
7649 if (!NT_STATUS_IS_OK(status)) {
7650 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
7651 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7652 } else {
7653 printf("* chkpath on a non existent component should fail\n");
7654 ret = False;
7657 cli_rmdir(cli, "\\chkpath.dir\\dir2");
7658 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7659 cli_rmdir(cli, "\\chkpath.dir");
7661 if (!torture_close_connection(cli)) {
7662 return False;
7665 return ret;
7668 static bool run_eatest(int dummy)
7670 static struct cli_state *cli;
7671 const char *fname = "\\eatest.txt";
7672 bool correct = True;
7673 uint16_t fnum;
7674 int i;
7675 size_t num_eas;
7676 struct ea_struct *ea_list = NULL;
7677 TALLOC_CTX *mem_ctx = talloc_init("eatest");
7678 NTSTATUS status;
7680 printf("starting eatest\n");
7682 if (!torture_open_connection(&cli, 0)) {
7683 talloc_destroy(mem_ctx);
7684 return False;
7687 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7689 status = cli_ntcreate(cli, fname, 0,
7690 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
7691 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
7692 0x4044, 0, &fnum, NULL);
7693 if (!NT_STATUS_IS_OK(status)) {
7694 printf("open failed - %s\n", nt_errstr(status));
7695 talloc_destroy(mem_ctx);
7696 return False;
7699 for (i = 0; i < 10; i++) {
7700 fstring ea_name, ea_val;
7702 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
7703 memset(ea_val, (char)i+1, i+1);
7704 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
7705 if (!NT_STATUS_IS_OK(status)) {
7706 printf("ea_set of name %s failed - %s\n", ea_name,
7707 nt_errstr(status));
7708 talloc_destroy(mem_ctx);
7709 return False;
7713 cli_close(cli, fnum);
7714 for (i = 0; i < 10; i++) {
7715 fstring ea_name, ea_val;
7717 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
7718 memset(ea_val, (char)i+1, i+1);
7719 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
7720 if (!NT_STATUS_IS_OK(status)) {
7721 printf("ea_set of name %s failed - %s\n", ea_name,
7722 nt_errstr(status));
7723 talloc_destroy(mem_ctx);
7724 return False;
7728 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
7729 if (!NT_STATUS_IS_OK(status)) {
7730 printf("ea_get list failed - %s\n", nt_errstr(status));
7731 correct = False;
7734 printf("num_eas = %d\n", (int)num_eas);
7736 if (num_eas != 20) {
7737 printf("Should be 20 EA's stored... failing.\n");
7738 correct = False;
7741 for (i = 0; i < num_eas; i++) {
7742 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
7743 dump_data(0, ea_list[i].value.data,
7744 ea_list[i].value.length);
7747 /* Setting EA's to zero length deletes them. Test this */
7748 printf("Now deleting all EA's - case indepenent....\n");
7750 #if 1
7751 cli_set_ea_path(cli, fname, "", "", 0);
7752 #else
7753 for (i = 0; i < 20; i++) {
7754 fstring ea_name;
7755 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
7756 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
7757 if (!NT_STATUS_IS_OK(status)) {
7758 printf("ea_set of name %s failed - %s\n", ea_name,
7759 nt_errstr(status));
7760 talloc_destroy(mem_ctx);
7761 return False;
7764 #endif
7766 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
7767 if (!NT_STATUS_IS_OK(status)) {
7768 printf("ea_get list failed - %s\n", nt_errstr(status));
7769 correct = False;
7772 printf("num_eas = %d\n", (int)num_eas);
7773 for (i = 0; i < num_eas; i++) {
7774 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
7775 dump_data(0, ea_list[i].value.data,
7776 ea_list[i].value.length);
7779 if (num_eas != 0) {
7780 printf("deleting EA's failed.\n");
7781 correct = False;
7784 /* Try and delete a non existent EA. */
7785 status = cli_set_ea_path(cli, fname, "foo", "", 0);
7786 if (!NT_STATUS_IS_OK(status)) {
7787 printf("deleting non-existent EA 'foo' should succeed. %s\n",
7788 nt_errstr(status));
7789 correct = False;
7792 talloc_destroy(mem_ctx);
7793 if (!torture_close_connection(cli)) {
7794 correct = False;
7797 return correct;
7800 static bool run_dirtest1(int dummy)
7802 int i;
7803 static struct cli_state *cli;
7804 uint16_t fnum;
7805 int num_seen;
7806 bool correct = True;
7808 printf("starting directory test\n");
7810 if (!torture_open_connection(&cli, 0)) {
7811 return False;
7814 smbXcli_conn_set_sockopt(cli->conn, sockops);
7816 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
7817 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
7818 cli_rmdir(cli, "\\LISTDIR");
7819 cli_mkdir(cli, "\\LISTDIR");
7821 /* Create 1000 files and 1000 directories. */
7822 for (i=0;i<1000;i++) {
7823 fstring fname;
7824 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
7825 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
7826 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
7827 0, 0, &fnum, NULL))) {
7828 fprintf(stderr,"Failed to open %s\n", fname);
7829 return False;
7831 cli_close(cli, fnum);
7833 for (i=0;i<1000;i++) {
7834 fstring fname;
7835 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
7836 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
7837 fprintf(stderr,"Failed to open %s\n", fname);
7838 return False;
7842 /* Now ensure that doing an old list sees both files and directories. */
7843 num_seen = 0;
7844 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7845 printf("num_seen = %d\n", num_seen );
7846 /* We should see 100 files + 1000 directories + . and .. */
7847 if (num_seen != 2002)
7848 correct = False;
7850 /* Ensure if we have the "must have" bits we only see the
7851 * relevent entries.
7853 num_seen = 0;
7854 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7855 printf("num_seen = %d\n", num_seen );
7856 if (num_seen != 1002)
7857 correct = False;
7859 num_seen = 0;
7860 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7861 printf("num_seen = %d\n", num_seen );
7862 if (num_seen != 1000)
7863 correct = False;
7865 /* Delete everything. */
7866 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
7867 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
7868 cli_rmdir(cli, "\\LISTDIR");
7870 #if 0
7871 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
7872 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
7873 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
7874 #endif
7876 if (!torture_close_connection(cli)) {
7877 correct = False;
7880 printf("finished dirtest1\n");
7882 return correct;
7885 static bool run_error_map_extract(int dummy) {
7887 static struct cli_state *c_dos;
7888 static struct cli_state *c_nt;
7889 NTSTATUS status;
7891 uint32_t error;
7893 uint32_t errnum;
7894 uint8_t errclass;
7896 NTSTATUS nt_status;
7898 fstring user;
7900 /* NT-Error connection */
7902 disable_spnego = true;
7903 if (!(c_nt = open_nbt_connection())) {
7904 disable_spnego = false;
7905 return False;
7907 disable_spnego = false;
7909 status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
7910 PROTOCOL_NT1);
7912 if (!NT_STATUS_IS_OK(status)) {
7913 printf("%s rejected the NT-error negprot (%s)\n", host,
7914 nt_errstr(status));
7915 cli_shutdown(c_nt);
7916 return False;
7919 status = cli_session_setup_anon(c_nt);
7920 if (!NT_STATUS_IS_OK(status)) {
7921 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
7922 return False;
7925 /* DOS-Error connection */
7927 disable_spnego = true;
7928 force_dos_errors = true;
7929 if (!(c_dos = open_nbt_connection())) {
7930 disable_spnego = false;
7931 force_dos_errors = false;
7932 return False;
7934 disable_spnego = false;
7935 force_dos_errors = false;
7937 status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
7938 PROTOCOL_NT1);
7939 if (!NT_STATUS_IS_OK(status)) {
7940 printf("%s rejected the DOS-error negprot (%s)\n", host,
7941 nt_errstr(status));
7942 cli_shutdown(c_dos);
7943 return False;
7946 status = cli_session_setup_anon(c_dos);
7947 if (!NT_STATUS_IS_OK(status)) {
7948 printf("%s rejected the DOS-error initial session setup (%s)\n",
7949 host, nt_errstr(status));
7950 return False;
7953 c_nt->map_dos_errors = false;
7954 c_dos->map_dos_errors = false;
7956 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
7957 struct cli_credentials *user_creds = NULL;
7959 fstr_sprintf(user, "%X", error);
7961 user_creds = cli_session_creds_init(talloc_tos(),
7962 user,
7963 workgroup,
7964 NULL, /* realm */
7965 password,
7966 false, /* use_kerberos */
7967 false, /* fallback_after_kerberos */
7968 false, /* use_ccache */
7969 false); /* password_is_nt_hash */
7970 if (user_creds == NULL) {
7971 printf("cli_session_creds_init(%s) failed\n", user);
7972 return false;
7975 status = cli_session_setup_creds(c_nt, user_creds);
7976 if (NT_STATUS_IS_OK(status)) {
7977 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
7980 /* Case #1: 32-bit NT errors */
7981 if (!NT_STATUS_IS_DOS(status)) {
7982 nt_status = status;
7983 } else {
7984 printf("/** Dos error on NT connection! (%s) */\n",
7985 nt_errstr(status));
7986 nt_status = NT_STATUS(0xc0000000);
7989 status = cli_session_setup_creds(c_dos, user_creds);
7990 if (NT_STATUS_IS_OK(status)) {
7991 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
7994 /* Case #1: 32-bit NT errors */
7995 if (NT_STATUS_IS_DOS(status)) {
7996 printf("/** NT error on DOS connection! (%s) */\n",
7997 nt_errstr(status));
7998 errnum = errclass = 0;
7999 } else {
8000 errclass = NT_STATUS_DOS_CLASS(status);
8001 errnum = NT_STATUS_DOS_CODE(status);
8004 if (NT_STATUS_V(nt_status) != error) {
8005 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
8006 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
8007 get_nt_error_c_code(talloc_tos(), nt_status));
8010 printf("\t{%s,\t%s,\t%s},\n",
8011 smb_dos_err_class(errclass),
8012 smb_dos_err_name(errclass, errnum),
8013 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
8015 TALLOC_FREE(user_creds);
8017 return True;
8020 static bool run_sesssetup_bench(int dummy)
8022 static struct cli_state *c;
8023 const char *fname = "\\file.dat";
8024 uint16_t fnum;
8025 NTSTATUS status;
8026 int i;
8028 if (!torture_open_connection(&c, 0)) {
8029 return false;
8032 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8033 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8034 FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
8035 if (!NT_STATUS_IS_OK(status)) {
8036 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8037 return false;
8040 for (i=0; i<torture_numops; i++) {
8041 status = cli_session_setup_creds(c, torture_creds);
8042 if (!NT_STATUS_IS_OK(status)) {
8043 d_printf("(%s) cli_session_setup_creds failed: %s\n",
8044 __location__, nt_errstr(status));
8045 return false;
8048 d_printf("\r%d ", (int)cli_state_get_uid(c));
8050 status = cli_ulogoff(c);
8051 if (!NT_STATUS_IS_OK(status)) {
8052 d_printf("(%s) cli_ulogoff failed: %s\n",
8053 __location__, nt_errstr(status));
8054 return false;
8058 return true;
8061 static bool subst_test(const char *str, const char *user, const char *domain,
8062 uid_t uid, gid_t gid, const char *expected)
8064 char *subst;
8065 bool result = true;
8067 subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
8069 if (strcmp(subst, expected) != 0) {
8070 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
8071 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
8072 expected);
8073 result = false;
8076 TALLOC_FREE(subst);
8077 return result;
8080 static void chain1_open_completion(struct tevent_req *req)
8082 uint16_t fnum;
8083 NTSTATUS status;
8084 status = cli_openx_recv(req, &fnum);
8085 TALLOC_FREE(req);
8087 d_printf("cli_openx_recv returned %s: %d\n",
8088 nt_errstr(status),
8089 NT_STATUS_IS_OK(status) ? fnum : -1);
8092 static void chain1_write_completion(struct tevent_req *req)
8094 size_t written;
8095 NTSTATUS status;
8096 status = cli_write_andx_recv(req, &written);
8097 TALLOC_FREE(req);
8099 d_printf("cli_write_andx_recv returned %s: %d\n",
8100 nt_errstr(status),
8101 NT_STATUS_IS_OK(status) ? (int)written : -1);
8104 static void chain1_close_completion(struct tevent_req *req)
8106 NTSTATUS status;
8107 bool *done = (bool *)tevent_req_callback_data_void(req);
8109 status = cli_close_recv(req);
8110 *done = true;
8112 TALLOC_FREE(req);
8114 d_printf("cli_close returned %s\n", nt_errstr(status));
8117 static bool run_chain1(int dummy)
8119 struct cli_state *cli1;
8120 struct tevent_context *evt = samba_tevent_context_init(NULL);
8121 struct tevent_req *reqs[3], *smbreqs[3];
8122 bool done = false;
8123 const char *str = "foobar";
8124 const char *fname = "\\test_chain";
8125 NTSTATUS status;
8127 printf("starting chain1 test\n");
8128 if (!torture_open_connection(&cli1, 0)) {
8129 return False;
8132 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8134 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8136 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
8137 O_CREAT|O_RDWR, 0, &smbreqs[0]);
8138 if (reqs[0] == NULL) return false;
8139 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
8142 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
8143 (const uint8_t *)str, 0, strlen(str)+1,
8144 smbreqs, 1, &smbreqs[1]);
8145 if (reqs[1] == NULL) return false;
8146 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
8148 reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
8149 if (reqs[2] == NULL) return false;
8150 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
8152 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
8153 if (!NT_STATUS_IS_OK(status)) {
8154 return false;
8157 while (!done) {
8158 tevent_loop_once(evt);
8161 torture_close_connection(cli1);
8162 return True;
8165 static void chain2_sesssetup_completion(struct tevent_req *req)
8167 NTSTATUS status;
8168 status = cli_session_setup_guest_recv(req);
8169 d_printf("sesssetup returned %s\n", nt_errstr(status));
8172 static void chain2_tcon_completion(struct tevent_req *req)
8174 bool *done = (bool *)tevent_req_callback_data_void(req);
8175 NTSTATUS status;
8176 status = cli_tcon_andx_recv(req);
8177 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
8178 *done = true;
8181 static bool run_chain2(int dummy)
8183 struct cli_state *cli1;
8184 struct tevent_context *evt = samba_tevent_context_init(NULL);
8185 struct tevent_req *reqs[2], *smbreqs[2];
8186 bool done = false;
8187 NTSTATUS status;
8188 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
8190 printf("starting chain2 test\n");
8191 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
8192 port_to_use, SMB_SIGNING_DEFAULT, flags);
8193 if (!NT_STATUS_IS_OK(status)) {
8194 return False;
8197 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8199 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
8200 &smbreqs[0]);
8201 if (reqs[0] == NULL) return false;
8202 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
8204 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
8205 "?????", NULL, 0, &smbreqs[1]);
8206 if (reqs[1] == NULL) return false;
8207 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
8209 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
8210 if (!NT_STATUS_IS_OK(status)) {
8211 return false;
8214 while (!done) {
8215 tevent_loop_once(evt);
8218 torture_close_connection(cli1);
8219 return True;
8223 struct torture_createdel_state {
8224 struct tevent_context *ev;
8225 struct cli_state *cli;
8228 static void torture_createdel_created(struct tevent_req *subreq);
8229 static void torture_createdel_closed(struct tevent_req *subreq);
8231 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
8232 struct tevent_context *ev,
8233 struct cli_state *cli,
8234 const char *name)
8236 struct tevent_req *req, *subreq;
8237 struct torture_createdel_state *state;
8239 req = tevent_req_create(mem_ctx, &state,
8240 struct torture_createdel_state);
8241 if (req == NULL) {
8242 return NULL;
8244 state->ev = ev;
8245 state->cli = cli;
8247 subreq = cli_ntcreate_send(
8248 state, ev, cli, name, 0,
8249 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
8250 FILE_ATTRIBUTE_NORMAL,
8251 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8252 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
8254 if (tevent_req_nomem(subreq, req)) {
8255 return tevent_req_post(req, ev);
8257 tevent_req_set_callback(subreq, torture_createdel_created, req);
8258 return req;
8261 static void torture_createdel_created(struct tevent_req *subreq)
8263 struct tevent_req *req = tevent_req_callback_data(
8264 subreq, struct tevent_req);
8265 struct torture_createdel_state *state = tevent_req_data(
8266 req, struct torture_createdel_state);
8267 NTSTATUS status;
8268 uint16_t fnum;
8270 status = cli_ntcreate_recv(subreq, &fnum, NULL);
8271 TALLOC_FREE(subreq);
8272 if (tevent_req_nterror(req, status)) {
8273 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
8274 nt_errstr(status)));
8275 return;
8278 subreq = cli_close_send(state, state->ev, state->cli, fnum);
8279 if (tevent_req_nomem(subreq, req)) {
8280 return;
8282 tevent_req_set_callback(subreq, torture_createdel_closed, req);
8285 static void torture_createdel_closed(struct tevent_req *subreq)
8287 struct tevent_req *req = tevent_req_callback_data(
8288 subreq, struct tevent_req);
8289 NTSTATUS status;
8291 status = cli_close_recv(subreq);
8292 if (tevent_req_nterror(req, status)) {
8293 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
8294 return;
8296 tevent_req_done(req);
8299 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
8301 return tevent_req_simple_recv_ntstatus(req);
8304 struct torture_createdels_state {
8305 struct tevent_context *ev;
8306 struct cli_state *cli;
8307 const char *base_name;
8308 int sent;
8309 int received;
8310 int num_files;
8311 struct tevent_req **reqs;
8314 static void torture_createdels_done(struct tevent_req *subreq);
8316 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
8317 struct tevent_context *ev,
8318 struct cli_state *cli,
8319 const char *base_name,
8320 int num_parallel,
8321 int num_files)
8323 struct tevent_req *req;
8324 struct torture_createdels_state *state;
8325 int i;
8327 req = tevent_req_create(mem_ctx, &state,
8328 struct torture_createdels_state);
8329 if (req == NULL) {
8330 return NULL;
8332 state->ev = ev;
8333 state->cli = cli;
8334 state->base_name = talloc_strdup(state, base_name);
8335 if (tevent_req_nomem(state->base_name, req)) {
8336 return tevent_req_post(req, ev);
8338 state->num_files = MAX(num_parallel, num_files);
8339 state->sent = 0;
8340 state->received = 0;
8342 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
8343 if (tevent_req_nomem(state->reqs, req)) {
8344 return tevent_req_post(req, ev);
8347 for (i=0; i<num_parallel; i++) {
8348 char *name;
8350 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
8351 state->sent);
8352 if (tevent_req_nomem(name, req)) {
8353 return tevent_req_post(req, ev);
8355 state->reqs[i] = torture_createdel_send(
8356 state->reqs, state->ev, state->cli, name);
8357 if (tevent_req_nomem(state->reqs[i], req)) {
8358 return tevent_req_post(req, ev);
8360 name = talloc_move(state->reqs[i], &name);
8361 tevent_req_set_callback(state->reqs[i],
8362 torture_createdels_done, req);
8363 state->sent += 1;
8365 return req;
8368 static void torture_createdels_done(struct tevent_req *subreq)
8370 struct tevent_req *req = tevent_req_callback_data(
8371 subreq, struct tevent_req);
8372 struct torture_createdels_state *state = tevent_req_data(
8373 req, struct torture_createdels_state);
8374 size_t num_parallel = talloc_array_length(state->reqs);
8375 NTSTATUS status;
8376 char *name;
8377 int i;
8379 status = torture_createdel_recv(subreq);
8380 if (!NT_STATUS_IS_OK(status)){
8381 DEBUG(10, ("torture_createdel_recv returned %s\n",
8382 nt_errstr(status)));
8383 TALLOC_FREE(subreq);
8384 tevent_req_nterror(req, status);
8385 return;
8388 for (i=0; i<num_parallel; i++) {
8389 if (subreq == state->reqs[i]) {
8390 break;
8393 if (i == num_parallel) {
8394 DEBUG(10, ("received something we did not send\n"));
8395 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
8396 return;
8398 TALLOC_FREE(state->reqs[i]);
8400 if (state->sent >= state->num_files) {
8401 tevent_req_done(req);
8402 return;
8405 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
8406 state->sent);
8407 if (tevent_req_nomem(name, req)) {
8408 return;
8410 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
8411 state->cli, name);
8412 if (tevent_req_nomem(state->reqs[i], req)) {
8413 return;
8415 name = talloc_move(state->reqs[i], &name);
8416 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
8417 state->sent += 1;
8420 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
8422 return tevent_req_simple_recv_ntstatus(req);
8425 struct swallow_notify_state {
8426 struct tevent_context *ev;
8427 struct cli_state *cli;
8428 uint16_t fnum;
8429 uint32_t completion_filter;
8430 bool recursive;
8431 bool (*fn)(uint32_t action, const char *name, void *priv);
8432 void *priv;
8435 static void swallow_notify_done(struct tevent_req *subreq);
8437 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
8438 struct tevent_context *ev,
8439 struct cli_state *cli,
8440 uint16_t fnum,
8441 uint32_t completion_filter,
8442 bool recursive,
8443 bool (*fn)(uint32_t action,
8444 const char *name,
8445 void *priv),
8446 void *priv)
8448 struct tevent_req *req, *subreq;
8449 struct swallow_notify_state *state;
8451 req = tevent_req_create(mem_ctx, &state,
8452 struct swallow_notify_state);
8453 if (req == NULL) {
8454 return NULL;
8456 state->ev = ev;
8457 state->cli = cli;
8458 state->fnum = fnum;
8459 state->completion_filter = completion_filter;
8460 state->recursive = recursive;
8461 state->fn = fn;
8462 state->priv = priv;
8464 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
8465 0xffff, state->completion_filter,
8466 state->recursive);
8467 if (tevent_req_nomem(subreq, req)) {
8468 return tevent_req_post(req, ev);
8470 tevent_req_set_callback(subreq, swallow_notify_done, req);
8471 return req;
8474 static void swallow_notify_done(struct tevent_req *subreq)
8476 struct tevent_req *req = tevent_req_callback_data(
8477 subreq, struct tevent_req);
8478 struct swallow_notify_state *state = tevent_req_data(
8479 req, struct swallow_notify_state);
8480 NTSTATUS status;
8481 uint32_t i, num_changes;
8482 struct notify_change *changes;
8484 status = cli_notify_recv(subreq, state, &num_changes, &changes);
8485 TALLOC_FREE(subreq);
8486 if (!NT_STATUS_IS_OK(status)) {
8487 DEBUG(10, ("cli_notify_recv returned %s\n",
8488 nt_errstr(status)));
8489 tevent_req_nterror(req, status);
8490 return;
8493 for (i=0; i<num_changes; i++) {
8494 state->fn(changes[i].action, changes[i].name, state->priv);
8496 TALLOC_FREE(changes);
8498 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
8499 0xffff, state->completion_filter,
8500 state->recursive);
8501 if (tevent_req_nomem(subreq, req)) {
8502 return;
8504 tevent_req_set_callback(subreq, swallow_notify_done, req);
8507 static bool print_notifies(uint32_t action, const char *name, void *priv)
8509 if (DEBUGLEVEL > 5) {
8510 d_printf("%d %s\n", (int)action, name);
8512 return true;
8515 static void notify_bench_done(struct tevent_req *req)
8517 int *num_finished = (int *)tevent_req_callback_data_void(req);
8518 *num_finished += 1;
8521 static bool run_notify_bench(int dummy)
8523 const char *dname = "\\notify-bench";
8524 struct tevent_context *ev;
8525 NTSTATUS status;
8526 uint16_t dnum;
8527 struct tevent_req *req1;
8528 struct tevent_req *req2 = NULL;
8529 int i, num_unc_names;
8530 int num_finished = 0;
8532 printf("starting notify-bench test\n");
8534 if (use_multishare_conn) {
8535 char **unc_list;
8536 unc_list = file_lines_load(multishare_conn_fname,
8537 &num_unc_names, 0, NULL);
8538 if (!unc_list || num_unc_names <= 0) {
8539 d_printf("Failed to load unc names list from '%s'\n",
8540 multishare_conn_fname);
8541 return false;
8543 TALLOC_FREE(unc_list);
8544 } else {
8545 num_unc_names = 1;
8548 ev = samba_tevent_context_init(talloc_tos());
8549 if (ev == NULL) {
8550 d_printf("tevent_context_init failed\n");
8551 return false;
8554 for (i=0; i<num_unc_names; i++) {
8555 struct cli_state *cli;
8556 char *base_fname;
8558 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
8559 dname, i);
8560 if (base_fname == NULL) {
8561 return false;
8564 if (!torture_open_connection(&cli, i)) {
8565 return false;
8568 status = cli_ntcreate(cli, dname, 0,
8569 MAXIMUM_ALLOWED_ACCESS,
8570 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
8571 FILE_SHARE_DELETE,
8572 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
8573 &dnum, NULL);
8575 if (!NT_STATUS_IS_OK(status)) {
8576 d_printf("Could not create %s: %s\n", dname,
8577 nt_errstr(status));
8578 return false;
8581 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
8582 FILE_NOTIFY_CHANGE_FILE_NAME |
8583 FILE_NOTIFY_CHANGE_DIR_NAME |
8584 FILE_NOTIFY_CHANGE_ATTRIBUTES |
8585 FILE_NOTIFY_CHANGE_LAST_WRITE,
8586 false, print_notifies, NULL);
8587 if (req1 == NULL) {
8588 d_printf("Could not create notify request\n");
8589 return false;
8592 req2 = torture_createdels_send(talloc_tos(), ev, cli,
8593 base_fname, 10, torture_numops);
8594 if (req2 == NULL) {
8595 d_printf("Could not create createdels request\n");
8596 return false;
8598 TALLOC_FREE(base_fname);
8600 tevent_req_set_callback(req2, notify_bench_done,
8601 &num_finished);
8604 while (num_finished < num_unc_names) {
8605 int ret;
8606 ret = tevent_loop_once(ev);
8607 if (ret != 0) {
8608 d_printf("tevent_loop_once failed\n");
8609 return false;
8613 if (!tevent_req_poll(req2, ev)) {
8614 d_printf("tevent_req_poll failed\n");
8617 status = torture_createdels_recv(req2);
8618 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
8620 return true;
8623 static bool run_mangle1(int dummy)
8625 struct cli_state *cli;
8626 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
8627 uint16_t fnum;
8628 fstring alt_name;
8629 NTSTATUS status;
8630 time_t change_time, access_time, write_time;
8631 off_t size;
8632 uint16_t mode;
8634 printf("starting mangle1 test\n");
8635 if (!torture_open_connection(&cli, 0)) {
8636 return False;
8639 smbXcli_conn_set_sockopt(cli->conn, sockops);
8641 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8642 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8643 0, 0, &fnum, NULL);
8644 if (!NT_STATUS_IS_OK(status)) {
8645 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8646 return false;
8648 cli_close(cli, fnum);
8650 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
8651 if (!NT_STATUS_IS_OK(status)) {
8652 d_printf("cli_qpathinfo_alt_name failed: %s\n",
8653 nt_errstr(status));
8654 return false;
8656 d_printf("alt_name: %s\n", alt_name);
8658 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
8659 if (!NT_STATUS_IS_OK(status)) {
8660 d_printf("cli_openx(%s) failed: %s\n", alt_name,
8661 nt_errstr(status));
8662 return false;
8664 cli_close(cli, fnum);
8666 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
8667 &write_time, &size, &mode);
8668 if (!NT_STATUS_IS_OK(status)) {
8669 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
8670 nt_errstr(status));
8671 return false;
8674 return true;
8677 static NTSTATUS mangle_illegal_list_shortname_fn(const char *mntpoint,
8678 struct file_info *f,
8679 const char *mask,
8680 void *state)
8682 if (f->short_name == NULL) {
8683 return NT_STATUS_OK;
8686 if (strlen(f->short_name) == 0) {
8687 return NT_STATUS_OK;
8690 printf("unexpected shortname: %s\n", f->short_name);
8692 return NT_STATUS_OBJECT_NAME_INVALID;
8695 static NTSTATUS mangle_illegal_list_name_fn(const char *mntpoint,
8696 struct file_info *f,
8697 const char *mask,
8698 void *state)
8700 char *name = state;
8702 printf("name: %s\n", f->name);
8703 fstrcpy(name, f->name);
8704 return NT_STATUS_OK;
8707 static bool run_mangle_illegal(int dummy)
8709 struct cli_state *cli = NULL;
8710 struct cli_state *cli_posix = NULL;
8711 const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
8712 const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
8713 char *mangled_path = NULL;
8714 uint16_t fnum;
8715 fstring name;
8716 fstring alt_name;
8717 NTSTATUS status;
8719 printf("starting mangle-illegal test\n");
8721 if (!torture_open_connection(&cli, 0)) {
8722 return False;
8725 smbXcli_conn_set_sockopt(cli->conn, sockops);
8727 if (!torture_open_connection(&cli_posix, 0)) {
8728 return false;
8731 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
8733 status = torture_setup_unix_extensions(cli_posix);
8734 if (!NT_STATUS_IS_OK(status)) {
8735 return false;
8738 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
8739 status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
8740 if (!NT_STATUS_IS_OK(status)) {
8741 printf("mkdir1 failed : %s\n", nt_errstr(status));
8742 return False;
8746 * Create a file with illegal NTFS characters and test that we
8747 * get a usable mangled name
8750 cli_setatr(cli_posix, illegal_fname, 0, 0);
8751 cli_posix_unlink(cli_posix, illegal_fname);
8753 status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
8754 0600, &fnum);
8755 if (!NT_STATUS_IS_OK(status)) {
8756 printf("POSIX create of %s failed (%s)\n",
8757 illegal_fname, nt_errstr(status));
8758 return false;
8761 status = cli_close(cli_posix, fnum);
8762 if (!NT_STATUS_IS_OK(status)) {
8763 printf("close failed (%s)\n", nt_errstr(status));
8764 return false;
8767 status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
8768 if (!NT_STATUS_IS_OK(status)) {
8769 d_printf("cli_list failed: %s\n", nt_errstr(status));
8770 return false;
8773 mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
8774 if (mangled_path == NULL) {
8775 return false;
8778 status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
8779 if (!NT_STATUS_IS_OK(status)) {
8780 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
8781 TALLOC_FREE(mangled_path);
8782 return false;
8784 TALLOC_FREE(mangled_path);
8785 cli_close(cli, fnum);
8787 cli_setatr(cli_posix, illegal_fname, 0, 0);
8788 cli_posix_unlink(cli_posix, illegal_fname);
8791 * Create a file with a long name and check that we got *no* short name.
8794 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8795 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8796 0, 0, &fnum, NULL);
8797 if (!NT_STATUS_IS_OK(status)) {
8798 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8799 return false;
8801 cli_close(cli, fnum);
8803 status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
8804 if (!NT_STATUS_IS_OK(status)) {
8805 d_printf("cli_list failed\n");
8806 return false;
8809 cli_unlink(cli, fname, 0);
8810 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
8812 if (!torture_close_connection(cli_posix)) {
8813 return false;
8816 if (!torture_close_connection(cli)) {
8817 return false;
8820 return true;
8823 static size_t null_source(uint8_t *buf, size_t n, void *priv)
8825 size_t *to_pull = (size_t *)priv;
8826 size_t thistime = *to_pull;
8828 thistime = MIN(thistime, n);
8829 if (thistime == 0) {
8830 return 0;
8833 memset(buf, 0, thistime);
8834 *to_pull -= thistime;
8835 return thistime;
8838 static bool run_windows_write(int dummy)
8840 struct cli_state *cli1;
8841 uint16_t fnum;
8842 int i;
8843 bool ret = false;
8844 const char *fname = "\\writetest.txt";
8845 struct timeval start_time;
8846 double seconds;
8847 double kbytes;
8848 NTSTATUS status;
8850 printf("starting windows_write test\n");
8851 if (!torture_open_connection(&cli1, 0)) {
8852 return False;
8855 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
8856 if (!NT_STATUS_IS_OK(status)) {
8857 printf("open failed (%s)\n", nt_errstr(status));
8858 return False;
8861 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8863 start_time = timeval_current();
8865 for (i=0; i<torture_numops; i++) {
8866 uint8_t c = 0;
8867 off_t start = i * torture_blocksize;
8868 size_t to_pull = torture_blocksize - 1;
8870 status = cli_writeall(cli1, fnum, 0, &c,
8871 start + torture_blocksize - 1, 1, NULL);
8872 if (!NT_STATUS_IS_OK(status)) {
8873 printf("cli_write failed: %s\n", nt_errstr(status));
8874 goto fail;
8877 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
8878 null_source, &to_pull);
8879 if (!NT_STATUS_IS_OK(status)) {
8880 printf("cli_push returned: %s\n", nt_errstr(status));
8881 goto fail;
8885 seconds = timeval_elapsed(&start_time);
8886 kbytes = (double)torture_blocksize * torture_numops;
8887 kbytes /= 1024;
8889 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
8890 (double)seconds, (int)(kbytes/seconds));
8892 ret = true;
8893 fail:
8894 cli_close(cli1, fnum);
8895 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8896 torture_close_connection(cli1);
8897 return ret;
8900 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
8902 size_t max_pdu = 0x1FFFF;
8904 if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
8905 max_pdu = 0xFFFFFF;
8908 if (smb1cli_conn_signing_is_active(cli->conn)) {
8909 max_pdu = 0x1FFFF;
8912 if (smb1cli_conn_encryption_on(cli->conn)) {
8913 max_pdu = CLI_BUFFER_SIZE;
8916 if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
8917 len_requested &= 0xFFFF;
8920 return MIN(len_requested,
8921 max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
8924 static bool check_read_call(struct cli_state *cli,
8925 uint16_t fnum,
8926 uint8_t *buf,
8927 size_t len_requested)
8929 NTSTATUS status;
8930 struct tevent_req *subreq = NULL;
8931 ssize_t len_read = 0;
8932 size_t len_expected = 0;
8933 struct tevent_context *ev = NULL;
8935 ev = samba_tevent_context_init(talloc_tos());
8936 if (ev == NULL) {
8937 return false;
8940 subreq = cli_read_andx_send(talloc_tos(),
8942 cli,
8943 fnum,
8945 len_requested);
8947 if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
8948 return false;
8951 status = cli_read_andx_recv(subreq, &len_read, &buf);
8952 if (!NT_STATUS_IS_OK(status)) {
8953 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
8954 return false;
8957 TALLOC_FREE(subreq);
8958 TALLOC_FREE(ev);
8960 len_expected = calc_expected_return(cli, len_requested);
8962 if (len_expected > 0x10000 && len_read == 0x10000) {
8963 /* Windows servers only return a max of 0x10000,
8964 doesn't matter if you set CAP_LARGE_READX in
8965 the client sessionsetupX call or not. */
8966 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
8967 (unsigned int)len_requested);
8968 } else if (len_read != len_expected) {
8969 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
8970 (unsigned int)len_requested,
8971 (unsigned int)len_read,
8972 (unsigned int)len_expected);
8973 return false;
8974 } else {
8975 d_printf("Correct read reply.\n");
8978 return true;
8981 /* Test large readX variants. */
8982 static bool large_readx_tests(struct cli_state *cli,
8983 uint16_t fnum,
8984 uint8_t *buf)
8986 /* A read of 0xFFFF0001 should *always* return 1 byte. */
8987 if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
8988 return false;
8990 /* A read of 0x10000 should return 0x10000 bytes. */
8991 if (check_read_call(cli, fnum, buf, 0x10000) == false) {
8992 return false;
8994 /* A read of 0x10000 should return 0x10001 bytes. */
8995 if (check_read_call(cli, fnum, buf, 0x10001) == false) {
8996 return false;
8998 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
8999 the requested number of bytes. */
9000 if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
9001 return false;
9003 /* A read of 1MB should return 1MB bytes (on Samba). */
9004 if (check_read_call(cli, fnum, buf, 0x100000) == false) {
9005 return false;
9008 if (check_read_call(cli, fnum, buf, 0x20001) == false) {
9009 return false;
9011 if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
9012 return false;
9014 if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
9015 return false;
9017 return true;
9020 static bool run_large_readx(int dummy)
9022 uint8_t *buf = NULL;
9023 struct cli_state *cli1 = NULL;
9024 struct cli_state *cli2 = NULL;
9025 bool correct = false;
9026 const char *fname = "\\large_readx.dat";
9027 NTSTATUS status;
9028 uint16_t fnum1 = UINT16_MAX;
9029 uint32_t normal_caps = 0;
9030 size_t file_size = 20*1024*1024;
9031 TALLOC_CTX *frame = talloc_stackframe();
9032 size_t i;
9033 struct {
9034 const char *name;
9035 enum smb_signing_setting signing_setting;
9036 enum protocol_types protocol;
9037 } runs[] = {
9039 .name = "NT1",
9040 .signing_setting = SMB_SIGNING_IF_REQUIRED,
9041 .protocol = PROTOCOL_NT1,
9043 .name = "NT1 - SIGNING_REQUIRED",
9044 .signing_setting = SMB_SIGNING_REQUIRED,
9045 .protocol = PROTOCOL_NT1,
9049 printf("starting large_readx test\n");
9051 if (!torture_open_connection(&cli1, 0)) {
9052 goto out;
9055 normal_caps = smb1cli_conn_capabilities(cli1->conn);
9057 if (!(normal_caps & CAP_LARGE_READX)) {
9058 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
9059 (unsigned int)normal_caps);
9060 goto out;
9063 /* Create a file of size 4MB. */
9064 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
9065 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
9066 0, 0, &fnum1, NULL);
9068 if (!NT_STATUS_IS_OK(status)) {
9069 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
9070 goto out;
9073 /* Write file_size bytes. */
9074 buf = talloc_zero_array(frame, uint8_t, file_size);
9075 if (buf == NULL) {
9076 goto out;
9079 status = cli_writeall(cli1,
9080 fnum1,
9082 buf,
9084 file_size,
9085 NULL);
9086 if (!NT_STATUS_IS_OK(status)) {
9087 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
9088 goto out;
9091 status = cli_close(cli1, fnum1);
9092 if (!NT_STATUS_IS_OK(status)) {
9093 d_printf("cli_close failed: %s\n", nt_errstr(status));
9094 goto out;
9097 fnum1 = UINT16_MAX;
9099 for (i=0; i < ARRAY_SIZE(runs); i++) {
9100 enum smb_signing_setting saved_signing_setting = signing_state;
9101 uint16_t fnum2 = -1;
9103 if (do_encrypt &&
9104 (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
9106 d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
9107 continue;
9110 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
9112 signing_state = runs[i].signing_setting;
9113 cli2 = open_nbt_connection();
9114 signing_state = saved_signing_setting;
9115 if (cli2 == NULL) {
9116 goto out;
9119 status = smbXcli_negprot(cli2->conn,
9120 cli2->timeout,
9121 runs[i].protocol,
9122 runs[i].protocol);
9123 if (!NT_STATUS_IS_OK(status)) {
9124 goto out;
9127 status = cli_session_setup_creds(cli2, torture_creds);
9128 if (!NT_STATUS_IS_OK(status)) {
9129 goto out;
9132 status = cli_tree_connect(cli2,
9133 share,
9134 "?????",
9135 password);
9136 if (!NT_STATUS_IS_OK(status)) {
9137 goto out;
9140 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
9142 normal_caps = smb1cli_conn_capabilities(cli2->conn);
9144 if (!(normal_caps & CAP_LARGE_READX)) {
9145 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
9146 (unsigned int)normal_caps);
9147 goto out;
9150 if (do_encrypt) {
9151 if (force_cli_encryption(cli2, share) == false) {
9152 goto out;
9154 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
9155 uint16_t major, minor;
9156 uint32_t caplow, caphigh;
9158 status = cli_unix_extensions_version(cli2,
9159 &major, &minor,
9160 &caplow, &caphigh);
9161 if (!NT_STATUS_IS_OK(status)) {
9162 goto out;
9166 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
9167 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
9168 0, 0, &fnum2, NULL);
9169 if (!NT_STATUS_IS_OK(status)) {
9170 d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
9171 goto out;
9174 /* All reads must return less than file_size bytes. */
9175 if (!large_readx_tests(cli2, fnum2, buf)) {
9176 goto out;
9179 status = cli_close(cli2, fnum2);
9180 if (!NT_STATUS_IS_OK(status)) {
9181 d_printf("cli_close failed: %s\n", nt_errstr(status));
9182 goto out;
9184 fnum2 = -1;
9186 if (!torture_close_connection(cli2)) {
9187 goto out;
9189 cli2 = NULL;
9192 correct = true;
9193 printf("Success on large_readx test\n");
9195 out:
9197 if (cli2) {
9198 if (!torture_close_connection(cli2)) {
9199 correct = false;
9203 if (cli1) {
9204 if (fnum1 != UINT16_MAX) {
9205 status = cli_close(cli1, fnum1);
9206 if (!NT_STATUS_IS_OK(status)) {
9207 d_printf("cli_close failed: %s\n", nt_errstr(status));
9209 fnum1 = UINT16_MAX;
9212 status = cli_unlink(cli1, fname,
9213 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9214 if (!NT_STATUS_IS_OK(status)) {
9215 printf("unlink failed (%s)\n", nt_errstr(status));
9218 if (!torture_close_connection(cli1)) {
9219 correct = false;
9223 TALLOC_FREE(frame);
9225 printf("finished large_readx test\n");
9226 return correct;
9229 static bool run_cli_echo(int dummy)
9231 struct cli_state *cli;
9232 NTSTATUS status;
9234 printf("starting cli_echo test\n");
9235 if (!torture_open_connection(&cli, 0)) {
9236 return false;
9238 smbXcli_conn_set_sockopt(cli->conn, sockops);
9240 status = cli_echo(cli, 5, data_blob_const("hello", 5));
9242 d_printf("cli_echo returned %s\n", nt_errstr(status));
9244 torture_close_connection(cli);
9245 return NT_STATUS_IS_OK(status);
9248 static int splice_status(off_t written, void *priv)
9250 return true;
9253 static bool run_cli_splice(int dummy)
9255 uint8_t *buf = NULL;
9256 struct cli_state *cli1 = NULL;
9257 bool correct = false;
9258 const char *fname_src = "\\splice_src.dat";
9259 const char *fname_dst = "\\splice_dst.dat";
9260 NTSTATUS status;
9261 uint16_t fnum1 = UINT16_MAX;
9262 uint16_t fnum2 = UINT16_MAX;
9263 size_t file_size = 2*1024*1024;
9264 size_t splice_size = 1*1024*1024 + 713;
9265 MD5_CTX md5_ctx;
9266 uint8_t digest1[16], digest2[16];
9267 off_t written = 0;
9268 size_t nread = 0;
9269 TALLOC_CTX *frame = talloc_stackframe();
9271 printf("starting cli_splice test\n");
9273 if (!torture_open_connection(&cli1, 0)) {
9274 goto out;
9277 cli_unlink(cli1, fname_src,
9278 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9279 cli_unlink(cli1, fname_dst,
9280 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9282 /* Create a file */
9283 status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
9284 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
9285 0, 0, &fnum1, NULL);
9287 if (!NT_STATUS_IS_OK(status)) {
9288 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
9289 goto out;
9292 /* Write file_size bytes - must be bigger than splice_size. */
9293 buf = talloc_zero_array(frame, uint8_t, file_size);
9294 if (buf == NULL) {
9295 d_printf("talloc_fail\n");
9296 goto out;
9299 /* Fill it with random numbers. */
9300 generate_random_buffer(buf, file_size);
9302 /* MD5 the first 1MB + 713 bytes. */
9303 MD5Init(&md5_ctx);
9304 MD5Update(&md5_ctx, buf, splice_size);
9305 MD5Final(digest1, &md5_ctx);
9307 status = cli_writeall(cli1,
9308 fnum1,
9310 buf,
9312 file_size,
9313 NULL);
9314 if (!NT_STATUS_IS_OK(status)) {
9315 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
9316 goto out;
9319 status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
9320 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
9321 0, 0, &fnum2, NULL);
9323 if (!NT_STATUS_IS_OK(status)) {
9324 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
9325 goto out;
9328 /* Now splice 1MB + 713 bytes. */
9329 status = cli_splice(cli1,
9330 cli1,
9331 fnum1,
9332 fnum2,
9333 splice_size,
9336 &written,
9337 splice_status,
9338 NULL);
9340 if (!NT_STATUS_IS_OK(status)) {
9341 d_printf("cli_splice failed: %s\n", nt_errstr(status));
9342 goto out;
9345 /* Clear the old buffer. */
9346 memset(buf, '\0', file_size);
9348 /* Read the new file. */
9349 status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
9350 if (!NT_STATUS_IS_OK(status)) {
9351 d_printf("cli_read failed: %s\n", nt_errstr(status));
9352 goto out;
9354 if (nread != splice_size) {
9355 d_printf("bad read of 0x%x, should be 0x%x\n",
9356 (unsigned int)nread,
9357 (unsigned int)splice_size);
9358 goto out;
9361 /* MD5 the first 1MB + 713 bytes. */
9362 MD5Init(&md5_ctx);
9363 MD5Update(&md5_ctx, buf, splice_size);
9364 MD5Final(digest2, &md5_ctx);
9366 /* Must be the same. */
9367 if (memcmp(digest1, digest2, 16) != 0) {
9368 d_printf("bad MD5 compare\n");
9369 goto out;
9372 correct = true;
9373 printf("Success on cli_splice test\n");
9375 out:
9377 if (cli1) {
9378 if (fnum1 != UINT16_MAX) {
9379 cli_close(cli1, fnum1);
9381 if (fnum2 != UINT16_MAX) {
9382 cli_close(cli1, fnum2);
9385 cli_unlink(cli1, fname_src,
9386 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9387 cli_unlink(cli1, fname_dst,
9388 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9390 if (!torture_close_connection(cli1)) {
9391 correct = false;
9395 TALLOC_FREE(frame);
9396 return correct;
9399 static bool run_uid_regression_test(int dummy)
9401 static struct cli_state *cli;
9402 int16_t old_vuid;
9403 int32_t old_cnum;
9404 bool correct = True;
9405 struct smbXcli_tcon *orig_tcon = NULL;
9406 NTSTATUS status;
9408 printf("starting uid regression test\n");
9410 if (!torture_open_connection(&cli, 0)) {
9411 return False;
9414 smbXcli_conn_set_sockopt(cli->conn, sockops);
9416 /* Ok - now save then logoff our current user. */
9417 old_vuid = cli_state_get_uid(cli);
9419 status = cli_ulogoff(cli);
9420 if (!NT_STATUS_IS_OK(status)) {
9421 d_printf("(%s) cli_ulogoff failed: %s\n",
9422 __location__, nt_errstr(status));
9423 correct = false;
9424 goto out;
9427 cli_state_set_uid(cli, old_vuid);
9429 /* Try an operation. */
9430 status = cli_mkdir(cli, "\\uid_reg_test");
9431 if (NT_STATUS_IS_OK(status)) {
9432 d_printf("(%s) cli_mkdir succeeded\n",
9433 __location__);
9434 correct = false;
9435 goto out;
9436 } else {
9437 /* Should be bad uid. */
9438 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
9439 NT_STATUS_USER_SESSION_DELETED)) {
9440 correct = false;
9441 goto out;
9445 old_cnum = cli_state_get_tid(cli);
9446 orig_tcon = cli_state_save_tcon(cli);
9447 if (orig_tcon == NULL) {
9448 correct = false;
9449 goto out;
9452 /* Now try a SMBtdis with the invald vuid set to zero. */
9453 cli_state_set_uid(cli, 0);
9455 /* This should succeed. */
9456 status = cli_tdis(cli);
9458 if (NT_STATUS_IS_OK(status)) {
9459 d_printf("First tdis with invalid vuid should succeed.\n");
9460 } else {
9461 d_printf("First tdis failed (%s)\n", nt_errstr(status));
9462 correct = false;
9463 cli_state_restore_tcon(cli, orig_tcon);
9464 goto out;
9467 cli_state_restore_tcon(cli, orig_tcon);
9468 cli_state_set_uid(cli, old_vuid);
9469 cli_state_set_tid(cli, old_cnum);
9471 /* This should fail. */
9472 status = cli_tdis(cli);
9473 if (NT_STATUS_IS_OK(status)) {
9474 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
9475 correct = false;
9476 goto out;
9477 } else {
9478 /* Should be bad tid. */
9479 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
9480 NT_STATUS_NETWORK_NAME_DELETED)) {
9481 correct = false;
9482 goto out;
9486 cli_rmdir(cli, "\\uid_reg_test");
9488 out:
9490 cli_shutdown(cli);
9491 return correct;
9495 static const char *illegal_chars = "*\\/?<>|\":";
9496 static char force_shortname_chars[] = " +,.[];=\177";
9498 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
9499 const char *mask, void *state)
9501 struct cli_state *pcli = (struct cli_state *)state;
9502 fstring fname;
9503 NTSTATUS status = NT_STATUS_OK;
9505 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
9507 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9508 return NT_STATUS_OK;
9510 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
9511 status = cli_rmdir(pcli, fname);
9512 if (!NT_STATUS_IS_OK(status)) {
9513 printf("del_fn: failed to rmdir %s\n,", fname );
9515 } else {
9516 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9517 if (!NT_STATUS_IS_OK(status)) {
9518 printf("del_fn: failed to unlink %s\n,", fname );
9521 return status;
9524 struct sn_state {
9525 int matched;
9526 int i;
9527 bool val;
9530 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
9531 const char *name, void *state)
9533 struct sn_state *s = (struct sn_state *)state;
9534 int i = s->i;
9536 #if 0
9537 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
9538 i, finfo->name, finfo->short_name);
9539 #endif
9541 if (strchr(force_shortname_chars, i)) {
9542 if (!finfo->short_name) {
9543 /* Shortname not created when it should be. */
9544 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
9545 __location__, finfo->name, i);
9546 s->val = true;
9548 } else if (finfo->short_name){
9549 /* Shortname created when it should not be. */
9550 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
9551 __location__, finfo->short_name, finfo->name);
9552 s->val = true;
9554 s->matched += 1;
9555 return NT_STATUS_OK;
9558 static bool run_shortname_test(int dummy)
9560 static struct cli_state *cli;
9561 bool correct = True;
9562 int i;
9563 struct sn_state s;
9564 char fname[40];
9565 NTSTATUS status;
9567 printf("starting shortname test\n");
9569 if (!torture_open_connection(&cli, 0)) {
9570 return False;
9573 smbXcli_conn_set_sockopt(cli->conn, sockops);
9575 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
9576 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
9577 cli_rmdir(cli, "\\shortname");
9579 status = cli_mkdir(cli, "\\shortname");
9580 if (!NT_STATUS_IS_OK(status)) {
9581 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
9582 __location__, nt_errstr(status));
9583 correct = false;
9584 goto out;
9587 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
9588 correct = false;
9589 goto out;
9591 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
9592 correct = false;
9593 goto out;
9596 s.val = false;
9598 for (i = 32; i < 128; i++) {
9599 uint16_t fnum = (uint16_t)-1;
9601 s.i = i;
9603 if (strchr(illegal_chars, i)) {
9604 continue;
9606 fname[15] = i;
9608 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
9609 FILE_SHARE_READ|FILE_SHARE_WRITE,
9610 FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
9611 if (!NT_STATUS_IS_OK(status)) {
9612 d_printf("(%s) cli_nt_create of %s failed: %s\n",
9613 __location__, fname, nt_errstr(status));
9614 correct = false;
9615 goto out;
9617 cli_close(cli, fnum);
9619 s.matched = 0;
9620 status = cli_list(cli, "\\shortname\\test*.*", 0,
9621 shortname_list_fn, &s);
9622 if (s.matched != 1) {
9623 d_printf("(%s) failed to list %s: %s\n",
9624 __location__, fname, nt_errstr(status));
9625 correct = false;
9626 goto out;
9629 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9630 if (!NT_STATUS_IS_OK(status)) {
9631 d_printf("(%s) failed to delete %s: %s\n",
9632 __location__, fname, nt_errstr(status));
9633 correct = false;
9634 goto out;
9637 if (s.val) {
9638 correct = false;
9639 goto out;
9643 out:
9645 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
9646 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
9647 cli_rmdir(cli, "\\shortname");
9648 torture_close_connection(cli);
9649 return correct;
9652 static void pagedsearch_cb(struct tevent_req *req)
9654 TLDAPRC rc;
9655 struct tldap_message *msg;
9656 char *dn;
9658 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
9659 if (!TLDAP_RC_IS_SUCCESS(rc)) {
9660 d_printf("tldap_search_paged_recv failed: %s\n",
9661 tldap_rc2string(rc));
9662 return;
9664 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
9665 TALLOC_FREE(msg);
9666 return;
9668 if (!tldap_entry_dn(msg, &dn)) {
9669 d_printf("tldap_entry_dn failed\n");
9670 return;
9672 d_printf("%s\n", dn);
9673 TALLOC_FREE(msg);
9676 static bool run_tldap(int dummy)
9678 struct tldap_context *ld;
9679 int fd;
9680 TLDAPRC rc;
9681 NTSTATUS status;
9682 struct sockaddr_storage addr;
9683 struct tevent_context *ev;
9684 struct tevent_req *req;
9685 char *basedn;
9686 const char *filter;
9688 if (!resolve_name(host, &addr, 0, false)) {
9689 d_printf("could not find host %s\n", host);
9690 return false;
9692 status = open_socket_out(&addr, 389, 9999, &fd);
9693 if (!NT_STATUS_IS_OK(status)) {
9694 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
9695 return false;
9698 ld = tldap_context_create(talloc_tos(), fd);
9699 if (ld == NULL) {
9700 close(fd);
9701 d_printf("tldap_context_create failed\n");
9702 return false;
9705 rc = tldap_fetch_rootdse(ld);
9706 if (!TLDAP_RC_IS_SUCCESS(rc)) {
9707 d_printf("tldap_fetch_rootdse failed: %s\n",
9708 tldap_errstr(talloc_tos(), ld, rc));
9709 return false;
9712 basedn = tldap_talloc_single_attribute(
9713 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
9714 if (basedn == NULL) {
9715 d_printf("no defaultNamingContext\n");
9716 return false;
9718 d_printf("defaultNamingContext: %s\n", basedn);
9720 ev = samba_tevent_context_init(talloc_tos());
9721 if (ev == NULL) {
9722 d_printf("tevent_context_init failed\n");
9723 return false;
9726 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
9727 TLDAP_SCOPE_SUB, "(objectclass=*)",
9728 NULL, 0, 0,
9729 NULL, 0, NULL, 0, 0, 0, 0, 5);
9730 if (req == NULL) {
9731 d_printf("tldap_search_paged_send failed\n");
9732 return false;
9734 tevent_req_set_callback(req, pagedsearch_cb, NULL);
9736 tevent_req_poll(req, ev);
9738 TALLOC_FREE(req);
9740 /* test search filters against rootDSE */
9741 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
9742 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
9744 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
9745 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
9746 talloc_tos(), NULL);
9747 if (!TLDAP_RC_IS_SUCCESS(rc)) {
9748 d_printf("tldap_search with complex filter failed: %s\n",
9749 tldap_errstr(talloc_tos(), ld, rc));
9750 return false;
9753 TALLOC_FREE(ld);
9754 return true;
9757 /* Torture test to ensure no regression of :
9758 https://bugzilla.samba.org/show_bug.cgi?id=7084
9761 static bool run_dir_createtime(int dummy)
9763 struct cli_state *cli;
9764 const char *dname = "\\testdir_createtime";
9765 const char *fname = "\\testdir_createtime\\testfile";
9766 NTSTATUS status;
9767 struct timespec create_time;
9768 struct timespec create_time1;
9769 uint16_t fnum;
9770 bool ret = false;
9772 if (!torture_open_connection(&cli, 0)) {
9773 return false;
9776 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9777 cli_rmdir(cli, dname);
9779 status = cli_mkdir(cli, dname);
9780 if (!NT_STATUS_IS_OK(status)) {
9781 printf("mkdir failed: %s\n", nt_errstr(status));
9782 goto out;
9785 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
9786 NULL, NULL, NULL);
9787 if (!NT_STATUS_IS_OK(status)) {
9788 printf("cli_qpathinfo2 returned %s\n",
9789 nt_errstr(status));
9790 goto out;
9793 /* Sleep 3 seconds, then create a file. */
9794 sleep(3);
9796 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
9797 DENY_NONE, &fnum);
9798 if (!NT_STATUS_IS_OK(status)) {
9799 printf("cli_openx failed: %s\n", nt_errstr(status));
9800 goto out;
9803 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
9804 NULL, NULL, NULL);
9805 if (!NT_STATUS_IS_OK(status)) {
9806 printf("cli_qpathinfo2 (2) returned %s\n",
9807 nt_errstr(status));
9808 goto out;
9811 if (timespec_compare(&create_time1, &create_time)) {
9812 printf("run_dir_createtime: create time was updated (error)\n");
9813 } else {
9814 printf("run_dir_createtime: create time was not updated (correct)\n");
9815 ret = true;
9818 out:
9820 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9821 cli_rmdir(cli, dname);
9822 if (!torture_close_connection(cli)) {
9823 ret = false;
9825 return ret;
9829 static bool run_streamerror(int dummy)
9831 struct cli_state *cli;
9832 const char *dname = "\\testdir_streamerror";
9833 const char *streamname =
9834 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
9835 NTSTATUS status;
9836 time_t change_time, access_time, write_time;
9837 off_t size;
9838 uint16_t mode, fnum;
9839 bool ret = true;
9841 if (!torture_open_connection(&cli, 0)) {
9842 return false;
9845 cli_unlink(cli, "\\testdir_streamerror\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9846 cli_rmdir(cli, dname);
9848 status = cli_mkdir(cli, dname);
9849 if (!NT_STATUS_IS_OK(status)) {
9850 printf("mkdir failed: %s\n", nt_errstr(status));
9851 return false;
9854 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
9855 &write_time, &size, &mode);
9856 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
9857 printf("pathinfo returned %s, expected "
9858 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
9859 nt_errstr(status));
9860 ret = false;
9863 status = cli_ntcreate(cli, streamname, 0x16,
9864 FILE_READ_DATA|FILE_READ_EA|
9865 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
9866 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
9867 FILE_OPEN, 0, 0, &fnum, NULL);
9869 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
9870 printf("ntcreate returned %s, expected "
9871 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
9872 nt_errstr(status));
9873 ret = false;
9877 cli_rmdir(cli, dname);
9878 return ret;
9881 struct pidtest_state {
9882 bool success;
9883 uint16_t vwv[1];
9884 DATA_BLOB data;
9887 static void pid_echo_done(struct tevent_req *subreq);
9889 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
9890 struct tevent_context *ev,
9891 struct cli_state *cli)
9893 struct tevent_req *req, *subreq;
9894 struct pidtest_state *state;
9896 req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
9897 if (req == NULL) {
9898 return NULL;
9901 SSVAL(state->vwv, 0, 1);
9902 state->data = data_blob_const("hello", 5);
9904 subreq = smb1cli_req_send(state,
9906 cli->conn,
9907 SMBecho,
9908 0, 0, /* *_flags */
9909 0, 0, /* *_flags2 */
9910 cli->timeout,
9911 0xDEADBEEF, /* pid */
9912 NULL, /* tcon */
9913 NULL, /* session */
9914 ARRAY_SIZE(state->vwv), state->vwv,
9915 state->data.length, state->data.data);
9917 if (tevent_req_nomem(subreq, req)) {
9918 return tevent_req_post(req, ev);
9920 tevent_req_set_callback(subreq, pid_echo_done, req);
9921 return req;
9924 static void pid_echo_done(struct tevent_req *subreq)
9926 struct tevent_req *req = tevent_req_callback_data(
9927 subreq, struct tevent_req);
9928 struct pidtest_state *state = tevent_req_data(
9929 req, struct pidtest_state);
9930 NTSTATUS status;
9931 uint32_t num_bytes;
9932 uint8_t *bytes = NULL;
9933 struct iovec *recv_iov = NULL;
9934 uint8_t *phdr = NULL;
9935 uint16_t pidlow = 0;
9936 uint16_t pidhigh = 0;
9937 struct smb1cli_req_expected_response expected[] = {
9939 .status = NT_STATUS_OK,
9940 .wct = 1,
9944 status = smb1cli_req_recv(subreq, state,
9945 &recv_iov,
9946 &phdr,
9947 NULL, /* pwct */
9948 NULL, /* pvwv */
9949 NULL, /* pvwv_offset */
9950 &num_bytes,
9951 &bytes,
9952 NULL, /* pbytes_offset */
9953 NULL, /* pinbuf */
9954 expected, ARRAY_SIZE(expected));
9956 TALLOC_FREE(subreq);
9958 if (!NT_STATUS_IS_OK(status)) {
9959 tevent_req_nterror(req, status);
9960 return;
9963 if (num_bytes != state->data.length) {
9964 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9965 return;
9968 if (memcmp(bytes, state->data.data, num_bytes) != 0) {
9969 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9970 return;
9973 /* Check pid low/high == DEADBEEF */
9974 pidlow = SVAL(phdr, HDR_PID);
9975 if (pidlow != 0xBEEF){
9976 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
9977 (unsigned int)pidlow);
9978 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9979 return;
9981 pidhigh = SVAL(phdr, HDR_PIDHIGH);
9982 if (pidhigh != 0xDEAD){
9983 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
9984 (unsigned int)pidhigh);
9985 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9986 return;
9989 tevent_req_done(req);
9992 static NTSTATUS pid_echo_recv(struct tevent_req *req)
9994 return tevent_req_simple_recv_ntstatus(req);
9997 static bool run_pidhigh(int dummy)
9999 bool success = false;
10000 struct cli_state *cli = NULL;
10001 NTSTATUS status;
10002 struct tevent_context *ev = NULL;
10003 struct tevent_req *req = NULL;
10004 TALLOC_CTX *frame = talloc_stackframe();
10006 printf("starting pid high test\n");
10007 if (!torture_open_connection(&cli, 0)) {
10008 return false;
10010 smbXcli_conn_set_sockopt(cli->conn, sockops);
10012 ev = samba_tevent_context_init(frame);
10013 if (ev == NULL) {
10014 goto fail;
10017 req = pid_echo_send(frame, ev, cli);
10018 if (req == NULL) {
10019 goto fail;
10022 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
10023 goto fail;
10026 status = pid_echo_recv(req);
10027 if (NT_STATUS_IS_OK(status)) {
10028 printf("pid high test ok\n");
10029 success = true;
10032 fail:
10034 TALLOC_FREE(frame);
10035 torture_close_connection(cli);
10036 return success;
10040 Test Windows open on a bad POSIX symlink.
10042 static bool run_symlink_open_test(int dummy)
10044 static struct cli_state *cli;
10045 const char *fname = "non_existant_file";
10046 const char *sname = "dangling_symlink";
10047 uint16_t fnum = (uint16_t)-1;
10048 bool correct = false;
10049 NTSTATUS status;
10050 TALLOC_CTX *frame = NULL;
10052 frame = talloc_stackframe();
10054 printf("Starting Windows bad symlink open test\n");
10056 if (!torture_open_connection(&cli, 0)) {
10057 TALLOC_FREE(frame);
10058 return false;
10061 smbXcli_conn_set_sockopt(cli->conn, sockops);
10063 status = torture_setup_unix_extensions(cli);
10064 if (!NT_STATUS_IS_OK(status)) {
10065 TALLOC_FREE(frame);
10066 return false;
10069 /* Ensure nothing exists. */
10070 cli_setatr(cli, fname, 0, 0);
10071 cli_posix_unlink(cli, fname);
10072 cli_setatr(cli, sname, 0, 0);
10073 cli_posix_unlink(cli, sname);
10075 /* Create a symlink pointing nowhere. */
10076 status = cli_posix_symlink(cli, fname, sname);
10077 if (!NT_STATUS_IS_OK(status)) {
10078 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
10079 sname,
10080 fname,
10081 nt_errstr(status));
10082 goto out;
10085 /* Now ensure that a Windows open doesn't hang. */
10086 status = cli_ntcreate(cli,
10087 sname,
10089 FILE_READ_DATA|FILE_WRITE_DATA,
10091 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10092 FILE_OPEN_IF,
10093 0x0,
10094 0x0,
10095 &fnum,
10096 NULL);
10099 * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
10100 * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
10101 * we use O_NOFOLLOW on the server or not.
10103 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
10104 NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
10106 correct = true;
10107 } else {
10108 printf("cli_ntcreate of %s returned %s - should return"
10109 " either (%s) or (%s)\n",
10110 sname,
10111 nt_errstr(status),
10112 nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
10113 nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
10114 goto out;
10117 correct = true;
10119 out:
10121 if (fnum != (uint16_t)-1) {
10122 cli_close(cli, fnum);
10123 fnum = (uint16_t)-1;
10126 cli_setatr(cli, sname, 0, 0);
10127 cli_posix_unlink(cli, sname);
10128 cli_setatr(cli, fname, 0, 0);
10129 cli_posix_unlink(cli, fname);
10131 if (!torture_close_connection(cli)) {
10132 correct = false;
10135 TALLOC_FREE(frame);
10136 return correct;
10140 * Only testing minimal time strings, as the others
10141 * need (locale-dependent) guessing at what strftime does and
10142 * even may differ in builds.
10144 static bool timesubst_test(void)
10146 TALLOC_CTX *ctx = NULL;
10147 /* Sa 23. Dez 04:33:20 CET 2017 */
10148 const struct timeval tv = { 1514000000, 123 };
10149 const char* expect_minimal = "20171223_033320";
10150 const char* expect_minus = "20171223_033320_000123";
10151 char *s;
10152 char *env_tz, *orig_tz = NULL;
10153 bool result = true;
10155 ctx = talloc_new(NULL);
10157 env_tz = getenv("TZ");
10158 if(env_tz) {
10159 orig_tz = talloc_strdup(ctx, env_tz);
10161 setenv("TZ", "UTC", 1);
10163 s = minimal_timeval_string(ctx, &tv, false);
10165 if(!s || strcmp(s, expect_minimal)) {
10166 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
10167 "[%s]\n", s ? s : "<nil>", expect_minimal);
10168 result = false;
10170 TALLOC_FREE(s);
10171 s = minimal_timeval_string(ctx, &tv, true);
10172 if(!s || strcmp(s, expect_minus)) {
10173 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
10174 "[%s]\n", s ? s : "<nil>", expect_minus);
10175 result = false;
10177 TALLOC_FREE(s);
10179 if(orig_tz) {
10180 setenv("TZ", orig_tz, 1);
10183 TALLOC_FREE(ctx);
10184 return result;
10187 static bool run_local_substitute(int dummy)
10189 bool ok = true;
10191 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
10192 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
10193 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
10194 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
10195 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
10196 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
10197 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
10198 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
10199 ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
10200 /* Substitution depends on current time, so better test the underlying
10201 formatting function. At least covers %t. */
10202 ok &= timesubst_test();
10204 /* Different captialization rules in sub_basic... */
10206 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
10207 "blaDOM") == 0);
10209 return ok;
10212 static bool run_local_base64(int dummy)
10214 int i;
10215 bool ret = true;
10217 for (i=1; i<2000; i++) {
10218 DATA_BLOB blob1, blob2;
10219 char *b64;
10221 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
10222 blob1.length = i;
10223 generate_random_buffer(blob1.data, blob1.length);
10225 b64 = base64_encode_data_blob(talloc_tos(), blob1);
10226 if (b64 == NULL) {
10227 d_fprintf(stderr, "base64_encode_data_blob failed "
10228 "for %d bytes\n", i);
10229 ret = false;
10231 blob2 = base64_decode_data_blob(b64);
10232 TALLOC_FREE(b64);
10234 if (data_blob_cmp(&blob1, &blob2)) {
10235 d_fprintf(stderr, "data_blob_cmp failed for %d "
10236 "bytes\n", i);
10237 ret = false;
10239 TALLOC_FREE(blob1.data);
10240 data_blob_free(&blob2);
10242 return ret;
10245 static void parse_fn(const struct gencache_timeout *t,
10246 DATA_BLOB blob,
10247 void *private_data)
10249 return;
10252 static bool run_local_gencache(int dummy)
10254 char *val;
10255 time_t tm;
10256 DATA_BLOB blob;
10257 char v;
10258 struct memcache *mem;
10259 int i;
10261 mem = memcache_init(NULL, 0);
10262 if (mem == NULL) {
10263 d_printf("%s: memcache_init failed\n", __location__);
10264 return false;
10266 memcache_set_global(mem);
10268 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
10269 d_printf("%s: gencache_set() failed\n", __location__);
10270 return False;
10273 if (!gencache_get("foo", NULL, NULL, NULL)) {
10274 d_printf("%s: gencache_get() failed\n", __location__);
10275 return False;
10278 for (i=0; i<1000000; i++) {
10279 gencache_parse("foo", parse_fn, NULL);
10282 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
10283 d_printf("%s: gencache_get() failed\n", __location__);
10284 return False;
10286 TALLOC_FREE(val);
10288 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
10289 d_printf("%s: gencache_get() failed\n", __location__);
10290 return False;
10293 if (strcmp(val, "bar") != 0) {
10294 d_printf("%s: gencache_get() returned %s, expected %s\n",
10295 __location__, val, "bar");
10296 TALLOC_FREE(val);
10297 return False;
10300 TALLOC_FREE(val);
10302 if (!gencache_del("foo")) {
10303 d_printf("%s: gencache_del() failed\n", __location__);
10304 return False;
10306 if (gencache_del("foo")) {
10307 d_printf("%s: second gencache_del() succeeded\n",
10308 __location__);
10309 return False;
10312 if (gencache_get("foo", talloc_tos(), &val, &tm)) {
10313 d_printf("%s: gencache_get() on deleted entry "
10314 "succeeded\n", __location__);
10315 return False;
10318 blob = data_blob_string_const_null("bar");
10319 tm = time(NULL) + 60;
10321 if (!gencache_set_data_blob("foo", blob, tm)) {
10322 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
10323 return False;
10326 if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
10327 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
10328 return False;
10331 if (strcmp((const char *)blob.data, "bar") != 0) {
10332 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
10333 __location__, (const char *)blob.data, "bar");
10334 data_blob_free(&blob);
10335 return False;
10338 data_blob_free(&blob);
10340 if (!gencache_del("foo")) {
10341 d_printf("%s: gencache_del() failed\n", __location__);
10342 return False;
10344 if (gencache_del("foo")) {
10345 d_printf("%s: second gencache_del() succeeded\n",
10346 __location__);
10347 return False;
10350 if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
10351 d_printf("%s: gencache_get_data_blob() on deleted entry "
10352 "succeeded\n", __location__);
10353 return False;
10356 v = 1;
10357 blob.data = (uint8_t *)&v;
10358 blob.length = sizeof(v);
10360 if (!gencache_set_data_blob("blob", blob, tm)) {
10361 d_printf("%s: gencache_set_data_blob() failed\n",
10362 __location__);
10363 return false;
10365 if (gencache_get("blob", talloc_tos(), &val, &tm)) {
10366 d_printf("%s: gencache_get succeeded\n", __location__);
10367 return false;
10370 return True;
10373 static bool rbt_testval(struct db_context *db, const char *key,
10374 const char *value)
10376 struct db_record *rec;
10377 TDB_DATA data = string_tdb_data(value);
10378 bool ret = false;
10379 NTSTATUS status;
10380 TDB_DATA dbvalue;
10382 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
10383 if (rec == NULL) {
10384 d_fprintf(stderr, "fetch_locked failed\n");
10385 goto done;
10387 status = dbwrap_record_store(rec, data, 0);
10388 if (!NT_STATUS_IS_OK(status)) {
10389 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
10390 goto done;
10392 TALLOC_FREE(rec);
10394 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
10395 if (rec == NULL) {
10396 d_fprintf(stderr, "second fetch_locked failed\n");
10397 goto done;
10400 dbvalue = dbwrap_record_get_value(rec);
10401 if ((dbvalue.dsize != data.dsize)
10402 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
10403 d_fprintf(stderr, "Got wrong data back\n");
10404 goto done;
10407 ret = true;
10408 done:
10409 TALLOC_FREE(rec);
10410 return ret;
10413 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
10415 int *count2 = (int *)private_data;
10416 (*count2)++;
10417 return 0;
10420 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
10422 int *count2 = (int *)private_data;
10423 (*count2)++;
10424 dbwrap_record_delete(rec);
10425 return 0;
10428 static bool run_local_rbtree(int dummy)
10430 struct db_context *db;
10431 bool ret = false;
10432 int i;
10433 NTSTATUS status;
10434 int count = 0;
10435 int count2 = 0;
10437 db = db_open_rbt(NULL);
10439 if (db == NULL) {
10440 d_fprintf(stderr, "db_open_rbt failed\n");
10441 return false;
10444 for (i=0; i<1000; i++) {
10445 char *key, *value;
10447 if (asprintf(&key, "key%ld", random()) == -1) {
10448 goto done;
10450 if (asprintf(&value, "value%ld", random()) == -1) {
10451 SAFE_FREE(key);
10452 goto done;
10455 if (!rbt_testval(db, key, value)) {
10456 SAFE_FREE(key);
10457 SAFE_FREE(value);
10458 goto done;
10461 SAFE_FREE(value);
10462 if (asprintf(&value, "value%ld", random()) == -1) {
10463 SAFE_FREE(key);
10464 goto done;
10467 if (!rbt_testval(db, key, value)) {
10468 SAFE_FREE(key);
10469 SAFE_FREE(value);
10470 goto done;
10473 SAFE_FREE(key);
10474 SAFE_FREE(value);
10477 ret = true;
10478 count = 0; count2 = 0;
10479 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
10480 &count2, &count);
10481 printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10482 if ((count != count2) || (count != 1000)) {
10483 ret = false;
10485 count = 0; count2 = 0;
10486 status = dbwrap_traverse(db, local_rbtree_traverse_delete,
10487 &count2, &count);
10488 printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10489 if ((count != count2) || (count != 1000)) {
10490 ret = false;
10492 count = 0; count2 = 0;
10493 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
10494 &count2, &count);
10495 printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10496 if ((count != count2) || (count != 0)) {
10497 ret = false;
10500 done:
10501 TALLOC_FREE(db);
10502 return ret;
10507 local test for character set functions
10509 This is a very simple test for the functionality in convert_string_error()
10511 static bool run_local_convert_string(int dummy)
10513 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
10514 const char *test_strings[2] = { "March", "M\303\244rz" };
10515 char dst[7];
10516 int i;
10518 for (i=0; i<2; i++) {
10519 const char *str = test_strings[i];
10520 int len = strlen(str);
10521 size_t converted_size;
10522 bool ret;
10524 memset(dst, 'X', sizeof(dst));
10526 /* first try with real source length */
10527 ret = convert_string_error(CH_UNIX, CH_UTF8,
10528 str, len,
10529 dst, sizeof(dst),
10530 &converted_size);
10531 if (ret != true) {
10532 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
10533 goto failed;
10536 if (converted_size != len) {
10537 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
10538 str, len, (int)converted_size);
10539 goto failed;
10542 if (strncmp(str, dst, converted_size) != 0) {
10543 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
10544 goto failed;
10547 if (strlen(str) != converted_size) {
10548 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
10549 (int)strlen(str), (int)converted_size);
10550 goto failed;
10553 if (dst[converted_size] != 'X') {
10554 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
10555 goto failed;
10558 /* now with srclen==-1, this causes the nul to be
10559 * converted too */
10560 ret = convert_string_error(CH_UNIX, CH_UTF8,
10561 str, -1,
10562 dst, sizeof(dst),
10563 &converted_size);
10564 if (ret != true) {
10565 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
10566 goto failed;
10569 if (converted_size != len+1) {
10570 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
10571 str, len, (int)converted_size);
10572 goto failed;
10575 if (strncmp(str, dst, converted_size) != 0) {
10576 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
10577 goto failed;
10580 if (len+1 != converted_size) {
10581 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
10582 len+1, (int)converted_size);
10583 goto failed;
10586 if (dst[converted_size] != 'X') {
10587 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
10588 goto failed;
10594 TALLOC_FREE(tmp_ctx);
10595 return true;
10596 failed:
10597 TALLOC_FREE(tmp_ctx);
10598 return false;
10601 static bool run_local_string_to_sid(int dummy) {
10602 struct dom_sid sid;
10604 if (string_to_sid(&sid, "S--1-5-32-545")) {
10605 printf("allowing S--1-5-32-545\n");
10606 return false;
10608 if (string_to_sid(&sid, "S-1-5-32-+545")) {
10609 printf("allowing S-1-5-32-+545\n");
10610 return false;
10612 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")) {
10613 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
10614 return false;
10616 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
10617 printf("allowing S-1-5-32-545-abc\n");
10618 return false;
10620 if (string_to_sid(&sid, "S-300-5-32-545")) {
10621 printf("allowing S-300-5-32-545\n");
10622 return false;
10624 if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
10625 printf("allowing S-1-0xfffffffffffffe-32-545\n");
10626 return false;
10628 if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
10629 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
10630 return false;
10632 if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
10633 printf("could not parse S-1-0xfffffffffffe-32-545\n");
10634 return false;
10636 if (!string_to_sid(&sid, "S-1-5-32-545")) {
10637 printf("could not parse S-1-5-32-545\n");
10638 return false;
10640 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
10641 printf("mis-parsed S-1-5-32-545 as %s\n",
10642 sid_string_tos(&sid));
10643 return false;
10645 return true;
10648 static bool sid_to_string_test(const char *expected) {
10649 char *str;
10650 bool res = true;
10651 struct dom_sid sid;
10653 if (!string_to_sid(&sid, expected)) {
10654 printf("could not parse %s\n", expected);
10655 return false;
10658 str = dom_sid_string(NULL, &sid);
10659 if (strcmp(str, expected)) {
10660 printf("Comparison failed (%s != %s)\n", str, expected);
10661 res = false;
10663 TALLOC_FREE(str);
10664 return res;
10667 static bool run_local_sid_to_string(int dummy) {
10668 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
10669 return false;
10670 if (!sid_to_string_test("S-1-545"))
10671 return false;
10672 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
10673 return false;
10674 return true;
10677 static bool run_local_binary_to_sid(int dummy) {
10678 struct dom_sid *sid = talloc(NULL, struct dom_sid);
10679 static const uint8_t good_binary_sid[] = {
10680 0x1, /* revision number */
10681 15, /* num auths */
10682 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10683 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10684 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10685 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10686 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10687 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10688 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10689 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10690 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10691 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10692 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10693 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10694 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10695 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10696 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10697 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10700 static const uint8_t long_binary_sid[] = {
10701 0x1, /* revision number */
10702 15, /* num auths */
10703 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10704 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10705 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10706 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10707 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10708 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10709 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10710 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10711 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10712 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10713 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10714 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10715 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10716 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10717 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10718 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10719 0x1, 0x1, 0x1, 0x1, /* auth[15] */
10720 0x1, 0x1, 0x1, 0x1, /* auth[16] */
10721 0x1, 0x1, 0x1, 0x1, /* auth[17] */
10724 static const uint8_t long_binary_sid2[] = {
10725 0x1, /* revision number */
10726 32, /* num auths */
10727 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10728 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10729 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10730 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10731 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10732 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10733 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10734 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10735 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10736 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10737 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10738 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10739 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10740 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10741 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10742 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10743 0x1, 0x1, 0x1, 0x1, /* auth[15] */
10744 0x1, 0x1, 0x1, 0x1, /* auth[16] */
10745 0x1, 0x1, 0x1, 0x1, /* auth[17] */
10746 0x1, 0x1, 0x1, 0x1, /* auth[18] */
10747 0x1, 0x1, 0x1, 0x1, /* auth[19] */
10748 0x1, 0x1, 0x1, 0x1, /* auth[20] */
10749 0x1, 0x1, 0x1, 0x1, /* auth[21] */
10750 0x1, 0x1, 0x1, 0x1, /* auth[22] */
10751 0x1, 0x1, 0x1, 0x1, /* auth[23] */
10752 0x1, 0x1, 0x1, 0x1, /* auth[24] */
10753 0x1, 0x1, 0x1, 0x1, /* auth[25] */
10754 0x1, 0x1, 0x1, 0x1, /* auth[26] */
10755 0x1, 0x1, 0x1, 0x1, /* auth[27] */
10756 0x1, 0x1, 0x1, 0x1, /* auth[28] */
10757 0x1, 0x1, 0x1, 0x1, /* auth[29] */
10758 0x1, 0x1, 0x1, 0x1, /* auth[30] */
10759 0x1, 0x1, 0x1, 0x1, /* auth[31] */
10762 if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
10763 return false;
10765 if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
10766 return false;
10768 if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
10769 return false;
10771 return true;
10774 /* Split a path name into filename and stream name components. Canonicalise
10775 * such that an implicit $DATA token is always explicit.
10777 * The "specification" of this function can be found in the
10778 * run_local_stream_name() function in torture.c, I've tried those
10779 * combinations against a W2k3 server.
10782 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
10783 char **pbase, char **pstream)
10785 char *base = NULL;
10786 char *stream = NULL;
10787 char *sname; /* stream name */
10788 const char *stype; /* stream type */
10790 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
10792 sname = strchr_m(fname, ':');
10794 if (sname == NULL) {
10795 if (pbase != NULL) {
10796 base = talloc_strdup(mem_ctx, fname);
10797 NT_STATUS_HAVE_NO_MEMORY(base);
10799 goto done;
10802 if (pbase != NULL) {
10803 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
10804 NT_STATUS_HAVE_NO_MEMORY(base);
10807 sname += 1;
10809 stype = strchr_m(sname, ':');
10811 if (stype == NULL) {
10812 sname = talloc_strdup(mem_ctx, sname);
10813 stype = "$DATA";
10815 else {
10816 if (strcasecmp_m(stype, ":$DATA") != 0) {
10818 * If there is an explicit stream type, so far we only
10819 * allow $DATA. Is there anything else allowed? -- vl
10821 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
10822 TALLOC_FREE(base);
10823 return NT_STATUS_OBJECT_NAME_INVALID;
10825 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
10826 stype += 1;
10829 if (sname == NULL) {
10830 TALLOC_FREE(base);
10831 return NT_STATUS_NO_MEMORY;
10834 if (sname[0] == '\0') {
10836 * no stream name, so no stream
10838 goto done;
10841 if (pstream != NULL) {
10842 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
10843 if (stream == NULL) {
10844 TALLOC_FREE(sname);
10845 TALLOC_FREE(base);
10846 return NT_STATUS_NO_MEMORY;
10849 * upper-case the type field
10851 (void)strupper_m(strchr_m(stream, ':')+1);
10854 done:
10855 if (pbase != NULL) {
10856 *pbase = base;
10858 if (pstream != NULL) {
10859 *pstream = stream;
10861 return NT_STATUS_OK;
10864 static bool test_stream_name(const char *fname, const char *expected_base,
10865 const char *expected_stream,
10866 NTSTATUS expected_status)
10868 NTSTATUS status;
10869 char *base = NULL;
10870 char *stream = NULL;
10872 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
10873 if (!NT_STATUS_EQUAL(status, expected_status)) {
10874 goto error;
10877 if (!NT_STATUS_IS_OK(status)) {
10878 return true;
10881 if (base == NULL) goto error;
10883 if (strcmp(expected_base, base) != 0) goto error;
10885 if ((expected_stream != NULL) && (stream == NULL)) goto error;
10886 if ((expected_stream == NULL) && (stream != NULL)) goto error;
10888 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
10889 goto error;
10891 TALLOC_FREE(base);
10892 TALLOC_FREE(stream);
10893 return true;
10895 error:
10896 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
10897 fname, expected_base ? expected_base : "<NULL>",
10898 expected_stream ? expected_stream : "<NULL>",
10899 nt_errstr(expected_status));
10900 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
10901 base ? base : "<NULL>", stream ? stream : "<NULL>",
10902 nt_errstr(status));
10903 TALLOC_FREE(base);
10904 TALLOC_FREE(stream);
10905 return false;
10908 static bool run_local_stream_name(int dummy)
10910 bool ret = true;
10912 ret &= test_stream_name(
10913 "bla", "bla", NULL, NT_STATUS_OK);
10914 ret &= test_stream_name(
10915 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
10916 ret &= test_stream_name(
10917 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
10918 ret &= test_stream_name(
10919 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
10920 ret &= test_stream_name(
10921 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
10922 ret &= test_stream_name(
10923 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
10924 ret &= test_stream_name(
10925 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
10926 ret &= test_stream_name(
10927 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
10929 return ret;
10932 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
10934 if (a.length != b.length) {
10935 printf("a.length=%d != b.length=%d\n",
10936 (int)a.length, (int)b.length);
10937 return false;
10939 if (memcmp(a.data, b.data, a.length) != 0) {
10940 printf("a.data and b.data differ\n");
10941 return false;
10943 return true;
10946 static bool run_local_memcache(int dummy)
10948 struct memcache *cache;
10949 DATA_BLOB k1, k2, k3;
10950 DATA_BLOB d1, d3;
10951 DATA_BLOB v1, v3;
10953 TALLOC_CTX *mem_ctx;
10954 char *ptr1 = NULL;
10955 char *ptr2 = NULL;
10957 char *str1, *str2;
10958 size_t size1, size2;
10959 bool ret = false;
10961 mem_ctx = talloc_init("foo");
10962 if (mem_ctx == NULL) {
10963 return false;
10966 /* STAT_CACHE TESTS */
10968 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
10970 if (cache == NULL) {
10971 printf("memcache_init failed\n");
10972 return false;
10975 d1 = data_blob_const("d1", 2);
10976 d3 = data_blob_const("d3", 2);
10978 k1 = data_blob_const("d1", 2);
10979 k2 = data_blob_const("d2", 2);
10980 k3 = data_blob_const("d3", 2);
10982 memcache_add(cache, STAT_CACHE, k1, d1);
10984 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
10985 printf("could not find k1\n");
10986 return false;
10988 if (!data_blob_equal(d1, v1)) {
10989 return false;
10992 memcache_add(cache, STAT_CACHE, k1, d3);
10994 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
10995 printf("could not find replaced k1\n");
10996 return false;
10998 if (!data_blob_equal(d3, v3)) {
10999 return false;
11002 TALLOC_FREE(cache);
11004 /* GETWD_CACHE TESTS */
11005 str1 = talloc_strdup(mem_ctx, "string1");
11006 if (str1 == NULL) {
11007 return false;
11009 ptr2 = str1; /* Keep an alias for comparison. */
11011 str2 = talloc_strdup(mem_ctx, "string2");
11012 if (str2 == NULL) {
11013 return false;
11016 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
11017 if (cache == NULL) {
11018 printf("memcache_init failed\n");
11019 return false;
11022 memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
11023 /* str1 == NULL now. */
11024 ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
11025 if (ptr1 == NULL) {
11026 printf("could not find k2\n");
11027 return false;
11029 if (ptr1 != ptr2) {
11030 printf("fetch of k2 got wrong string\n");
11031 return false;
11034 /* Add a blob to ensure k2 gets purged. */
11035 d3 = data_blob_talloc_zero(mem_ctx, 180);
11036 memcache_add(cache, STAT_CACHE, k3, d3);
11038 ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
11039 if (ptr2 != NULL) {
11040 printf("Did find k2, should have been purged\n");
11041 return false;
11044 TALLOC_FREE(cache);
11045 TALLOC_FREE(mem_ctx);
11047 mem_ctx = talloc_init("foo");
11048 if (mem_ctx == NULL) {
11049 return false;
11052 cache = memcache_init(NULL, 0);
11053 if (cache == NULL) {
11054 return false;
11057 str1 = talloc_strdup(mem_ctx, "string1");
11058 if (str1 == NULL) {
11059 return false;
11061 str2 = talloc_strdup(mem_ctx, "string2");
11062 if (str2 == NULL) {
11063 return false;
11065 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
11066 data_blob_string_const("torture"), &str1);
11067 size1 = talloc_total_size(cache);
11069 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
11070 data_blob_string_const("torture"), &str2);
11071 size2 = talloc_total_size(cache);
11073 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
11075 if (size2 > size1) {
11076 printf("memcache leaks memory!\n");
11077 goto fail;
11080 ret = true;
11081 fail:
11082 TALLOC_FREE(cache);
11083 return ret;
11086 static void wbclient_done(struct tevent_req *req)
11088 wbcErr wbc_err;
11089 struct winbindd_response *wb_resp;
11090 int *i = (int *)tevent_req_callback_data_void(req);
11092 wbc_err = wb_trans_recv(req, req, &wb_resp);
11093 TALLOC_FREE(req);
11094 *i += 1;
11095 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
11098 static bool run_wbclient_multi_ping(int dummy)
11100 struct tevent_context *ev;
11101 struct wb_context **wb_ctx;
11102 struct winbindd_request wb_req;
11103 bool result = false;
11104 int i, j;
11106 BlockSignals(True, SIGPIPE);
11108 ev = tevent_context_init(talloc_tos());
11109 if (ev == NULL) {
11110 goto fail;
11113 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
11114 if (wb_ctx == NULL) {
11115 goto fail;
11118 ZERO_STRUCT(wb_req);
11119 wb_req.cmd = WINBINDD_PING;
11121 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
11123 for (i=0; i<torture_nprocs; i++) {
11124 wb_ctx[i] = wb_context_init(ev, NULL);
11125 if (wb_ctx[i] == NULL) {
11126 goto fail;
11128 for (j=0; j<torture_numops; j++) {
11129 struct tevent_req *req;
11130 req = wb_trans_send(ev, ev, wb_ctx[i],
11131 (j % 2) == 0, &wb_req);
11132 if (req == NULL) {
11133 goto fail;
11135 tevent_req_set_callback(req, wbclient_done, &i);
11139 i = 0;
11141 while (i < torture_nprocs * torture_numops) {
11142 tevent_loop_once(ev);
11145 result = true;
11146 fail:
11147 TALLOC_FREE(ev);
11148 return result;
11151 static bool dbtrans_inc(struct db_context *db)
11153 struct db_record *rec;
11154 uint32_t val;
11155 bool ret = false;
11156 NTSTATUS status;
11157 TDB_DATA value;
11159 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
11160 if (rec == NULL) {
11161 printf(__location__ "fetch_lock failed\n");
11162 return false;
11165 value = dbwrap_record_get_value(rec);
11167 if (value.dsize != sizeof(uint32_t)) {
11168 printf(__location__ "value.dsize = %d\n",
11169 (int)value.dsize);
11170 goto fail;
11173 memcpy(&val, value.dptr, sizeof(val));
11174 val += 1;
11176 status = dbwrap_record_store(
11177 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
11178 if (!NT_STATUS_IS_OK(status)) {
11179 printf(__location__ "store failed: %s\n",
11180 nt_errstr(status));
11181 goto fail;
11184 ret = true;
11185 fail:
11186 TALLOC_FREE(rec);
11187 return ret;
11190 static bool run_local_dbtrans(int dummy)
11192 struct db_context *db;
11193 struct db_record *rec;
11194 NTSTATUS status;
11195 uint32_t initial;
11196 int res;
11197 TDB_DATA value;
11199 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
11200 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
11201 DBWRAP_FLAG_NONE);
11202 if (db == NULL) {
11203 printf("Could not open transtest.db\n");
11204 return false;
11207 res = dbwrap_transaction_start(db);
11208 if (res != 0) {
11209 printf(__location__ "transaction_start failed\n");
11210 return false;
11213 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
11214 if (rec == NULL) {
11215 printf(__location__ "fetch_lock failed\n");
11216 return false;
11219 value = dbwrap_record_get_value(rec);
11221 if (value.dptr == NULL) {
11222 initial = 0;
11223 status = dbwrap_record_store(
11224 rec, make_tdb_data((uint8_t *)&initial,
11225 sizeof(initial)),
11227 if (!NT_STATUS_IS_OK(status)) {
11228 printf(__location__ "store returned %s\n",
11229 nt_errstr(status));
11230 return false;
11234 TALLOC_FREE(rec);
11236 res = dbwrap_transaction_commit(db);
11237 if (res != 0) {
11238 printf(__location__ "transaction_commit failed\n");
11239 return false;
11242 while (true) {
11243 uint32_t val, val2;
11244 int i;
11246 res = dbwrap_transaction_start(db);
11247 if (res != 0) {
11248 printf(__location__ "transaction_start failed\n");
11249 break;
11252 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
11253 if (!NT_STATUS_IS_OK(status)) {
11254 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
11255 nt_errstr(status));
11256 break;
11259 for (i=0; i<10; i++) {
11260 if (!dbtrans_inc(db)) {
11261 return false;
11265 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
11266 if (!NT_STATUS_IS_OK(status)) {
11267 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
11268 nt_errstr(status));
11269 break;
11272 if (val2 != val + 10) {
11273 printf(__location__ "val=%d, val2=%d\n",
11274 (int)val, (int)val2);
11275 break;
11278 printf("val2=%d\r", val2);
11280 res = dbwrap_transaction_commit(db);
11281 if (res != 0) {
11282 printf(__location__ "transaction_commit failed\n");
11283 break;
11287 TALLOC_FREE(db);
11288 return true;
11292 * Just a dummy test to be run under a debugger. There's no real way
11293 * to inspect the tevent_poll specific function from outside of
11294 * tevent_poll.c.
11297 static bool run_local_tevent_poll(int dummy)
11299 struct tevent_context *ev;
11300 struct tevent_fd *fd1, *fd2;
11301 bool result = false;
11303 ev = tevent_context_init_byname(NULL, "poll");
11304 if (ev == NULL) {
11305 d_fprintf(stderr, "tevent_context_init_byname failed\n");
11306 goto fail;
11309 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
11310 if (fd1 == NULL) {
11311 d_fprintf(stderr, "tevent_add_fd failed\n");
11312 goto fail;
11314 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
11315 if (fd2 == NULL) {
11316 d_fprintf(stderr, "tevent_add_fd failed\n");
11317 goto fail;
11319 TALLOC_FREE(fd2);
11321 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
11322 if (fd2 == NULL) {
11323 d_fprintf(stderr, "tevent_add_fd failed\n");
11324 goto fail;
11327 result = true;
11328 fail:
11329 TALLOC_FREE(ev);
11330 return result;
11333 static bool run_local_hex_encode_buf(int dummy)
11335 char buf[17];
11336 uint8_t src[8];
11337 int i;
11339 for (i=0; i<sizeof(src); i++) {
11340 src[i] = i;
11342 hex_encode_buf(buf, src, sizeof(src));
11343 if (strcmp(buf, "0001020304050607") != 0) {
11344 return false;
11346 hex_encode_buf(buf, NULL, 0);
11347 if (buf[0] != '\0') {
11348 return false;
11350 return true;
11353 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
11354 "0.0.0.0",
11355 "::0",
11356 "1.2.3.1",
11357 "0.0.0.0",
11358 "0.0.0.0",
11359 "1.2.3.2",
11360 "1.2.3.3",
11361 "1.2.3.4",
11362 "1.2.3.5",
11363 "::0",
11364 "1.2.3.6",
11365 "1.2.3.7",
11366 "::0",
11367 "::0",
11368 "::0",
11369 "1.2.3.8",
11370 "1.2.3.9",
11371 "1.2.3.10",
11372 "1.2.3.11",
11373 "1.2.3.12",
11374 "1.2.3.13",
11375 "1001:1111:1111:1000:0:1111:1111:1111",
11376 "1.2.3.1",
11377 "1.2.3.2",
11378 "1.2.3.3",
11379 "1.2.3.12",
11380 "::0",
11381 "::0"
11384 static const char *remove_duplicate_addrs2_test_strings_result[] = {
11385 "1.2.3.1",
11386 "1.2.3.2",
11387 "1.2.3.3",
11388 "1.2.3.4",
11389 "1.2.3.5",
11390 "1.2.3.6",
11391 "1.2.3.7",
11392 "1.2.3.8",
11393 "1.2.3.9",
11394 "1.2.3.10",
11395 "1.2.3.11",
11396 "1.2.3.12",
11397 "1.2.3.13",
11398 "1001:1111:1111:1000:0:1111:1111:1111"
11401 static bool run_local_remove_duplicate_addrs2(int dummy)
11403 struct ip_service test_vector[28];
11404 int count, i;
11406 /* Construct the sockaddr_storage test vector. */
11407 for (i = 0; i < 28; i++) {
11408 struct addrinfo hints;
11409 struct addrinfo *res = NULL;
11410 int ret;
11412 memset(&hints, '\0', sizeof(hints));
11413 hints.ai_flags = AI_NUMERICHOST;
11414 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
11415 NULL,
11416 &hints,
11417 &res);
11418 if (ret) {
11419 fprintf(stderr, "getaddrinfo failed on [%s]\n",
11420 remove_duplicate_addrs2_test_strings_vector[i]);
11421 return false;
11423 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
11424 memcpy(&test_vector[i].ss,
11425 res->ai_addr,
11426 res->ai_addrlen);
11427 freeaddrinfo(res);
11430 count = remove_duplicate_addrs2(test_vector, i);
11432 if (count != 14) {
11433 fprintf(stderr, "count wrong (%d) should be 14\n",
11434 count);
11435 return false;
11438 for (i = 0; i < count; i++) {
11439 char addr[INET6_ADDRSTRLEN];
11441 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
11443 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
11444 fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
11446 addr,
11447 remove_duplicate_addrs2_test_strings_result[i]);
11448 return false;
11452 printf("run_local_remove_duplicate_addrs2: success\n");
11453 return true;
11456 static bool run_local_tdb_opener(int dummy)
11458 TDB_CONTEXT *t;
11459 unsigned v = 0;
11461 while (1) {
11462 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
11463 O_RDWR|O_CREAT, 0755);
11464 if (t == NULL) {
11465 perror("tdb_open failed");
11466 return false;
11468 tdb_close(t);
11470 v += 1;
11471 printf("\r%u", v);
11473 return true;
11476 static bool run_local_tdb_writer(int dummy)
11478 TDB_CONTEXT *t;
11479 unsigned v = 0;
11480 TDB_DATA val;
11482 t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
11483 if (t == 0) {
11484 perror("tdb_open failed");
11485 return 1;
11488 val.dptr = (uint8_t *)&v;
11489 val.dsize = sizeof(v);
11491 while (1) {
11492 TDB_DATA data;
11493 int ret;
11495 ret = tdb_store(t, val, val, 0);
11496 if (ret != 0) {
11497 printf("%s\n", tdb_errorstr(t));
11499 v += 1;
11500 printf("\r%u", v);
11502 data = tdb_fetch(t, val);
11503 if (data.dptr != NULL) {
11504 SAFE_FREE(data.dptr);
11507 return true;
11510 static bool run_local_canonicalize_path(int dummy)
11512 const char *src[] = {
11513 "/foo/..",
11514 "/..",
11515 "/foo/bar/../baz",
11516 "/foo/././",
11517 "/../foo",
11518 ".././././",
11519 ".././././../../../boo",
11520 "./..",
11521 NULL
11523 const char *dst[] = {
11524 "/",
11525 "/",
11526 "/foo/baz",
11527 "/foo",
11528 "/foo",
11529 "/",
11530 "/boo",
11531 "/",
11532 NULL
11534 unsigned int i;
11536 for (i = 0; src[i] != NULL; i++) {
11537 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
11538 if (d == NULL) {
11539 perror("talloc fail\n");
11540 return false;
11542 if (strcmp(d, dst[i]) != 0) {
11543 d_fprintf(stderr,
11544 "canonicalize mismatch %s -> %s != %s",
11545 src[i], d, dst[i]);
11546 return false;
11548 talloc_free(d);
11550 return true;
11553 static bool run_ign_bad_negprot(int dummy)
11555 struct tevent_context *ev;
11556 struct tevent_req *req;
11557 struct smbXcli_conn *conn;
11558 struct sockaddr_storage ss;
11559 NTSTATUS status;
11560 int fd;
11561 bool ok;
11563 printf("starting ignore bad negprot\n");
11565 ok = resolve_name(host, &ss, 0x20, true);
11566 if (!ok) {
11567 d_fprintf(stderr, "Could not resolve name %s\n", host);
11568 return false;
11571 status = open_socket_out(&ss, 445, 10000, &fd);
11572 if (!NT_STATUS_IS_OK(status)) {
11573 d_fprintf(stderr, "open_socket_out failed: %s\n",
11574 nt_errstr(status));
11575 return false;
11578 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
11579 NULL, 0);
11580 if (conn == NULL) {
11581 d_fprintf(stderr, "smbXcli_conn_create failed\n");
11582 return false;
11585 status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
11586 if (NT_STATUS_IS_OK(status)) {
11587 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
11588 return false;
11591 ev = samba_tevent_context_init(talloc_tos());
11592 if (ev == NULL) {
11593 d_fprintf(stderr, "samba_tevent_context_init failed\n");
11594 return false;
11597 req = smb1cli_session_setup_nt1_send(
11598 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
11599 data_blob_null, data_blob_null, 0x40,
11600 "Windows 2000 2195", "Windows 2000 5.0");
11601 if (req == NULL) {
11602 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
11603 return false;
11606 ok = tevent_req_poll_ntstatus(req, ev, &status);
11607 if (!ok) {
11608 d_fprintf(stderr, "tevent_req_poll failed\n");
11609 return false;
11612 status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
11613 NULL, NULL);
11614 if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
11615 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
11616 "%s, expected NT_STATUS_CONNECTION_RESET\n",
11617 nt_errstr(status));
11618 return false;
11621 TALLOC_FREE(conn);
11623 printf("starting ignore bad negprot\n");
11625 return true;
11628 static double create_procs(bool (*fn)(int), bool *result)
11630 int i, status;
11631 volatile pid_t *child_status;
11632 volatile bool *child_status_out;
11633 int synccount;
11634 int tries = 8;
11635 struct timeval start;
11637 synccount = 0;
11639 child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
11640 if (!child_status) {
11641 printf("Failed to setup shared memory\n");
11642 return -1;
11645 child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
11646 if (!child_status_out) {
11647 printf("Failed to setup result status shared memory\n");
11648 return -1;
11651 for (i = 0; i < torture_nprocs; i++) {
11652 child_status[i] = 0;
11653 child_status_out[i] = True;
11656 start = timeval_current();
11658 for (i=0;i<torture_nprocs;i++) {
11659 procnum = i;
11660 if (fork() == 0) {
11661 pid_t mypid = getpid();
11662 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
11664 slprintf(myname,sizeof(myname),"CLIENT%d", i);
11666 while (1) {
11667 if (torture_open_connection(&current_cli, i)) break;
11668 if (tries-- == 0) {
11669 printf("pid %d failed to start\n", (int)getpid());
11670 _exit(1);
11672 smb_msleep(10);
11675 child_status[i] = getpid();
11677 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
11679 child_status_out[i] = fn(i);
11680 _exit(0);
11684 do {
11685 synccount = 0;
11686 for (i=0;i<torture_nprocs;i++) {
11687 if (child_status[i]) synccount++;
11689 if (synccount == torture_nprocs) break;
11690 smb_msleep(10);
11691 } while (timeval_elapsed(&start) < 30);
11693 if (synccount != torture_nprocs) {
11694 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
11695 *result = False;
11696 return timeval_elapsed(&start);
11699 /* start the client load */
11700 start = timeval_current();
11702 for (i=0;i<torture_nprocs;i++) {
11703 child_status[i] = 0;
11706 printf("%d clients started\n", torture_nprocs);
11708 for (i=0;i<torture_nprocs;i++) {
11709 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
11712 printf("\n");
11714 for (i=0;i<torture_nprocs;i++) {
11715 if (!child_status_out[i]) {
11716 *result = False;
11719 return timeval_elapsed(&start);
11722 #define FLAG_MULTIPROC 1
11724 static struct {
11725 const char *name;
11726 bool (*fn)(int);
11727 unsigned flags;
11728 } torture_ops[] = {
11729 {"FDPASS", run_fdpasstest, 0},
11730 {"LOCK1", run_locktest1, 0},
11731 {"LOCK2", run_locktest2, 0},
11732 {"LOCK3", run_locktest3, 0},
11733 {"LOCK4", run_locktest4, 0},
11734 {"LOCK5", run_locktest5, 0},
11735 {"LOCK6", run_locktest6, 0},
11736 {"LOCK7", run_locktest7, 0},
11737 {"LOCK8", run_locktest8, 0},
11738 {"LOCK9", run_locktest9, 0},
11739 {"UNLINK", run_unlinktest, 0},
11740 {"BROWSE", run_browsetest, 0},
11741 {"ATTR", run_attrtest, 0},
11742 {"TRANS2", run_trans2test, 0},
11743 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
11744 {"TORTURE",run_torture, FLAG_MULTIPROC},
11745 {"RANDOMIPC", run_randomipc, 0},
11746 {"NEGNOWAIT", run_negprot_nowait, 0},
11747 {"NBENCH", run_nbench, 0},
11748 {"NBENCH2", run_nbench2, 0},
11749 {"OPLOCK1", run_oplock1, 0},
11750 {"OPLOCK2", run_oplock2, 0},
11751 {"OPLOCK4", run_oplock4, 0},
11752 {"DIR", run_dirtest, 0},
11753 {"DIR1", run_dirtest1, 0},
11754 {"DIR-CREATETIME", run_dir_createtime, 0},
11755 {"DENY1", torture_denytest1, 0},
11756 {"DENY2", torture_denytest2, 0},
11757 {"TCON", run_tcon_test, 0},
11758 {"TCONDEV", run_tcon_devtype_test, 0},
11759 {"RW1", run_readwritetest, 0},
11760 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
11761 {"RW3", run_readwritelarge, 0},
11762 {"RW-SIGNING", run_readwritelarge_signtest, 0},
11763 {"OPEN", run_opentest, 0},
11764 {"POSIX", run_simple_posix_open_test, 0},
11765 {"POSIX-APPEND", run_posix_append, 0},
11766 {"POSIX-SYMLINK-ACL", run_acl_symlink_test, 0},
11767 {"POSIX-SYMLINK-EA", run_ea_symlink_test, 0},
11768 {"POSIX-STREAM-DELETE", run_posix_stream_delete, 0},
11769 {"POSIX-OFD-LOCK", run_posix_ofd_lock_test, 0},
11770 {"WINDOWS-BAD-SYMLINK", run_symlink_open_test, 0},
11771 {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
11772 {"ASYNC-ECHO", run_async_echo, 0},
11773 { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
11774 { "SHORTNAME-TEST", run_shortname_test, 0},
11775 { "ADDRCHANGE", run_addrchange, 0},
11776 #if 1
11777 {"OPENATTR", run_openattrtest, 0},
11778 #endif
11779 {"XCOPY", run_xcopy, 0},
11780 {"RENAME", run_rename, 0},
11781 {"RENAME-ACCESS", run_rename_access, 0},
11782 {"OWNER-RIGHTS", run_owner_rights, 0},
11783 {"DELETE", run_deletetest, 0},
11784 {"DELETE-PRINT", run_delete_print_test, 0},
11785 {"WILDDELETE", run_wild_deletetest, 0},
11786 {"DELETE-LN", run_deletetest_ln, 0},
11787 {"PROPERTIES", run_properties, 0},
11788 {"MANGLE", torture_mangle, 0},
11789 {"MANGLE1", run_mangle1, 0},
11790 {"MANGLE-ILLEGAL", run_mangle_illegal, 0},
11791 {"W2K", run_w2ktest, 0},
11792 {"TRANS2SCAN", torture_trans2_scan, 0},
11793 {"NTTRANSSCAN", torture_nttrans_scan, 0},
11794 {"UTABLE", torture_utable, 0},
11795 {"CASETABLE", torture_casetable, 0},
11796 {"ERRMAPEXTRACT", run_error_map_extract, 0},
11797 {"PIPE_NUMBER", run_pipe_number, 0},
11798 {"TCON2", run_tcon2_test, 0},
11799 {"IOCTL", torture_ioctl_test, 0},
11800 {"CHKPATH", torture_chkpath_test, 0},
11801 {"FDSESS", run_fdsesstest, 0},
11802 { "EATEST", run_eatest, 0},
11803 { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
11804 { "CHAIN1", run_chain1, 0},
11805 { "CHAIN2", run_chain2, 0},
11806 { "CHAIN3", run_chain3, 0},
11807 { "WINDOWS-WRITE", run_windows_write, 0},
11808 { "LARGE_READX", run_large_readx, 0},
11809 { "NTTRANS-CREATE", run_nttrans_create, 0},
11810 { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
11811 { "CLI_ECHO", run_cli_echo, 0},
11812 { "CLI_SPLICE", run_cli_splice, 0},
11813 { "TLDAP", run_tldap },
11814 { "STREAMERROR", run_streamerror },
11815 { "NOTIFY-BENCH", run_notify_bench },
11816 { "NOTIFY-BENCH2", run_notify_bench2 },
11817 { "NOTIFY-BENCH3", run_notify_bench3 },
11818 { "BAD-NBT-SESSION", run_bad_nbt_session },
11819 { "IGN-BAD-NEGPROT", run_ign_bad_negprot },
11820 { "SMB-ANY-CONNECT", run_smb_any_connect },
11821 { "NOTIFY-ONLINE", run_notify_online },
11822 { "SMB2-BASIC", run_smb2_basic },
11823 { "SMB2-NEGPROT", run_smb2_negprot },
11824 { "SMB2-ANONYMOUS", run_smb2_anonymous },
11825 { "SMB2-SESSION-RECONNECT", run_smb2_session_reconnect },
11826 { "SMB2-TCON-DEPENDENCE", run_smb2_tcon_dependence },
11827 { "SMB2-MULTI-CHANNEL", run_smb2_multi_channel },
11828 { "SMB2-SESSION-REAUTH", run_smb2_session_reauth },
11829 { "SMB2-FTRUNCATE", run_smb2_ftruncate },
11830 { "SMB2-DIR-FSYNC", run_smb2_dir_fsync },
11831 { "CLEANUP1", run_cleanup1 },
11832 { "CLEANUP2", run_cleanup2 },
11833 { "CLEANUP3", run_cleanup3 },
11834 { "CLEANUP4", run_cleanup4 },
11835 { "OPLOCK-CANCEL", run_oplock_cancel },
11836 { "PIDHIGH", run_pidhigh },
11837 { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
11838 { "LOCAL-GENCACHE", run_local_gencache, 0},
11839 { "LOCAL-DBWRAP-WATCH1", run_dbwrap_watch1, 0 },
11840 { "LOCAL-DBWRAP-WATCH2", run_dbwrap_watch2, 0 },
11841 { "LOCAL-DBWRAP-DO-LOCKED1", run_dbwrap_do_locked1, 0 },
11842 { "LOCAL-MESSAGING-READ1", run_messaging_read1, 0 },
11843 { "LOCAL-MESSAGING-READ2", run_messaging_read2, 0 },
11844 { "LOCAL-MESSAGING-READ3", run_messaging_read3, 0 },
11845 { "LOCAL-MESSAGING-READ4", run_messaging_read4, 0 },
11846 { "LOCAL-MESSAGING-FDPASS1", run_messaging_fdpass1, 0 },
11847 { "LOCAL-MESSAGING-FDPASS2", run_messaging_fdpass2, 0 },
11848 { "LOCAL-MESSAGING-FDPASS2a", run_messaging_fdpass2a, 0 },
11849 { "LOCAL-MESSAGING-FDPASS2b", run_messaging_fdpass2b, 0 },
11850 { "LOCAL-MESSAGING-SEND-ALL", run_messaging_send_all, 0 },
11851 { "LOCAL-BASE64", run_local_base64, 0},
11852 { "LOCAL-RBTREE", run_local_rbtree, 0},
11853 { "LOCAL-MEMCACHE", run_local_memcache, 0},
11854 { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
11855 { "WBCLIENT-MULTI-PING", run_wbclient_multi_ping, 0},
11856 { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
11857 { "LOCAL-sid_to_string", run_local_sid_to_string, 0},
11858 { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
11859 { "LOCAL-DBTRANS", run_local_dbtrans, 0},
11860 { "LOCAL-TEVENT-POLL", run_local_tevent_poll, 0},
11861 { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
11862 { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
11863 { "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0},
11864 { "LOCAL-IDMAP-TDB-COMMON", run_idmap_tdb_common_test, 0},
11865 { "LOCAL-remove_duplicate_addrs2", run_local_remove_duplicate_addrs2, 0},
11866 { "local-tdb-opener", run_local_tdb_opener, 0 },
11867 { "local-tdb-writer", run_local_tdb_writer, 0 },
11868 { "LOCAL-DBWRAP-CTDB", run_local_dbwrap_ctdb, 0 },
11869 { "LOCAL-BENCH-PTHREADPOOL", run_bench_pthreadpool, 0 },
11870 { "LOCAL-PTHREADPOOL-TEVENT", run_pthreadpool_tevent, 0 },
11871 { "LOCAL-G-LOCK1", run_g_lock1, 0 },
11872 { "LOCAL-G-LOCK2", run_g_lock2, 0 },
11873 { "LOCAL-G-LOCK3", run_g_lock3, 0 },
11874 { "LOCAL-G-LOCK4", run_g_lock4, 0 },
11875 { "LOCAL-G-LOCK5", run_g_lock5, 0 },
11876 { "LOCAL-G-LOCK6", run_g_lock6, 0 },
11877 { "LOCAL-G-LOCK-PING-PONG", run_g_lock_ping_pong, 0 },
11878 { "LOCAL-CANONICALIZE-PATH", run_local_canonicalize_path, 0 },
11879 { "LOCAL-NAMEMAP-CACHE1", run_local_namemap_cache1, 0 },
11880 { "qpathinfo-bufsize", run_qpathinfo_bufsize, 0 },
11881 { "hide-new-files-timeout", run_hidenewfiles, 0 },
11882 {NULL, NULL, 0}};
11884 /****************************************************************************
11885 run a specified test or "ALL"
11886 ****************************************************************************/
11887 static bool run_test(const char *name)
11889 bool ret = True;
11890 bool result = True;
11891 bool found = False;
11892 int i;
11893 double t;
11894 if (strequal(name,"ALL")) {
11895 for (i=0;torture_ops[i].name;i++) {
11896 run_test(torture_ops[i].name);
11898 found = True;
11901 for (i=0;torture_ops[i].name;i++) {
11902 fstr_sprintf(randomfname, "\\XX%x",
11903 (unsigned)random());
11905 if (strequal(name, torture_ops[i].name)) {
11906 found = True;
11907 printf("Running %s\n", name);
11908 if (torture_ops[i].flags & FLAG_MULTIPROC) {
11909 t = create_procs(torture_ops[i].fn, &result);
11910 if (!result) {
11911 ret = False;
11912 printf("TEST %s FAILED!\n", name);
11914 } else {
11915 struct timeval start;
11916 start = timeval_current();
11917 if (!torture_ops[i].fn(0)) {
11918 ret = False;
11919 printf("TEST %s FAILED!\n", name);
11921 t = timeval_elapsed(&start);
11923 printf("%s took %g secs\n\n", name, t);
11927 if (!found) {
11928 printf("Did not find a test named %s\n", name);
11929 ret = False;
11932 return ret;
11936 static void usage(void)
11938 int i;
11940 printf("WARNING samba4 test suite is much more complete nowadays.\n");
11941 printf("Please use samba4 torture.\n\n");
11943 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
11945 printf("\t-d debuglevel\n");
11946 printf("\t-U user%%pass\n");
11947 printf("\t-k use kerberos\n");
11948 printf("\t-N numprocs\n");
11949 printf("\t-n my_netbios_name\n");
11950 printf("\t-W workgroup\n");
11951 printf("\t-o num_operations\n");
11952 printf("\t-O socket_options\n");
11953 printf("\t-m maximum protocol\n");
11954 printf("\t-L use oplocks\n");
11955 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
11956 printf("\t-A showall\n");
11957 printf("\t-p port\n");
11958 printf("\t-s seed\n");
11959 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
11960 printf("\t-f filename filename to test\n");
11961 printf("\t-e encrypt\n");
11962 printf("\n\n");
11964 printf("tests are:");
11965 for (i=0;torture_ops[i].name;i++) {
11966 printf(" %s", torture_ops[i].name);
11968 printf("\n");
11970 printf("default test is ALL\n");
11972 exit(1);
11975 /****************************************************************************
11976 main program
11977 ****************************************************************************/
11978 int main(int argc,char *argv[])
11980 int opt, i;
11981 char *p;
11982 int gotuser = 0;
11983 int gotpass = 0;
11984 bool correct = True;
11985 TALLOC_CTX *frame = talloc_stackframe();
11986 int seed = time(NULL);
11988 #ifdef HAVE_SETBUFFER
11989 setbuffer(stdout, NULL, 0);
11990 #endif
11992 setup_logging("smbtorture", DEBUG_STDOUT);
11994 smb_init_locale();
11995 fault_setup();
11997 if (is_default_dyn_CONFIGFILE()) {
11998 if(getenv("SMB_CONF_PATH")) {
11999 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
12002 lp_load_global(get_dyn_CONFIGFILE());
12003 load_interfaces();
12005 if (argc < 2) {
12006 usage();
12009 for(p = argv[1]; *p; p++)
12010 if(*p == '\\')
12011 *p = '/';
12013 if (strncmp(argv[1], "//", 2)) {
12014 usage();
12017 fstrcpy(host, &argv[1][2]);
12018 p = strchr_m(&host[2],'/');
12019 if (!p) {
12020 usage();
12022 *p = 0;
12023 fstrcpy(share, p+1);
12025 fstrcpy(myname, get_myname(talloc_tos()));
12026 if (!*myname) {
12027 fprintf(stderr, "Failed to get my hostname.\n");
12028 return 1;
12031 if (*username == 0 && getenv("LOGNAME")) {
12032 fstrcpy(username,getenv("LOGNAME"));
12035 argc--;
12036 argv++;
12038 fstrcpy(workgroup, lp_workgroup());
12040 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
12041 != EOF) {
12042 switch (opt) {
12043 case 'p':
12044 port_to_use = atoi(optarg);
12045 break;
12046 case 's':
12047 seed = atoi(optarg);
12048 break;
12049 case 'W':
12050 fstrcpy(workgroup,optarg);
12051 break;
12052 case 'm':
12053 lp_set_cmdline("client max protocol", optarg);
12054 break;
12055 case 'N':
12056 torture_nprocs = atoi(optarg);
12057 break;
12058 case 'o':
12059 torture_numops = atoi(optarg);
12060 break;
12061 case 'd':
12062 lp_set_cmdline("log level", optarg);
12063 break;
12064 case 'O':
12065 sockops = optarg;
12066 break;
12067 case 'L':
12068 use_oplocks = True;
12069 break;
12070 case 'l':
12071 local_path = optarg;
12072 break;
12073 case 'A':
12074 torture_showall = True;
12075 break;
12076 case 'n':
12077 fstrcpy(myname, optarg);
12078 break;
12079 case 'c':
12080 client_txt = optarg;
12081 break;
12082 case 'e':
12083 do_encrypt = true;
12084 break;
12085 case 'k':
12086 #ifdef HAVE_KRB5
12087 use_kerberos = True;
12088 #else
12089 d_printf("No kerberos support compiled in\n");
12090 exit(1);
12091 #endif
12092 break;
12093 case 'U':
12094 gotuser = 1;
12095 fstrcpy(username,optarg);
12096 p = strchr_m(username,'%');
12097 if (p) {
12098 *p = 0;
12099 fstrcpy(password, p+1);
12100 gotpass = 1;
12102 break;
12103 case 'b':
12104 fstrcpy(multishare_conn_fname, optarg);
12105 use_multishare_conn = True;
12106 break;
12107 case 'B':
12108 torture_blocksize = atoi(optarg);
12109 break;
12110 case 'f':
12111 test_filename = SMB_STRDUP(optarg);
12112 break;
12113 default:
12114 printf("Unknown option %c (%d)\n", (char)opt, opt);
12115 usage();
12119 d_printf("using seed %d\n", seed);
12121 srandom(seed);
12123 if(use_kerberos && !gotuser) gotpass = True;
12125 while (!gotpass) {
12126 char pwd[256] = {0};
12127 int rc;
12129 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
12130 if (rc == 0) {
12131 fstrcpy(password, pwd);
12132 gotpass = 1;
12136 printf("host=%s share=%s user=%s myname=%s\n",
12137 host, share, username, myname);
12139 torture_creds = cli_session_creds_init(frame,
12140 username,
12141 workgroup,
12142 NULL, /* realm */
12143 password,
12144 use_kerberos,
12145 false, /* fallback_after_kerberos */
12146 false, /* use_ccache */
12147 false); /* password_is_nt_hash */
12148 if (torture_creds == NULL) {
12149 d_printf("cli_session_creds_init() failed.\n");
12150 exit(1);
12153 if (argc == optind) {
12154 correct = run_test("ALL");
12155 } else {
12156 for (i=optind;i<argc;i++) {
12157 if (!run_test(argv[i])) {
12158 correct = False;
12163 TALLOC_FREE(frame);
12165 if (correct) {
12166 return(0);
12167 } else {
12168 return(1);