CVE-2015-7560: s3: torture3: Add new POSIX-SYMLINK-ACL test.
[Samba.git] / source3 / torture / torture.c
blobf1ea7b05ea2e7ef393b2f2f369e5d11a9c79b374
1 /*
2 Unix SMB/CIFS implementation.
3 SMB torture tester
4 Copyright (C) Andrew Tridgell 1997-1998
5 Copyright (C) Jeremy Allison 2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "system/shmem.h"
23 #include "wbc_async.h"
24 #include "torture/proto.h"
25 #include "libcli/security/security.h"
26 #include "tldap.h"
27 #include "tldap_util.h"
28 #include "../librpc/gen_ndr/svcctl.h"
29 #include "../lib/util/memcache.h"
30 #include "nsswitch/winbind_client.h"
31 #include "dbwrap/dbwrap.h"
32 #include "dbwrap/dbwrap_open.h"
33 #include "dbwrap/dbwrap_rbt.h"
34 #include "talloc_dict.h"
35 #include "async_smb.h"
36 #include "libsmb/libsmb.h"
37 #include "libsmb/clirap.h"
38 #include "trans2.h"
39 #include "libsmb/nmblib.h"
40 #include "../lib/util/tevent_ntstatus.h"
41 #include "util_tdb.h"
42 #include "../libcli/smb/read_smb.h"
43 #include "../libcli/smb/smbXcli_base.h"
44 #include "lib/sys_rw_data.h"
46 extern char *optarg;
47 extern int optind;
49 fstring host, workgroup, share, password, username, myname;
50 static const char *sockops="TCP_NODELAY";
51 int torture_nprocs=1;
52 static int port_to_use=0;
53 int torture_numops=100;
54 int torture_blocksize=1024*1024;
55 static int procnum; /* records process count number when forking */
56 static struct cli_state *current_cli;
57 static fstring randomfname;
58 static bool use_oplocks;
59 static bool use_level_II_oplocks;
60 static const char *client_txt = "client_oplocks.txt";
61 static bool disable_spnego;
62 static bool use_kerberos;
63 static bool force_dos_errors;
64 static fstring multishare_conn_fname;
65 static bool use_multishare_conn = False;
66 static bool do_encrypt;
67 static const char *local_path = NULL;
68 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
69 char *test_filename;
71 bool torture_showall = False;
73 static double create_procs(bool (*fn)(int), bool *result);
75 /********************************************************************
76 Ensure a connection is encrypted.
77 ********************************************************************/
79 static bool force_cli_encryption(struct cli_state *c,
80 const char *sharename)
82 uint16_t major, minor;
83 uint32_t caplow, caphigh;
84 NTSTATUS status;
86 if (!SERVER_HAS_UNIX_CIFS(c)) {
87 d_printf("Encryption required and "
88 "server that doesn't support "
89 "UNIX extensions - failing connect\n");
90 return false;
93 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
94 &caphigh);
95 if (!NT_STATUS_IS_OK(status)) {
96 d_printf("Encryption required and "
97 "can't get UNIX CIFS extensions "
98 "version from server: %s\n", nt_errstr(status));
99 return false;
102 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
103 d_printf("Encryption required and "
104 "share %s doesn't support "
105 "encryption.\n", sharename);
106 return false;
109 if (c->use_kerberos) {
110 status = cli_gss_smb_encryption_start(c);
111 } else {
112 status = cli_raw_ntlm_smb_encryption_start(c,
113 username,
114 password,
115 workgroup);
118 if (!NT_STATUS_IS_OK(status)) {
119 d_printf("Encryption required and "
120 "setup failed with error %s.\n",
121 nt_errstr(status));
122 return false;
125 return true;
129 static struct cli_state *open_nbt_connection(void)
131 struct cli_state *c;
132 NTSTATUS status;
133 int flags = 0;
135 if (disable_spnego) {
136 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
139 if (use_oplocks) {
140 flags |= CLI_FULL_CONNECTION_OPLOCKS;
143 if (use_level_II_oplocks) {
144 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
147 if (use_kerberos) {
148 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
151 if (force_dos_errors) {
152 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
155 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
156 signing_state, flags, &c);
157 if (!NT_STATUS_IS_OK(status)) {
158 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
159 return NULL;
162 cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
164 return c;
167 /****************************************************************************
168 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
169 ****************************************************************************/
171 static bool cli_bad_session_request(int fd,
172 struct nmb_name *calling, struct nmb_name *called)
174 TALLOC_CTX *frame;
175 uint8_t len_buf[4];
176 struct iovec iov[3];
177 ssize_t len;
178 uint8_t *inbuf;
179 int err;
180 bool ret = false;
181 uint8_t message_type;
182 uint8_t error;
183 struct tevent_context *ev;
184 struct tevent_req *req;
186 frame = talloc_stackframe();
188 iov[0].iov_base = len_buf;
189 iov[0].iov_len = sizeof(len_buf);
191 /* put in the destination name */
193 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
194 called->name_type);
195 if (iov[1].iov_base == NULL) {
196 goto fail;
198 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
199 talloc_get_size(iov[1].iov_base));
201 /* and my name */
203 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
204 calling->name_type);
205 if (iov[2].iov_base == NULL) {
206 goto fail;
208 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
209 talloc_get_size(iov[2].iov_base));
211 /* Deliberately corrupt the name len (first byte) */
212 *((uint8_t *)iov[2].iov_base) = 100;
214 /* send a session request (RFC 1002) */
215 /* setup the packet length
216 * Remove four bytes from the length count, since the length
217 * field in the NBT Session Service header counts the number
218 * of bytes which follow. The cli_send_smb() function knows
219 * about this and accounts for those four bytes.
220 * CRH.
223 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
224 SCVAL(len_buf,0,0x81);
226 len = write_data_iov(fd, iov, 3);
227 if (len == -1) {
228 goto fail;
231 ev = samba_tevent_context_init(frame);
232 if (ev == NULL) {
233 goto fail;
235 req = read_smb_send(frame, ev, fd);
236 if (req == NULL) {
237 goto fail;
239 if (!tevent_req_poll(req, ev)) {
240 goto fail;
242 len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
243 if (len == -1) {
244 errno = err;
245 goto fail;
247 TALLOC_FREE(ev);
249 message_type = CVAL(inbuf, 0);
250 if (message_type != 0x83) {
251 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
252 message_type);
253 goto fail;
256 if (smb_len(inbuf) != 1) {
257 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
258 (int)smb_len(inbuf));
259 goto fail;
262 error = CVAL(inbuf, 4);
263 if (error != 0x82) {
264 d_fprintf(stderr, "Expected error 0x82, got %d\n",
265 (int)error);
266 goto fail;
269 ret = true;
270 fail:
271 TALLOC_FREE(frame);
272 return ret;
275 /* Insert a NULL at the first separator of the given path and return a pointer
276 * to the remainder of the string.
278 static char *
279 terminate_path_at_separator(char * path)
281 char * p;
283 if (!path) {
284 return NULL;
287 if ((p = strchr_m(path, '/'))) {
288 *p = '\0';
289 return p + 1;
292 if ((p = strchr_m(path, '\\'))) {
293 *p = '\0';
294 return p + 1;
297 /* No separator. */
298 return NULL;
302 parse a //server/share type UNC name
304 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
305 char **hostname, char **sharename)
307 char *p;
309 *hostname = *sharename = NULL;
311 if (strncmp(unc_name, "\\\\", 2) &&
312 strncmp(unc_name, "//", 2)) {
313 return False;
316 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
317 p = terminate_path_at_separator(*hostname);
319 if (p && *p) {
320 *sharename = talloc_strdup(mem_ctx, p);
321 terminate_path_at_separator(*sharename);
324 if (*hostname && *sharename) {
325 return True;
328 TALLOC_FREE(*hostname);
329 TALLOC_FREE(*sharename);
330 return False;
333 static bool torture_open_connection_share(struct cli_state **c,
334 const char *hostname,
335 const char *sharename)
337 int flags = 0;
338 NTSTATUS status;
340 if (use_kerberos)
341 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
342 if (use_oplocks)
343 flags |= CLI_FULL_CONNECTION_OPLOCKS;
344 if (use_level_II_oplocks)
345 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
347 status = cli_full_connection(c, myname,
348 hostname, NULL, port_to_use,
349 sharename, "?????",
350 username, workgroup,
351 password, flags, signing_state);
352 if (!NT_STATUS_IS_OK(status)) {
353 printf("failed to open share connection: //%s/%s port:%d - %s\n",
354 hostname, sharename, port_to_use, nt_errstr(status));
355 return False;
358 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
360 if (do_encrypt) {
361 return force_cli_encryption(*c,
362 sharename);
364 return True;
367 bool torture_open_connection(struct cli_state **c, int conn_index)
369 char **unc_list = NULL;
370 int num_unc_names = 0;
371 bool result;
373 if (use_multishare_conn==True) {
374 char *h, *s;
375 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
376 if (!unc_list || num_unc_names <= 0) {
377 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
378 exit(1);
381 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
382 NULL, &h, &s)) {
383 printf("Failed to parse UNC name %s\n",
384 unc_list[conn_index % num_unc_names]);
385 TALLOC_FREE(unc_list);
386 exit(1);
389 result = torture_open_connection_share(c, h, s);
391 /* h, s were copied earlier */
392 TALLOC_FREE(unc_list);
393 return result;
396 return torture_open_connection_share(c, host, share);
399 bool torture_init_connection(struct cli_state **pcli)
401 struct cli_state *cli;
403 cli = open_nbt_connection();
404 if (cli == NULL) {
405 return false;
408 *pcli = cli;
409 return true;
412 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
414 uint16_t old_vuid = cli_state_get_uid(cli);
415 size_t passlen = strlen(password);
416 NTSTATUS status;
417 bool ret;
419 cli_state_set_uid(cli, 0);
420 status = cli_session_setup(cli, username,
421 password, passlen,
422 password, passlen,
423 workgroup);
424 ret = NT_STATUS_IS_OK(status);
425 *new_vuid = cli_state_get_uid(cli);
426 cli_state_set_uid(cli, old_vuid);
427 return ret;
431 bool torture_close_connection(struct cli_state *c)
433 bool ret = True;
434 NTSTATUS status;
436 status = cli_tdis(c);
437 if (!NT_STATUS_IS_OK(status)) {
438 printf("tdis failed (%s)\n", nt_errstr(status));
439 ret = False;
442 cli_shutdown(c);
444 return ret;
448 /* check if the server produced the expected dos or nt error code */
449 static bool check_both_error(int line, NTSTATUS status,
450 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
452 if (NT_STATUS_IS_DOS(status)) {
453 uint8_t cclass;
454 uint32_t num;
456 /* Check DOS error */
457 cclass = NT_STATUS_DOS_CLASS(status);
458 num = NT_STATUS_DOS_CODE(status);
460 if (eclass != cclass || ecode != num) {
461 printf("unexpected error code class=%d code=%d\n",
462 (int)cclass, (int)num);
463 printf(" expected %d/%d %s (line=%d)\n",
464 (int)eclass, (int)ecode, nt_errstr(nterr), line);
465 return false;
467 } else {
468 /* Check NT error */
469 if (!NT_STATUS_EQUAL(nterr, status)) {
470 printf("unexpected error code %s\n",
471 nt_errstr(status));
472 printf(" expected %s (line=%d)\n",
473 nt_errstr(nterr), line);
474 return false;
478 return true;
482 /* check if the server produced the expected error code */
483 static bool check_error(int line, NTSTATUS status,
484 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
486 if (NT_STATUS_IS_DOS(status)) {
487 uint8_t cclass;
488 uint32_t num;
490 /* Check DOS error */
492 cclass = NT_STATUS_DOS_CLASS(status);
493 num = NT_STATUS_DOS_CODE(status);
495 if (eclass != cclass || ecode != num) {
496 printf("unexpected error code class=%d code=%d\n",
497 (int)cclass, (int)num);
498 printf(" expected %d/%d %s (line=%d)\n",
499 (int)eclass, (int)ecode, nt_errstr(nterr),
500 line);
501 return False;
504 } else {
505 /* Check NT error */
507 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
508 printf("unexpected error code %s\n",
509 nt_errstr(status));
510 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
511 line);
512 return False;
516 return True;
520 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
522 NTSTATUS status;
524 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
526 while (!NT_STATUS_IS_OK(status)) {
527 if (!check_both_error(__LINE__, status, ERRDOS,
528 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
529 return false;
532 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
535 return true;
539 static bool rw_torture(struct cli_state *c)
541 const char *lockfname = "\\torture.lck";
542 fstring fname;
543 uint16_t fnum;
544 uint16_t fnum2;
545 pid_t pid2, pid = getpid();
546 int i, j;
547 char buf[1024];
548 bool correct = True;
549 size_t nread = 0;
550 NTSTATUS status;
552 memset(buf, '\0', sizeof(buf));
554 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
555 DENY_NONE, &fnum2);
556 if (!NT_STATUS_IS_OK(status)) {
557 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
559 if (!NT_STATUS_IS_OK(status)) {
560 printf("open of %s failed (%s)\n",
561 lockfname, nt_errstr(status));
562 return False;
565 for (i=0;i<torture_numops;i++) {
566 unsigned n = (unsigned)sys_random()%10;
568 if (i % 10 == 0) {
569 printf("%d\r", i); fflush(stdout);
571 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
573 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
574 return False;
577 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
578 DENY_ALL, &fnum);
579 if (!NT_STATUS_IS_OK(status)) {
580 printf("open failed (%s)\n", nt_errstr(status));
581 correct = False;
582 break;
585 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
586 sizeof(pid), NULL);
587 if (!NT_STATUS_IS_OK(status)) {
588 printf("write failed (%s)\n", nt_errstr(status));
589 correct = False;
592 for (j=0;j<50;j++) {
593 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
594 sizeof(pid)+(j*sizeof(buf)),
595 sizeof(buf), NULL);
596 if (!NT_STATUS_IS_OK(status)) {
597 printf("write failed (%s)\n",
598 nt_errstr(status));
599 correct = False;
603 pid2 = 0;
605 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
606 &nread);
607 if (!NT_STATUS_IS_OK(status)) {
608 printf("read failed (%s)\n", nt_errstr(status));
609 correct = false;
610 } else if (nread != sizeof(pid)) {
611 printf("read/write compare failed: "
612 "recv %ld req %ld\n", (unsigned long)nread,
613 (unsigned long)sizeof(pid));
614 correct = false;
617 if (pid2 != pid) {
618 printf("data corruption!\n");
619 correct = False;
622 status = cli_close(c, fnum);
623 if (!NT_STATUS_IS_OK(status)) {
624 printf("close failed (%s)\n", nt_errstr(status));
625 correct = False;
628 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
629 if (!NT_STATUS_IS_OK(status)) {
630 printf("unlink failed (%s)\n", nt_errstr(status));
631 correct = False;
634 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
635 if (!NT_STATUS_IS_OK(status)) {
636 printf("unlock failed (%s)\n", nt_errstr(status));
637 correct = False;
641 cli_close(c, fnum2);
642 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
644 printf("%d\n", i);
646 return correct;
649 static bool run_torture(int dummy)
651 struct cli_state *cli;
652 bool ret;
654 cli = current_cli;
656 smbXcli_conn_set_sockopt(cli->conn, sockops);
658 ret = rw_torture(cli);
660 if (!torture_close_connection(cli)) {
661 ret = False;
664 return ret;
667 static bool rw_torture3(struct cli_state *c, char *lockfname)
669 uint16_t fnum = (uint16_t)-1;
670 unsigned int i = 0;
671 char buf[131072];
672 char buf_rd[131072];
673 unsigned count;
674 unsigned countprev = 0;
675 size_t sent = 0;
676 bool correct = True;
677 NTSTATUS status = NT_STATUS_OK;
679 srandom(1);
680 for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
682 SIVAL(buf, i, sys_random());
685 if (procnum == 0)
687 status = cli_unlink(
688 c, lockfname,
689 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
690 if (!NT_STATUS_IS_OK(status)) {
691 printf("unlink failed (%s) (normal, this file should "
692 "not exist)\n", nt_errstr(status));
695 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
696 DENY_NONE, &fnum);
697 if (!NT_STATUS_IS_OK(status)) {
698 printf("first open read/write of %s failed (%s)\n",
699 lockfname, nt_errstr(status));
700 return False;
703 else
705 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
707 status = cli_openx(c, lockfname, O_RDONLY,
708 DENY_NONE, &fnum);
709 if (NT_STATUS_IS_OK(status)) {
710 break;
712 smb_msleep(10);
714 if (!NT_STATUS_IS_OK(status)) {
715 printf("second open read-only of %s failed (%s)\n",
716 lockfname, nt_errstr(status));
717 return False;
721 i = 0;
722 for (count = 0; count < sizeof(buf); count += sent)
724 if (count >= countprev) {
725 printf("%d %8d\r", i, count);
726 fflush(stdout);
727 i++;
728 countprev += (sizeof(buf) / 20);
731 if (procnum == 0)
733 sent = ((unsigned)sys_random()%(20))+ 1;
734 if (sent > sizeof(buf) - count)
736 sent = sizeof(buf) - count;
739 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
740 count, sent, NULL);
741 if (!NT_STATUS_IS_OK(status)) {
742 printf("write failed (%s)\n",
743 nt_errstr(status));
744 correct = False;
747 else
749 status = cli_read(c, fnum, buf_rd+count, count,
750 sizeof(buf)-count, &sent);
751 if(!NT_STATUS_IS_OK(status)) {
752 printf("read failed offset:%d size:%ld (%s)\n",
753 count, (unsigned long)sizeof(buf)-count,
754 nt_errstr(status));
755 correct = False;
756 sent = 0;
757 } else if (sent > 0) {
758 if (memcmp(buf_rd+count, buf+count, sent) != 0)
760 printf("read/write compare failed\n");
761 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
762 correct = False;
763 break;
770 status = cli_close(c, fnum);
771 if (!NT_STATUS_IS_OK(status)) {
772 printf("close failed (%s)\n", nt_errstr(status));
773 correct = False;
776 return correct;
779 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
781 const char *lockfname = "\\torture2.lck";
782 uint16_t fnum1;
783 uint16_t fnum2;
784 int i;
785 char buf[131072];
786 char buf_rd[131072];
787 bool correct = True;
788 size_t bytes_read;
789 NTSTATUS status;
791 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
792 if (!NT_STATUS_IS_OK(status)) {
793 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
796 status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
797 DENY_NONE, &fnum1);
798 if (!NT_STATUS_IS_OK(status)) {
799 printf("first open read/write of %s failed (%s)\n",
800 lockfname, nt_errstr(status));
801 return False;
804 status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
805 if (!NT_STATUS_IS_OK(status)) {
806 printf("second open read-only of %s failed (%s)\n",
807 lockfname, nt_errstr(status));
808 cli_close(c1, fnum1);
809 return False;
812 for (i = 0; i < torture_numops; i++)
814 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
815 if (i % 10 == 0) {
816 printf("%d\r", i); fflush(stdout);
819 generate_random_buffer((unsigned char *)buf, buf_size);
821 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
822 buf_size, NULL);
823 if (!NT_STATUS_IS_OK(status)) {
824 printf("write failed (%s)\n", nt_errstr(status));
825 correct = False;
826 break;
829 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
830 if(!NT_STATUS_IS_OK(status)) {
831 printf("read failed (%s)\n", nt_errstr(status));
832 correct = false;
833 break;
834 } else if (bytes_read != buf_size) {
835 printf("read failed\n");
836 printf("read %ld, expected %ld\n",
837 (unsigned long)bytes_read,
838 (unsigned long)buf_size);
839 correct = False;
840 break;
843 if (memcmp(buf_rd, buf, buf_size) != 0)
845 printf("read/write compare failed\n");
846 correct = False;
847 break;
851 status = cli_close(c2, fnum2);
852 if (!NT_STATUS_IS_OK(status)) {
853 printf("close failed (%s)\n", nt_errstr(status));
854 correct = False;
857 status = cli_close(c1, fnum1);
858 if (!NT_STATUS_IS_OK(status)) {
859 printf("close failed (%s)\n", nt_errstr(status));
860 correct = False;
863 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
864 if (!NT_STATUS_IS_OK(status)) {
865 printf("unlink failed (%s)\n", nt_errstr(status));
866 correct = False;
869 return correct;
872 static bool run_readwritetest(int dummy)
874 struct cli_state *cli1, *cli2;
875 bool test1, test2 = False;
877 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
878 return False;
880 smbXcli_conn_set_sockopt(cli1->conn, sockops);
881 smbXcli_conn_set_sockopt(cli2->conn, sockops);
883 printf("starting readwritetest\n");
885 test1 = rw_torture2(cli1, cli2);
886 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
888 if (test1) {
889 test2 = rw_torture2(cli1, cli1);
890 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
893 if (!torture_close_connection(cli1)) {
894 test1 = False;
897 if (!torture_close_connection(cli2)) {
898 test2 = False;
901 return (test1 && test2);
904 static bool run_readwritemulti(int dummy)
906 struct cli_state *cli;
907 bool test;
909 cli = current_cli;
911 smbXcli_conn_set_sockopt(cli->conn, sockops);
913 printf("run_readwritemulti: fname %s\n", randomfname);
914 test = rw_torture3(cli, randomfname);
916 if (!torture_close_connection(cli)) {
917 test = False;
920 return test;
923 static bool run_readwritelarge_internal(void)
925 static struct cli_state *cli1;
926 uint16_t fnum1;
927 const char *lockfname = "\\large.dat";
928 off_t fsize;
929 char buf[126*1024];
930 bool correct = True;
931 NTSTATUS status;
933 if (!torture_open_connection(&cli1, 0)) {
934 return False;
936 smbXcli_conn_set_sockopt(cli1->conn, sockops);
937 memset(buf,'\0',sizeof(buf));
939 printf("starting readwritelarge_internal\n");
941 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
943 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
944 DENY_NONE, &fnum1);
945 if (!NT_STATUS_IS_OK(status)) {
946 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
947 return False;
950 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
952 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
953 NULL, NULL, NULL);
954 if (!NT_STATUS_IS_OK(status)) {
955 printf("qfileinfo failed (%s)\n", nt_errstr(status));
956 correct = False;
959 if (fsize == sizeof(buf))
960 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
961 (unsigned long)fsize);
962 else {
963 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
964 (unsigned long)fsize);
965 correct = False;
968 status = cli_close(cli1, fnum1);
969 if (!NT_STATUS_IS_OK(status)) {
970 printf("close failed (%s)\n", nt_errstr(status));
971 correct = False;
974 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
975 if (!NT_STATUS_IS_OK(status)) {
976 printf("unlink failed (%s)\n", nt_errstr(status));
977 correct = False;
980 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
981 DENY_NONE, &fnum1);
982 if (!NT_STATUS_IS_OK(status)) {
983 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
984 return False;
987 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
989 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
990 NULL, NULL, NULL);
991 if (!NT_STATUS_IS_OK(status)) {
992 printf("qfileinfo failed (%s)\n", nt_errstr(status));
993 correct = False;
996 if (fsize == sizeof(buf))
997 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
998 (unsigned long)fsize);
999 else {
1000 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1001 (unsigned long)fsize);
1002 correct = False;
1005 #if 0
1006 /* ToDo - set allocation. JRA */
1007 if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1008 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1009 return False;
1011 if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1012 NULL, NULL)) {
1013 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1014 correct = False;
1016 if (fsize != 0)
1017 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1018 #endif
1020 status = cli_close(cli1, fnum1);
1021 if (!NT_STATUS_IS_OK(status)) {
1022 printf("close failed (%s)\n", nt_errstr(status));
1023 correct = False;
1026 if (!torture_close_connection(cli1)) {
1027 correct = False;
1029 return correct;
1032 static bool run_readwritelarge(int dummy)
1034 return run_readwritelarge_internal();
1037 static bool run_readwritelarge_signtest(int dummy)
1039 bool ret;
1040 signing_state = SMB_SIGNING_REQUIRED;
1041 ret = run_readwritelarge_internal();
1042 signing_state = SMB_SIGNING_DEFAULT;
1043 return ret;
1046 int line_count = 0;
1047 int nbio_id;
1049 #define ival(s) strtol(s, NULL, 0)
1051 /* run a test that simulates an approximate netbench client load */
1052 static bool run_netbench(int client)
1054 struct cli_state *cli;
1055 int i;
1056 char line[1024];
1057 char cname[20];
1058 FILE *f;
1059 const char *params[20];
1060 bool correct = True;
1062 cli = current_cli;
1064 nbio_id = client;
1066 smbXcli_conn_set_sockopt(cli->conn, sockops);
1068 nb_setup(cli);
1070 slprintf(cname,sizeof(cname)-1, "client%d", client);
1072 f = fopen(client_txt, "r");
1074 if (!f) {
1075 perror(client_txt);
1076 return False;
1079 while (fgets(line, sizeof(line)-1, f)) {
1080 char *saveptr;
1081 line_count++;
1083 line[strlen(line)-1] = 0;
1085 /* printf("[%d] %s\n", line_count, line); */
1087 all_string_sub(line,"client1", cname, sizeof(line));
1089 /* parse the command parameters */
1090 params[0] = strtok_r(line, " ", &saveptr);
1091 i = 0;
1092 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1094 params[i] = "";
1096 if (i < 2) continue;
1098 if (!strncmp(params[0],"SMB", 3)) {
1099 printf("ERROR: You are using a dbench 1 load file\n");
1100 exit(1);
1103 if (!strcmp(params[0],"NTCreateX")) {
1104 nb_createx(params[1], ival(params[2]), ival(params[3]),
1105 ival(params[4]));
1106 } else if (!strcmp(params[0],"Close")) {
1107 nb_close(ival(params[1]));
1108 } else if (!strcmp(params[0],"Rename")) {
1109 nb_rename(params[1], params[2]);
1110 } else if (!strcmp(params[0],"Unlink")) {
1111 nb_unlink(params[1]);
1112 } else if (!strcmp(params[0],"Deltree")) {
1113 nb_deltree(params[1]);
1114 } else if (!strcmp(params[0],"Rmdir")) {
1115 nb_rmdir(params[1]);
1116 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1117 nb_qpathinfo(params[1]);
1118 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1119 nb_qfileinfo(ival(params[1]));
1120 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1121 nb_qfsinfo(ival(params[1]));
1122 } else if (!strcmp(params[0],"FIND_FIRST")) {
1123 nb_findfirst(params[1]);
1124 } else if (!strcmp(params[0],"WriteX")) {
1125 nb_writex(ival(params[1]),
1126 ival(params[2]), ival(params[3]), ival(params[4]));
1127 } else if (!strcmp(params[0],"ReadX")) {
1128 nb_readx(ival(params[1]),
1129 ival(params[2]), ival(params[3]), ival(params[4]));
1130 } else if (!strcmp(params[0],"Flush")) {
1131 nb_flush(ival(params[1]));
1132 } else {
1133 printf("Unknown operation %s\n", params[0]);
1134 exit(1);
1137 fclose(f);
1139 nb_cleanup();
1141 if (!torture_close_connection(cli)) {
1142 correct = False;
1145 return correct;
1149 /* run a test that simulates an approximate netbench client load */
1150 static bool run_nbench(int dummy)
1152 double t;
1153 bool correct = True;
1155 nbio_shmem(torture_nprocs);
1157 nbio_id = -1;
1159 signal(SIGALRM, nb_alarm);
1160 alarm(1);
1161 t = create_procs(run_netbench, &correct);
1162 alarm(0);
1164 printf("\nThroughput %g MB/sec\n",
1165 1.0e-6 * nbio_total() / t);
1166 return correct;
1171 This test checks for two things:
1173 1) correct support for retaining locks over a close (ie. the server
1174 must not use posix semantics)
1175 2) support for lock timeouts
1177 static bool run_locktest1(int dummy)
1179 struct cli_state *cli1, *cli2;
1180 const char *fname = "\\lockt1.lck";
1181 uint16_t fnum1, fnum2, fnum3;
1182 time_t t1, t2;
1183 unsigned lock_timeout;
1184 NTSTATUS status;
1186 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1187 return False;
1189 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1190 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1192 printf("starting locktest1\n");
1194 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1196 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1197 &fnum1);
1198 if (!NT_STATUS_IS_OK(status)) {
1199 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1200 return False;
1203 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1204 if (!NT_STATUS_IS_OK(status)) {
1205 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1206 return False;
1209 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1210 if (!NT_STATUS_IS_OK(status)) {
1211 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1212 return False;
1215 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1216 if (!NT_STATUS_IS_OK(status)) {
1217 printf("lock1 failed (%s)\n", nt_errstr(status));
1218 return false;
1221 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1222 if (NT_STATUS_IS_OK(status)) {
1223 printf("lock2 succeeded! This is a locking bug\n");
1224 return false;
1225 } else {
1226 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1227 NT_STATUS_LOCK_NOT_GRANTED)) {
1228 return false;
1232 lock_timeout = (1 + (random() % 20));
1233 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1234 t1 = time(NULL);
1235 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1236 if (NT_STATUS_IS_OK(status)) {
1237 printf("lock3 succeeded! This is a locking bug\n");
1238 return false;
1239 } else {
1240 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1241 NT_STATUS_FILE_LOCK_CONFLICT)) {
1242 return false;
1245 t2 = time(NULL);
1247 if (ABS(t2 - t1) < lock_timeout-1) {
1248 printf("error: This server appears not to support timed lock requests\n");
1251 printf("server slept for %u seconds for a %u second timeout\n",
1252 (unsigned int)(t2-t1), lock_timeout);
1254 status = cli_close(cli1, fnum2);
1255 if (!NT_STATUS_IS_OK(status)) {
1256 printf("close1 failed (%s)\n", nt_errstr(status));
1257 return False;
1260 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1261 if (NT_STATUS_IS_OK(status)) {
1262 printf("lock4 succeeded! This is a locking bug\n");
1263 return false;
1264 } else {
1265 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1266 NT_STATUS_FILE_LOCK_CONFLICT)) {
1267 return false;
1271 status = cli_close(cli1, fnum1);
1272 if (!NT_STATUS_IS_OK(status)) {
1273 printf("close2 failed (%s)\n", nt_errstr(status));
1274 return False;
1277 status = cli_close(cli2, fnum3);
1278 if (!NT_STATUS_IS_OK(status)) {
1279 printf("close3 failed (%s)\n", nt_errstr(status));
1280 return False;
1283 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1284 if (!NT_STATUS_IS_OK(status)) {
1285 printf("unlink failed (%s)\n", nt_errstr(status));
1286 return False;
1290 if (!torture_close_connection(cli1)) {
1291 return False;
1294 if (!torture_close_connection(cli2)) {
1295 return False;
1298 printf("Passed locktest1\n");
1299 return True;
1303 this checks to see if a secondary tconx can use open files from an
1304 earlier tconx
1306 static bool run_tcon_test(int dummy)
1308 static struct cli_state *cli;
1309 const char *fname = "\\tcontest.tmp";
1310 uint16_t fnum1;
1311 uint16_t cnum1, cnum2, cnum3;
1312 uint16_t vuid1, vuid2;
1313 char buf[4];
1314 bool ret = True;
1315 NTSTATUS status;
1317 memset(buf, '\0', sizeof(buf));
1319 if (!torture_open_connection(&cli, 0)) {
1320 return False;
1322 smbXcli_conn_set_sockopt(cli->conn, sockops);
1324 printf("starting tcontest\n");
1326 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1328 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1329 if (!NT_STATUS_IS_OK(status)) {
1330 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1331 return False;
1334 cnum1 = cli_state_get_tid(cli);
1335 vuid1 = cli_state_get_uid(cli);
1337 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1338 if (!NT_STATUS_IS_OK(status)) {
1339 printf("initial write failed (%s)", nt_errstr(status));
1340 return False;
1343 status = cli_tree_connect(cli, share, "?????",
1344 password, strlen(password)+1);
1345 if (!NT_STATUS_IS_OK(status)) {
1346 printf("%s refused 2nd tree connect (%s)\n", host,
1347 nt_errstr(status));
1348 cli_shutdown(cli);
1349 return False;
1352 cnum2 = cli_state_get_tid(cli);
1353 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1354 vuid2 = cli_state_get_uid(cli) + 1;
1356 /* try a write with the wrong tid */
1357 cli_state_set_tid(cli, cnum2);
1359 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1360 if (NT_STATUS_IS_OK(status)) {
1361 printf("* server allows write with wrong TID\n");
1362 ret = False;
1363 } else {
1364 printf("server fails write with wrong TID : %s\n",
1365 nt_errstr(status));
1369 /* try a write with an invalid tid */
1370 cli_state_set_tid(cli, cnum3);
1372 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1373 if (NT_STATUS_IS_OK(status)) {
1374 printf("* server allows write with invalid TID\n");
1375 ret = False;
1376 } else {
1377 printf("server fails write with invalid TID : %s\n",
1378 nt_errstr(status));
1381 /* try a write with an invalid vuid */
1382 cli_state_set_uid(cli, vuid2);
1383 cli_state_set_tid(cli, cnum1);
1385 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1386 if (NT_STATUS_IS_OK(status)) {
1387 printf("* server allows write with invalid VUID\n");
1388 ret = False;
1389 } else {
1390 printf("server fails write with invalid VUID : %s\n",
1391 nt_errstr(status));
1394 cli_state_set_tid(cli, cnum1);
1395 cli_state_set_uid(cli, vuid1);
1397 status = cli_close(cli, fnum1);
1398 if (!NT_STATUS_IS_OK(status)) {
1399 printf("close failed (%s)\n", nt_errstr(status));
1400 return False;
1403 cli_state_set_tid(cli, cnum2);
1405 status = cli_tdis(cli);
1406 if (!NT_STATUS_IS_OK(status)) {
1407 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1408 return False;
1411 cli_state_set_tid(cli, cnum1);
1413 if (!torture_close_connection(cli)) {
1414 return False;
1417 return ret;
1422 checks for old style tcon support
1424 static bool run_tcon2_test(int dummy)
1426 static struct cli_state *cli;
1427 uint16_t cnum, max_xmit;
1428 char *service;
1429 NTSTATUS status;
1431 if (!torture_open_connection(&cli, 0)) {
1432 return False;
1434 smbXcli_conn_set_sockopt(cli->conn, sockops);
1436 printf("starting tcon2 test\n");
1438 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1439 return false;
1442 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1444 SAFE_FREE(service);
1446 if (!NT_STATUS_IS_OK(status)) {
1447 printf("tcon2 failed : %s\n", nt_errstr(status));
1448 } else {
1449 printf("tcon OK : max_xmit=%d cnum=%d\n",
1450 (int)max_xmit, (int)cnum);
1453 if (!torture_close_connection(cli)) {
1454 return False;
1457 printf("Passed tcon2 test\n");
1458 return True;
1461 static bool tcon_devtest(struct cli_state *cli,
1462 const char *myshare, const char *devtype,
1463 const char *return_devtype,
1464 NTSTATUS expected_error)
1466 NTSTATUS status;
1467 bool ret;
1469 status = cli_tree_connect(cli, myshare, devtype,
1470 password, strlen(password)+1);
1472 if (NT_STATUS_IS_OK(expected_error)) {
1473 if (NT_STATUS_IS_OK(status)) {
1474 if (strcmp(cli->dev, return_devtype) == 0) {
1475 ret = True;
1476 } else {
1477 printf("tconX to share %s with type %s "
1478 "succeeded but returned the wrong "
1479 "device type (got [%s] but should have got [%s])\n",
1480 myshare, devtype, cli->dev, return_devtype);
1481 ret = False;
1483 } else {
1484 printf("tconX to share %s with type %s "
1485 "should have succeeded but failed\n",
1486 myshare, devtype);
1487 ret = False;
1489 cli_tdis(cli);
1490 } else {
1491 if (NT_STATUS_IS_OK(status)) {
1492 printf("tconx to share %s with type %s "
1493 "should have failed but succeeded\n",
1494 myshare, devtype);
1495 ret = False;
1496 } else {
1497 if (NT_STATUS_EQUAL(status, expected_error)) {
1498 ret = True;
1499 } else {
1500 printf("Returned unexpected error\n");
1501 ret = False;
1505 return ret;
1509 checks for correct tconX support
1511 static bool run_tcon_devtype_test(int dummy)
1513 static struct cli_state *cli1 = NULL;
1514 int flags = 0;
1515 NTSTATUS status;
1516 bool ret = True;
1518 status = cli_full_connection(&cli1, myname,
1519 host, NULL, port_to_use,
1520 NULL, NULL,
1521 username, workgroup,
1522 password, flags, signing_state);
1524 if (!NT_STATUS_IS_OK(status)) {
1525 printf("could not open connection\n");
1526 return False;
1529 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1530 ret = False;
1532 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1533 ret = False;
1535 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1536 ret = False;
1538 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1539 ret = False;
1541 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1542 ret = False;
1544 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1545 ret = False;
1547 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1548 ret = False;
1550 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1551 ret = False;
1553 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1554 ret = False;
1556 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1557 ret = False;
1559 cli_shutdown(cli1);
1561 if (ret)
1562 printf("Passed tcondevtest\n");
1564 return ret;
1569 This test checks that
1571 1) the server supports multiple locking contexts on the one SMB
1572 connection, distinguished by PID.
1574 2) the server correctly fails overlapping locks made by the same PID (this
1575 goes against POSIX behaviour, which is why it is tricky to implement)
1577 3) the server denies unlock requests by an incorrect client PID
1579 static bool run_locktest2(int dummy)
1581 static struct cli_state *cli;
1582 const char *fname = "\\lockt2.lck";
1583 uint16_t fnum1, fnum2, fnum3;
1584 bool correct = True;
1585 NTSTATUS status;
1587 if (!torture_open_connection(&cli, 0)) {
1588 return False;
1591 smbXcli_conn_set_sockopt(cli->conn, sockops);
1593 printf("starting locktest2\n");
1595 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1597 cli_setpid(cli, 1);
1599 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1600 if (!NT_STATUS_IS_OK(status)) {
1601 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1602 return False;
1605 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1606 if (!NT_STATUS_IS_OK(status)) {
1607 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1608 return False;
1611 cli_setpid(cli, 2);
1613 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1614 if (!NT_STATUS_IS_OK(status)) {
1615 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1616 return False;
1619 cli_setpid(cli, 1);
1621 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1622 if (!NT_STATUS_IS_OK(status)) {
1623 printf("lock1 failed (%s)\n", nt_errstr(status));
1624 return false;
1627 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1628 if (NT_STATUS_IS_OK(status)) {
1629 printf("WRITE lock1 succeeded! This is a locking bug\n");
1630 correct = false;
1631 } else {
1632 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1633 NT_STATUS_LOCK_NOT_GRANTED)) {
1634 return false;
1638 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1639 if (NT_STATUS_IS_OK(status)) {
1640 printf("WRITE lock2 succeeded! This is a locking bug\n");
1641 correct = false;
1642 } else {
1643 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1644 NT_STATUS_LOCK_NOT_GRANTED)) {
1645 return false;
1649 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1650 if (NT_STATUS_IS_OK(status)) {
1651 printf("READ lock2 succeeded! This is a locking bug\n");
1652 correct = false;
1653 } else {
1654 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1655 NT_STATUS_FILE_LOCK_CONFLICT)) {
1656 return false;
1660 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1661 if (!NT_STATUS_IS_OK(status)) {
1662 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1664 cli_setpid(cli, 2);
1665 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1666 printf("unlock at 100 succeeded! This is a locking bug\n");
1667 correct = False;
1670 status = cli_unlock(cli, fnum1, 0, 4);
1671 if (NT_STATUS_IS_OK(status)) {
1672 printf("unlock1 succeeded! This is a locking bug\n");
1673 correct = false;
1674 } else {
1675 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1676 NT_STATUS_RANGE_NOT_LOCKED)) {
1677 return false;
1681 status = cli_unlock(cli, fnum1, 0, 8);
1682 if (NT_STATUS_IS_OK(status)) {
1683 printf("unlock2 succeeded! This is a locking bug\n");
1684 correct = false;
1685 } else {
1686 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1687 NT_STATUS_RANGE_NOT_LOCKED)) {
1688 return false;
1692 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1693 if (NT_STATUS_IS_OK(status)) {
1694 printf("lock3 succeeded! This is a locking bug\n");
1695 correct = false;
1696 } else {
1697 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1698 NT_STATUS_LOCK_NOT_GRANTED)) {
1699 return false;
1703 cli_setpid(cli, 1);
1705 status = cli_close(cli, fnum1);
1706 if (!NT_STATUS_IS_OK(status)) {
1707 printf("close1 failed (%s)\n", nt_errstr(status));
1708 return False;
1711 status = cli_close(cli, fnum2);
1712 if (!NT_STATUS_IS_OK(status)) {
1713 printf("close2 failed (%s)\n", nt_errstr(status));
1714 return False;
1717 status = cli_close(cli, fnum3);
1718 if (!NT_STATUS_IS_OK(status)) {
1719 printf("close3 failed (%s)\n", nt_errstr(status));
1720 return False;
1723 if (!torture_close_connection(cli)) {
1724 correct = False;
1727 printf("locktest2 finished\n");
1729 return correct;
1734 This test checks that
1736 1) the server supports the full offset range in lock requests
1738 static bool run_locktest3(int dummy)
1740 static struct cli_state *cli1, *cli2;
1741 const char *fname = "\\lockt3.lck";
1742 uint16_t fnum1, fnum2;
1743 int i;
1744 uint32_t offset;
1745 bool correct = True;
1746 NTSTATUS status;
1748 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1750 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1751 return False;
1753 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1754 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1756 printf("starting locktest3\n");
1758 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1760 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1761 &fnum1);
1762 if (!NT_STATUS_IS_OK(status)) {
1763 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1764 return False;
1767 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1768 if (!NT_STATUS_IS_OK(status)) {
1769 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1770 return False;
1773 for (offset=i=0;i<torture_numops;i++) {
1774 NEXT_OFFSET;
1776 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1777 if (!NT_STATUS_IS_OK(status)) {
1778 printf("lock1 %d failed (%s)\n",
1780 nt_errstr(status));
1781 return False;
1784 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1785 if (!NT_STATUS_IS_OK(status)) {
1786 printf("lock2 %d failed (%s)\n",
1788 nt_errstr(status));
1789 return False;
1793 for (offset=i=0;i<torture_numops;i++) {
1794 NEXT_OFFSET;
1796 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1797 if (NT_STATUS_IS_OK(status)) {
1798 printf("error: lock1 %d succeeded!\n", i);
1799 return False;
1802 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1803 if (NT_STATUS_IS_OK(status)) {
1804 printf("error: lock2 %d succeeded!\n", i);
1805 return False;
1808 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1809 if (NT_STATUS_IS_OK(status)) {
1810 printf("error: lock3 %d succeeded!\n", i);
1811 return False;
1814 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1815 if (NT_STATUS_IS_OK(status)) {
1816 printf("error: lock4 %d succeeded!\n", i);
1817 return False;
1821 for (offset=i=0;i<torture_numops;i++) {
1822 NEXT_OFFSET;
1824 status = cli_unlock(cli1, fnum1, offset-1, 1);
1825 if (!NT_STATUS_IS_OK(status)) {
1826 printf("unlock1 %d failed (%s)\n",
1828 nt_errstr(status));
1829 return False;
1832 status = cli_unlock(cli2, fnum2, offset-2, 1);
1833 if (!NT_STATUS_IS_OK(status)) {
1834 printf("unlock2 %d failed (%s)\n",
1836 nt_errstr(status));
1837 return False;
1841 status = cli_close(cli1, fnum1);
1842 if (!NT_STATUS_IS_OK(status)) {
1843 printf("close1 failed (%s)\n", nt_errstr(status));
1844 return False;
1847 status = cli_close(cli2, fnum2);
1848 if (!NT_STATUS_IS_OK(status)) {
1849 printf("close2 failed (%s)\n", nt_errstr(status));
1850 return False;
1853 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1854 if (!NT_STATUS_IS_OK(status)) {
1855 printf("unlink failed (%s)\n", nt_errstr(status));
1856 return False;
1859 if (!torture_close_connection(cli1)) {
1860 correct = False;
1863 if (!torture_close_connection(cli2)) {
1864 correct = False;
1867 printf("finished locktest3\n");
1869 return correct;
1872 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1873 char *buf, off_t offset, size_t size,
1874 size_t *nread, size_t expect)
1876 NTSTATUS status;
1877 size_t l_nread;
1879 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1881 if(!NT_STATUS_IS_OK(status)) {
1882 return false;
1883 } else if (l_nread != expect) {
1884 return false;
1887 if (nread) {
1888 *nread = l_nread;
1891 return true;
1894 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1895 printf("** "); correct = False; \
1899 looks at overlapping locks
1901 static bool run_locktest4(int dummy)
1903 static struct cli_state *cli1, *cli2;
1904 const char *fname = "\\lockt4.lck";
1905 uint16_t fnum1, fnum2, f;
1906 bool ret;
1907 char buf[1000];
1908 bool correct = True;
1909 NTSTATUS status;
1911 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1912 return False;
1915 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1916 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1918 printf("starting locktest4\n");
1920 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1922 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1923 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1925 memset(buf, 0, sizeof(buf));
1927 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1928 NULL);
1929 if (!NT_STATUS_IS_OK(status)) {
1930 printf("Failed to create file: %s\n", nt_errstr(status));
1931 correct = False;
1932 goto fail;
1935 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1936 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1937 EXPECTED(ret, False);
1938 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1940 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1941 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1942 EXPECTED(ret, True);
1943 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1945 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1946 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1947 EXPECTED(ret, False);
1948 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1950 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1951 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1952 EXPECTED(ret, True);
1953 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1955 ret = (cli_setpid(cli1, 1),
1956 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1957 (cli_setpid(cli1, 2),
1958 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1959 EXPECTED(ret, False);
1960 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1962 ret = (cli_setpid(cli1, 1),
1963 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1964 (cli_setpid(cli1, 2),
1965 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1966 EXPECTED(ret, True);
1967 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1969 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1970 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1971 EXPECTED(ret, True);
1972 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1974 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1975 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1976 EXPECTED(ret, False);
1977 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1979 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1980 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1981 EXPECTED(ret, False);
1982 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1984 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1985 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
1986 EXPECTED(ret, True);
1987 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1989 ret = (cli_setpid(cli1, 1),
1990 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
1991 (cli_setpid(cli1, 2),
1992 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
1993 EXPECTED(ret, False);
1994 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1996 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
1997 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
1998 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
1999 EXPECTED(ret, False);
2000 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2003 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2004 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2005 EXPECTED(ret, False);
2006 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2008 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2009 ret = NT_STATUS_IS_OK(status);
2010 if (ret) {
2011 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2012 NULL);
2013 ret = NT_STATUS_IS_OK(status);
2015 EXPECTED(ret, False);
2016 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2019 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2020 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2021 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2022 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2023 EXPECTED(ret, True);
2024 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2027 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2028 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2029 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2030 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2031 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2032 150, 4, NULL))) &&
2033 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2034 EXPECTED(ret, True);
2035 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2037 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2038 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2039 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2040 160, 4, NULL)) &&
2041 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2042 EXPECTED(ret, True);
2043 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2045 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2046 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2047 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2048 170, 4, NULL)) &&
2049 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2050 EXPECTED(ret, True);
2051 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2053 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2054 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2055 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2056 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2057 190, 4, NULL)) &&
2058 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2059 EXPECTED(ret, True);
2060 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2062 cli_close(cli1, fnum1);
2063 cli_close(cli2, fnum2);
2064 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2065 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2066 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2067 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2068 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2069 NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2070 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2071 cli_close(cli1, f);
2072 cli_close(cli1, fnum1);
2073 EXPECTED(ret, True);
2074 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2076 fail:
2077 cli_close(cli1, fnum1);
2078 cli_close(cli2, fnum2);
2079 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2080 torture_close_connection(cli1);
2081 torture_close_connection(cli2);
2083 printf("finished locktest4\n");
2084 return correct;
2088 looks at lock upgrade/downgrade.
2090 static bool run_locktest5(int dummy)
2092 static struct cli_state *cli1, *cli2;
2093 const char *fname = "\\lockt5.lck";
2094 uint16_t fnum1, fnum2, fnum3;
2095 bool ret;
2096 char buf[1000];
2097 bool correct = True;
2098 NTSTATUS status;
2100 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2101 return False;
2104 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2105 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2107 printf("starting locktest5\n");
2109 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2111 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2112 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2113 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2115 memset(buf, 0, sizeof(buf));
2117 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2118 NULL);
2119 if (!NT_STATUS_IS_OK(status)) {
2120 printf("Failed to create file: %s\n", nt_errstr(status));
2121 correct = False;
2122 goto fail;
2125 /* Check for NT bug... */
2126 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2127 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2128 cli_close(cli1, fnum1);
2129 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2130 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2131 ret = NT_STATUS_IS_OK(status);
2132 EXPECTED(ret, True);
2133 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2134 cli_close(cli1, fnum1);
2135 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2136 cli_unlock(cli1, fnum3, 0, 1);
2138 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2139 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2140 EXPECTED(ret, True);
2141 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2143 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2144 ret = NT_STATUS_IS_OK(status);
2145 EXPECTED(ret, False);
2147 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2149 /* Unlock the process 2 lock. */
2150 cli_unlock(cli2, fnum2, 0, 4);
2152 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2153 ret = NT_STATUS_IS_OK(status);
2154 EXPECTED(ret, False);
2156 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2158 /* Unlock the process 1 fnum3 lock. */
2159 cli_unlock(cli1, fnum3, 0, 4);
2161 /* Stack 2 more locks here. */
2162 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2163 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2165 EXPECTED(ret, True);
2166 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2168 /* Unlock the first process lock, then check this was the WRITE lock that was
2169 removed. */
2171 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2172 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2174 EXPECTED(ret, True);
2175 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2177 /* Unlock the process 2 lock. */
2178 cli_unlock(cli2, fnum2, 0, 4);
2180 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2182 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2183 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2184 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2186 EXPECTED(ret, True);
2187 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2189 /* Ensure the next unlock fails. */
2190 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2191 EXPECTED(ret, False);
2192 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2194 /* Ensure connection 2 can get a write lock. */
2195 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2196 ret = NT_STATUS_IS_OK(status);
2197 EXPECTED(ret, True);
2199 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2202 fail:
2203 cli_close(cli1, fnum1);
2204 cli_close(cli2, fnum2);
2205 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2206 if (!torture_close_connection(cli1)) {
2207 correct = False;
2209 if (!torture_close_connection(cli2)) {
2210 correct = False;
2213 printf("finished locktest5\n");
2215 return correct;
2219 tries the unusual lockingX locktype bits
2221 static bool run_locktest6(int dummy)
2223 static struct cli_state *cli;
2224 const char *fname[1] = { "\\lock6.txt" };
2225 int i;
2226 uint16_t fnum;
2227 NTSTATUS status;
2229 if (!torture_open_connection(&cli, 0)) {
2230 return False;
2233 smbXcli_conn_set_sockopt(cli->conn, sockops);
2235 printf("starting locktest6\n");
2237 for (i=0;i<1;i++) {
2238 printf("Testing %s\n", fname[i]);
2240 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2242 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2243 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2244 cli_close(cli, fnum);
2245 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2247 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2248 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2249 cli_close(cli, fnum);
2250 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2252 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2255 torture_close_connection(cli);
2257 printf("finished locktest6\n");
2258 return True;
2261 static bool run_locktest7(int dummy)
2263 struct cli_state *cli1;
2264 const char *fname = "\\lockt7.lck";
2265 uint16_t fnum1;
2266 char buf[200];
2267 bool correct = False;
2268 size_t nread;
2269 NTSTATUS status;
2271 if (!torture_open_connection(&cli1, 0)) {
2272 return False;
2275 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2277 printf("starting locktest7\n");
2279 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2281 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2283 memset(buf, 0, sizeof(buf));
2285 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2286 NULL);
2287 if (!NT_STATUS_IS_OK(status)) {
2288 printf("Failed to create file: %s\n", nt_errstr(status));
2289 goto fail;
2292 cli_setpid(cli1, 1);
2294 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2295 if (!NT_STATUS_IS_OK(status)) {
2296 printf("Unable to apply read lock on range 130:4, "
2297 "error was %s\n", nt_errstr(status));
2298 goto fail;
2299 } else {
2300 printf("pid1 successfully locked range 130:4 for READ\n");
2303 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2304 if (!NT_STATUS_IS_OK(status)) {
2305 printf("pid1 unable to read the range 130:4, error was %s\n",
2306 nt_errstr(status));
2307 goto fail;
2308 } else if (nread != 4) {
2309 printf("pid1 unable to read the range 130:4, "
2310 "recv %ld req %d\n", (unsigned long)nread, 4);
2311 goto fail;
2312 } else {
2313 printf("pid1 successfully read the range 130:4\n");
2316 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2317 if (!NT_STATUS_IS_OK(status)) {
2318 printf("pid1 unable to write to the range 130:4, error was "
2319 "%s\n", nt_errstr(status));
2320 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2321 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2322 goto fail;
2324 } else {
2325 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2326 goto fail;
2329 cli_setpid(cli1, 2);
2331 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2332 if (!NT_STATUS_IS_OK(status)) {
2333 printf("pid2 unable to read the range 130:4, error was %s\n",
2334 nt_errstr(status));
2335 goto fail;
2336 } else if (nread != 4) {
2337 printf("pid2 unable to read the range 130:4, "
2338 "recv %ld req %d\n", (unsigned long)nread, 4);
2339 goto fail;
2340 } else {
2341 printf("pid2 successfully read the range 130:4\n");
2344 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2345 if (!NT_STATUS_IS_OK(status)) {
2346 printf("pid2 unable to write to the range 130:4, error was "
2347 "%s\n", nt_errstr(status));
2348 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2349 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2350 goto fail;
2352 } else {
2353 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2354 goto fail;
2357 cli_setpid(cli1, 1);
2358 cli_unlock(cli1, fnum1, 130, 4);
2360 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2361 if (!NT_STATUS_IS_OK(status)) {
2362 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2363 goto fail;
2364 } else {
2365 printf("pid1 successfully locked range 130:4 for WRITE\n");
2368 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2369 if (!NT_STATUS_IS_OK(status)) {
2370 printf("pid1 unable to read the range 130:4, error was %s\n",
2371 nt_errstr(status));
2372 goto fail;
2373 } else if (nread != 4) {
2374 printf("pid1 unable to read the range 130:4, "
2375 "recv %ld req %d\n", (unsigned long)nread, 4);
2376 goto fail;
2377 } else {
2378 printf("pid1 successfully read the range 130:4\n");
2381 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2382 if (!NT_STATUS_IS_OK(status)) {
2383 printf("pid1 unable to write to the range 130:4, error was "
2384 "%s\n", nt_errstr(status));
2385 goto fail;
2386 } else {
2387 printf("pid1 successfully wrote to the range 130:4\n");
2390 cli_setpid(cli1, 2);
2392 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2393 if (!NT_STATUS_IS_OK(status)) {
2394 printf("pid2 unable to read the range 130:4, error was "
2395 "%s\n", nt_errstr(status));
2396 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2397 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2398 goto fail;
2400 } else {
2401 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2402 (unsigned long)nread);
2403 goto fail;
2406 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2407 if (!NT_STATUS_IS_OK(status)) {
2408 printf("pid2 unable to write to the range 130:4, error was "
2409 "%s\n", nt_errstr(status));
2410 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2411 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2412 goto fail;
2414 } else {
2415 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2416 goto fail;
2419 cli_unlock(cli1, fnum1, 130, 0);
2420 correct = True;
2422 fail:
2423 cli_close(cli1, fnum1);
2424 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2425 torture_close_connection(cli1);
2427 printf("finished locktest7\n");
2428 return correct;
2432 * This demonstrates a problem with our use of GPFS share modes: A file
2433 * descriptor sitting in the pending close queue holding a GPFS share mode
2434 * blocks opening a file another time. Happens with Word 2007 temp files.
2435 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2436 * open is denied with NT_STATUS_SHARING_VIOLATION.
2439 static bool run_locktest8(int dummy)
2441 struct cli_state *cli1;
2442 const char *fname = "\\lockt8.lck";
2443 uint16_t fnum1, fnum2;
2444 char buf[200];
2445 bool correct = False;
2446 NTSTATUS status;
2448 if (!torture_open_connection(&cli1, 0)) {
2449 return False;
2452 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2454 printf("starting locktest8\n");
2456 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2458 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2459 &fnum1);
2460 if (!NT_STATUS_IS_OK(status)) {
2461 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2462 return false;
2465 memset(buf, 0, sizeof(buf));
2467 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2468 if (!NT_STATUS_IS_OK(status)) {
2469 d_fprintf(stderr, "cli_openx second time returned %s\n",
2470 nt_errstr(status));
2471 goto fail;
2474 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2475 if (!NT_STATUS_IS_OK(status)) {
2476 printf("Unable to apply read lock on range 1:1, error was "
2477 "%s\n", nt_errstr(status));
2478 goto fail;
2481 status = cli_close(cli1, fnum1);
2482 if (!NT_STATUS_IS_OK(status)) {
2483 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2484 goto fail;
2487 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2488 if (!NT_STATUS_IS_OK(status)) {
2489 d_fprintf(stderr, "cli_openx third time returned %s\n",
2490 nt_errstr(status));
2491 goto fail;
2494 correct = true;
2496 fail:
2497 cli_close(cli1, fnum1);
2498 cli_close(cli1, fnum2);
2499 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2500 torture_close_connection(cli1);
2502 printf("finished locktest8\n");
2503 return correct;
2507 * This test is designed to be run in conjunction with
2508 * external NFS or POSIX locks taken in the filesystem.
2509 * It checks that the smbd server will block until the
2510 * lock is released and then acquire it. JRA.
2513 static bool got_alarm;
2514 static struct cli_state *alarm_cli;
2516 static void alarm_handler(int dummy)
2518 got_alarm = True;
2521 static void alarm_handler_parent(int dummy)
2523 smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_OK);
2526 static void do_local_lock(int read_fd, int write_fd)
2528 int fd;
2529 char c = '\0';
2530 struct flock lock;
2531 const char *local_pathname = NULL;
2532 int ret;
2534 local_pathname = talloc_asprintf(talloc_tos(),
2535 "%s/lockt9.lck", local_path);
2536 if (!local_pathname) {
2537 printf("child: alloc fail\n");
2538 exit(1);
2541 unlink(local_pathname);
2542 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2543 if (fd == -1) {
2544 printf("child: open of %s failed %s.\n",
2545 local_pathname, strerror(errno));
2546 exit(1);
2549 /* Now take a fcntl lock. */
2550 lock.l_type = F_WRLCK;
2551 lock.l_whence = SEEK_SET;
2552 lock.l_start = 0;
2553 lock.l_len = 4;
2554 lock.l_pid = getpid();
2556 ret = fcntl(fd,F_SETLK,&lock);
2557 if (ret == -1) {
2558 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2559 local_pathname, strerror(errno));
2560 exit(1);
2561 } else {
2562 printf("child: got lock 0:4 on file %s.\n",
2563 local_pathname );
2564 fflush(stdout);
2567 CatchSignal(SIGALRM, alarm_handler);
2568 alarm(5);
2569 /* Signal the parent. */
2570 if (write(write_fd, &c, 1) != 1) {
2571 printf("child: start signal fail %s.\n",
2572 strerror(errno));
2573 exit(1);
2575 alarm(0);
2577 alarm(10);
2578 /* Wait for the parent to be ready. */
2579 if (read(read_fd, &c, 1) != 1) {
2580 printf("child: reply signal fail %s.\n",
2581 strerror(errno));
2582 exit(1);
2584 alarm(0);
2586 sleep(5);
2587 close(fd);
2588 printf("child: released lock 0:4 on file %s.\n",
2589 local_pathname );
2590 fflush(stdout);
2591 exit(0);
2594 static bool run_locktest9(int dummy)
2596 struct cli_state *cli1;
2597 const char *fname = "\\lockt9.lck";
2598 uint16_t fnum;
2599 bool correct = False;
2600 int pipe_in[2], pipe_out[2];
2601 pid_t child_pid;
2602 char c = '\0';
2603 int ret;
2604 struct timeval start;
2605 double seconds;
2606 NTSTATUS status;
2608 printf("starting locktest9\n");
2610 if (local_path == NULL) {
2611 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2612 return false;
2615 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2616 return false;
2619 child_pid = fork();
2620 if (child_pid == -1) {
2621 return false;
2624 if (child_pid == 0) {
2625 /* Child. */
2626 do_local_lock(pipe_out[0], pipe_in[1]);
2627 exit(0);
2630 close(pipe_out[0]);
2631 close(pipe_in[1]);
2632 pipe_out[0] = -1;
2633 pipe_in[1] = -1;
2635 /* Parent. */
2636 ret = read(pipe_in[0], &c, 1);
2637 if (ret != 1) {
2638 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2639 strerror(errno));
2640 return false;
2643 if (!torture_open_connection(&cli1, 0)) {
2644 return false;
2647 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2649 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE,
2650 &fnum);
2651 if (!NT_STATUS_IS_OK(status)) {
2652 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2653 return false;
2656 /* Ensure the child has the lock. */
2657 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2658 if (NT_STATUS_IS_OK(status)) {
2659 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2660 goto fail;
2661 } else {
2662 d_printf("Child has the lock.\n");
2665 /* Tell the child to wait 5 seconds then exit. */
2666 ret = write(pipe_out[1], &c, 1);
2667 if (ret != 1) {
2668 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2669 strerror(errno));
2670 goto fail;
2673 /* Wait 20 seconds for the lock. */
2674 alarm_cli = cli1;
2675 CatchSignal(SIGALRM, alarm_handler_parent);
2676 alarm(20);
2678 start = timeval_current();
2680 status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2681 if (!NT_STATUS_IS_OK(status)) {
2682 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2683 "%s\n", nt_errstr(status));
2684 goto fail_nofd;
2686 alarm(0);
2688 seconds = timeval_elapsed(&start);
2690 printf("Parent got the lock after %.2f seconds.\n",
2691 seconds);
2693 status = cli_close(cli1, fnum);
2694 if (!NT_STATUS_IS_OK(status)) {
2695 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2696 goto fail;
2699 correct = true;
2701 fail:
2702 cli_close(cli1, fnum);
2703 torture_close_connection(cli1);
2705 fail_nofd:
2707 printf("finished locktest9\n");
2708 return correct;
2712 test whether fnums and tids open on one VC are available on another (a major
2713 security hole)
2715 static bool run_fdpasstest(int dummy)
2717 struct cli_state *cli1, *cli2;
2718 const char *fname = "\\fdpass.tst";
2719 uint16_t fnum1;
2720 char buf[1024];
2721 NTSTATUS status;
2723 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2724 return False;
2726 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2727 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2729 printf("starting fdpasstest\n");
2731 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2733 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2734 &fnum1);
2735 if (!NT_STATUS_IS_OK(status)) {
2736 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2737 return False;
2740 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2741 13, NULL);
2742 if (!NT_STATUS_IS_OK(status)) {
2743 printf("write failed (%s)\n", nt_errstr(status));
2744 return False;
2747 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
2748 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2749 cli_setpid(cli2, cli_getpid(cli1));
2751 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
2752 printf("read succeeded! nasty security hole [%s]\n", buf);
2753 return false;
2756 cli_close(cli1, fnum1);
2757 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2759 torture_close_connection(cli1);
2760 torture_close_connection(cli2);
2762 printf("finished fdpasstest\n");
2763 return True;
2766 static bool run_fdsesstest(int dummy)
2768 struct cli_state *cli;
2769 uint16_t new_vuid;
2770 uint16_t saved_vuid;
2771 uint16_t new_cnum;
2772 uint16_t saved_cnum;
2773 const char *fname = "\\fdsess.tst";
2774 const char *fname1 = "\\fdsess1.tst";
2775 uint16_t fnum1;
2776 uint16_t fnum2;
2777 char buf[1024];
2778 bool ret = True;
2779 NTSTATUS status;
2781 if (!torture_open_connection(&cli, 0))
2782 return False;
2783 smbXcli_conn_set_sockopt(cli->conn, sockops);
2785 if (!torture_cli_session_setup2(cli, &new_vuid))
2786 return False;
2788 saved_cnum = cli_state_get_tid(cli);
2789 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", "", 1)))
2790 return False;
2791 new_cnum = cli_state_get_tid(cli);
2792 cli_state_set_tid(cli, saved_cnum);
2794 printf("starting fdsesstest\n");
2796 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2797 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2799 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2800 if (!NT_STATUS_IS_OK(status)) {
2801 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2802 return False;
2805 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2806 NULL);
2807 if (!NT_STATUS_IS_OK(status)) {
2808 printf("write failed (%s)\n", nt_errstr(status));
2809 return False;
2812 saved_vuid = cli_state_get_uid(cli);
2813 cli_state_set_uid(cli, new_vuid);
2815 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2816 printf("read succeeded with different vuid! "
2817 "nasty security hole [%s]\n", buf);
2818 ret = false;
2820 /* Try to open a file with different vuid, samba cnum. */
2821 if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2822 printf("create with different vuid, same cnum succeeded.\n");
2823 cli_close(cli, fnum2);
2824 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2825 } else {
2826 printf("create with different vuid, same cnum failed.\n");
2827 printf("This will cause problems with service clients.\n");
2828 ret = False;
2831 cli_state_set_uid(cli, saved_vuid);
2833 /* Try with same vuid, different cnum. */
2834 cli_state_set_tid(cli, new_cnum);
2836 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2837 printf("read succeeded with different cnum![%s]\n", buf);
2838 ret = false;
2841 cli_state_set_tid(cli, saved_cnum);
2842 cli_close(cli, fnum1);
2843 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2845 torture_close_connection(cli);
2847 printf("finished fdsesstest\n");
2848 return ret;
2852 This test checks that
2854 1) the server does not allow an unlink on a file that is open
2856 static bool run_unlinktest(int dummy)
2858 struct cli_state *cli;
2859 const char *fname = "\\unlink.tst";
2860 uint16_t fnum;
2861 bool correct = True;
2862 NTSTATUS status;
2864 if (!torture_open_connection(&cli, 0)) {
2865 return False;
2868 smbXcli_conn_set_sockopt(cli->conn, sockops);
2870 printf("starting unlink test\n");
2872 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2874 cli_setpid(cli, 1);
2876 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2877 if (!NT_STATUS_IS_OK(status)) {
2878 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2879 return False;
2882 status = cli_unlink(cli, fname,
2883 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2884 if (NT_STATUS_IS_OK(status)) {
2885 printf("error: server allowed unlink on an open file\n");
2886 correct = False;
2887 } else {
2888 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
2889 NT_STATUS_SHARING_VIOLATION);
2892 cli_close(cli, fnum);
2893 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2895 if (!torture_close_connection(cli)) {
2896 correct = False;
2899 printf("unlink test finished\n");
2901 return correct;
2906 test how many open files this server supports on the one socket
2908 static bool run_maxfidtest(int dummy)
2910 struct cli_state *cli;
2911 fstring fname;
2912 uint16_t fnums[0x11000];
2913 int i;
2914 int retries=4;
2915 bool correct = True;
2916 NTSTATUS status;
2918 cli = current_cli;
2920 if (retries <= 0) {
2921 printf("failed to connect\n");
2922 return False;
2925 smbXcli_conn_set_sockopt(cli->conn, sockops);
2927 for (i=0; i<0x11000; i++) {
2928 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2929 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2930 &fnums[i]);
2931 if (!NT_STATUS_IS_OK(status)) {
2932 printf("open of %s failed (%s)\n",
2933 fname, nt_errstr(status));
2934 printf("maximum fnum is %d\n", i);
2935 break;
2937 printf("%6d\r", i);
2939 printf("%6d\n", i);
2940 i--;
2942 printf("cleaning up\n");
2943 for (;i>=0;i--) {
2944 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2945 cli_close(cli, fnums[i]);
2947 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2948 if (!NT_STATUS_IS_OK(status)) {
2949 printf("unlink of %s failed (%s)\n",
2950 fname, nt_errstr(status));
2951 correct = False;
2953 printf("%6d\r", i);
2955 printf("%6d\n", 0);
2957 printf("maxfid test finished\n");
2958 if (!torture_close_connection(cli)) {
2959 correct = False;
2961 return correct;
2964 /* generate a random buffer */
2965 static void rand_buf(char *buf, int len)
2967 while (len--) {
2968 *buf = (char)sys_random();
2969 buf++;
2973 /* send smb negprot commands, not reading the response */
2974 static bool run_negprot_nowait(int dummy)
2976 struct tevent_context *ev;
2977 int i;
2978 struct cli_state *cli;
2979 bool correct = True;
2981 printf("starting negprot nowait test\n");
2983 ev = samba_tevent_context_init(talloc_tos());
2984 if (ev == NULL) {
2985 return false;
2988 if (!(cli = open_nbt_connection())) {
2989 TALLOC_FREE(ev);
2990 return False;
2993 for (i=0;i<50000;i++) {
2994 struct tevent_req *req;
2996 req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
2997 PROTOCOL_CORE, PROTOCOL_NT1);
2998 if (req == NULL) {
2999 TALLOC_FREE(ev);
3000 return false;
3002 if (!tevent_req_poll(req, ev)) {
3003 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3004 strerror(errno));
3005 TALLOC_FREE(ev);
3006 return false;
3008 TALLOC_FREE(req);
3011 if (torture_close_connection(cli)) {
3012 correct = False;
3015 printf("finished negprot nowait test\n");
3017 return correct;
3020 /* send smb negprot commands, not reading the response */
3021 static bool run_bad_nbt_session(int dummy)
3023 struct nmb_name called, calling;
3024 struct sockaddr_storage ss;
3025 NTSTATUS status;
3026 int fd;
3027 bool ret;
3029 printf("starting bad nbt session test\n");
3031 make_nmb_name(&calling, myname, 0x0);
3032 make_nmb_name(&called , host, 0x20);
3034 if (!resolve_name(host, &ss, 0x20, true)) {
3035 d_fprintf(stderr, "Could not resolve name %s\n", host);
3036 return false;
3039 status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3040 if (!NT_STATUS_IS_OK(status)) {
3041 d_fprintf(stderr, "open_socket_out failed: %s\n",
3042 nt_errstr(status));
3043 return false;
3046 ret = cli_bad_session_request(fd, &calling, &called);
3047 close(fd);
3048 if (!ret) {
3049 d_fprintf(stderr, "open_socket_out failed: %s\n",
3050 nt_errstr(status));
3051 return false;
3054 printf("finished bad nbt session test\n");
3055 return true;
3058 /* send random IPC commands */
3059 static bool run_randomipc(int dummy)
3061 char *rparam = NULL;
3062 char *rdata = NULL;
3063 unsigned int rdrcnt,rprcnt;
3064 char param[1024];
3065 int api, param_len, i;
3066 struct cli_state *cli;
3067 bool correct = True;
3068 int count = 50000;
3070 printf("starting random ipc test\n");
3072 if (!torture_open_connection(&cli, 0)) {
3073 return False;
3076 for (i=0;i<count;i++) {
3077 api = sys_random() % 500;
3078 param_len = (sys_random() % 64);
3080 rand_buf(param, param_len);
3082 SSVAL(param,0,api);
3084 cli_api(cli,
3085 param, param_len, 8,
3086 NULL, 0, CLI_BUFFER_SIZE,
3087 &rparam, &rprcnt,
3088 &rdata, &rdrcnt);
3089 if (i % 100 == 0) {
3090 printf("%d/%d\r", i,count);
3093 printf("%d/%d\n", i, count);
3095 if (!torture_close_connection(cli)) {
3096 correct = False;
3099 SAFE_FREE(rparam);
3100 SAFE_FREE(rdata);
3102 printf("finished random ipc test\n");
3104 return correct;
3109 static void browse_callback(const char *sname, uint32_t stype,
3110 const char *comment, void *state)
3112 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3118 This test checks the browse list code
3121 static bool run_browsetest(int dummy)
3123 static struct cli_state *cli;
3124 bool correct = True;
3126 printf("starting browse test\n");
3128 if (!torture_open_connection(&cli, 0)) {
3129 return False;
3132 printf("domain list:\n");
3133 cli_NetServerEnum(cli, cli->server_domain,
3134 SV_TYPE_DOMAIN_ENUM,
3135 browse_callback, NULL);
3137 printf("machine list:\n");
3138 cli_NetServerEnum(cli, cli->server_domain,
3139 SV_TYPE_ALL,
3140 browse_callback, NULL);
3142 if (!torture_close_connection(cli)) {
3143 correct = False;
3146 printf("browse test finished\n");
3148 return correct;
3154 This checks how the getatr calls works
3156 static bool run_attrtest(int dummy)
3158 struct cli_state *cli;
3159 uint16_t fnum;
3160 time_t t, t2;
3161 const char *fname = "\\attrib123456789.tst";
3162 bool correct = True;
3163 NTSTATUS status;
3165 printf("starting attrib test\n");
3167 if (!torture_open_connection(&cli, 0)) {
3168 return False;
3171 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3172 cli_openx(cli, fname,
3173 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3174 cli_close(cli, fnum);
3176 status = cli_getatr(cli, fname, NULL, NULL, &t);
3177 if (!NT_STATUS_IS_OK(status)) {
3178 printf("getatr failed (%s)\n", nt_errstr(status));
3179 correct = False;
3182 if (abs(t - time(NULL)) > 60*60*24*10) {
3183 printf("ERROR: SMBgetatr bug. time is %s",
3184 ctime(&t));
3185 t = time(NULL);
3186 correct = True;
3189 t2 = t-60*60*24; /* 1 day ago */
3191 status = cli_setatr(cli, fname, 0, t2);
3192 if (!NT_STATUS_IS_OK(status)) {
3193 printf("setatr failed (%s)\n", nt_errstr(status));
3194 correct = True;
3197 status = cli_getatr(cli, fname, NULL, NULL, &t);
3198 if (!NT_STATUS_IS_OK(status)) {
3199 printf("getatr failed (%s)\n", nt_errstr(status));
3200 correct = True;
3203 if (t != t2) {
3204 printf("ERROR: getatr/setatr bug. times are\n%s",
3205 ctime(&t));
3206 printf("%s", ctime(&t2));
3207 correct = True;
3210 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3212 if (!torture_close_connection(cli)) {
3213 correct = False;
3216 printf("attrib test finished\n");
3218 return correct;
3223 This checks a couple of trans2 calls
3225 static bool run_trans2test(int dummy)
3227 struct cli_state *cli;
3228 uint16_t fnum;
3229 off_t size;
3230 time_t c_time, a_time, m_time;
3231 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3232 const char *fname = "\\trans2.tst";
3233 const char *dname = "\\trans2";
3234 const char *fname2 = "\\trans2\\trans2.tst";
3235 char *pname;
3236 bool correct = True;
3237 NTSTATUS status;
3238 uint32_t fs_attr;
3240 printf("starting trans2 test\n");
3242 if (!torture_open_connection(&cli, 0)) {
3243 return False;
3246 status = cli_get_fs_attr_info(cli, &fs_attr);
3247 if (!NT_STATUS_IS_OK(status)) {
3248 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3249 nt_errstr(status));
3250 correct = false;
3253 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3254 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3255 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3256 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3257 if (!NT_STATUS_IS_OK(status)) {
3258 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3259 correct = False;
3262 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3263 if (!NT_STATUS_IS_OK(status)) {
3264 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3265 correct = False;
3268 if (strcmp(pname, fname)) {
3269 printf("qfilename gave different name? [%s] [%s]\n",
3270 fname, pname);
3271 correct = False;
3274 cli_close(cli, fnum);
3276 sleep(2);
3278 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3279 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3280 &fnum);
3281 if (!NT_STATUS_IS_OK(status)) {
3282 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3283 return False;
3285 cli_close(cli, fnum);
3287 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3288 NULL);
3289 if (!NT_STATUS_IS_OK(status)) {
3290 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3291 correct = False;
3292 } else {
3293 time_t t = time(NULL);
3295 if (c_time != m_time) {
3296 printf("create time=%s", ctime(&c_time));
3297 printf("modify time=%s", ctime(&m_time));
3298 printf("This system appears to have sticky create times\n");
3300 if ((abs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
3301 printf("access time=%s", ctime(&a_time));
3302 printf("This system appears to set a midnight access time\n");
3303 correct = False;
3306 if (abs(m_time - t) > 60*60*24*7) {
3307 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3308 correct = False;
3313 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3314 cli_openx(cli, fname,
3315 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3316 cli_close(cli, fnum);
3317 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3318 &m_time_ts, &size, NULL, NULL);
3319 if (!NT_STATUS_IS_OK(status)) {
3320 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3321 correct = False;
3322 } else {
3323 if (w_time_ts.tv_sec < 60*60*24*2) {
3324 printf("write time=%s", ctime(&w_time_ts.tv_sec));
3325 printf("This system appears to set a initial 0 write time\n");
3326 correct = False;
3330 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3333 /* check if the server updates the directory modification time
3334 when creating a new file */
3335 status = cli_mkdir(cli, dname);
3336 if (!NT_STATUS_IS_OK(status)) {
3337 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3338 correct = False;
3340 sleep(3);
3341 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3342 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3343 if (!NT_STATUS_IS_OK(status)) {
3344 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3345 correct = False;
3348 cli_openx(cli, fname2,
3349 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3350 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3351 cli_close(cli, fnum);
3352 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3353 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3354 if (!NT_STATUS_IS_OK(status)) {
3355 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3356 correct = False;
3357 } else {
3358 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3359 == 0) {
3360 printf("This system does not update directory modification times\n");
3361 correct = False;
3364 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3365 cli_rmdir(cli, dname);
3367 if (!torture_close_connection(cli)) {
3368 correct = False;
3371 printf("trans2 test finished\n");
3373 return correct;
3377 This checks new W2K calls.
3380 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3382 uint8_t *buf = NULL;
3383 uint32_t len;
3384 NTSTATUS status;
3386 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3387 CLI_BUFFER_SIZE, NULL, &buf, &len);
3388 if (!NT_STATUS_IS_OK(status)) {
3389 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3390 nt_errstr(status));
3391 } else {
3392 printf("qfileinfo: level %d, len = %u\n", level, len);
3393 dump_data(0, (uint8_t *)buf, len);
3394 printf("\n");
3396 TALLOC_FREE(buf);
3397 return status;
3400 static bool run_w2ktest(int dummy)
3402 struct cli_state *cli;
3403 uint16_t fnum;
3404 const char *fname = "\\w2ktest\\w2k.tst";
3405 int level;
3406 bool correct = True;
3408 printf("starting w2k test\n");
3410 if (!torture_open_connection(&cli, 0)) {
3411 return False;
3414 cli_openx(cli, fname,
3415 O_RDWR | O_CREAT , DENY_NONE, &fnum);
3417 for (level = 1004; level < 1040; level++) {
3418 new_trans(cli, fnum, level);
3421 cli_close(cli, fnum);
3423 if (!torture_close_connection(cli)) {
3424 correct = False;
3427 printf("w2k test finished\n");
3429 return correct;
3434 this is a harness for some oplock tests
3436 static bool run_oplock1(int dummy)
3438 struct cli_state *cli1;
3439 const char *fname = "\\lockt1.lck";
3440 uint16_t fnum1;
3441 bool correct = True;
3442 NTSTATUS status;
3444 printf("starting oplock test 1\n");
3446 if (!torture_open_connection(&cli1, 0)) {
3447 return False;
3450 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3452 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3454 cli1->use_oplocks = True;
3456 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3457 &fnum1);
3458 if (!NT_STATUS_IS_OK(status)) {
3459 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3460 return False;
3463 cli1->use_oplocks = False;
3465 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3466 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3468 status = cli_close(cli1, fnum1);
3469 if (!NT_STATUS_IS_OK(status)) {
3470 printf("close2 failed (%s)\n", nt_errstr(status));
3471 return False;
3474 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3475 if (!NT_STATUS_IS_OK(status)) {
3476 printf("unlink failed (%s)\n", nt_errstr(status));
3477 return False;
3480 if (!torture_close_connection(cli1)) {
3481 correct = False;
3484 printf("finished oplock test 1\n");
3486 return correct;
3489 static bool run_oplock2(int dummy)
3491 struct cli_state *cli1, *cli2;
3492 const char *fname = "\\lockt2.lck";
3493 uint16_t fnum1, fnum2;
3494 int saved_use_oplocks = use_oplocks;
3495 char buf[4];
3496 bool correct = True;
3497 volatile bool *shared_correct;
3498 size_t nread;
3499 NTSTATUS status;
3501 shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
3502 *shared_correct = True;
3504 use_level_II_oplocks = True;
3505 use_oplocks = True;
3507 printf("starting oplock test 2\n");
3509 if (!torture_open_connection(&cli1, 0)) {
3510 use_level_II_oplocks = False;
3511 use_oplocks = saved_use_oplocks;
3512 return False;
3515 if (!torture_open_connection(&cli2, 1)) {
3516 use_level_II_oplocks = False;
3517 use_oplocks = saved_use_oplocks;
3518 return False;
3521 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3523 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3524 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3526 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3527 &fnum1);
3528 if (!NT_STATUS_IS_OK(status)) {
3529 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3530 return False;
3533 /* Don't need the globals any more. */
3534 use_level_II_oplocks = False;
3535 use_oplocks = saved_use_oplocks;
3537 if (fork() == 0) {
3538 /* Child code */
3539 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3540 if (!NT_STATUS_IS_OK(status)) {
3541 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3542 *shared_correct = False;
3543 exit(0);
3546 sleep(2);
3548 status = cli_close(cli2, fnum2);
3549 if (!NT_STATUS_IS_OK(status)) {
3550 printf("close2 failed (%s)\n", nt_errstr(status));
3551 *shared_correct = False;
3554 exit(0);
3557 sleep(2);
3559 /* Ensure cli1 processes the break. Empty file should always return 0
3560 * bytes. */
3561 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
3562 if (!NT_STATUS_IS_OK(status)) {
3563 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
3564 correct = false;
3565 } else if (nread != 0) {
3566 printf("read on empty fnum1 failed. recv %ld expected %d\n",
3567 (unsigned long)nread, 0);
3568 correct = false;
3571 /* Should now be at level II. */
3572 /* Test if sending a write locks causes a break to none. */
3573 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3574 if (!NT_STATUS_IS_OK(status)) {
3575 printf("lock failed (%s)\n", nt_errstr(status));
3576 correct = False;
3579 cli_unlock(cli1, fnum1, 0, 4);
3581 sleep(2);
3583 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3584 if (!NT_STATUS_IS_OK(status)) {
3585 printf("lock failed (%s)\n", nt_errstr(status));
3586 correct = False;
3589 cli_unlock(cli1, fnum1, 0, 4);
3591 sleep(2);
3593 cli_read(cli1, fnum1, buf, 0, 4, NULL);
3595 status = cli_close(cli1, fnum1);
3596 if (!NT_STATUS_IS_OK(status)) {
3597 printf("close1 failed (%s)\n", nt_errstr(status));
3598 correct = False;
3601 sleep(4);
3603 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3604 if (!NT_STATUS_IS_OK(status)) {
3605 printf("unlink failed (%s)\n", nt_errstr(status));
3606 correct = False;
3609 if (!torture_close_connection(cli1)) {
3610 correct = False;
3613 if (!*shared_correct) {
3614 correct = False;
3617 printf("finished oplock test 2\n");
3619 return correct;
3622 struct oplock4_state {
3623 struct tevent_context *ev;
3624 struct cli_state *cli;
3625 bool *got_break;
3626 uint16_t *fnum2;
3629 static void oplock4_got_break(struct tevent_req *req);
3630 static void oplock4_got_open(struct tevent_req *req);
3632 static bool run_oplock4(int dummy)
3634 struct tevent_context *ev;
3635 struct cli_state *cli1, *cli2;
3636 struct tevent_req *oplock_req, *open_req;
3637 const char *fname = "\\lockt4.lck";
3638 const char *fname_ln = "\\lockt4_ln.lck";
3639 uint16_t fnum1, fnum2;
3640 int saved_use_oplocks = use_oplocks;
3641 NTSTATUS status;
3642 bool correct = true;
3644 bool got_break;
3646 struct oplock4_state *state;
3648 printf("starting oplock test 4\n");
3650 if (!torture_open_connection(&cli1, 0)) {
3651 use_level_II_oplocks = false;
3652 use_oplocks = saved_use_oplocks;
3653 return false;
3656 if (!torture_open_connection(&cli2, 1)) {
3657 use_level_II_oplocks = false;
3658 use_oplocks = saved_use_oplocks;
3659 return false;
3662 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3663 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3665 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3666 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3668 /* Create the file. */
3669 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3670 &fnum1);
3671 if (!NT_STATUS_IS_OK(status)) {
3672 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3673 return false;
3676 status = cli_close(cli1, fnum1);
3677 if (!NT_STATUS_IS_OK(status)) {
3678 printf("close1 failed (%s)\n", nt_errstr(status));
3679 return false;
3682 /* Now create a hardlink. */
3683 status = cli_nt_hardlink(cli1, fname, fname_ln);
3684 if (!NT_STATUS_IS_OK(status)) {
3685 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3686 return false;
3689 /* Prove that opening hardlinks cause deny modes to conflict. */
3690 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3691 if (!NT_STATUS_IS_OK(status)) {
3692 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3693 return false;
3696 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3697 if (NT_STATUS_IS_OK(status)) {
3698 printf("open of %s succeeded - should fail with sharing violation.\n",
3699 fname_ln);
3700 return false;
3703 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3704 printf("open of %s should fail with sharing violation. Got %s\n",
3705 fname_ln, nt_errstr(status));
3706 return false;
3709 status = cli_close(cli1, fnum1);
3710 if (!NT_STATUS_IS_OK(status)) {
3711 printf("close1 failed (%s)\n", nt_errstr(status));
3712 return false;
3715 cli1->use_oplocks = true;
3716 cli2->use_oplocks = true;
3718 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3719 if (!NT_STATUS_IS_OK(status)) {
3720 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3721 return false;
3724 ev = samba_tevent_context_init(talloc_tos());
3725 if (ev == NULL) {
3726 printf("tevent_context_init failed\n");
3727 return false;
3730 state = talloc(ev, struct oplock4_state);
3731 if (state == NULL) {
3732 printf("talloc failed\n");
3733 return false;
3735 state->ev = ev;
3736 state->cli = cli1;
3737 state->got_break = &got_break;
3738 state->fnum2 = &fnum2;
3740 oplock_req = cli_smb_oplock_break_waiter_send(
3741 talloc_tos(), ev, cli1);
3742 if (oplock_req == NULL) {
3743 printf("cli_smb_oplock_break_waiter_send failed\n");
3744 return false;
3746 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3748 open_req = cli_openx_send(
3749 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3750 if (open_req == NULL) {
3751 printf("cli_openx_send failed\n");
3752 return false;
3754 tevent_req_set_callback(open_req, oplock4_got_open, state);
3756 got_break = false;
3757 fnum2 = 0xffff;
3759 while (!got_break || fnum2 == 0xffff) {
3760 int ret;
3761 ret = tevent_loop_once(ev);
3762 if (ret == -1) {
3763 printf("tevent_loop_once failed: %s\n",
3764 strerror(errno));
3765 return false;
3769 status = cli_close(cli2, fnum2);
3770 if (!NT_STATUS_IS_OK(status)) {
3771 printf("close2 failed (%s)\n", nt_errstr(status));
3772 correct = false;
3775 status = cli_close(cli1, fnum1);
3776 if (!NT_STATUS_IS_OK(status)) {
3777 printf("close1 failed (%s)\n", nt_errstr(status));
3778 correct = false;
3781 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3782 if (!NT_STATUS_IS_OK(status)) {
3783 printf("unlink failed (%s)\n", nt_errstr(status));
3784 correct = false;
3787 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3788 if (!NT_STATUS_IS_OK(status)) {
3789 printf("unlink failed (%s)\n", nt_errstr(status));
3790 correct = false;
3793 if (!torture_close_connection(cli1)) {
3794 correct = false;
3797 if (!got_break) {
3798 correct = false;
3801 printf("finished oplock test 4\n");
3803 return correct;
3806 static void oplock4_got_break(struct tevent_req *req)
3808 struct oplock4_state *state = tevent_req_callback_data(
3809 req, struct oplock4_state);
3810 uint16_t fnum;
3811 uint8_t level;
3812 NTSTATUS status;
3814 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3815 TALLOC_FREE(req);
3816 if (!NT_STATUS_IS_OK(status)) {
3817 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3818 nt_errstr(status));
3819 return;
3821 *state->got_break = true;
3823 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3824 NO_OPLOCK);
3825 if (req == NULL) {
3826 printf("cli_oplock_ack_send failed\n");
3827 return;
3831 static void oplock4_got_open(struct tevent_req *req)
3833 struct oplock4_state *state = tevent_req_callback_data(
3834 req, struct oplock4_state);
3835 NTSTATUS status;
3837 status = cli_openx_recv(req, state->fnum2);
3838 if (!NT_STATUS_IS_OK(status)) {
3839 printf("cli_openx_recv returned %s\n", nt_errstr(status));
3840 *state->fnum2 = 0xffff;
3845 Test delete on close semantics.
3847 static bool run_deletetest(int dummy)
3849 struct cli_state *cli1 = NULL;
3850 struct cli_state *cli2 = NULL;
3851 const char *fname = "\\delete.file";
3852 uint16_t fnum1 = (uint16_t)-1;
3853 uint16_t fnum2 = (uint16_t)-1;
3854 bool correct = false;
3855 NTSTATUS status;
3857 printf("starting delete test\n");
3859 if (!torture_open_connection(&cli1, 0)) {
3860 return False;
3863 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3865 /* Test 1 - this should delete the file on close. */
3867 cli_setatr(cli1, fname, 0, 0);
3868 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3870 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3871 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3872 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
3873 if (!NT_STATUS_IS_OK(status)) {
3874 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3875 goto fail;
3878 status = cli_close(cli1, fnum1);
3879 if (!NT_STATUS_IS_OK(status)) {
3880 printf("[1] close failed (%s)\n", nt_errstr(status));
3881 goto fail;
3884 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3885 if (NT_STATUS_IS_OK(status)) {
3886 printf("[1] open of %s succeeded (should fail)\n", fname);
3887 goto fail;
3890 printf("first delete on close test succeeded.\n");
3892 /* Test 2 - this should delete the file on close. */
3894 cli_setatr(cli1, fname, 0, 0);
3895 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3897 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3898 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3899 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
3900 if (!NT_STATUS_IS_OK(status)) {
3901 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3902 goto fail;
3905 status = cli_nt_delete_on_close(cli1, fnum1, true);
3906 if (!NT_STATUS_IS_OK(status)) {
3907 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3908 goto fail;
3911 status = cli_close(cli1, fnum1);
3912 if (!NT_STATUS_IS_OK(status)) {
3913 printf("[2] close failed (%s)\n", nt_errstr(status));
3914 goto fail;
3917 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
3918 if (NT_STATUS_IS_OK(status)) {
3919 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3920 status = cli_close(cli1, fnum1);
3921 if (!NT_STATUS_IS_OK(status)) {
3922 printf("[2] close failed (%s)\n", nt_errstr(status));
3924 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3925 goto fail;
3928 printf("second delete on close test succeeded.\n");
3930 /* Test 3 - ... */
3931 cli_setatr(cli1, fname, 0, 0);
3932 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3934 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3935 FILE_ATTRIBUTE_NORMAL,
3936 FILE_SHARE_READ|FILE_SHARE_WRITE,
3937 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
3938 if (!NT_STATUS_IS_OK(status)) {
3939 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
3940 goto fail;
3943 /* This should fail with a sharing violation - open for delete is only compatible
3944 with SHARE_DELETE. */
3946 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3947 FILE_ATTRIBUTE_NORMAL,
3948 FILE_SHARE_READ|FILE_SHARE_WRITE,
3949 FILE_OPEN, 0, 0, &fnum2, NULL);
3950 if (NT_STATUS_IS_OK(status)) {
3951 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
3952 goto fail;
3955 /* This should succeed. */
3956 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3957 FILE_ATTRIBUTE_NORMAL,
3958 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3959 FILE_OPEN, 0, 0, &fnum2, NULL);
3960 if (!NT_STATUS_IS_OK(status)) {
3961 printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
3962 goto fail;
3965 status = cli_nt_delete_on_close(cli1, fnum1, true);
3966 if (!NT_STATUS_IS_OK(status)) {
3967 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
3968 goto fail;
3971 status = cli_close(cli1, fnum1);
3972 if (!NT_STATUS_IS_OK(status)) {
3973 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
3974 goto fail;
3977 status = cli_close(cli1, fnum2);
3978 if (!NT_STATUS_IS_OK(status)) {
3979 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
3980 goto fail;
3983 /* This should fail - file should no longer be there. */
3985 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
3986 if (NT_STATUS_IS_OK(status)) {
3987 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
3988 status = cli_close(cli1, fnum1);
3989 if (!NT_STATUS_IS_OK(status)) {
3990 printf("[3] close failed (%s)\n", nt_errstr(status));
3992 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3993 goto fail;
3996 printf("third delete on close test succeeded.\n");
3998 /* Test 4 ... */
3999 cli_setatr(cli1, fname, 0, 0);
4000 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4002 status = cli_ntcreate(cli1, fname, 0,
4003 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4004 FILE_ATTRIBUTE_NORMAL,
4005 FILE_SHARE_READ|FILE_SHARE_WRITE,
4006 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4007 if (!NT_STATUS_IS_OK(status)) {
4008 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4009 goto fail;
4012 /* This should succeed. */
4013 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4014 FILE_ATTRIBUTE_NORMAL,
4015 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4016 FILE_OPEN, 0, 0, &fnum2, NULL);
4017 if (!NT_STATUS_IS_OK(status)) {
4018 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4019 goto fail;
4022 status = cli_close(cli1, fnum2);
4023 if (!NT_STATUS_IS_OK(status)) {
4024 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4025 goto fail;
4028 status = cli_nt_delete_on_close(cli1, fnum1, true);
4029 if (!NT_STATUS_IS_OK(status)) {
4030 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4031 goto fail;
4034 /* This should fail - no more opens once delete on close set. */
4035 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4036 FILE_ATTRIBUTE_NORMAL,
4037 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4038 FILE_OPEN, 0, 0, &fnum2, NULL);
4039 if (NT_STATUS_IS_OK(status)) {
4040 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
4041 goto fail;
4044 status = cli_close(cli1, fnum1);
4045 if (!NT_STATUS_IS_OK(status)) {
4046 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4047 goto fail;
4050 printf("fourth delete on close test succeeded.\n");
4052 /* Test 5 ... */
4053 cli_setatr(cli1, fname, 0, 0);
4054 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4056 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4057 if (!NT_STATUS_IS_OK(status)) {
4058 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4059 goto fail;
4062 /* This should fail - only allowed on NT opens with DELETE access. */
4064 status = cli_nt_delete_on_close(cli1, fnum1, true);
4065 if (NT_STATUS_IS_OK(status)) {
4066 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4067 goto fail;
4070 status = cli_close(cli1, fnum1);
4071 if (!NT_STATUS_IS_OK(status)) {
4072 printf("[5] close failed (%s)\n", nt_errstr(status));
4073 goto fail;
4076 printf("fifth delete on close test succeeded.\n");
4078 /* Test 6 ... */
4079 cli_setatr(cli1, fname, 0, 0);
4080 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4082 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4083 FILE_ATTRIBUTE_NORMAL,
4084 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4085 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4086 if (!NT_STATUS_IS_OK(status)) {
4087 printf("[6] open of %s failed (%s)\n", fname,
4088 nt_errstr(status));
4089 goto fail;
4092 /* This should fail - only allowed on NT opens with DELETE access. */
4094 status = cli_nt_delete_on_close(cli1, fnum1, true);
4095 if (NT_STATUS_IS_OK(status)) {
4096 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4097 goto fail;
4100 status = cli_close(cli1, fnum1);
4101 if (!NT_STATUS_IS_OK(status)) {
4102 printf("[6] close failed (%s)\n", nt_errstr(status));
4103 goto fail;
4106 printf("sixth delete on close test succeeded.\n");
4108 /* Test 7 ... */
4109 cli_setatr(cli1, fname, 0, 0);
4110 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4112 status = cli_ntcreate(cli1, fname, 0,
4113 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4114 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4115 0, 0, &fnum1, NULL);
4116 if (!NT_STATUS_IS_OK(status)) {
4117 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4118 goto fail;
4121 status = cli_nt_delete_on_close(cli1, fnum1, true);
4122 if (!NT_STATUS_IS_OK(status)) {
4123 printf("[7] setting delete_on_close on file failed !\n");
4124 goto fail;
4127 status = cli_nt_delete_on_close(cli1, fnum1, false);
4128 if (!NT_STATUS_IS_OK(status)) {
4129 printf("[7] unsetting delete_on_close on file failed !\n");
4130 goto fail;
4133 status = cli_close(cli1, fnum1);
4134 if (!NT_STATUS_IS_OK(status)) {
4135 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
4136 goto fail;
4139 /* This next open should succeed - we reset the flag. */
4140 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4141 if (!NT_STATUS_IS_OK(status)) {
4142 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4143 goto fail;
4146 status = cli_close(cli1, fnum1);
4147 if (!NT_STATUS_IS_OK(status)) {
4148 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4149 goto fail;
4152 printf("seventh delete on close test succeeded.\n");
4154 /* Test 8 ... */
4155 cli_setatr(cli1, fname, 0, 0);
4156 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4158 if (!torture_open_connection(&cli2, 1)) {
4159 printf("[8] failed to open second connection.\n");
4160 goto fail;
4163 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4165 status = cli_ntcreate(cli1, fname, 0,
4166 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4167 FILE_ATTRIBUTE_NORMAL,
4168 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4169 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4170 if (!NT_STATUS_IS_OK(status)) {
4171 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4172 goto fail;
4175 status = cli_ntcreate(cli2, fname, 0,
4176 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4177 FILE_ATTRIBUTE_NORMAL,
4178 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4179 FILE_OPEN, 0, 0, &fnum2, NULL);
4180 if (!NT_STATUS_IS_OK(status)) {
4181 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4182 goto fail;
4185 status = cli_nt_delete_on_close(cli1, fnum1, true);
4186 if (!NT_STATUS_IS_OK(status)) {
4187 printf("[8] setting delete_on_close on file failed !\n");
4188 goto fail;
4191 status = cli_close(cli1, fnum1);
4192 if (!NT_STATUS_IS_OK(status)) {
4193 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4194 goto fail;
4197 status = cli_close(cli2, fnum2);
4198 if (!NT_STATUS_IS_OK(status)) {
4199 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4200 goto fail;
4203 /* This should fail.. */
4204 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4205 if (NT_STATUS_IS_OK(status)) {
4206 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4207 goto fail;
4210 printf("eighth delete on close test succeeded.\n");
4212 /* Test 9 ... */
4214 /* This should fail - we need to set DELETE_ACCESS. */
4215 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4216 FILE_ATTRIBUTE_NORMAL,
4217 FILE_SHARE_NONE,
4218 FILE_OVERWRITE_IF,
4219 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4220 if (NT_STATUS_IS_OK(status)) {
4221 printf("[9] open of %s succeeded should have failed!\n", fname);
4222 goto fail;
4225 printf("ninth delete on close test succeeded.\n");
4227 /* Test 10 ... */
4229 status = cli_ntcreate(cli1, fname, 0,
4230 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4231 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4232 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4233 0, &fnum1, NULL);
4234 if (!NT_STATUS_IS_OK(status)) {
4235 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4236 goto fail;
4239 /* This should delete the file. */
4240 status = cli_close(cli1, fnum1);
4241 if (!NT_STATUS_IS_OK(status)) {
4242 printf("[10] close failed (%s)\n", nt_errstr(status));
4243 goto fail;
4246 /* This should fail.. */
4247 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4248 if (NT_STATUS_IS_OK(status)) {
4249 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4250 goto fail;
4253 printf("tenth delete on close test succeeded.\n");
4255 /* Test 11 ... */
4257 cli_setatr(cli1, fname, 0, 0);
4258 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4260 /* Can we open a read-only file with delete access? */
4262 /* Create a readonly file. */
4263 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4264 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4265 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4266 if (!NT_STATUS_IS_OK(status)) {
4267 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4268 goto fail;
4271 status = cli_close(cli1, fnum1);
4272 if (!NT_STATUS_IS_OK(status)) {
4273 printf("[11] close failed (%s)\n", nt_errstr(status));
4274 goto fail;
4277 /* Now try open for delete access. */
4278 status = cli_ntcreate(cli1, fname, 0,
4279 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4281 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4282 FILE_OPEN, 0, 0, &fnum1, NULL);
4283 if (!NT_STATUS_IS_OK(status)) {
4284 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
4285 goto fail;
4288 cli_close(cli1, fnum1);
4290 printf("eleventh delete on close test succeeded.\n");
4293 * Test 12
4294 * like test 4 but with initial delete on close
4297 cli_setatr(cli1, fname, 0, 0);
4298 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4300 status = cli_ntcreate(cli1, fname, 0,
4301 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4302 FILE_ATTRIBUTE_NORMAL,
4303 FILE_SHARE_READ|FILE_SHARE_WRITE,
4304 FILE_OVERWRITE_IF,
4305 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4306 if (!NT_STATUS_IS_OK(status)) {
4307 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4308 goto fail;
4311 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4312 FILE_ATTRIBUTE_NORMAL,
4313 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4314 FILE_OPEN, 0, 0, &fnum2, NULL);
4315 if (!NT_STATUS_IS_OK(status)) {
4316 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
4317 goto fail;
4320 status = cli_close(cli1, fnum2);
4321 if (!NT_STATUS_IS_OK(status)) {
4322 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
4323 goto fail;
4326 status = cli_nt_delete_on_close(cli1, fnum1, true);
4327 if (!NT_STATUS_IS_OK(status)) {
4328 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
4329 goto fail;
4332 /* This should fail - no more opens once delete on close set. */
4333 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4334 FILE_ATTRIBUTE_NORMAL,
4335 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4336 FILE_OPEN, 0, 0, &fnum2, NULL);
4337 if (NT_STATUS_IS_OK(status)) {
4338 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
4339 goto fail;
4342 status = cli_nt_delete_on_close(cli1, fnum1, false);
4343 if (!NT_STATUS_IS_OK(status)) {
4344 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
4345 goto fail;
4348 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4349 FILE_ATTRIBUTE_NORMAL,
4350 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4351 FILE_OPEN, 0, 0, &fnum2, NULL);
4352 if (!NT_STATUS_IS_OK(status)) {
4353 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
4354 goto fail;
4357 status = cli_close(cli1, fnum2);
4358 if (!NT_STATUS_IS_OK(status)) {
4359 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
4360 goto fail;
4363 status = cli_close(cli1, fnum1);
4364 if (!NT_STATUS_IS_OK(status)) {
4365 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
4366 goto fail;
4370 * setting delete on close on the handle does
4371 * not unset the initial delete on close...
4373 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4374 FILE_ATTRIBUTE_NORMAL,
4375 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4376 FILE_OPEN, 0, 0, &fnum2, NULL);
4377 if (NT_STATUS_IS_OK(status)) {
4378 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
4379 goto fail;
4380 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4381 printf("ntcreate returned %s, expected "
4382 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
4383 nt_errstr(status));
4384 goto fail;
4387 printf("twelfth delete on close test succeeded.\n");
4390 printf("finished delete test\n");
4392 correct = true;
4394 fail:
4395 /* FIXME: This will crash if we aborted before cli2 got
4396 * intialized, because these functions don't handle
4397 * uninitialized connections. */
4399 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4400 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4401 cli_setatr(cli1, fname, 0, 0);
4402 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4404 if (cli1 && !torture_close_connection(cli1)) {
4405 correct = False;
4407 if (cli2 && !torture_close_connection(cli2)) {
4408 correct = False;
4410 return correct;
4415 Test wildcard delete.
4417 static bool run_wild_deletetest(int dummy)
4419 struct cli_state *cli = NULL;
4420 const char *dname = "\\WTEST";
4421 const char *fname = "\\WTEST\\A";
4422 const char *wunlink_name = "\\WTEST\\*";
4423 uint16_t fnum1 = (uint16_t)-1;
4424 bool correct = false;
4425 NTSTATUS status;
4427 printf("starting wildcard delete test\n");
4429 if (!torture_open_connection(&cli, 0)) {
4430 return false;
4433 smbXcli_conn_set_sockopt(cli->conn, sockops);
4435 cli_unlink(cli, fname, 0);
4436 cli_rmdir(cli, dname);
4437 status = cli_mkdir(cli, dname);
4438 if (!NT_STATUS_IS_OK(status)) {
4439 printf("mkdir of %s failed %s!\n", dname, nt_errstr(status));
4440 goto fail;
4442 status = cli_openx(cli, fname, O_CREAT|O_RDONLY, DENY_NONE, &fnum1);
4443 if (!NT_STATUS_IS_OK(status)) {
4444 printf("open of %s failed %s!\n", fname, nt_errstr(status));
4445 goto fail;
4447 status = cli_close(cli, fnum1);
4448 fnum1 = -1;
4451 * Note the unlink attribute-type of zero. This should
4452 * map into FILE_ATTRIBUTE_NORMAL at the server even
4453 * on a wildcard delete.
4456 status = cli_unlink(cli, wunlink_name, 0);
4457 if (!NT_STATUS_IS_OK(status)) {
4458 printf("unlink of %s failed %s!\n",
4459 wunlink_name, nt_errstr(status));
4460 goto fail;
4463 printf("finished wildcard delete test\n");
4465 correct = true;
4467 fail:
4469 if (fnum1 != (uint16_t)-1) cli_close(cli, fnum1);
4470 cli_unlink(cli, fname, 0);
4471 cli_rmdir(cli, dname);
4473 if (cli && !torture_close_connection(cli)) {
4474 correct = false;
4476 return correct;
4479 static bool run_deletetest_ln(int dummy)
4481 struct cli_state *cli;
4482 const char *fname = "\\delete1";
4483 const char *fname_ln = "\\delete1_ln";
4484 uint16_t fnum;
4485 uint16_t fnum1;
4486 NTSTATUS status;
4487 bool correct = true;
4488 time_t t;
4490 printf("starting deletetest-ln\n");
4492 if (!torture_open_connection(&cli, 0)) {
4493 return false;
4496 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4497 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4499 smbXcli_conn_set_sockopt(cli->conn, sockops);
4501 /* Create the file. */
4502 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4503 if (!NT_STATUS_IS_OK(status)) {
4504 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4505 return false;
4508 status = cli_close(cli, fnum);
4509 if (!NT_STATUS_IS_OK(status)) {
4510 printf("close1 failed (%s)\n", nt_errstr(status));
4511 return false;
4514 /* Now create a hardlink. */
4515 status = cli_nt_hardlink(cli, fname, fname_ln);
4516 if (!NT_STATUS_IS_OK(status)) {
4517 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4518 return false;
4521 /* Open the original file. */
4522 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4523 FILE_ATTRIBUTE_NORMAL,
4524 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4525 FILE_OPEN_IF, 0, 0, &fnum, NULL);
4526 if (!NT_STATUS_IS_OK(status)) {
4527 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4528 return false;
4531 /* Unlink the hard link path. */
4532 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4533 FILE_ATTRIBUTE_NORMAL,
4534 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4535 FILE_OPEN_IF, 0, 0, &fnum1, NULL);
4536 if (!NT_STATUS_IS_OK(status)) {
4537 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4538 return false;
4540 status = cli_nt_delete_on_close(cli, fnum1, true);
4541 if (!NT_STATUS_IS_OK(status)) {
4542 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4543 __location__, fname_ln, nt_errstr(status));
4544 return false;
4547 status = cli_close(cli, fnum1);
4548 if (!NT_STATUS_IS_OK(status)) {
4549 printf("close %s failed (%s)\n",
4550 fname_ln, nt_errstr(status));
4551 return false;
4554 status = cli_close(cli, fnum);
4555 if (!NT_STATUS_IS_OK(status)) {
4556 printf("close %s failed (%s)\n",
4557 fname, nt_errstr(status));
4558 return false;
4561 /* Ensure the original file is still there. */
4562 status = cli_getatr(cli, fname, NULL, NULL, &t);
4563 if (!NT_STATUS_IS_OK(status)) {
4564 printf("%s getatr on file %s failed (%s)\n",
4565 __location__,
4566 fname,
4567 nt_errstr(status));
4568 correct = False;
4571 /* Ensure the link path is gone. */
4572 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4573 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4574 printf("%s, getatr for file %s returned wrong error code %s "
4575 "- should have been deleted\n",
4576 __location__,
4577 fname_ln, nt_errstr(status));
4578 correct = False;
4581 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4582 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4584 if (!torture_close_connection(cli)) {
4585 correct = false;
4588 printf("finished deletetest-ln\n");
4590 return correct;
4594 print out server properties
4596 static bool run_properties(int dummy)
4598 struct cli_state *cli;
4599 bool correct = True;
4601 printf("starting properties test\n");
4603 ZERO_STRUCT(cli);
4605 if (!torture_open_connection(&cli, 0)) {
4606 return False;
4609 smbXcli_conn_set_sockopt(cli->conn, sockops);
4611 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
4613 if (!torture_close_connection(cli)) {
4614 correct = False;
4617 return correct;
4622 /* FIRST_DESIRED_ACCESS 0xf019f */
4623 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4624 FILE_READ_EA| /* 0xf */ \
4625 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
4626 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
4627 DELETE_ACCESS|READ_CONTROL_ACCESS|\
4628 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
4629 /* SECOND_DESIRED_ACCESS 0xe0080 */
4630 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4631 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4632 WRITE_OWNER_ACCESS /* 0xe0000 */
4634 #if 0
4635 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4636 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4637 FILE_READ_DATA|\
4638 WRITE_OWNER_ACCESS /* */
4639 #endif
4642 Test ntcreate calls made by xcopy
4644 static bool run_xcopy(int dummy)
4646 static struct cli_state *cli1;
4647 const char *fname = "\\test.txt";
4648 bool correct = True;
4649 uint16_t fnum1, fnum2;
4650 NTSTATUS status;
4652 printf("starting xcopy test\n");
4654 if (!torture_open_connection(&cli1, 0)) {
4655 return False;
4658 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4659 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4660 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
4661 if (!NT_STATUS_IS_OK(status)) {
4662 printf("First open failed - %s\n", nt_errstr(status));
4663 return False;
4666 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4667 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4668 FILE_OPEN, 0x200000, 0, &fnum2, NULL);
4669 if (!NT_STATUS_IS_OK(status)) {
4670 printf("second open failed - %s\n", nt_errstr(status));
4671 return False;
4674 if (!torture_close_connection(cli1)) {
4675 correct = False;
4678 return correct;
4682 Test rename on files open with share delete and no share delete.
4684 static bool run_rename(int dummy)
4686 static struct cli_state *cli1;
4687 const char *fname = "\\test.txt";
4688 const char *fname1 = "\\test1.txt";
4689 bool correct = True;
4690 uint16_t fnum1;
4691 uint16_t attr;
4692 NTSTATUS status;
4694 printf("starting rename test\n");
4696 if (!torture_open_connection(&cli1, 0)) {
4697 return False;
4700 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4701 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4703 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4704 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4705 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4706 if (!NT_STATUS_IS_OK(status)) {
4707 printf("First open failed - %s\n", nt_errstr(status));
4708 return False;
4711 status = cli_rename(cli1, fname, fname1);
4712 if (!NT_STATUS_IS_OK(status)) {
4713 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4714 } else {
4715 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4716 correct = False;
4719 status = cli_close(cli1, fnum1);
4720 if (!NT_STATUS_IS_OK(status)) {
4721 printf("close - 1 failed (%s)\n", nt_errstr(status));
4722 return False;
4725 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4726 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4727 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4728 #if 0
4729 FILE_SHARE_DELETE|FILE_SHARE_NONE,
4730 #else
4731 FILE_SHARE_DELETE|FILE_SHARE_READ,
4732 #endif
4733 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4734 if (!NT_STATUS_IS_OK(status)) {
4735 printf("Second open failed - %s\n", nt_errstr(status));
4736 return False;
4739 status = cli_rename(cli1, fname, fname1);
4740 if (!NT_STATUS_IS_OK(status)) {
4741 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4742 correct = False;
4743 } else {
4744 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4747 status = cli_close(cli1, fnum1);
4748 if (!NT_STATUS_IS_OK(status)) {
4749 printf("close - 2 failed (%s)\n", nt_errstr(status));
4750 return False;
4753 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4754 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4756 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4757 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4758 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4759 if (!NT_STATUS_IS_OK(status)) {
4760 printf("Third open failed - %s\n", nt_errstr(status));
4761 return False;
4765 #if 0
4767 uint16_t fnum2;
4769 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4770 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
4771 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4772 return False;
4774 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4775 printf("[8] setting delete_on_close on file failed !\n");
4776 return False;
4779 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4780 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4781 return False;
4784 #endif
4786 status = cli_rename(cli1, fname, fname1);
4787 if (!NT_STATUS_IS_OK(status)) {
4788 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4789 correct = False;
4790 } else {
4791 printf("Third rename succeeded (SHARE_NONE)\n");
4794 status = cli_close(cli1, fnum1);
4795 if (!NT_STATUS_IS_OK(status)) {
4796 printf("close - 3 failed (%s)\n", nt_errstr(status));
4797 return False;
4800 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4801 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4803 /*----*/
4805 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4806 FILE_ATTRIBUTE_NORMAL,
4807 FILE_SHARE_READ | FILE_SHARE_WRITE,
4808 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4809 if (!NT_STATUS_IS_OK(status)) {
4810 printf("Fourth open failed - %s\n", nt_errstr(status));
4811 return False;
4814 status = cli_rename(cli1, fname, fname1);
4815 if (!NT_STATUS_IS_OK(status)) {
4816 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4817 } else {
4818 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4819 correct = False;
4822 status = cli_close(cli1, fnum1);
4823 if (!NT_STATUS_IS_OK(status)) {
4824 printf("close - 4 failed (%s)\n", nt_errstr(status));
4825 return False;
4828 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4829 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4831 /*--*/
4833 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4834 FILE_ATTRIBUTE_NORMAL,
4835 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4836 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4837 if (!NT_STATUS_IS_OK(status)) {
4838 printf("Fifth open failed - %s\n", nt_errstr(status));
4839 return False;
4842 status = cli_rename(cli1, fname, fname1);
4843 if (!NT_STATUS_IS_OK(status)) {
4844 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4845 correct = False;
4846 } else {
4847 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4851 * Now check if the first name still exists ...
4854 /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4855 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4856 FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
4857 printf("Opening original file after rename of open file fails: %s\n",
4858 cli_errstr(cli1));
4860 else {
4861 printf("Opening original file after rename of open file works ...\n");
4862 (void)cli_close(cli1, fnum2);
4863 } */
4865 /*--*/
4866 status = cli_close(cli1, fnum1);
4867 if (!NT_STATUS_IS_OK(status)) {
4868 printf("close - 5 failed (%s)\n", nt_errstr(status));
4869 return False;
4872 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4873 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4874 if (!NT_STATUS_IS_OK(status)) {
4875 printf("getatr on file %s failed - %s ! \n",
4876 fname1, nt_errstr(status));
4877 correct = False;
4878 } else {
4879 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4880 printf("Renamed file %s has wrong attr 0x%x "
4881 "(should be 0x%x)\n",
4882 fname1,
4883 attr,
4884 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4885 correct = False;
4886 } else {
4887 printf("Renamed file %s has archive bit set\n", fname1);
4891 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4892 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4894 if (!torture_close_connection(cli1)) {
4895 correct = False;
4898 return correct;
4901 static bool run_pipe_number(int dummy)
4903 struct cli_state *cli1;
4904 const char *pipe_name = "\\SPOOLSS";
4905 uint16_t fnum;
4906 int num_pipes = 0;
4907 NTSTATUS status;
4909 printf("starting pipenumber test\n");
4910 if (!torture_open_connection(&cli1, 0)) {
4911 return False;
4914 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4915 while(1) {
4916 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
4917 FILE_ATTRIBUTE_NORMAL,
4918 FILE_SHARE_READ|FILE_SHARE_WRITE,
4919 FILE_OPEN_IF, 0, 0, &fnum, NULL);
4920 if (!NT_STATUS_IS_OK(status)) {
4921 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
4922 break;
4924 num_pipes++;
4925 printf("\r%6d", num_pipes);
4928 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4929 torture_close_connection(cli1);
4930 return True;
4934 Test open mode returns on read-only files.
4936 static bool run_opentest(int dummy)
4938 static struct cli_state *cli1;
4939 static struct cli_state *cli2;
4940 const char *fname = "\\readonly.file";
4941 uint16_t fnum1, fnum2;
4942 char buf[20];
4943 off_t fsize;
4944 bool correct = True;
4945 char *tmp_path;
4946 NTSTATUS status;
4948 printf("starting open test\n");
4950 if (!torture_open_connection(&cli1, 0)) {
4951 return False;
4954 cli_setatr(cli1, fname, 0, 0);
4955 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4957 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4959 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4960 if (!NT_STATUS_IS_OK(status)) {
4961 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4962 return False;
4965 status = cli_close(cli1, fnum1);
4966 if (!NT_STATUS_IS_OK(status)) {
4967 printf("close2 failed (%s)\n", nt_errstr(status));
4968 return False;
4971 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
4972 if (!NT_STATUS_IS_OK(status)) {
4973 printf("cli_setatr failed (%s)\n", nt_errstr(status));
4974 return False;
4977 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4978 if (!NT_STATUS_IS_OK(status)) {
4979 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4980 return False;
4983 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4984 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4986 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
4987 NT_STATUS_ACCESS_DENIED)) {
4988 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4991 printf("finished open test 1\n");
4993 cli_close(cli1, fnum1);
4995 /* Now try not readonly and ensure ERRbadshare is returned. */
4997 cli_setatr(cli1, fname, 0, 0);
4999 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
5000 if (!NT_STATUS_IS_OK(status)) {
5001 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5002 return False;
5005 /* This will fail - but the error should be ERRshare. */
5006 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
5008 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
5009 NT_STATUS_SHARING_VIOLATION)) {
5010 printf("correct error code ERRDOS/ERRbadshare returned\n");
5013 status = cli_close(cli1, fnum1);
5014 if (!NT_STATUS_IS_OK(status)) {
5015 printf("close2 failed (%s)\n", nt_errstr(status));
5016 return False;
5019 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5021 printf("finished open test 2\n");
5023 /* Test truncate open disposition on file opened for read. */
5024 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
5025 if (!NT_STATUS_IS_OK(status)) {
5026 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
5027 return False;
5030 /* write 20 bytes. */
5032 memset(buf, '\0', 20);
5034 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
5035 if (!NT_STATUS_IS_OK(status)) {
5036 printf("write failed (%s)\n", nt_errstr(status));
5037 correct = False;
5040 status = cli_close(cli1, fnum1);
5041 if (!NT_STATUS_IS_OK(status)) {
5042 printf("(3) close1 failed (%s)\n", nt_errstr(status));
5043 return False;
5046 /* Ensure size == 20. */
5047 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5048 if (!NT_STATUS_IS_OK(status)) {
5049 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5050 return False;
5053 if (fsize != 20) {
5054 printf("(3) file size != 20\n");
5055 return False;
5058 /* Now test if we can truncate a file opened for readonly. */
5059 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
5060 if (!NT_STATUS_IS_OK(status)) {
5061 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
5062 return False;
5065 status = cli_close(cli1, fnum1);
5066 if (!NT_STATUS_IS_OK(status)) {
5067 printf("close2 failed (%s)\n", nt_errstr(status));
5068 return False;
5071 /* Ensure size == 0. */
5072 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5073 if (!NT_STATUS_IS_OK(status)) {
5074 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5075 return False;
5078 if (fsize != 0) {
5079 printf("(3) file size != 0\n");
5080 return False;
5082 printf("finished open test 3\n");
5084 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5086 printf("Do ctemp tests\n");
5087 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
5088 if (!NT_STATUS_IS_OK(status)) {
5089 printf("ctemp failed (%s)\n", nt_errstr(status));
5090 return False;
5093 printf("ctemp gave path %s\n", tmp_path);
5094 status = cli_close(cli1, fnum1);
5095 if (!NT_STATUS_IS_OK(status)) {
5096 printf("close of temp failed (%s)\n", nt_errstr(status));
5099 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5100 if (!NT_STATUS_IS_OK(status)) {
5101 printf("unlink of temp failed (%s)\n", nt_errstr(status));
5104 /* Test the non-io opens... */
5106 if (!torture_open_connection(&cli2, 1)) {
5107 return False;
5110 cli_setatr(cli2, fname, 0, 0);
5111 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5113 smbXcli_conn_set_sockopt(cli2->conn, sockops);
5115 printf("TEST #1 testing 2 non-io opens (no delete)\n");
5116 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5117 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5118 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5119 if (!NT_STATUS_IS_OK(status)) {
5120 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5121 return False;
5124 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5125 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5126 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5127 if (!NT_STATUS_IS_OK(status)) {
5128 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5129 return False;
5132 status = cli_close(cli1, fnum1);
5133 if (!NT_STATUS_IS_OK(status)) {
5134 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5135 return False;
5138 status = cli_close(cli2, fnum2);
5139 if (!NT_STATUS_IS_OK(status)) {
5140 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5141 return False;
5144 printf("non-io open test #1 passed.\n");
5146 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5148 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5150 status = cli_ntcreate(cli1, fname, 0,
5151 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5152 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5153 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5154 if (!NT_STATUS_IS_OK(status)) {
5155 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5156 return False;
5159 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5160 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5161 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5162 if (!NT_STATUS_IS_OK(status)) {
5163 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5164 return False;
5167 status = cli_close(cli1, fnum1);
5168 if (!NT_STATUS_IS_OK(status)) {
5169 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5170 return False;
5173 status = cli_close(cli2, fnum2);
5174 if (!NT_STATUS_IS_OK(status)) {
5175 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5176 return False;
5179 printf("non-io open test #2 passed.\n");
5181 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5183 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5185 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5186 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5187 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5188 if (!NT_STATUS_IS_OK(status)) {
5189 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5190 return False;
5193 status = cli_ntcreate(cli2, fname, 0,
5194 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5195 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5196 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5197 if (!NT_STATUS_IS_OK(status)) {
5198 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5199 return False;
5202 status = cli_close(cli1, fnum1);
5203 if (!NT_STATUS_IS_OK(status)) {
5204 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5205 return False;
5208 status = cli_close(cli2, fnum2);
5209 if (!NT_STATUS_IS_OK(status)) {
5210 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5211 return False;
5214 printf("non-io open test #3 passed.\n");
5216 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5218 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5220 status = cli_ntcreate(cli1, fname, 0,
5221 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5222 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5223 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5224 if (!NT_STATUS_IS_OK(status)) {
5225 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5226 return False;
5229 status = cli_ntcreate(cli2, fname, 0,
5230 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5231 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5232 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5233 if (NT_STATUS_IS_OK(status)) {
5234 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5235 return False;
5238 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5240 status = cli_close(cli1, fnum1);
5241 if (!NT_STATUS_IS_OK(status)) {
5242 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5243 return False;
5246 printf("non-io open test #4 passed.\n");
5248 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5250 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5252 status = cli_ntcreate(cli1, fname, 0,
5253 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5254 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5255 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5256 if (!NT_STATUS_IS_OK(status)) {
5257 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5258 return False;
5261 status = cli_ntcreate(cli2, fname, 0,
5262 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5263 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5264 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5265 if (!NT_STATUS_IS_OK(status)) {
5266 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5267 return False;
5270 status = cli_close(cli1, fnum1);
5271 if (!NT_STATUS_IS_OK(status)) {
5272 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5273 return False;
5276 status = cli_close(cli2, fnum2);
5277 if (!NT_STATUS_IS_OK(status)) {
5278 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5279 return False;
5282 printf("non-io open test #5 passed.\n");
5284 printf("TEST #6 testing 1 non-io open, one io open\n");
5286 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5288 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5289 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5290 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5291 if (!NT_STATUS_IS_OK(status)) {
5292 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5293 return False;
5296 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5297 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5298 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5299 if (!NT_STATUS_IS_OK(status)) {
5300 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5301 return False;
5304 status = cli_close(cli1, fnum1);
5305 if (!NT_STATUS_IS_OK(status)) {
5306 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5307 return False;
5310 status = cli_close(cli2, fnum2);
5311 if (!NT_STATUS_IS_OK(status)) {
5312 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5313 return False;
5316 printf("non-io open test #6 passed.\n");
5318 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5320 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5322 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5323 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5324 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5325 if (!NT_STATUS_IS_OK(status)) {
5326 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5327 return False;
5330 status = cli_ntcreate(cli2, fname, 0,
5331 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5332 FILE_ATTRIBUTE_NORMAL,
5333 FILE_SHARE_READ|FILE_SHARE_DELETE,
5334 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5335 if (NT_STATUS_IS_OK(status)) {
5336 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5337 return False;
5340 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5342 status = cli_close(cli1, fnum1);
5343 if (!NT_STATUS_IS_OK(status)) {
5344 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5345 return False;
5348 printf("non-io open test #7 passed.\n");
5350 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5352 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5353 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5354 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5355 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5356 if (!NT_STATUS_IS_OK(status)) {
5357 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5358 correct = false;
5359 goto out;
5362 /* Write to ensure we have to update the file time. */
5363 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5364 NULL);
5365 if (!NT_STATUS_IS_OK(status)) {
5366 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5367 correct = false;
5368 goto out;
5371 status = cli_close(cli1, fnum1);
5372 if (!NT_STATUS_IS_OK(status)) {
5373 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5374 correct = false;
5377 out:
5379 if (!torture_close_connection(cli1)) {
5380 correct = False;
5382 if (!torture_close_connection(cli2)) {
5383 correct = False;
5386 return correct;
5389 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5391 uint16_t major, minor;
5392 uint32_t caplow, caphigh;
5393 NTSTATUS status;
5395 if (!SERVER_HAS_UNIX_CIFS(cli)) {
5396 printf("Server doesn't support UNIX CIFS extensions.\n");
5397 return NT_STATUS_NOT_SUPPORTED;
5400 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5401 &caphigh);
5402 if (!NT_STATUS_IS_OK(status)) {
5403 printf("Server didn't return UNIX CIFS extensions: %s\n",
5404 nt_errstr(status));
5405 return status;
5408 status = cli_set_unix_extensions_capabilities(cli, major, minor,
5409 caplow, caphigh);
5410 if (!NT_STATUS_IS_OK(status)) {
5411 printf("Server doesn't support setting UNIX CIFS extensions: "
5412 "%s.\n", nt_errstr(status));
5413 return status;
5416 return NT_STATUS_OK;
5420 Test POSIX open /mkdir calls.
5422 static bool run_simple_posix_open_test(int dummy)
5424 static struct cli_state *cli1;
5425 const char *fname = "posix:file";
5426 const char *hname = "posix:hlink";
5427 const char *sname = "posix:symlink";
5428 const char *dname = "posix:dir";
5429 char buf[10];
5430 char namebuf[11];
5431 uint16_t fnum1 = (uint16_t)-1;
5432 SMB_STRUCT_STAT sbuf;
5433 bool correct = false;
5434 NTSTATUS status;
5435 size_t nread;
5436 const char *fname_windows = "windows_file";
5437 uint16_t fnum2 = (uint16_t)-1;
5439 printf("Starting simple POSIX open test\n");
5441 if (!torture_open_connection(&cli1, 0)) {
5442 return false;
5445 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5447 status = torture_setup_unix_extensions(cli1);
5448 if (!NT_STATUS_IS_OK(status)) {
5449 return false;
5452 cli_setatr(cli1, fname, 0, 0);
5453 cli_posix_unlink(cli1, fname);
5454 cli_setatr(cli1, dname, 0, 0);
5455 cli_posix_rmdir(cli1, dname);
5456 cli_setatr(cli1, hname, 0, 0);
5457 cli_posix_unlink(cli1, hname);
5458 cli_setatr(cli1, sname, 0, 0);
5459 cli_posix_unlink(cli1, sname);
5460 cli_setatr(cli1, fname_windows, 0, 0);
5461 cli_posix_unlink(cli1, fname_windows);
5463 /* Create a directory. */
5464 status = cli_posix_mkdir(cli1, dname, 0777);
5465 if (!NT_STATUS_IS_OK(status)) {
5466 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5467 goto out;
5470 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5471 0600, &fnum1);
5472 if (!NT_STATUS_IS_OK(status)) {
5473 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5474 goto out;
5477 /* Test ftruncate - set file size. */
5478 status = cli_ftruncate(cli1, fnum1, 1000);
5479 if (!NT_STATUS_IS_OK(status)) {
5480 printf("ftruncate failed (%s)\n", nt_errstr(status));
5481 goto out;
5484 /* Ensure st_size == 1000 */
5485 status = cli_posix_stat(cli1, fname, &sbuf);
5486 if (!NT_STATUS_IS_OK(status)) {
5487 printf("stat failed (%s)\n", nt_errstr(status));
5488 goto out;
5491 if (sbuf.st_ex_size != 1000) {
5492 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5493 goto out;
5496 /* Ensure st_mode == 0600 */
5497 if ((sbuf.st_ex_mode & 07777) != 0600) {
5498 printf("posix_open - bad permissions 0%o != 0600\n",
5499 (unsigned int)(sbuf.st_ex_mode & 07777));
5500 goto out;
5503 /* Test ftruncate - set file size back to zero. */
5504 status = cli_ftruncate(cli1, fnum1, 0);
5505 if (!NT_STATUS_IS_OK(status)) {
5506 printf("ftruncate failed (%s)\n", nt_errstr(status));
5507 goto out;
5510 status = cli_close(cli1, fnum1);
5511 if (!NT_STATUS_IS_OK(status)) {
5512 printf("close failed (%s)\n", nt_errstr(status));
5513 goto out;
5516 /* Now open the file again for read only. */
5517 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5518 if (!NT_STATUS_IS_OK(status)) {
5519 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5520 goto out;
5523 /* Now unlink while open. */
5524 status = cli_posix_unlink(cli1, fname);
5525 if (!NT_STATUS_IS_OK(status)) {
5526 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5527 goto out;
5530 status = cli_close(cli1, fnum1);
5531 if (!NT_STATUS_IS_OK(status)) {
5532 printf("close(2) failed (%s)\n", nt_errstr(status));
5533 goto out;
5536 /* Ensure the file has gone. */
5537 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5538 if (NT_STATUS_IS_OK(status)) {
5539 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5540 goto out;
5543 /* Create again to test open with O_TRUNC. */
5544 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
5545 if (!NT_STATUS_IS_OK(status)) {
5546 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5547 goto out;
5550 /* Test ftruncate - set file size. */
5551 status = cli_ftruncate(cli1, fnum1, 1000);
5552 if (!NT_STATUS_IS_OK(status)) {
5553 printf("ftruncate failed (%s)\n", nt_errstr(status));
5554 goto out;
5557 /* Ensure st_size == 1000 */
5558 status = cli_posix_stat(cli1, fname, &sbuf);
5559 if (!NT_STATUS_IS_OK(status)) {
5560 printf("stat failed (%s)\n", nt_errstr(status));
5561 goto out;
5564 if (sbuf.st_ex_size != 1000) {
5565 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5566 goto out;
5569 status = cli_close(cli1, fnum1);
5570 if (!NT_STATUS_IS_OK(status)) {
5571 printf("close(2) failed (%s)\n", nt_errstr(status));
5572 goto out;
5575 /* Re-open with O_TRUNC. */
5576 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
5577 if (!NT_STATUS_IS_OK(status)) {
5578 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5579 goto out;
5582 /* Ensure st_size == 0 */
5583 status = cli_posix_stat(cli1, fname, &sbuf);
5584 if (!NT_STATUS_IS_OK(status)) {
5585 printf("stat failed (%s)\n", nt_errstr(status));
5586 goto out;
5589 if (sbuf.st_ex_size != 0) {
5590 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5591 goto out;
5594 status = cli_close(cli1, fnum1);
5595 if (!NT_STATUS_IS_OK(status)) {
5596 printf("close failed (%s)\n", nt_errstr(status));
5597 goto out;
5600 status = cli_posix_unlink(cli1, fname);
5601 if (!NT_STATUS_IS_OK(status)) {
5602 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5603 goto out;
5606 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
5607 if (!NT_STATUS_IS_OK(status)) {
5608 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5609 dname, nt_errstr(status));
5610 goto out;
5613 cli_close(cli1, fnum1);
5615 /* What happens when we try and POSIX open a directory for write ? */
5616 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
5617 if (NT_STATUS_IS_OK(status)) {
5618 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5619 goto out;
5620 } else {
5621 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
5622 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5623 goto out;
5627 /* Create the file. */
5628 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5629 0600, &fnum1);
5630 if (!NT_STATUS_IS_OK(status)) {
5631 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5632 goto out;
5635 /* Write some data into it. */
5636 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5637 NULL);
5638 if (!NT_STATUS_IS_OK(status)) {
5639 printf("cli_write failed: %s\n", nt_errstr(status));
5640 goto out;
5643 cli_close(cli1, fnum1);
5645 /* Now create a hardlink. */
5646 status = cli_posix_hardlink(cli1, fname, hname);
5647 if (!NT_STATUS_IS_OK(status)) {
5648 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5649 goto out;
5652 /* Now create a symlink. */
5653 status = cli_posix_symlink(cli1, fname, sname);
5654 if (!NT_STATUS_IS_OK(status)) {
5655 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5656 goto out;
5659 /* Open the hardlink for read. */
5660 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5661 if (!NT_STATUS_IS_OK(status)) {
5662 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5663 goto out;
5666 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
5667 if (!NT_STATUS_IS_OK(status)) {
5668 printf("POSIX read of %s failed (%s)\n", hname,
5669 nt_errstr(status));
5670 goto out;
5671 } else if (nread != 10) {
5672 printf("POSIX read of %s failed. Received %ld, expected %d\n",
5673 hname, (unsigned long)nread, 10);
5674 goto out;
5677 if (memcmp(buf, "TEST DATA\n", 10)) {
5678 printf("invalid data read from hardlink\n");
5679 goto out;
5682 /* Do a POSIX lock/unlock. */
5683 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5684 if (!NT_STATUS_IS_OK(status)) {
5685 printf("POSIX lock failed %s\n", nt_errstr(status));
5686 goto out;
5689 /* Punch a hole in the locked area. */
5690 status = cli_posix_unlock(cli1, fnum1, 10, 80);
5691 if (!NT_STATUS_IS_OK(status)) {
5692 printf("POSIX unlock failed %s\n", nt_errstr(status));
5693 goto out;
5696 cli_close(cli1, fnum1);
5698 /* Open the symlink for read - this should fail. A POSIX
5699 client should not be doing opens on a symlink. */
5700 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5701 if (NT_STATUS_IS_OK(status)) {
5702 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5703 goto out;
5704 } else {
5705 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
5706 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5707 printf("POSIX open of %s should have failed "
5708 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5709 "failed with %s instead.\n",
5710 sname, nt_errstr(status));
5711 goto out;
5715 status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5716 if (!NT_STATUS_IS_OK(status)) {
5717 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5718 goto out;
5721 if (strcmp(namebuf, fname) != 0) {
5722 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5723 sname, fname, namebuf);
5724 goto out;
5727 status = cli_posix_rmdir(cli1, dname);
5728 if (!NT_STATUS_IS_OK(status)) {
5729 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5730 goto out;
5733 /* Check directory opens with a specific permission. */
5734 status = cli_posix_mkdir(cli1, dname, 0700);
5735 if (!NT_STATUS_IS_OK(status)) {
5736 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5737 goto out;
5740 /* Ensure st_mode == 0700 */
5741 status = cli_posix_stat(cli1, dname, &sbuf);
5742 if (!NT_STATUS_IS_OK(status)) {
5743 printf("stat failed (%s)\n", nt_errstr(status));
5744 goto out;
5747 if ((sbuf.st_ex_mode & 07777) != 0700) {
5748 printf("posix_mkdir - bad permissions 0%o != 0700\n",
5749 (unsigned int)(sbuf.st_ex_mode & 07777));
5750 goto out;
5754 * Now create a Windows file, and attempt a POSIX unlink.
5755 * This should fail with a sharing violation but due to:
5757 * [Bug 9571] Unlink after open causes smbd to panic
5759 * ensure we've fixed the lock ordering violation.
5762 status = cli_ntcreate(cli1, fname_windows, 0,
5763 FILE_READ_DATA|FILE_WRITE_DATA, 0,
5764 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5765 FILE_CREATE,
5766 0x0, 0x0, &fnum2, NULL);
5767 if (!NT_STATUS_IS_OK(status)) {
5768 printf("Windows create of %s failed (%s)\n", fname_windows,
5769 nt_errstr(status));
5770 goto out;
5773 /* Now try posix_unlink. */
5774 status = cli_posix_unlink(cli1, fname_windows);
5775 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5776 printf("POSIX unlink of %s should fail "
5777 "with NT_STATUS_SHARING_VIOLATION "
5778 "got %s instead !\n",
5779 fname_windows,
5780 nt_errstr(status));
5781 goto out;
5784 cli_close(cli1, fnum2);
5786 printf("Simple POSIX open test passed\n");
5787 correct = true;
5789 out:
5791 if (fnum1 != (uint16_t)-1) {
5792 cli_close(cli1, fnum1);
5793 fnum1 = (uint16_t)-1;
5796 if (fnum2 != (uint16_t)-1) {
5797 cli_close(cli1, fnum2);
5798 fnum2 = (uint16_t)-1;
5801 cli_setatr(cli1, sname, 0, 0);
5802 cli_posix_unlink(cli1, sname);
5803 cli_setatr(cli1, hname, 0, 0);
5804 cli_posix_unlink(cli1, hname);
5805 cli_setatr(cli1, fname, 0, 0);
5806 cli_posix_unlink(cli1, fname);
5807 cli_setatr(cli1, dname, 0, 0);
5808 cli_posix_rmdir(cli1, dname);
5809 cli_setatr(cli1, fname_windows, 0, 0);
5810 cli_posix_unlink(cli1, fname_windows);
5812 if (!torture_close_connection(cli1)) {
5813 correct = false;
5816 return correct;
5820 Test POSIX and Windows ACLs are rejected on symlinks.
5822 static bool run_acl_symlink_test(int dummy)
5824 static struct cli_state *cli;
5825 const char *fname = "posix_file";
5826 const char *sname = "posix_symlink";
5827 uint16_t fnum = (uint16_t)-1;
5828 bool correct = false;
5829 NTSTATUS status;
5830 char *posix_acl = NULL;
5831 size_t posix_acl_len = 0;
5832 char *posix_acl_sym = NULL;
5833 size_t posix_acl_len_sym = 0;
5834 struct security_descriptor *sd = NULL;
5835 struct security_descriptor *sd_sym = NULL;
5836 TALLOC_CTX *frame = NULL;
5838 frame = talloc_stackframe();
5840 printf("Starting acl symlink test\n");
5842 if (!torture_open_connection(&cli, 0)) {
5843 TALLOC_FREE(frame);
5844 return false;
5847 smbXcli_conn_set_sockopt(cli->conn, sockops);
5849 status = torture_setup_unix_extensions(cli);
5850 if (!NT_STATUS_IS_OK(status)) {
5851 TALLOC_FREE(frame);
5852 return false;
5855 cli_setatr(cli, fname, 0, 0);
5856 cli_posix_unlink(cli, fname);
5857 cli_setatr(cli, sname, 0, 0);
5858 cli_posix_unlink(cli, sname);
5860 status = cli_ntcreate(cli,
5861 fname,
5863 READ_CONTROL_ACCESS,
5865 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5866 FILE_CREATE,
5867 0x0,
5868 0x0,
5869 &fnum,
5870 NULL);
5872 if (!NT_STATUS_IS_OK(status)) {
5873 printf("cli_ntcreate of %s failed (%s)\n",
5874 fname,
5875 nt_errstr(status));
5876 goto out;
5879 /* Get the Windows ACL on the file. */
5880 status = cli_query_secdesc(cli,
5881 fnum,
5882 frame,
5883 &sd);
5884 if (!NT_STATUS_IS_OK(status)) {
5885 printf("cli_query_secdesc failed (%s)\n",
5886 nt_errstr(status));
5887 goto out;
5890 /* Get the POSIX ACL on the file. */
5891 status = cli_posix_getacl(cli,
5892 fname,
5893 frame,
5894 &posix_acl_len,
5895 &posix_acl);
5897 if (!NT_STATUS_IS_OK(status)) {
5898 printf("cli_posix_getacl failed (%s)\n",
5899 nt_errstr(status));
5900 goto out;
5903 status = cli_close(cli, fnum);
5904 if (!NT_STATUS_IS_OK(status)) {
5905 printf("close failed (%s)\n", nt_errstr(status));
5906 goto out;
5908 fnum = (uint16_t)-1;
5910 /* Now create a symlink. */
5911 status = cli_posix_symlink(cli, fname, sname);
5912 if (!NT_STATUS_IS_OK(status)) {
5913 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
5914 sname,
5915 fname,
5916 nt_errstr(status));
5917 goto out;
5920 /* Open a handle on the symlink. */
5921 status = cli_ntcreate(cli,
5922 sname,
5924 READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
5926 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5927 FILE_OPEN,
5928 0x0,
5929 0x0,
5930 &fnum,
5931 NULL);
5933 if (!NT_STATUS_IS_OK(status)) {
5934 printf("cli_posix_open of %s failed (%s)\n",
5935 sname,
5936 nt_errstr(status));
5937 goto out;
5940 /* Get the Windows ACL on the symlink handle. Should fail */
5941 status = cli_query_secdesc(cli,
5942 fnum,
5943 frame,
5944 &sd_sym);
5946 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5947 printf("cli_query_secdesc on a symlink gave %s. "
5948 "Should be NT_STATUS_ACCESS_DENIED.\n",
5949 nt_errstr(status));
5950 goto out;
5953 /* Get the POSIX ACL on the symlink pathname. Should fail. */
5954 status = cli_posix_getacl(cli,
5955 sname,
5956 frame,
5957 &posix_acl_len_sym,
5958 &posix_acl_sym);
5960 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5961 printf("cli_posix_getacl on a symlink gave %s. "
5962 "Should be NT_STATUS_ACCESS_DENIED.\n",
5963 nt_errstr(status));
5964 goto out;
5967 /* Set the Windows ACL on the symlink handle. Should fail */
5968 status = cli_set_security_descriptor(cli,
5969 fnum,
5970 SECINFO_DACL,
5971 sd);
5973 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5974 printf("cli_query_secdesc on a symlink gave %s. "
5975 "Should be NT_STATUS_ACCESS_DENIED.\n",
5976 nt_errstr(status));
5977 goto out;
5980 /* Set the POSIX ACL on the symlink pathname. Should fail. */
5981 status = cli_posix_setacl(cli,
5982 sname,
5983 posix_acl,
5984 posix_acl_len);
5986 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5987 printf("cli_posix_getacl on a symlink gave %s. "
5988 "Should be NT_STATUS_ACCESS_DENIED.\n",
5989 nt_errstr(status));
5990 goto out;
5993 printf("ACL symlink test passed\n");
5994 correct = true;
5996 out:
5998 if (fnum != (uint16_t)-1) {
5999 cli_close(cli, fnum);
6000 fnum = (uint16_t)-1;
6003 cli_setatr(cli, sname, 0, 0);
6004 cli_posix_unlink(cli, sname);
6005 cli_setatr(cli, fname, 0, 0);
6006 cli_posix_unlink(cli, fname);
6008 if (!torture_close_connection(cli)) {
6009 correct = false;
6012 TALLOC_FREE(frame);
6013 return correct;
6017 static uint32_t open_attrs_table[] = {
6018 FILE_ATTRIBUTE_NORMAL,
6019 FILE_ATTRIBUTE_ARCHIVE,
6020 FILE_ATTRIBUTE_READONLY,
6021 FILE_ATTRIBUTE_HIDDEN,
6022 FILE_ATTRIBUTE_SYSTEM,
6024 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
6025 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
6026 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
6027 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
6028 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
6029 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
6031 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
6032 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
6033 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
6034 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
6037 struct trunc_open_results {
6038 unsigned int num;
6039 uint32_t init_attr;
6040 uint32_t trunc_attr;
6041 uint32_t result_attr;
6044 static struct trunc_open_results attr_results[] = {
6045 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
6046 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
6047 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
6048 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
6049 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
6050 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
6051 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
6052 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
6053 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
6054 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
6055 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
6056 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
6057 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
6058 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
6059 { 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 },
6060 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
6061 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
6062 { 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 },
6063 { 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 },
6064 { 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 },
6065 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
6066 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
6067 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
6068 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
6069 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
6070 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
6073 static bool run_openattrtest(int dummy)
6075 static struct cli_state *cli1;
6076 const char *fname = "\\openattr.file";
6077 uint16_t fnum1;
6078 bool correct = True;
6079 uint16_t attr;
6080 unsigned int i, j, k, l;
6081 NTSTATUS status;
6083 printf("starting open attr test\n");
6085 if (!torture_open_connection(&cli1, 0)) {
6086 return False;
6089 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6091 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
6092 cli_setatr(cli1, fname, 0, 0);
6093 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6095 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
6096 open_attrs_table[i], FILE_SHARE_NONE,
6097 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6098 if (!NT_STATUS_IS_OK(status)) {
6099 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
6100 return False;
6103 status = cli_close(cli1, fnum1);
6104 if (!NT_STATUS_IS_OK(status)) {
6105 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
6106 return False;
6109 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
6110 status = cli_ntcreate(cli1, fname, 0,
6111 FILE_READ_DATA|FILE_WRITE_DATA,
6112 open_attrs_table[j],
6113 FILE_SHARE_NONE, FILE_OVERWRITE,
6114 0, 0, &fnum1, NULL);
6115 if (!NT_STATUS_IS_OK(status)) {
6116 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
6117 if (attr_results[l].num == k) {
6118 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
6119 k, open_attrs_table[i],
6120 open_attrs_table[j],
6121 fname, NT_STATUS_V(status), nt_errstr(status));
6122 correct = False;
6126 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6127 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
6128 k, open_attrs_table[i], open_attrs_table[j],
6129 nt_errstr(status));
6130 correct = False;
6132 #if 0
6133 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
6134 #endif
6135 k++;
6136 continue;
6139 status = cli_close(cli1, fnum1);
6140 if (!NT_STATUS_IS_OK(status)) {
6141 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
6142 return False;
6145 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
6146 if (!NT_STATUS_IS_OK(status)) {
6147 printf("getatr(2) failed (%s)\n", nt_errstr(status));
6148 return False;
6151 #if 0
6152 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
6153 k, open_attrs_table[i], open_attrs_table[j], attr );
6154 #endif
6156 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
6157 if (attr_results[l].num == k) {
6158 if (attr != attr_results[l].result_attr ||
6159 open_attrs_table[i] != attr_results[l].init_attr ||
6160 open_attrs_table[j] != attr_results[l].trunc_attr) {
6161 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
6162 open_attrs_table[i],
6163 open_attrs_table[j],
6164 (unsigned int)attr,
6165 attr_results[l].result_attr);
6166 correct = False;
6168 break;
6171 k++;
6175 cli_setatr(cli1, fname, 0, 0);
6176 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6178 printf("open attr test %s.\n", correct ? "passed" : "failed");
6180 if (!torture_close_connection(cli1)) {
6181 correct = False;
6183 return correct;
6186 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
6187 const char *name, void *state)
6189 int *matched = (int *)state;
6190 if (matched != NULL) {
6191 *matched += 1;
6193 return NT_STATUS_OK;
6197 test directory listing speed
6199 static bool run_dirtest(int dummy)
6201 int i;
6202 static struct cli_state *cli;
6203 uint16_t fnum;
6204 struct timeval core_start;
6205 bool correct = True;
6206 int matched;
6208 printf("starting directory test\n");
6210 if (!torture_open_connection(&cli, 0)) {
6211 return False;
6214 smbXcli_conn_set_sockopt(cli->conn, sockops);
6216 srandom(0);
6217 for (i=0;i<torture_numops;i++) {
6218 fstring fname;
6219 slprintf(fname, sizeof(fname), "\\%x", (int)random());
6220 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
6221 fprintf(stderr,"Failed to open %s\n", fname);
6222 return False;
6224 cli_close(cli, fnum);
6227 core_start = timeval_current();
6229 matched = 0;
6230 cli_list(cli, "a*.*", 0, list_fn, &matched);
6231 printf("Matched %d\n", matched);
6233 matched = 0;
6234 cli_list(cli, "b*.*", 0, list_fn, &matched);
6235 printf("Matched %d\n", matched);
6237 matched = 0;
6238 cli_list(cli, "xyzabc", 0, list_fn, &matched);
6239 printf("Matched %d\n", matched);
6241 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
6243 srandom(0);
6244 for (i=0;i<torture_numops;i++) {
6245 fstring fname;
6246 slprintf(fname, sizeof(fname), "\\%x", (int)random());
6247 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6250 if (!torture_close_connection(cli)) {
6251 correct = False;
6254 printf("finished dirtest\n");
6256 return correct;
6259 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
6260 void *state)
6262 struct cli_state *pcli = (struct cli_state *)state;
6263 fstring fname;
6264 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
6266 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
6267 return NT_STATUS_OK;
6269 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
6270 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
6271 printf("del_fn: failed to rmdir %s\n,", fname );
6272 } else {
6273 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
6274 printf("del_fn: failed to unlink %s\n,", fname );
6276 return NT_STATUS_OK;
6281 sees what IOCTLs are supported
6283 bool torture_ioctl_test(int dummy)
6285 static struct cli_state *cli;
6286 uint16_t device, function;
6287 uint16_t fnum;
6288 const char *fname = "\\ioctl.dat";
6289 DATA_BLOB blob;
6290 NTSTATUS status;
6292 if (!torture_open_connection(&cli, 0)) {
6293 return False;
6296 printf("starting ioctl test\n");
6298 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6300 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6301 if (!NT_STATUS_IS_OK(status)) {
6302 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6303 return False;
6306 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
6307 printf("ioctl device info: %s\n", nt_errstr(status));
6309 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
6310 printf("ioctl job info: %s\n", nt_errstr(status));
6312 for (device=0;device<0x100;device++) {
6313 printf("ioctl test with device = 0x%x\n", device);
6314 for (function=0;function<0x100;function++) {
6315 uint32_t code = (device<<16) | function;
6317 status = cli_raw_ioctl(cli, fnum, code, &blob);
6319 if (NT_STATUS_IS_OK(status)) {
6320 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
6321 (int)blob.length);
6322 data_blob_free(&blob);
6327 if (!torture_close_connection(cli)) {
6328 return False;
6331 return True;
6336 tries varients of chkpath
6338 bool torture_chkpath_test(int dummy)
6340 static struct cli_state *cli;
6341 uint16_t fnum;
6342 bool ret;
6343 NTSTATUS status;
6345 if (!torture_open_connection(&cli, 0)) {
6346 return False;
6349 printf("starting chkpath test\n");
6351 /* cleanup from an old run */
6352 cli_rmdir(cli, "\\chkpath.dir\\dir2");
6353 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6354 cli_rmdir(cli, "\\chkpath.dir");
6356 status = cli_mkdir(cli, "\\chkpath.dir");
6357 if (!NT_STATUS_IS_OK(status)) {
6358 printf("mkdir1 failed : %s\n", nt_errstr(status));
6359 return False;
6362 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
6363 if (!NT_STATUS_IS_OK(status)) {
6364 printf("mkdir2 failed : %s\n", nt_errstr(status));
6365 return False;
6368 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
6369 DENY_NONE, &fnum);
6370 if (!NT_STATUS_IS_OK(status)) {
6371 printf("open1 failed (%s)\n", nt_errstr(status));
6372 return False;
6374 cli_close(cli, fnum);
6376 status = cli_chkpath(cli, "\\chkpath.dir");
6377 if (!NT_STATUS_IS_OK(status)) {
6378 printf("chkpath1 failed: %s\n", nt_errstr(status));
6379 ret = False;
6382 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
6383 if (!NT_STATUS_IS_OK(status)) {
6384 printf("chkpath2 failed: %s\n", nt_errstr(status));
6385 ret = False;
6388 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
6389 if (!NT_STATUS_IS_OK(status)) {
6390 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6391 NT_STATUS_NOT_A_DIRECTORY);
6392 } else {
6393 printf("* chkpath on a file should fail\n");
6394 ret = False;
6397 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
6398 if (!NT_STATUS_IS_OK(status)) {
6399 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
6400 NT_STATUS_OBJECT_NAME_NOT_FOUND);
6401 } else {
6402 printf("* chkpath on a non existent file should fail\n");
6403 ret = False;
6406 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
6407 if (!NT_STATUS_IS_OK(status)) {
6408 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6409 NT_STATUS_OBJECT_PATH_NOT_FOUND);
6410 } else {
6411 printf("* chkpath on a non existent component should fail\n");
6412 ret = False;
6415 cli_rmdir(cli, "\\chkpath.dir\\dir2");
6416 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6417 cli_rmdir(cli, "\\chkpath.dir");
6419 if (!torture_close_connection(cli)) {
6420 return False;
6423 return ret;
6426 static bool run_eatest(int dummy)
6428 static struct cli_state *cli;
6429 const char *fname = "\\eatest.txt";
6430 bool correct = True;
6431 uint16_t fnum;
6432 int i;
6433 size_t num_eas;
6434 struct ea_struct *ea_list = NULL;
6435 TALLOC_CTX *mem_ctx = talloc_init("eatest");
6436 NTSTATUS status;
6438 printf("starting eatest\n");
6440 if (!torture_open_connection(&cli, 0)) {
6441 talloc_destroy(mem_ctx);
6442 return False;
6445 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6447 status = cli_ntcreate(cli, fname, 0,
6448 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6449 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
6450 0x4044, 0, &fnum, NULL);
6451 if (!NT_STATUS_IS_OK(status)) {
6452 printf("open failed - %s\n", nt_errstr(status));
6453 talloc_destroy(mem_ctx);
6454 return False;
6457 for (i = 0; i < 10; i++) {
6458 fstring ea_name, ea_val;
6460 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
6461 memset(ea_val, (char)i+1, i+1);
6462 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
6463 if (!NT_STATUS_IS_OK(status)) {
6464 printf("ea_set of name %s failed - %s\n", ea_name,
6465 nt_errstr(status));
6466 talloc_destroy(mem_ctx);
6467 return False;
6471 cli_close(cli, fnum);
6472 for (i = 0; i < 10; i++) {
6473 fstring ea_name, ea_val;
6475 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
6476 memset(ea_val, (char)i+1, i+1);
6477 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
6478 if (!NT_STATUS_IS_OK(status)) {
6479 printf("ea_set of name %s failed - %s\n", ea_name,
6480 nt_errstr(status));
6481 talloc_destroy(mem_ctx);
6482 return False;
6486 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6487 if (!NT_STATUS_IS_OK(status)) {
6488 printf("ea_get list failed - %s\n", nt_errstr(status));
6489 correct = False;
6492 printf("num_eas = %d\n", (int)num_eas);
6494 if (num_eas != 20) {
6495 printf("Should be 20 EA's stored... failing.\n");
6496 correct = False;
6499 for (i = 0; i < num_eas; i++) {
6500 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6501 dump_data(0, ea_list[i].value.data,
6502 ea_list[i].value.length);
6505 /* Setting EA's to zero length deletes them. Test this */
6506 printf("Now deleting all EA's - case indepenent....\n");
6508 #if 1
6509 cli_set_ea_path(cli, fname, "", "", 0);
6510 #else
6511 for (i = 0; i < 20; i++) {
6512 fstring ea_name;
6513 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
6514 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
6515 if (!NT_STATUS_IS_OK(status)) {
6516 printf("ea_set of name %s failed - %s\n", ea_name,
6517 nt_errstr(status));
6518 talloc_destroy(mem_ctx);
6519 return False;
6522 #endif
6524 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6525 if (!NT_STATUS_IS_OK(status)) {
6526 printf("ea_get list failed - %s\n", nt_errstr(status));
6527 correct = False;
6530 printf("num_eas = %d\n", (int)num_eas);
6531 for (i = 0; i < num_eas; i++) {
6532 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6533 dump_data(0, ea_list[i].value.data,
6534 ea_list[i].value.length);
6537 if (num_eas != 0) {
6538 printf("deleting EA's failed.\n");
6539 correct = False;
6542 /* Try and delete a non existent EA. */
6543 status = cli_set_ea_path(cli, fname, "foo", "", 0);
6544 if (!NT_STATUS_IS_OK(status)) {
6545 printf("deleting non-existent EA 'foo' should succeed. %s\n",
6546 nt_errstr(status));
6547 correct = False;
6550 talloc_destroy(mem_ctx);
6551 if (!torture_close_connection(cli)) {
6552 correct = False;
6555 return correct;
6558 static bool run_dirtest1(int dummy)
6560 int i;
6561 static struct cli_state *cli;
6562 uint16_t fnum;
6563 int num_seen;
6564 bool correct = True;
6566 printf("starting directory test\n");
6568 if (!torture_open_connection(&cli, 0)) {
6569 return False;
6572 smbXcli_conn_set_sockopt(cli->conn, sockops);
6574 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6575 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6576 cli_rmdir(cli, "\\LISTDIR");
6577 cli_mkdir(cli, "\\LISTDIR");
6579 /* Create 1000 files and 1000 directories. */
6580 for (i=0;i<1000;i++) {
6581 fstring fname;
6582 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6583 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6584 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
6585 0, 0, &fnum, NULL))) {
6586 fprintf(stderr,"Failed to open %s\n", fname);
6587 return False;
6589 cli_close(cli, fnum);
6591 for (i=0;i<1000;i++) {
6592 fstring fname;
6593 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6594 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6595 fprintf(stderr,"Failed to open %s\n", fname);
6596 return False;
6600 /* Now ensure that doing an old list sees both files and directories. */
6601 num_seen = 0;
6602 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6603 printf("num_seen = %d\n", num_seen );
6604 /* We should see 100 files + 1000 directories + . and .. */
6605 if (num_seen != 2002)
6606 correct = False;
6608 /* Ensure if we have the "must have" bits we only see the
6609 * relevent entries.
6611 num_seen = 0;
6612 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6613 printf("num_seen = %d\n", num_seen );
6614 if (num_seen != 1002)
6615 correct = False;
6617 num_seen = 0;
6618 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6619 printf("num_seen = %d\n", num_seen );
6620 if (num_seen != 1000)
6621 correct = False;
6623 /* Delete everything. */
6624 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6625 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6626 cli_rmdir(cli, "\\LISTDIR");
6628 #if 0
6629 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6630 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6631 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6632 #endif
6634 if (!torture_close_connection(cli)) {
6635 correct = False;
6638 printf("finished dirtest1\n");
6640 return correct;
6643 static bool run_error_map_extract(int dummy) {
6645 static struct cli_state *c_dos;
6646 static struct cli_state *c_nt;
6647 NTSTATUS status;
6649 uint32_t error;
6651 uint32_t errnum;
6652 uint8_t errclass;
6654 NTSTATUS nt_status;
6656 fstring user;
6658 /* NT-Error connection */
6660 disable_spnego = true;
6661 if (!(c_nt = open_nbt_connection())) {
6662 disable_spnego = false;
6663 return False;
6665 disable_spnego = false;
6667 status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
6668 PROTOCOL_NT1);
6670 if (!NT_STATUS_IS_OK(status)) {
6671 printf("%s rejected the NT-error negprot (%s)\n", host,
6672 nt_errstr(status));
6673 cli_shutdown(c_nt);
6674 return False;
6677 status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6678 if (!NT_STATUS_IS_OK(status)) {
6679 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6680 return False;
6683 /* DOS-Error connection */
6685 disable_spnego = true;
6686 force_dos_errors = true;
6687 if (!(c_dos = open_nbt_connection())) {
6688 disable_spnego = false;
6689 force_dos_errors = false;
6690 return False;
6692 disable_spnego = false;
6693 force_dos_errors = false;
6695 status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
6696 PROTOCOL_NT1);
6697 if (!NT_STATUS_IS_OK(status)) {
6698 printf("%s rejected the DOS-error negprot (%s)\n", host,
6699 nt_errstr(status));
6700 cli_shutdown(c_dos);
6701 return False;
6704 status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
6705 if (!NT_STATUS_IS_OK(status)) {
6706 printf("%s rejected the DOS-error initial session setup (%s)\n",
6707 host, nt_errstr(status));
6708 return False;
6711 c_nt->map_dos_errors = false;
6712 c_dos->map_dos_errors = false;
6714 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
6715 fstr_sprintf(user, "%X", error);
6717 status = cli_session_setup(c_nt, user,
6718 password, strlen(password),
6719 password, strlen(password),
6720 workgroup);
6721 if (NT_STATUS_IS_OK(status)) {
6722 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6725 /* Case #1: 32-bit NT errors */
6726 if (!NT_STATUS_IS_DOS(status)) {
6727 nt_status = status;
6728 } else {
6729 printf("/** Dos error on NT connection! (%s) */\n",
6730 nt_errstr(status));
6731 nt_status = NT_STATUS(0xc0000000);
6734 status = cli_session_setup(c_dos, user,
6735 password, strlen(password),
6736 password, strlen(password),
6737 workgroup);
6738 if (NT_STATUS_IS_OK(status)) {
6739 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6742 /* Case #1: 32-bit NT errors */
6743 if (NT_STATUS_IS_DOS(status)) {
6744 printf("/** NT error on DOS connection! (%s) */\n",
6745 nt_errstr(status));
6746 errnum = errclass = 0;
6747 } else {
6748 errclass = NT_STATUS_DOS_CLASS(status);
6749 errnum = NT_STATUS_DOS_CODE(status);
6752 if (NT_STATUS_V(nt_status) != error) {
6753 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
6754 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
6755 get_nt_error_c_code(talloc_tos(), nt_status));
6758 printf("\t{%s,\t%s,\t%s},\n",
6759 smb_dos_err_class(errclass),
6760 smb_dos_err_name(errclass, errnum),
6761 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
6763 return True;
6766 static bool run_sesssetup_bench(int dummy)
6768 static struct cli_state *c;
6769 const char *fname = "\\file.dat";
6770 uint16_t fnum;
6771 NTSTATUS status;
6772 int i;
6774 if (!torture_open_connection(&c, 0)) {
6775 return false;
6778 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6779 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6780 FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
6781 if (!NT_STATUS_IS_OK(status)) {
6782 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6783 return false;
6786 for (i=0; i<torture_numops; i++) {
6787 status = cli_session_setup(
6788 c, username,
6789 password, strlen(password),
6790 password, strlen(password),
6791 workgroup);
6792 if (!NT_STATUS_IS_OK(status)) {
6793 d_printf("(%s) cli_session_setup failed: %s\n",
6794 __location__, nt_errstr(status));
6795 return false;
6798 d_printf("\r%d ", (int)cli_state_get_uid(c));
6800 status = cli_ulogoff(c);
6801 if (!NT_STATUS_IS_OK(status)) {
6802 d_printf("(%s) cli_ulogoff failed: %s\n",
6803 __location__, nt_errstr(status));
6804 return false;
6808 return true;
6811 static bool subst_test(const char *str, const char *user, const char *domain,
6812 uid_t uid, gid_t gid, const char *expected)
6814 char *subst;
6815 bool result = true;
6817 subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
6819 if (strcmp(subst, expected) != 0) {
6820 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
6821 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
6822 expected);
6823 result = false;
6826 TALLOC_FREE(subst);
6827 return result;
6830 static void chain1_open_completion(struct tevent_req *req)
6832 uint16_t fnum;
6833 NTSTATUS status;
6834 status = cli_openx_recv(req, &fnum);
6835 TALLOC_FREE(req);
6837 d_printf("cli_openx_recv returned %s: %d\n",
6838 nt_errstr(status),
6839 NT_STATUS_IS_OK(status) ? fnum : -1);
6842 static void chain1_write_completion(struct tevent_req *req)
6844 size_t written;
6845 NTSTATUS status;
6846 status = cli_write_andx_recv(req, &written);
6847 TALLOC_FREE(req);
6849 d_printf("cli_write_andx_recv returned %s: %d\n",
6850 nt_errstr(status),
6851 NT_STATUS_IS_OK(status) ? (int)written : -1);
6854 static void chain1_close_completion(struct tevent_req *req)
6856 NTSTATUS status;
6857 bool *done = (bool *)tevent_req_callback_data_void(req);
6859 status = cli_close_recv(req);
6860 *done = true;
6862 TALLOC_FREE(req);
6864 d_printf("cli_close returned %s\n", nt_errstr(status));
6867 static bool run_chain1(int dummy)
6869 struct cli_state *cli1;
6870 struct tevent_context *evt = samba_tevent_context_init(NULL);
6871 struct tevent_req *reqs[3], *smbreqs[3];
6872 bool done = false;
6873 const char *str = "foobar";
6874 NTSTATUS status;
6876 printf("starting chain1 test\n");
6877 if (!torture_open_connection(&cli1, 0)) {
6878 return False;
6881 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6883 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, "\\test",
6884 O_CREAT|O_RDWR, 0, &smbreqs[0]);
6885 if (reqs[0] == NULL) return false;
6886 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
6889 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
6890 (const uint8_t *)str, 0, strlen(str)+1,
6891 smbreqs, 1, &smbreqs[1]);
6892 if (reqs[1] == NULL) return false;
6893 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
6895 reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
6896 if (reqs[2] == NULL) return false;
6897 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
6899 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
6900 if (!NT_STATUS_IS_OK(status)) {
6901 return false;
6904 while (!done) {
6905 tevent_loop_once(evt);
6908 torture_close_connection(cli1);
6909 return True;
6912 static void chain2_sesssetup_completion(struct tevent_req *req)
6914 NTSTATUS status;
6915 status = cli_session_setup_guest_recv(req);
6916 d_printf("sesssetup returned %s\n", nt_errstr(status));
6919 static void chain2_tcon_completion(struct tevent_req *req)
6921 bool *done = (bool *)tevent_req_callback_data_void(req);
6922 NTSTATUS status;
6923 status = cli_tcon_andx_recv(req);
6924 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
6925 *done = true;
6928 static bool run_chain2(int dummy)
6930 struct cli_state *cli1;
6931 struct tevent_context *evt = samba_tevent_context_init(NULL);
6932 struct tevent_req *reqs[2], *smbreqs[2];
6933 bool done = false;
6934 NTSTATUS status;
6936 printf("starting chain2 test\n");
6937 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
6938 port_to_use, SMB_SIGNING_DEFAULT, 0);
6939 if (!NT_STATUS_IS_OK(status)) {
6940 return False;
6943 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6945 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
6946 &smbreqs[0]);
6947 if (reqs[0] == NULL) return false;
6948 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
6950 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
6951 "?????", NULL, 0, &smbreqs[1]);
6952 if (reqs[1] == NULL) return false;
6953 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
6955 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
6956 if (!NT_STATUS_IS_OK(status)) {
6957 return false;
6960 while (!done) {
6961 tevent_loop_once(evt);
6964 torture_close_connection(cli1);
6965 return True;
6969 struct torture_createdel_state {
6970 struct tevent_context *ev;
6971 struct cli_state *cli;
6974 static void torture_createdel_created(struct tevent_req *subreq);
6975 static void torture_createdel_closed(struct tevent_req *subreq);
6977 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
6978 struct tevent_context *ev,
6979 struct cli_state *cli,
6980 const char *name)
6982 struct tevent_req *req, *subreq;
6983 struct torture_createdel_state *state;
6985 req = tevent_req_create(mem_ctx, &state,
6986 struct torture_createdel_state);
6987 if (req == NULL) {
6988 return NULL;
6990 state->ev = ev;
6991 state->cli = cli;
6993 subreq = cli_ntcreate_send(
6994 state, ev, cli, name, 0,
6995 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
6996 FILE_ATTRIBUTE_NORMAL,
6997 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6998 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
7000 if (tevent_req_nomem(subreq, req)) {
7001 return tevent_req_post(req, ev);
7003 tevent_req_set_callback(subreq, torture_createdel_created, req);
7004 return req;
7007 static void torture_createdel_created(struct tevent_req *subreq)
7009 struct tevent_req *req = tevent_req_callback_data(
7010 subreq, struct tevent_req);
7011 struct torture_createdel_state *state = tevent_req_data(
7012 req, struct torture_createdel_state);
7013 NTSTATUS status;
7014 uint16_t fnum;
7016 status = cli_ntcreate_recv(subreq, &fnum, NULL);
7017 TALLOC_FREE(subreq);
7018 if (tevent_req_nterror(req, status)) {
7019 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
7020 nt_errstr(status)));
7021 return;
7024 subreq = cli_close_send(state, state->ev, state->cli, fnum);
7025 if (tevent_req_nomem(subreq, req)) {
7026 return;
7028 tevent_req_set_callback(subreq, torture_createdel_closed, req);
7031 static void torture_createdel_closed(struct tevent_req *subreq)
7033 struct tevent_req *req = tevent_req_callback_data(
7034 subreq, struct tevent_req);
7035 NTSTATUS status;
7037 status = cli_close_recv(subreq);
7038 if (tevent_req_nterror(req, status)) {
7039 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
7040 return;
7042 tevent_req_done(req);
7045 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
7047 return tevent_req_simple_recv_ntstatus(req);
7050 struct torture_createdels_state {
7051 struct tevent_context *ev;
7052 struct cli_state *cli;
7053 const char *base_name;
7054 int sent;
7055 int received;
7056 int num_files;
7057 struct tevent_req **reqs;
7060 static void torture_createdels_done(struct tevent_req *subreq);
7062 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
7063 struct tevent_context *ev,
7064 struct cli_state *cli,
7065 const char *base_name,
7066 int num_parallel,
7067 int num_files)
7069 struct tevent_req *req;
7070 struct torture_createdels_state *state;
7071 int i;
7073 req = tevent_req_create(mem_ctx, &state,
7074 struct torture_createdels_state);
7075 if (req == NULL) {
7076 return NULL;
7078 state->ev = ev;
7079 state->cli = cli;
7080 state->base_name = talloc_strdup(state, base_name);
7081 if (tevent_req_nomem(state->base_name, req)) {
7082 return tevent_req_post(req, ev);
7084 state->num_files = MAX(num_parallel, num_files);
7085 state->sent = 0;
7086 state->received = 0;
7088 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
7089 if (tevent_req_nomem(state->reqs, req)) {
7090 return tevent_req_post(req, ev);
7093 for (i=0; i<num_parallel; i++) {
7094 char *name;
7096 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
7097 state->sent);
7098 if (tevent_req_nomem(name, req)) {
7099 return tevent_req_post(req, ev);
7101 state->reqs[i] = torture_createdel_send(
7102 state->reqs, state->ev, state->cli, name);
7103 if (tevent_req_nomem(state->reqs[i], req)) {
7104 return tevent_req_post(req, ev);
7106 name = talloc_move(state->reqs[i], &name);
7107 tevent_req_set_callback(state->reqs[i],
7108 torture_createdels_done, req);
7109 state->sent += 1;
7111 return req;
7114 static void torture_createdels_done(struct tevent_req *subreq)
7116 struct tevent_req *req = tevent_req_callback_data(
7117 subreq, struct tevent_req);
7118 struct torture_createdels_state *state = tevent_req_data(
7119 req, struct torture_createdels_state);
7120 size_t num_parallel = talloc_array_length(state->reqs);
7121 NTSTATUS status;
7122 char *name;
7123 int i;
7125 status = torture_createdel_recv(subreq);
7126 if (!NT_STATUS_IS_OK(status)){
7127 DEBUG(10, ("torture_createdel_recv returned %s\n",
7128 nt_errstr(status)));
7129 TALLOC_FREE(subreq);
7130 tevent_req_nterror(req, status);
7131 return;
7134 for (i=0; i<num_parallel; i++) {
7135 if (subreq == state->reqs[i]) {
7136 break;
7139 if (i == num_parallel) {
7140 DEBUG(10, ("received something we did not send\n"));
7141 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
7142 return;
7144 TALLOC_FREE(state->reqs[i]);
7146 if (state->sent >= state->num_files) {
7147 tevent_req_done(req);
7148 return;
7151 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
7152 state->sent);
7153 if (tevent_req_nomem(name, req)) {
7154 return;
7156 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
7157 state->cli, name);
7158 if (tevent_req_nomem(state->reqs[i], req)) {
7159 return;
7161 name = talloc_move(state->reqs[i], &name);
7162 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
7163 state->sent += 1;
7166 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
7168 return tevent_req_simple_recv_ntstatus(req);
7171 struct swallow_notify_state {
7172 struct tevent_context *ev;
7173 struct cli_state *cli;
7174 uint16_t fnum;
7175 uint32_t completion_filter;
7176 bool recursive;
7177 bool (*fn)(uint32_t action, const char *name, void *priv);
7178 void *priv;
7181 static void swallow_notify_done(struct tevent_req *subreq);
7183 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
7184 struct tevent_context *ev,
7185 struct cli_state *cli,
7186 uint16_t fnum,
7187 uint32_t completion_filter,
7188 bool recursive,
7189 bool (*fn)(uint32_t action,
7190 const char *name,
7191 void *priv),
7192 void *priv)
7194 struct tevent_req *req, *subreq;
7195 struct swallow_notify_state *state;
7197 req = tevent_req_create(mem_ctx, &state,
7198 struct swallow_notify_state);
7199 if (req == NULL) {
7200 return NULL;
7202 state->ev = ev;
7203 state->cli = cli;
7204 state->fnum = fnum;
7205 state->completion_filter = completion_filter;
7206 state->recursive = recursive;
7207 state->fn = fn;
7208 state->priv = priv;
7210 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
7211 0xffff, state->completion_filter,
7212 state->recursive);
7213 if (tevent_req_nomem(subreq, req)) {
7214 return tevent_req_post(req, ev);
7216 tevent_req_set_callback(subreq, swallow_notify_done, req);
7217 return req;
7220 static void swallow_notify_done(struct tevent_req *subreq)
7222 struct tevent_req *req = tevent_req_callback_data(
7223 subreq, struct tevent_req);
7224 struct swallow_notify_state *state = tevent_req_data(
7225 req, struct swallow_notify_state);
7226 NTSTATUS status;
7227 uint32_t i, num_changes;
7228 struct notify_change *changes;
7230 status = cli_notify_recv(subreq, state, &num_changes, &changes);
7231 TALLOC_FREE(subreq);
7232 if (!NT_STATUS_IS_OK(status)) {
7233 DEBUG(10, ("cli_notify_recv returned %s\n",
7234 nt_errstr(status)));
7235 tevent_req_nterror(req, status);
7236 return;
7239 for (i=0; i<num_changes; i++) {
7240 state->fn(changes[i].action, changes[i].name, state->priv);
7242 TALLOC_FREE(changes);
7244 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
7245 0xffff, state->completion_filter,
7246 state->recursive);
7247 if (tevent_req_nomem(subreq, req)) {
7248 return;
7250 tevent_req_set_callback(subreq, swallow_notify_done, req);
7253 static bool print_notifies(uint32_t action, const char *name, void *priv)
7255 if (DEBUGLEVEL > 5) {
7256 d_printf("%d %s\n", (int)action, name);
7258 return true;
7261 static void notify_bench_done(struct tevent_req *req)
7263 int *num_finished = (int *)tevent_req_callback_data_void(req);
7264 *num_finished += 1;
7267 static bool run_notify_bench(int dummy)
7269 const char *dname = "\\notify-bench";
7270 struct tevent_context *ev;
7271 NTSTATUS status;
7272 uint16_t dnum;
7273 struct tevent_req *req1;
7274 struct tevent_req *req2 = NULL;
7275 int i, num_unc_names;
7276 int num_finished = 0;
7278 printf("starting notify-bench test\n");
7280 if (use_multishare_conn) {
7281 char **unc_list;
7282 unc_list = file_lines_load(multishare_conn_fname,
7283 &num_unc_names, 0, NULL);
7284 if (!unc_list || num_unc_names <= 0) {
7285 d_printf("Failed to load unc names list from '%s'\n",
7286 multishare_conn_fname);
7287 return false;
7289 TALLOC_FREE(unc_list);
7290 } else {
7291 num_unc_names = 1;
7294 ev = samba_tevent_context_init(talloc_tos());
7295 if (ev == NULL) {
7296 d_printf("tevent_context_init failed\n");
7297 return false;
7300 for (i=0; i<num_unc_names; i++) {
7301 struct cli_state *cli;
7302 char *base_fname;
7304 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
7305 dname, i);
7306 if (base_fname == NULL) {
7307 return false;
7310 if (!torture_open_connection(&cli, i)) {
7311 return false;
7314 status = cli_ntcreate(cli, dname, 0,
7315 MAXIMUM_ALLOWED_ACCESS,
7316 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
7317 FILE_SHARE_DELETE,
7318 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
7319 &dnum, NULL);
7321 if (!NT_STATUS_IS_OK(status)) {
7322 d_printf("Could not create %s: %s\n", dname,
7323 nt_errstr(status));
7324 return false;
7327 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
7328 FILE_NOTIFY_CHANGE_FILE_NAME |
7329 FILE_NOTIFY_CHANGE_DIR_NAME |
7330 FILE_NOTIFY_CHANGE_ATTRIBUTES |
7331 FILE_NOTIFY_CHANGE_LAST_WRITE,
7332 false, print_notifies, NULL);
7333 if (req1 == NULL) {
7334 d_printf("Could not create notify request\n");
7335 return false;
7338 req2 = torture_createdels_send(talloc_tos(), ev, cli,
7339 base_fname, 10, torture_numops);
7340 if (req2 == NULL) {
7341 d_printf("Could not create createdels request\n");
7342 return false;
7344 TALLOC_FREE(base_fname);
7346 tevent_req_set_callback(req2, notify_bench_done,
7347 &num_finished);
7350 while (num_finished < num_unc_names) {
7351 int ret;
7352 ret = tevent_loop_once(ev);
7353 if (ret != 0) {
7354 d_printf("tevent_loop_once failed\n");
7355 return false;
7359 if (!tevent_req_poll(req2, ev)) {
7360 d_printf("tevent_req_poll failed\n");
7363 status = torture_createdels_recv(req2);
7364 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
7366 return true;
7369 static bool run_mangle1(int dummy)
7371 struct cli_state *cli;
7372 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
7373 uint16_t fnum;
7374 fstring alt_name;
7375 NTSTATUS status;
7376 time_t change_time, access_time, write_time;
7377 off_t size;
7378 uint16_t mode;
7380 printf("starting mangle1 test\n");
7381 if (!torture_open_connection(&cli, 0)) {
7382 return False;
7385 smbXcli_conn_set_sockopt(cli->conn, sockops);
7387 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7388 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7389 0, 0, &fnum, NULL);
7390 if (!NT_STATUS_IS_OK(status)) {
7391 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7392 return false;
7394 cli_close(cli, fnum);
7396 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
7397 if (!NT_STATUS_IS_OK(status)) {
7398 d_printf("cli_qpathinfo_alt_name failed: %s\n",
7399 nt_errstr(status));
7400 return false;
7402 d_printf("alt_name: %s\n", alt_name);
7404 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
7405 if (!NT_STATUS_IS_OK(status)) {
7406 d_printf("cli_openx(%s) failed: %s\n", alt_name,
7407 nt_errstr(status));
7408 return false;
7410 cli_close(cli, fnum);
7412 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
7413 &write_time, &size, &mode);
7414 if (!NT_STATUS_IS_OK(status)) {
7415 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
7416 nt_errstr(status));
7417 return false;
7420 return true;
7423 static size_t null_source(uint8_t *buf, size_t n, void *priv)
7425 size_t *to_pull = (size_t *)priv;
7426 size_t thistime = *to_pull;
7428 thistime = MIN(thistime, n);
7429 if (thistime == 0) {
7430 return 0;
7433 memset(buf, 0, thistime);
7434 *to_pull -= thistime;
7435 return thistime;
7438 static bool run_windows_write(int dummy)
7440 struct cli_state *cli1;
7441 uint16_t fnum;
7442 int i;
7443 bool ret = false;
7444 const char *fname = "\\writetest.txt";
7445 struct timeval start_time;
7446 double seconds;
7447 double kbytes;
7448 NTSTATUS status;
7450 printf("starting windows_write test\n");
7451 if (!torture_open_connection(&cli1, 0)) {
7452 return False;
7455 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7456 if (!NT_STATUS_IS_OK(status)) {
7457 printf("open failed (%s)\n", nt_errstr(status));
7458 return False;
7461 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7463 start_time = timeval_current();
7465 for (i=0; i<torture_numops; i++) {
7466 uint8_t c = 0;
7467 off_t start = i * torture_blocksize;
7468 size_t to_pull = torture_blocksize - 1;
7470 status = cli_writeall(cli1, fnum, 0, &c,
7471 start + torture_blocksize - 1, 1, NULL);
7472 if (!NT_STATUS_IS_OK(status)) {
7473 printf("cli_write failed: %s\n", nt_errstr(status));
7474 goto fail;
7477 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
7478 null_source, &to_pull);
7479 if (!NT_STATUS_IS_OK(status)) {
7480 printf("cli_push returned: %s\n", nt_errstr(status));
7481 goto fail;
7485 seconds = timeval_elapsed(&start_time);
7486 kbytes = (double)torture_blocksize * torture_numops;
7487 kbytes /= 1024;
7489 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
7490 (double)seconds, (int)(kbytes/seconds));
7492 ret = true;
7493 fail:
7494 cli_close(cli1, fnum);
7495 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7496 torture_close_connection(cli1);
7497 return ret;
7500 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
7502 size_t max_pdu = 0x1FFFF;
7504 if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
7505 max_pdu = 0xFFFFFF;
7508 if (smb1cli_conn_signing_is_active(cli->conn)) {
7509 max_pdu = 0x1FFFF;
7512 if (smb1cli_conn_encryption_on(cli->conn)) {
7513 max_pdu = CLI_BUFFER_SIZE;
7516 if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
7517 len_requested &= 0xFFFF;
7520 return MIN(len_requested,
7521 max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
7524 static bool check_read_call(struct cli_state *cli,
7525 uint16_t fnum,
7526 uint8_t *buf,
7527 size_t len_requested)
7529 NTSTATUS status;
7530 struct tevent_req *subreq = NULL;
7531 ssize_t len_read = 0;
7532 size_t len_expected = 0;
7533 struct tevent_context *ev = NULL;
7535 ev = samba_tevent_context_init(talloc_tos());
7536 if (ev == NULL) {
7537 return false;
7540 subreq = cli_read_andx_send(talloc_tos(),
7542 cli,
7543 fnum,
7545 len_requested);
7547 if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
7548 return false;
7551 status = cli_read_andx_recv(subreq, &len_read, &buf);
7552 if (!NT_STATUS_IS_OK(status)) {
7553 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
7554 return false;
7557 TALLOC_FREE(subreq);
7558 TALLOC_FREE(ev);
7560 len_expected = calc_expected_return(cli, len_requested);
7562 if (len_expected > 0x10000 && len_read == 0x10000) {
7563 /* Windows servers only return a max of 0x10000,
7564 doesn't matter if you set CAP_LARGE_READX in
7565 the client sessionsetupX call or not. */
7566 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
7567 (unsigned int)len_requested);
7568 } else if (len_read != len_expected) {
7569 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
7570 (unsigned int)len_requested,
7571 (unsigned int)len_read,
7572 (unsigned int)len_expected);
7573 return false;
7574 } else {
7575 d_printf("Correct read reply.\n");
7578 return true;
7581 /* Test large readX variants. */
7582 static bool large_readx_tests(struct cli_state *cli,
7583 uint16_t fnum,
7584 uint8_t *buf)
7586 /* A read of 0xFFFF0001 should *always* return 1 byte. */
7587 if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
7588 return false;
7590 /* A read of 0x10000 should return 0x10000 bytes. */
7591 if (check_read_call(cli, fnum, buf, 0x10000) == false) {
7592 return false;
7594 /* A read of 0x10000 should return 0x10001 bytes. */
7595 if (check_read_call(cli, fnum, buf, 0x10001) == false) {
7596 return false;
7598 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
7599 the requested number of bytes. */
7600 if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
7601 return false;
7603 /* A read of 1MB should return 1MB bytes (on Samba). */
7604 if (check_read_call(cli, fnum, buf, 0x100000) == false) {
7605 return false;
7608 if (check_read_call(cli, fnum, buf, 0x20001) == false) {
7609 return false;
7611 if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
7612 return false;
7614 if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
7615 return false;
7617 return true;
7620 static bool run_large_readx(int dummy)
7622 uint8_t *buf = NULL;
7623 struct cli_state *cli1 = NULL;
7624 struct cli_state *cli2 = NULL;
7625 bool correct = false;
7626 const char *fname = "\\large_readx.dat";
7627 NTSTATUS status;
7628 uint16_t fnum1 = UINT16_MAX;
7629 uint32_t normal_caps = 0;
7630 size_t file_size = 20*1024*1024;
7631 TALLOC_CTX *frame = talloc_stackframe();
7632 size_t i;
7633 struct {
7634 const char *name;
7635 enum smb_signing_setting signing_setting;
7636 enum protocol_types protocol;
7637 } runs[] = {
7639 .name = "NT1",
7640 .signing_setting = SMB_SIGNING_IF_REQUIRED,
7641 .protocol = PROTOCOL_NT1,
7643 .name = "NT1 - SIGNING_REQUIRED",
7644 .signing_setting = SMB_SIGNING_REQUIRED,
7645 .protocol = PROTOCOL_NT1,
7649 printf("starting large_readx test\n");
7651 if (!torture_open_connection(&cli1, 0)) {
7652 goto out;
7655 normal_caps = smb1cli_conn_capabilities(cli1->conn);
7657 if (!(normal_caps & CAP_LARGE_READX)) {
7658 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
7659 (unsigned int)normal_caps);
7660 goto out;
7663 /* Create a file of size 4MB. */
7664 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
7665 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7666 0, 0, &fnum1, NULL);
7668 if (!NT_STATUS_IS_OK(status)) {
7669 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7670 goto out;
7673 /* Write file_size bytes. */
7674 buf = talloc_zero_array(frame, uint8_t, file_size);
7675 if (buf == NULL) {
7676 goto out;
7679 status = cli_writeall(cli1,
7680 fnum1,
7682 buf,
7684 file_size,
7685 NULL);
7686 if (!NT_STATUS_IS_OK(status)) {
7687 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
7688 goto out;
7691 status = cli_close(cli1, fnum1);
7692 if (!NT_STATUS_IS_OK(status)) {
7693 d_printf("cli_close failed: %s\n", nt_errstr(status));
7694 goto out;
7697 fnum1 = UINT16_MAX;
7699 for (i=0; i < ARRAY_SIZE(runs); i++) {
7700 enum smb_signing_setting saved_signing_setting = signing_state;
7701 uint16_t fnum2 = -1;
7703 if (do_encrypt &&
7704 (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
7706 d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
7707 continue;
7710 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
7712 signing_state = runs[i].signing_setting;
7713 cli2 = open_nbt_connection();
7714 signing_state = saved_signing_setting;
7715 if (cli2 == NULL) {
7716 goto out;
7719 status = smbXcli_negprot(cli2->conn,
7720 cli2->timeout,
7721 runs[i].protocol,
7722 runs[i].protocol);
7723 if (!NT_STATUS_IS_OK(status)) {
7724 goto out;
7727 status = cli_session_setup(cli2,
7728 username,
7729 password,
7730 strlen(password)+1,
7731 password,
7732 strlen(password)+1,
7733 workgroup);
7734 if (!NT_STATUS_IS_OK(status)) {
7735 goto out;
7738 status = cli_tree_connect(cli2,
7739 share,
7740 "?????",
7741 password,
7742 strlen(password)+1);
7743 if (!NT_STATUS_IS_OK(status)) {
7744 goto out;
7747 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
7749 normal_caps = smb1cli_conn_capabilities(cli2->conn);
7751 if (!(normal_caps & CAP_LARGE_READX)) {
7752 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
7753 (unsigned int)normal_caps);
7754 goto out;
7757 if (do_encrypt) {
7758 if (force_cli_encryption(cli2, share) == false) {
7759 goto out;
7761 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
7762 uint16_t major, minor;
7763 uint32_t caplow, caphigh;
7765 status = cli_unix_extensions_version(cli2,
7766 &major, &minor,
7767 &caplow, &caphigh);
7768 if (!NT_STATUS_IS_OK(status)) {
7769 goto out;
7773 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
7774 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
7775 0, 0, &fnum2, NULL);
7776 if (!NT_STATUS_IS_OK(status)) {
7777 d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
7778 goto out;
7781 /* All reads must return less than file_size bytes. */
7782 if (!large_readx_tests(cli2, fnum2, buf)) {
7783 goto out;
7786 status = cli_close(cli2, fnum2);
7787 if (!NT_STATUS_IS_OK(status)) {
7788 d_printf("cli_close failed: %s\n", nt_errstr(status));
7789 goto out;
7791 fnum2 = -1;
7793 if (!torture_close_connection(cli2)) {
7794 goto out;
7796 cli2 = NULL;
7799 correct = true;
7800 printf("Success on large_readx test\n");
7802 out:
7804 if (cli2) {
7805 if (!torture_close_connection(cli2)) {
7806 correct = false;
7810 if (cli1) {
7811 if (fnum1 != UINT16_MAX) {
7812 status = cli_close(cli1, fnum1);
7813 if (!NT_STATUS_IS_OK(status)) {
7814 d_printf("cli_close failed: %s\n", nt_errstr(status));
7816 fnum1 = UINT16_MAX;
7819 status = cli_unlink(cli1, fname,
7820 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7821 if (!NT_STATUS_IS_OK(status)) {
7822 printf("unlink failed (%s)\n", nt_errstr(status));
7825 if (!torture_close_connection(cli1)) {
7826 correct = false;
7830 TALLOC_FREE(frame);
7832 printf("finished large_readx test\n");
7833 return correct;
7836 static bool run_cli_echo(int dummy)
7838 struct cli_state *cli;
7839 NTSTATUS status;
7841 printf("starting cli_echo test\n");
7842 if (!torture_open_connection(&cli, 0)) {
7843 return false;
7845 smbXcli_conn_set_sockopt(cli->conn, sockops);
7847 status = cli_echo(cli, 5, data_blob_const("hello", 5));
7849 d_printf("cli_echo returned %s\n", nt_errstr(status));
7851 torture_close_connection(cli);
7852 return NT_STATUS_IS_OK(status);
7855 static bool run_uid_regression_test(int dummy)
7857 static struct cli_state *cli;
7858 int16_t old_vuid;
7859 int16_t old_cnum;
7860 bool correct = True;
7861 NTSTATUS status;
7863 printf("starting uid regression test\n");
7865 if (!torture_open_connection(&cli, 0)) {
7866 return False;
7869 smbXcli_conn_set_sockopt(cli->conn, sockops);
7871 /* Ok - now save then logoff our current user. */
7872 old_vuid = cli_state_get_uid(cli);
7874 status = cli_ulogoff(cli);
7875 if (!NT_STATUS_IS_OK(status)) {
7876 d_printf("(%s) cli_ulogoff failed: %s\n",
7877 __location__, nt_errstr(status));
7878 correct = false;
7879 goto out;
7882 cli_state_set_uid(cli, old_vuid);
7884 /* Try an operation. */
7885 status = cli_mkdir(cli, "\\uid_reg_test");
7886 if (NT_STATUS_IS_OK(status)) {
7887 d_printf("(%s) cli_mkdir succeeded\n",
7888 __location__);
7889 correct = false;
7890 goto out;
7891 } else {
7892 /* Should be bad uid. */
7893 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
7894 NT_STATUS_USER_SESSION_DELETED)) {
7895 correct = false;
7896 goto out;
7900 old_cnum = cli_state_get_tid(cli);
7902 /* Now try a SMBtdis with the invald vuid set to zero. */
7903 cli_state_set_uid(cli, 0);
7905 /* This should succeed. */
7906 status = cli_tdis(cli);
7908 if (NT_STATUS_IS_OK(status)) {
7909 d_printf("First tdis with invalid vuid should succeed.\n");
7910 } else {
7911 d_printf("First tdis failed (%s)\n", nt_errstr(status));
7912 correct = false;
7913 goto out;
7916 cli_state_set_uid(cli, old_vuid);
7917 cli_state_set_tid(cli, old_cnum);
7919 /* This should fail. */
7920 status = cli_tdis(cli);
7921 if (NT_STATUS_IS_OK(status)) {
7922 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
7923 correct = false;
7924 goto out;
7925 } else {
7926 /* Should be bad tid. */
7927 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
7928 NT_STATUS_NETWORK_NAME_DELETED)) {
7929 correct = false;
7930 goto out;
7934 cli_rmdir(cli, "\\uid_reg_test");
7936 out:
7938 cli_shutdown(cli);
7939 return correct;
7943 static const char *illegal_chars = "*\\/?<>|\":";
7944 static char force_shortname_chars[] = " +,.[];=\177";
7946 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
7947 const char *mask, void *state)
7949 struct cli_state *pcli = (struct cli_state *)state;
7950 fstring fname;
7951 NTSTATUS status = NT_STATUS_OK;
7953 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
7955 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7956 return NT_STATUS_OK;
7958 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7959 status = cli_rmdir(pcli, fname);
7960 if (!NT_STATUS_IS_OK(status)) {
7961 printf("del_fn: failed to rmdir %s\n,", fname );
7963 } else {
7964 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7965 if (!NT_STATUS_IS_OK(status)) {
7966 printf("del_fn: failed to unlink %s\n,", fname );
7969 return status;
7972 struct sn_state {
7973 int matched;
7974 int i;
7975 bool val;
7978 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
7979 const char *name, void *state)
7981 struct sn_state *s = (struct sn_state *)state;
7982 int i = s->i;
7984 #if 0
7985 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
7986 i, finfo->name, finfo->short_name);
7987 #endif
7989 if (strchr(force_shortname_chars, i)) {
7990 if (!finfo->short_name) {
7991 /* Shortname not created when it should be. */
7992 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
7993 __location__, finfo->name, i);
7994 s->val = true;
7996 } else if (finfo->short_name){
7997 /* Shortname created when it should not be. */
7998 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
7999 __location__, finfo->short_name, finfo->name);
8000 s->val = true;
8002 s->matched += 1;
8003 return NT_STATUS_OK;
8006 static bool run_shortname_test(int dummy)
8008 static struct cli_state *cli;
8009 bool correct = True;
8010 int i;
8011 struct sn_state s;
8012 char fname[40];
8013 NTSTATUS status;
8015 printf("starting shortname test\n");
8017 if (!torture_open_connection(&cli, 0)) {
8018 return False;
8021 smbXcli_conn_set_sockopt(cli->conn, sockops);
8023 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
8024 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
8025 cli_rmdir(cli, "\\shortname");
8027 status = cli_mkdir(cli, "\\shortname");
8028 if (!NT_STATUS_IS_OK(status)) {
8029 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
8030 __location__, nt_errstr(status));
8031 correct = false;
8032 goto out;
8035 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
8036 correct = false;
8037 goto out;
8039 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
8040 correct = false;
8041 goto out;
8044 s.val = false;
8046 for (i = 32; i < 128; i++) {
8047 uint16_t fnum = (uint16_t)-1;
8049 s.i = i;
8051 if (strchr(illegal_chars, i)) {
8052 continue;
8054 fname[15] = i;
8056 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
8057 FILE_SHARE_READ|FILE_SHARE_WRITE,
8058 FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
8059 if (!NT_STATUS_IS_OK(status)) {
8060 d_printf("(%s) cli_nt_create of %s failed: %s\n",
8061 __location__, fname, nt_errstr(status));
8062 correct = false;
8063 goto out;
8065 cli_close(cli, fnum);
8067 s.matched = 0;
8068 status = cli_list(cli, "\\shortname\\test*.*", 0,
8069 shortname_list_fn, &s);
8070 if (s.matched != 1) {
8071 d_printf("(%s) failed to list %s: %s\n",
8072 __location__, fname, nt_errstr(status));
8073 correct = false;
8074 goto out;
8077 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8078 if (!NT_STATUS_IS_OK(status)) {
8079 d_printf("(%s) failed to delete %s: %s\n",
8080 __location__, fname, nt_errstr(status));
8081 correct = false;
8082 goto out;
8085 if (s.val) {
8086 correct = false;
8087 goto out;
8091 out:
8093 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
8094 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
8095 cli_rmdir(cli, "\\shortname");
8096 torture_close_connection(cli);
8097 return correct;
8100 static void pagedsearch_cb(struct tevent_req *req)
8102 int rc;
8103 struct tldap_message *msg;
8104 char *dn;
8106 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
8107 if (rc != TLDAP_SUCCESS) {
8108 d_printf("tldap_search_paged_recv failed: %s\n",
8109 tldap_err2string(rc));
8110 return;
8112 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
8113 TALLOC_FREE(msg);
8114 return;
8116 if (!tldap_entry_dn(msg, &dn)) {
8117 d_printf("tldap_entry_dn failed\n");
8118 return;
8120 d_printf("%s\n", dn);
8121 TALLOC_FREE(msg);
8124 static bool run_tldap(int dummy)
8126 struct tldap_context *ld;
8127 int fd, rc;
8128 NTSTATUS status;
8129 struct sockaddr_storage addr;
8130 struct tevent_context *ev;
8131 struct tevent_req *req;
8132 char *basedn;
8133 const char *filter;
8135 if (!resolve_name(host, &addr, 0, false)) {
8136 d_printf("could not find host %s\n", host);
8137 return false;
8139 status = open_socket_out(&addr, 389, 9999, &fd);
8140 if (!NT_STATUS_IS_OK(status)) {
8141 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
8142 return false;
8145 ld = tldap_context_create(talloc_tos(), fd);
8146 if (ld == NULL) {
8147 close(fd);
8148 d_printf("tldap_context_create failed\n");
8149 return false;
8152 rc = tldap_fetch_rootdse(ld);
8153 if (rc != TLDAP_SUCCESS) {
8154 d_printf("tldap_fetch_rootdse failed: %s\n",
8155 tldap_errstr(talloc_tos(), ld, rc));
8156 return false;
8159 basedn = tldap_talloc_single_attribute(
8160 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
8161 if (basedn == NULL) {
8162 d_printf("no defaultNamingContext\n");
8163 return false;
8165 d_printf("defaultNamingContext: %s\n", basedn);
8167 ev = samba_tevent_context_init(talloc_tos());
8168 if (ev == NULL) {
8169 d_printf("tevent_context_init failed\n");
8170 return false;
8173 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
8174 TLDAP_SCOPE_SUB, "(objectclass=*)",
8175 NULL, 0, 0,
8176 NULL, 0, NULL, 0, 0, 0, 0, 5);
8177 if (req == NULL) {
8178 d_printf("tldap_search_paged_send failed\n");
8179 return false;
8181 tevent_req_set_callback(req, pagedsearch_cb, NULL);
8183 tevent_req_poll(req, ev);
8185 TALLOC_FREE(req);
8187 /* test search filters against rootDSE */
8188 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
8189 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
8191 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
8192 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
8193 talloc_tos(), NULL, NULL);
8194 if (rc != TLDAP_SUCCESS) {
8195 d_printf("tldap_search with complex filter failed: %s\n",
8196 tldap_errstr(talloc_tos(), ld, rc));
8197 return false;
8200 TALLOC_FREE(ld);
8201 return true;
8204 /* Torture test to ensure no regression of :
8205 https://bugzilla.samba.org/show_bug.cgi?id=7084
8208 static bool run_dir_createtime(int dummy)
8210 struct cli_state *cli;
8211 const char *dname = "\\testdir";
8212 const char *fname = "\\testdir\\testfile";
8213 NTSTATUS status;
8214 struct timespec create_time;
8215 struct timespec create_time1;
8216 uint16_t fnum;
8217 bool ret = false;
8219 if (!torture_open_connection(&cli, 0)) {
8220 return false;
8223 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8224 cli_rmdir(cli, dname);
8226 status = cli_mkdir(cli, dname);
8227 if (!NT_STATUS_IS_OK(status)) {
8228 printf("mkdir failed: %s\n", nt_errstr(status));
8229 goto out;
8232 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
8233 NULL, NULL, NULL);
8234 if (!NT_STATUS_IS_OK(status)) {
8235 printf("cli_qpathinfo2 returned %s\n",
8236 nt_errstr(status));
8237 goto out;
8240 /* Sleep 3 seconds, then create a file. */
8241 sleep(3);
8243 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
8244 DENY_NONE, &fnum);
8245 if (!NT_STATUS_IS_OK(status)) {
8246 printf("cli_openx failed: %s\n", nt_errstr(status));
8247 goto out;
8250 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
8251 NULL, NULL, NULL);
8252 if (!NT_STATUS_IS_OK(status)) {
8253 printf("cli_qpathinfo2 (2) returned %s\n",
8254 nt_errstr(status));
8255 goto out;
8258 if (timespec_compare(&create_time1, &create_time)) {
8259 printf("run_dir_createtime: create time was updated (error)\n");
8260 } else {
8261 printf("run_dir_createtime: create time was not updated (correct)\n");
8262 ret = true;
8265 out:
8267 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8268 cli_rmdir(cli, dname);
8269 if (!torture_close_connection(cli)) {
8270 ret = false;
8272 return ret;
8276 static bool run_streamerror(int dummy)
8278 struct cli_state *cli;
8279 const char *dname = "\\testdir";
8280 const char *streamname =
8281 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
8282 NTSTATUS status;
8283 time_t change_time, access_time, write_time;
8284 off_t size;
8285 uint16_t mode, fnum;
8286 bool ret = true;
8288 if (!torture_open_connection(&cli, 0)) {
8289 return false;
8292 cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8293 cli_rmdir(cli, dname);
8295 status = cli_mkdir(cli, dname);
8296 if (!NT_STATUS_IS_OK(status)) {
8297 printf("mkdir failed: %s\n", nt_errstr(status));
8298 return false;
8301 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
8302 &write_time, &size, &mode);
8303 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
8304 printf("pathinfo returned %s, expected "
8305 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
8306 nt_errstr(status));
8307 ret = false;
8310 status = cli_ntcreate(cli, streamname, 0x16,
8311 FILE_READ_DATA|FILE_READ_EA|
8312 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
8313 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
8314 FILE_OPEN, 0, 0, &fnum, NULL);
8316 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
8317 printf("ntcreate returned %s, expected "
8318 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
8319 nt_errstr(status));
8320 ret = false;
8324 cli_rmdir(cli, dname);
8325 return ret;
8328 static bool run_local_substitute(int dummy)
8330 bool ok = true;
8332 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
8333 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
8334 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
8335 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
8336 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
8337 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
8338 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
8339 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
8341 /* Different captialization rules in sub_basic... */
8343 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
8344 "blaDOM") == 0);
8346 return ok;
8349 static bool run_local_base64(int dummy)
8351 int i;
8352 bool ret = true;
8354 for (i=1; i<2000; i++) {
8355 DATA_BLOB blob1, blob2;
8356 char *b64;
8358 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
8359 blob1.length = i;
8360 generate_random_buffer(blob1.data, blob1.length);
8362 b64 = base64_encode_data_blob(talloc_tos(), blob1);
8363 if (b64 == NULL) {
8364 d_fprintf(stderr, "base64_encode_data_blob failed "
8365 "for %d bytes\n", i);
8366 ret = false;
8368 blob2 = base64_decode_data_blob(b64);
8369 TALLOC_FREE(b64);
8371 if (data_blob_cmp(&blob1, &blob2)) {
8372 d_fprintf(stderr, "data_blob_cmp failed for %d "
8373 "bytes\n", i);
8374 ret = false;
8376 TALLOC_FREE(blob1.data);
8377 data_blob_free(&blob2);
8379 return ret;
8382 static void parse_fn(time_t timeout, DATA_BLOB blob, void *private_data)
8384 return;
8387 static bool run_local_gencache(int dummy)
8389 char *val;
8390 time_t tm;
8391 DATA_BLOB blob;
8392 char v;
8393 struct memcache *mem;
8394 int i;
8396 mem = memcache_init(NULL, 0);
8397 if (mem == NULL) {
8398 d_printf("%s: memcache_init failed\n", __location__);
8399 return false;
8401 memcache_set_global(mem);
8403 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
8404 d_printf("%s: gencache_set() failed\n", __location__);
8405 return False;
8408 if (!gencache_get("foo", NULL, NULL, NULL)) {
8409 d_printf("%s: gencache_get() failed\n", __location__);
8410 return False;
8413 for (i=0; i<1000000; i++) {
8414 gencache_parse("foo", parse_fn, NULL);
8417 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
8418 d_printf("%s: gencache_get() failed\n", __location__);
8419 return False;
8421 TALLOC_FREE(val);
8423 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
8424 d_printf("%s: gencache_get() failed\n", __location__);
8425 return False;
8428 if (strcmp(val, "bar") != 0) {
8429 d_printf("%s: gencache_get() returned %s, expected %s\n",
8430 __location__, val, "bar");
8431 TALLOC_FREE(val);
8432 return False;
8435 TALLOC_FREE(val);
8437 if (!gencache_del("foo")) {
8438 d_printf("%s: gencache_del() failed\n", __location__);
8439 return False;
8441 if (gencache_del("foo")) {
8442 d_printf("%s: second gencache_del() succeeded\n",
8443 __location__);
8444 return False;
8447 if (gencache_get("foo", talloc_tos(), &val, &tm)) {
8448 d_printf("%s: gencache_get() on deleted entry "
8449 "succeeded\n", __location__);
8450 return False;
8453 blob = data_blob_string_const_null("bar");
8454 tm = time(NULL) + 60;
8456 if (!gencache_set_data_blob("foo", &blob, tm)) {
8457 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
8458 return False;
8461 if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
8462 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
8463 return False;
8466 if (strcmp((const char *)blob.data, "bar") != 0) {
8467 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
8468 __location__, (const char *)blob.data, "bar");
8469 data_blob_free(&blob);
8470 return False;
8473 data_blob_free(&blob);
8475 if (!gencache_del("foo")) {
8476 d_printf("%s: gencache_del() failed\n", __location__);
8477 return False;
8479 if (gencache_del("foo")) {
8480 d_printf("%s: second gencache_del() succeeded\n",
8481 __location__);
8482 return False;
8485 if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
8486 d_printf("%s: gencache_get_data_blob() on deleted entry "
8487 "succeeded\n", __location__);
8488 return False;
8491 v = 1;
8492 blob.data = (uint8_t *)&v;
8493 blob.length = sizeof(v);
8495 if (!gencache_set_data_blob("blob", &blob, tm)) {
8496 d_printf("%s: gencache_set_data_blob() failed\n",
8497 __location__);
8498 return false;
8500 if (gencache_get("blob", talloc_tos(), &val, &tm)) {
8501 d_printf("%s: gencache_get succeeded\n", __location__);
8502 return false;
8505 return True;
8508 static bool rbt_testval(struct db_context *db, const char *key,
8509 const char *value)
8511 struct db_record *rec;
8512 TDB_DATA data = string_tdb_data(value);
8513 bool ret = false;
8514 NTSTATUS status;
8515 TDB_DATA dbvalue;
8517 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
8518 if (rec == NULL) {
8519 d_fprintf(stderr, "fetch_locked failed\n");
8520 goto done;
8522 status = dbwrap_record_store(rec, data, 0);
8523 if (!NT_STATUS_IS_OK(status)) {
8524 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
8525 goto done;
8527 TALLOC_FREE(rec);
8529 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
8530 if (rec == NULL) {
8531 d_fprintf(stderr, "second fetch_locked failed\n");
8532 goto done;
8535 dbvalue = dbwrap_record_get_value(rec);
8536 if ((dbvalue.dsize != data.dsize)
8537 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
8538 d_fprintf(stderr, "Got wrong data back\n");
8539 goto done;
8542 ret = true;
8543 done:
8544 TALLOC_FREE(rec);
8545 return ret;
8548 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
8550 int *count2 = (int *)private_data;
8551 (*count2)++;
8552 return 0;
8555 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
8557 int *count2 = (int *)private_data;
8558 (*count2)++;
8559 dbwrap_record_delete(rec);
8560 return 0;
8563 static bool run_local_rbtree(int dummy)
8565 struct db_context *db;
8566 bool ret = false;
8567 int i;
8568 NTSTATUS status;
8569 int count = 0;
8570 int count2 = 0;
8572 db = db_open_rbt(NULL);
8574 if (db == NULL) {
8575 d_fprintf(stderr, "db_open_rbt failed\n");
8576 return false;
8579 for (i=0; i<1000; i++) {
8580 char *key, *value;
8582 if (asprintf(&key, "key%ld", random()) == -1) {
8583 goto done;
8585 if (asprintf(&value, "value%ld", random()) == -1) {
8586 SAFE_FREE(key);
8587 goto done;
8590 if (!rbt_testval(db, key, value)) {
8591 SAFE_FREE(key);
8592 SAFE_FREE(value);
8593 goto done;
8596 SAFE_FREE(value);
8597 if (asprintf(&value, "value%ld", random()) == -1) {
8598 SAFE_FREE(key);
8599 goto done;
8602 if (!rbt_testval(db, key, value)) {
8603 SAFE_FREE(key);
8604 SAFE_FREE(value);
8605 goto done;
8608 SAFE_FREE(key);
8609 SAFE_FREE(value);
8612 ret = true;
8613 count = 0; count2 = 0;
8614 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
8615 &count2, &count);
8616 printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
8617 if ((count != count2) || (count != 1000)) {
8618 ret = false;
8620 count = 0; count2 = 0;
8621 status = dbwrap_traverse(db, local_rbtree_traverse_delete,
8622 &count2, &count);
8623 printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
8624 if ((count != count2) || (count != 1000)) {
8625 ret = false;
8627 count = 0; count2 = 0;
8628 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
8629 &count2, &count);
8630 printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
8631 if ((count != count2) || (count != 0)) {
8632 ret = false;
8635 done:
8636 TALLOC_FREE(db);
8637 return ret;
8642 local test for character set functions
8644 This is a very simple test for the functionality in convert_string_error()
8646 static bool run_local_convert_string(int dummy)
8648 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
8649 const char *test_strings[2] = { "March", "M\303\244rz" };
8650 char dst[7];
8651 int i;
8653 for (i=0; i<2; i++) {
8654 const char *str = test_strings[i];
8655 int len = strlen(str);
8656 size_t converted_size;
8657 bool ret;
8659 memset(dst, 'X', sizeof(dst));
8661 /* first try with real source length */
8662 ret = convert_string_error(CH_UNIX, CH_UTF8,
8663 str, len,
8664 dst, sizeof(dst),
8665 &converted_size);
8666 if (ret != true) {
8667 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
8668 goto failed;
8671 if (converted_size != len) {
8672 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
8673 str, len, (int)converted_size);
8674 goto failed;
8677 if (strncmp(str, dst, converted_size) != 0) {
8678 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
8679 goto failed;
8682 if (strlen(str) != converted_size) {
8683 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
8684 (int)strlen(str), (int)converted_size);
8685 goto failed;
8688 if (dst[converted_size] != 'X') {
8689 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
8690 goto failed;
8693 /* now with srclen==-1, this causes the nul to be
8694 * converted too */
8695 ret = convert_string_error(CH_UNIX, CH_UTF8,
8696 str, -1,
8697 dst, sizeof(dst),
8698 &converted_size);
8699 if (ret != true) {
8700 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
8701 goto failed;
8704 if (converted_size != len+1) {
8705 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
8706 str, len, (int)converted_size);
8707 goto failed;
8710 if (strncmp(str, dst, converted_size) != 0) {
8711 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
8712 goto failed;
8715 if (len+1 != converted_size) {
8716 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
8717 len+1, (int)converted_size);
8718 goto failed;
8721 if (dst[converted_size] != 'X') {
8722 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
8723 goto failed;
8729 TALLOC_FREE(tmp_ctx);
8730 return true;
8731 failed:
8732 TALLOC_FREE(tmp_ctx);
8733 return false;
8737 struct talloc_dict_test {
8738 int content;
8741 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
8743 int *count = (int *)priv;
8744 *count += 1;
8745 return 0;
8748 static bool run_local_talloc_dict(int dummy)
8750 struct talloc_dict *dict;
8751 struct talloc_dict_test *t;
8752 int key, count, res;
8753 bool ok;
8755 dict = talloc_dict_init(talloc_tos());
8756 if (dict == NULL) {
8757 return false;
8760 t = talloc(talloc_tos(), struct talloc_dict_test);
8761 if (t == NULL) {
8762 return false;
8765 key = 1;
8766 t->content = 1;
8767 ok = talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), &t);
8768 if (!ok) {
8769 return false;
8772 count = 0;
8773 res = talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count);
8774 if (res == -1) {
8775 return false;
8778 if (count != 1) {
8779 return false;
8782 if (count != res) {
8783 return false;
8786 TALLOC_FREE(dict);
8788 return true;
8791 static bool run_local_string_to_sid(int dummy) {
8792 struct dom_sid sid;
8794 if (string_to_sid(&sid, "S--1-5-32-545")) {
8795 printf("allowing S--1-5-32-545\n");
8796 return false;
8798 if (string_to_sid(&sid, "S-1-5-32-+545")) {
8799 printf("allowing S-1-5-32-+545\n");
8800 return false;
8802 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")) {
8803 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
8804 return false;
8806 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
8807 printf("allowing S-1-5-32-545-abc\n");
8808 return false;
8810 if (string_to_sid(&sid, "S-300-5-32-545")) {
8811 printf("allowing S-300-5-32-545\n");
8812 return false;
8814 if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
8815 printf("allowing S-1-0xfffffffffffffe-32-545\n");
8816 return false;
8818 if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
8819 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
8820 return false;
8822 if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
8823 printf("could not parse S-1-0xfffffffffffe-32-545\n");
8824 return false;
8826 if (!string_to_sid(&sid, "S-1-5-32-545")) {
8827 printf("could not parse S-1-5-32-545\n");
8828 return false;
8830 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
8831 printf("mis-parsed S-1-5-32-545 as %s\n",
8832 sid_string_tos(&sid));
8833 return false;
8835 return true;
8838 static bool sid_to_string_test(const char *expected) {
8839 char *str;
8840 bool res = true;
8841 struct dom_sid sid;
8843 if (!string_to_sid(&sid, expected)) {
8844 printf("could not parse %s\n", expected);
8845 return false;
8848 str = dom_sid_string(NULL, &sid);
8849 if (strcmp(str, expected)) {
8850 printf("Comparison failed (%s != %s)\n", str, expected);
8851 res = false;
8853 TALLOC_FREE(str);
8854 return res;
8857 static bool run_local_sid_to_string(int dummy) {
8858 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
8859 return false;
8860 if (!sid_to_string_test("S-1-545"))
8861 return false;
8862 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
8863 return false;
8864 return true;
8867 static bool run_local_binary_to_sid(int dummy) {
8868 struct dom_sid *sid = talloc(NULL, struct dom_sid);
8869 static const char good_binary_sid[] = {
8870 0x1, /* revision number */
8871 15, /* num auths */
8872 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8873 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8874 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8875 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8876 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8877 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8878 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8879 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8880 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8881 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8882 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8883 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8884 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8885 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8886 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8887 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8890 static const char long_binary_sid[] = {
8891 0x1, /* revision number */
8892 15, /* num auths */
8893 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8894 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8895 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8896 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8897 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8898 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8899 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8900 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8901 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8902 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8903 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8904 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8905 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8906 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8907 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8908 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8909 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8910 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8911 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8914 static const char long_binary_sid2[] = {
8915 0x1, /* revision number */
8916 32, /* num auths */
8917 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8918 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8919 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8920 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8921 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8922 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8923 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8924 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8925 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8926 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8927 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8928 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8929 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8930 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8931 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8932 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8933 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8934 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8935 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8936 0x1, 0x1, 0x1, 0x1, /* auth[18] */
8937 0x1, 0x1, 0x1, 0x1, /* auth[19] */
8938 0x1, 0x1, 0x1, 0x1, /* auth[20] */
8939 0x1, 0x1, 0x1, 0x1, /* auth[21] */
8940 0x1, 0x1, 0x1, 0x1, /* auth[22] */
8941 0x1, 0x1, 0x1, 0x1, /* auth[23] */
8942 0x1, 0x1, 0x1, 0x1, /* auth[24] */
8943 0x1, 0x1, 0x1, 0x1, /* auth[25] */
8944 0x1, 0x1, 0x1, 0x1, /* auth[26] */
8945 0x1, 0x1, 0x1, 0x1, /* auth[27] */
8946 0x1, 0x1, 0x1, 0x1, /* auth[28] */
8947 0x1, 0x1, 0x1, 0x1, /* auth[29] */
8948 0x1, 0x1, 0x1, 0x1, /* auth[30] */
8949 0x1, 0x1, 0x1, 0x1, /* auth[31] */
8952 if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
8953 return false;
8955 if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
8956 return false;
8958 if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
8959 return false;
8961 return true;
8964 /* Split a path name into filename and stream name components. Canonicalise
8965 * such that an implicit $DATA token is always explicit.
8967 * The "specification" of this function can be found in the
8968 * run_local_stream_name() function in torture.c, I've tried those
8969 * combinations against a W2k3 server.
8972 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
8973 char **pbase, char **pstream)
8975 char *base = NULL;
8976 char *stream = NULL;
8977 char *sname; /* stream name */
8978 const char *stype; /* stream type */
8980 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
8982 sname = strchr_m(fname, ':');
8984 if (lp_posix_pathnames() || (sname == NULL)) {
8985 if (pbase != NULL) {
8986 base = talloc_strdup(mem_ctx, fname);
8987 NT_STATUS_HAVE_NO_MEMORY(base);
8989 goto done;
8992 if (pbase != NULL) {
8993 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
8994 NT_STATUS_HAVE_NO_MEMORY(base);
8997 sname += 1;
8999 stype = strchr_m(sname, ':');
9001 if (stype == NULL) {
9002 sname = talloc_strdup(mem_ctx, sname);
9003 stype = "$DATA";
9005 else {
9006 if (strcasecmp_m(stype, ":$DATA") != 0) {
9008 * If there is an explicit stream type, so far we only
9009 * allow $DATA. Is there anything else allowed? -- vl
9011 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
9012 TALLOC_FREE(base);
9013 return NT_STATUS_OBJECT_NAME_INVALID;
9015 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
9016 stype += 1;
9019 if (sname == NULL) {
9020 TALLOC_FREE(base);
9021 return NT_STATUS_NO_MEMORY;
9024 if (sname[0] == '\0') {
9026 * no stream name, so no stream
9028 goto done;
9031 if (pstream != NULL) {
9032 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
9033 if (stream == NULL) {
9034 TALLOC_FREE(sname);
9035 TALLOC_FREE(base);
9036 return NT_STATUS_NO_MEMORY;
9039 * upper-case the type field
9041 (void)strupper_m(strchr_m(stream, ':')+1);
9044 done:
9045 if (pbase != NULL) {
9046 *pbase = base;
9048 if (pstream != NULL) {
9049 *pstream = stream;
9051 return NT_STATUS_OK;
9054 static bool test_stream_name(const char *fname, const char *expected_base,
9055 const char *expected_stream,
9056 NTSTATUS expected_status)
9058 NTSTATUS status;
9059 char *base = NULL;
9060 char *stream = NULL;
9062 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
9063 if (!NT_STATUS_EQUAL(status, expected_status)) {
9064 goto error;
9067 if (!NT_STATUS_IS_OK(status)) {
9068 return true;
9071 if (base == NULL) goto error;
9073 if (strcmp(expected_base, base) != 0) goto error;
9075 if ((expected_stream != NULL) && (stream == NULL)) goto error;
9076 if ((expected_stream == NULL) && (stream != NULL)) goto error;
9078 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
9079 goto error;
9081 TALLOC_FREE(base);
9082 TALLOC_FREE(stream);
9083 return true;
9085 error:
9086 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
9087 fname, expected_base ? expected_base : "<NULL>",
9088 expected_stream ? expected_stream : "<NULL>",
9089 nt_errstr(expected_status));
9090 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
9091 base ? base : "<NULL>", stream ? stream : "<NULL>",
9092 nt_errstr(status));
9093 TALLOC_FREE(base);
9094 TALLOC_FREE(stream);
9095 return false;
9098 static bool run_local_stream_name(int dummy)
9100 bool ret = true;
9102 ret &= test_stream_name(
9103 "bla", "bla", NULL, NT_STATUS_OK);
9104 ret &= test_stream_name(
9105 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
9106 ret &= test_stream_name(
9107 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
9108 ret &= test_stream_name(
9109 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
9110 ret &= test_stream_name(
9111 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
9112 ret &= test_stream_name(
9113 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
9114 ret &= test_stream_name(
9115 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
9116 ret &= test_stream_name(
9117 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
9119 return ret;
9122 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
9124 if (a.length != b.length) {
9125 printf("a.length=%d != b.length=%d\n",
9126 (int)a.length, (int)b.length);
9127 return false;
9129 if (memcmp(a.data, b.data, a.length) != 0) {
9130 printf("a.data and b.data differ\n");
9131 return false;
9133 return true;
9136 static bool run_local_memcache(int dummy)
9138 struct memcache *cache;
9139 DATA_BLOB k1, k2;
9140 DATA_BLOB d1, d2, d3;
9141 DATA_BLOB v1, v2, v3;
9143 TALLOC_CTX *mem_ctx;
9144 char *str1, *str2;
9145 size_t size1, size2;
9146 bool ret = false;
9148 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
9150 if (cache == NULL) {
9151 printf("memcache_init failed\n");
9152 return false;
9155 d1 = data_blob_const("d1", 2);
9156 d2 = data_blob_const("d2", 2);
9157 d3 = data_blob_const("d3", 2);
9159 k1 = data_blob_const("d1", 2);
9160 k2 = data_blob_const("d2", 2);
9162 memcache_add(cache, STAT_CACHE, k1, d1);
9163 memcache_add(cache, GETWD_CACHE, k2, d2);
9165 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
9166 printf("could not find k1\n");
9167 return false;
9169 if (!data_blob_equal(d1, v1)) {
9170 return false;
9173 if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
9174 printf("could not find k2\n");
9175 return false;
9177 if (!data_blob_equal(d2, v2)) {
9178 return false;
9181 memcache_add(cache, STAT_CACHE, k1, d3);
9183 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
9184 printf("could not find replaced k1\n");
9185 return false;
9187 if (!data_blob_equal(d3, v3)) {
9188 return false;
9191 memcache_add(cache, GETWD_CACHE, k1, d1);
9193 if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
9194 printf("Did find k2, should have been purged\n");
9195 return false;
9198 TALLOC_FREE(cache);
9200 cache = memcache_init(NULL, 0);
9202 mem_ctx = talloc_init("foo");
9204 str1 = talloc_strdup(mem_ctx, "string1");
9205 str2 = talloc_strdup(mem_ctx, "string2");
9207 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
9208 data_blob_string_const("torture"), &str1);
9209 size1 = talloc_total_size(cache);
9211 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
9212 data_blob_string_const("torture"), &str2);
9213 size2 = talloc_total_size(cache);
9215 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
9217 if (size2 > size1) {
9218 printf("memcache leaks memory!\n");
9219 goto fail;
9222 ret = true;
9223 fail:
9224 TALLOC_FREE(cache);
9225 return ret;
9228 static void wbclient_done(struct tevent_req *req)
9230 wbcErr wbc_err;
9231 struct winbindd_response *wb_resp;
9232 int *i = (int *)tevent_req_callback_data_void(req);
9234 wbc_err = wb_trans_recv(req, req, &wb_resp);
9235 TALLOC_FREE(req);
9236 *i += 1;
9237 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
9240 static bool run_wbclient_multi_ping(int dummy)
9242 struct tevent_context *ev;
9243 struct wb_context **wb_ctx;
9244 struct winbindd_request wb_req;
9245 bool result = false;
9246 int i, j;
9248 BlockSignals(True, SIGPIPE);
9250 ev = tevent_context_init(talloc_tos());
9251 if (ev == NULL) {
9252 goto fail;
9255 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
9256 if (wb_ctx == NULL) {
9257 goto fail;
9260 ZERO_STRUCT(wb_req);
9261 wb_req.cmd = WINBINDD_PING;
9263 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
9265 for (i=0; i<torture_nprocs; i++) {
9266 wb_ctx[i] = wb_context_init(ev, NULL);
9267 if (wb_ctx[i] == NULL) {
9268 goto fail;
9270 for (j=0; j<torture_numops; j++) {
9271 struct tevent_req *req;
9272 req = wb_trans_send(ev, ev, wb_ctx[i],
9273 (j % 2) == 0, &wb_req);
9274 if (req == NULL) {
9275 goto fail;
9277 tevent_req_set_callback(req, wbclient_done, &i);
9281 i = 0;
9283 while (i < torture_nprocs * torture_numops) {
9284 tevent_loop_once(ev);
9287 result = true;
9288 fail:
9289 TALLOC_FREE(ev);
9290 return result;
9293 static void getaddrinfo_finished(struct tevent_req *req)
9295 char *name = (char *)tevent_req_callback_data_void(req);
9296 struct addrinfo *ainfo;
9297 int res;
9299 res = getaddrinfo_recv(req, &ainfo);
9300 if (res != 0) {
9301 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
9302 return;
9304 d_printf("gai(%s) succeeded\n", name);
9305 freeaddrinfo(ainfo);
9308 static bool run_getaddrinfo_send(int dummy)
9310 TALLOC_CTX *frame = talloc_stackframe();
9311 struct fncall_context *ctx;
9312 struct tevent_context *ev;
9313 bool result = false;
9314 const char *names[4] = { "www.samba.org", "notfound.samba.org",
9315 "www.slashdot.org", "heise.de" };
9316 struct tevent_req *reqs[4];
9317 int i;
9319 ev = samba_tevent_context_init(frame);
9320 if (ev == NULL) {
9321 goto fail;
9324 ctx = fncall_context_init(frame, 4);
9326 for (i=0; i<ARRAY_SIZE(names); i++) {
9327 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
9328 NULL);
9329 if (reqs[i] == NULL) {
9330 goto fail;
9332 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
9333 discard_const_p(void, names[i]));
9336 for (i=0; i<ARRAY_SIZE(reqs); i++) {
9337 tevent_loop_once(ev);
9340 result = true;
9341 fail:
9342 TALLOC_FREE(frame);
9343 return result;
9346 static bool dbtrans_inc(struct db_context *db)
9348 struct db_record *rec;
9349 uint32_t val;
9350 bool ret = false;
9351 NTSTATUS status;
9352 TDB_DATA value;
9354 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
9355 if (rec == NULL) {
9356 printf(__location__ "fetch_lock failed\n");
9357 return false;
9360 value = dbwrap_record_get_value(rec);
9362 if (value.dsize != sizeof(uint32_t)) {
9363 printf(__location__ "value.dsize = %d\n",
9364 (int)value.dsize);
9365 goto fail;
9368 memcpy(&val, value.dptr, sizeof(val));
9369 val += 1;
9371 status = dbwrap_record_store(
9372 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
9373 if (!NT_STATUS_IS_OK(status)) {
9374 printf(__location__ "store failed: %s\n",
9375 nt_errstr(status));
9376 goto fail;
9379 ret = true;
9380 fail:
9381 TALLOC_FREE(rec);
9382 return ret;
9385 static bool run_local_dbtrans(int dummy)
9387 struct db_context *db;
9388 struct db_record *rec;
9389 NTSTATUS status;
9390 uint32_t initial;
9391 int res;
9392 TDB_DATA value;
9394 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
9395 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
9396 DBWRAP_FLAG_NONE);
9397 if (db == NULL) {
9398 printf("Could not open transtest.db\n");
9399 return false;
9402 res = dbwrap_transaction_start(db);
9403 if (res != 0) {
9404 printf(__location__ "transaction_start failed\n");
9405 return false;
9408 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
9409 if (rec == NULL) {
9410 printf(__location__ "fetch_lock failed\n");
9411 return false;
9414 value = dbwrap_record_get_value(rec);
9416 if (value.dptr == NULL) {
9417 initial = 0;
9418 status = dbwrap_record_store(
9419 rec, make_tdb_data((uint8_t *)&initial,
9420 sizeof(initial)),
9422 if (!NT_STATUS_IS_OK(status)) {
9423 printf(__location__ "store returned %s\n",
9424 nt_errstr(status));
9425 return false;
9429 TALLOC_FREE(rec);
9431 res = dbwrap_transaction_commit(db);
9432 if (res != 0) {
9433 printf(__location__ "transaction_commit failed\n");
9434 return false;
9437 while (true) {
9438 uint32_t val, val2;
9439 int i;
9441 res = dbwrap_transaction_start(db);
9442 if (res != 0) {
9443 printf(__location__ "transaction_start failed\n");
9444 break;
9447 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
9448 if (!NT_STATUS_IS_OK(status)) {
9449 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
9450 nt_errstr(status));
9451 break;
9454 for (i=0; i<10; i++) {
9455 if (!dbtrans_inc(db)) {
9456 return false;
9460 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
9461 if (!NT_STATUS_IS_OK(status)) {
9462 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
9463 nt_errstr(status));
9464 break;
9467 if (val2 != val + 10) {
9468 printf(__location__ "val=%d, val2=%d\n",
9469 (int)val, (int)val2);
9470 break;
9473 printf("val2=%d\r", val2);
9475 res = dbwrap_transaction_commit(db);
9476 if (res != 0) {
9477 printf(__location__ "transaction_commit failed\n");
9478 break;
9482 TALLOC_FREE(db);
9483 return true;
9487 * Just a dummy test to be run under a debugger. There's no real way
9488 * to inspect the tevent_select specific function from outside of
9489 * tevent_select.c.
9492 static bool run_local_tevent_select(int dummy)
9494 struct tevent_context *ev;
9495 struct tevent_fd *fd1, *fd2;
9496 bool result = false;
9498 ev = tevent_context_init_byname(NULL, "select");
9499 if (ev == NULL) {
9500 d_fprintf(stderr, "tevent_context_init_byname failed\n");
9501 goto fail;
9504 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
9505 if (fd1 == NULL) {
9506 d_fprintf(stderr, "tevent_add_fd failed\n");
9507 goto fail;
9509 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
9510 if (fd2 == NULL) {
9511 d_fprintf(stderr, "tevent_add_fd failed\n");
9512 goto fail;
9514 TALLOC_FREE(fd2);
9516 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
9517 if (fd2 == NULL) {
9518 d_fprintf(stderr, "tevent_add_fd failed\n");
9519 goto fail;
9522 result = true;
9523 fail:
9524 TALLOC_FREE(ev);
9525 return result;
9528 static bool run_local_hex_encode_buf(int dummy)
9530 char buf[17];
9531 uint8_t src[8];
9532 int i;
9534 for (i=0; i<sizeof(src); i++) {
9535 src[i] = i;
9537 hex_encode_buf(buf, src, sizeof(src));
9538 if (strcmp(buf, "0001020304050607") != 0) {
9539 return false;
9541 hex_encode_buf(buf, NULL, 0);
9542 if (buf[0] != '\0') {
9543 return false;
9545 return true;
9548 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
9549 "0.0.0.0",
9550 "::0",
9551 "1.2.3.1",
9552 "0.0.0.0",
9553 "0.0.0.0",
9554 "1.2.3.2",
9555 "1.2.3.3",
9556 "1.2.3.4",
9557 "1.2.3.5",
9558 "::0",
9559 "1.2.3.6",
9560 "1.2.3.7",
9561 "::0",
9562 "::0",
9563 "::0",
9564 "1.2.3.8",
9565 "1.2.3.9",
9566 "1.2.3.10",
9567 "1.2.3.11",
9568 "1.2.3.12",
9569 "1.2.3.13",
9570 "1001:1111:1111:1000:0:1111:1111:1111",
9571 "1.2.3.1",
9572 "1.2.3.2",
9573 "1.2.3.3",
9574 "1.2.3.12",
9575 "::0",
9576 "::0"
9579 static const char *remove_duplicate_addrs2_test_strings_result[] = {
9580 "1.2.3.1",
9581 "1.2.3.2",
9582 "1.2.3.3",
9583 "1.2.3.4",
9584 "1.2.3.5",
9585 "1.2.3.6",
9586 "1.2.3.7",
9587 "1.2.3.8",
9588 "1.2.3.9",
9589 "1.2.3.10",
9590 "1.2.3.11",
9591 "1.2.3.12",
9592 "1.2.3.13",
9593 "1001:1111:1111:1000:0:1111:1111:1111"
9596 static bool run_local_remove_duplicate_addrs2(int dummy)
9598 struct ip_service test_vector[28];
9599 int count, i;
9601 /* Construct the sockaddr_storage test vector. */
9602 for (i = 0; i < 28; i++) {
9603 struct addrinfo hints;
9604 struct addrinfo *res = NULL;
9605 int ret;
9607 memset(&hints, '\0', sizeof(hints));
9608 hints.ai_flags = AI_NUMERICHOST;
9609 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
9610 NULL,
9611 &hints,
9612 &res);
9613 if (ret) {
9614 fprintf(stderr, "getaddrinfo failed on [%s]\n",
9615 remove_duplicate_addrs2_test_strings_vector[i]);
9616 return false;
9618 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
9619 memcpy(&test_vector[i].ss,
9620 res->ai_addr,
9621 res->ai_addrlen);
9622 freeaddrinfo(res);
9625 count = remove_duplicate_addrs2(test_vector, i);
9627 if (count != 14) {
9628 fprintf(stderr, "count wrong (%d) should be 14\n",
9629 count);
9630 return false;
9633 for (i = 0; i < count; i++) {
9634 char addr[INET6_ADDRSTRLEN];
9636 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
9638 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
9639 fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
9641 addr,
9642 remove_duplicate_addrs2_test_strings_result[i]);
9643 return false;
9647 printf("run_local_remove_duplicate_addrs2: success\n");
9648 return true;
9651 static bool run_local_tdb_opener(int dummy)
9653 TDB_CONTEXT *t;
9654 unsigned v = 0;
9656 while (1) {
9657 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
9658 O_RDWR|O_CREAT, 0755);
9659 if (t == NULL) {
9660 perror("tdb_open failed");
9661 return false;
9663 tdb_close(t);
9665 v += 1;
9666 printf("\r%u", v);
9668 return true;
9671 static bool run_local_tdb_writer(int dummy)
9673 TDB_CONTEXT *t;
9674 unsigned v = 0;
9675 TDB_DATA val;
9677 t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
9678 if (t == 0) {
9679 perror("tdb_open failed");
9680 return 1;
9683 val.dptr = (uint8_t *)&v;
9684 val.dsize = sizeof(v);
9686 while (1) {
9687 TDB_DATA data;
9688 int ret;
9690 ret = tdb_store(t, val, val, 0);
9691 if (ret != 0) {
9692 printf("%s\n", tdb_errorstr(t));
9694 v += 1;
9695 printf("\r%u", v);
9697 data = tdb_fetch(t, val);
9698 if (data.dptr != NULL) {
9699 SAFE_FREE(data.dptr);
9702 return true;
9705 static double create_procs(bool (*fn)(int), bool *result)
9707 int i, status;
9708 volatile pid_t *child_status;
9709 volatile bool *child_status_out;
9710 int synccount;
9711 int tries = 8;
9712 struct timeval start;
9714 synccount = 0;
9716 child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
9717 if (!child_status) {
9718 printf("Failed to setup shared memory\n");
9719 return -1;
9722 child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
9723 if (!child_status_out) {
9724 printf("Failed to setup result status shared memory\n");
9725 return -1;
9728 for (i = 0; i < torture_nprocs; i++) {
9729 child_status[i] = 0;
9730 child_status_out[i] = True;
9733 start = timeval_current();
9735 for (i=0;i<torture_nprocs;i++) {
9736 procnum = i;
9737 if (fork() == 0) {
9738 pid_t mypid = getpid();
9739 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
9741 slprintf(myname,sizeof(myname),"CLIENT%d", i);
9743 while (1) {
9744 if (torture_open_connection(&current_cli, i)) break;
9745 if (tries-- == 0) {
9746 printf("pid %d failed to start\n", (int)getpid());
9747 _exit(1);
9749 smb_msleep(10);
9752 child_status[i] = getpid();
9754 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
9756 child_status_out[i] = fn(i);
9757 _exit(0);
9761 do {
9762 synccount = 0;
9763 for (i=0;i<torture_nprocs;i++) {
9764 if (child_status[i]) synccount++;
9766 if (synccount == torture_nprocs) break;
9767 smb_msleep(10);
9768 } while (timeval_elapsed(&start) < 30);
9770 if (synccount != torture_nprocs) {
9771 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
9772 *result = False;
9773 return timeval_elapsed(&start);
9776 /* start the client load */
9777 start = timeval_current();
9779 for (i=0;i<torture_nprocs;i++) {
9780 child_status[i] = 0;
9783 printf("%d clients started\n", torture_nprocs);
9785 for (i=0;i<torture_nprocs;i++) {
9786 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
9789 printf("\n");
9791 for (i=0;i<torture_nprocs;i++) {
9792 if (!child_status_out[i]) {
9793 *result = False;
9796 return timeval_elapsed(&start);
9799 #define FLAG_MULTIPROC 1
9801 static struct {
9802 const char *name;
9803 bool (*fn)(int);
9804 unsigned flags;
9805 } torture_ops[] = {
9806 {"FDPASS", run_fdpasstest, 0},
9807 {"LOCK1", run_locktest1, 0},
9808 {"LOCK2", run_locktest2, 0},
9809 {"LOCK3", run_locktest3, 0},
9810 {"LOCK4", run_locktest4, 0},
9811 {"LOCK5", run_locktest5, 0},
9812 {"LOCK6", run_locktest6, 0},
9813 {"LOCK7", run_locktest7, 0},
9814 {"LOCK8", run_locktest8, 0},
9815 {"LOCK9", run_locktest9, 0},
9816 {"UNLINK", run_unlinktest, 0},
9817 {"BROWSE", run_browsetest, 0},
9818 {"ATTR", run_attrtest, 0},
9819 {"TRANS2", run_trans2test, 0},
9820 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
9821 {"TORTURE",run_torture, FLAG_MULTIPROC},
9822 {"RANDOMIPC", run_randomipc, 0},
9823 {"NEGNOWAIT", run_negprot_nowait, 0},
9824 {"NBENCH", run_nbench, 0},
9825 {"NBENCH2", run_nbench2, 0},
9826 {"OPLOCK1", run_oplock1, 0},
9827 {"OPLOCK2", run_oplock2, 0},
9828 {"OPLOCK4", run_oplock4, 0},
9829 {"DIR", run_dirtest, 0},
9830 {"DIR1", run_dirtest1, 0},
9831 {"DIR-CREATETIME", run_dir_createtime, 0},
9832 {"DENY1", torture_denytest1, 0},
9833 {"DENY2", torture_denytest2, 0},
9834 {"TCON", run_tcon_test, 0},
9835 {"TCONDEV", run_tcon_devtype_test, 0},
9836 {"RW1", run_readwritetest, 0},
9837 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
9838 {"RW3", run_readwritelarge, 0},
9839 {"RW-SIGNING", run_readwritelarge_signtest, 0},
9840 {"OPEN", run_opentest, 0},
9841 {"POSIX", run_simple_posix_open_test, 0},
9842 {"POSIX-APPEND", run_posix_append, 0},
9843 {"POSIX-SYMLINK-ACL", run_acl_symlink_test, 0},
9844 {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
9845 {"ASYNC-ECHO", run_async_echo, 0},
9846 { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
9847 { "SHORTNAME-TEST", run_shortname_test, 0},
9848 { "ADDRCHANGE", run_addrchange, 0},
9849 #if 1
9850 {"OPENATTR", run_openattrtest, 0},
9851 #endif
9852 {"XCOPY", run_xcopy, 0},
9853 {"RENAME", run_rename, 0},
9854 {"DELETE", run_deletetest, 0},
9855 {"WILDDELETE", run_wild_deletetest, 0},
9856 {"DELETE-LN", run_deletetest_ln, 0},
9857 {"PROPERTIES", run_properties, 0},
9858 {"MANGLE", torture_mangle, 0},
9859 {"MANGLE1", run_mangle1, 0},
9860 {"W2K", run_w2ktest, 0},
9861 {"TRANS2SCAN", torture_trans2_scan, 0},
9862 {"NTTRANSSCAN", torture_nttrans_scan, 0},
9863 {"UTABLE", torture_utable, 0},
9864 {"CASETABLE", torture_casetable, 0},
9865 {"ERRMAPEXTRACT", run_error_map_extract, 0},
9866 {"PIPE_NUMBER", run_pipe_number, 0},
9867 {"TCON2", run_tcon2_test, 0},
9868 {"IOCTL", torture_ioctl_test, 0},
9869 {"CHKPATH", torture_chkpath_test, 0},
9870 {"FDSESS", run_fdsesstest, 0},
9871 { "EATEST", run_eatest, 0},
9872 { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
9873 { "CHAIN1", run_chain1, 0},
9874 { "CHAIN2", run_chain2, 0},
9875 { "CHAIN3", run_chain3, 0},
9876 { "WINDOWS-WRITE", run_windows_write, 0},
9877 { "LARGE_READX", run_large_readx, 0},
9878 { "NTTRANS-CREATE", run_nttrans_create, 0},
9879 { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
9880 { "CLI_ECHO", run_cli_echo, 0},
9881 { "GETADDRINFO", run_getaddrinfo_send, 0},
9882 { "TLDAP", run_tldap },
9883 { "STREAMERROR", run_streamerror },
9884 { "NOTIFY-BENCH", run_notify_bench },
9885 { "NOTIFY-BENCH2", run_notify_bench2 },
9886 { "NOTIFY-BENCH3", run_notify_bench3 },
9887 { "BAD-NBT-SESSION", run_bad_nbt_session },
9888 { "SMB-ANY-CONNECT", run_smb_any_connect },
9889 { "NOTIFY-ONLINE", run_notify_online },
9890 { "SMB2-BASIC", run_smb2_basic },
9891 { "SMB2-NEGPROT", run_smb2_negprot },
9892 { "SMB2-SESSION-RECONNECT", run_smb2_session_reconnect },
9893 { "SMB2-TCON-DEPENDENCE", run_smb2_tcon_dependence },
9894 { "SMB2-MULTI-CHANNEL", run_smb2_multi_channel },
9895 { "SMB2-SESSION-REAUTH", run_smb2_session_reauth },
9896 { "CLEANUP1", run_cleanup1 },
9897 { "CLEANUP2", run_cleanup2 },
9898 { "CLEANUP3", run_cleanup3 },
9899 { "CLEANUP4", run_cleanup4 },
9900 { "OPLOCK-CANCEL", run_oplock_cancel },
9901 { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
9902 { "LOCAL-GENCACHE", run_local_gencache, 0},
9903 { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
9904 { "LOCAL-DBWRAP-WATCH1", run_dbwrap_watch1, 0 },
9905 { "LOCAL-MESSAGING-READ1", run_messaging_read1, 0 },
9906 { "LOCAL-MESSAGING-READ2", run_messaging_read2, 0 },
9907 { "LOCAL-MESSAGING-READ3", run_messaging_read3, 0 },
9908 { "LOCAL-MESSAGING-READ4", run_messaging_read4, 0 },
9909 { "LOCAL-MESSAGING-FDPASS1", run_messaging_fdpass1, 0 },
9910 { "LOCAL-MESSAGING-FDPASS2", run_messaging_fdpass2, 0 },
9911 { "LOCAL-MESSAGING-FDPASS2a", run_messaging_fdpass2a, 0 },
9912 { "LOCAL-MESSAGING-FDPASS2b", run_messaging_fdpass2b, 0 },
9913 { "LOCAL-BASE64", run_local_base64, 0},
9914 { "LOCAL-RBTREE", run_local_rbtree, 0},
9915 { "LOCAL-MEMCACHE", run_local_memcache, 0},
9916 { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
9917 { "WBCLIENT-MULTI-PING", run_wbclient_multi_ping, 0},
9918 { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
9919 { "LOCAL-sid_to_string", run_local_sid_to_string, 0},
9920 { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
9921 { "LOCAL-DBTRANS", run_local_dbtrans, 0},
9922 { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
9923 { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
9924 { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
9925 { "LOCAL-sprintf_append", run_local_sprintf_append, 0},
9926 { "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0},
9927 { "LOCAL-IDMAP-TDB-COMMON", run_idmap_tdb_common_test, 0},
9928 { "LOCAL-remove_duplicate_addrs2", run_local_remove_duplicate_addrs2, 0},
9929 { "local-tdb-opener", run_local_tdb_opener, 0 },
9930 { "local-tdb-writer", run_local_tdb_writer, 0 },
9931 { "LOCAL-DBWRAP-CTDB", run_local_dbwrap_ctdb, 0 },
9932 { "LOCAL-BENCH-PTHREADPOOL", run_bench_pthreadpool, 0 },
9933 { "qpathinfo-bufsize", run_qpathinfo_bufsize, 0 },
9934 {NULL, NULL, 0}};
9937 * dummy function to satisfy linker dependency
9939 struct tevent_context *winbind_event_context(void);
9940 struct tevent_context *winbind_event_context(void)
9942 return NULL;
9945 /****************************************************************************
9946 run a specified test or "ALL"
9947 ****************************************************************************/
9948 static bool run_test(const char *name)
9950 bool ret = True;
9951 bool result = True;
9952 bool found = False;
9953 int i;
9954 double t;
9955 if (strequal(name,"ALL")) {
9956 for (i=0;torture_ops[i].name;i++) {
9957 run_test(torture_ops[i].name);
9959 found = True;
9962 for (i=0;torture_ops[i].name;i++) {
9963 fstr_sprintf(randomfname, "\\XX%x",
9964 (unsigned)random());
9966 if (strequal(name, torture_ops[i].name)) {
9967 found = True;
9968 printf("Running %s\n", name);
9969 if (torture_ops[i].flags & FLAG_MULTIPROC) {
9970 t = create_procs(torture_ops[i].fn, &result);
9971 if (!result) {
9972 ret = False;
9973 printf("TEST %s FAILED!\n", name);
9975 } else {
9976 struct timeval start;
9977 start = timeval_current();
9978 if (!torture_ops[i].fn(0)) {
9979 ret = False;
9980 printf("TEST %s FAILED!\n", name);
9982 t = timeval_elapsed(&start);
9984 printf("%s took %g secs\n\n", name, t);
9988 if (!found) {
9989 printf("Did not find a test named %s\n", name);
9990 ret = False;
9993 return ret;
9997 static void usage(void)
9999 int i;
10001 printf("WARNING samba4 test suite is much more complete nowadays.\n");
10002 printf("Please use samba4 torture.\n\n");
10004 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
10006 printf("\t-d debuglevel\n");
10007 printf("\t-U user%%pass\n");
10008 printf("\t-k use kerberos\n");
10009 printf("\t-N numprocs\n");
10010 printf("\t-n my_netbios_name\n");
10011 printf("\t-W workgroup\n");
10012 printf("\t-o num_operations\n");
10013 printf("\t-O socket_options\n");
10014 printf("\t-m maximum protocol\n");
10015 printf("\t-L use oplocks\n");
10016 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
10017 printf("\t-A showall\n");
10018 printf("\t-p port\n");
10019 printf("\t-s seed\n");
10020 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
10021 printf("\t-f filename filename to test\n");
10022 printf("\t-e encrypt\n");
10023 printf("\n\n");
10025 printf("tests are:");
10026 for (i=0;torture_ops[i].name;i++) {
10027 printf(" %s", torture_ops[i].name);
10029 printf("\n");
10031 printf("default test is ALL\n");
10033 exit(1);
10036 /****************************************************************************
10037 main program
10038 ****************************************************************************/
10039 int main(int argc,char *argv[])
10041 int opt, i;
10042 char *p;
10043 int gotuser = 0;
10044 int gotpass = 0;
10045 bool correct = True;
10046 TALLOC_CTX *frame = talloc_stackframe();
10047 int seed = time(NULL);
10049 #ifdef HAVE_SETBUFFER
10050 setbuffer(stdout, NULL, 0);
10051 #endif
10053 setup_logging("smbtorture", DEBUG_STDOUT);
10055 smb_init_locale();
10056 fault_setup();
10058 if (is_default_dyn_CONFIGFILE()) {
10059 if(getenv("SMB_CONF_PATH")) {
10060 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
10063 lp_load_global(get_dyn_CONFIGFILE());
10064 load_interfaces();
10066 if (argc < 2) {
10067 usage();
10070 for(p = argv[1]; *p; p++)
10071 if(*p == '\\')
10072 *p = '/';
10074 if (strncmp(argv[1], "//", 2)) {
10075 usage();
10078 fstrcpy(host, &argv[1][2]);
10079 p = strchr_m(&host[2],'/');
10080 if (!p) {
10081 usage();
10083 *p = 0;
10084 fstrcpy(share, p+1);
10086 fstrcpy(myname, get_myname(talloc_tos()));
10087 if (!*myname) {
10088 fprintf(stderr, "Failed to get my hostname.\n");
10089 return 1;
10092 if (*username == 0 && getenv("LOGNAME")) {
10093 fstrcpy(username,getenv("LOGNAME"));
10096 argc--;
10097 argv++;
10099 fstrcpy(workgroup, lp_workgroup());
10101 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
10102 != EOF) {
10103 switch (opt) {
10104 case 'p':
10105 port_to_use = atoi(optarg);
10106 break;
10107 case 's':
10108 seed = atoi(optarg);
10109 break;
10110 case 'W':
10111 fstrcpy(workgroup,optarg);
10112 break;
10113 case 'm':
10114 lp_set_cmdline("client max protocol", optarg);
10115 break;
10116 case 'N':
10117 torture_nprocs = atoi(optarg);
10118 break;
10119 case 'o':
10120 torture_numops = atoi(optarg);
10121 break;
10122 case 'd':
10123 lp_set_cmdline("log level", optarg);
10124 break;
10125 case 'O':
10126 sockops = optarg;
10127 break;
10128 case 'L':
10129 use_oplocks = True;
10130 break;
10131 case 'l':
10132 local_path = optarg;
10133 break;
10134 case 'A':
10135 torture_showall = True;
10136 break;
10137 case 'n':
10138 fstrcpy(myname, optarg);
10139 break;
10140 case 'c':
10141 client_txt = optarg;
10142 break;
10143 case 'e':
10144 do_encrypt = true;
10145 break;
10146 case 'k':
10147 #ifdef HAVE_KRB5
10148 use_kerberos = True;
10149 #else
10150 d_printf("No kerberos support compiled in\n");
10151 exit(1);
10152 #endif
10153 break;
10154 case 'U':
10155 gotuser = 1;
10156 fstrcpy(username,optarg);
10157 p = strchr_m(username,'%');
10158 if (p) {
10159 *p = 0;
10160 fstrcpy(password, p+1);
10161 gotpass = 1;
10163 break;
10164 case 'b':
10165 fstrcpy(multishare_conn_fname, optarg);
10166 use_multishare_conn = True;
10167 break;
10168 case 'B':
10169 torture_blocksize = atoi(optarg);
10170 break;
10171 case 'f':
10172 test_filename = SMB_STRDUP(optarg);
10173 break;
10174 default:
10175 printf("Unknown option %c (%d)\n", (char)opt, opt);
10176 usage();
10180 d_printf("using seed %d\n", seed);
10182 srandom(seed);
10184 if(use_kerberos && !gotuser) gotpass = True;
10186 while (!gotpass) {
10187 char pwd[256] = {0};
10188 int rc;
10190 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
10191 if (rc == 0) {
10192 fstrcpy(password, pwd);
10193 gotpass = 1;
10197 printf("host=%s share=%s user=%s myname=%s\n",
10198 host, share, username, myname);
10200 if (argc == optind) {
10201 correct = run_test("ALL");
10202 } else {
10203 for (i=optind;i<argc;i++) {
10204 if (!run_test(argv[i])) {
10205 correct = False;
10210 TALLOC_FREE(frame);
10212 if (correct) {
10213 return(0);
10214 } else {
10215 return(1);