auth/spnego: split out gensec_spnego_update_pre/post() functions
[Samba.git] / source3 / torture / torture.c
blob6959b715b00c9452bd106062339ca3275716e288
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/util/sys_rw_data.h"
45 #include "lib/util/base64.h"
47 extern char *optarg;
48 extern int optind;
50 fstring host, workgroup, share, password, username, myname;
51 struct cli_credentials *torture_creds;
52 static const char *sockops="TCP_NODELAY";
53 int torture_nprocs=1;
54 static int port_to_use=0;
55 int torture_numops=100;
56 int torture_blocksize=1024*1024;
57 static int procnum; /* records process count number when forking */
58 static struct cli_state *current_cli;
59 static fstring randomfname;
60 static bool use_oplocks;
61 static bool use_level_II_oplocks;
62 static const char *client_txt = "client_oplocks.txt";
63 static bool disable_spnego;
64 static bool use_kerberos;
65 static bool force_dos_errors;
66 static fstring multishare_conn_fname;
67 static bool use_multishare_conn = False;
68 static bool do_encrypt;
69 static const char *local_path = NULL;
70 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
71 char *test_filename;
73 bool torture_showall = False;
75 static double create_procs(bool (*fn)(int), bool *result);
77 /********************************************************************
78 Ensure a connection is encrypted.
79 ********************************************************************/
81 static bool force_cli_encryption(struct cli_state *c,
82 const char *sharename)
84 uint16_t major, minor;
85 uint32_t caplow, caphigh;
86 NTSTATUS status;
88 if (!SERVER_HAS_UNIX_CIFS(c)) {
89 d_printf("Encryption required and "
90 "server that doesn't support "
91 "UNIX extensions - failing connect\n");
92 return false;
95 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
96 &caphigh);
97 if (!NT_STATUS_IS_OK(status)) {
98 d_printf("Encryption required and "
99 "can't get UNIX CIFS extensions "
100 "version from server: %s\n", nt_errstr(status));
101 return false;
104 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
105 d_printf("Encryption required and "
106 "share %s doesn't support "
107 "encryption.\n", sharename);
108 return false;
111 status = cli_smb1_setup_encryption(c, torture_creds);
112 if (!NT_STATUS_IS_OK(status)) {
113 d_printf("Encryption required and "
114 "setup failed with error %s.\n",
115 nt_errstr(status));
116 return false;
119 return true;
123 static struct cli_state *open_nbt_connection(void)
125 struct cli_state *c;
126 NTSTATUS status;
127 int flags = 0;
129 if (disable_spnego) {
130 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
133 if (use_oplocks) {
134 flags |= CLI_FULL_CONNECTION_OPLOCKS;
137 if (use_level_II_oplocks) {
138 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
141 if (use_kerberos) {
142 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
145 if (force_dos_errors) {
146 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
149 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
150 signing_state, flags, &c);
151 if (!NT_STATUS_IS_OK(status)) {
152 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
153 return NULL;
156 cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
158 return c;
161 /****************************************************************************
162 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
163 ****************************************************************************/
165 static bool cli_bad_session_request(int fd,
166 struct nmb_name *calling, struct nmb_name *called)
168 TALLOC_CTX *frame;
169 uint8_t len_buf[4];
170 struct iovec iov[3];
171 ssize_t len;
172 uint8_t *inbuf;
173 int err;
174 bool ret = false;
175 uint8_t message_type;
176 uint8_t error;
177 struct tevent_context *ev;
178 struct tevent_req *req;
180 frame = talloc_stackframe();
182 iov[0].iov_base = len_buf;
183 iov[0].iov_len = sizeof(len_buf);
185 /* put in the destination name */
187 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
188 called->name_type);
189 if (iov[1].iov_base == NULL) {
190 goto fail;
192 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
193 talloc_get_size(iov[1].iov_base));
195 /* and my name */
197 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
198 calling->name_type);
199 if (iov[2].iov_base == NULL) {
200 goto fail;
202 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
203 talloc_get_size(iov[2].iov_base));
205 /* Deliberately corrupt the name len (first byte) */
206 *((uint8_t *)iov[2].iov_base) = 100;
208 /* send a session request (RFC 1002) */
209 /* setup the packet length
210 * Remove four bytes from the length count, since the length
211 * field in the NBT Session Service header counts the number
212 * of bytes which follow. The cli_send_smb() function knows
213 * about this and accounts for those four bytes.
214 * CRH.
217 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
218 SCVAL(len_buf,0,0x81);
220 len = write_data_iov(fd, iov, 3);
221 if (len == -1) {
222 goto fail;
225 ev = samba_tevent_context_init(frame);
226 if (ev == NULL) {
227 goto fail;
229 req = read_smb_send(frame, ev, fd);
230 if (req == NULL) {
231 goto fail;
233 if (!tevent_req_poll(req, ev)) {
234 goto fail;
236 len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
237 if (len == -1) {
238 errno = err;
239 goto fail;
241 TALLOC_FREE(ev);
243 message_type = CVAL(inbuf, 0);
244 if (message_type != 0x83) {
245 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
246 message_type);
247 goto fail;
250 if (smb_len(inbuf) != 1) {
251 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
252 (int)smb_len(inbuf));
253 goto fail;
256 error = CVAL(inbuf, 4);
257 if (error != 0x82) {
258 d_fprintf(stderr, "Expected error 0x82, got %d\n",
259 (int)error);
260 goto fail;
263 ret = true;
264 fail:
265 TALLOC_FREE(frame);
266 return ret;
269 /* Insert a NULL at the first separator of the given path and return a pointer
270 * to the remainder of the string.
272 static char *
273 terminate_path_at_separator(char * path)
275 char * p;
277 if (!path) {
278 return NULL;
281 if ((p = strchr_m(path, '/'))) {
282 *p = '\0';
283 return p + 1;
286 if ((p = strchr_m(path, '\\'))) {
287 *p = '\0';
288 return p + 1;
291 /* No separator. */
292 return NULL;
296 parse a //server/share type UNC name
298 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
299 char **hostname, char **sharename)
301 char *p;
303 *hostname = *sharename = NULL;
305 if (strncmp(unc_name, "\\\\", 2) &&
306 strncmp(unc_name, "//", 2)) {
307 return False;
310 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
311 p = terminate_path_at_separator(*hostname);
313 if (p && *p) {
314 *sharename = talloc_strdup(mem_ctx, p);
315 terminate_path_at_separator(*sharename);
318 if (*hostname && *sharename) {
319 return True;
322 TALLOC_FREE(*hostname);
323 TALLOC_FREE(*sharename);
324 return False;
327 static bool torture_open_connection_share(struct cli_state **c,
328 const char *hostname,
329 const char *sharename,
330 int flags)
332 NTSTATUS status;
334 status = cli_full_connection_creds(c,
335 myname,
336 hostname,
337 NULL, /* dest_ss */
338 port_to_use,
339 sharename,
340 "?????",
341 torture_creds,
342 flags,
343 signing_state);
344 if (!NT_STATUS_IS_OK(status)) {
345 printf("failed to open share connection: //%s/%s port:%d - %s\n",
346 hostname, sharename, port_to_use, nt_errstr(status));
347 return False;
350 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
352 if (do_encrypt) {
353 return force_cli_encryption(*c,
354 sharename);
356 return True;
359 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
361 char **unc_list = NULL;
362 int num_unc_names = 0;
363 bool result;
365 if (use_multishare_conn==True) {
366 char *h, *s;
367 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
368 if (!unc_list || num_unc_names <= 0) {
369 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
370 exit(1);
373 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
374 NULL, &h, &s)) {
375 printf("Failed to parse UNC name %s\n",
376 unc_list[conn_index % num_unc_names]);
377 TALLOC_FREE(unc_list);
378 exit(1);
381 result = torture_open_connection_share(c, h, s, flags);
383 /* h, s were copied earlier */
384 TALLOC_FREE(unc_list);
385 return result;
388 return torture_open_connection_share(c, host, share, flags);
391 bool torture_open_connection(struct cli_state **c, int conn_index)
393 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
395 if (use_oplocks) {
396 flags |= CLI_FULL_CONNECTION_OPLOCKS;
398 if (use_level_II_oplocks) {
399 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
402 return torture_open_connection_flags(c, conn_index, flags);
405 bool torture_init_connection(struct cli_state **pcli)
407 struct cli_state *cli;
409 cli = open_nbt_connection();
410 if (cli == NULL) {
411 return false;
414 *pcli = cli;
415 return true;
418 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
420 uint16_t old_vuid = cli_state_get_uid(cli);
421 NTSTATUS status;
422 bool ret;
424 cli_state_set_uid(cli, 0);
425 status = cli_session_setup_creds(cli, torture_creds);
426 ret = NT_STATUS_IS_OK(status);
427 *new_vuid = cli_state_get_uid(cli);
428 cli_state_set_uid(cli, old_vuid);
429 return ret;
433 bool torture_close_connection(struct cli_state *c)
435 bool ret = True;
436 NTSTATUS status;
438 status = cli_tdis(c);
439 if (!NT_STATUS_IS_OK(status)) {
440 printf("tdis failed (%s)\n", nt_errstr(status));
441 ret = False;
444 cli_shutdown(c);
446 return ret;
450 /* check if the server produced the expected dos or nt error code */
451 static bool check_both_error(int line, NTSTATUS status,
452 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
454 if (NT_STATUS_IS_DOS(status)) {
455 uint8_t cclass;
456 uint32_t num;
458 /* Check DOS error */
459 cclass = NT_STATUS_DOS_CLASS(status);
460 num = NT_STATUS_DOS_CODE(status);
462 if (eclass != cclass || ecode != num) {
463 printf("unexpected error code class=%d code=%d\n",
464 (int)cclass, (int)num);
465 printf(" expected %d/%d %s (line=%d)\n",
466 (int)eclass, (int)ecode, nt_errstr(nterr), line);
467 return false;
469 } else {
470 /* Check NT error */
471 if (!NT_STATUS_EQUAL(nterr, status)) {
472 printf("unexpected error code %s\n",
473 nt_errstr(status));
474 printf(" expected %s (line=%d)\n",
475 nt_errstr(nterr), line);
476 return false;
480 return true;
484 /* check if the server produced the expected error code */
485 static bool check_error(int line, NTSTATUS status,
486 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
488 if (NT_STATUS_IS_DOS(status)) {
489 uint8_t cclass;
490 uint32_t num;
492 /* Check DOS error */
494 cclass = NT_STATUS_DOS_CLASS(status);
495 num = NT_STATUS_DOS_CODE(status);
497 if (eclass != cclass || ecode != num) {
498 printf("unexpected error code class=%d code=%d\n",
499 (int)cclass, (int)num);
500 printf(" expected %d/%d %s (line=%d)\n",
501 (int)eclass, (int)ecode, nt_errstr(nterr),
502 line);
503 return False;
506 } else {
507 /* Check NT error */
509 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
510 printf("unexpected error code %s\n",
511 nt_errstr(status));
512 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
513 line);
514 return False;
518 return True;
522 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
524 NTSTATUS status;
526 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
528 while (!NT_STATUS_IS_OK(status)) {
529 if (!check_both_error(__LINE__, status, ERRDOS,
530 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
531 return false;
534 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
537 return true;
541 static bool rw_torture(struct cli_state *c)
543 const char *lockfname = "\\torture.lck";
544 fstring fname;
545 uint16_t fnum;
546 uint16_t fnum2;
547 pid_t pid2, pid = getpid();
548 int i, j;
549 char buf[1024];
550 bool correct = True;
551 size_t nread = 0;
552 NTSTATUS status;
554 memset(buf, '\0', sizeof(buf));
556 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
557 DENY_NONE, &fnum2);
558 if (!NT_STATUS_IS_OK(status)) {
559 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
561 if (!NT_STATUS_IS_OK(status)) {
562 printf("open of %s failed (%s)\n",
563 lockfname, nt_errstr(status));
564 return False;
567 for (i=0;i<torture_numops;i++) {
568 unsigned n = (unsigned)sys_random()%10;
570 if (i % 10 == 0) {
571 printf("%d\r", i); fflush(stdout);
573 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
575 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
576 return False;
579 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
580 DENY_ALL, &fnum);
581 if (!NT_STATUS_IS_OK(status)) {
582 printf("open failed (%s)\n", nt_errstr(status));
583 correct = False;
584 break;
587 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
588 sizeof(pid), NULL);
589 if (!NT_STATUS_IS_OK(status)) {
590 printf("write failed (%s)\n", nt_errstr(status));
591 correct = False;
594 for (j=0;j<50;j++) {
595 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
596 sizeof(pid)+(j*sizeof(buf)),
597 sizeof(buf), NULL);
598 if (!NT_STATUS_IS_OK(status)) {
599 printf("write failed (%s)\n",
600 nt_errstr(status));
601 correct = False;
605 pid2 = 0;
607 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
608 &nread);
609 if (!NT_STATUS_IS_OK(status)) {
610 printf("read failed (%s)\n", nt_errstr(status));
611 correct = false;
612 } else if (nread != sizeof(pid)) {
613 printf("read/write compare failed: "
614 "recv %ld req %ld\n", (unsigned long)nread,
615 (unsigned long)sizeof(pid));
616 correct = false;
619 if (pid2 != pid) {
620 printf("data corruption!\n");
621 correct = False;
624 status = cli_close(c, fnum);
625 if (!NT_STATUS_IS_OK(status)) {
626 printf("close failed (%s)\n", nt_errstr(status));
627 correct = False;
630 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
631 if (!NT_STATUS_IS_OK(status)) {
632 printf("unlink failed (%s)\n", nt_errstr(status));
633 correct = False;
636 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
637 if (!NT_STATUS_IS_OK(status)) {
638 printf("unlock failed (%s)\n", nt_errstr(status));
639 correct = False;
643 cli_close(c, fnum2);
644 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
646 printf("%d\n", i);
648 return correct;
651 static bool run_torture(int dummy)
653 struct cli_state *cli;
654 bool ret;
656 cli = current_cli;
658 smbXcli_conn_set_sockopt(cli->conn, sockops);
660 ret = rw_torture(cli);
662 if (!torture_close_connection(cli)) {
663 ret = False;
666 return ret;
669 static bool rw_torture3(struct cli_state *c, char *lockfname)
671 uint16_t fnum = (uint16_t)-1;
672 unsigned int i = 0;
673 char buf[131072];
674 char buf_rd[131072];
675 unsigned count;
676 unsigned countprev = 0;
677 size_t sent = 0;
678 bool correct = True;
679 NTSTATUS status = NT_STATUS_OK;
681 srandom(1);
682 for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
684 SIVAL(buf, i, sys_random());
687 if (procnum == 0)
689 status = cli_unlink(
690 c, lockfname,
691 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
692 if (!NT_STATUS_IS_OK(status)) {
693 printf("unlink failed (%s) (normal, this file should "
694 "not exist)\n", nt_errstr(status));
697 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
698 DENY_NONE, &fnum);
699 if (!NT_STATUS_IS_OK(status)) {
700 printf("first open read/write of %s failed (%s)\n",
701 lockfname, nt_errstr(status));
702 return False;
705 else
707 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
709 status = cli_openx(c, lockfname, O_RDONLY,
710 DENY_NONE, &fnum);
711 if (NT_STATUS_IS_OK(status)) {
712 break;
714 smb_msleep(10);
716 if (!NT_STATUS_IS_OK(status)) {
717 printf("second open read-only of %s failed (%s)\n",
718 lockfname, nt_errstr(status));
719 return False;
723 i = 0;
724 for (count = 0; count < sizeof(buf); count += sent)
726 if (count >= countprev) {
727 printf("%d %8d\r", i, count);
728 fflush(stdout);
729 i++;
730 countprev += (sizeof(buf) / 20);
733 if (procnum == 0)
735 sent = ((unsigned)sys_random()%(20))+ 1;
736 if (sent > sizeof(buf) - count)
738 sent = sizeof(buf) - count;
741 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
742 count, sent, NULL);
743 if (!NT_STATUS_IS_OK(status)) {
744 printf("write failed (%s)\n",
745 nt_errstr(status));
746 correct = False;
749 else
751 status = cli_read(c, fnum, buf_rd+count, count,
752 sizeof(buf)-count, &sent);
753 if(!NT_STATUS_IS_OK(status)) {
754 printf("read failed offset:%d size:%ld (%s)\n",
755 count, (unsigned long)sizeof(buf)-count,
756 nt_errstr(status));
757 correct = False;
758 sent = 0;
759 } else if (sent > 0) {
760 if (memcmp(buf_rd+count, buf+count, sent) != 0)
762 printf("read/write compare failed\n");
763 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
764 correct = False;
765 break;
772 status = cli_close(c, fnum);
773 if (!NT_STATUS_IS_OK(status)) {
774 printf("close failed (%s)\n", nt_errstr(status));
775 correct = False;
778 return correct;
781 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
783 const char *lockfname = "\\torture2.lck";
784 uint16_t fnum1;
785 uint16_t fnum2;
786 int i;
787 char buf[131072];
788 char buf_rd[131072];
789 bool correct = True;
790 size_t bytes_read;
791 NTSTATUS status;
793 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
794 if (!NT_STATUS_IS_OK(status)) {
795 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
798 status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
799 DENY_NONE, &fnum1);
800 if (!NT_STATUS_IS_OK(status)) {
801 printf("first open read/write of %s failed (%s)\n",
802 lockfname, nt_errstr(status));
803 return False;
806 status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
807 if (!NT_STATUS_IS_OK(status)) {
808 printf("second open read-only of %s failed (%s)\n",
809 lockfname, nt_errstr(status));
810 cli_close(c1, fnum1);
811 return False;
814 for (i = 0; i < torture_numops; i++)
816 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
817 if (i % 10 == 0) {
818 printf("%d\r", i); fflush(stdout);
821 generate_random_buffer((unsigned char *)buf, buf_size);
823 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
824 buf_size, NULL);
825 if (!NT_STATUS_IS_OK(status)) {
826 printf("write failed (%s)\n", nt_errstr(status));
827 correct = False;
828 break;
831 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
832 if(!NT_STATUS_IS_OK(status)) {
833 printf("read failed (%s)\n", nt_errstr(status));
834 correct = false;
835 break;
836 } else if (bytes_read != buf_size) {
837 printf("read failed\n");
838 printf("read %ld, expected %ld\n",
839 (unsigned long)bytes_read,
840 (unsigned long)buf_size);
841 correct = False;
842 break;
845 if (memcmp(buf_rd, buf, buf_size) != 0)
847 printf("read/write compare failed\n");
848 correct = False;
849 break;
853 status = cli_close(c2, fnum2);
854 if (!NT_STATUS_IS_OK(status)) {
855 printf("close failed (%s)\n", nt_errstr(status));
856 correct = False;
859 status = cli_close(c1, fnum1);
860 if (!NT_STATUS_IS_OK(status)) {
861 printf("close failed (%s)\n", nt_errstr(status));
862 correct = False;
865 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
866 if (!NT_STATUS_IS_OK(status)) {
867 printf("unlink failed (%s)\n", nt_errstr(status));
868 correct = False;
871 return correct;
874 static bool run_readwritetest(int dummy)
876 struct cli_state *cli1, *cli2;
877 bool test1, test2 = False;
879 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
880 return False;
882 smbXcli_conn_set_sockopt(cli1->conn, sockops);
883 smbXcli_conn_set_sockopt(cli2->conn, sockops);
885 printf("starting readwritetest\n");
887 test1 = rw_torture2(cli1, cli2);
888 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
890 if (test1) {
891 test2 = rw_torture2(cli1, cli1);
892 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
895 if (!torture_close_connection(cli1)) {
896 test1 = False;
899 if (!torture_close_connection(cli2)) {
900 test2 = False;
903 return (test1 && test2);
906 static bool run_readwritemulti(int dummy)
908 struct cli_state *cli;
909 bool test;
911 cli = current_cli;
913 smbXcli_conn_set_sockopt(cli->conn, sockops);
915 printf("run_readwritemulti: fname %s\n", randomfname);
916 test = rw_torture3(cli, randomfname);
918 if (!torture_close_connection(cli)) {
919 test = False;
922 return test;
925 static bool run_readwritelarge_internal(void)
927 static struct cli_state *cli1;
928 uint16_t fnum1;
929 const char *lockfname = "\\large.dat";
930 off_t fsize;
931 char buf[126*1024];
932 bool correct = True;
933 NTSTATUS status;
935 if (!torture_open_connection(&cli1, 0)) {
936 return False;
938 smbXcli_conn_set_sockopt(cli1->conn, sockops);
939 memset(buf,'\0',sizeof(buf));
941 printf("starting readwritelarge_internal\n");
943 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
945 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
946 DENY_NONE, &fnum1);
947 if (!NT_STATUS_IS_OK(status)) {
948 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
949 return False;
952 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
954 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
955 NULL, NULL, NULL);
956 if (!NT_STATUS_IS_OK(status)) {
957 printf("qfileinfo failed (%s)\n", nt_errstr(status));
958 correct = False;
961 if (fsize == sizeof(buf))
962 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
963 (unsigned long)fsize);
964 else {
965 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
966 (unsigned long)fsize);
967 correct = False;
970 status = cli_close(cli1, fnum1);
971 if (!NT_STATUS_IS_OK(status)) {
972 printf("close failed (%s)\n", nt_errstr(status));
973 correct = False;
976 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
977 if (!NT_STATUS_IS_OK(status)) {
978 printf("unlink failed (%s)\n", nt_errstr(status));
979 correct = False;
982 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
983 DENY_NONE, &fnum1);
984 if (!NT_STATUS_IS_OK(status)) {
985 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
986 return False;
989 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
991 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
992 NULL, NULL, NULL);
993 if (!NT_STATUS_IS_OK(status)) {
994 printf("qfileinfo failed (%s)\n", nt_errstr(status));
995 correct = False;
998 if (fsize == sizeof(buf))
999 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1000 (unsigned long)fsize);
1001 else {
1002 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1003 (unsigned long)fsize);
1004 correct = False;
1007 #if 0
1008 /* ToDo - set allocation. JRA */
1009 if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1010 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1011 return False;
1013 if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1014 NULL, NULL)) {
1015 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1016 correct = False;
1018 if (fsize != 0)
1019 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1020 #endif
1022 status = cli_close(cli1, fnum1);
1023 if (!NT_STATUS_IS_OK(status)) {
1024 printf("close failed (%s)\n", nt_errstr(status));
1025 correct = False;
1028 if (!torture_close_connection(cli1)) {
1029 correct = False;
1031 return correct;
1034 static bool run_readwritelarge(int dummy)
1036 return run_readwritelarge_internal();
1039 static bool run_readwritelarge_signtest(int dummy)
1041 bool ret;
1042 signing_state = SMB_SIGNING_REQUIRED;
1043 ret = run_readwritelarge_internal();
1044 signing_state = SMB_SIGNING_DEFAULT;
1045 return ret;
1048 int line_count = 0;
1049 int nbio_id;
1051 #define ival(s) strtol(s, NULL, 0)
1053 /* run a test that simulates an approximate netbench client load */
1054 static bool run_netbench(int client)
1056 struct cli_state *cli;
1057 int i;
1058 char line[1024];
1059 char cname[20];
1060 FILE *f;
1061 const char *params[20];
1062 bool correct = True;
1064 cli = current_cli;
1066 nbio_id = client;
1068 smbXcli_conn_set_sockopt(cli->conn, sockops);
1070 nb_setup(cli);
1072 slprintf(cname,sizeof(cname)-1, "client%d", client);
1074 f = fopen(client_txt, "r");
1076 if (!f) {
1077 perror(client_txt);
1078 return False;
1081 while (fgets(line, sizeof(line)-1, f)) {
1082 char *saveptr;
1083 line_count++;
1085 line[strlen(line)-1] = 0;
1087 /* printf("[%d] %s\n", line_count, line); */
1089 all_string_sub(line,"client1", cname, sizeof(line));
1091 /* parse the command parameters */
1092 params[0] = strtok_r(line, " ", &saveptr);
1093 i = 0;
1094 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1096 params[i] = "";
1098 if (i < 2) continue;
1100 if (!strncmp(params[0],"SMB", 3)) {
1101 printf("ERROR: You are using a dbench 1 load file\n");
1102 exit(1);
1105 if (!strcmp(params[0],"NTCreateX")) {
1106 nb_createx(params[1], ival(params[2]), ival(params[3]),
1107 ival(params[4]));
1108 } else if (!strcmp(params[0],"Close")) {
1109 nb_close(ival(params[1]));
1110 } else if (!strcmp(params[0],"Rename")) {
1111 nb_rename(params[1], params[2]);
1112 } else if (!strcmp(params[0],"Unlink")) {
1113 nb_unlink(params[1]);
1114 } else if (!strcmp(params[0],"Deltree")) {
1115 nb_deltree(params[1]);
1116 } else if (!strcmp(params[0],"Rmdir")) {
1117 nb_rmdir(params[1]);
1118 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1119 nb_qpathinfo(params[1]);
1120 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1121 nb_qfileinfo(ival(params[1]));
1122 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1123 nb_qfsinfo(ival(params[1]));
1124 } else if (!strcmp(params[0],"FIND_FIRST")) {
1125 nb_findfirst(params[1]);
1126 } else if (!strcmp(params[0],"WriteX")) {
1127 nb_writex(ival(params[1]),
1128 ival(params[2]), ival(params[3]), ival(params[4]));
1129 } else if (!strcmp(params[0],"ReadX")) {
1130 nb_readx(ival(params[1]),
1131 ival(params[2]), ival(params[3]), ival(params[4]));
1132 } else if (!strcmp(params[0],"Flush")) {
1133 nb_flush(ival(params[1]));
1134 } else {
1135 printf("Unknown operation %s\n", params[0]);
1136 exit(1);
1139 fclose(f);
1141 nb_cleanup();
1143 if (!torture_close_connection(cli)) {
1144 correct = False;
1147 return correct;
1151 /* run a test that simulates an approximate netbench client load */
1152 static bool run_nbench(int dummy)
1154 double t;
1155 bool correct = True;
1157 nbio_shmem(torture_nprocs);
1159 nbio_id = -1;
1161 signal(SIGALRM, nb_alarm);
1162 alarm(1);
1163 t = create_procs(run_netbench, &correct);
1164 alarm(0);
1166 printf("\nThroughput %g MB/sec\n",
1167 1.0e-6 * nbio_total() / t);
1168 return correct;
1173 This test checks for two things:
1175 1) correct support for retaining locks over a close (ie. the server
1176 must not use posix semantics)
1177 2) support for lock timeouts
1179 static bool run_locktest1(int dummy)
1181 struct cli_state *cli1, *cli2;
1182 const char *fname = "\\lockt1.lck";
1183 uint16_t fnum1, fnum2, fnum3;
1184 time_t t1, t2;
1185 unsigned lock_timeout;
1186 NTSTATUS status;
1188 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1189 return False;
1191 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1192 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1194 printf("starting locktest1\n");
1196 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1198 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1199 &fnum1);
1200 if (!NT_STATUS_IS_OK(status)) {
1201 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1202 return False;
1205 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1206 if (!NT_STATUS_IS_OK(status)) {
1207 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1208 return False;
1211 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1212 if (!NT_STATUS_IS_OK(status)) {
1213 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1214 return False;
1217 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1218 if (!NT_STATUS_IS_OK(status)) {
1219 printf("lock1 failed (%s)\n", nt_errstr(status));
1220 return false;
1223 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1224 if (NT_STATUS_IS_OK(status)) {
1225 printf("lock2 succeeded! This is a locking bug\n");
1226 return false;
1227 } else {
1228 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1229 NT_STATUS_LOCK_NOT_GRANTED)) {
1230 return false;
1234 lock_timeout = (1 + (random() % 20));
1235 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1236 t1 = time(NULL);
1237 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1238 if (NT_STATUS_IS_OK(status)) {
1239 printf("lock3 succeeded! This is a locking bug\n");
1240 return false;
1241 } else {
1242 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1243 NT_STATUS_FILE_LOCK_CONFLICT)) {
1244 return false;
1247 t2 = time(NULL);
1249 if (ABS(t2 - t1) < lock_timeout-1) {
1250 printf("error: This server appears not to support timed lock requests\n");
1253 printf("server slept for %u seconds for a %u second timeout\n",
1254 (unsigned int)(t2-t1), lock_timeout);
1256 status = cli_close(cli1, fnum2);
1257 if (!NT_STATUS_IS_OK(status)) {
1258 printf("close1 failed (%s)\n", nt_errstr(status));
1259 return False;
1262 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1263 if (NT_STATUS_IS_OK(status)) {
1264 printf("lock4 succeeded! This is a locking bug\n");
1265 return false;
1266 } else {
1267 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1268 NT_STATUS_FILE_LOCK_CONFLICT)) {
1269 return false;
1273 status = cli_close(cli1, fnum1);
1274 if (!NT_STATUS_IS_OK(status)) {
1275 printf("close2 failed (%s)\n", nt_errstr(status));
1276 return False;
1279 status = cli_close(cli2, fnum3);
1280 if (!NT_STATUS_IS_OK(status)) {
1281 printf("close3 failed (%s)\n", nt_errstr(status));
1282 return False;
1285 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1286 if (!NT_STATUS_IS_OK(status)) {
1287 printf("unlink failed (%s)\n", nt_errstr(status));
1288 return False;
1292 if (!torture_close_connection(cli1)) {
1293 return False;
1296 if (!torture_close_connection(cli2)) {
1297 return False;
1300 printf("Passed locktest1\n");
1301 return True;
1305 this checks to see if a secondary tconx can use open files from an
1306 earlier tconx
1308 static bool run_tcon_test(int dummy)
1310 static struct cli_state *cli;
1311 const char *fname = "\\tcontest.tmp";
1312 uint16_t fnum1;
1313 uint32_t cnum1, cnum2, cnum3;
1314 struct smbXcli_tcon *orig_tcon = NULL;
1315 uint16_t vuid1, vuid2;
1316 char buf[4];
1317 bool ret = True;
1318 NTSTATUS status;
1320 memset(buf, '\0', sizeof(buf));
1322 if (!torture_open_connection(&cli, 0)) {
1323 return False;
1325 smbXcli_conn_set_sockopt(cli->conn, sockops);
1327 printf("starting tcontest\n");
1329 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1331 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1332 if (!NT_STATUS_IS_OK(status)) {
1333 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1334 return False;
1337 cnum1 = cli_state_get_tid(cli);
1338 vuid1 = cli_state_get_uid(cli);
1340 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1341 if (!NT_STATUS_IS_OK(status)) {
1342 printf("initial write failed (%s)", nt_errstr(status));
1343 return False;
1346 orig_tcon = cli_state_save_tcon(cli);
1347 if (orig_tcon == NULL) {
1348 return false;
1351 status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1352 if (!NT_STATUS_IS_OK(status)) {
1353 printf("%s refused 2nd tree connect (%s)\n", host,
1354 nt_errstr(status));
1355 cli_shutdown(cli);
1356 return False;
1359 cnum2 = cli_state_get_tid(cli);
1360 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1361 vuid2 = cli_state_get_uid(cli) + 1;
1363 /* try a write with the wrong tid */
1364 cli_state_set_tid(cli, cnum2);
1366 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1367 if (NT_STATUS_IS_OK(status)) {
1368 printf("* server allows write with wrong TID\n");
1369 ret = False;
1370 } else {
1371 printf("server fails write with wrong TID : %s\n",
1372 nt_errstr(status));
1376 /* try a write with an invalid tid */
1377 cli_state_set_tid(cli, cnum3);
1379 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1380 if (NT_STATUS_IS_OK(status)) {
1381 printf("* server allows write with invalid TID\n");
1382 ret = False;
1383 } else {
1384 printf("server fails write with invalid TID : %s\n",
1385 nt_errstr(status));
1388 /* try a write with an invalid vuid */
1389 cli_state_set_uid(cli, vuid2);
1390 cli_state_set_tid(cli, cnum1);
1392 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1393 if (NT_STATUS_IS_OK(status)) {
1394 printf("* server allows write with invalid VUID\n");
1395 ret = False;
1396 } else {
1397 printf("server fails write with invalid VUID : %s\n",
1398 nt_errstr(status));
1401 cli_state_set_tid(cli, cnum1);
1402 cli_state_set_uid(cli, vuid1);
1404 status = cli_close(cli, fnum1);
1405 if (!NT_STATUS_IS_OK(status)) {
1406 printf("close failed (%s)\n", nt_errstr(status));
1407 return False;
1410 cli_state_set_tid(cli, cnum2);
1412 status = cli_tdis(cli);
1413 if (!NT_STATUS_IS_OK(status)) {
1414 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1415 return False;
1418 cli_state_restore_tcon(cli, orig_tcon);
1420 cli_state_set_tid(cli, cnum1);
1422 if (!torture_close_connection(cli)) {
1423 return False;
1426 return ret;
1431 checks for old style tcon support
1433 static bool run_tcon2_test(int dummy)
1435 static struct cli_state *cli;
1436 uint16_t cnum, max_xmit;
1437 char *service;
1438 NTSTATUS status;
1440 if (!torture_open_connection(&cli, 0)) {
1441 return False;
1443 smbXcli_conn_set_sockopt(cli->conn, sockops);
1445 printf("starting tcon2 test\n");
1447 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1448 return false;
1451 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1453 SAFE_FREE(service);
1455 if (!NT_STATUS_IS_OK(status)) {
1456 printf("tcon2 failed : %s\n", nt_errstr(status));
1457 } else {
1458 printf("tcon OK : max_xmit=%d cnum=%d\n",
1459 (int)max_xmit, (int)cnum);
1462 if (!torture_close_connection(cli)) {
1463 return False;
1466 printf("Passed tcon2 test\n");
1467 return True;
1470 static bool tcon_devtest(struct cli_state *cli,
1471 const char *myshare, const char *devtype,
1472 const char *return_devtype,
1473 NTSTATUS expected_error)
1475 NTSTATUS status;
1476 bool ret;
1478 status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1480 if (NT_STATUS_IS_OK(expected_error)) {
1481 if (NT_STATUS_IS_OK(status)) {
1482 if (strcmp(cli->dev, return_devtype) == 0) {
1483 ret = True;
1484 } else {
1485 printf("tconX to share %s with type %s "
1486 "succeeded but returned the wrong "
1487 "device type (got [%s] but should have got [%s])\n",
1488 myshare, devtype, cli->dev, return_devtype);
1489 ret = False;
1491 } else {
1492 printf("tconX to share %s with type %s "
1493 "should have succeeded but failed\n",
1494 myshare, devtype);
1495 ret = False;
1497 cli_tdis(cli);
1498 } else {
1499 if (NT_STATUS_IS_OK(status)) {
1500 printf("tconx to share %s with type %s "
1501 "should have failed but succeeded\n",
1502 myshare, devtype);
1503 ret = False;
1504 } else {
1505 if (NT_STATUS_EQUAL(status, expected_error)) {
1506 ret = True;
1507 } else {
1508 printf("Returned unexpected error\n");
1509 ret = False;
1513 return ret;
1517 checks for correct tconX support
1519 static bool run_tcon_devtype_test(int dummy)
1521 static struct cli_state *cli1 = NULL;
1522 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1523 NTSTATUS status;
1524 bool ret = True;
1526 status = cli_full_connection_creds(&cli1,
1527 myname,
1528 host,
1529 NULL, /* dest_ss */
1530 port_to_use,
1531 NULL, /* service */
1532 NULL, /* service_type */
1533 torture_creds,
1534 flags,
1535 signing_state);
1537 if (!NT_STATUS_IS_OK(status)) {
1538 printf("could not open connection\n");
1539 return False;
1542 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1543 ret = False;
1545 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1546 ret = False;
1548 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1549 ret = False;
1551 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1552 ret = False;
1554 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1555 ret = False;
1557 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1558 ret = False;
1560 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1561 ret = False;
1563 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1564 ret = False;
1566 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1567 ret = False;
1569 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1570 ret = False;
1572 cli_shutdown(cli1);
1574 if (ret)
1575 printf("Passed tcondevtest\n");
1577 return ret;
1582 This test checks that
1584 1) the server supports multiple locking contexts on the one SMB
1585 connection, distinguished by PID.
1587 2) the server correctly fails overlapping locks made by the same PID (this
1588 goes against POSIX behaviour, which is why it is tricky to implement)
1590 3) the server denies unlock requests by an incorrect client PID
1592 static bool run_locktest2(int dummy)
1594 static struct cli_state *cli;
1595 const char *fname = "\\lockt2.lck";
1596 uint16_t fnum1, fnum2, fnum3;
1597 bool correct = True;
1598 NTSTATUS status;
1600 if (!torture_open_connection(&cli, 0)) {
1601 return False;
1604 smbXcli_conn_set_sockopt(cli->conn, sockops);
1606 printf("starting locktest2\n");
1608 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1610 cli_setpid(cli, 1);
1612 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1613 if (!NT_STATUS_IS_OK(status)) {
1614 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1615 return False;
1618 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1619 if (!NT_STATUS_IS_OK(status)) {
1620 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1621 return False;
1624 cli_setpid(cli, 2);
1626 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1627 if (!NT_STATUS_IS_OK(status)) {
1628 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1629 return False;
1632 cli_setpid(cli, 1);
1634 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1635 if (!NT_STATUS_IS_OK(status)) {
1636 printf("lock1 failed (%s)\n", nt_errstr(status));
1637 return false;
1640 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1641 if (NT_STATUS_IS_OK(status)) {
1642 printf("WRITE lock1 succeeded! This is a locking bug\n");
1643 correct = false;
1644 } else {
1645 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1646 NT_STATUS_LOCK_NOT_GRANTED)) {
1647 return false;
1651 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1652 if (NT_STATUS_IS_OK(status)) {
1653 printf("WRITE lock2 succeeded! This is a locking bug\n");
1654 correct = false;
1655 } else {
1656 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1657 NT_STATUS_LOCK_NOT_GRANTED)) {
1658 return false;
1662 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1663 if (NT_STATUS_IS_OK(status)) {
1664 printf("READ lock2 succeeded! This is a locking bug\n");
1665 correct = false;
1666 } else {
1667 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1668 NT_STATUS_FILE_LOCK_CONFLICT)) {
1669 return false;
1673 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1674 if (!NT_STATUS_IS_OK(status)) {
1675 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1677 cli_setpid(cli, 2);
1678 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1679 printf("unlock at 100 succeeded! This is a locking bug\n");
1680 correct = False;
1683 status = cli_unlock(cli, fnum1, 0, 4);
1684 if (NT_STATUS_IS_OK(status)) {
1685 printf("unlock1 succeeded! This is a locking bug\n");
1686 correct = false;
1687 } else {
1688 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1689 NT_STATUS_RANGE_NOT_LOCKED)) {
1690 return false;
1694 status = cli_unlock(cli, fnum1, 0, 8);
1695 if (NT_STATUS_IS_OK(status)) {
1696 printf("unlock2 succeeded! This is a locking bug\n");
1697 correct = false;
1698 } else {
1699 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1700 NT_STATUS_RANGE_NOT_LOCKED)) {
1701 return false;
1705 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1706 if (NT_STATUS_IS_OK(status)) {
1707 printf("lock3 succeeded! This is a locking bug\n");
1708 correct = false;
1709 } else {
1710 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1711 NT_STATUS_LOCK_NOT_GRANTED)) {
1712 return false;
1716 cli_setpid(cli, 1);
1718 status = cli_close(cli, fnum1);
1719 if (!NT_STATUS_IS_OK(status)) {
1720 printf("close1 failed (%s)\n", nt_errstr(status));
1721 return False;
1724 status = cli_close(cli, fnum2);
1725 if (!NT_STATUS_IS_OK(status)) {
1726 printf("close2 failed (%s)\n", nt_errstr(status));
1727 return False;
1730 status = cli_close(cli, fnum3);
1731 if (!NT_STATUS_IS_OK(status)) {
1732 printf("close3 failed (%s)\n", nt_errstr(status));
1733 return False;
1736 if (!torture_close_connection(cli)) {
1737 correct = False;
1740 printf("locktest2 finished\n");
1742 return correct;
1747 This test checks that
1749 1) the server supports the full offset range in lock requests
1751 static bool run_locktest3(int dummy)
1753 static struct cli_state *cli1, *cli2;
1754 const char *fname = "\\lockt3.lck";
1755 uint16_t fnum1, fnum2;
1756 int i;
1757 uint32_t offset;
1758 bool correct = True;
1759 NTSTATUS status;
1761 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1763 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1764 return False;
1766 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1767 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1769 printf("starting locktest3\n");
1771 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1773 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1774 &fnum1);
1775 if (!NT_STATUS_IS_OK(status)) {
1776 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1777 return False;
1780 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1781 if (!NT_STATUS_IS_OK(status)) {
1782 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1783 return False;
1786 for (offset=i=0;i<torture_numops;i++) {
1787 NEXT_OFFSET;
1789 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1790 if (!NT_STATUS_IS_OK(status)) {
1791 printf("lock1 %d failed (%s)\n",
1793 nt_errstr(status));
1794 return False;
1797 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1798 if (!NT_STATUS_IS_OK(status)) {
1799 printf("lock2 %d failed (%s)\n",
1801 nt_errstr(status));
1802 return False;
1806 for (offset=i=0;i<torture_numops;i++) {
1807 NEXT_OFFSET;
1809 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1810 if (NT_STATUS_IS_OK(status)) {
1811 printf("error: lock1 %d succeeded!\n", i);
1812 return False;
1815 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1816 if (NT_STATUS_IS_OK(status)) {
1817 printf("error: lock2 %d succeeded!\n", i);
1818 return False;
1821 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1822 if (NT_STATUS_IS_OK(status)) {
1823 printf("error: lock3 %d succeeded!\n", i);
1824 return False;
1827 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1828 if (NT_STATUS_IS_OK(status)) {
1829 printf("error: lock4 %d succeeded!\n", i);
1830 return False;
1834 for (offset=i=0;i<torture_numops;i++) {
1835 NEXT_OFFSET;
1837 status = cli_unlock(cli1, fnum1, offset-1, 1);
1838 if (!NT_STATUS_IS_OK(status)) {
1839 printf("unlock1 %d failed (%s)\n",
1841 nt_errstr(status));
1842 return False;
1845 status = cli_unlock(cli2, fnum2, offset-2, 1);
1846 if (!NT_STATUS_IS_OK(status)) {
1847 printf("unlock2 %d failed (%s)\n",
1849 nt_errstr(status));
1850 return False;
1854 status = cli_close(cli1, fnum1);
1855 if (!NT_STATUS_IS_OK(status)) {
1856 printf("close1 failed (%s)\n", nt_errstr(status));
1857 return False;
1860 status = cli_close(cli2, fnum2);
1861 if (!NT_STATUS_IS_OK(status)) {
1862 printf("close2 failed (%s)\n", nt_errstr(status));
1863 return False;
1866 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1867 if (!NT_STATUS_IS_OK(status)) {
1868 printf("unlink failed (%s)\n", nt_errstr(status));
1869 return False;
1872 if (!torture_close_connection(cli1)) {
1873 correct = False;
1876 if (!torture_close_connection(cli2)) {
1877 correct = False;
1880 printf("finished locktest3\n");
1882 return correct;
1885 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1886 char *buf, off_t offset, size_t size,
1887 size_t *nread, size_t expect)
1889 NTSTATUS status;
1890 size_t l_nread;
1892 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1894 if(!NT_STATUS_IS_OK(status)) {
1895 return false;
1896 } else if (l_nread != expect) {
1897 return false;
1900 if (nread) {
1901 *nread = l_nread;
1904 return true;
1907 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1908 printf("** "); correct = False; \
1912 looks at overlapping locks
1914 static bool run_locktest4(int dummy)
1916 static struct cli_state *cli1, *cli2;
1917 const char *fname = "\\lockt4.lck";
1918 uint16_t fnum1, fnum2, f;
1919 bool ret;
1920 char buf[1000];
1921 bool correct = True;
1922 NTSTATUS status;
1924 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1925 return False;
1928 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1929 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1931 printf("starting locktest4\n");
1933 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1935 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1936 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1938 memset(buf, 0, sizeof(buf));
1940 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1941 NULL);
1942 if (!NT_STATUS_IS_OK(status)) {
1943 printf("Failed to create file: %s\n", nt_errstr(status));
1944 correct = False;
1945 goto fail;
1948 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1949 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1950 EXPECTED(ret, False);
1951 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1953 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1954 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1955 EXPECTED(ret, True);
1956 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1958 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1959 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1960 EXPECTED(ret, False);
1961 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1963 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1964 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1965 EXPECTED(ret, True);
1966 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1968 ret = (cli_setpid(cli1, 1),
1969 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1970 (cli_setpid(cli1, 2),
1971 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1972 EXPECTED(ret, False);
1973 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1975 ret = (cli_setpid(cli1, 1),
1976 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1977 (cli_setpid(cli1, 2),
1978 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1979 EXPECTED(ret, True);
1980 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1982 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1983 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1984 EXPECTED(ret, True);
1985 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1987 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1988 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1989 EXPECTED(ret, False);
1990 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1992 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1993 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1994 EXPECTED(ret, False);
1995 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1997 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1998 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
1999 EXPECTED(ret, True);
2000 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2002 ret = (cli_setpid(cli1, 1),
2003 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2004 (cli_setpid(cli1, 2),
2005 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2006 EXPECTED(ret, False);
2007 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2009 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2010 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2011 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2012 EXPECTED(ret, False);
2013 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2016 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2017 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2018 EXPECTED(ret, False);
2019 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2021 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2022 ret = NT_STATUS_IS_OK(status);
2023 if (ret) {
2024 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2025 NULL);
2026 ret = NT_STATUS_IS_OK(status);
2028 EXPECTED(ret, False);
2029 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2032 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2033 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2034 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2035 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2036 EXPECTED(ret, True);
2037 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2040 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2041 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2042 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2043 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2044 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2045 150, 4, NULL))) &&
2046 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2047 EXPECTED(ret, True);
2048 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2050 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2051 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2052 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2053 160, 4, NULL)) &&
2054 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2055 EXPECTED(ret, True);
2056 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2058 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2059 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2060 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2061 170, 4, NULL)) &&
2062 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2063 EXPECTED(ret, True);
2064 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2066 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2067 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2068 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2069 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2070 190, 4, NULL)) &&
2071 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2072 EXPECTED(ret, True);
2073 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2075 cli_close(cli1, fnum1);
2076 cli_close(cli2, fnum2);
2077 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2078 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2079 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2080 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2081 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2082 NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2083 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2084 cli_close(cli1, f);
2085 cli_close(cli1, fnum1);
2086 EXPECTED(ret, True);
2087 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2089 fail:
2090 cli_close(cli1, fnum1);
2091 cli_close(cli2, fnum2);
2092 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2093 torture_close_connection(cli1);
2094 torture_close_connection(cli2);
2096 printf("finished locktest4\n");
2097 return correct;
2101 looks at lock upgrade/downgrade.
2103 static bool run_locktest5(int dummy)
2105 static struct cli_state *cli1, *cli2;
2106 const char *fname = "\\lockt5.lck";
2107 uint16_t fnum1, fnum2, fnum3;
2108 bool ret;
2109 char buf[1000];
2110 bool correct = True;
2111 NTSTATUS status;
2113 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2114 return False;
2117 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2118 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2120 printf("starting locktest5\n");
2122 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2124 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2125 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2126 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2128 memset(buf, 0, sizeof(buf));
2130 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2131 NULL);
2132 if (!NT_STATUS_IS_OK(status)) {
2133 printf("Failed to create file: %s\n", nt_errstr(status));
2134 correct = False;
2135 goto fail;
2138 /* Check for NT bug... */
2139 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2140 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2141 cli_close(cli1, fnum1);
2142 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2143 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2144 ret = NT_STATUS_IS_OK(status);
2145 EXPECTED(ret, True);
2146 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2147 cli_close(cli1, fnum1);
2148 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2149 cli_unlock(cli1, fnum3, 0, 1);
2151 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2152 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2153 EXPECTED(ret, True);
2154 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2156 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2157 ret = NT_STATUS_IS_OK(status);
2158 EXPECTED(ret, False);
2160 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2162 /* Unlock the process 2 lock. */
2163 cli_unlock(cli2, fnum2, 0, 4);
2165 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2166 ret = NT_STATUS_IS_OK(status);
2167 EXPECTED(ret, False);
2169 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2171 /* Unlock the process 1 fnum3 lock. */
2172 cli_unlock(cli1, fnum3, 0, 4);
2174 /* Stack 2 more locks here. */
2175 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2176 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2178 EXPECTED(ret, True);
2179 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2181 /* Unlock the first process lock, then check this was the WRITE lock that was
2182 removed. */
2184 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2185 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2187 EXPECTED(ret, True);
2188 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2190 /* Unlock the process 2 lock. */
2191 cli_unlock(cli2, fnum2, 0, 4);
2193 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2195 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2196 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2197 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2199 EXPECTED(ret, True);
2200 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2202 /* Ensure the next unlock fails. */
2203 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2204 EXPECTED(ret, False);
2205 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2207 /* Ensure connection 2 can get a write lock. */
2208 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2209 ret = NT_STATUS_IS_OK(status);
2210 EXPECTED(ret, True);
2212 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2215 fail:
2216 cli_close(cli1, fnum1);
2217 cli_close(cli2, fnum2);
2218 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2219 if (!torture_close_connection(cli1)) {
2220 correct = False;
2222 if (!torture_close_connection(cli2)) {
2223 correct = False;
2226 printf("finished locktest5\n");
2228 return correct;
2232 tries the unusual lockingX locktype bits
2234 static bool run_locktest6(int dummy)
2236 static struct cli_state *cli;
2237 const char *fname[1] = { "\\lock6.txt" };
2238 int i;
2239 uint16_t fnum;
2240 NTSTATUS status;
2242 if (!torture_open_connection(&cli, 0)) {
2243 return False;
2246 smbXcli_conn_set_sockopt(cli->conn, sockops);
2248 printf("starting locktest6\n");
2250 for (i=0;i<1;i++) {
2251 printf("Testing %s\n", fname[i]);
2253 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2255 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2256 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2257 cli_close(cli, fnum);
2258 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2260 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2261 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2262 cli_close(cli, fnum);
2263 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2265 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2268 torture_close_connection(cli);
2270 printf("finished locktest6\n");
2271 return True;
2274 static bool run_locktest7(int dummy)
2276 struct cli_state *cli1;
2277 const char *fname = "\\lockt7.lck";
2278 uint16_t fnum1;
2279 char buf[200];
2280 bool correct = False;
2281 size_t nread;
2282 NTSTATUS status;
2284 if (!torture_open_connection(&cli1, 0)) {
2285 return False;
2288 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2290 printf("starting locktest7\n");
2292 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2294 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2296 memset(buf, 0, sizeof(buf));
2298 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2299 NULL);
2300 if (!NT_STATUS_IS_OK(status)) {
2301 printf("Failed to create file: %s\n", nt_errstr(status));
2302 goto fail;
2305 cli_setpid(cli1, 1);
2307 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2308 if (!NT_STATUS_IS_OK(status)) {
2309 printf("Unable to apply read lock on range 130:4, "
2310 "error was %s\n", nt_errstr(status));
2311 goto fail;
2312 } else {
2313 printf("pid1 successfully locked range 130:4 for READ\n");
2316 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2317 if (!NT_STATUS_IS_OK(status)) {
2318 printf("pid1 unable to read the range 130:4, error was %s\n",
2319 nt_errstr(status));
2320 goto fail;
2321 } else if (nread != 4) {
2322 printf("pid1 unable to read the range 130:4, "
2323 "recv %ld req %d\n", (unsigned long)nread, 4);
2324 goto fail;
2325 } else {
2326 printf("pid1 successfully read the range 130:4\n");
2329 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2330 if (!NT_STATUS_IS_OK(status)) {
2331 printf("pid1 unable to write to the range 130:4, error was "
2332 "%s\n", nt_errstr(status));
2333 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2334 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2335 goto fail;
2337 } else {
2338 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2339 goto fail;
2342 cli_setpid(cli1, 2);
2344 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2345 if (!NT_STATUS_IS_OK(status)) {
2346 printf("pid2 unable to read the range 130:4, error was %s\n",
2347 nt_errstr(status));
2348 goto fail;
2349 } else if (nread != 4) {
2350 printf("pid2 unable to read the range 130:4, "
2351 "recv %ld req %d\n", (unsigned long)nread, 4);
2352 goto fail;
2353 } else {
2354 printf("pid2 successfully read the range 130:4\n");
2357 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2358 if (!NT_STATUS_IS_OK(status)) {
2359 printf("pid2 unable to write to the range 130:4, error was "
2360 "%s\n", nt_errstr(status));
2361 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2362 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2363 goto fail;
2365 } else {
2366 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2367 goto fail;
2370 cli_setpid(cli1, 1);
2371 cli_unlock(cli1, fnum1, 130, 4);
2373 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2374 if (!NT_STATUS_IS_OK(status)) {
2375 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2376 goto fail;
2377 } else {
2378 printf("pid1 successfully locked range 130:4 for WRITE\n");
2381 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2382 if (!NT_STATUS_IS_OK(status)) {
2383 printf("pid1 unable to read the range 130:4, error was %s\n",
2384 nt_errstr(status));
2385 goto fail;
2386 } else if (nread != 4) {
2387 printf("pid1 unable to read the range 130:4, "
2388 "recv %ld req %d\n", (unsigned long)nread, 4);
2389 goto fail;
2390 } else {
2391 printf("pid1 successfully read the range 130:4\n");
2394 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2395 if (!NT_STATUS_IS_OK(status)) {
2396 printf("pid1 unable to write to the range 130:4, error was "
2397 "%s\n", nt_errstr(status));
2398 goto fail;
2399 } else {
2400 printf("pid1 successfully wrote to the range 130:4\n");
2403 cli_setpid(cli1, 2);
2405 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2406 if (!NT_STATUS_IS_OK(status)) {
2407 printf("pid2 unable to read the range 130:4, error was "
2408 "%s\n", nt_errstr(status));
2409 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2410 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2411 goto fail;
2413 } else {
2414 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2415 (unsigned long)nread);
2416 goto fail;
2419 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2420 if (!NT_STATUS_IS_OK(status)) {
2421 printf("pid2 unable to write to the range 130:4, error was "
2422 "%s\n", nt_errstr(status));
2423 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2424 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2425 goto fail;
2427 } else {
2428 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2429 goto fail;
2432 cli_unlock(cli1, fnum1, 130, 0);
2433 correct = True;
2435 fail:
2436 cli_close(cli1, fnum1);
2437 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2438 torture_close_connection(cli1);
2440 printf("finished locktest7\n");
2441 return correct;
2445 * This demonstrates a problem with our use of GPFS share modes: A file
2446 * descriptor sitting in the pending close queue holding a GPFS share mode
2447 * blocks opening a file another time. Happens with Word 2007 temp files.
2448 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2449 * open is denied with NT_STATUS_SHARING_VIOLATION.
2452 static bool run_locktest8(int dummy)
2454 struct cli_state *cli1;
2455 const char *fname = "\\lockt8.lck";
2456 uint16_t fnum1, fnum2;
2457 char buf[200];
2458 bool correct = False;
2459 NTSTATUS status;
2461 if (!torture_open_connection(&cli1, 0)) {
2462 return False;
2465 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2467 printf("starting locktest8\n");
2469 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2471 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2472 &fnum1);
2473 if (!NT_STATUS_IS_OK(status)) {
2474 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2475 return false;
2478 memset(buf, 0, sizeof(buf));
2480 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2481 if (!NT_STATUS_IS_OK(status)) {
2482 d_fprintf(stderr, "cli_openx second time returned %s\n",
2483 nt_errstr(status));
2484 goto fail;
2487 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2488 if (!NT_STATUS_IS_OK(status)) {
2489 printf("Unable to apply read lock on range 1:1, error was "
2490 "%s\n", nt_errstr(status));
2491 goto fail;
2494 status = cli_close(cli1, fnum1);
2495 if (!NT_STATUS_IS_OK(status)) {
2496 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2497 goto fail;
2500 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2501 if (!NT_STATUS_IS_OK(status)) {
2502 d_fprintf(stderr, "cli_openx third time returned %s\n",
2503 nt_errstr(status));
2504 goto fail;
2507 correct = true;
2509 fail:
2510 cli_close(cli1, fnum1);
2511 cli_close(cli1, fnum2);
2512 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2513 torture_close_connection(cli1);
2515 printf("finished locktest8\n");
2516 return correct;
2520 * This test is designed to be run in conjunction with
2521 * external NFS or POSIX locks taken in the filesystem.
2522 * It checks that the smbd server will block until the
2523 * lock is released and then acquire it. JRA.
2526 static bool got_alarm;
2527 static struct cli_state *alarm_cli;
2529 static void alarm_handler(int dummy)
2531 got_alarm = True;
2534 static void alarm_handler_parent(int dummy)
2536 smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_OK);
2539 static void do_local_lock(int read_fd, int write_fd)
2541 int fd;
2542 char c = '\0';
2543 struct flock lock;
2544 const char *local_pathname = NULL;
2545 int ret;
2547 local_pathname = talloc_asprintf(talloc_tos(),
2548 "%s/lockt9.lck", local_path);
2549 if (!local_pathname) {
2550 printf("child: alloc fail\n");
2551 exit(1);
2554 unlink(local_pathname);
2555 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2556 if (fd == -1) {
2557 printf("child: open of %s failed %s.\n",
2558 local_pathname, strerror(errno));
2559 exit(1);
2562 /* Now take a fcntl lock. */
2563 lock.l_type = F_WRLCK;
2564 lock.l_whence = SEEK_SET;
2565 lock.l_start = 0;
2566 lock.l_len = 4;
2567 lock.l_pid = getpid();
2569 ret = fcntl(fd,F_SETLK,&lock);
2570 if (ret == -1) {
2571 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2572 local_pathname, strerror(errno));
2573 exit(1);
2574 } else {
2575 printf("child: got lock 0:4 on file %s.\n",
2576 local_pathname );
2577 fflush(stdout);
2580 CatchSignal(SIGALRM, alarm_handler);
2581 alarm(5);
2582 /* Signal the parent. */
2583 if (write(write_fd, &c, 1) != 1) {
2584 printf("child: start signal fail %s.\n",
2585 strerror(errno));
2586 exit(1);
2588 alarm(0);
2590 alarm(10);
2591 /* Wait for the parent to be ready. */
2592 if (read(read_fd, &c, 1) != 1) {
2593 printf("child: reply signal fail %s.\n",
2594 strerror(errno));
2595 exit(1);
2597 alarm(0);
2599 sleep(5);
2600 close(fd);
2601 printf("child: released lock 0:4 on file %s.\n",
2602 local_pathname );
2603 fflush(stdout);
2604 exit(0);
2607 static bool run_locktest9(int dummy)
2609 struct cli_state *cli1;
2610 const char *fname = "\\lockt9.lck";
2611 uint16_t fnum;
2612 bool correct = False;
2613 int pipe_in[2], pipe_out[2];
2614 pid_t child_pid;
2615 char c = '\0';
2616 int ret;
2617 struct timeval start;
2618 double seconds;
2619 NTSTATUS status;
2621 printf("starting locktest9\n");
2623 if (local_path == NULL) {
2624 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2625 return false;
2628 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2629 return false;
2632 child_pid = fork();
2633 if (child_pid == -1) {
2634 return false;
2637 if (child_pid == 0) {
2638 /* Child. */
2639 do_local_lock(pipe_out[0], pipe_in[1]);
2640 exit(0);
2643 close(pipe_out[0]);
2644 close(pipe_in[1]);
2645 pipe_out[0] = -1;
2646 pipe_in[1] = -1;
2648 /* Parent. */
2649 ret = read(pipe_in[0], &c, 1);
2650 if (ret != 1) {
2651 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2652 strerror(errno));
2653 return false;
2656 if (!torture_open_connection(&cli1, 0)) {
2657 return false;
2660 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2662 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE,
2663 &fnum);
2664 if (!NT_STATUS_IS_OK(status)) {
2665 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2666 return false;
2669 /* Ensure the child has the lock. */
2670 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2671 if (NT_STATUS_IS_OK(status)) {
2672 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2673 goto fail;
2674 } else {
2675 d_printf("Child has the lock.\n");
2678 /* Tell the child to wait 5 seconds then exit. */
2679 ret = write(pipe_out[1], &c, 1);
2680 if (ret != 1) {
2681 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2682 strerror(errno));
2683 goto fail;
2686 /* Wait 20 seconds for the lock. */
2687 alarm_cli = cli1;
2688 CatchSignal(SIGALRM, alarm_handler_parent);
2689 alarm(20);
2691 start = timeval_current();
2693 status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2694 if (!NT_STATUS_IS_OK(status)) {
2695 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2696 "%s\n", nt_errstr(status));
2697 goto fail_nofd;
2699 alarm(0);
2701 seconds = timeval_elapsed(&start);
2703 printf("Parent got the lock after %.2f seconds.\n",
2704 seconds);
2706 status = cli_close(cli1, fnum);
2707 if (!NT_STATUS_IS_OK(status)) {
2708 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2709 goto fail;
2712 correct = true;
2714 fail:
2715 cli_close(cli1, fnum);
2716 torture_close_connection(cli1);
2718 fail_nofd:
2720 printf("finished locktest9\n");
2721 return correct;
2725 test whether fnums and tids open on one VC are available on another (a major
2726 security hole)
2728 static bool run_fdpasstest(int dummy)
2730 struct cli_state *cli1, *cli2;
2731 const char *fname = "\\fdpass.tst";
2732 uint16_t fnum1;
2733 char buf[1024];
2734 NTSTATUS status;
2736 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2737 return False;
2739 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2740 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2742 printf("starting fdpasstest\n");
2744 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2746 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2747 &fnum1);
2748 if (!NT_STATUS_IS_OK(status)) {
2749 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2750 return False;
2753 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2754 13, NULL);
2755 if (!NT_STATUS_IS_OK(status)) {
2756 printf("write failed (%s)\n", nt_errstr(status));
2757 return False;
2760 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
2761 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2762 cli_setpid(cli2, cli_getpid(cli1));
2764 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
2765 printf("read succeeded! nasty security hole [%s]\n", buf);
2766 return false;
2769 cli_close(cli1, fnum1);
2770 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2772 torture_close_connection(cli1);
2773 torture_close_connection(cli2);
2775 printf("finished fdpasstest\n");
2776 return True;
2779 static bool run_fdsesstest(int dummy)
2781 struct cli_state *cli;
2782 uint16_t new_vuid;
2783 uint16_t saved_vuid;
2784 uint32_t new_cnum;
2785 uint32_t saved_cnum;
2786 const char *fname = "\\fdsess.tst";
2787 const char *fname1 = "\\fdsess1.tst";
2788 uint16_t fnum1;
2789 uint16_t fnum2;
2790 char buf[1024];
2791 bool ret = True;
2792 NTSTATUS status;
2794 if (!torture_open_connection(&cli, 0))
2795 return False;
2796 smbXcli_conn_set_sockopt(cli->conn, sockops);
2798 if (!torture_cli_session_setup2(cli, &new_vuid))
2799 return False;
2801 saved_cnum = cli_state_get_tid(cli);
2802 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
2803 return False;
2804 new_cnum = cli_state_get_tid(cli);
2805 cli_state_set_tid(cli, saved_cnum);
2807 printf("starting fdsesstest\n");
2809 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2810 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2812 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2813 if (!NT_STATUS_IS_OK(status)) {
2814 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2815 return False;
2818 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2819 NULL);
2820 if (!NT_STATUS_IS_OK(status)) {
2821 printf("write failed (%s)\n", nt_errstr(status));
2822 return False;
2825 saved_vuid = cli_state_get_uid(cli);
2826 cli_state_set_uid(cli, new_vuid);
2828 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2829 printf("read succeeded with different vuid! "
2830 "nasty security hole [%s]\n", buf);
2831 ret = false;
2833 /* Try to open a file with different vuid, samba cnum. */
2834 if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2835 printf("create with different vuid, same cnum succeeded.\n");
2836 cli_close(cli, fnum2);
2837 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2838 } else {
2839 printf("create with different vuid, same cnum failed.\n");
2840 printf("This will cause problems with service clients.\n");
2841 ret = False;
2844 cli_state_set_uid(cli, saved_vuid);
2846 /* Try with same vuid, different cnum. */
2847 cli_state_set_tid(cli, new_cnum);
2849 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2850 printf("read succeeded with different cnum![%s]\n", buf);
2851 ret = false;
2854 cli_state_set_tid(cli, saved_cnum);
2855 cli_close(cli, fnum1);
2856 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2858 torture_close_connection(cli);
2860 printf("finished fdsesstest\n");
2861 return ret;
2865 This test checks that
2867 1) the server does not allow an unlink on a file that is open
2869 static bool run_unlinktest(int dummy)
2871 struct cli_state *cli;
2872 const char *fname = "\\unlink.tst";
2873 uint16_t fnum;
2874 bool correct = True;
2875 NTSTATUS status;
2877 if (!torture_open_connection(&cli, 0)) {
2878 return False;
2881 smbXcli_conn_set_sockopt(cli->conn, sockops);
2883 printf("starting unlink test\n");
2885 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2887 cli_setpid(cli, 1);
2889 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2890 if (!NT_STATUS_IS_OK(status)) {
2891 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2892 return False;
2895 status = cli_unlink(cli, fname,
2896 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2897 if (NT_STATUS_IS_OK(status)) {
2898 printf("error: server allowed unlink on an open file\n");
2899 correct = False;
2900 } else {
2901 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
2902 NT_STATUS_SHARING_VIOLATION);
2905 cli_close(cli, fnum);
2906 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2908 if (!torture_close_connection(cli)) {
2909 correct = False;
2912 printf("unlink test finished\n");
2914 return correct;
2919 test how many open files this server supports on the one socket
2921 static bool run_maxfidtest(int dummy)
2923 struct cli_state *cli;
2924 fstring fname;
2925 uint16_t fnums[0x11000];
2926 int i;
2927 int retries=4;
2928 bool correct = True;
2929 NTSTATUS status;
2931 cli = current_cli;
2933 if (retries <= 0) {
2934 printf("failed to connect\n");
2935 return False;
2938 smbXcli_conn_set_sockopt(cli->conn, sockops);
2940 for (i=0; i<0x11000; i++) {
2941 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2942 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2943 &fnums[i]);
2944 if (!NT_STATUS_IS_OK(status)) {
2945 printf("open of %s failed (%s)\n",
2946 fname, nt_errstr(status));
2947 printf("maximum fnum is %d\n", i);
2948 break;
2950 printf("%6d\r", i);
2952 printf("%6d\n", i);
2953 i--;
2955 printf("cleaning up\n");
2956 for (;i>=0;i--) {
2957 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2958 cli_close(cli, fnums[i]);
2960 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2961 if (!NT_STATUS_IS_OK(status)) {
2962 printf("unlink of %s failed (%s)\n",
2963 fname, nt_errstr(status));
2964 correct = False;
2966 printf("%6d\r", i);
2968 printf("%6d\n", 0);
2970 printf("maxfid test finished\n");
2971 if (!torture_close_connection(cli)) {
2972 correct = False;
2974 return correct;
2977 /* generate a random buffer */
2978 static void rand_buf(char *buf, int len)
2980 while (len--) {
2981 *buf = (char)sys_random();
2982 buf++;
2986 /* send smb negprot commands, not reading the response */
2987 static bool run_negprot_nowait(int dummy)
2989 struct tevent_context *ev;
2990 int i;
2991 struct cli_state *cli;
2992 bool correct = True;
2994 printf("starting negprot nowait test\n");
2996 ev = samba_tevent_context_init(talloc_tos());
2997 if (ev == NULL) {
2998 return false;
3001 if (!(cli = open_nbt_connection())) {
3002 TALLOC_FREE(ev);
3003 return False;
3006 for (i=0;i<50000;i++) {
3007 struct tevent_req *req;
3009 req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
3010 PROTOCOL_CORE, PROTOCOL_NT1, 0);
3011 if (req == NULL) {
3012 TALLOC_FREE(ev);
3013 return false;
3015 if (!tevent_req_poll(req, ev)) {
3016 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3017 strerror(errno));
3018 TALLOC_FREE(ev);
3019 return false;
3021 TALLOC_FREE(req);
3024 if (torture_close_connection(cli)) {
3025 correct = False;
3028 printf("finished negprot nowait test\n");
3030 return correct;
3033 /* send smb negprot commands, not reading the response */
3034 static bool run_bad_nbt_session(int dummy)
3036 struct nmb_name called, calling;
3037 struct sockaddr_storage ss;
3038 NTSTATUS status;
3039 int fd;
3040 bool ret;
3042 printf("starting bad nbt session test\n");
3044 make_nmb_name(&calling, myname, 0x0);
3045 make_nmb_name(&called , host, 0x20);
3047 if (!resolve_name(host, &ss, 0x20, true)) {
3048 d_fprintf(stderr, "Could not resolve name %s\n", host);
3049 return false;
3052 status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3053 if (!NT_STATUS_IS_OK(status)) {
3054 d_fprintf(stderr, "open_socket_out failed: %s\n",
3055 nt_errstr(status));
3056 return false;
3059 ret = cli_bad_session_request(fd, &calling, &called);
3060 close(fd);
3061 if (!ret) {
3062 d_fprintf(stderr, "open_socket_out failed: %s\n",
3063 nt_errstr(status));
3064 return false;
3067 printf("finished bad nbt session test\n");
3068 return true;
3071 /* send random IPC commands */
3072 static bool run_randomipc(int dummy)
3074 char *rparam = NULL;
3075 char *rdata = NULL;
3076 unsigned int rdrcnt,rprcnt;
3077 char param[1024];
3078 int api, param_len, i;
3079 struct cli_state *cli;
3080 bool correct = True;
3081 int count = 50000;
3083 printf("starting random ipc test\n");
3085 if (!torture_open_connection(&cli, 0)) {
3086 return False;
3089 for (i=0;i<count;i++) {
3090 api = sys_random() % 500;
3091 param_len = (sys_random() % 64);
3093 rand_buf(param, param_len);
3095 SSVAL(param,0,api);
3097 cli_api(cli,
3098 param, param_len, 8,
3099 NULL, 0, CLI_BUFFER_SIZE,
3100 &rparam, &rprcnt,
3101 &rdata, &rdrcnt);
3102 if (i % 100 == 0) {
3103 printf("%d/%d\r", i,count);
3106 printf("%d/%d\n", i, count);
3108 if (!torture_close_connection(cli)) {
3109 correct = False;
3112 SAFE_FREE(rparam);
3113 SAFE_FREE(rdata);
3115 printf("finished random ipc test\n");
3117 return correct;
3122 static void browse_callback(const char *sname, uint32_t stype,
3123 const char *comment, void *state)
3125 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3131 This test checks the browse list code
3134 static bool run_browsetest(int dummy)
3136 static struct cli_state *cli;
3137 bool correct = True;
3139 printf("starting browse test\n");
3141 if (!torture_open_connection(&cli, 0)) {
3142 return False;
3145 printf("domain list:\n");
3146 cli_NetServerEnum(cli, cli->server_domain,
3147 SV_TYPE_DOMAIN_ENUM,
3148 browse_callback, NULL);
3150 printf("machine list:\n");
3151 cli_NetServerEnum(cli, cli->server_domain,
3152 SV_TYPE_ALL,
3153 browse_callback, NULL);
3155 if (!torture_close_connection(cli)) {
3156 correct = False;
3159 printf("browse test finished\n");
3161 return correct;
3167 This checks how the getatr calls works
3169 static bool run_attrtest(int dummy)
3171 struct cli_state *cli;
3172 uint16_t fnum;
3173 time_t t, t2;
3174 const char *fname = "\\attrib123456789.tst";
3175 bool correct = True;
3176 NTSTATUS status;
3178 printf("starting attrib test\n");
3180 if (!torture_open_connection(&cli, 0)) {
3181 return False;
3184 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3185 cli_openx(cli, fname,
3186 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3187 cli_close(cli, fnum);
3189 status = cli_getatr(cli, fname, NULL, NULL, &t);
3190 if (!NT_STATUS_IS_OK(status)) {
3191 printf("getatr failed (%s)\n", nt_errstr(status));
3192 correct = False;
3195 if (abs(t - time(NULL)) > 60*60*24*10) {
3196 printf("ERROR: SMBgetatr bug. time is %s",
3197 ctime(&t));
3198 t = time(NULL);
3199 correct = True;
3202 t2 = t-60*60*24; /* 1 day ago */
3204 status = cli_setatr(cli, fname, 0, t2);
3205 if (!NT_STATUS_IS_OK(status)) {
3206 printf("setatr failed (%s)\n", nt_errstr(status));
3207 correct = True;
3210 status = cli_getatr(cli, fname, NULL, NULL, &t);
3211 if (!NT_STATUS_IS_OK(status)) {
3212 printf("getatr failed (%s)\n", nt_errstr(status));
3213 correct = True;
3216 if (t != t2) {
3217 printf("ERROR: getatr/setatr bug. times are\n%s",
3218 ctime(&t));
3219 printf("%s", ctime(&t2));
3220 correct = True;
3223 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3225 if (!torture_close_connection(cli)) {
3226 correct = False;
3229 printf("attrib test finished\n");
3231 return correct;
3236 This checks a couple of trans2 calls
3238 static bool run_trans2test(int dummy)
3240 struct cli_state *cli;
3241 uint16_t fnum;
3242 off_t size;
3243 time_t c_time, a_time, m_time;
3244 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3245 const char *fname = "\\trans2.tst";
3246 const char *dname = "\\trans2";
3247 const char *fname2 = "\\trans2\\trans2.tst";
3248 char *pname;
3249 bool correct = True;
3250 NTSTATUS status;
3251 uint32_t fs_attr;
3253 printf("starting trans2 test\n");
3255 if (!torture_open_connection(&cli, 0)) {
3256 return False;
3259 status = cli_get_fs_attr_info(cli, &fs_attr);
3260 if (!NT_STATUS_IS_OK(status)) {
3261 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3262 nt_errstr(status));
3263 correct = false;
3266 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3267 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3268 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3269 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3270 if (!NT_STATUS_IS_OK(status)) {
3271 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3272 correct = False;
3275 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3276 if (!NT_STATUS_IS_OK(status)) {
3277 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3278 correct = False;
3280 else if (strcmp(pname, fname)) {
3281 printf("qfilename gave different name? [%s] [%s]\n",
3282 fname, pname);
3283 correct = False;
3286 cli_close(cli, fnum);
3288 sleep(2);
3290 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3291 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3292 &fnum);
3293 if (!NT_STATUS_IS_OK(status)) {
3294 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3295 return False;
3297 cli_close(cli, fnum);
3299 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3300 NULL);
3301 if (!NT_STATUS_IS_OK(status)) {
3302 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3303 correct = False;
3304 } else {
3305 time_t t = time(NULL);
3307 if (c_time != m_time) {
3308 printf("create time=%s", ctime(&c_time));
3309 printf("modify time=%s", ctime(&m_time));
3310 printf("This system appears to have sticky create times\n");
3312 if ((abs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
3313 printf("access time=%s", ctime(&a_time));
3314 printf("This system appears to set a midnight access time\n");
3315 correct = False;
3318 if (abs(m_time - t) > 60*60*24*7) {
3319 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3320 correct = False;
3325 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3326 cli_openx(cli, fname,
3327 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3328 cli_close(cli, fnum);
3329 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3330 &m_time_ts, &size, NULL, NULL);
3331 if (!NT_STATUS_IS_OK(status)) {
3332 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3333 correct = False;
3334 } else {
3335 if (w_time_ts.tv_sec < 60*60*24*2) {
3336 printf("write time=%s", ctime(&w_time_ts.tv_sec));
3337 printf("This system appears to set a initial 0 write time\n");
3338 correct = False;
3342 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3345 /* check if the server updates the directory modification time
3346 when creating a new file */
3347 status = cli_mkdir(cli, dname);
3348 if (!NT_STATUS_IS_OK(status)) {
3349 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3350 correct = False;
3352 sleep(3);
3353 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3354 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3355 if (!NT_STATUS_IS_OK(status)) {
3356 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3357 correct = False;
3360 cli_openx(cli, fname2,
3361 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3362 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3363 cli_close(cli, fnum);
3364 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3365 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3366 if (!NT_STATUS_IS_OK(status)) {
3367 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3368 correct = False;
3369 } else {
3370 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3371 == 0) {
3372 printf("This system does not update directory modification times\n");
3373 correct = False;
3376 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3377 cli_rmdir(cli, dname);
3379 if (!torture_close_connection(cli)) {
3380 correct = False;
3383 printf("trans2 test finished\n");
3385 return correct;
3389 This checks new W2K calls.
3392 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3394 uint8_t *buf = NULL;
3395 uint32_t len;
3396 NTSTATUS status;
3398 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3399 CLI_BUFFER_SIZE, NULL, &buf, &len);
3400 if (!NT_STATUS_IS_OK(status)) {
3401 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3402 nt_errstr(status));
3403 } else {
3404 printf("qfileinfo: level %d, len = %u\n", level, len);
3405 dump_data(0, (uint8_t *)buf, len);
3406 printf("\n");
3408 TALLOC_FREE(buf);
3409 return status;
3412 static bool run_w2ktest(int dummy)
3414 struct cli_state *cli;
3415 uint16_t fnum;
3416 const char *fname = "\\w2ktest\\w2k.tst";
3417 int level;
3418 bool correct = True;
3420 printf("starting w2k test\n");
3422 if (!torture_open_connection(&cli, 0)) {
3423 return False;
3426 cli_openx(cli, fname,
3427 O_RDWR | O_CREAT , DENY_NONE, &fnum);
3429 for (level = 1004; level < 1040; level++) {
3430 new_trans(cli, fnum, level);
3433 cli_close(cli, fnum);
3435 if (!torture_close_connection(cli)) {
3436 correct = False;
3439 printf("w2k test finished\n");
3441 return correct;
3446 this is a harness for some oplock tests
3448 static bool run_oplock1(int dummy)
3450 struct cli_state *cli1;
3451 const char *fname = "\\lockt1.lck";
3452 uint16_t fnum1;
3453 bool correct = True;
3454 NTSTATUS status;
3456 printf("starting oplock test 1\n");
3458 if (!torture_open_connection(&cli1, 0)) {
3459 return False;
3462 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3464 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3466 cli1->use_oplocks = True;
3468 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3469 &fnum1);
3470 if (!NT_STATUS_IS_OK(status)) {
3471 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3472 return False;
3475 cli1->use_oplocks = False;
3477 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3478 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3480 status = cli_close(cli1, fnum1);
3481 if (!NT_STATUS_IS_OK(status)) {
3482 printf("close2 failed (%s)\n", nt_errstr(status));
3483 return False;
3486 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3487 if (!NT_STATUS_IS_OK(status)) {
3488 printf("unlink failed (%s)\n", nt_errstr(status));
3489 return False;
3492 if (!torture_close_connection(cli1)) {
3493 correct = False;
3496 printf("finished oplock test 1\n");
3498 return correct;
3501 static bool run_oplock2(int dummy)
3503 struct cli_state *cli1, *cli2;
3504 const char *fname = "\\lockt2.lck";
3505 uint16_t fnum1, fnum2;
3506 int saved_use_oplocks = use_oplocks;
3507 char buf[4];
3508 bool correct = True;
3509 volatile bool *shared_correct;
3510 size_t nread;
3511 NTSTATUS status;
3513 shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
3514 *shared_correct = True;
3516 use_level_II_oplocks = True;
3517 use_oplocks = True;
3519 printf("starting oplock test 2\n");
3521 if (!torture_open_connection(&cli1, 0)) {
3522 use_level_II_oplocks = False;
3523 use_oplocks = saved_use_oplocks;
3524 return False;
3527 if (!torture_open_connection(&cli2, 1)) {
3528 use_level_II_oplocks = False;
3529 use_oplocks = saved_use_oplocks;
3530 return False;
3533 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3535 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3536 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3538 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3539 &fnum1);
3540 if (!NT_STATUS_IS_OK(status)) {
3541 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3542 return False;
3545 /* Don't need the globals any more. */
3546 use_level_II_oplocks = False;
3547 use_oplocks = saved_use_oplocks;
3549 if (fork() == 0) {
3550 /* Child code */
3551 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3552 if (!NT_STATUS_IS_OK(status)) {
3553 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3554 *shared_correct = False;
3555 exit(0);
3558 sleep(2);
3560 status = cli_close(cli2, fnum2);
3561 if (!NT_STATUS_IS_OK(status)) {
3562 printf("close2 failed (%s)\n", nt_errstr(status));
3563 *shared_correct = False;
3566 exit(0);
3569 sleep(2);
3571 /* Ensure cli1 processes the break. Empty file should always return 0
3572 * bytes. */
3573 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
3574 if (!NT_STATUS_IS_OK(status)) {
3575 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
3576 correct = false;
3577 } else if (nread != 0) {
3578 printf("read on empty fnum1 failed. recv %ld expected %d\n",
3579 (unsigned long)nread, 0);
3580 correct = false;
3583 /* Should now be at level II. */
3584 /* Test if sending a write locks causes a break to none. */
3585 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3586 if (!NT_STATUS_IS_OK(status)) {
3587 printf("lock failed (%s)\n", nt_errstr(status));
3588 correct = False;
3591 cli_unlock(cli1, fnum1, 0, 4);
3593 sleep(2);
3595 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3596 if (!NT_STATUS_IS_OK(status)) {
3597 printf("lock failed (%s)\n", nt_errstr(status));
3598 correct = False;
3601 cli_unlock(cli1, fnum1, 0, 4);
3603 sleep(2);
3605 cli_read(cli1, fnum1, buf, 0, 4, NULL);
3607 status = cli_close(cli1, fnum1);
3608 if (!NT_STATUS_IS_OK(status)) {
3609 printf("close1 failed (%s)\n", nt_errstr(status));
3610 correct = False;
3613 sleep(4);
3615 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3616 if (!NT_STATUS_IS_OK(status)) {
3617 printf("unlink failed (%s)\n", nt_errstr(status));
3618 correct = False;
3621 if (!torture_close_connection(cli1)) {
3622 correct = False;
3625 if (!*shared_correct) {
3626 correct = False;
3629 printf("finished oplock test 2\n");
3631 return correct;
3634 struct oplock4_state {
3635 struct tevent_context *ev;
3636 struct cli_state *cli;
3637 bool *got_break;
3638 uint16_t *fnum2;
3641 static void oplock4_got_break(struct tevent_req *req);
3642 static void oplock4_got_open(struct tevent_req *req);
3644 static bool run_oplock4(int dummy)
3646 struct tevent_context *ev;
3647 struct cli_state *cli1, *cli2;
3648 struct tevent_req *oplock_req, *open_req;
3649 const char *fname = "\\lockt4.lck";
3650 const char *fname_ln = "\\lockt4_ln.lck";
3651 uint16_t fnum1, fnum2;
3652 int saved_use_oplocks = use_oplocks;
3653 NTSTATUS status;
3654 bool correct = true;
3656 bool got_break;
3658 struct oplock4_state *state;
3660 printf("starting oplock test 4\n");
3662 if (!torture_open_connection(&cli1, 0)) {
3663 use_level_II_oplocks = false;
3664 use_oplocks = saved_use_oplocks;
3665 return false;
3668 if (!torture_open_connection(&cli2, 1)) {
3669 use_level_II_oplocks = false;
3670 use_oplocks = saved_use_oplocks;
3671 return false;
3674 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3675 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3677 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3678 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3680 /* Create the file. */
3681 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3682 &fnum1);
3683 if (!NT_STATUS_IS_OK(status)) {
3684 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3685 return false;
3688 status = cli_close(cli1, fnum1);
3689 if (!NT_STATUS_IS_OK(status)) {
3690 printf("close1 failed (%s)\n", nt_errstr(status));
3691 return false;
3694 /* Now create a hardlink. */
3695 status = cli_nt_hardlink(cli1, fname, fname_ln);
3696 if (!NT_STATUS_IS_OK(status)) {
3697 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3698 return false;
3701 /* Prove that opening hardlinks cause deny modes to conflict. */
3702 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3703 if (!NT_STATUS_IS_OK(status)) {
3704 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3705 return false;
3708 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3709 if (NT_STATUS_IS_OK(status)) {
3710 printf("open of %s succeeded - should fail with sharing violation.\n",
3711 fname_ln);
3712 return false;
3715 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3716 printf("open of %s should fail with sharing violation. Got %s\n",
3717 fname_ln, nt_errstr(status));
3718 return false;
3721 status = cli_close(cli1, fnum1);
3722 if (!NT_STATUS_IS_OK(status)) {
3723 printf("close1 failed (%s)\n", nt_errstr(status));
3724 return false;
3727 cli1->use_oplocks = true;
3728 cli2->use_oplocks = true;
3730 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3731 if (!NT_STATUS_IS_OK(status)) {
3732 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3733 return false;
3736 ev = samba_tevent_context_init(talloc_tos());
3737 if (ev == NULL) {
3738 printf("tevent_context_init failed\n");
3739 return false;
3742 state = talloc(ev, struct oplock4_state);
3743 if (state == NULL) {
3744 printf("talloc failed\n");
3745 return false;
3747 state->ev = ev;
3748 state->cli = cli1;
3749 state->got_break = &got_break;
3750 state->fnum2 = &fnum2;
3752 oplock_req = cli_smb_oplock_break_waiter_send(
3753 talloc_tos(), ev, cli1);
3754 if (oplock_req == NULL) {
3755 printf("cli_smb_oplock_break_waiter_send failed\n");
3756 return false;
3758 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3760 open_req = cli_openx_send(
3761 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3762 if (open_req == NULL) {
3763 printf("cli_openx_send failed\n");
3764 return false;
3766 tevent_req_set_callback(open_req, oplock4_got_open, state);
3768 got_break = false;
3769 fnum2 = 0xffff;
3771 while (!got_break || fnum2 == 0xffff) {
3772 int ret;
3773 ret = tevent_loop_once(ev);
3774 if (ret == -1) {
3775 printf("tevent_loop_once failed: %s\n",
3776 strerror(errno));
3777 return false;
3781 status = cli_close(cli2, fnum2);
3782 if (!NT_STATUS_IS_OK(status)) {
3783 printf("close2 failed (%s)\n", nt_errstr(status));
3784 correct = false;
3787 status = cli_close(cli1, fnum1);
3788 if (!NT_STATUS_IS_OK(status)) {
3789 printf("close1 failed (%s)\n", nt_errstr(status));
3790 correct = false;
3793 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3794 if (!NT_STATUS_IS_OK(status)) {
3795 printf("unlink failed (%s)\n", nt_errstr(status));
3796 correct = false;
3799 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3800 if (!NT_STATUS_IS_OK(status)) {
3801 printf("unlink failed (%s)\n", nt_errstr(status));
3802 correct = false;
3805 if (!torture_close_connection(cli1)) {
3806 correct = false;
3809 if (!got_break) {
3810 correct = false;
3813 printf("finished oplock test 4\n");
3815 return correct;
3818 static void oplock4_got_break(struct tevent_req *req)
3820 struct oplock4_state *state = tevent_req_callback_data(
3821 req, struct oplock4_state);
3822 uint16_t fnum;
3823 uint8_t level;
3824 NTSTATUS status;
3826 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3827 TALLOC_FREE(req);
3828 if (!NT_STATUS_IS_OK(status)) {
3829 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3830 nt_errstr(status));
3831 return;
3833 *state->got_break = true;
3835 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3836 NO_OPLOCK);
3837 if (req == NULL) {
3838 printf("cli_oplock_ack_send failed\n");
3839 return;
3843 static void oplock4_got_open(struct tevent_req *req)
3845 struct oplock4_state *state = tevent_req_callback_data(
3846 req, struct oplock4_state);
3847 NTSTATUS status;
3849 status = cli_openx_recv(req, state->fnum2);
3850 if (!NT_STATUS_IS_OK(status)) {
3851 printf("cli_openx_recv returned %s\n", nt_errstr(status));
3852 *state->fnum2 = 0xffff;
3857 Test delete on close semantics.
3859 static bool run_deletetest(int dummy)
3861 struct cli_state *cli1 = NULL;
3862 struct cli_state *cli2 = NULL;
3863 const char *fname = "\\delete.file";
3864 uint16_t fnum1 = (uint16_t)-1;
3865 uint16_t fnum2 = (uint16_t)-1;
3866 bool correct = false;
3867 NTSTATUS status;
3869 printf("starting delete test\n");
3871 if (!torture_open_connection(&cli1, 0)) {
3872 return False;
3875 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3877 /* Test 1 - this should delete the file on close. */
3879 cli_setatr(cli1, fname, 0, 0);
3880 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3882 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3883 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3884 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
3885 if (!NT_STATUS_IS_OK(status)) {
3886 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3887 goto fail;
3890 status = cli_close(cli1, fnum1);
3891 if (!NT_STATUS_IS_OK(status)) {
3892 printf("[1] close failed (%s)\n", nt_errstr(status));
3893 goto fail;
3896 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3897 if (NT_STATUS_IS_OK(status)) {
3898 printf("[1] open of %s succeeded (should fail)\n", fname);
3899 goto fail;
3902 printf("first delete on close test succeeded.\n");
3904 /* Test 2 - this should delete the file on close. */
3906 cli_setatr(cli1, fname, 0, 0);
3907 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3909 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3910 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3911 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
3912 if (!NT_STATUS_IS_OK(status)) {
3913 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3914 goto fail;
3917 status = cli_nt_delete_on_close(cli1, fnum1, true);
3918 if (!NT_STATUS_IS_OK(status)) {
3919 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3920 goto fail;
3923 status = cli_close(cli1, fnum1);
3924 if (!NT_STATUS_IS_OK(status)) {
3925 printf("[2] close failed (%s)\n", nt_errstr(status));
3926 goto fail;
3929 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
3930 if (NT_STATUS_IS_OK(status)) {
3931 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3932 status = cli_close(cli1, fnum1);
3933 if (!NT_STATUS_IS_OK(status)) {
3934 printf("[2] close failed (%s)\n", nt_errstr(status));
3936 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3937 goto fail;
3940 printf("second delete on close test succeeded.\n");
3942 /* Test 3 - ... */
3943 cli_setatr(cli1, fname, 0, 0);
3944 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3946 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3947 FILE_ATTRIBUTE_NORMAL,
3948 FILE_SHARE_READ|FILE_SHARE_WRITE,
3949 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
3950 if (!NT_STATUS_IS_OK(status)) {
3951 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
3952 goto fail;
3955 /* This should fail with a sharing violation - open for delete is only compatible
3956 with SHARE_DELETE. */
3958 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3959 FILE_ATTRIBUTE_NORMAL,
3960 FILE_SHARE_READ|FILE_SHARE_WRITE,
3961 FILE_OPEN, 0, 0, &fnum2, NULL);
3962 if (NT_STATUS_IS_OK(status)) {
3963 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
3964 goto fail;
3967 /* This should succeed. */
3968 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3969 FILE_ATTRIBUTE_NORMAL,
3970 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3971 FILE_OPEN, 0, 0, &fnum2, NULL);
3972 if (!NT_STATUS_IS_OK(status)) {
3973 printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
3974 goto fail;
3977 status = cli_nt_delete_on_close(cli1, fnum1, true);
3978 if (!NT_STATUS_IS_OK(status)) {
3979 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
3980 goto fail;
3983 status = cli_close(cli1, fnum1);
3984 if (!NT_STATUS_IS_OK(status)) {
3985 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
3986 goto fail;
3989 status = cli_close(cli1, fnum2);
3990 if (!NT_STATUS_IS_OK(status)) {
3991 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
3992 goto fail;
3995 /* This should fail - file should no longer be there. */
3997 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
3998 if (NT_STATUS_IS_OK(status)) {
3999 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
4000 status = cli_close(cli1, fnum1);
4001 if (!NT_STATUS_IS_OK(status)) {
4002 printf("[3] close failed (%s)\n", nt_errstr(status));
4004 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4005 goto fail;
4008 printf("third delete on close test succeeded.\n");
4010 /* Test 4 ... */
4011 cli_setatr(cli1, fname, 0, 0);
4012 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4014 status = cli_ntcreate(cli1, fname, 0,
4015 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4016 FILE_ATTRIBUTE_NORMAL,
4017 FILE_SHARE_READ|FILE_SHARE_WRITE,
4018 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4019 if (!NT_STATUS_IS_OK(status)) {
4020 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4021 goto fail;
4024 /* This should succeed. */
4025 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4026 FILE_ATTRIBUTE_NORMAL,
4027 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4028 FILE_OPEN, 0, 0, &fnum2, NULL);
4029 if (!NT_STATUS_IS_OK(status)) {
4030 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4031 goto fail;
4034 status = cli_close(cli1, fnum2);
4035 if (!NT_STATUS_IS_OK(status)) {
4036 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4037 goto fail;
4040 status = cli_nt_delete_on_close(cli1, fnum1, true);
4041 if (!NT_STATUS_IS_OK(status)) {
4042 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4043 goto fail;
4046 /* This should fail - no more opens once delete on close set. */
4047 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4048 FILE_ATTRIBUTE_NORMAL,
4049 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4050 FILE_OPEN, 0, 0, &fnum2, NULL);
4051 if (NT_STATUS_IS_OK(status)) {
4052 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
4053 goto fail;
4056 status = cli_close(cli1, fnum1);
4057 if (!NT_STATUS_IS_OK(status)) {
4058 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4059 goto fail;
4062 printf("fourth delete on close test succeeded.\n");
4064 /* Test 5 ... */
4065 cli_setatr(cli1, fname, 0, 0);
4066 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4068 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4069 if (!NT_STATUS_IS_OK(status)) {
4070 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4071 goto fail;
4074 /* This should fail - only allowed on NT opens with DELETE access. */
4076 status = cli_nt_delete_on_close(cli1, fnum1, true);
4077 if (NT_STATUS_IS_OK(status)) {
4078 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4079 goto fail;
4082 status = cli_close(cli1, fnum1);
4083 if (!NT_STATUS_IS_OK(status)) {
4084 printf("[5] close failed (%s)\n", nt_errstr(status));
4085 goto fail;
4088 printf("fifth delete on close test succeeded.\n");
4090 /* Test 6 ... */
4091 cli_setatr(cli1, fname, 0, 0);
4092 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4094 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4095 FILE_ATTRIBUTE_NORMAL,
4096 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4097 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4098 if (!NT_STATUS_IS_OK(status)) {
4099 printf("[6] open of %s failed (%s)\n", fname,
4100 nt_errstr(status));
4101 goto fail;
4104 /* This should fail - only allowed on NT opens with DELETE access. */
4106 status = cli_nt_delete_on_close(cli1, fnum1, true);
4107 if (NT_STATUS_IS_OK(status)) {
4108 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4109 goto fail;
4112 status = cli_close(cli1, fnum1);
4113 if (!NT_STATUS_IS_OK(status)) {
4114 printf("[6] close failed (%s)\n", nt_errstr(status));
4115 goto fail;
4118 printf("sixth delete on close test succeeded.\n");
4120 /* Test 7 ... */
4121 cli_setatr(cli1, fname, 0, 0);
4122 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4124 status = cli_ntcreate(cli1, fname, 0,
4125 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4126 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4127 0, 0, &fnum1, NULL);
4128 if (!NT_STATUS_IS_OK(status)) {
4129 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4130 goto fail;
4133 status = cli_nt_delete_on_close(cli1, fnum1, true);
4134 if (!NT_STATUS_IS_OK(status)) {
4135 printf("[7] setting delete_on_close on file failed !\n");
4136 goto fail;
4139 status = cli_nt_delete_on_close(cli1, fnum1, false);
4140 if (!NT_STATUS_IS_OK(status)) {
4141 printf("[7] unsetting delete_on_close on file failed !\n");
4142 goto fail;
4145 status = cli_close(cli1, fnum1);
4146 if (!NT_STATUS_IS_OK(status)) {
4147 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
4148 goto fail;
4151 /* This next open should succeed - we reset the flag. */
4152 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4153 if (!NT_STATUS_IS_OK(status)) {
4154 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4155 goto fail;
4158 status = cli_close(cli1, fnum1);
4159 if (!NT_STATUS_IS_OK(status)) {
4160 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4161 goto fail;
4164 printf("seventh delete on close test succeeded.\n");
4166 /* Test 8 ... */
4167 cli_setatr(cli1, fname, 0, 0);
4168 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4170 if (!torture_open_connection(&cli2, 1)) {
4171 printf("[8] failed to open second connection.\n");
4172 goto fail;
4175 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4177 status = cli_ntcreate(cli1, fname, 0,
4178 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4179 FILE_ATTRIBUTE_NORMAL,
4180 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4181 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4182 if (!NT_STATUS_IS_OK(status)) {
4183 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4184 goto fail;
4187 status = cli_ntcreate(cli2, fname, 0,
4188 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4189 FILE_ATTRIBUTE_NORMAL,
4190 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4191 FILE_OPEN, 0, 0, &fnum2, NULL);
4192 if (!NT_STATUS_IS_OK(status)) {
4193 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4194 goto fail;
4197 status = cli_nt_delete_on_close(cli1, fnum1, true);
4198 if (!NT_STATUS_IS_OK(status)) {
4199 printf("[8] setting delete_on_close on file failed !\n");
4200 goto fail;
4203 status = cli_close(cli1, fnum1);
4204 if (!NT_STATUS_IS_OK(status)) {
4205 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4206 goto fail;
4209 status = cli_close(cli2, fnum2);
4210 if (!NT_STATUS_IS_OK(status)) {
4211 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4212 goto fail;
4215 /* This should fail.. */
4216 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4217 if (NT_STATUS_IS_OK(status)) {
4218 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4219 goto fail;
4222 printf("eighth delete on close test succeeded.\n");
4224 /* Test 9 ... */
4226 /* This should fail - we need to set DELETE_ACCESS. */
4227 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4228 FILE_ATTRIBUTE_NORMAL,
4229 FILE_SHARE_NONE,
4230 FILE_OVERWRITE_IF,
4231 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4232 if (NT_STATUS_IS_OK(status)) {
4233 printf("[9] open of %s succeeded should have failed!\n", fname);
4234 goto fail;
4237 printf("ninth delete on close test succeeded.\n");
4239 /* Test 10 ... */
4241 status = cli_ntcreate(cli1, fname, 0,
4242 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4243 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4244 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4245 0, &fnum1, NULL);
4246 if (!NT_STATUS_IS_OK(status)) {
4247 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4248 goto fail;
4251 /* This should delete the file. */
4252 status = cli_close(cli1, fnum1);
4253 if (!NT_STATUS_IS_OK(status)) {
4254 printf("[10] close failed (%s)\n", nt_errstr(status));
4255 goto fail;
4258 /* This should fail.. */
4259 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4260 if (NT_STATUS_IS_OK(status)) {
4261 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4262 goto fail;
4265 printf("tenth delete on close test succeeded.\n");
4267 /* Test 11 ... */
4269 cli_setatr(cli1, fname, 0, 0);
4270 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4272 /* Can we open a read-only file with delete access? */
4274 /* Create a readonly file. */
4275 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4276 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4277 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4278 if (!NT_STATUS_IS_OK(status)) {
4279 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4280 goto fail;
4283 status = cli_close(cli1, fnum1);
4284 if (!NT_STATUS_IS_OK(status)) {
4285 printf("[11] close failed (%s)\n", nt_errstr(status));
4286 goto fail;
4289 /* Now try open for delete access. */
4290 status = cli_ntcreate(cli1, fname, 0,
4291 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4293 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4294 FILE_OPEN, 0, 0, &fnum1, NULL);
4295 if (!NT_STATUS_IS_OK(status)) {
4296 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
4297 goto fail;
4300 cli_close(cli1, fnum1);
4302 printf("eleventh delete on close test succeeded.\n");
4305 * Test 12
4306 * like test 4 but with initial delete on close
4309 cli_setatr(cli1, fname, 0, 0);
4310 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4312 status = cli_ntcreate(cli1, fname, 0,
4313 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4314 FILE_ATTRIBUTE_NORMAL,
4315 FILE_SHARE_READ|FILE_SHARE_WRITE,
4316 FILE_OVERWRITE_IF,
4317 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4318 if (!NT_STATUS_IS_OK(status)) {
4319 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4320 goto fail;
4323 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4324 FILE_ATTRIBUTE_NORMAL,
4325 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4326 FILE_OPEN, 0, 0, &fnum2, NULL);
4327 if (!NT_STATUS_IS_OK(status)) {
4328 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
4329 goto fail;
4332 status = cli_close(cli1, fnum2);
4333 if (!NT_STATUS_IS_OK(status)) {
4334 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
4335 goto fail;
4338 status = cli_nt_delete_on_close(cli1, fnum1, true);
4339 if (!NT_STATUS_IS_OK(status)) {
4340 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
4341 goto fail;
4344 /* This should fail - no more opens once delete on close set. */
4345 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4346 FILE_ATTRIBUTE_NORMAL,
4347 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4348 FILE_OPEN, 0, 0, &fnum2, NULL);
4349 if (NT_STATUS_IS_OK(status)) {
4350 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
4351 goto fail;
4354 status = cli_nt_delete_on_close(cli1, fnum1, false);
4355 if (!NT_STATUS_IS_OK(status)) {
4356 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
4357 goto fail;
4360 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4361 FILE_ATTRIBUTE_NORMAL,
4362 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4363 FILE_OPEN, 0, 0, &fnum2, NULL);
4364 if (!NT_STATUS_IS_OK(status)) {
4365 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
4366 goto fail;
4369 status = cli_close(cli1, fnum2);
4370 if (!NT_STATUS_IS_OK(status)) {
4371 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
4372 goto fail;
4375 status = cli_close(cli1, fnum1);
4376 if (!NT_STATUS_IS_OK(status)) {
4377 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
4378 goto fail;
4382 * setting delete on close on the handle does
4383 * not unset the initial delete on close...
4385 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4386 FILE_ATTRIBUTE_NORMAL,
4387 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4388 FILE_OPEN, 0, 0, &fnum2, NULL);
4389 if (NT_STATUS_IS_OK(status)) {
4390 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
4391 goto fail;
4392 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4393 printf("ntcreate returned %s, expected "
4394 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
4395 nt_errstr(status));
4396 goto fail;
4399 printf("twelfth delete on close test succeeded.\n");
4402 printf("finished delete test\n");
4404 correct = true;
4406 fail:
4407 /* FIXME: This will crash if we aborted before cli2 got
4408 * intialized, because these functions don't handle
4409 * uninitialized connections. */
4411 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4412 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4413 cli_setatr(cli1, fname, 0, 0);
4414 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4416 if (cli1 && !torture_close_connection(cli1)) {
4417 correct = False;
4419 if (cli2 && !torture_close_connection(cli2)) {
4420 correct = False;
4422 return correct;
4427 Test wildcard delete.
4429 static bool run_wild_deletetest(int dummy)
4431 struct cli_state *cli = NULL;
4432 const char *dname = "\\WTEST";
4433 const char *fname = "\\WTEST\\A";
4434 const char *wunlink_name = "\\WTEST\\*";
4435 uint16_t fnum1 = (uint16_t)-1;
4436 bool correct = false;
4437 NTSTATUS status;
4439 printf("starting wildcard delete test\n");
4441 if (!torture_open_connection(&cli, 0)) {
4442 return false;
4445 smbXcli_conn_set_sockopt(cli->conn, sockops);
4447 cli_unlink(cli, fname, 0);
4448 cli_rmdir(cli, dname);
4449 status = cli_mkdir(cli, dname);
4450 if (!NT_STATUS_IS_OK(status)) {
4451 printf("mkdir of %s failed %s!\n", dname, nt_errstr(status));
4452 goto fail;
4454 status = cli_openx(cli, fname, O_CREAT|O_RDONLY, DENY_NONE, &fnum1);
4455 if (!NT_STATUS_IS_OK(status)) {
4456 printf("open of %s failed %s!\n", fname, nt_errstr(status));
4457 goto fail;
4459 status = cli_close(cli, fnum1);
4460 fnum1 = -1;
4463 * Note the unlink attribute-type of zero. This should
4464 * map into FILE_ATTRIBUTE_NORMAL at the server even
4465 * on a wildcard delete.
4468 status = cli_unlink(cli, wunlink_name, 0);
4469 if (!NT_STATUS_IS_OK(status)) {
4470 printf("unlink of %s failed %s!\n",
4471 wunlink_name, nt_errstr(status));
4472 goto fail;
4475 printf("finished wildcard delete test\n");
4477 correct = true;
4479 fail:
4481 if (fnum1 != (uint16_t)-1) cli_close(cli, fnum1);
4482 cli_unlink(cli, fname, 0);
4483 cli_rmdir(cli, dname);
4485 if (cli && !torture_close_connection(cli)) {
4486 correct = false;
4488 return correct;
4491 static bool run_deletetest_ln(int dummy)
4493 struct cli_state *cli;
4494 const char *fname = "\\delete1";
4495 const char *fname_ln = "\\delete1_ln";
4496 uint16_t fnum;
4497 uint16_t fnum1;
4498 NTSTATUS status;
4499 bool correct = true;
4500 time_t t;
4502 printf("starting deletetest-ln\n");
4504 if (!torture_open_connection(&cli, 0)) {
4505 return false;
4508 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4509 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4511 smbXcli_conn_set_sockopt(cli->conn, sockops);
4513 /* Create the file. */
4514 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4515 if (!NT_STATUS_IS_OK(status)) {
4516 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4517 return false;
4520 status = cli_close(cli, fnum);
4521 if (!NT_STATUS_IS_OK(status)) {
4522 printf("close1 failed (%s)\n", nt_errstr(status));
4523 return false;
4526 /* Now create a hardlink. */
4527 status = cli_nt_hardlink(cli, fname, fname_ln);
4528 if (!NT_STATUS_IS_OK(status)) {
4529 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4530 return false;
4533 /* Open the original file. */
4534 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4535 FILE_ATTRIBUTE_NORMAL,
4536 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4537 FILE_OPEN_IF, 0, 0, &fnum, NULL);
4538 if (!NT_STATUS_IS_OK(status)) {
4539 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4540 return false;
4543 /* Unlink the hard link path. */
4544 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4545 FILE_ATTRIBUTE_NORMAL,
4546 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4547 FILE_OPEN_IF, 0, 0, &fnum1, NULL);
4548 if (!NT_STATUS_IS_OK(status)) {
4549 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4550 return false;
4552 status = cli_nt_delete_on_close(cli, fnum1, true);
4553 if (!NT_STATUS_IS_OK(status)) {
4554 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4555 __location__, fname_ln, nt_errstr(status));
4556 return false;
4559 status = cli_close(cli, fnum1);
4560 if (!NT_STATUS_IS_OK(status)) {
4561 printf("close %s failed (%s)\n",
4562 fname_ln, nt_errstr(status));
4563 return false;
4566 status = cli_close(cli, fnum);
4567 if (!NT_STATUS_IS_OK(status)) {
4568 printf("close %s failed (%s)\n",
4569 fname, nt_errstr(status));
4570 return false;
4573 /* Ensure the original file is still there. */
4574 status = cli_getatr(cli, fname, NULL, NULL, &t);
4575 if (!NT_STATUS_IS_OK(status)) {
4576 printf("%s getatr on file %s failed (%s)\n",
4577 __location__,
4578 fname,
4579 nt_errstr(status));
4580 correct = False;
4583 /* Ensure the link path is gone. */
4584 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4585 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4586 printf("%s, getatr for file %s returned wrong error code %s "
4587 "- should have been deleted\n",
4588 __location__,
4589 fname_ln, nt_errstr(status));
4590 correct = False;
4593 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4594 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4596 if (!torture_close_connection(cli)) {
4597 correct = false;
4600 printf("finished deletetest-ln\n");
4602 return correct;
4606 print out server properties
4608 static bool run_properties(int dummy)
4610 struct cli_state *cli;
4611 bool correct = True;
4613 printf("starting properties test\n");
4615 ZERO_STRUCT(cli);
4617 if (!torture_open_connection(&cli, 0)) {
4618 return False;
4621 smbXcli_conn_set_sockopt(cli->conn, sockops);
4623 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
4625 if (!torture_close_connection(cli)) {
4626 correct = False;
4629 return correct;
4634 /* FIRST_DESIRED_ACCESS 0xf019f */
4635 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4636 FILE_READ_EA| /* 0xf */ \
4637 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
4638 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
4639 DELETE_ACCESS|READ_CONTROL_ACCESS|\
4640 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
4641 /* SECOND_DESIRED_ACCESS 0xe0080 */
4642 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4643 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4644 WRITE_OWNER_ACCESS /* 0xe0000 */
4646 #if 0
4647 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4648 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4649 FILE_READ_DATA|\
4650 WRITE_OWNER_ACCESS /* */
4651 #endif
4654 Test ntcreate calls made by xcopy
4656 static bool run_xcopy(int dummy)
4658 static struct cli_state *cli1;
4659 const char *fname = "\\test.txt";
4660 bool correct = True;
4661 uint16_t fnum1, fnum2;
4662 NTSTATUS status;
4664 printf("starting xcopy test\n");
4666 if (!torture_open_connection(&cli1, 0)) {
4667 return False;
4670 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4671 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4672 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
4673 if (!NT_STATUS_IS_OK(status)) {
4674 printf("First open failed - %s\n", nt_errstr(status));
4675 return False;
4678 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4679 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4680 FILE_OPEN, 0x200000, 0, &fnum2, NULL);
4681 if (!NT_STATUS_IS_OK(status)) {
4682 printf("second open failed - %s\n", nt_errstr(status));
4683 return False;
4686 if (!torture_close_connection(cli1)) {
4687 correct = False;
4690 return correct;
4694 Test rename on files open with share delete and no share delete.
4696 static bool run_rename(int dummy)
4698 static struct cli_state *cli1;
4699 const char *fname = "\\test.txt";
4700 const char *fname1 = "\\test1.txt";
4701 bool correct = True;
4702 uint16_t fnum1;
4703 uint16_t attr;
4704 NTSTATUS status;
4706 printf("starting rename test\n");
4708 if (!torture_open_connection(&cli1, 0)) {
4709 return False;
4712 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4713 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4715 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4716 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4717 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4718 if (!NT_STATUS_IS_OK(status)) {
4719 printf("First open failed - %s\n", nt_errstr(status));
4720 return False;
4723 status = cli_rename(cli1, fname, fname1, false);
4724 if (!NT_STATUS_IS_OK(status)) {
4725 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4726 } else {
4727 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4728 correct = False;
4731 status = cli_close(cli1, fnum1);
4732 if (!NT_STATUS_IS_OK(status)) {
4733 printf("close - 1 failed (%s)\n", nt_errstr(status));
4734 return False;
4737 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4738 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4739 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4740 #if 0
4741 FILE_SHARE_DELETE|FILE_SHARE_NONE,
4742 #else
4743 FILE_SHARE_DELETE|FILE_SHARE_READ,
4744 #endif
4745 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4746 if (!NT_STATUS_IS_OK(status)) {
4747 printf("Second open failed - %s\n", nt_errstr(status));
4748 return False;
4751 status = cli_rename(cli1, fname, fname1, false);
4752 if (!NT_STATUS_IS_OK(status)) {
4753 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4754 correct = False;
4755 } else {
4756 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4759 status = cli_close(cli1, fnum1);
4760 if (!NT_STATUS_IS_OK(status)) {
4761 printf("close - 2 failed (%s)\n", nt_errstr(status));
4762 return False;
4765 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4766 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4768 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4769 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4770 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4771 if (!NT_STATUS_IS_OK(status)) {
4772 printf("Third open failed - %s\n", nt_errstr(status));
4773 return False;
4777 #if 0
4779 uint16_t fnum2;
4781 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4782 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
4783 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4784 return False;
4786 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4787 printf("[8] setting delete_on_close on file failed !\n");
4788 return False;
4791 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4792 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4793 return False;
4796 #endif
4798 status = cli_rename(cli1, fname, fname1, false);
4799 if (!NT_STATUS_IS_OK(status)) {
4800 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4801 correct = False;
4802 } else {
4803 printf("Third rename succeeded (SHARE_NONE)\n");
4806 status = cli_close(cli1, fnum1);
4807 if (!NT_STATUS_IS_OK(status)) {
4808 printf("close - 3 failed (%s)\n", nt_errstr(status));
4809 return False;
4812 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4813 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4815 /*----*/
4817 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4818 FILE_ATTRIBUTE_NORMAL,
4819 FILE_SHARE_READ | FILE_SHARE_WRITE,
4820 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4821 if (!NT_STATUS_IS_OK(status)) {
4822 printf("Fourth open failed - %s\n", nt_errstr(status));
4823 return False;
4826 status = cli_rename(cli1, fname, fname1, false);
4827 if (!NT_STATUS_IS_OK(status)) {
4828 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4829 } else {
4830 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4831 correct = False;
4834 status = cli_close(cli1, fnum1);
4835 if (!NT_STATUS_IS_OK(status)) {
4836 printf("close - 4 failed (%s)\n", nt_errstr(status));
4837 return False;
4840 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4841 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4843 /*--*/
4845 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4846 FILE_ATTRIBUTE_NORMAL,
4847 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4848 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4849 if (!NT_STATUS_IS_OK(status)) {
4850 printf("Fifth open failed - %s\n", nt_errstr(status));
4851 return False;
4854 status = cli_rename(cli1, fname, fname1, false);
4855 if (!NT_STATUS_IS_OK(status)) {
4856 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4857 correct = False;
4858 } else {
4859 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4863 * Now check if the first name still exists ...
4866 /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4867 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4868 FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
4869 printf("Opening original file after rename of open file fails: %s\n",
4870 cli_errstr(cli1));
4872 else {
4873 printf("Opening original file after rename of open file works ...\n");
4874 (void)cli_close(cli1, fnum2);
4875 } */
4877 /*--*/
4878 status = cli_close(cli1, fnum1);
4879 if (!NT_STATUS_IS_OK(status)) {
4880 printf("close - 5 failed (%s)\n", nt_errstr(status));
4881 return False;
4884 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4885 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4886 if (!NT_STATUS_IS_OK(status)) {
4887 printf("getatr on file %s failed - %s ! \n",
4888 fname1, nt_errstr(status));
4889 correct = False;
4890 } else {
4891 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4892 printf("Renamed file %s has wrong attr 0x%x "
4893 "(should be 0x%x)\n",
4894 fname1,
4895 attr,
4896 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4897 correct = False;
4898 } else {
4899 printf("Renamed file %s has archive bit set\n", fname1);
4903 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4904 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4906 if (!torture_close_connection(cli1)) {
4907 correct = False;
4910 return correct;
4914 Test rename into a directory with an ACL denying it.
4916 static bool run_rename_access(int dummy)
4918 static struct cli_state *cli = NULL;
4919 static struct cli_state *posix_cli = NULL;
4920 const char *src = "test.txt";
4921 const char *dname = "dir";
4922 const char *dst = "dir\\test.txt";
4923 const char *dsrc = "test.dir";
4924 const char *ddst = "dir\\test.dir";
4925 uint16_t fnum = (uint16_t)-1;
4926 struct security_descriptor *sd = NULL;
4927 struct security_descriptor *newsd = NULL;
4928 NTSTATUS status;
4929 TALLOC_CTX *frame = NULL;
4931 frame = talloc_stackframe();
4932 printf("starting rename access test\n");
4934 /* Windows connection. */
4935 if (!torture_open_connection(&cli, 0)) {
4936 goto fail;
4939 smbXcli_conn_set_sockopt(cli->conn, sockops);
4941 /* Posix connection. */
4942 if (!torture_open_connection(&posix_cli, 0)) {
4943 goto fail;
4946 smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
4948 status = torture_setup_unix_extensions(posix_cli);
4949 if (!NT_STATUS_IS_OK(status)) {
4950 goto fail;
4953 /* Start with a clean slate. */
4954 cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4955 cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4956 cli_rmdir(cli, dsrc);
4957 cli_rmdir(cli, ddst);
4958 cli_rmdir(cli, dname);
4961 * Setup the destination directory with a DENY ACE to
4962 * prevent new files within it.
4964 status = cli_ntcreate(cli,
4965 dname,
4967 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
4968 WRITE_DAC_ACCESS|FILE_READ_DATA|
4969 WRITE_OWNER_ACCESS,
4970 FILE_ATTRIBUTE_DIRECTORY,
4971 FILE_SHARE_READ|FILE_SHARE_WRITE,
4972 FILE_CREATE,
4973 FILE_DIRECTORY_FILE,
4975 &fnum,
4976 NULL);
4977 if (!NT_STATUS_IS_OK(status)) {
4978 printf("Create of %s - %s\n", dname, nt_errstr(status));
4979 goto fail;
4982 status = cli_query_secdesc(cli,
4983 fnum,
4984 frame,
4985 &sd);
4986 if (!NT_STATUS_IS_OK(status)) {
4987 printf("cli_query_secdesc failed for %s (%s)\n",
4988 dname, nt_errstr(status));
4989 goto fail;
4992 newsd = security_descriptor_dacl_create(frame,
4994 NULL,
4995 NULL,
4996 SID_WORLD,
4997 SEC_ACE_TYPE_ACCESS_DENIED,
4998 SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
5000 NULL);
5001 if (newsd == NULL) {
5002 goto fail;
5004 sd->dacl = security_acl_concatenate(frame,
5005 newsd->dacl,
5006 sd->dacl);
5007 if (sd->dacl == NULL) {
5008 goto fail;
5010 status = cli_set_secdesc(cli, fnum, sd);
5011 if (!NT_STATUS_IS_OK(status)) {
5012 printf("cli_set_secdesc failed for %s (%s)\n",
5013 dname, nt_errstr(status));
5014 goto fail;
5016 status = cli_close(cli, fnum);
5017 if (!NT_STATUS_IS_OK(status)) {
5018 printf("close failed for %s (%s)\n",
5019 dname, nt_errstr(status));
5020 goto fail;
5022 /* Now go around the back and chmod to 777 via POSIX. */
5023 status = cli_posix_chmod(posix_cli, dname, 0777);
5024 if (!NT_STATUS_IS_OK(status)) {
5025 printf("cli_posix_chmod failed for %s (%s)\n",
5026 dname, nt_errstr(status));
5027 goto fail;
5030 /* Check we can't create a file within dname via Windows. */
5031 status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5032 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5033 cli_close(posix_cli, fnum);
5034 printf("Create of %s should be ACCESS denied, was %s\n",
5035 dst, nt_errstr(status));
5036 goto fail;
5039 /* Make the sample file/directory. */
5040 status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5041 if (!NT_STATUS_IS_OK(status)) {
5042 printf("open of %s failed (%s)\n", src, nt_errstr(status));
5043 goto fail;
5045 status = cli_close(cli, fnum);
5046 if (!NT_STATUS_IS_OK(status)) {
5047 printf("cli_close failed (%s)\n", nt_errstr(status));
5048 goto fail;
5051 status = cli_mkdir(cli, dsrc);
5052 if (!NT_STATUS_IS_OK(status)) {
5053 printf("cli_mkdir of %s failed (%s)\n",
5054 dsrc, nt_errstr(status));
5055 goto fail;
5059 * OK - renames of the new file and directory into the
5060 * dst directory should fail.
5063 status = cli_rename(cli, src, dst, false);
5064 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5065 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
5066 src, dst, nt_errstr(status));
5067 goto fail;
5069 status = cli_rename(cli, dsrc, ddst, false);
5070 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5071 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
5072 src, dst, nt_errstr(status));
5073 goto fail;
5076 TALLOC_FREE(frame);
5077 return true;
5079 fail:
5081 if (posix_cli) {
5082 torture_close_connection(posix_cli);
5085 if (cli) {
5086 if (fnum != (uint64_t)-1) {
5087 cli_close(cli, fnum);
5089 cli_unlink(cli, src,
5090 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5091 cli_unlink(cli, dst,
5092 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5093 cli_rmdir(cli, dsrc);
5094 cli_rmdir(cli, ddst);
5095 cli_rmdir(cli, dname);
5097 torture_close_connection(cli);
5100 TALLOC_FREE(frame);
5101 return false;
5105 Test owner rights ACE.
5107 static bool run_owner_rights(int dummy)
5109 static struct cli_state *cli = NULL;
5110 const char *fname = "owner_rights.txt";
5111 uint16_t fnum = (uint16_t)-1;
5112 struct security_descriptor *sd = NULL;
5113 struct security_descriptor *newsd = NULL;
5114 NTSTATUS status;
5115 TALLOC_CTX *frame = NULL;
5117 frame = talloc_stackframe();
5118 printf("starting owner rights test\n");
5120 /* Windows connection. */
5121 if (!torture_open_connection(&cli, 0)) {
5122 goto fail;
5125 smbXcli_conn_set_sockopt(cli->conn, sockops);
5127 /* Start with a clean slate. */
5128 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5130 /* Create the test file. */
5131 /* Now try and open for read and write-dac. */
5132 status = cli_ntcreate(cli,
5133 fname,
5135 GENERIC_ALL_ACCESS,
5136 FILE_ATTRIBUTE_NORMAL,
5137 FILE_SHARE_READ|FILE_SHARE_WRITE|
5138 FILE_SHARE_DELETE,
5139 FILE_CREATE,
5142 &fnum,
5143 NULL);
5144 if (!NT_STATUS_IS_OK(status)) {
5145 printf("Create of %s - %s\n", fname, nt_errstr(status));
5146 goto fail;
5149 /* Get the original SD. */
5150 status = cli_query_secdesc(cli,
5151 fnum,
5152 frame,
5153 &sd);
5154 if (!NT_STATUS_IS_OK(status)) {
5155 printf("cli_query_secdesc failed for %s (%s)\n",
5156 fname, nt_errstr(status));
5157 goto fail;
5161 * Add an "owner-rights" ACE denying WRITE_DATA,
5162 * and an "owner-rights" ACE allowing READ_DATA.
5165 newsd = security_descriptor_dacl_create(frame,
5167 NULL,
5168 NULL,
5169 SID_OWNER_RIGHTS,
5170 SEC_ACE_TYPE_ACCESS_DENIED,
5171 FILE_WRITE_DATA,
5173 SID_OWNER_RIGHTS,
5174 SEC_ACE_TYPE_ACCESS_ALLOWED,
5175 FILE_READ_DATA,
5177 NULL);
5178 if (newsd == NULL) {
5179 goto fail;
5181 sd->dacl = security_acl_concatenate(frame,
5182 newsd->dacl,
5183 sd->dacl);
5184 if (sd->dacl == NULL) {
5185 goto fail;
5187 status = cli_set_secdesc(cli, fnum, sd);
5188 if (!NT_STATUS_IS_OK(status)) {
5189 printf("cli_set_secdesc failed for %s (%s)\n",
5190 fname, nt_errstr(status));
5191 goto fail;
5193 status = cli_close(cli, fnum);
5194 if (!NT_STATUS_IS_OK(status)) {
5195 printf("close failed for %s (%s)\n",
5196 fname, nt_errstr(status));
5197 goto fail;
5199 fnum = (uint16_t)-1;
5201 /* Try and open for FILE_WRITE_DATA */
5202 status = cli_ntcreate(cli,
5203 fname,
5205 FILE_WRITE_DATA,
5206 FILE_ATTRIBUTE_NORMAL,
5207 FILE_SHARE_READ|FILE_SHARE_WRITE|
5208 FILE_SHARE_DELETE,
5209 FILE_OPEN,
5212 &fnum,
5213 NULL);
5214 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5215 printf("Open of %s - %s\n", fname, nt_errstr(status));
5216 goto fail;
5219 /* Now try and open for FILE_READ_DATA */
5220 status = cli_ntcreate(cli,
5221 fname,
5223 FILE_READ_DATA,
5224 FILE_ATTRIBUTE_NORMAL,
5225 FILE_SHARE_READ|FILE_SHARE_WRITE|
5226 FILE_SHARE_DELETE,
5227 FILE_OPEN,
5230 &fnum,
5231 NULL);
5232 if (!NT_STATUS_IS_OK(status)) {
5233 printf("Open of %s - %s\n", fname, nt_errstr(status));
5234 goto fail;
5237 status = cli_close(cli, fnum);
5238 if (!NT_STATUS_IS_OK(status)) {
5239 printf("close failed for %s (%s)\n",
5240 fname, nt_errstr(status));
5241 goto fail;
5244 /* Restore clean slate. */
5245 TALLOC_FREE(sd);
5246 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5248 /* Create the test file. */
5249 status = cli_ntcreate(cli,
5250 fname,
5252 GENERIC_ALL_ACCESS,
5253 FILE_ATTRIBUTE_NORMAL,
5254 FILE_SHARE_READ|FILE_SHARE_WRITE|
5255 FILE_SHARE_DELETE,
5256 FILE_CREATE,
5259 &fnum,
5260 NULL);
5261 if (!NT_STATUS_IS_OK(status)) {
5262 printf("Create of %s - %s\n", fname, nt_errstr(status));
5263 goto fail;
5266 /* Get the original SD. */
5267 status = cli_query_secdesc(cli,
5268 fnum,
5269 frame,
5270 &sd);
5271 if (!NT_STATUS_IS_OK(status)) {
5272 printf("cli_query_secdesc failed for %s (%s)\n",
5273 fname, nt_errstr(status));
5274 goto fail;
5278 * Add an "owner-rights ACE denying WRITE_DATA,
5279 * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
5282 newsd = security_descriptor_dacl_create(frame,
5284 NULL,
5285 NULL,
5286 SID_OWNER_RIGHTS,
5287 SEC_ACE_TYPE_ACCESS_DENIED,
5288 FILE_WRITE_DATA,
5290 SID_OWNER_RIGHTS,
5291 SEC_ACE_TYPE_ACCESS_ALLOWED,
5292 FILE_READ_DATA|FILE_WRITE_DATA,
5294 NULL);
5295 if (newsd == NULL) {
5296 goto fail;
5298 sd->dacl = security_acl_concatenate(frame,
5299 newsd->dacl,
5300 sd->dacl);
5301 if (sd->dacl == NULL) {
5302 goto fail;
5304 status = cli_set_secdesc(cli, fnum, sd);
5305 if (!NT_STATUS_IS_OK(status)) {
5306 printf("cli_set_secdesc failed for %s (%s)\n",
5307 fname, nt_errstr(status));
5308 goto fail;
5310 status = cli_close(cli, fnum);
5311 if (!NT_STATUS_IS_OK(status)) {
5312 printf("close failed for %s (%s)\n",
5313 fname, nt_errstr(status));
5314 goto fail;
5316 fnum = (uint16_t)-1;
5318 /* Try and open for FILE_WRITE_DATA */
5319 status = cli_ntcreate(cli,
5320 fname,
5322 FILE_WRITE_DATA,
5323 FILE_ATTRIBUTE_NORMAL,
5324 FILE_SHARE_READ|FILE_SHARE_WRITE|
5325 FILE_SHARE_DELETE,
5326 FILE_OPEN,
5329 &fnum,
5330 NULL);
5331 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5332 printf("Open of %s - %s\n", fname, nt_errstr(status));
5333 goto fail;
5336 /* Now try and open for FILE_READ_DATA */
5337 status = cli_ntcreate(cli,
5338 fname,
5340 FILE_READ_DATA,
5341 FILE_ATTRIBUTE_NORMAL,
5342 FILE_SHARE_READ|FILE_SHARE_WRITE|
5343 FILE_SHARE_DELETE,
5344 FILE_OPEN,
5347 &fnum,
5348 NULL);
5349 if (!NT_STATUS_IS_OK(status)) {
5350 printf("Open of %s - %s\n", fname, nt_errstr(status));
5351 goto fail;
5354 status = cli_close(cli, fnum);
5355 if (!NT_STATUS_IS_OK(status)) {
5356 printf("close failed for %s (%s)\n",
5357 fname, nt_errstr(status));
5358 goto fail;
5361 /* Restore clean slate. */
5362 TALLOC_FREE(sd);
5363 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5366 /* Create the test file. */
5367 status = cli_ntcreate(cli,
5368 fname,
5370 GENERIC_ALL_ACCESS,
5371 FILE_ATTRIBUTE_NORMAL,
5372 FILE_SHARE_READ|FILE_SHARE_WRITE|
5373 FILE_SHARE_DELETE,
5374 FILE_CREATE,
5377 &fnum,
5378 NULL);
5379 if (!NT_STATUS_IS_OK(status)) {
5380 printf("Create of %s - %s\n", fname, nt_errstr(status));
5381 goto fail;
5384 /* Get the original SD. */
5385 status = cli_query_secdesc(cli,
5386 fnum,
5387 frame,
5388 &sd);
5389 if (!NT_STATUS_IS_OK(status)) {
5390 printf("cli_query_secdesc failed for %s (%s)\n",
5391 fname, nt_errstr(status));
5392 goto fail;
5396 * Add an "authenticated users" ACE allowing READ_DATA,
5397 * add an "owner-rights" denying READ_DATA,
5398 * and an "authenticated users" ACE allowing WRITE_DATA.
5401 newsd = security_descriptor_dacl_create(frame,
5403 NULL,
5404 NULL,
5405 SID_NT_AUTHENTICATED_USERS,
5406 SEC_ACE_TYPE_ACCESS_ALLOWED,
5407 FILE_READ_DATA,
5409 SID_OWNER_RIGHTS,
5410 SEC_ACE_TYPE_ACCESS_DENIED,
5411 FILE_READ_DATA,
5413 SID_NT_AUTHENTICATED_USERS,
5414 SEC_ACE_TYPE_ACCESS_ALLOWED,
5415 FILE_WRITE_DATA,
5417 NULL);
5418 if (newsd == NULL) {
5419 printf("newsd == NULL\n");
5420 goto fail;
5422 sd->dacl = security_acl_concatenate(frame,
5423 newsd->dacl,
5424 sd->dacl);
5425 if (sd->dacl == NULL) {
5426 printf("sd->dacl == NULL\n");
5427 goto fail;
5429 status = cli_set_secdesc(cli, fnum, sd);
5430 if (!NT_STATUS_IS_OK(status)) {
5431 printf("cli_set_secdesc failed for %s (%s)\n",
5432 fname, nt_errstr(status));
5433 goto fail;
5435 status = cli_close(cli, fnum);
5436 if (!NT_STATUS_IS_OK(status)) {
5437 printf("close failed for %s (%s)\n",
5438 fname, nt_errstr(status));
5439 goto fail;
5441 fnum = (uint16_t)-1;
5443 /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
5444 status = cli_ntcreate(cli,
5445 fname,
5447 FILE_READ_DATA|FILE_WRITE_DATA,
5448 FILE_ATTRIBUTE_NORMAL,
5449 FILE_SHARE_READ|FILE_SHARE_WRITE|
5450 FILE_SHARE_DELETE,
5451 FILE_OPEN,
5454 &fnum,
5455 NULL);
5456 if (!NT_STATUS_IS_OK(status)) {
5457 printf("Open of %s - %s\n", fname, nt_errstr(status));
5458 goto fail;
5461 status = cli_close(cli, fnum);
5462 if (!NT_STATUS_IS_OK(status)) {
5463 printf("close failed for %s (%s)\n",
5464 fname, nt_errstr(status));
5465 goto fail;
5468 cli_unlink(cli, fname,
5469 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5471 TALLOC_FREE(frame);
5472 return true;
5474 fail:
5476 if (cli) {
5477 if (fnum != (uint16_t)-1) {
5478 cli_close(cli, fnum);
5480 cli_unlink(cli, fname,
5481 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5482 torture_close_connection(cli);
5485 TALLOC_FREE(frame);
5486 return false;
5489 static bool run_pipe_number(int dummy)
5491 struct cli_state *cli1;
5492 const char *pipe_name = "\\SPOOLSS";
5493 uint16_t fnum;
5494 int num_pipes = 0;
5495 NTSTATUS status;
5497 printf("starting pipenumber test\n");
5498 if (!torture_open_connection(&cli1, 0)) {
5499 return False;
5502 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5503 while(1) {
5504 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
5505 FILE_ATTRIBUTE_NORMAL,
5506 FILE_SHARE_READ|FILE_SHARE_WRITE,
5507 FILE_OPEN_IF, 0, 0, &fnum, NULL);
5508 if (!NT_STATUS_IS_OK(status)) {
5509 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
5510 break;
5512 num_pipes++;
5513 printf("\r%6d", num_pipes);
5516 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
5517 torture_close_connection(cli1);
5518 return True;
5522 Test open mode returns on read-only files.
5524 static bool run_opentest(int dummy)
5526 static struct cli_state *cli1;
5527 static struct cli_state *cli2;
5528 const char *fname = "\\readonly.file";
5529 uint16_t fnum1, fnum2;
5530 char buf[20];
5531 off_t fsize;
5532 bool correct = True;
5533 char *tmp_path;
5534 NTSTATUS status;
5536 printf("starting open test\n");
5538 if (!torture_open_connection(&cli1, 0)) {
5539 return False;
5542 cli_setatr(cli1, fname, 0, 0);
5543 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5545 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5547 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
5548 if (!NT_STATUS_IS_OK(status)) {
5549 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5550 return False;
5553 status = cli_close(cli1, fnum1);
5554 if (!NT_STATUS_IS_OK(status)) {
5555 printf("close2 failed (%s)\n", nt_errstr(status));
5556 return False;
5559 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
5560 if (!NT_STATUS_IS_OK(status)) {
5561 printf("cli_setatr failed (%s)\n", nt_errstr(status));
5562 return False;
5565 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
5566 if (!NT_STATUS_IS_OK(status)) {
5567 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5568 return False;
5571 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
5572 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
5574 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
5575 NT_STATUS_ACCESS_DENIED)) {
5576 printf("correct error code ERRDOS/ERRnoaccess returned\n");
5579 printf("finished open test 1\n");
5581 cli_close(cli1, fnum1);
5583 /* Now try not readonly and ensure ERRbadshare is returned. */
5585 cli_setatr(cli1, fname, 0, 0);
5587 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
5588 if (!NT_STATUS_IS_OK(status)) {
5589 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5590 return False;
5593 /* This will fail - but the error should be ERRshare. */
5594 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
5596 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
5597 NT_STATUS_SHARING_VIOLATION)) {
5598 printf("correct error code ERRDOS/ERRbadshare returned\n");
5601 status = cli_close(cli1, fnum1);
5602 if (!NT_STATUS_IS_OK(status)) {
5603 printf("close2 failed (%s)\n", nt_errstr(status));
5604 return False;
5607 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5609 printf("finished open test 2\n");
5611 /* Test truncate open disposition on file opened for read. */
5612 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
5613 if (!NT_STATUS_IS_OK(status)) {
5614 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
5615 return False;
5618 /* write 20 bytes. */
5620 memset(buf, '\0', 20);
5622 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
5623 if (!NT_STATUS_IS_OK(status)) {
5624 printf("write failed (%s)\n", nt_errstr(status));
5625 correct = False;
5628 status = cli_close(cli1, fnum1);
5629 if (!NT_STATUS_IS_OK(status)) {
5630 printf("(3) close1 failed (%s)\n", nt_errstr(status));
5631 return False;
5634 /* Ensure size == 20. */
5635 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5636 if (!NT_STATUS_IS_OK(status)) {
5637 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5638 return False;
5641 if (fsize != 20) {
5642 printf("(3) file size != 20\n");
5643 return False;
5646 /* Now test if we can truncate a file opened for readonly. */
5647 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
5648 if (!NT_STATUS_IS_OK(status)) {
5649 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
5650 return False;
5653 status = cli_close(cli1, fnum1);
5654 if (!NT_STATUS_IS_OK(status)) {
5655 printf("close2 failed (%s)\n", nt_errstr(status));
5656 return False;
5659 /* Ensure size == 0. */
5660 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5661 if (!NT_STATUS_IS_OK(status)) {
5662 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5663 return False;
5666 if (fsize != 0) {
5667 printf("(3) file size != 0\n");
5668 return False;
5670 printf("finished open test 3\n");
5672 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5674 printf("Do ctemp tests\n");
5675 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
5676 if (!NT_STATUS_IS_OK(status)) {
5677 printf("ctemp failed (%s)\n", nt_errstr(status));
5678 return False;
5681 printf("ctemp gave path %s\n", tmp_path);
5682 status = cli_close(cli1, fnum1);
5683 if (!NT_STATUS_IS_OK(status)) {
5684 printf("close of temp failed (%s)\n", nt_errstr(status));
5687 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5688 if (!NT_STATUS_IS_OK(status)) {
5689 printf("unlink of temp failed (%s)\n", nt_errstr(status));
5692 /* Test the non-io opens... */
5694 if (!torture_open_connection(&cli2, 1)) {
5695 return False;
5698 cli_setatr(cli2, fname, 0, 0);
5699 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5701 smbXcli_conn_set_sockopt(cli2->conn, sockops);
5703 printf("TEST #1 testing 2 non-io opens (no delete)\n");
5704 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5705 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5706 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5707 if (!NT_STATUS_IS_OK(status)) {
5708 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5709 return False;
5712 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5713 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5714 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5715 if (!NT_STATUS_IS_OK(status)) {
5716 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5717 return False;
5720 status = cli_close(cli1, fnum1);
5721 if (!NT_STATUS_IS_OK(status)) {
5722 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5723 return False;
5726 status = cli_close(cli2, fnum2);
5727 if (!NT_STATUS_IS_OK(status)) {
5728 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5729 return False;
5732 printf("non-io open test #1 passed.\n");
5734 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5736 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5738 status = cli_ntcreate(cli1, fname, 0,
5739 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5740 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5741 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5742 if (!NT_STATUS_IS_OK(status)) {
5743 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5744 return False;
5747 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5748 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5749 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5750 if (!NT_STATUS_IS_OK(status)) {
5751 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5752 return False;
5755 status = cli_close(cli1, fnum1);
5756 if (!NT_STATUS_IS_OK(status)) {
5757 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5758 return False;
5761 status = cli_close(cli2, fnum2);
5762 if (!NT_STATUS_IS_OK(status)) {
5763 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5764 return False;
5767 printf("non-io open test #2 passed.\n");
5769 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5771 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5773 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5774 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5775 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5776 if (!NT_STATUS_IS_OK(status)) {
5777 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5778 return False;
5781 status = cli_ntcreate(cli2, fname, 0,
5782 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5783 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5784 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5785 if (!NT_STATUS_IS_OK(status)) {
5786 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5787 return False;
5790 status = cli_close(cli1, fnum1);
5791 if (!NT_STATUS_IS_OK(status)) {
5792 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5793 return False;
5796 status = cli_close(cli2, fnum2);
5797 if (!NT_STATUS_IS_OK(status)) {
5798 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5799 return False;
5802 printf("non-io open test #3 passed.\n");
5804 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5806 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5808 status = cli_ntcreate(cli1, fname, 0,
5809 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5810 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5811 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5812 if (!NT_STATUS_IS_OK(status)) {
5813 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5814 return False;
5817 status = cli_ntcreate(cli2, fname, 0,
5818 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5819 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5820 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5821 if (NT_STATUS_IS_OK(status)) {
5822 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5823 return False;
5826 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5828 status = cli_close(cli1, fnum1);
5829 if (!NT_STATUS_IS_OK(status)) {
5830 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5831 return False;
5834 printf("non-io open test #4 passed.\n");
5836 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5838 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5840 status = cli_ntcreate(cli1, fname, 0,
5841 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5842 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5843 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5844 if (!NT_STATUS_IS_OK(status)) {
5845 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5846 return False;
5849 status = cli_ntcreate(cli2, fname, 0,
5850 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5851 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5852 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5853 if (!NT_STATUS_IS_OK(status)) {
5854 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5855 return False;
5858 status = cli_close(cli1, fnum1);
5859 if (!NT_STATUS_IS_OK(status)) {
5860 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5861 return False;
5864 status = cli_close(cli2, fnum2);
5865 if (!NT_STATUS_IS_OK(status)) {
5866 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5867 return False;
5870 printf("non-io open test #5 passed.\n");
5872 printf("TEST #6 testing 1 non-io open, one io open\n");
5874 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5876 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5877 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5878 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5879 if (!NT_STATUS_IS_OK(status)) {
5880 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5881 return False;
5884 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5885 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5886 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5887 if (!NT_STATUS_IS_OK(status)) {
5888 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5889 return False;
5892 status = cli_close(cli1, fnum1);
5893 if (!NT_STATUS_IS_OK(status)) {
5894 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5895 return False;
5898 status = cli_close(cli2, fnum2);
5899 if (!NT_STATUS_IS_OK(status)) {
5900 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5901 return False;
5904 printf("non-io open test #6 passed.\n");
5906 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5908 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5910 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5911 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5912 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5913 if (!NT_STATUS_IS_OK(status)) {
5914 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5915 return False;
5918 status = cli_ntcreate(cli2, fname, 0,
5919 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5920 FILE_ATTRIBUTE_NORMAL,
5921 FILE_SHARE_READ|FILE_SHARE_DELETE,
5922 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5923 if (NT_STATUS_IS_OK(status)) {
5924 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5925 return False;
5928 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5930 status = cli_close(cli1, fnum1);
5931 if (!NT_STATUS_IS_OK(status)) {
5932 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5933 return False;
5936 printf("non-io open test #7 passed.\n");
5938 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5940 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5941 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5942 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5943 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5944 if (!NT_STATUS_IS_OK(status)) {
5945 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5946 correct = false;
5947 goto out;
5950 /* Write to ensure we have to update the file time. */
5951 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5952 NULL);
5953 if (!NT_STATUS_IS_OK(status)) {
5954 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5955 correct = false;
5956 goto out;
5959 status = cli_close(cli1, fnum1);
5960 if (!NT_STATUS_IS_OK(status)) {
5961 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5962 correct = false;
5965 out:
5967 if (!torture_close_connection(cli1)) {
5968 correct = False;
5970 if (!torture_close_connection(cli2)) {
5971 correct = False;
5974 return correct;
5977 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5979 uint16_t major, minor;
5980 uint32_t caplow, caphigh;
5981 NTSTATUS status;
5983 if (!SERVER_HAS_UNIX_CIFS(cli)) {
5984 printf("Server doesn't support UNIX CIFS extensions.\n");
5985 return NT_STATUS_NOT_SUPPORTED;
5988 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5989 &caphigh);
5990 if (!NT_STATUS_IS_OK(status)) {
5991 printf("Server didn't return UNIX CIFS extensions: %s\n",
5992 nt_errstr(status));
5993 return status;
5996 status = cli_set_unix_extensions_capabilities(cli, major, minor,
5997 caplow, caphigh);
5998 if (!NT_STATUS_IS_OK(status)) {
5999 printf("Server doesn't support setting UNIX CIFS extensions: "
6000 "%s.\n", nt_errstr(status));
6001 return status;
6004 return NT_STATUS_OK;
6008 Test POSIX open /mkdir calls.
6010 static bool run_simple_posix_open_test(int dummy)
6012 static struct cli_state *cli1;
6013 const char *fname = "posix:file";
6014 const char *hname = "posix:hlink";
6015 const char *sname = "posix:symlink";
6016 const char *dname = "posix:dir";
6017 char buf[10];
6018 char namebuf[11];
6019 uint16_t fnum1 = (uint16_t)-1;
6020 SMB_STRUCT_STAT sbuf;
6021 bool correct = false;
6022 NTSTATUS status;
6023 size_t nread;
6024 const char *fname_windows = "windows_file";
6025 uint16_t fnum2 = (uint16_t)-1;
6027 printf("Starting simple POSIX open test\n");
6029 if (!torture_open_connection(&cli1, 0)) {
6030 return false;
6033 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6035 status = torture_setup_unix_extensions(cli1);
6036 if (!NT_STATUS_IS_OK(status)) {
6037 return false;
6040 cli_setatr(cli1, fname, 0, 0);
6041 cli_posix_unlink(cli1, fname);
6042 cli_setatr(cli1, dname, 0, 0);
6043 cli_posix_rmdir(cli1, dname);
6044 cli_setatr(cli1, hname, 0, 0);
6045 cli_posix_unlink(cli1, hname);
6046 cli_setatr(cli1, sname, 0, 0);
6047 cli_posix_unlink(cli1, sname);
6048 cli_setatr(cli1, fname_windows, 0, 0);
6049 cli_posix_unlink(cli1, fname_windows);
6051 /* Create a directory. */
6052 status = cli_posix_mkdir(cli1, dname, 0777);
6053 if (!NT_STATUS_IS_OK(status)) {
6054 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
6055 goto out;
6058 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
6059 0600, &fnum1);
6060 if (!NT_STATUS_IS_OK(status)) {
6061 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6062 goto out;
6065 /* Test ftruncate - set file size. */
6066 status = cli_ftruncate(cli1, fnum1, 1000);
6067 if (!NT_STATUS_IS_OK(status)) {
6068 printf("ftruncate failed (%s)\n", nt_errstr(status));
6069 goto out;
6072 /* Ensure st_size == 1000 */
6073 status = cli_posix_stat(cli1, fname, &sbuf);
6074 if (!NT_STATUS_IS_OK(status)) {
6075 printf("stat failed (%s)\n", nt_errstr(status));
6076 goto out;
6079 if (sbuf.st_ex_size != 1000) {
6080 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
6081 goto out;
6084 /* Ensure st_mode == 0600 */
6085 if ((sbuf.st_ex_mode & 07777) != 0600) {
6086 printf("posix_open - bad permissions 0%o != 0600\n",
6087 (unsigned int)(sbuf.st_ex_mode & 07777));
6088 goto out;
6091 /* Test ftruncate - set file size back to zero. */
6092 status = cli_ftruncate(cli1, fnum1, 0);
6093 if (!NT_STATUS_IS_OK(status)) {
6094 printf("ftruncate failed (%s)\n", nt_errstr(status));
6095 goto out;
6098 status = cli_close(cli1, fnum1);
6099 if (!NT_STATUS_IS_OK(status)) {
6100 printf("close failed (%s)\n", nt_errstr(status));
6101 goto out;
6104 /* Now open the file again for read only. */
6105 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
6106 if (!NT_STATUS_IS_OK(status)) {
6107 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
6108 goto out;
6111 /* Now unlink while open. */
6112 status = cli_posix_unlink(cli1, fname);
6113 if (!NT_STATUS_IS_OK(status)) {
6114 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
6115 goto out;
6118 status = cli_close(cli1, fnum1);
6119 if (!NT_STATUS_IS_OK(status)) {
6120 printf("close(2) failed (%s)\n", nt_errstr(status));
6121 goto out;
6124 /* Ensure the file has gone. */
6125 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
6126 if (NT_STATUS_IS_OK(status)) {
6127 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
6128 goto out;
6131 /* Create again to test open with O_TRUNC. */
6132 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
6133 if (!NT_STATUS_IS_OK(status)) {
6134 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6135 goto out;
6138 /* Test ftruncate - set file size. */
6139 status = cli_ftruncate(cli1, fnum1, 1000);
6140 if (!NT_STATUS_IS_OK(status)) {
6141 printf("ftruncate failed (%s)\n", nt_errstr(status));
6142 goto out;
6145 /* Ensure st_size == 1000 */
6146 status = cli_posix_stat(cli1, fname, &sbuf);
6147 if (!NT_STATUS_IS_OK(status)) {
6148 printf("stat failed (%s)\n", nt_errstr(status));
6149 goto out;
6152 if (sbuf.st_ex_size != 1000) {
6153 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
6154 goto out;
6157 status = cli_close(cli1, fnum1);
6158 if (!NT_STATUS_IS_OK(status)) {
6159 printf("close(2) failed (%s)\n", nt_errstr(status));
6160 goto out;
6163 /* Re-open with O_TRUNC. */
6164 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
6165 if (!NT_STATUS_IS_OK(status)) {
6166 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6167 goto out;
6170 /* Ensure st_size == 0 */
6171 status = cli_posix_stat(cli1, fname, &sbuf);
6172 if (!NT_STATUS_IS_OK(status)) {
6173 printf("stat failed (%s)\n", nt_errstr(status));
6174 goto out;
6177 if (sbuf.st_ex_size != 0) {
6178 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
6179 goto out;
6182 status = cli_close(cli1, fnum1);
6183 if (!NT_STATUS_IS_OK(status)) {
6184 printf("close failed (%s)\n", nt_errstr(status));
6185 goto out;
6188 status = cli_posix_unlink(cli1, fname);
6189 if (!NT_STATUS_IS_OK(status)) {
6190 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
6191 goto out;
6194 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
6195 if (!NT_STATUS_IS_OK(status)) {
6196 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
6197 dname, nt_errstr(status));
6198 goto out;
6201 cli_close(cli1, fnum1);
6203 /* What happens when we try and POSIX open a directory for write ? */
6204 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
6205 if (NT_STATUS_IS_OK(status)) {
6206 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
6207 goto out;
6208 } else {
6209 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
6210 NT_STATUS_FILE_IS_A_DIRECTORY)) {
6211 goto out;
6215 /* Create the file. */
6216 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
6217 0600, &fnum1);
6218 if (!NT_STATUS_IS_OK(status)) {
6219 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6220 goto out;
6223 /* Write some data into it. */
6224 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
6225 NULL);
6226 if (!NT_STATUS_IS_OK(status)) {
6227 printf("cli_write failed: %s\n", nt_errstr(status));
6228 goto out;
6231 cli_close(cli1, fnum1);
6233 /* Now create a hardlink. */
6234 status = cli_posix_hardlink(cli1, fname, hname);
6235 if (!NT_STATUS_IS_OK(status)) {
6236 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
6237 goto out;
6240 /* Now create a symlink. */
6241 status = cli_posix_symlink(cli1, fname, sname);
6242 if (!NT_STATUS_IS_OK(status)) {
6243 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
6244 goto out;
6247 /* Open the hardlink for read. */
6248 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
6249 if (!NT_STATUS_IS_OK(status)) {
6250 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
6251 goto out;
6254 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
6255 if (!NT_STATUS_IS_OK(status)) {
6256 printf("POSIX read of %s failed (%s)\n", hname,
6257 nt_errstr(status));
6258 goto out;
6259 } else if (nread != 10) {
6260 printf("POSIX read of %s failed. Received %ld, expected %d\n",
6261 hname, (unsigned long)nread, 10);
6262 goto out;
6265 if (memcmp(buf, "TEST DATA\n", 10)) {
6266 printf("invalid data read from hardlink\n");
6267 goto out;
6270 /* Do a POSIX lock/unlock. */
6271 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
6272 if (!NT_STATUS_IS_OK(status)) {
6273 printf("POSIX lock failed %s\n", nt_errstr(status));
6274 goto out;
6277 /* Punch a hole in the locked area. */
6278 status = cli_posix_unlock(cli1, fnum1, 10, 80);
6279 if (!NT_STATUS_IS_OK(status)) {
6280 printf("POSIX unlock failed %s\n", nt_errstr(status));
6281 goto out;
6284 cli_close(cli1, fnum1);
6286 /* Open the symlink for read - this should fail. A POSIX
6287 client should not be doing opens on a symlink. */
6288 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
6289 if (NT_STATUS_IS_OK(status)) {
6290 printf("POSIX open of %s succeeded (should have failed)\n", sname);
6291 goto out;
6292 } else {
6293 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
6294 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
6295 printf("POSIX open of %s should have failed "
6296 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
6297 "failed with %s instead.\n",
6298 sname, nt_errstr(status));
6299 goto out;
6303 status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
6304 if (!NT_STATUS_IS_OK(status)) {
6305 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
6306 goto out;
6309 if (strcmp(namebuf, fname) != 0) {
6310 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
6311 sname, fname, namebuf);
6312 goto out;
6315 status = cli_posix_rmdir(cli1, dname);
6316 if (!NT_STATUS_IS_OK(status)) {
6317 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
6318 goto out;
6321 /* Check directory opens with a specific permission. */
6322 status = cli_posix_mkdir(cli1, dname, 0700);
6323 if (!NT_STATUS_IS_OK(status)) {
6324 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
6325 goto out;
6328 /* Ensure st_mode == 0700 */
6329 status = cli_posix_stat(cli1, dname, &sbuf);
6330 if (!NT_STATUS_IS_OK(status)) {
6331 printf("stat failed (%s)\n", nt_errstr(status));
6332 goto out;
6335 if ((sbuf.st_ex_mode & 07777) != 0700) {
6336 printf("posix_mkdir - bad permissions 0%o != 0700\n",
6337 (unsigned int)(sbuf.st_ex_mode & 07777));
6338 goto out;
6342 * Now create a Windows file, and attempt a POSIX unlink.
6343 * This should fail with a sharing violation but due to:
6345 * [Bug 9571] Unlink after open causes smbd to panic
6347 * ensure we've fixed the lock ordering violation.
6350 status = cli_ntcreate(cli1, fname_windows, 0,
6351 FILE_READ_DATA|FILE_WRITE_DATA, 0,
6352 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6353 FILE_CREATE,
6354 0x0, 0x0, &fnum2, NULL);
6355 if (!NT_STATUS_IS_OK(status)) {
6356 printf("Windows create of %s failed (%s)\n", fname_windows,
6357 nt_errstr(status));
6358 goto out;
6361 /* Now try posix_unlink. */
6362 status = cli_posix_unlink(cli1, fname_windows);
6363 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6364 printf("POSIX unlink of %s should fail "
6365 "with NT_STATUS_SHARING_VIOLATION "
6366 "got %s instead !\n",
6367 fname_windows,
6368 nt_errstr(status));
6369 goto out;
6372 cli_close(cli1, fnum2);
6374 printf("Simple POSIX open test passed\n");
6375 correct = true;
6377 out:
6379 if (fnum1 != (uint16_t)-1) {
6380 cli_close(cli1, fnum1);
6381 fnum1 = (uint16_t)-1;
6384 if (fnum2 != (uint16_t)-1) {
6385 cli_close(cli1, fnum2);
6386 fnum2 = (uint16_t)-1;
6389 cli_setatr(cli1, sname, 0, 0);
6390 cli_posix_unlink(cli1, sname);
6391 cli_setatr(cli1, hname, 0, 0);
6392 cli_posix_unlink(cli1, hname);
6393 cli_setatr(cli1, fname, 0, 0);
6394 cli_posix_unlink(cli1, fname);
6395 cli_setatr(cli1, dname, 0, 0);
6396 cli_posix_rmdir(cli1, dname);
6397 cli_setatr(cli1, fname_windows, 0, 0);
6398 cli_posix_unlink(cli1, fname_windows);
6400 if (!torture_close_connection(cli1)) {
6401 correct = false;
6404 return correct;
6408 Test POSIX and Windows ACLs are rejected on symlinks.
6410 static bool run_acl_symlink_test(int dummy)
6412 static struct cli_state *cli;
6413 const char *fname = "posix_file";
6414 const char *sname = "posix_symlink";
6415 uint16_t fnum = (uint16_t)-1;
6416 bool correct = false;
6417 NTSTATUS status;
6418 char *posix_acl = NULL;
6419 size_t posix_acl_len = 0;
6420 char *posix_acl_sym = NULL;
6421 size_t posix_acl_len_sym = 0;
6422 struct security_descriptor *sd = NULL;
6423 struct security_descriptor *sd_sym = NULL;
6424 TALLOC_CTX *frame = NULL;
6426 frame = talloc_stackframe();
6428 printf("Starting acl symlink test\n");
6430 if (!torture_open_connection(&cli, 0)) {
6431 TALLOC_FREE(frame);
6432 return false;
6435 smbXcli_conn_set_sockopt(cli->conn, sockops);
6437 status = torture_setup_unix_extensions(cli);
6438 if (!NT_STATUS_IS_OK(status)) {
6439 TALLOC_FREE(frame);
6440 return false;
6443 cli_setatr(cli, fname, 0, 0);
6444 cli_posix_unlink(cli, fname);
6445 cli_setatr(cli, sname, 0, 0);
6446 cli_posix_unlink(cli, sname);
6448 status = cli_ntcreate(cli,
6449 fname,
6451 READ_CONTROL_ACCESS,
6453 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6454 FILE_CREATE,
6455 0x0,
6456 0x0,
6457 &fnum,
6458 NULL);
6460 if (!NT_STATUS_IS_OK(status)) {
6461 printf("cli_ntcreate of %s failed (%s)\n",
6462 fname,
6463 nt_errstr(status));
6464 goto out;
6467 /* Get the Windows ACL on the file. */
6468 status = cli_query_secdesc(cli,
6469 fnum,
6470 frame,
6471 &sd);
6472 if (!NT_STATUS_IS_OK(status)) {
6473 printf("cli_query_secdesc failed (%s)\n",
6474 nt_errstr(status));
6475 goto out;
6478 /* Get the POSIX ACL on the file. */
6479 status = cli_posix_getacl(cli,
6480 fname,
6481 frame,
6482 &posix_acl_len,
6483 &posix_acl);
6485 if (!NT_STATUS_IS_OK(status)) {
6486 printf("cli_posix_getacl failed (%s)\n",
6487 nt_errstr(status));
6488 goto out;
6491 status = cli_close(cli, fnum);
6492 if (!NT_STATUS_IS_OK(status)) {
6493 printf("close failed (%s)\n", nt_errstr(status));
6494 goto out;
6496 fnum = (uint16_t)-1;
6498 /* Now create a symlink. */
6499 status = cli_posix_symlink(cli, fname, sname);
6500 if (!NT_STATUS_IS_OK(status)) {
6501 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
6502 sname,
6503 fname,
6504 nt_errstr(status));
6505 goto out;
6508 /* Open a handle on the symlink. */
6509 status = cli_ntcreate(cli,
6510 sname,
6512 READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
6514 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6515 FILE_OPEN,
6516 0x0,
6517 0x0,
6518 &fnum,
6519 NULL);
6521 if (!NT_STATUS_IS_OK(status)) {
6522 printf("cli_posix_open of %s failed (%s)\n",
6523 sname,
6524 nt_errstr(status));
6525 goto out;
6528 /* Get the Windows ACL on the symlink handle. Should fail */
6529 status = cli_query_secdesc(cli,
6530 fnum,
6531 frame,
6532 &sd_sym);
6534 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6535 printf("cli_query_secdesc on a symlink gave %s. "
6536 "Should be NT_STATUS_ACCESS_DENIED.\n",
6537 nt_errstr(status));
6538 goto out;
6541 /* Get the POSIX ACL on the symlink pathname. Should fail. */
6542 status = cli_posix_getacl(cli,
6543 sname,
6544 frame,
6545 &posix_acl_len_sym,
6546 &posix_acl_sym);
6548 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6549 printf("cli_posix_getacl on a symlink gave %s. "
6550 "Should be NT_STATUS_ACCESS_DENIED.\n",
6551 nt_errstr(status));
6552 goto out;
6555 /* Set the Windows ACL on the symlink handle. Should fail */
6556 status = cli_set_security_descriptor(cli,
6557 fnum,
6558 SECINFO_DACL,
6559 sd);
6561 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6562 printf("cli_query_secdesc on a symlink gave %s. "
6563 "Should be NT_STATUS_ACCESS_DENIED.\n",
6564 nt_errstr(status));
6565 goto out;
6568 /* Set the POSIX ACL on the symlink pathname. Should fail. */
6569 status = cli_posix_setacl(cli,
6570 sname,
6571 posix_acl,
6572 posix_acl_len);
6574 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6575 printf("cli_posix_getacl on a symlink gave %s. "
6576 "Should be NT_STATUS_ACCESS_DENIED.\n",
6577 nt_errstr(status));
6578 goto out;
6581 printf("ACL symlink test passed\n");
6582 correct = true;
6584 out:
6586 if (fnum != (uint16_t)-1) {
6587 cli_close(cli, fnum);
6588 fnum = (uint16_t)-1;
6591 cli_setatr(cli, sname, 0, 0);
6592 cli_posix_unlink(cli, sname);
6593 cli_setatr(cli, fname, 0, 0);
6594 cli_posix_unlink(cli, fname);
6596 if (!torture_close_connection(cli)) {
6597 correct = false;
6600 TALLOC_FREE(frame);
6601 return correct;
6605 Test POSIX can delete a file containing streams.
6607 static bool run_posix_stream_delete(int dummy)
6609 struct cli_state *cli1 = NULL;
6610 struct cli_state *cli2 = NULL;
6611 const char *fname = "streamfile";
6612 const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
6613 uint16_t fnum1 = (uint16_t)-1;
6614 bool correct = false;
6615 NTSTATUS status;
6616 TALLOC_CTX *frame = NULL;
6618 frame = talloc_stackframe();
6620 printf("Starting POSIX stream delete test\n");
6622 if (!torture_open_connection(&cli1, 0) ||
6623 !torture_open_connection(&cli2, 1)) {
6624 TALLOC_FREE(frame);
6625 return false;
6628 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6629 smbXcli_conn_set_sockopt(cli2->conn, sockops);
6631 status = torture_setup_unix_extensions(cli2);
6632 if (!NT_STATUS_IS_OK(status)) {
6633 goto out;
6636 cli_setatr(cli1, fname, 0, 0);
6637 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6639 /* Create the file. */
6640 status = cli_ntcreate(cli1,
6641 fname,
6643 READ_CONTROL_ACCESS,
6645 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6646 FILE_CREATE,
6647 0x0,
6648 0x0,
6649 &fnum1,
6650 NULL);
6652 if (!NT_STATUS_IS_OK(status)) {
6653 printf("cli_ntcreate of %s failed (%s)\n",
6654 fname,
6655 nt_errstr(status));
6656 goto out;
6659 status = cli_close(cli1, fnum1);
6660 if (!NT_STATUS_IS_OK(status)) {
6661 printf("cli_close of %s failed (%s)\n",
6662 fname,
6663 nt_errstr(status));
6664 goto out;
6666 fnum1 = (uint16_t)-1;
6668 /* Now create the stream. */
6669 status = cli_ntcreate(cli1,
6670 stream_fname,
6672 FILE_WRITE_DATA,
6674 FILE_SHARE_READ|FILE_SHARE_WRITE,
6675 FILE_CREATE,
6676 0x0,
6677 0x0,
6678 &fnum1,
6679 NULL);
6681 if (!NT_STATUS_IS_OK(status)) {
6682 printf("cli_ntcreate of %s failed (%s)\n",
6683 stream_fname,
6684 nt_errstr(status));
6685 goto out;
6688 /* Leave the stream handle open... */
6690 /* POSIX unlink should fail. */
6691 status = cli_posix_unlink(cli2, fname);
6692 if (NT_STATUS_IS_OK(status)) {
6693 printf("cli_posix_unlink of %s succeeded, should have failed\n",
6694 fname);
6695 goto out;
6698 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6699 printf("cli_posix_unlink of %s failed with (%s) "
6700 "should have been NT_STATUS_SHARING_VIOLATION\n",
6701 fname,
6702 nt_errstr(status));
6703 goto out;
6706 /* Close the stream handle. */
6707 status = cli_close(cli1, fnum1);
6708 if (!NT_STATUS_IS_OK(status)) {
6709 printf("cli_close of %s failed (%s)\n",
6710 stream_fname,
6711 nt_errstr(status));
6712 goto out;
6714 fnum1 = (uint16_t)-1;
6716 /* POSIX unlink after stream handle closed should succeed. */
6717 status = cli_posix_unlink(cli2, fname);
6718 if (!NT_STATUS_IS_OK(status)) {
6719 printf("cli_posix_unlink of %s failed (%s)\n",
6720 fname,
6721 nt_errstr(status));
6722 goto out;
6725 printf("POSIX stream delete test passed\n");
6726 correct = true;
6728 out:
6730 if (fnum1 != (uint16_t)-1) {
6731 cli_close(cli1, fnum1);
6732 fnum1 = (uint16_t)-1;
6735 cli_setatr(cli1, fname, 0, 0);
6736 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6738 if (!torture_close_connection(cli1)) {
6739 correct = false;
6741 if (!torture_close_connection(cli2)) {
6742 correct = false;
6745 TALLOC_FREE(frame);
6746 return correct;
6750 Test setting EA's are rejected on symlinks.
6752 static bool run_ea_symlink_test(int dummy)
6754 static struct cli_state *cli;
6755 const char *fname = "posix_file_ea";
6756 const char *sname = "posix_symlink_ea";
6757 const char *ea_name = "testea_name";
6758 const char *ea_value = "testea_value";
6759 uint16_t fnum = (uint16_t)-1;
6760 bool correct = false;
6761 NTSTATUS status;
6762 size_t i, num_eas;
6763 struct ea_struct *eas = NULL;
6764 TALLOC_CTX *frame = NULL;
6766 frame = talloc_stackframe();
6768 printf("Starting EA symlink test\n");
6770 if (!torture_open_connection(&cli, 0)) {
6771 TALLOC_FREE(frame);
6772 return false;
6775 smbXcli_conn_set_sockopt(cli->conn, sockops);
6777 status = torture_setup_unix_extensions(cli);
6778 if (!NT_STATUS_IS_OK(status)) {
6779 TALLOC_FREE(frame);
6780 return false;
6783 cli_setatr(cli, fname, 0, 0);
6784 cli_posix_unlink(cli, fname);
6785 cli_setatr(cli, sname, 0, 0);
6786 cli_posix_unlink(cli, sname);
6788 status = cli_ntcreate(cli,
6789 fname,
6791 READ_CONTROL_ACCESS,
6793 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6794 FILE_CREATE,
6795 0x0,
6796 0x0,
6797 &fnum,
6798 NULL);
6800 if (!NT_STATUS_IS_OK(status)) {
6801 printf("cli_ntcreate of %s failed (%s)\n",
6802 fname,
6803 nt_errstr(status));
6804 goto out;
6807 status = cli_close(cli, fnum);
6808 if (!NT_STATUS_IS_OK(status)) {
6809 printf("close failed (%s)\n",
6810 nt_errstr(status));
6811 goto out;
6813 fnum = (uint16_t)-1;
6815 /* Set an EA on the path. */
6816 status = cli_set_ea_path(cli,
6817 fname,
6818 ea_name,
6819 ea_value,
6820 strlen(ea_value)+1);
6822 if (!NT_STATUS_IS_OK(status)) {
6823 printf("cli_set_ea_path failed (%s)\n",
6824 nt_errstr(status));
6825 goto out;
6828 /* Now create a symlink. */
6829 status = cli_posix_symlink(cli, fname, sname);
6830 if (!NT_STATUS_IS_OK(status)) {
6831 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
6832 sname,
6833 fname,
6834 nt_errstr(status));
6835 goto out;
6838 /* Get the EA list on the path. Should return value set. */
6839 status = cli_get_ea_list_path(cli,
6840 fname,
6841 frame,
6842 &num_eas,
6843 &eas);
6845 if (!NT_STATUS_IS_OK(status)) {
6846 printf("cli_get_ea_list_path failed (%s)\n",
6847 nt_errstr(status));
6848 goto out;
6851 /* Ensure the EA we set is there. */
6852 for (i=0; i<num_eas; i++) {
6853 if (strcmp(eas[i].name, ea_name) == 0 &&
6854 eas[i].value.length == strlen(ea_value)+1 &&
6855 memcmp(eas[i].value.data,
6856 ea_value,
6857 eas[i].value.length) == 0) {
6858 break;
6862 if (i == num_eas) {
6863 printf("Didn't find EA on pathname %s\n",
6864 fname);
6865 goto out;
6868 num_eas = 0;
6869 TALLOC_FREE(eas);
6871 /* Get the EA list on the symlink. Should return empty list. */
6872 status = cli_get_ea_list_path(cli,
6873 sname,
6874 frame,
6875 &num_eas,
6876 &eas);
6878 if (!NT_STATUS_IS_OK(status)) {
6879 printf("cli_get_ea_list_path failed (%s)\n",
6880 nt_errstr(status));
6881 goto out;
6884 if (num_eas != 0) {
6885 printf("cli_get_ea_list_path failed (%s)\n",
6886 nt_errstr(status));
6887 goto out;
6890 /* Set an EA on the symlink. Should fail. */
6891 status = cli_set_ea_path(cli,
6892 sname,
6893 ea_name,
6894 ea_value,
6895 strlen(ea_value)+1);
6897 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6898 printf("cli_set_ea_path on a symlink gave %s. "
6899 "Should be NT_STATUS_ACCESS_DENIED.\n",
6900 nt_errstr(status));
6901 goto out;
6904 printf("EA symlink test passed\n");
6905 correct = true;
6907 out:
6909 if (fnum != (uint16_t)-1) {
6910 cli_close(cli, fnum);
6911 fnum = (uint16_t)-1;
6914 cli_setatr(cli, sname, 0, 0);
6915 cli_posix_unlink(cli, sname);
6916 cli_setatr(cli, fname, 0, 0);
6917 cli_posix_unlink(cli, fname);
6919 if (!torture_close_connection(cli)) {
6920 correct = false;
6923 TALLOC_FREE(frame);
6924 return correct;
6928 Test POSIX locks are OFD-locks.
6930 static bool run_posix_ofd_lock_test(int dummy)
6932 static struct cli_state *cli;
6933 const char *fname = "posix_file";
6934 uint16_t fnum1 = (uint16_t)-1;
6935 uint16_t fnum2 = (uint16_t)-1;
6936 bool correct = false;
6937 NTSTATUS status;
6938 TALLOC_CTX *frame = NULL;
6940 frame = talloc_stackframe();
6942 printf("Starting POSIX ofd-lock test\n");
6944 if (!torture_open_connection(&cli, 0)) {
6945 TALLOC_FREE(frame);
6946 return false;
6949 smbXcli_conn_set_sockopt(cli->conn, sockops);
6951 status = torture_setup_unix_extensions(cli);
6952 if (!NT_STATUS_IS_OK(status)) {
6953 TALLOC_FREE(frame);
6954 return false;
6957 cli_setatr(cli, fname, 0, 0);
6958 cli_posix_unlink(cli, fname);
6960 /* Open the file twice. */
6961 status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
6962 0600, &fnum1);
6963 if (!NT_STATUS_IS_OK(status)) {
6964 printf("First POSIX open of %s failed\n", fname);
6965 goto out;
6968 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
6969 if (!NT_STATUS_IS_OK(status)) {
6970 printf("First POSIX open of %s failed\n", fname);
6971 goto out;
6974 /* Set a 0-50 lock on fnum1. */
6975 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
6976 if (!NT_STATUS_IS_OK(status)) {
6977 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
6978 goto out;
6981 /* Set a 60-100 lock on fnum2. */
6982 status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
6983 if (!NT_STATUS_IS_OK(status)) {
6984 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
6985 goto out;
6988 /* close fnum1 - 0-50 lock should go away. */
6989 status = cli_close(cli, fnum1);
6990 if (!NT_STATUS_IS_OK(status)) {
6991 printf("close failed (%s)\n",
6992 nt_errstr(status));
6993 goto out;
6995 fnum1 = (uint16_t)-1;
6997 /* Change the lock context. */
6998 cli_setpid(cli, cli_getpid(cli) + 1);
7000 /* Re-open fnum1. */
7001 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
7002 if (!NT_STATUS_IS_OK(status)) {
7003 printf("Third POSIX open of %s failed\n", fname);
7004 goto out;
7007 /* 60-100 lock should still be there. */
7008 status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
7009 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
7010 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
7011 goto out;
7014 /* 0-50 lock should be gone. */
7015 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
7016 if (!NT_STATUS_IS_OK(status)) {
7017 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
7018 goto out;
7021 printf("POSIX OFD lock test passed\n");
7022 correct = true;
7024 out:
7026 if (fnum1 != (uint16_t)-1) {
7027 cli_close(cli, fnum1);
7028 fnum1 = (uint16_t)-1;
7030 if (fnum2 != (uint16_t)-1) {
7031 cli_close(cli, fnum2);
7032 fnum2 = (uint16_t)-1;
7035 cli_setatr(cli, fname, 0, 0);
7036 cli_posix_unlink(cli, fname);
7038 if (!torture_close_connection(cli)) {
7039 correct = false;
7042 TALLOC_FREE(frame);
7043 return correct;
7046 static uint32_t open_attrs_table[] = {
7047 FILE_ATTRIBUTE_NORMAL,
7048 FILE_ATTRIBUTE_ARCHIVE,
7049 FILE_ATTRIBUTE_READONLY,
7050 FILE_ATTRIBUTE_HIDDEN,
7051 FILE_ATTRIBUTE_SYSTEM,
7053 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
7054 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
7055 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
7056 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
7057 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
7058 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
7060 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
7061 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
7062 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
7063 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
7066 struct trunc_open_results {
7067 unsigned int num;
7068 uint32_t init_attr;
7069 uint32_t trunc_attr;
7070 uint32_t result_attr;
7073 static struct trunc_open_results attr_results[] = {
7074 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
7075 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
7076 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
7077 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
7078 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
7079 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
7080 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7081 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7082 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
7083 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7084 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7085 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
7086 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7087 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7088 { 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 },
7089 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7090 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7091 { 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 },
7092 { 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 },
7093 { 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 },
7094 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7095 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7096 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
7097 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7098 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7099 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
7102 static bool run_openattrtest(int dummy)
7104 static struct cli_state *cli1;
7105 const char *fname = "\\openattr.file";
7106 uint16_t fnum1;
7107 bool correct = True;
7108 uint16_t attr;
7109 unsigned int i, j, k, l;
7110 NTSTATUS status;
7112 printf("starting open attr test\n");
7114 if (!torture_open_connection(&cli1, 0)) {
7115 return False;
7118 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7120 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
7121 cli_setatr(cli1, fname, 0, 0);
7122 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7124 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
7125 open_attrs_table[i], FILE_SHARE_NONE,
7126 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7127 if (!NT_STATUS_IS_OK(status)) {
7128 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
7129 return False;
7132 status = cli_close(cli1, fnum1);
7133 if (!NT_STATUS_IS_OK(status)) {
7134 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
7135 return False;
7138 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
7139 status = cli_ntcreate(cli1, fname, 0,
7140 FILE_READ_DATA|FILE_WRITE_DATA,
7141 open_attrs_table[j],
7142 FILE_SHARE_NONE, FILE_OVERWRITE,
7143 0, 0, &fnum1, NULL);
7144 if (!NT_STATUS_IS_OK(status)) {
7145 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
7146 if (attr_results[l].num == k) {
7147 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
7148 k, open_attrs_table[i],
7149 open_attrs_table[j],
7150 fname, NT_STATUS_V(status), nt_errstr(status));
7151 correct = False;
7155 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7156 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
7157 k, open_attrs_table[i], open_attrs_table[j],
7158 nt_errstr(status));
7159 correct = False;
7161 #if 0
7162 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
7163 #endif
7164 k++;
7165 continue;
7168 status = cli_close(cli1, fnum1);
7169 if (!NT_STATUS_IS_OK(status)) {
7170 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
7171 return False;
7174 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
7175 if (!NT_STATUS_IS_OK(status)) {
7176 printf("getatr(2) failed (%s)\n", nt_errstr(status));
7177 return False;
7180 #if 0
7181 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
7182 k, open_attrs_table[i], open_attrs_table[j], attr );
7183 #endif
7185 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
7186 if (attr_results[l].num == k) {
7187 if (attr != attr_results[l].result_attr ||
7188 open_attrs_table[i] != attr_results[l].init_attr ||
7189 open_attrs_table[j] != attr_results[l].trunc_attr) {
7190 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
7191 open_attrs_table[i],
7192 open_attrs_table[j],
7193 (unsigned int)attr,
7194 attr_results[l].result_attr);
7195 correct = False;
7197 break;
7200 k++;
7204 cli_setatr(cli1, fname, 0, 0);
7205 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7207 printf("open attr test %s.\n", correct ? "passed" : "failed");
7209 if (!torture_close_connection(cli1)) {
7210 correct = False;
7212 return correct;
7215 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
7216 const char *name, void *state)
7218 int *matched = (int *)state;
7219 if (matched != NULL) {
7220 *matched += 1;
7222 return NT_STATUS_OK;
7226 test directory listing speed
7228 static bool run_dirtest(int dummy)
7230 int i;
7231 static struct cli_state *cli;
7232 uint16_t fnum;
7233 struct timeval core_start;
7234 bool correct = True;
7235 int matched;
7237 printf("starting directory test\n");
7239 if (!torture_open_connection(&cli, 0)) {
7240 return False;
7243 smbXcli_conn_set_sockopt(cli->conn, sockops);
7245 srandom(0);
7246 for (i=0;i<torture_numops;i++) {
7247 fstring fname;
7248 slprintf(fname, sizeof(fname), "\\%x", (int)random());
7249 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
7250 fprintf(stderr,"Failed to open %s\n", fname);
7251 return False;
7253 cli_close(cli, fnum);
7256 core_start = timeval_current();
7258 matched = 0;
7259 cli_list(cli, "a*.*", 0, list_fn, &matched);
7260 printf("Matched %d\n", matched);
7262 matched = 0;
7263 cli_list(cli, "b*.*", 0, list_fn, &matched);
7264 printf("Matched %d\n", matched);
7266 matched = 0;
7267 cli_list(cli, "xyzabc", 0, list_fn, &matched);
7268 printf("Matched %d\n", matched);
7270 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
7272 srandom(0);
7273 for (i=0;i<torture_numops;i++) {
7274 fstring fname;
7275 slprintf(fname, sizeof(fname), "\\%x", (int)random());
7276 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7279 if (!torture_close_connection(cli)) {
7280 correct = False;
7283 printf("finished dirtest\n");
7285 return correct;
7288 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
7289 void *state)
7291 struct cli_state *pcli = (struct cli_state *)state;
7292 fstring fname;
7293 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
7295 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7296 return NT_STATUS_OK;
7298 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7299 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
7300 printf("del_fn: failed to rmdir %s\n,", fname );
7301 } else {
7302 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
7303 printf("del_fn: failed to unlink %s\n,", fname );
7305 return NT_STATUS_OK;
7310 sees what IOCTLs are supported
7312 bool torture_ioctl_test(int dummy)
7314 static struct cli_state *cli;
7315 uint16_t device, function;
7316 uint16_t fnum;
7317 const char *fname = "\\ioctl.dat";
7318 DATA_BLOB blob;
7319 NTSTATUS status;
7321 if (!torture_open_connection(&cli, 0)) {
7322 return False;
7325 printf("starting ioctl test\n");
7327 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7329 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7330 if (!NT_STATUS_IS_OK(status)) {
7331 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7332 return False;
7335 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
7336 printf("ioctl device info: %s\n", nt_errstr(status));
7338 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
7339 printf("ioctl job info: %s\n", nt_errstr(status));
7341 for (device=0;device<0x100;device++) {
7342 printf("ioctl test with device = 0x%x\n", device);
7343 for (function=0;function<0x100;function++) {
7344 uint32_t code = (device<<16) | function;
7346 status = cli_raw_ioctl(cli, fnum, code, &blob);
7348 if (NT_STATUS_IS_OK(status)) {
7349 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
7350 (int)blob.length);
7351 data_blob_free(&blob);
7356 if (!torture_close_connection(cli)) {
7357 return False;
7360 return True;
7365 tries varients of chkpath
7367 bool torture_chkpath_test(int dummy)
7369 static struct cli_state *cli;
7370 uint16_t fnum;
7371 bool ret;
7372 NTSTATUS status;
7374 if (!torture_open_connection(&cli, 0)) {
7375 return False;
7378 printf("starting chkpath test\n");
7380 /* cleanup from an old run */
7381 cli_rmdir(cli, "\\chkpath.dir\\dir2");
7382 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7383 cli_rmdir(cli, "\\chkpath.dir");
7385 status = cli_mkdir(cli, "\\chkpath.dir");
7386 if (!NT_STATUS_IS_OK(status)) {
7387 printf("mkdir1 failed : %s\n", nt_errstr(status));
7388 return False;
7391 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
7392 if (!NT_STATUS_IS_OK(status)) {
7393 printf("mkdir2 failed : %s\n", nt_errstr(status));
7394 return False;
7397 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
7398 DENY_NONE, &fnum);
7399 if (!NT_STATUS_IS_OK(status)) {
7400 printf("open1 failed (%s)\n", nt_errstr(status));
7401 return False;
7403 cli_close(cli, fnum);
7405 status = cli_chkpath(cli, "\\chkpath.dir");
7406 if (!NT_STATUS_IS_OK(status)) {
7407 printf("chkpath1 failed: %s\n", nt_errstr(status));
7408 ret = False;
7411 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
7412 if (!NT_STATUS_IS_OK(status)) {
7413 printf("chkpath2 failed: %s\n", nt_errstr(status));
7414 ret = False;
7417 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
7418 if (!NT_STATUS_IS_OK(status)) {
7419 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
7420 NT_STATUS_NOT_A_DIRECTORY);
7421 } else {
7422 printf("* chkpath on a file should fail\n");
7423 ret = False;
7426 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
7427 if (!NT_STATUS_IS_OK(status)) {
7428 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
7429 NT_STATUS_OBJECT_NAME_NOT_FOUND);
7430 } else {
7431 printf("* chkpath on a non existent file should fail\n");
7432 ret = False;
7435 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
7436 if (!NT_STATUS_IS_OK(status)) {
7437 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
7438 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7439 } else {
7440 printf("* chkpath on a non existent component should fail\n");
7441 ret = False;
7444 cli_rmdir(cli, "\\chkpath.dir\\dir2");
7445 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7446 cli_rmdir(cli, "\\chkpath.dir");
7448 if (!torture_close_connection(cli)) {
7449 return False;
7452 return ret;
7455 static bool run_eatest(int dummy)
7457 static struct cli_state *cli;
7458 const char *fname = "\\eatest.txt";
7459 bool correct = True;
7460 uint16_t fnum;
7461 int i;
7462 size_t num_eas;
7463 struct ea_struct *ea_list = NULL;
7464 TALLOC_CTX *mem_ctx = talloc_init("eatest");
7465 NTSTATUS status;
7467 printf("starting eatest\n");
7469 if (!torture_open_connection(&cli, 0)) {
7470 talloc_destroy(mem_ctx);
7471 return False;
7474 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7476 status = cli_ntcreate(cli, fname, 0,
7477 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
7478 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
7479 0x4044, 0, &fnum, NULL);
7480 if (!NT_STATUS_IS_OK(status)) {
7481 printf("open failed - %s\n", nt_errstr(status));
7482 talloc_destroy(mem_ctx);
7483 return False;
7486 for (i = 0; i < 10; i++) {
7487 fstring ea_name, ea_val;
7489 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
7490 memset(ea_val, (char)i+1, i+1);
7491 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
7492 if (!NT_STATUS_IS_OK(status)) {
7493 printf("ea_set of name %s failed - %s\n", ea_name,
7494 nt_errstr(status));
7495 talloc_destroy(mem_ctx);
7496 return False;
7500 cli_close(cli, fnum);
7501 for (i = 0; i < 10; i++) {
7502 fstring ea_name, ea_val;
7504 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
7505 memset(ea_val, (char)i+1, i+1);
7506 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
7507 if (!NT_STATUS_IS_OK(status)) {
7508 printf("ea_set of name %s failed - %s\n", ea_name,
7509 nt_errstr(status));
7510 talloc_destroy(mem_ctx);
7511 return False;
7515 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
7516 if (!NT_STATUS_IS_OK(status)) {
7517 printf("ea_get list failed - %s\n", nt_errstr(status));
7518 correct = False;
7521 printf("num_eas = %d\n", (int)num_eas);
7523 if (num_eas != 20) {
7524 printf("Should be 20 EA's stored... failing.\n");
7525 correct = False;
7528 for (i = 0; i < num_eas; i++) {
7529 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
7530 dump_data(0, ea_list[i].value.data,
7531 ea_list[i].value.length);
7534 /* Setting EA's to zero length deletes them. Test this */
7535 printf("Now deleting all EA's - case indepenent....\n");
7537 #if 1
7538 cli_set_ea_path(cli, fname, "", "", 0);
7539 #else
7540 for (i = 0; i < 20; i++) {
7541 fstring ea_name;
7542 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
7543 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
7544 if (!NT_STATUS_IS_OK(status)) {
7545 printf("ea_set of name %s failed - %s\n", ea_name,
7546 nt_errstr(status));
7547 talloc_destroy(mem_ctx);
7548 return False;
7551 #endif
7553 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
7554 if (!NT_STATUS_IS_OK(status)) {
7555 printf("ea_get list failed - %s\n", nt_errstr(status));
7556 correct = False;
7559 printf("num_eas = %d\n", (int)num_eas);
7560 for (i = 0; i < num_eas; i++) {
7561 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
7562 dump_data(0, ea_list[i].value.data,
7563 ea_list[i].value.length);
7566 if (num_eas != 0) {
7567 printf("deleting EA's failed.\n");
7568 correct = False;
7571 /* Try and delete a non existent EA. */
7572 status = cli_set_ea_path(cli, fname, "foo", "", 0);
7573 if (!NT_STATUS_IS_OK(status)) {
7574 printf("deleting non-existent EA 'foo' should succeed. %s\n",
7575 nt_errstr(status));
7576 correct = False;
7579 talloc_destroy(mem_ctx);
7580 if (!torture_close_connection(cli)) {
7581 correct = False;
7584 return correct;
7587 static bool run_dirtest1(int dummy)
7589 int i;
7590 static struct cli_state *cli;
7591 uint16_t fnum;
7592 int num_seen;
7593 bool correct = True;
7595 printf("starting directory test\n");
7597 if (!torture_open_connection(&cli, 0)) {
7598 return False;
7601 smbXcli_conn_set_sockopt(cli->conn, sockops);
7603 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
7604 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
7605 cli_rmdir(cli, "\\LISTDIR");
7606 cli_mkdir(cli, "\\LISTDIR");
7608 /* Create 1000 files and 1000 directories. */
7609 for (i=0;i<1000;i++) {
7610 fstring fname;
7611 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
7612 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
7613 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
7614 0, 0, &fnum, NULL))) {
7615 fprintf(stderr,"Failed to open %s\n", fname);
7616 return False;
7618 cli_close(cli, fnum);
7620 for (i=0;i<1000;i++) {
7621 fstring fname;
7622 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
7623 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
7624 fprintf(stderr,"Failed to open %s\n", fname);
7625 return False;
7629 /* Now ensure that doing an old list sees both files and directories. */
7630 num_seen = 0;
7631 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7632 printf("num_seen = %d\n", num_seen );
7633 /* We should see 100 files + 1000 directories + . and .. */
7634 if (num_seen != 2002)
7635 correct = False;
7637 /* Ensure if we have the "must have" bits we only see the
7638 * relevent entries.
7640 num_seen = 0;
7641 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7642 printf("num_seen = %d\n", num_seen );
7643 if (num_seen != 1002)
7644 correct = False;
7646 num_seen = 0;
7647 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7648 printf("num_seen = %d\n", num_seen );
7649 if (num_seen != 1000)
7650 correct = False;
7652 /* Delete everything. */
7653 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
7654 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
7655 cli_rmdir(cli, "\\LISTDIR");
7657 #if 0
7658 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
7659 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
7660 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
7661 #endif
7663 if (!torture_close_connection(cli)) {
7664 correct = False;
7667 printf("finished dirtest1\n");
7669 return correct;
7672 static bool run_error_map_extract(int dummy) {
7674 static struct cli_state *c_dos;
7675 static struct cli_state *c_nt;
7676 NTSTATUS status;
7678 uint32_t error;
7680 uint32_t errnum;
7681 uint8_t errclass;
7683 NTSTATUS nt_status;
7685 fstring user;
7687 /* NT-Error connection */
7689 disable_spnego = true;
7690 if (!(c_nt = open_nbt_connection())) {
7691 disable_spnego = false;
7692 return False;
7694 disable_spnego = false;
7696 status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
7697 PROTOCOL_NT1);
7699 if (!NT_STATUS_IS_OK(status)) {
7700 printf("%s rejected the NT-error negprot (%s)\n", host,
7701 nt_errstr(status));
7702 cli_shutdown(c_nt);
7703 return False;
7706 status = cli_session_setup_anon(c_nt);
7707 if (!NT_STATUS_IS_OK(status)) {
7708 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
7709 return False;
7712 /* DOS-Error connection */
7714 disable_spnego = true;
7715 force_dos_errors = true;
7716 if (!(c_dos = open_nbt_connection())) {
7717 disable_spnego = false;
7718 force_dos_errors = false;
7719 return False;
7721 disable_spnego = false;
7722 force_dos_errors = false;
7724 status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
7725 PROTOCOL_NT1);
7726 if (!NT_STATUS_IS_OK(status)) {
7727 printf("%s rejected the DOS-error negprot (%s)\n", host,
7728 nt_errstr(status));
7729 cli_shutdown(c_dos);
7730 return False;
7733 status = cli_session_setup_anon(c_dos);
7734 if (!NT_STATUS_IS_OK(status)) {
7735 printf("%s rejected the DOS-error initial session setup (%s)\n",
7736 host, nt_errstr(status));
7737 return False;
7740 c_nt->map_dos_errors = false;
7741 c_dos->map_dos_errors = false;
7743 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
7744 struct cli_credentials *user_creds = NULL;
7746 fstr_sprintf(user, "%X", error);
7748 user_creds = cli_session_creds_init(talloc_tos(),
7749 user,
7750 workgroup,
7751 NULL, /* realm */
7752 password,
7753 false, /* use_kerberos */
7754 false, /* fallback_after_kerberos */
7755 false, /* use_ccache */
7756 false); /* password_is_nt_hash */
7757 if (user_creds == NULL) {
7758 printf("cli_session_creds_init(%s) failed\n", user);
7759 return false;
7762 status = cli_session_setup_creds(c_nt, user_creds);
7763 if (NT_STATUS_IS_OK(status)) {
7764 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
7767 /* Case #1: 32-bit NT errors */
7768 if (!NT_STATUS_IS_DOS(status)) {
7769 nt_status = status;
7770 } else {
7771 printf("/** Dos error on NT connection! (%s) */\n",
7772 nt_errstr(status));
7773 nt_status = NT_STATUS(0xc0000000);
7776 status = cli_session_setup_creds(c_dos, user_creds);
7777 if (NT_STATUS_IS_OK(status)) {
7778 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
7781 /* Case #1: 32-bit NT errors */
7782 if (NT_STATUS_IS_DOS(status)) {
7783 printf("/** NT error on DOS connection! (%s) */\n",
7784 nt_errstr(status));
7785 errnum = errclass = 0;
7786 } else {
7787 errclass = NT_STATUS_DOS_CLASS(status);
7788 errnum = NT_STATUS_DOS_CODE(status);
7791 if (NT_STATUS_V(nt_status) != error) {
7792 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
7793 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
7794 get_nt_error_c_code(talloc_tos(), nt_status));
7797 printf("\t{%s,\t%s,\t%s},\n",
7798 smb_dos_err_class(errclass),
7799 smb_dos_err_name(errclass, errnum),
7800 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
7802 TALLOC_FREE(user_creds);
7804 return True;
7807 static bool run_sesssetup_bench(int dummy)
7809 static struct cli_state *c;
7810 const char *fname = "\\file.dat";
7811 uint16_t fnum;
7812 NTSTATUS status;
7813 int i;
7815 if (!torture_open_connection(&c, 0)) {
7816 return false;
7819 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7820 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7821 FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
7822 if (!NT_STATUS_IS_OK(status)) {
7823 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7824 return false;
7827 for (i=0; i<torture_numops; i++) {
7828 status = cli_session_setup_creds(c, torture_creds);
7829 if (!NT_STATUS_IS_OK(status)) {
7830 d_printf("(%s) cli_session_setup_creds failed: %s\n",
7831 __location__, nt_errstr(status));
7832 return false;
7835 d_printf("\r%d ", (int)cli_state_get_uid(c));
7837 status = cli_ulogoff(c);
7838 if (!NT_STATUS_IS_OK(status)) {
7839 d_printf("(%s) cli_ulogoff failed: %s\n",
7840 __location__, nt_errstr(status));
7841 return false;
7845 return true;
7848 static bool subst_test(const char *str, const char *user, const char *domain,
7849 uid_t uid, gid_t gid, const char *expected)
7851 char *subst;
7852 bool result = true;
7854 subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
7856 if (strcmp(subst, expected) != 0) {
7857 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
7858 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
7859 expected);
7860 result = false;
7863 TALLOC_FREE(subst);
7864 return result;
7867 static void chain1_open_completion(struct tevent_req *req)
7869 uint16_t fnum;
7870 NTSTATUS status;
7871 status = cli_openx_recv(req, &fnum);
7872 TALLOC_FREE(req);
7874 d_printf("cli_openx_recv returned %s: %d\n",
7875 nt_errstr(status),
7876 NT_STATUS_IS_OK(status) ? fnum : -1);
7879 static void chain1_write_completion(struct tevent_req *req)
7881 size_t written;
7882 NTSTATUS status;
7883 status = cli_write_andx_recv(req, &written);
7884 TALLOC_FREE(req);
7886 d_printf("cli_write_andx_recv returned %s: %d\n",
7887 nt_errstr(status),
7888 NT_STATUS_IS_OK(status) ? (int)written : -1);
7891 static void chain1_close_completion(struct tevent_req *req)
7893 NTSTATUS status;
7894 bool *done = (bool *)tevent_req_callback_data_void(req);
7896 status = cli_close_recv(req);
7897 *done = true;
7899 TALLOC_FREE(req);
7901 d_printf("cli_close returned %s\n", nt_errstr(status));
7904 static bool run_chain1(int dummy)
7906 struct cli_state *cli1;
7907 struct tevent_context *evt = samba_tevent_context_init(NULL);
7908 struct tevent_req *reqs[3], *smbreqs[3];
7909 bool done = false;
7910 const char *str = "foobar";
7911 NTSTATUS status;
7913 printf("starting chain1 test\n");
7914 if (!torture_open_connection(&cli1, 0)) {
7915 return False;
7918 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7920 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, "\\test",
7921 O_CREAT|O_RDWR, 0, &smbreqs[0]);
7922 if (reqs[0] == NULL) return false;
7923 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
7926 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
7927 (const uint8_t *)str, 0, strlen(str)+1,
7928 smbreqs, 1, &smbreqs[1]);
7929 if (reqs[1] == NULL) return false;
7930 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
7932 reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
7933 if (reqs[2] == NULL) return false;
7934 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
7936 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
7937 if (!NT_STATUS_IS_OK(status)) {
7938 return false;
7941 while (!done) {
7942 tevent_loop_once(evt);
7945 torture_close_connection(cli1);
7946 return True;
7949 static void chain2_sesssetup_completion(struct tevent_req *req)
7951 NTSTATUS status;
7952 status = cli_session_setup_guest_recv(req);
7953 d_printf("sesssetup returned %s\n", nt_errstr(status));
7956 static void chain2_tcon_completion(struct tevent_req *req)
7958 bool *done = (bool *)tevent_req_callback_data_void(req);
7959 NTSTATUS status;
7960 status = cli_tcon_andx_recv(req);
7961 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
7962 *done = true;
7965 static bool run_chain2(int dummy)
7967 struct cli_state *cli1;
7968 struct tevent_context *evt = samba_tevent_context_init(NULL);
7969 struct tevent_req *reqs[2], *smbreqs[2];
7970 bool done = false;
7971 NTSTATUS status;
7972 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
7974 printf("starting chain2 test\n");
7975 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
7976 port_to_use, SMB_SIGNING_DEFAULT, flags);
7977 if (!NT_STATUS_IS_OK(status)) {
7978 return False;
7981 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7983 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
7984 &smbreqs[0]);
7985 if (reqs[0] == NULL) return false;
7986 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
7988 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
7989 "?????", NULL, 0, &smbreqs[1]);
7990 if (reqs[1] == NULL) return false;
7991 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
7993 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
7994 if (!NT_STATUS_IS_OK(status)) {
7995 return false;
7998 while (!done) {
7999 tevent_loop_once(evt);
8002 torture_close_connection(cli1);
8003 return True;
8007 struct torture_createdel_state {
8008 struct tevent_context *ev;
8009 struct cli_state *cli;
8012 static void torture_createdel_created(struct tevent_req *subreq);
8013 static void torture_createdel_closed(struct tevent_req *subreq);
8015 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
8016 struct tevent_context *ev,
8017 struct cli_state *cli,
8018 const char *name)
8020 struct tevent_req *req, *subreq;
8021 struct torture_createdel_state *state;
8023 req = tevent_req_create(mem_ctx, &state,
8024 struct torture_createdel_state);
8025 if (req == NULL) {
8026 return NULL;
8028 state->ev = ev;
8029 state->cli = cli;
8031 subreq = cli_ntcreate_send(
8032 state, ev, cli, name, 0,
8033 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
8034 FILE_ATTRIBUTE_NORMAL,
8035 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8036 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
8038 if (tevent_req_nomem(subreq, req)) {
8039 return tevent_req_post(req, ev);
8041 tevent_req_set_callback(subreq, torture_createdel_created, req);
8042 return req;
8045 static void torture_createdel_created(struct tevent_req *subreq)
8047 struct tevent_req *req = tevent_req_callback_data(
8048 subreq, struct tevent_req);
8049 struct torture_createdel_state *state = tevent_req_data(
8050 req, struct torture_createdel_state);
8051 NTSTATUS status;
8052 uint16_t fnum;
8054 status = cli_ntcreate_recv(subreq, &fnum, NULL);
8055 TALLOC_FREE(subreq);
8056 if (tevent_req_nterror(req, status)) {
8057 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
8058 nt_errstr(status)));
8059 return;
8062 subreq = cli_close_send(state, state->ev, state->cli, fnum);
8063 if (tevent_req_nomem(subreq, req)) {
8064 return;
8066 tevent_req_set_callback(subreq, torture_createdel_closed, req);
8069 static void torture_createdel_closed(struct tevent_req *subreq)
8071 struct tevent_req *req = tevent_req_callback_data(
8072 subreq, struct tevent_req);
8073 NTSTATUS status;
8075 status = cli_close_recv(subreq);
8076 if (tevent_req_nterror(req, status)) {
8077 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
8078 return;
8080 tevent_req_done(req);
8083 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
8085 return tevent_req_simple_recv_ntstatus(req);
8088 struct torture_createdels_state {
8089 struct tevent_context *ev;
8090 struct cli_state *cli;
8091 const char *base_name;
8092 int sent;
8093 int received;
8094 int num_files;
8095 struct tevent_req **reqs;
8098 static void torture_createdels_done(struct tevent_req *subreq);
8100 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
8101 struct tevent_context *ev,
8102 struct cli_state *cli,
8103 const char *base_name,
8104 int num_parallel,
8105 int num_files)
8107 struct tevent_req *req;
8108 struct torture_createdels_state *state;
8109 int i;
8111 req = tevent_req_create(mem_ctx, &state,
8112 struct torture_createdels_state);
8113 if (req == NULL) {
8114 return NULL;
8116 state->ev = ev;
8117 state->cli = cli;
8118 state->base_name = talloc_strdup(state, base_name);
8119 if (tevent_req_nomem(state->base_name, req)) {
8120 return tevent_req_post(req, ev);
8122 state->num_files = MAX(num_parallel, num_files);
8123 state->sent = 0;
8124 state->received = 0;
8126 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
8127 if (tevent_req_nomem(state->reqs, req)) {
8128 return tevent_req_post(req, ev);
8131 for (i=0; i<num_parallel; i++) {
8132 char *name;
8134 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
8135 state->sent);
8136 if (tevent_req_nomem(name, req)) {
8137 return tevent_req_post(req, ev);
8139 state->reqs[i] = torture_createdel_send(
8140 state->reqs, state->ev, state->cli, name);
8141 if (tevent_req_nomem(state->reqs[i], req)) {
8142 return tevent_req_post(req, ev);
8144 name = talloc_move(state->reqs[i], &name);
8145 tevent_req_set_callback(state->reqs[i],
8146 torture_createdels_done, req);
8147 state->sent += 1;
8149 return req;
8152 static void torture_createdels_done(struct tevent_req *subreq)
8154 struct tevent_req *req = tevent_req_callback_data(
8155 subreq, struct tevent_req);
8156 struct torture_createdels_state *state = tevent_req_data(
8157 req, struct torture_createdels_state);
8158 size_t num_parallel = talloc_array_length(state->reqs);
8159 NTSTATUS status;
8160 char *name;
8161 int i;
8163 status = torture_createdel_recv(subreq);
8164 if (!NT_STATUS_IS_OK(status)){
8165 DEBUG(10, ("torture_createdel_recv returned %s\n",
8166 nt_errstr(status)));
8167 TALLOC_FREE(subreq);
8168 tevent_req_nterror(req, status);
8169 return;
8172 for (i=0; i<num_parallel; i++) {
8173 if (subreq == state->reqs[i]) {
8174 break;
8177 if (i == num_parallel) {
8178 DEBUG(10, ("received something we did not send\n"));
8179 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
8180 return;
8182 TALLOC_FREE(state->reqs[i]);
8184 if (state->sent >= state->num_files) {
8185 tevent_req_done(req);
8186 return;
8189 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
8190 state->sent);
8191 if (tevent_req_nomem(name, req)) {
8192 return;
8194 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
8195 state->cli, name);
8196 if (tevent_req_nomem(state->reqs[i], req)) {
8197 return;
8199 name = talloc_move(state->reqs[i], &name);
8200 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
8201 state->sent += 1;
8204 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
8206 return tevent_req_simple_recv_ntstatus(req);
8209 struct swallow_notify_state {
8210 struct tevent_context *ev;
8211 struct cli_state *cli;
8212 uint16_t fnum;
8213 uint32_t completion_filter;
8214 bool recursive;
8215 bool (*fn)(uint32_t action, const char *name, void *priv);
8216 void *priv;
8219 static void swallow_notify_done(struct tevent_req *subreq);
8221 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
8222 struct tevent_context *ev,
8223 struct cli_state *cli,
8224 uint16_t fnum,
8225 uint32_t completion_filter,
8226 bool recursive,
8227 bool (*fn)(uint32_t action,
8228 const char *name,
8229 void *priv),
8230 void *priv)
8232 struct tevent_req *req, *subreq;
8233 struct swallow_notify_state *state;
8235 req = tevent_req_create(mem_ctx, &state,
8236 struct swallow_notify_state);
8237 if (req == NULL) {
8238 return NULL;
8240 state->ev = ev;
8241 state->cli = cli;
8242 state->fnum = fnum;
8243 state->completion_filter = completion_filter;
8244 state->recursive = recursive;
8245 state->fn = fn;
8246 state->priv = priv;
8248 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
8249 0xffff, state->completion_filter,
8250 state->recursive);
8251 if (tevent_req_nomem(subreq, req)) {
8252 return tevent_req_post(req, ev);
8254 tevent_req_set_callback(subreq, swallow_notify_done, req);
8255 return req;
8258 static void swallow_notify_done(struct tevent_req *subreq)
8260 struct tevent_req *req = tevent_req_callback_data(
8261 subreq, struct tevent_req);
8262 struct swallow_notify_state *state = tevent_req_data(
8263 req, struct swallow_notify_state);
8264 NTSTATUS status;
8265 uint32_t i, num_changes;
8266 struct notify_change *changes;
8268 status = cli_notify_recv(subreq, state, &num_changes, &changes);
8269 TALLOC_FREE(subreq);
8270 if (!NT_STATUS_IS_OK(status)) {
8271 DEBUG(10, ("cli_notify_recv returned %s\n",
8272 nt_errstr(status)));
8273 tevent_req_nterror(req, status);
8274 return;
8277 for (i=0; i<num_changes; i++) {
8278 state->fn(changes[i].action, changes[i].name, state->priv);
8280 TALLOC_FREE(changes);
8282 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
8283 0xffff, state->completion_filter,
8284 state->recursive);
8285 if (tevent_req_nomem(subreq, req)) {
8286 return;
8288 tevent_req_set_callback(subreq, swallow_notify_done, req);
8291 static bool print_notifies(uint32_t action, const char *name, void *priv)
8293 if (DEBUGLEVEL > 5) {
8294 d_printf("%d %s\n", (int)action, name);
8296 return true;
8299 static void notify_bench_done(struct tevent_req *req)
8301 int *num_finished = (int *)tevent_req_callback_data_void(req);
8302 *num_finished += 1;
8305 static bool run_notify_bench(int dummy)
8307 const char *dname = "\\notify-bench";
8308 struct tevent_context *ev;
8309 NTSTATUS status;
8310 uint16_t dnum;
8311 struct tevent_req *req1;
8312 struct tevent_req *req2 = NULL;
8313 int i, num_unc_names;
8314 int num_finished = 0;
8316 printf("starting notify-bench test\n");
8318 if (use_multishare_conn) {
8319 char **unc_list;
8320 unc_list = file_lines_load(multishare_conn_fname,
8321 &num_unc_names, 0, NULL);
8322 if (!unc_list || num_unc_names <= 0) {
8323 d_printf("Failed to load unc names list from '%s'\n",
8324 multishare_conn_fname);
8325 return false;
8327 TALLOC_FREE(unc_list);
8328 } else {
8329 num_unc_names = 1;
8332 ev = samba_tevent_context_init(talloc_tos());
8333 if (ev == NULL) {
8334 d_printf("tevent_context_init failed\n");
8335 return false;
8338 for (i=0; i<num_unc_names; i++) {
8339 struct cli_state *cli;
8340 char *base_fname;
8342 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
8343 dname, i);
8344 if (base_fname == NULL) {
8345 return false;
8348 if (!torture_open_connection(&cli, i)) {
8349 return false;
8352 status = cli_ntcreate(cli, dname, 0,
8353 MAXIMUM_ALLOWED_ACCESS,
8354 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
8355 FILE_SHARE_DELETE,
8356 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
8357 &dnum, NULL);
8359 if (!NT_STATUS_IS_OK(status)) {
8360 d_printf("Could not create %s: %s\n", dname,
8361 nt_errstr(status));
8362 return false;
8365 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
8366 FILE_NOTIFY_CHANGE_FILE_NAME |
8367 FILE_NOTIFY_CHANGE_DIR_NAME |
8368 FILE_NOTIFY_CHANGE_ATTRIBUTES |
8369 FILE_NOTIFY_CHANGE_LAST_WRITE,
8370 false, print_notifies, NULL);
8371 if (req1 == NULL) {
8372 d_printf("Could not create notify request\n");
8373 return false;
8376 req2 = torture_createdels_send(talloc_tos(), ev, cli,
8377 base_fname, 10, torture_numops);
8378 if (req2 == NULL) {
8379 d_printf("Could not create createdels request\n");
8380 return false;
8382 TALLOC_FREE(base_fname);
8384 tevent_req_set_callback(req2, notify_bench_done,
8385 &num_finished);
8388 while (num_finished < num_unc_names) {
8389 int ret;
8390 ret = tevent_loop_once(ev);
8391 if (ret != 0) {
8392 d_printf("tevent_loop_once failed\n");
8393 return false;
8397 if (!tevent_req_poll(req2, ev)) {
8398 d_printf("tevent_req_poll failed\n");
8401 status = torture_createdels_recv(req2);
8402 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
8404 return true;
8407 static bool run_mangle1(int dummy)
8409 struct cli_state *cli;
8410 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
8411 uint16_t fnum;
8412 fstring alt_name;
8413 NTSTATUS status;
8414 time_t change_time, access_time, write_time;
8415 off_t size;
8416 uint16_t mode;
8418 printf("starting mangle1 test\n");
8419 if (!torture_open_connection(&cli, 0)) {
8420 return False;
8423 smbXcli_conn_set_sockopt(cli->conn, sockops);
8425 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8426 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8427 0, 0, &fnum, NULL);
8428 if (!NT_STATUS_IS_OK(status)) {
8429 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8430 return false;
8432 cli_close(cli, fnum);
8434 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
8435 if (!NT_STATUS_IS_OK(status)) {
8436 d_printf("cli_qpathinfo_alt_name failed: %s\n",
8437 nt_errstr(status));
8438 return false;
8440 d_printf("alt_name: %s\n", alt_name);
8442 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
8443 if (!NT_STATUS_IS_OK(status)) {
8444 d_printf("cli_openx(%s) failed: %s\n", alt_name,
8445 nt_errstr(status));
8446 return false;
8448 cli_close(cli, fnum);
8450 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
8451 &write_time, &size, &mode);
8452 if (!NT_STATUS_IS_OK(status)) {
8453 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
8454 nt_errstr(status));
8455 return false;
8458 return true;
8461 static NTSTATUS mangle_illegal_list_shortname_fn(const char *mntpoint,
8462 struct file_info *f,
8463 const char *mask,
8464 void *state)
8466 if (f->short_name == NULL) {
8467 return NT_STATUS_OK;
8470 if (strlen(f->short_name) == 0) {
8471 return NT_STATUS_OK;
8474 printf("unexpected shortname: %s\n", f->short_name);
8476 return NT_STATUS_OBJECT_NAME_INVALID;
8479 static NTSTATUS mangle_illegal_list_name_fn(const char *mntpoint,
8480 struct file_info *f,
8481 const char *mask,
8482 void *state)
8484 char *name = state;
8486 printf("name: %s\n", f->name);
8487 fstrcpy(name, f->name);
8488 return NT_STATUS_OK;
8491 static bool run_mangle_illegal(int dummy)
8493 struct cli_state *cli = NULL;
8494 struct cli_state *cli_posix = NULL;
8495 const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
8496 const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
8497 char *mangled_path = NULL;
8498 uint16_t fnum;
8499 fstring name;
8500 fstring alt_name;
8501 NTSTATUS status;
8503 printf("starting mangle-illegal test\n");
8505 if (!torture_open_connection(&cli, 0)) {
8506 return False;
8509 smbXcli_conn_set_sockopt(cli->conn, sockops);
8511 if (!torture_open_connection(&cli_posix, 0)) {
8512 return false;
8515 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
8517 status = torture_setup_unix_extensions(cli_posix);
8518 if (!NT_STATUS_IS_OK(status)) {
8519 return false;
8522 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
8523 status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
8524 if (!NT_STATUS_IS_OK(status)) {
8525 printf("mkdir1 failed : %s\n", nt_errstr(status));
8526 return False;
8530 * Create a file with illegal NTFS characters and test that we
8531 * get a usable mangled name
8534 cli_setatr(cli_posix, illegal_fname, 0, 0);
8535 cli_posix_unlink(cli_posix, illegal_fname);
8537 status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
8538 0600, &fnum);
8539 if (!NT_STATUS_IS_OK(status)) {
8540 printf("POSIX create of %s failed (%s)\n",
8541 illegal_fname, nt_errstr(status));
8542 return false;
8545 status = cli_close(cli_posix, fnum);
8546 if (!NT_STATUS_IS_OK(status)) {
8547 printf("close failed (%s)\n", nt_errstr(status));
8548 return false;
8551 status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
8552 if (!NT_STATUS_IS_OK(status)) {
8553 d_printf("cli_list failed: %s\n", nt_errstr(status));
8554 return false;
8557 mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
8558 if (mangled_path == NULL) {
8559 return false;
8562 status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
8563 if (!NT_STATUS_IS_OK(status)) {
8564 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
8565 TALLOC_FREE(mangled_path);
8566 return false;
8568 TALLOC_FREE(mangled_path);
8569 cli_close(cli, fnum);
8571 cli_setatr(cli_posix, illegal_fname, 0, 0);
8572 cli_posix_unlink(cli_posix, illegal_fname);
8575 * Create a file with a long name and check that we got *no* short name.
8578 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8579 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8580 0, 0, &fnum, NULL);
8581 if (!NT_STATUS_IS_OK(status)) {
8582 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8583 return false;
8585 cli_close(cli, fnum);
8587 status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
8588 if (!NT_STATUS_IS_OK(status)) {
8589 d_printf("cli_list failed\n");
8590 return false;
8593 cli_unlink(cli, fname, 0);
8594 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
8596 if (!torture_close_connection(cli_posix)) {
8597 return false;
8600 if (!torture_close_connection(cli)) {
8601 return false;
8604 return true;
8607 static size_t null_source(uint8_t *buf, size_t n, void *priv)
8609 size_t *to_pull = (size_t *)priv;
8610 size_t thistime = *to_pull;
8612 thistime = MIN(thistime, n);
8613 if (thistime == 0) {
8614 return 0;
8617 memset(buf, 0, thistime);
8618 *to_pull -= thistime;
8619 return thistime;
8622 static bool run_windows_write(int dummy)
8624 struct cli_state *cli1;
8625 uint16_t fnum;
8626 int i;
8627 bool ret = false;
8628 const char *fname = "\\writetest.txt";
8629 struct timeval start_time;
8630 double seconds;
8631 double kbytes;
8632 NTSTATUS status;
8634 printf("starting windows_write test\n");
8635 if (!torture_open_connection(&cli1, 0)) {
8636 return False;
8639 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
8640 if (!NT_STATUS_IS_OK(status)) {
8641 printf("open failed (%s)\n", nt_errstr(status));
8642 return False;
8645 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8647 start_time = timeval_current();
8649 for (i=0; i<torture_numops; i++) {
8650 uint8_t c = 0;
8651 off_t start = i * torture_blocksize;
8652 size_t to_pull = torture_blocksize - 1;
8654 status = cli_writeall(cli1, fnum, 0, &c,
8655 start + torture_blocksize - 1, 1, NULL);
8656 if (!NT_STATUS_IS_OK(status)) {
8657 printf("cli_write failed: %s\n", nt_errstr(status));
8658 goto fail;
8661 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
8662 null_source, &to_pull);
8663 if (!NT_STATUS_IS_OK(status)) {
8664 printf("cli_push returned: %s\n", nt_errstr(status));
8665 goto fail;
8669 seconds = timeval_elapsed(&start_time);
8670 kbytes = (double)torture_blocksize * torture_numops;
8671 kbytes /= 1024;
8673 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
8674 (double)seconds, (int)(kbytes/seconds));
8676 ret = true;
8677 fail:
8678 cli_close(cli1, fnum);
8679 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8680 torture_close_connection(cli1);
8681 return ret;
8684 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
8686 size_t max_pdu = 0x1FFFF;
8688 if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
8689 max_pdu = 0xFFFFFF;
8692 if (smb1cli_conn_signing_is_active(cli->conn)) {
8693 max_pdu = 0x1FFFF;
8696 if (smb1cli_conn_encryption_on(cli->conn)) {
8697 max_pdu = CLI_BUFFER_SIZE;
8700 if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
8701 len_requested &= 0xFFFF;
8704 return MIN(len_requested,
8705 max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
8708 static bool check_read_call(struct cli_state *cli,
8709 uint16_t fnum,
8710 uint8_t *buf,
8711 size_t len_requested)
8713 NTSTATUS status;
8714 struct tevent_req *subreq = NULL;
8715 ssize_t len_read = 0;
8716 size_t len_expected = 0;
8717 struct tevent_context *ev = NULL;
8719 ev = samba_tevent_context_init(talloc_tos());
8720 if (ev == NULL) {
8721 return false;
8724 subreq = cli_read_andx_send(talloc_tos(),
8726 cli,
8727 fnum,
8729 len_requested);
8731 if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
8732 return false;
8735 status = cli_read_andx_recv(subreq, &len_read, &buf);
8736 if (!NT_STATUS_IS_OK(status)) {
8737 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
8738 return false;
8741 TALLOC_FREE(subreq);
8742 TALLOC_FREE(ev);
8744 len_expected = calc_expected_return(cli, len_requested);
8746 if (len_expected > 0x10000 && len_read == 0x10000) {
8747 /* Windows servers only return a max of 0x10000,
8748 doesn't matter if you set CAP_LARGE_READX in
8749 the client sessionsetupX call or not. */
8750 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
8751 (unsigned int)len_requested);
8752 } else if (len_read != len_expected) {
8753 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
8754 (unsigned int)len_requested,
8755 (unsigned int)len_read,
8756 (unsigned int)len_expected);
8757 return false;
8758 } else {
8759 d_printf("Correct read reply.\n");
8762 return true;
8765 /* Test large readX variants. */
8766 static bool large_readx_tests(struct cli_state *cli,
8767 uint16_t fnum,
8768 uint8_t *buf)
8770 /* A read of 0xFFFF0001 should *always* return 1 byte. */
8771 if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
8772 return false;
8774 /* A read of 0x10000 should return 0x10000 bytes. */
8775 if (check_read_call(cli, fnum, buf, 0x10000) == false) {
8776 return false;
8778 /* A read of 0x10000 should return 0x10001 bytes. */
8779 if (check_read_call(cli, fnum, buf, 0x10001) == false) {
8780 return false;
8782 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
8783 the requested number of bytes. */
8784 if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
8785 return false;
8787 /* A read of 1MB should return 1MB bytes (on Samba). */
8788 if (check_read_call(cli, fnum, buf, 0x100000) == false) {
8789 return false;
8792 if (check_read_call(cli, fnum, buf, 0x20001) == false) {
8793 return false;
8795 if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
8796 return false;
8798 if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
8799 return false;
8801 return true;
8804 static bool run_large_readx(int dummy)
8806 uint8_t *buf = NULL;
8807 struct cli_state *cli1 = NULL;
8808 struct cli_state *cli2 = NULL;
8809 bool correct = false;
8810 const char *fname = "\\large_readx.dat";
8811 NTSTATUS status;
8812 uint16_t fnum1 = UINT16_MAX;
8813 uint32_t normal_caps = 0;
8814 size_t file_size = 20*1024*1024;
8815 TALLOC_CTX *frame = talloc_stackframe();
8816 size_t i;
8817 struct {
8818 const char *name;
8819 enum smb_signing_setting signing_setting;
8820 enum protocol_types protocol;
8821 } runs[] = {
8823 .name = "NT1",
8824 .signing_setting = SMB_SIGNING_IF_REQUIRED,
8825 .protocol = PROTOCOL_NT1,
8827 .name = "NT1 - SIGNING_REQUIRED",
8828 .signing_setting = SMB_SIGNING_REQUIRED,
8829 .protocol = PROTOCOL_NT1,
8833 printf("starting large_readx test\n");
8835 if (!torture_open_connection(&cli1, 0)) {
8836 goto out;
8839 normal_caps = smb1cli_conn_capabilities(cli1->conn);
8841 if (!(normal_caps & CAP_LARGE_READX)) {
8842 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
8843 (unsigned int)normal_caps);
8844 goto out;
8847 /* Create a file of size 4MB. */
8848 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
8849 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8850 0, 0, &fnum1, NULL);
8852 if (!NT_STATUS_IS_OK(status)) {
8853 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8854 goto out;
8857 /* Write file_size bytes. */
8858 buf = talloc_zero_array(frame, uint8_t, file_size);
8859 if (buf == NULL) {
8860 goto out;
8863 status = cli_writeall(cli1,
8864 fnum1,
8866 buf,
8868 file_size,
8869 NULL);
8870 if (!NT_STATUS_IS_OK(status)) {
8871 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
8872 goto out;
8875 status = cli_close(cli1, fnum1);
8876 if (!NT_STATUS_IS_OK(status)) {
8877 d_printf("cli_close failed: %s\n", nt_errstr(status));
8878 goto out;
8881 fnum1 = UINT16_MAX;
8883 for (i=0; i < ARRAY_SIZE(runs); i++) {
8884 enum smb_signing_setting saved_signing_setting = signing_state;
8885 uint16_t fnum2 = -1;
8887 if (do_encrypt &&
8888 (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
8890 d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
8891 continue;
8894 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
8896 signing_state = runs[i].signing_setting;
8897 cli2 = open_nbt_connection();
8898 signing_state = saved_signing_setting;
8899 if (cli2 == NULL) {
8900 goto out;
8903 status = smbXcli_negprot(cli2->conn,
8904 cli2->timeout,
8905 runs[i].protocol,
8906 runs[i].protocol);
8907 if (!NT_STATUS_IS_OK(status)) {
8908 goto out;
8911 status = cli_session_setup_creds(cli2, torture_creds);
8912 if (!NT_STATUS_IS_OK(status)) {
8913 goto out;
8916 status = cli_tree_connect(cli2,
8917 share,
8918 "?????",
8919 password);
8920 if (!NT_STATUS_IS_OK(status)) {
8921 goto out;
8924 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
8926 normal_caps = smb1cli_conn_capabilities(cli2->conn);
8928 if (!(normal_caps & CAP_LARGE_READX)) {
8929 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
8930 (unsigned int)normal_caps);
8931 goto out;
8934 if (do_encrypt) {
8935 if (force_cli_encryption(cli2, share) == false) {
8936 goto out;
8938 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
8939 uint16_t major, minor;
8940 uint32_t caplow, caphigh;
8942 status = cli_unix_extensions_version(cli2,
8943 &major, &minor,
8944 &caplow, &caphigh);
8945 if (!NT_STATUS_IS_OK(status)) {
8946 goto out;
8950 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
8951 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
8952 0, 0, &fnum2, NULL);
8953 if (!NT_STATUS_IS_OK(status)) {
8954 d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
8955 goto out;
8958 /* All reads must return less than file_size bytes. */
8959 if (!large_readx_tests(cli2, fnum2, buf)) {
8960 goto out;
8963 status = cli_close(cli2, fnum2);
8964 if (!NT_STATUS_IS_OK(status)) {
8965 d_printf("cli_close failed: %s\n", nt_errstr(status));
8966 goto out;
8968 fnum2 = -1;
8970 if (!torture_close_connection(cli2)) {
8971 goto out;
8973 cli2 = NULL;
8976 correct = true;
8977 printf("Success on large_readx test\n");
8979 out:
8981 if (cli2) {
8982 if (!torture_close_connection(cli2)) {
8983 correct = false;
8987 if (cli1) {
8988 if (fnum1 != UINT16_MAX) {
8989 status = cli_close(cli1, fnum1);
8990 if (!NT_STATUS_IS_OK(status)) {
8991 d_printf("cli_close failed: %s\n", nt_errstr(status));
8993 fnum1 = UINT16_MAX;
8996 status = cli_unlink(cli1, fname,
8997 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8998 if (!NT_STATUS_IS_OK(status)) {
8999 printf("unlink failed (%s)\n", nt_errstr(status));
9002 if (!torture_close_connection(cli1)) {
9003 correct = false;
9007 TALLOC_FREE(frame);
9009 printf("finished large_readx test\n");
9010 return correct;
9013 static bool run_cli_echo(int dummy)
9015 struct cli_state *cli;
9016 NTSTATUS status;
9018 printf("starting cli_echo test\n");
9019 if (!torture_open_connection(&cli, 0)) {
9020 return false;
9022 smbXcli_conn_set_sockopt(cli->conn, sockops);
9024 status = cli_echo(cli, 5, data_blob_const("hello", 5));
9026 d_printf("cli_echo returned %s\n", nt_errstr(status));
9028 torture_close_connection(cli);
9029 return NT_STATUS_IS_OK(status);
9032 static bool run_uid_regression_test(int dummy)
9034 static struct cli_state *cli;
9035 int16_t old_vuid;
9036 int32_t old_cnum;
9037 bool correct = True;
9038 struct smbXcli_tcon *orig_tcon = NULL;
9039 NTSTATUS status;
9041 printf("starting uid regression test\n");
9043 if (!torture_open_connection(&cli, 0)) {
9044 return False;
9047 smbXcli_conn_set_sockopt(cli->conn, sockops);
9049 /* Ok - now save then logoff our current user. */
9050 old_vuid = cli_state_get_uid(cli);
9052 status = cli_ulogoff(cli);
9053 if (!NT_STATUS_IS_OK(status)) {
9054 d_printf("(%s) cli_ulogoff failed: %s\n",
9055 __location__, nt_errstr(status));
9056 correct = false;
9057 goto out;
9060 cli_state_set_uid(cli, old_vuid);
9062 /* Try an operation. */
9063 status = cli_mkdir(cli, "\\uid_reg_test");
9064 if (NT_STATUS_IS_OK(status)) {
9065 d_printf("(%s) cli_mkdir succeeded\n",
9066 __location__);
9067 correct = false;
9068 goto out;
9069 } else {
9070 /* Should be bad uid. */
9071 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
9072 NT_STATUS_USER_SESSION_DELETED)) {
9073 correct = false;
9074 goto out;
9078 old_cnum = cli_state_get_tid(cli);
9079 orig_tcon = cli_state_save_tcon(cli);
9080 if (orig_tcon == NULL) {
9081 correct = false;
9082 goto out;
9085 /* Now try a SMBtdis with the invald vuid set to zero. */
9086 cli_state_set_uid(cli, 0);
9088 /* This should succeed. */
9089 status = cli_tdis(cli);
9091 if (NT_STATUS_IS_OK(status)) {
9092 d_printf("First tdis with invalid vuid should succeed.\n");
9093 } else {
9094 d_printf("First tdis failed (%s)\n", nt_errstr(status));
9095 correct = false;
9096 cli_state_restore_tcon(cli, orig_tcon);
9097 goto out;
9100 cli_state_restore_tcon(cli, orig_tcon);
9101 cli_state_set_uid(cli, old_vuid);
9102 cli_state_set_tid(cli, old_cnum);
9104 /* This should fail. */
9105 status = cli_tdis(cli);
9106 if (NT_STATUS_IS_OK(status)) {
9107 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
9108 correct = false;
9109 goto out;
9110 } else {
9111 /* Should be bad tid. */
9112 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
9113 NT_STATUS_NETWORK_NAME_DELETED)) {
9114 correct = false;
9115 goto out;
9119 cli_rmdir(cli, "\\uid_reg_test");
9121 out:
9123 cli_shutdown(cli);
9124 return correct;
9128 static const char *illegal_chars = "*\\/?<>|\":";
9129 static char force_shortname_chars[] = " +,.[];=\177";
9131 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
9132 const char *mask, void *state)
9134 struct cli_state *pcli = (struct cli_state *)state;
9135 fstring fname;
9136 NTSTATUS status = NT_STATUS_OK;
9138 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
9140 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9141 return NT_STATUS_OK;
9143 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
9144 status = cli_rmdir(pcli, fname);
9145 if (!NT_STATUS_IS_OK(status)) {
9146 printf("del_fn: failed to rmdir %s\n,", fname );
9148 } else {
9149 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9150 if (!NT_STATUS_IS_OK(status)) {
9151 printf("del_fn: failed to unlink %s\n,", fname );
9154 return status;
9157 struct sn_state {
9158 int matched;
9159 int i;
9160 bool val;
9163 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
9164 const char *name, void *state)
9166 struct sn_state *s = (struct sn_state *)state;
9167 int i = s->i;
9169 #if 0
9170 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
9171 i, finfo->name, finfo->short_name);
9172 #endif
9174 if (strchr(force_shortname_chars, i)) {
9175 if (!finfo->short_name) {
9176 /* Shortname not created when it should be. */
9177 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
9178 __location__, finfo->name, i);
9179 s->val = true;
9181 } else if (finfo->short_name){
9182 /* Shortname created when it should not be. */
9183 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
9184 __location__, finfo->short_name, finfo->name);
9185 s->val = true;
9187 s->matched += 1;
9188 return NT_STATUS_OK;
9191 static bool run_shortname_test(int dummy)
9193 static struct cli_state *cli;
9194 bool correct = True;
9195 int i;
9196 struct sn_state s;
9197 char fname[40];
9198 NTSTATUS status;
9200 printf("starting shortname test\n");
9202 if (!torture_open_connection(&cli, 0)) {
9203 return False;
9206 smbXcli_conn_set_sockopt(cli->conn, sockops);
9208 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
9209 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
9210 cli_rmdir(cli, "\\shortname");
9212 status = cli_mkdir(cli, "\\shortname");
9213 if (!NT_STATUS_IS_OK(status)) {
9214 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
9215 __location__, nt_errstr(status));
9216 correct = false;
9217 goto out;
9220 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
9221 correct = false;
9222 goto out;
9224 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
9225 correct = false;
9226 goto out;
9229 s.val = false;
9231 for (i = 32; i < 128; i++) {
9232 uint16_t fnum = (uint16_t)-1;
9234 s.i = i;
9236 if (strchr(illegal_chars, i)) {
9237 continue;
9239 fname[15] = i;
9241 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
9242 FILE_SHARE_READ|FILE_SHARE_WRITE,
9243 FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
9244 if (!NT_STATUS_IS_OK(status)) {
9245 d_printf("(%s) cli_nt_create of %s failed: %s\n",
9246 __location__, fname, nt_errstr(status));
9247 correct = false;
9248 goto out;
9250 cli_close(cli, fnum);
9252 s.matched = 0;
9253 status = cli_list(cli, "\\shortname\\test*.*", 0,
9254 shortname_list_fn, &s);
9255 if (s.matched != 1) {
9256 d_printf("(%s) failed to list %s: %s\n",
9257 __location__, fname, nt_errstr(status));
9258 correct = false;
9259 goto out;
9262 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9263 if (!NT_STATUS_IS_OK(status)) {
9264 d_printf("(%s) failed to delete %s: %s\n",
9265 __location__, fname, nt_errstr(status));
9266 correct = false;
9267 goto out;
9270 if (s.val) {
9271 correct = false;
9272 goto out;
9276 out:
9278 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
9279 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
9280 cli_rmdir(cli, "\\shortname");
9281 torture_close_connection(cli);
9282 return correct;
9285 static void pagedsearch_cb(struct tevent_req *req)
9287 TLDAPRC rc;
9288 struct tldap_message *msg;
9289 char *dn;
9291 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
9292 if (!TLDAP_RC_IS_SUCCESS(rc)) {
9293 d_printf("tldap_search_paged_recv failed: %s\n",
9294 tldap_rc2string(rc));
9295 return;
9297 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
9298 TALLOC_FREE(msg);
9299 return;
9301 if (!tldap_entry_dn(msg, &dn)) {
9302 d_printf("tldap_entry_dn failed\n");
9303 return;
9305 d_printf("%s\n", dn);
9306 TALLOC_FREE(msg);
9309 static bool run_tldap(int dummy)
9311 struct tldap_context *ld;
9312 int fd;
9313 TLDAPRC rc;
9314 NTSTATUS status;
9315 struct sockaddr_storage addr;
9316 struct tevent_context *ev;
9317 struct tevent_req *req;
9318 char *basedn;
9319 const char *filter;
9321 if (!resolve_name(host, &addr, 0, false)) {
9322 d_printf("could not find host %s\n", host);
9323 return false;
9325 status = open_socket_out(&addr, 389, 9999, &fd);
9326 if (!NT_STATUS_IS_OK(status)) {
9327 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
9328 return false;
9331 ld = tldap_context_create(talloc_tos(), fd);
9332 if (ld == NULL) {
9333 close(fd);
9334 d_printf("tldap_context_create failed\n");
9335 return false;
9338 rc = tldap_fetch_rootdse(ld);
9339 if (!TLDAP_RC_IS_SUCCESS(rc)) {
9340 d_printf("tldap_fetch_rootdse failed: %s\n",
9341 tldap_errstr(talloc_tos(), ld, rc));
9342 return false;
9345 basedn = tldap_talloc_single_attribute(
9346 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
9347 if (basedn == NULL) {
9348 d_printf("no defaultNamingContext\n");
9349 return false;
9351 d_printf("defaultNamingContext: %s\n", basedn);
9353 ev = samba_tevent_context_init(talloc_tos());
9354 if (ev == NULL) {
9355 d_printf("tevent_context_init failed\n");
9356 return false;
9359 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
9360 TLDAP_SCOPE_SUB, "(objectclass=*)",
9361 NULL, 0, 0,
9362 NULL, 0, NULL, 0, 0, 0, 0, 5);
9363 if (req == NULL) {
9364 d_printf("tldap_search_paged_send failed\n");
9365 return false;
9367 tevent_req_set_callback(req, pagedsearch_cb, NULL);
9369 tevent_req_poll(req, ev);
9371 TALLOC_FREE(req);
9373 /* test search filters against rootDSE */
9374 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
9375 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
9377 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
9378 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
9379 talloc_tos(), NULL);
9380 if (!TLDAP_RC_IS_SUCCESS(rc)) {
9381 d_printf("tldap_search with complex filter failed: %s\n",
9382 tldap_errstr(talloc_tos(), ld, rc));
9383 return false;
9386 TALLOC_FREE(ld);
9387 return true;
9390 /* Torture test to ensure no regression of :
9391 https://bugzilla.samba.org/show_bug.cgi?id=7084
9394 static bool run_dir_createtime(int dummy)
9396 struct cli_state *cli;
9397 const char *dname = "\\testdir";
9398 const char *fname = "\\testdir\\testfile";
9399 NTSTATUS status;
9400 struct timespec create_time;
9401 struct timespec create_time1;
9402 uint16_t fnum;
9403 bool ret = false;
9405 if (!torture_open_connection(&cli, 0)) {
9406 return false;
9409 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9410 cli_rmdir(cli, dname);
9412 status = cli_mkdir(cli, dname);
9413 if (!NT_STATUS_IS_OK(status)) {
9414 printf("mkdir failed: %s\n", nt_errstr(status));
9415 goto out;
9418 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
9419 NULL, NULL, NULL);
9420 if (!NT_STATUS_IS_OK(status)) {
9421 printf("cli_qpathinfo2 returned %s\n",
9422 nt_errstr(status));
9423 goto out;
9426 /* Sleep 3 seconds, then create a file. */
9427 sleep(3);
9429 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
9430 DENY_NONE, &fnum);
9431 if (!NT_STATUS_IS_OK(status)) {
9432 printf("cli_openx failed: %s\n", nt_errstr(status));
9433 goto out;
9436 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
9437 NULL, NULL, NULL);
9438 if (!NT_STATUS_IS_OK(status)) {
9439 printf("cli_qpathinfo2 (2) returned %s\n",
9440 nt_errstr(status));
9441 goto out;
9444 if (timespec_compare(&create_time1, &create_time)) {
9445 printf("run_dir_createtime: create time was updated (error)\n");
9446 } else {
9447 printf("run_dir_createtime: create time was not updated (correct)\n");
9448 ret = true;
9451 out:
9453 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9454 cli_rmdir(cli, dname);
9455 if (!torture_close_connection(cli)) {
9456 ret = false;
9458 return ret;
9462 static bool run_streamerror(int dummy)
9464 struct cli_state *cli;
9465 const char *dname = "\\testdir";
9466 const char *streamname =
9467 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
9468 NTSTATUS status;
9469 time_t change_time, access_time, write_time;
9470 off_t size;
9471 uint16_t mode, fnum;
9472 bool ret = true;
9474 if (!torture_open_connection(&cli, 0)) {
9475 return false;
9478 cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9479 cli_rmdir(cli, dname);
9481 status = cli_mkdir(cli, dname);
9482 if (!NT_STATUS_IS_OK(status)) {
9483 printf("mkdir failed: %s\n", nt_errstr(status));
9484 return false;
9487 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
9488 &write_time, &size, &mode);
9489 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
9490 printf("pathinfo returned %s, expected "
9491 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
9492 nt_errstr(status));
9493 ret = false;
9496 status = cli_ntcreate(cli, streamname, 0x16,
9497 FILE_READ_DATA|FILE_READ_EA|
9498 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
9499 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
9500 FILE_OPEN, 0, 0, &fnum, NULL);
9502 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
9503 printf("ntcreate returned %s, expected "
9504 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
9505 nt_errstr(status));
9506 ret = false;
9510 cli_rmdir(cli, dname);
9511 return ret;
9514 struct pidtest_state {
9515 bool success;
9516 uint16_t vwv[1];
9517 DATA_BLOB data;
9520 static void pid_echo_done(struct tevent_req *subreq);
9522 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
9523 struct tevent_context *ev,
9524 struct cli_state *cli)
9526 struct tevent_req *req, *subreq;
9527 struct pidtest_state *state;
9529 req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
9530 if (req == NULL) {
9531 return NULL;
9534 SSVAL(state->vwv, 0, 1);
9535 state->data = data_blob_const("hello", 5);
9537 subreq = smb1cli_req_send(state,
9539 cli->conn,
9540 SMBecho,
9541 0, 0, /* *_flags */
9542 0, 0, /* *_flags2 */
9543 cli->timeout,
9544 0xDEADBEEF, /* pid */
9545 NULL, /* tcon */
9546 NULL, /* session */
9547 ARRAY_SIZE(state->vwv), state->vwv,
9548 state->data.length, state->data.data);
9550 if (tevent_req_nomem(subreq, req)) {
9551 return tevent_req_post(req, ev);
9553 tevent_req_set_callback(subreq, pid_echo_done, req);
9554 return req;
9557 static void pid_echo_done(struct tevent_req *subreq)
9559 struct tevent_req *req = tevent_req_callback_data(
9560 subreq, struct tevent_req);
9561 struct pidtest_state *state = tevent_req_data(
9562 req, struct pidtest_state);
9563 NTSTATUS status;
9564 uint32_t num_bytes;
9565 uint8_t *bytes = NULL;
9566 struct iovec *recv_iov = NULL;
9567 uint8_t *phdr = NULL;
9568 uint16_t pidlow = 0;
9569 uint16_t pidhigh = 0;
9570 struct smb1cli_req_expected_response expected[] = {
9572 .status = NT_STATUS_OK,
9573 .wct = 1,
9577 status = smb1cli_req_recv(subreq, state,
9578 &recv_iov,
9579 &phdr,
9580 NULL, /* pwct */
9581 NULL, /* pvwv */
9582 NULL, /* pvwv_offset */
9583 &num_bytes,
9584 &bytes,
9585 NULL, /* pbytes_offset */
9586 NULL, /* pinbuf */
9587 expected, ARRAY_SIZE(expected));
9589 TALLOC_FREE(subreq);
9591 if (!NT_STATUS_IS_OK(status)) {
9592 tevent_req_nterror(req, status);
9593 return;
9596 if (num_bytes != state->data.length) {
9597 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9598 return;
9601 if (memcmp(bytes, state->data.data, num_bytes) != 0) {
9602 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9603 return;
9606 /* Check pid low/high == DEADBEEF */
9607 pidlow = SVAL(phdr, HDR_PID);
9608 if (pidlow != 0xBEEF){
9609 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
9610 (unsigned int)pidlow);
9611 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9612 return;
9614 pidhigh = SVAL(phdr, HDR_PIDHIGH);
9615 if (pidhigh != 0xDEAD){
9616 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
9617 (unsigned int)pidhigh);
9618 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9619 return;
9622 tevent_req_done(req);
9625 static NTSTATUS pid_echo_recv(struct tevent_req *req)
9627 return tevent_req_simple_recv_ntstatus(req);
9630 static bool run_pidhigh(int dummy)
9632 bool success = false;
9633 struct cli_state *cli = NULL;
9634 NTSTATUS status;
9635 struct tevent_context *ev = NULL;
9636 struct tevent_req *req = NULL;
9637 TALLOC_CTX *frame = talloc_stackframe();
9639 printf("starting pid high test\n");
9640 if (!torture_open_connection(&cli, 0)) {
9641 return false;
9643 smbXcli_conn_set_sockopt(cli->conn, sockops);
9645 ev = samba_tevent_context_init(frame);
9646 if (ev == NULL) {
9647 goto fail;
9650 req = pid_echo_send(frame, ev, cli);
9651 if (req == NULL) {
9652 goto fail;
9655 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
9656 goto fail;
9659 status = pid_echo_recv(req);
9660 if (NT_STATUS_IS_OK(status)) {
9661 printf("pid high test ok\n");
9662 success = true;
9665 fail:
9667 TALLOC_FREE(frame);
9668 torture_close_connection(cli);
9669 return success;
9673 Test Windows open on a bad POSIX symlink.
9675 static bool run_symlink_open_test(int dummy)
9677 static struct cli_state *cli;
9678 const char *fname = "non_existant_file";
9679 const char *sname = "dangling_symlink";
9680 uint16_t fnum = (uint16_t)-1;
9681 bool correct = false;
9682 NTSTATUS status;
9683 TALLOC_CTX *frame = NULL;
9685 frame = talloc_stackframe();
9687 printf("Starting Windows bad symlink open test\n");
9689 if (!torture_open_connection(&cli, 0)) {
9690 TALLOC_FREE(frame);
9691 return false;
9694 smbXcli_conn_set_sockopt(cli->conn, sockops);
9696 status = torture_setup_unix_extensions(cli);
9697 if (!NT_STATUS_IS_OK(status)) {
9698 TALLOC_FREE(frame);
9699 return false;
9702 /* Ensure nothing exists. */
9703 cli_setatr(cli, fname, 0, 0);
9704 cli_posix_unlink(cli, fname);
9705 cli_setatr(cli, sname, 0, 0);
9706 cli_posix_unlink(cli, sname);
9708 /* Create a symlink pointing nowhere. */
9709 status = cli_posix_symlink(cli, fname, sname);
9710 if (!NT_STATUS_IS_OK(status)) {
9711 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
9712 sname,
9713 fname,
9714 nt_errstr(status));
9715 goto out;
9718 /* Now ensure that a Windows open doesn't hang. */
9719 status = cli_ntcreate(cli,
9720 sname,
9722 FILE_READ_DATA|FILE_WRITE_DATA,
9724 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9725 FILE_OPEN_IF,
9726 0x0,
9727 0x0,
9728 &fnum,
9729 NULL);
9732 * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
9733 * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
9734 * we use O_NOFOLLOW on the server or not.
9736 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
9737 NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
9739 correct = true;
9740 } else {
9741 printf("cli_ntcreate of %s returned %s - should return"
9742 " either (%s) or (%s)\n",
9743 sname,
9744 nt_errstr(status),
9745 nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
9746 nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
9747 goto out;
9750 correct = true;
9752 out:
9754 if (fnum != (uint16_t)-1) {
9755 cli_close(cli, fnum);
9756 fnum = (uint16_t)-1;
9759 cli_setatr(cli, sname, 0, 0);
9760 cli_posix_unlink(cli, sname);
9761 cli_setatr(cli, fname, 0, 0);
9762 cli_posix_unlink(cli, fname);
9764 if (!torture_close_connection(cli)) {
9765 correct = false;
9768 TALLOC_FREE(frame);
9769 return correct;
9772 static bool run_local_substitute(int dummy)
9774 bool ok = true;
9776 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
9777 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
9778 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
9779 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
9780 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
9781 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
9782 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
9783 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
9785 /* Different captialization rules in sub_basic... */
9787 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
9788 "blaDOM") == 0);
9790 return ok;
9793 static bool run_local_base64(int dummy)
9795 int i;
9796 bool ret = true;
9798 for (i=1; i<2000; i++) {
9799 DATA_BLOB blob1, blob2;
9800 char *b64;
9802 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
9803 blob1.length = i;
9804 generate_random_buffer(blob1.data, blob1.length);
9806 b64 = base64_encode_data_blob(talloc_tos(), blob1);
9807 if (b64 == NULL) {
9808 d_fprintf(stderr, "base64_encode_data_blob failed "
9809 "for %d bytes\n", i);
9810 ret = false;
9812 blob2 = base64_decode_data_blob(b64);
9813 TALLOC_FREE(b64);
9815 if (data_blob_cmp(&blob1, &blob2)) {
9816 d_fprintf(stderr, "data_blob_cmp failed for %d "
9817 "bytes\n", i);
9818 ret = false;
9820 TALLOC_FREE(blob1.data);
9821 data_blob_free(&blob2);
9823 return ret;
9826 static void parse_fn(time_t timeout, DATA_BLOB blob, void *private_data)
9828 return;
9831 static bool run_local_gencache(int dummy)
9833 char *val;
9834 time_t tm;
9835 DATA_BLOB blob;
9836 char v;
9837 struct memcache *mem;
9838 int i;
9840 mem = memcache_init(NULL, 0);
9841 if (mem == NULL) {
9842 d_printf("%s: memcache_init failed\n", __location__);
9843 return false;
9845 memcache_set_global(mem);
9847 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
9848 d_printf("%s: gencache_set() failed\n", __location__);
9849 return False;
9852 if (!gencache_get("foo", NULL, NULL, NULL)) {
9853 d_printf("%s: gencache_get() failed\n", __location__);
9854 return False;
9857 for (i=0; i<1000000; i++) {
9858 gencache_parse("foo", parse_fn, NULL);
9861 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
9862 d_printf("%s: gencache_get() failed\n", __location__);
9863 return False;
9865 TALLOC_FREE(val);
9867 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
9868 d_printf("%s: gencache_get() failed\n", __location__);
9869 return False;
9872 if (strcmp(val, "bar") != 0) {
9873 d_printf("%s: gencache_get() returned %s, expected %s\n",
9874 __location__, val, "bar");
9875 TALLOC_FREE(val);
9876 return False;
9879 TALLOC_FREE(val);
9881 if (!gencache_del("foo")) {
9882 d_printf("%s: gencache_del() failed\n", __location__);
9883 return False;
9885 if (gencache_del("foo")) {
9886 d_printf("%s: second gencache_del() succeeded\n",
9887 __location__);
9888 return False;
9891 if (gencache_get("foo", talloc_tos(), &val, &tm)) {
9892 d_printf("%s: gencache_get() on deleted entry "
9893 "succeeded\n", __location__);
9894 return False;
9897 blob = data_blob_string_const_null("bar");
9898 tm = time(NULL) + 60;
9900 if (!gencache_set_data_blob("foo", &blob, tm)) {
9901 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
9902 return False;
9905 if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
9906 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
9907 return False;
9910 if (strcmp((const char *)blob.data, "bar") != 0) {
9911 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
9912 __location__, (const char *)blob.data, "bar");
9913 data_blob_free(&blob);
9914 return False;
9917 data_blob_free(&blob);
9919 if (!gencache_del("foo")) {
9920 d_printf("%s: gencache_del() failed\n", __location__);
9921 return False;
9923 if (gencache_del("foo")) {
9924 d_printf("%s: second gencache_del() succeeded\n",
9925 __location__);
9926 return False;
9929 if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
9930 d_printf("%s: gencache_get_data_blob() on deleted entry "
9931 "succeeded\n", __location__);
9932 return False;
9935 v = 1;
9936 blob.data = (uint8_t *)&v;
9937 blob.length = sizeof(v);
9939 if (!gencache_set_data_blob("blob", &blob, tm)) {
9940 d_printf("%s: gencache_set_data_blob() failed\n",
9941 __location__);
9942 return false;
9944 if (gencache_get("blob", talloc_tos(), &val, &tm)) {
9945 d_printf("%s: gencache_get succeeded\n", __location__);
9946 return false;
9949 return True;
9952 static bool rbt_testval(struct db_context *db, const char *key,
9953 const char *value)
9955 struct db_record *rec;
9956 TDB_DATA data = string_tdb_data(value);
9957 bool ret = false;
9958 NTSTATUS status;
9959 TDB_DATA dbvalue;
9961 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
9962 if (rec == NULL) {
9963 d_fprintf(stderr, "fetch_locked failed\n");
9964 goto done;
9966 status = dbwrap_record_store(rec, data, 0);
9967 if (!NT_STATUS_IS_OK(status)) {
9968 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
9969 goto done;
9971 TALLOC_FREE(rec);
9973 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
9974 if (rec == NULL) {
9975 d_fprintf(stderr, "second fetch_locked failed\n");
9976 goto done;
9979 dbvalue = dbwrap_record_get_value(rec);
9980 if ((dbvalue.dsize != data.dsize)
9981 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
9982 d_fprintf(stderr, "Got wrong data back\n");
9983 goto done;
9986 ret = true;
9987 done:
9988 TALLOC_FREE(rec);
9989 return ret;
9992 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
9994 int *count2 = (int *)private_data;
9995 (*count2)++;
9996 return 0;
9999 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
10001 int *count2 = (int *)private_data;
10002 (*count2)++;
10003 dbwrap_record_delete(rec);
10004 return 0;
10007 static bool run_local_rbtree(int dummy)
10009 struct db_context *db;
10010 bool ret = false;
10011 int i;
10012 NTSTATUS status;
10013 int count = 0;
10014 int count2 = 0;
10016 db = db_open_rbt(NULL);
10018 if (db == NULL) {
10019 d_fprintf(stderr, "db_open_rbt failed\n");
10020 return false;
10023 for (i=0; i<1000; i++) {
10024 char *key, *value;
10026 if (asprintf(&key, "key%ld", random()) == -1) {
10027 goto done;
10029 if (asprintf(&value, "value%ld", random()) == -1) {
10030 SAFE_FREE(key);
10031 goto done;
10034 if (!rbt_testval(db, key, value)) {
10035 SAFE_FREE(key);
10036 SAFE_FREE(value);
10037 goto done;
10040 SAFE_FREE(value);
10041 if (asprintf(&value, "value%ld", random()) == -1) {
10042 SAFE_FREE(key);
10043 goto done;
10046 if (!rbt_testval(db, key, value)) {
10047 SAFE_FREE(key);
10048 SAFE_FREE(value);
10049 goto done;
10052 SAFE_FREE(key);
10053 SAFE_FREE(value);
10056 ret = true;
10057 count = 0; count2 = 0;
10058 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
10059 &count2, &count);
10060 printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10061 if ((count != count2) || (count != 1000)) {
10062 ret = false;
10064 count = 0; count2 = 0;
10065 status = dbwrap_traverse(db, local_rbtree_traverse_delete,
10066 &count2, &count);
10067 printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10068 if ((count != count2) || (count != 1000)) {
10069 ret = false;
10071 count = 0; count2 = 0;
10072 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
10073 &count2, &count);
10074 printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10075 if ((count != count2) || (count != 0)) {
10076 ret = false;
10079 done:
10080 TALLOC_FREE(db);
10081 return ret;
10086 local test for character set functions
10088 This is a very simple test for the functionality in convert_string_error()
10090 static bool run_local_convert_string(int dummy)
10092 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
10093 const char *test_strings[2] = { "March", "M\303\244rz" };
10094 char dst[7];
10095 int i;
10097 for (i=0; i<2; i++) {
10098 const char *str = test_strings[i];
10099 int len = strlen(str);
10100 size_t converted_size;
10101 bool ret;
10103 memset(dst, 'X', sizeof(dst));
10105 /* first try with real source length */
10106 ret = convert_string_error(CH_UNIX, CH_UTF8,
10107 str, len,
10108 dst, sizeof(dst),
10109 &converted_size);
10110 if (ret != true) {
10111 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
10112 goto failed;
10115 if (converted_size != len) {
10116 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
10117 str, len, (int)converted_size);
10118 goto failed;
10121 if (strncmp(str, dst, converted_size) != 0) {
10122 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
10123 goto failed;
10126 if (strlen(str) != converted_size) {
10127 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
10128 (int)strlen(str), (int)converted_size);
10129 goto failed;
10132 if (dst[converted_size] != 'X') {
10133 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
10134 goto failed;
10137 /* now with srclen==-1, this causes the nul to be
10138 * converted too */
10139 ret = convert_string_error(CH_UNIX, CH_UTF8,
10140 str, -1,
10141 dst, sizeof(dst),
10142 &converted_size);
10143 if (ret != true) {
10144 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
10145 goto failed;
10148 if (converted_size != len+1) {
10149 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
10150 str, len, (int)converted_size);
10151 goto failed;
10154 if (strncmp(str, dst, converted_size) != 0) {
10155 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
10156 goto failed;
10159 if (len+1 != converted_size) {
10160 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
10161 len+1, (int)converted_size);
10162 goto failed;
10165 if (dst[converted_size] != 'X') {
10166 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
10167 goto failed;
10173 TALLOC_FREE(tmp_ctx);
10174 return true;
10175 failed:
10176 TALLOC_FREE(tmp_ctx);
10177 return false;
10181 struct talloc_dict_test {
10182 int content;
10185 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
10187 int *count = (int *)priv;
10188 *count += 1;
10189 return 0;
10192 static bool run_local_talloc_dict(int dummy)
10194 struct talloc_dict *dict;
10195 struct talloc_dict_test *t;
10196 int key, count, res;
10197 bool ok;
10199 dict = talloc_dict_init(talloc_tos());
10200 if (dict == NULL) {
10201 return false;
10204 t = talloc(talloc_tos(), struct talloc_dict_test);
10205 if (t == NULL) {
10206 return false;
10209 key = 1;
10210 t->content = 1;
10211 ok = talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), &t);
10212 if (!ok) {
10213 return false;
10216 count = 0;
10217 res = talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count);
10218 if (res == -1) {
10219 return false;
10222 if (count != 1) {
10223 return false;
10226 if (count != res) {
10227 return false;
10230 TALLOC_FREE(dict);
10232 return true;
10235 static bool run_local_string_to_sid(int dummy) {
10236 struct dom_sid sid;
10238 if (string_to_sid(&sid, "S--1-5-32-545")) {
10239 printf("allowing S--1-5-32-545\n");
10240 return false;
10242 if (string_to_sid(&sid, "S-1-5-32-+545")) {
10243 printf("allowing S-1-5-32-+545\n");
10244 return false;
10246 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")) {
10247 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
10248 return false;
10250 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
10251 printf("allowing S-1-5-32-545-abc\n");
10252 return false;
10254 if (string_to_sid(&sid, "S-300-5-32-545")) {
10255 printf("allowing S-300-5-32-545\n");
10256 return false;
10258 if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
10259 printf("allowing S-1-0xfffffffffffffe-32-545\n");
10260 return false;
10262 if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
10263 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
10264 return false;
10266 if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
10267 printf("could not parse S-1-0xfffffffffffe-32-545\n");
10268 return false;
10270 if (!string_to_sid(&sid, "S-1-5-32-545")) {
10271 printf("could not parse S-1-5-32-545\n");
10272 return false;
10274 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
10275 printf("mis-parsed S-1-5-32-545 as %s\n",
10276 sid_string_tos(&sid));
10277 return false;
10279 return true;
10282 static bool sid_to_string_test(const char *expected) {
10283 char *str;
10284 bool res = true;
10285 struct dom_sid sid;
10287 if (!string_to_sid(&sid, expected)) {
10288 printf("could not parse %s\n", expected);
10289 return false;
10292 str = dom_sid_string(NULL, &sid);
10293 if (strcmp(str, expected)) {
10294 printf("Comparison failed (%s != %s)\n", str, expected);
10295 res = false;
10297 TALLOC_FREE(str);
10298 return res;
10301 static bool run_local_sid_to_string(int dummy) {
10302 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
10303 return false;
10304 if (!sid_to_string_test("S-1-545"))
10305 return false;
10306 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
10307 return false;
10308 return true;
10311 static bool run_local_binary_to_sid(int dummy) {
10312 struct dom_sid *sid = talloc(NULL, struct dom_sid);
10313 static const uint8_t good_binary_sid[] = {
10314 0x1, /* revision number */
10315 15, /* num auths */
10316 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10317 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10318 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10319 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10320 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10321 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10322 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10323 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10324 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10325 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10326 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10327 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10328 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10329 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10330 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10331 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10334 static const uint8_t long_binary_sid[] = {
10335 0x1, /* revision number */
10336 15, /* num auths */
10337 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10338 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10339 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10340 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10341 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10342 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10343 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10344 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10345 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10346 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10347 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10348 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10349 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10350 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10351 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10352 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10353 0x1, 0x1, 0x1, 0x1, /* auth[15] */
10354 0x1, 0x1, 0x1, 0x1, /* auth[16] */
10355 0x1, 0x1, 0x1, 0x1, /* auth[17] */
10358 static const uint8_t long_binary_sid2[] = {
10359 0x1, /* revision number */
10360 32, /* num auths */
10361 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10362 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10363 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10364 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10365 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10366 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10367 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10368 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10369 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10370 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10371 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10372 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10373 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10374 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10375 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10376 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10377 0x1, 0x1, 0x1, 0x1, /* auth[15] */
10378 0x1, 0x1, 0x1, 0x1, /* auth[16] */
10379 0x1, 0x1, 0x1, 0x1, /* auth[17] */
10380 0x1, 0x1, 0x1, 0x1, /* auth[18] */
10381 0x1, 0x1, 0x1, 0x1, /* auth[19] */
10382 0x1, 0x1, 0x1, 0x1, /* auth[20] */
10383 0x1, 0x1, 0x1, 0x1, /* auth[21] */
10384 0x1, 0x1, 0x1, 0x1, /* auth[22] */
10385 0x1, 0x1, 0x1, 0x1, /* auth[23] */
10386 0x1, 0x1, 0x1, 0x1, /* auth[24] */
10387 0x1, 0x1, 0x1, 0x1, /* auth[25] */
10388 0x1, 0x1, 0x1, 0x1, /* auth[26] */
10389 0x1, 0x1, 0x1, 0x1, /* auth[27] */
10390 0x1, 0x1, 0x1, 0x1, /* auth[28] */
10391 0x1, 0x1, 0x1, 0x1, /* auth[29] */
10392 0x1, 0x1, 0x1, 0x1, /* auth[30] */
10393 0x1, 0x1, 0x1, 0x1, /* auth[31] */
10396 if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
10397 return false;
10399 if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
10400 return false;
10402 if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
10403 return false;
10405 return true;
10408 /* Split a path name into filename and stream name components. Canonicalise
10409 * such that an implicit $DATA token is always explicit.
10411 * The "specification" of this function can be found in the
10412 * run_local_stream_name() function in torture.c, I've tried those
10413 * combinations against a W2k3 server.
10416 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
10417 char **pbase, char **pstream)
10419 char *base = NULL;
10420 char *stream = NULL;
10421 char *sname; /* stream name */
10422 const char *stype; /* stream type */
10424 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
10426 sname = strchr_m(fname, ':');
10428 if (sname == NULL) {
10429 if (pbase != NULL) {
10430 base = talloc_strdup(mem_ctx, fname);
10431 NT_STATUS_HAVE_NO_MEMORY(base);
10433 goto done;
10436 if (pbase != NULL) {
10437 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
10438 NT_STATUS_HAVE_NO_MEMORY(base);
10441 sname += 1;
10443 stype = strchr_m(sname, ':');
10445 if (stype == NULL) {
10446 sname = talloc_strdup(mem_ctx, sname);
10447 stype = "$DATA";
10449 else {
10450 if (strcasecmp_m(stype, ":$DATA") != 0) {
10452 * If there is an explicit stream type, so far we only
10453 * allow $DATA. Is there anything else allowed? -- vl
10455 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
10456 TALLOC_FREE(base);
10457 return NT_STATUS_OBJECT_NAME_INVALID;
10459 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
10460 stype += 1;
10463 if (sname == NULL) {
10464 TALLOC_FREE(base);
10465 return NT_STATUS_NO_MEMORY;
10468 if (sname[0] == '\0') {
10470 * no stream name, so no stream
10472 goto done;
10475 if (pstream != NULL) {
10476 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
10477 if (stream == NULL) {
10478 TALLOC_FREE(sname);
10479 TALLOC_FREE(base);
10480 return NT_STATUS_NO_MEMORY;
10483 * upper-case the type field
10485 (void)strupper_m(strchr_m(stream, ':')+1);
10488 done:
10489 if (pbase != NULL) {
10490 *pbase = base;
10492 if (pstream != NULL) {
10493 *pstream = stream;
10495 return NT_STATUS_OK;
10498 static bool test_stream_name(const char *fname, const char *expected_base,
10499 const char *expected_stream,
10500 NTSTATUS expected_status)
10502 NTSTATUS status;
10503 char *base = NULL;
10504 char *stream = NULL;
10506 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
10507 if (!NT_STATUS_EQUAL(status, expected_status)) {
10508 goto error;
10511 if (!NT_STATUS_IS_OK(status)) {
10512 return true;
10515 if (base == NULL) goto error;
10517 if (strcmp(expected_base, base) != 0) goto error;
10519 if ((expected_stream != NULL) && (stream == NULL)) goto error;
10520 if ((expected_stream == NULL) && (stream != NULL)) goto error;
10522 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
10523 goto error;
10525 TALLOC_FREE(base);
10526 TALLOC_FREE(stream);
10527 return true;
10529 error:
10530 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
10531 fname, expected_base ? expected_base : "<NULL>",
10532 expected_stream ? expected_stream : "<NULL>",
10533 nt_errstr(expected_status));
10534 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
10535 base ? base : "<NULL>", stream ? stream : "<NULL>",
10536 nt_errstr(status));
10537 TALLOC_FREE(base);
10538 TALLOC_FREE(stream);
10539 return false;
10542 static bool run_local_stream_name(int dummy)
10544 bool ret = true;
10546 ret &= test_stream_name(
10547 "bla", "bla", NULL, NT_STATUS_OK);
10548 ret &= test_stream_name(
10549 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
10550 ret &= test_stream_name(
10551 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
10552 ret &= test_stream_name(
10553 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
10554 ret &= test_stream_name(
10555 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
10556 ret &= test_stream_name(
10557 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
10558 ret &= test_stream_name(
10559 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
10560 ret &= test_stream_name(
10561 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
10563 return ret;
10566 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
10568 if (a.length != b.length) {
10569 printf("a.length=%d != b.length=%d\n",
10570 (int)a.length, (int)b.length);
10571 return false;
10573 if (memcmp(a.data, b.data, a.length) != 0) {
10574 printf("a.data and b.data differ\n");
10575 return false;
10577 return true;
10580 static bool run_local_memcache(int dummy)
10582 struct memcache *cache;
10583 DATA_BLOB k1, k2, k3;
10584 DATA_BLOB d1, d3;
10585 DATA_BLOB v1, v3;
10587 TALLOC_CTX *mem_ctx;
10588 char *ptr1 = NULL;
10589 char *ptr2 = NULL;
10591 char *str1, *str2;
10592 size_t size1, size2;
10593 bool ret = false;
10595 mem_ctx = talloc_init("foo");
10596 if (mem_ctx == NULL) {
10597 return false;
10600 /* STAT_CACHE TESTS */
10602 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
10604 if (cache == NULL) {
10605 printf("memcache_init failed\n");
10606 return false;
10609 d1 = data_blob_const("d1", 2);
10610 d3 = data_blob_const("d3", 2);
10612 k1 = data_blob_const("d1", 2);
10613 k2 = data_blob_const("d2", 2);
10614 k3 = data_blob_const("d3", 2);
10616 memcache_add(cache, STAT_CACHE, k1, d1);
10618 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
10619 printf("could not find k1\n");
10620 return false;
10622 if (!data_blob_equal(d1, v1)) {
10623 return false;
10626 memcache_add(cache, STAT_CACHE, k1, d3);
10628 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
10629 printf("could not find replaced k1\n");
10630 return false;
10632 if (!data_blob_equal(d3, v3)) {
10633 return false;
10636 TALLOC_FREE(cache);
10638 /* GETWD_CACHE TESTS */
10639 str1 = talloc_strdup(mem_ctx, "string1");
10640 if (str1 == NULL) {
10641 return false;
10643 ptr2 = str1; /* Keep an alias for comparison. */
10645 str2 = talloc_strdup(mem_ctx, "string2");
10646 if (str2 == NULL) {
10647 return false;
10650 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
10651 if (cache == NULL) {
10652 printf("memcache_init failed\n");
10653 return false;
10656 memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
10657 /* str1 == NULL now. */
10658 ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
10659 if (ptr1 == NULL) {
10660 printf("could not find k2\n");
10661 return false;
10663 if (ptr1 != ptr2) {
10664 printf("fetch of k2 got wrong string\n");
10665 return false;
10668 /* Add a blob to ensure k2 gets purged. */
10669 d3 = data_blob_talloc_zero(mem_ctx, 180);
10670 memcache_add(cache, STAT_CACHE, k3, d3);
10672 ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
10673 if (ptr2 != NULL) {
10674 printf("Did find k2, should have been purged\n");
10675 return false;
10678 TALLOC_FREE(cache);
10679 TALLOC_FREE(mem_ctx);
10681 mem_ctx = talloc_init("foo");
10682 if (mem_ctx == NULL) {
10683 return false;
10686 cache = memcache_init(NULL, 0);
10687 if (cache == NULL) {
10688 return false;
10691 str1 = talloc_strdup(mem_ctx, "string1");
10692 if (str1 == NULL) {
10693 return false;
10695 str2 = talloc_strdup(mem_ctx, "string2");
10696 if (str2 == NULL) {
10697 return false;
10699 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
10700 data_blob_string_const("torture"), &str1);
10701 size1 = talloc_total_size(cache);
10703 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
10704 data_blob_string_const("torture"), &str2);
10705 size2 = talloc_total_size(cache);
10707 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
10709 if (size2 > size1) {
10710 printf("memcache leaks memory!\n");
10711 goto fail;
10714 ret = true;
10715 fail:
10716 TALLOC_FREE(cache);
10717 return ret;
10720 static void wbclient_done(struct tevent_req *req)
10722 wbcErr wbc_err;
10723 struct winbindd_response *wb_resp;
10724 int *i = (int *)tevent_req_callback_data_void(req);
10726 wbc_err = wb_trans_recv(req, req, &wb_resp);
10727 TALLOC_FREE(req);
10728 *i += 1;
10729 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
10732 static bool run_wbclient_multi_ping(int dummy)
10734 struct tevent_context *ev;
10735 struct wb_context **wb_ctx;
10736 struct winbindd_request wb_req;
10737 bool result = false;
10738 int i, j;
10740 BlockSignals(True, SIGPIPE);
10742 ev = tevent_context_init(talloc_tos());
10743 if (ev == NULL) {
10744 goto fail;
10747 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
10748 if (wb_ctx == NULL) {
10749 goto fail;
10752 ZERO_STRUCT(wb_req);
10753 wb_req.cmd = WINBINDD_PING;
10755 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
10757 for (i=0; i<torture_nprocs; i++) {
10758 wb_ctx[i] = wb_context_init(ev, NULL);
10759 if (wb_ctx[i] == NULL) {
10760 goto fail;
10762 for (j=0; j<torture_numops; j++) {
10763 struct tevent_req *req;
10764 req = wb_trans_send(ev, ev, wb_ctx[i],
10765 (j % 2) == 0, &wb_req);
10766 if (req == NULL) {
10767 goto fail;
10769 tevent_req_set_callback(req, wbclient_done, &i);
10773 i = 0;
10775 while (i < torture_nprocs * torture_numops) {
10776 tevent_loop_once(ev);
10779 result = true;
10780 fail:
10781 TALLOC_FREE(ev);
10782 return result;
10785 static void getaddrinfo_finished(struct tevent_req *req)
10787 char *name = (char *)tevent_req_callback_data_void(req);
10788 struct addrinfo *ainfo;
10789 int res;
10791 res = getaddrinfo_recv(req, &ainfo);
10792 if (res != 0) {
10793 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
10794 return;
10796 d_printf("gai(%s) succeeded\n", name);
10797 freeaddrinfo(ainfo);
10800 static bool run_getaddrinfo_send(int dummy)
10802 TALLOC_CTX *frame = talloc_stackframe();
10803 struct fncall_context *ctx;
10804 struct tevent_context *ev;
10805 bool result = false;
10806 const char *names[4] = { "www.samba.org", "notfound.samba.org",
10807 "www.slashdot.org", "heise.de" };
10808 struct tevent_req *reqs[4];
10809 int i;
10811 ev = samba_tevent_context_init(frame);
10812 if (ev == NULL) {
10813 goto fail;
10816 ctx = fncall_context_init(frame, 4);
10818 for (i=0; i<ARRAY_SIZE(names); i++) {
10819 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
10820 NULL);
10821 if (reqs[i] == NULL) {
10822 goto fail;
10824 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
10825 discard_const_p(void, names[i]));
10828 for (i=0; i<ARRAY_SIZE(reqs); i++) {
10829 tevent_loop_once(ev);
10832 result = true;
10833 fail:
10834 TALLOC_FREE(frame);
10835 return result;
10838 static bool dbtrans_inc(struct db_context *db)
10840 struct db_record *rec;
10841 uint32_t val;
10842 bool ret = false;
10843 NTSTATUS status;
10844 TDB_DATA value;
10846 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
10847 if (rec == NULL) {
10848 printf(__location__ "fetch_lock failed\n");
10849 return false;
10852 value = dbwrap_record_get_value(rec);
10854 if (value.dsize != sizeof(uint32_t)) {
10855 printf(__location__ "value.dsize = %d\n",
10856 (int)value.dsize);
10857 goto fail;
10860 memcpy(&val, value.dptr, sizeof(val));
10861 val += 1;
10863 status = dbwrap_record_store(
10864 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
10865 if (!NT_STATUS_IS_OK(status)) {
10866 printf(__location__ "store failed: %s\n",
10867 nt_errstr(status));
10868 goto fail;
10871 ret = true;
10872 fail:
10873 TALLOC_FREE(rec);
10874 return ret;
10877 static bool run_local_dbtrans(int dummy)
10879 struct db_context *db;
10880 struct db_record *rec;
10881 NTSTATUS status;
10882 uint32_t initial;
10883 int res;
10884 TDB_DATA value;
10886 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
10887 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
10888 DBWRAP_FLAG_NONE);
10889 if (db == NULL) {
10890 printf("Could not open transtest.db\n");
10891 return false;
10894 res = dbwrap_transaction_start(db);
10895 if (res != 0) {
10896 printf(__location__ "transaction_start failed\n");
10897 return false;
10900 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
10901 if (rec == NULL) {
10902 printf(__location__ "fetch_lock failed\n");
10903 return false;
10906 value = dbwrap_record_get_value(rec);
10908 if (value.dptr == NULL) {
10909 initial = 0;
10910 status = dbwrap_record_store(
10911 rec, make_tdb_data((uint8_t *)&initial,
10912 sizeof(initial)),
10914 if (!NT_STATUS_IS_OK(status)) {
10915 printf(__location__ "store returned %s\n",
10916 nt_errstr(status));
10917 return false;
10921 TALLOC_FREE(rec);
10923 res = dbwrap_transaction_commit(db);
10924 if (res != 0) {
10925 printf(__location__ "transaction_commit failed\n");
10926 return false;
10929 while (true) {
10930 uint32_t val, val2;
10931 int i;
10933 res = dbwrap_transaction_start(db);
10934 if (res != 0) {
10935 printf(__location__ "transaction_start failed\n");
10936 break;
10939 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
10940 if (!NT_STATUS_IS_OK(status)) {
10941 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
10942 nt_errstr(status));
10943 break;
10946 for (i=0; i<10; i++) {
10947 if (!dbtrans_inc(db)) {
10948 return false;
10952 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
10953 if (!NT_STATUS_IS_OK(status)) {
10954 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
10955 nt_errstr(status));
10956 break;
10959 if (val2 != val + 10) {
10960 printf(__location__ "val=%d, val2=%d\n",
10961 (int)val, (int)val2);
10962 break;
10965 printf("val2=%d\r", val2);
10967 res = dbwrap_transaction_commit(db);
10968 if (res != 0) {
10969 printf(__location__ "transaction_commit failed\n");
10970 break;
10974 TALLOC_FREE(db);
10975 return true;
10979 * Just a dummy test to be run under a debugger. There's no real way
10980 * to inspect the tevent_select specific function from outside of
10981 * tevent_select.c.
10984 static bool run_local_tevent_select(int dummy)
10986 struct tevent_context *ev;
10987 struct tevent_fd *fd1, *fd2;
10988 bool result = false;
10990 ev = tevent_context_init_byname(NULL, "select");
10991 if (ev == NULL) {
10992 d_fprintf(stderr, "tevent_context_init_byname failed\n");
10993 goto fail;
10996 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
10997 if (fd1 == NULL) {
10998 d_fprintf(stderr, "tevent_add_fd failed\n");
10999 goto fail;
11001 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
11002 if (fd2 == NULL) {
11003 d_fprintf(stderr, "tevent_add_fd failed\n");
11004 goto fail;
11006 TALLOC_FREE(fd2);
11008 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
11009 if (fd2 == NULL) {
11010 d_fprintf(stderr, "tevent_add_fd failed\n");
11011 goto fail;
11014 result = true;
11015 fail:
11016 TALLOC_FREE(ev);
11017 return result;
11020 static bool run_local_hex_encode_buf(int dummy)
11022 char buf[17];
11023 uint8_t src[8];
11024 int i;
11026 for (i=0; i<sizeof(src); i++) {
11027 src[i] = i;
11029 hex_encode_buf(buf, src, sizeof(src));
11030 if (strcmp(buf, "0001020304050607") != 0) {
11031 return false;
11033 hex_encode_buf(buf, NULL, 0);
11034 if (buf[0] != '\0') {
11035 return false;
11037 return true;
11040 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
11041 "0.0.0.0",
11042 "::0",
11043 "1.2.3.1",
11044 "0.0.0.0",
11045 "0.0.0.0",
11046 "1.2.3.2",
11047 "1.2.3.3",
11048 "1.2.3.4",
11049 "1.2.3.5",
11050 "::0",
11051 "1.2.3.6",
11052 "1.2.3.7",
11053 "::0",
11054 "::0",
11055 "::0",
11056 "1.2.3.8",
11057 "1.2.3.9",
11058 "1.2.3.10",
11059 "1.2.3.11",
11060 "1.2.3.12",
11061 "1.2.3.13",
11062 "1001:1111:1111:1000:0:1111:1111:1111",
11063 "1.2.3.1",
11064 "1.2.3.2",
11065 "1.2.3.3",
11066 "1.2.3.12",
11067 "::0",
11068 "::0"
11071 static const char *remove_duplicate_addrs2_test_strings_result[] = {
11072 "1.2.3.1",
11073 "1.2.3.2",
11074 "1.2.3.3",
11075 "1.2.3.4",
11076 "1.2.3.5",
11077 "1.2.3.6",
11078 "1.2.3.7",
11079 "1.2.3.8",
11080 "1.2.3.9",
11081 "1.2.3.10",
11082 "1.2.3.11",
11083 "1.2.3.12",
11084 "1.2.3.13",
11085 "1001:1111:1111:1000:0:1111:1111:1111"
11088 static bool run_local_remove_duplicate_addrs2(int dummy)
11090 struct ip_service test_vector[28];
11091 int count, i;
11093 /* Construct the sockaddr_storage test vector. */
11094 for (i = 0; i < 28; i++) {
11095 struct addrinfo hints;
11096 struct addrinfo *res = NULL;
11097 int ret;
11099 memset(&hints, '\0', sizeof(hints));
11100 hints.ai_flags = AI_NUMERICHOST;
11101 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
11102 NULL,
11103 &hints,
11104 &res);
11105 if (ret) {
11106 fprintf(stderr, "getaddrinfo failed on [%s]\n",
11107 remove_duplicate_addrs2_test_strings_vector[i]);
11108 return false;
11110 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
11111 memcpy(&test_vector[i].ss,
11112 res->ai_addr,
11113 res->ai_addrlen);
11114 freeaddrinfo(res);
11117 count = remove_duplicate_addrs2(test_vector, i);
11119 if (count != 14) {
11120 fprintf(stderr, "count wrong (%d) should be 14\n",
11121 count);
11122 return false;
11125 for (i = 0; i < count; i++) {
11126 char addr[INET6_ADDRSTRLEN];
11128 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
11130 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
11131 fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
11133 addr,
11134 remove_duplicate_addrs2_test_strings_result[i]);
11135 return false;
11139 printf("run_local_remove_duplicate_addrs2: success\n");
11140 return true;
11143 static bool run_local_tdb_opener(int dummy)
11145 TDB_CONTEXT *t;
11146 unsigned v = 0;
11148 while (1) {
11149 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
11150 O_RDWR|O_CREAT, 0755);
11151 if (t == NULL) {
11152 perror("tdb_open failed");
11153 return false;
11155 tdb_close(t);
11157 v += 1;
11158 printf("\r%u", v);
11160 return true;
11163 static bool run_local_tdb_writer(int dummy)
11165 TDB_CONTEXT *t;
11166 unsigned v = 0;
11167 TDB_DATA val;
11169 t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
11170 if (t == 0) {
11171 perror("tdb_open failed");
11172 return 1;
11175 val.dptr = (uint8_t *)&v;
11176 val.dsize = sizeof(v);
11178 while (1) {
11179 TDB_DATA data;
11180 int ret;
11182 ret = tdb_store(t, val, val, 0);
11183 if (ret != 0) {
11184 printf("%s\n", tdb_errorstr(t));
11186 v += 1;
11187 printf("\r%u", v);
11189 data = tdb_fetch(t, val);
11190 if (data.dptr != NULL) {
11191 SAFE_FREE(data.dptr);
11194 return true;
11197 static bool run_local_canonicalize_path(int dummy)
11199 const char *src[] = {
11200 "/foo/..",
11201 "/..",
11202 "/foo/bar/../baz",
11203 "/foo/././",
11204 "/../foo",
11205 ".././././",
11206 ".././././../../../boo",
11207 "./..",
11208 NULL
11210 const char *dst[] = {
11211 "/",
11212 "/",
11213 "/foo/baz",
11214 "/foo",
11215 "/foo",
11216 "/",
11217 "/boo",
11218 "/",
11219 NULL
11221 unsigned int i;
11223 for (i = 0; src[i] != NULL; i++) {
11224 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
11225 if (d == NULL) {
11226 perror("talloc fail\n");
11227 return false;
11229 if (strcmp(d, dst[i]) != 0) {
11230 d_fprintf(stderr,
11231 "canonicalize missmatch %s -> %s != %s",
11232 src[i], d, dst[i]);
11233 return false;
11235 talloc_free(d);
11237 return true;
11240 static bool run_ign_bad_negprot(int dummy)
11242 struct tevent_context *ev;
11243 struct tevent_req *req;
11244 struct smbXcli_conn *conn;
11245 struct sockaddr_storage ss;
11246 NTSTATUS status;
11247 int fd;
11248 bool ok;
11250 printf("starting ignore bad negprot\n");
11252 ok = resolve_name(host, &ss, 0x20, true);
11253 if (!ok) {
11254 d_fprintf(stderr, "Could not resolve name %s\n", host);
11255 return false;
11258 status = open_socket_out(&ss, 445, 10000, &fd);
11259 if (!NT_STATUS_IS_OK(status)) {
11260 d_fprintf(stderr, "open_socket_out failed: %s\n",
11261 nt_errstr(status));
11262 return false;
11265 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
11266 NULL, 0);
11267 if (conn == NULL) {
11268 d_fprintf(stderr, "smbXcli_conn_create failed\n");
11269 return false;
11272 status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
11273 if (NT_STATUS_IS_OK(status)) {
11274 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
11275 return false;
11278 ev = samba_tevent_context_init(talloc_tos());
11279 if (ev == NULL) {
11280 d_fprintf(stderr, "samba_tevent_context_init failed\n");
11281 return false;
11284 req = smb1cli_session_setup_nt1_send(
11285 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
11286 data_blob_null, data_blob_null, 0x40,
11287 "Windows 2000 2195", "Windows 2000 5.0");
11288 if (req == NULL) {
11289 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
11290 return false;
11293 ok = tevent_req_poll_ntstatus(req, ev, &status);
11294 if (!ok) {
11295 d_fprintf(stderr, "tevent_req_poll failed\n");
11296 return false;
11299 status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
11300 NULL, NULL);
11301 if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
11302 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
11303 "%s, expected NT_STATUS_CONNECTION_RESET\n",
11304 nt_errstr(status));
11305 return false;
11308 TALLOC_FREE(conn);
11310 printf("starting ignore bad negprot\n");
11312 return true;
11315 static double create_procs(bool (*fn)(int), bool *result)
11317 int i, status;
11318 volatile pid_t *child_status;
11319 volatile bool *child_status_out;
11320 int synccount;
11321 int tries = 8;
11322 struct timeval start;
11324 synccount = 0;
11326 child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
11327 if (!child_status) {
11328 printf("Failed to setup shared memory\n");
11329 return -1;
11332 child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
11333 if (!child_status_out) {
11334 printf("Failed to setup result status shared memory\n");
11335 return -1;
11338 for (i = 0; i < torture_nprocs; i++) {
11339 child_status[i] = 0;
11340 child_status_out[i] = True;
11343 start = timeval_current();
11345 for (i=0;i<torture_nprocs;i++) {
11346 procnum = i;
11347 if (fork() == 0) {
11348 pid_t mypid = getpid();
11349 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
11351 slprintf(myname,sizeof(myname),"CLIENT%d", i);
11353 while (1) {
11354 if (torture_open_connection(&current_cli, i)) break;
11355 if (tries-- == 0) {
11356 printf("pid %d failed to start\n", (int)getpid());
11357 _exit(1);
11359 smb_msleep(10);
11362 child_status[i] = getpid();
11364 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
11366 child_status_out[i] = fn(i);
11367 _exit(0);
11371 do {
11372 synccount = 0;
11373 for (i=0;i<torture_nprocs;i++) {
11374 if (child_status[i]) synccount++;
11376 if (synccount == torture_nprocs) break;
11377 smb_msleep(10);
11378 } while (timeval_elapsed(&start) < 30);
11380 if (synccount != torture_nprocs) {
11381 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
11382 *result = False;
11383 return timeval_elapsed(&start);
11386 /* start the client load */
11387 start = timeval_current();
11389 for (i=0;i<torture_nprocs;i++) {
11390 child_status[i] = 0;
11393 printf("%d clients started\n", torture_nprocs);
11395 for (i=0;i<torture_nprocs;i++) {
11396 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
11399 printf("\n");
11401 for (i=0;i<torture_nprocs;i++) {
11402 if (!child_status_out[i]) {
11403 *result = False;
11406 return timeval_elapsed(&start);
11409 #define FLAG_MULTIPROC 1
11411 static struct {
11412 const char *name;
11413 bool (*fn)(int);
11414 unsigned flags;
11415 } torture_ops[] = {
11416 {"FDPASS", run_fdpasstest, 0},
11417 {"LOCK1", run_locktest1, 0},
11418 {"LOCK2", run_locktest2, 0},
11419 {"LOCK3", run_locktest3, 0},
11420 {"LOCK4", run_locktest4, 0},
11421 {"LOCK5", run_locktest5, 0},
11422 {"LOCK6", run_locktest6, 0},
11423 {"LOCK7", run_locktest7, 0},
11424 {"LOCK8", run_locktest8, 0},
11425 {"LOCK9", run_locktest9, 0},
11426 {"UNLINK", run_unlinktest, 0},
11427 {"BROWSE", run_browsetest, 0},
11428 {"ATTR", run_attrtest, 0},
11429 {"TRANS2", run_trans2test, 0},
11430 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
11431 {"TORTURE",run_torture, FLAG_MULTIPROC},
11432 {"RANDOMIPC", run_randomipc, 0},
11433 {"NEGNOWAIT", run_negprot_nowait, 0},
11434 {"NBENCH", run_nbench, 0},
11435 {"NBENCH2", run_nbench2, 0},
11436 {"OPLOCK1", run_oplock1, 0},
11437 {"OPLOCK2", run_oplock2, 0},
11438 {"OPLOCK4", run_oplock4, 0},
11439 {"DIR", run_dirtest, 0},
11440 {"DIR1", run_dirtest1, 0},
11441 {"DIR-CREATETIME", run_dir_createtime, 0},
11442 {"DENY1", torture_denytest1, 0},
11443 {"DENY2", torture_denytest2, 0},
11444 {"TCON", run_tcon_test, 0},
11445 {"TCONDEV", run_tcon_devtype_test, 0},
11446 {"RW1", run_readwritetest, 0},
11447 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
11448 {"RW3", run_readwritelarge, 0},
11449 {"RW-SIGNING", run_readwritelarge_signtest, 0},
11450 {"OPEN", run_opentest, 0},
11451 {"POSIX", run_simple_posix_open_test, 0},
11452 {"POSIX-APPEND", run_posix_append, 0},
11453 {"POSIX-SYMLINK-ACL", run_acl_symlink_test, 0},
11454 {"POSIX-SYMLINK-EA", run_ea_symlink_test, 0},
11455 {"POSIX-STREAM-DELETE", run_posix_stream_delete, 0},
11456 {"POSIX-OFD-LOCK", run_posix_ofd_lock_test, 0},
11457 {"WINDOWS-BAD-SYMLINK", run_symlink_open_test, 0},
11458 {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
11459 {"ASYNC-ECHO", run_async_echo, 0},
11460 { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
11461 { "SHORTNAME-TEST", run_shortname_test, 0},
11462 { "ADDRCHANGE", run_addrchange, 0},
11463 #if 1
11464 {"OPENATTR", run_openattrtest, 0},
11465 #endif
11466 {"XCOPY", run_xcopy, 0},
11467 {"RENAME", run_rename, 0},
11468 {"RENAME-ACCESS", run_rename_access, 0},
11469 {"OWNER-RIGHTS", run_owner_rights, 0},
11470 {"DELETE", run_deletetest, 0},
11471 {"WILDDELETE", run_wild_deletetest, 0},
11472 {"DELETE-LN", run_deletetest_ln, 0},
11473 {"PROPERTIES", run_properties, 0},
11474 {"MANGLE", torture_mangle, 0},
11475 {"MANGLE1", run_mangle1, 0},
11476 {"MANGLE-ILLEGAL", run_mangle_illegal, 0},
11477 {"W2K", run_w2ktest, 0},
11478 {"TRANS2SCAN", torture_trans2_scan, 0},
11479 {"NTTRANSSCAN", torture_nttrans_scan, 0},
11480 {"UTABLE", torture_utable, 0},
11481 {"CASETABLE", torture_casetable, 0},
11482 {"ERRMAPEXTRACT", run_error_map_extract, 0},
11483 {"PIPE_NUMBER", run_pipe_number, 0},
11484 {"TCON2", run_tcon2_test, 0},
11485 {"IOCTL", torture_ioctl_test, 0},
11486 {"CHKPATH", torture_chkpath_test, 0},
11487 {"FDSESS", run_fdsesstest, 0},
11488 { "EATEST", run_eatest, 0},
11489 { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
11490 { "CHAIN1", run_chain1, 0},
11491 { "CHAIN2", run_chain2, 0},
11492 { "CHAIN3", run_chain3, 0},
11493 { "WINDOWS-WRITE", run_windows_write, 0},
11494 { "LARGE_READX", run_large_readx, 0},
11495 { "NTTRANS-CREATE", run_nttrans_create, 0},
11496 { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
11497 { "CLI_ECHO", run_cli_echo, 0},
11498 { "GETADDRINFO", run_getaddrinfo_send, 0},
11499 { "TLDAP", run_tldap },
11500 { "STREAMERROR", run_streamerror },
11501 { "NOTIFY-BENCH", run_notify_bench },
11502 { "NOTIFY-BENCH2", run_notify_bench2 },
11503 { "NOTIFY-BENCH3", run_notify_bench3 },
11504 { "BAD-NBT-SESSION", run_bad_nbt_session },
11505 { "IGN-BAD-NEGPROT", run_ign_bad_negprot },
11506 { "SMB-ANY-CONNECT", run_smb_any_connect },
11507 { "NOTIFY-ONLINE", run_notify_online },
11508 { "SMB2-BASIC", run_smb2_basic },
11509 { "SMB2-NEGPROT", run_smb2_negprot },
11510 { "SMB2-SESSION-RECONNECT", run_smb2_session_reconnect },
11511 { "SMB2-TCON-DEPENDENCE", run_smb2_tcon_dependence },
11512 { "SMB2-MULTI-CHANNEL", run_smb2_multi_channel },
11513 { "SMB2-SESSION-REAUTH", run_smb2_session_reauth },
11514 { "SMB2-FTRUNCATE", run_smb2_ftruncate },
11515 { "CLEANUP1", run_cleanup1 },
11516 { "CLEANUP2", run_cleanup2 },
11517 { "CLEANUP3", run_cleanup3 },
11518 { "CLEANUP4", run_cleanup4 },
11519 { "OPLOCK-CANCEL", run_oplock_cancel },
11520 { "PIDHIGH", run_pidhigh },
11521 { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
11522 { "LOCAL-GENCACHE", run_local_gencache, 0},
11523 { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
11524 { "LOCAL-DBWRAP-WATCH1", run_dbwrap_watch1, 0 },
11525 { "LOCAL-DBWRAP-WATCH2", run_dbwrap_watch2, 0 },
11526 { "LOCAL-MESSAGING-READ1", run_messaging_read1, 0 },
11527 { "LOCAL-MESSAGING-READ2", run_messaging_read2, 0 },
11528 { "LOCAL-MESSAGING-READ3", run_messaging_read3, 0 },
11529 { "LOCAL-MESSAGING-READ4", run_messaging_read4, 0 },
11530 { "LOCAL-MESSAGING-FDPASS1", run_messaging_fdpass1, 0 },
11531 { "LOCAL-MESSAGING-FDPASS2", run_messaging_fdpass2, 0 },
11532 { "LOCAL-MESSAGING-FDPASS2a", run_messaging_fdpass2a, 0 },
11533 { "LOCAL-MESSAGING-FDPASS2b", run_messaging_fdpass2b, 0 },
11534 { "LOCAL-BASE64", run_local_base64, 0},
11535 { "LOCAL-RBTREE", run_local_rbtree, 0},
11536 { "LOCAL-MEMCACHE", run_local_memcache, 0},
11537 { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
11538 { "WBCLIENT-MULTI-PING", run_wbclient_multi_ping, 0},
11539 { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
11540 { "LOCAL-sid_to_string", run_local_sid_to_string, 0},
11541 { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
11542 { "LOCAL-DBTRANS", run_local_dbtrans, 0},
11543 { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
11544 { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
11545 { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
11546 { "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0},
11547 { "LOCAL-IDMAP-TDB-COMMON", run_idmap_tdb_common_test, 0},
11548 { "LOCAL-remove_duplicate_addrs2", run_local_remove_duplicate_addrs2, 0},
11549 { "local-tdb-opener", run_local_tdb_opener, 0 },
11550 { "local-tdb-writer", run_local_tdb_writer, 0 },
11551 { "LOCAL-DBWRAP-CTDB", run_local_dbwrap_ctdb, 0 },
11552 { "LOCAL-BENCH-PTHREADPOOL", run_bench_pthreadpool, 0 },
11553 { "LOCAL-PTHREADPOOL-TEVENT", run_pthreadpool_tevent, 0 },
11554 { "LOCAL-G-LOCK1", run_g_lock1, 0 },
11555 { "LOCAL-G-LOCK2", run_g_lock2, 0 },
11556 { "LOCAL-G-LOCK3", run_g_lock3, 0 },
11557 { "LOCAL-G-LOCK4", run_g_lock4, 0 },
11558 { "LOCAL-G-LOCK5", run_g_lock5, 0 },
11559 { "LOCAL-CANONICALIZE-PATH", run_local_canonicalize_path, 0 },
11560 { "qpathinfo-bufsize", run_qpathinfo_bufsize, 0 },
11561 {NULL, NULL, 0}};
11564 * dummy function to satisfy linker dependency
11566 struct tevent_context *winbind_event_context(void);
11567 struct tevent_context *winbind_event_context(void)
11569 return NULL;
11572 /****************************************************************************
11573 run a specified test or "ALL"
11574 ****************************************************************************/
11575 static bool run_test(const char *name)
11577 bool ret = True;
11578 bool result = True;
11579 bool found = False;
11580 int i;
11581 double t;
11582 if (strequal(name,"ALL")) {
11583 for (i=0;torture_ops[i].name;i++) {
11584 run_test(torture_ops[i].name);
11586 found = True;
11589 for (i=0;torture_ops[i].name;i++) {
11590 fstr_sprintf(randomfname, "\\XX%x",
11591 (unsigned)random());
11593 if (strequal(name, torture_ops[i].name)) {
11594 found = True;
11595 printf("Running %s\n", name);
11596 if (torture_ops[i].flags & FLAG_MULTIPROC) {
11597 t = create_procs(torture_ops[i].fn, &result);
11598 if (!result) {
11599 ret = False;
11600 printf("TEST %s FAILED!\n", name);
11602 } else {
11603 struct timeval start;
11604 start = timeval_current();
11605 if (!torture_ops[i].fn(0)) {
11606 ret = False;
11607 printf("TEST %s FAILED!\n", name);
11609 t = timeval_elapsed(&start);
11611 printf("%s took %g secs\n\n", name, t);
11615 if (!found) {
11616 printf("Did not find a test named %s\n", name);
11617 ret = False;
11620 return ret;
11624 static void usage(void)
11626 int i;
11628 printf("WARNING samba4 test suite is much more complete nowadays.\n");
11629 printf("Please use samba4 torture.\n\n");
11631 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
11633 printf("\t-d debuglevel\n");
11634 printf("\t-U user%%pass\n");
11635 printf("\t-k use kerberos\n");
11636 printf("\t-N numprocs\n");
11637 printf("\t-n my_netbios_name\n");
11638 printf("\t-W workgroup\n");
11639 printf("\t-o num_operations\n");
11640 printf("\t-O socket_options\n");
11641 printf("\t-m maximum protocol\n");
11642 printf("\t-L use oplocks\n");
11643 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
11644 printf("\t-A showall\n");
11645 printf("\t-p port\n");
11646 printf("\t-s seed\n");
11647 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
11648 printf("\t-f filename filename to test\n");
11649 printf("\t-e encrypt\n");
11650 printf("\n\n");
11652 printf("tests are:");
11653 for (i=0;torture_ops[i].name;i++) {
11654 printf(" %s", torture_ops[i].name);
11656 printf("\n");
11658 printf("default test is ALL\n");
11660 exit(1);
11663 /****************************************************************************
11664 main program
11665 ****************************************************************************/
11666 int main(int argc,char *argv[])
11668 int opt, i;
11669 char *p;
11670 int gotuser = 0;
11671 int gotpass = 0;
11672 bool correct = True;
11673 TALLOC_CTX *frame = talloc_stackframe();
11674 int seed = time(NULL);
11676 #ifdef HAVE_SETBUFFER
11677 setbuffer(stdout, NULL, 0);
11678 #endif
11680 setup_logging("smbtorture", DEBUG_STDOUT);
11682 smb_init_locale();
11683 fault_setup();
11685 if (is_default_dyn_CONFIGFILE()) {
11686 if(getenv("SMB_CONF_PATH")) {
11687 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
11690 lp_load_global(get_dyn_CONFIGFILE());
11691 load_interfaces();
11693 if (argc < 2) {
11694 usage();
11697 for(p = argv[1]; *p; p++)
11698 if(*p == '\\')
11699 *p = '/';
11701 if (strncmp(argv[1], "//", 2)) {
11702 usage();
11705 fstrcpy(host, &argv[1][2]);
11706 p = strchr_m(&host[2],'/');
11707 if (!p) {
11708 usage();
11710 *p = 0;
11711 fstrcpy(share, p+1);
11713 fstrcpy(myname, get_myname(talloc_tos()));
11714 if (!*myname) {
11715 fprintf(stderr, "Failed to get my hostname.\n");
11716 return 1;
11719 if (*username == 0 && getenv("LOGNAME")) {
11720 fstrcpy(username,getenv("LOGNAME"));
11723 argc--;
11724 argv++;
11726 fstrcpy(workgroup, lp_workgroup());
11728 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
11729 != EOF) {
11730 switch (opt) {
11731 case 'p':
11732 port_to_use = atoi(optarg);
11733 break;
11734 case 's':
11735 seed = atoi(optarg);
11736 break;
11737 case 'W':
11738 fstrcpy(workgroup,optarg);
11739 break;
11740 case 'm':
11741 lp_set_cmdline("client max protocol", optarg);
11742 break;
11743 case 'N':
11744 torture_nprocs = atoi(optarg);
11745 break;
11746 case 'o':
11747 torture_numops = atoi(optarg);
11748 break;
11749 case 'd':
11750 lp_set_cmdline("log level", optarg);
11751 break;
11752 case 'O':
11753 sockops = optarg;
11754 break;
11755 case 'L':
11756 use_oplocks = True;
11757 break;
11758 case 'l':
11759 local_path = optarg;
11760 break;
11761 case 'A':
11762 torture_showall = True;
11763 break;
11764 case 'n':
11765 fstrcpy(myname, optarg);
11766 break;
11767 case 'c':
11768 client_txt = optarg;
11769 break;
11770 case 'e':
11771 do_encrypt = true;
11772 break;
11773 case 'k':
11774 #ifdef HAVE_KRB5
11775 use_kerberos = True;
11776 #else
11777 d_printf("No kerberos support compiled in\n");
11778 exit(1);
11779 #endif
11780 break;
11781 case 'U':
11782 gotuser = 1;
11783 fstrcpy(username,optarg);
11784 p = strchr_m(username,'%');
11785 if (p) {
11786 *p = 0;
11787 fstrcpy(password, p+1);
11788 gotpass = 1;
11790 break;
11791 case 'b':
11792 fstrcpy(multishare_conn_fname, optarg);
11793 use_multishare_conn = True;
11794 break;
11795 case 'B':
11796 torture_blocksize = atoi(optarg);
11797 break;
11798 case 'f':
11799 test_filename = SMB_STRDUP(optarg);
11800 break;
11801 default:
11802 printf("Unknown option %c (%d)\n", (char)opt, opt);
11803 usage();
11807 d_printf("using seed %d\n", seed);
11809 srandom(seed);
11811 if(use_kerberos && !gotuser) gotpass = True;
11813 while (!gotpass) {
11814 char pwd[256] = {0};
11815 int rc;
11817 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
11818 if (rc == 0) {
11819 fstrcpy(password, pwd);
11820 gotpass = 1;
11824 printf("host=%s share=%s user=%s myname=%s\n",
11825 host, share, username, myname);
11827 torture_creds = cli_session_creds_init(frame,
11828 username,
11829 workgroup,
11830 NULL, /* realm */
11831 password,
11832 use_kerberos,
11833 false, /* fallback_after_kerberos */
11834 false, /* use_ccache */
11835 false); /* password_is_nt_hash */
11836 if (torture_creds == NULL) {
11837 d_printf("cli_session_creds_init() failed.\n");
11838 exit(1);
11841 if (argc == optind) {
11842 correct = run_test("ALL");
11843 } else {
11844 for (i=optind;i<argc;i++) {
11845 if (!run_test(argv[i])) {
11846 correct = False;
11851 TALLOC_FREE(frame);
11853 if (correct) {
11854 return(0);
11855 } else {
11856 return(1);