torture3: Test lock upgrade/downgrade
[Samba.git] / source3 / torture / torture.c
blob4661da95d78d52a3221bbc1336354da86a98c3fe
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)
331 int flags = 0;
332 NTSTATUS status;
334 if (use_oplocks)
335 flags |= CLI_FULL_CONNECTION_OPLOCKS;
336 if (use_level_II_oplocks)
337 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
339 status = cli_full_connection_creds(c,
340 myname,
341 hostname,
342 NULL, /* dest_ss */
343 port_to_use,
344 sharename,
345 "?????",
346 torture_creds,
347 flags,
348 signing_state);
349 if (!NT_STATUS_IS_OK(status)) {
350 printf("failed to open share connection: //%s/%s port:%d - %s\n",
351 hostname, sharename, port_to_use, nt_errstr(status));
352 return False;
355 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
357 if (do_encrypt) {
358 return force_cli_encryption(*c,
359 sharename);
361 return True;
364 bool torture_open_connection(struct cli_state **c, int conn_index)
366 char **unc_list = NULL;
367 int num_unc_names = 0;
368 bool result;
370 if (use_multishare_conn==True) {
371 char *h, *s;
372 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
373 if (!unc_list || num_unc_names <= 0) {
374 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
375 exit(1);
378 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
379 NULL, &h, &s)) {
380 printf("Failed to parse UNC name %s\n",
381 unc_list[conn_index % num_unc_names]);
382 TALLOC_FREE(unc_list);
383 exit(1);
386 result = torture_open_connection_share(c, h, s);
388 /* h, s were copied earlier */
389 TALLOC_FREE(unc_list);
390 return result;
393 return torture_open_connection_share(c, host, share);
396 bool torture_init_connection(struct cli_state **pcli)
398 struct cli_state *cli;
400 cli = open_nbt_connection();
401 if (cli == NULL) {
402 return false;
405 *pcli = cli;
406 return true;
409 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
411 uint16_t old_vuid = cli_state_get_uid(cli);
412 NTSTATUS status;
413 bool ret;
415 cli_state_set_uid(cli, 0);
416 status = cli_session_setup_creds(cli, torture_creds);
417 ret = NT_STATUS_IS_OK(status);
418 *new_vuid = cli_state_get_uid(cli);
419 cli_state_set_uid(cli, old_vuid);
420 return ret;
424 bool torture_close_connection(struct cli_state *c)
426 bool ret = True;
427 NTSTATUS status;
429 status = cli_tdis(c);
430 if (!NT_STATUS_IS_OK(status)) {
431 printf("tdis failed (%s)\n", nt_errstr(status));
432 ret = False;
435 cli_shutdown(c);
437 return ret;
441 /* check if the server produced the expected dos or nt error code */
442 static bool check_both_error(int line, NTSTATUS status,
443 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
445 if (NT_STATUS_IS_DOS(status)) {
446 uint8_t cclass;
447 uint32_t num;
449 /* Check DOS error */
450 cclass = NT_STATUS_DOS_CLASS(status);
451 num = NT_STATUS_DOS_CODE(status);
453 if (eclass != cclass || ecode != num) {
454 printf("unexpected error code class=%d code=%d\n",
455 (int)cclass, (int)num);
456 printf(" expected %d/%d %s (line=%d)\n",
457 (int)eclass, (int)ecode, nt_errstr(nterr), line);
458 return false;
460 } else {
461 /* Check NT error */
462 if (!NT_STATUS_EQUAL(nterr, status)) {
463 printf("unexpected error code %s\n",
464 nt_errstr(status));
465 printf(" expected %s (line=%d)\n",
466 nt_errstr(nterr), line);
467 return false;
471 return true;
475 /* check if the server produced the expected error code */
476 static bool check_error(int line, NTSTATUS status,
477 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
479 if (NT_STATUS_IS_DOS(status)) {
480 uint8_t cclass;
481 uint32_t num;
483 /* Check DOS error */
485 cclass = NT_STATUS_DOS_CLASS(status);
486 num = NT_STATUS_DOS_CODE(status);
488 if (eclass != cclass || ecode != num) {
489 printf("unexpected error code class=%d code=%d\n",
490 (int)cclass, (int)num);
491 printf(" expected %d/%d %s (line=%d)\n",
492 (int)eclass, (int)ecode, nt_errstr(nterr),
493 line);
494 return False;
497 } else {
498 /* Check NT error */
500 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
501 printf("unexpected error code %s\n",
502 nt_errstr(status));
503 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
504 line);
505 return False;
509 return True;
513 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
515 NTSTATUS status;
517 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
519 while (!NT_STATUS_IS_OK(status)) {
520 if (!check_both_error(__LINE__, status, ERRDOS,
521 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
522 return false;
525 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
528 return true;
532 static bool rw_torture(struct cli_state *c)
534 const char *lockfname = "\\torture.lck";
535 fstring fname;
536 uint16_t fnum;
537 uint16_t fnum2;
538 pid_t pid2, pid = getpid();
539 int i, j;
540 char buf[1024];
541 bool correct = True;
542 size_t nread = 0;
543 NTSTATUS status;
545 memset(buf, '\0', sizeof(buf));
547 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
548 DENY_NONE, &fnum2);
549 if (!NT_STATUS_IS_OK(status)) {
550 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
552 if (!NT_STATUS_IS_OK(status)) {
553 printf("open of %s failed (%s)\n",
554 lockfname, nt_errstr(status));
555 return False;
558 for (i=0;i<torture_numops;i++) {
559 unsigned n = (unsigned)sys_random()%10;
561 if (i % 10 == 0) {
562 printf("%d\r", i); fflush(stdout);
564 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
566 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
567 return False;
570 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
571 DENY_ALL, &fnum);
572 if (!NT_STATUS_IS_OK(status)) {
573 printf("open failed (%s)\n", nt_errstr(status));
574 correct = False;
575 break;
578 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
579 sizeof(pid), NULL);
580 if (!NT_STATUS_IS_OK(status)) {
581 printf("write failed (%s)\n", nt_errstr(status));
582 correct = False;
585 for (j=0;j<50;j++) {
586 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
587 sizeof(pid)+(j*sizeof(buf)),
588 sizeof(buf), NULL);
589 if (!NT_STATUS_IS_OK(status)) {
590 printf("write failed (%s)\n",
591 nt_errstr(status));
592 correct = False;
596 pid2 = 0;
598 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
599 &nread);
600 if (!NT_STATUS_IS_OK(status)) {
601 printf("read failed (%s)\n", nt_errstr(status));
602 correct = false;
603 } else if (nread != sizeof(pid)) {
604 printf("read/write compare failed: "
605 "recv %ld req %ld\n", (unsigned long)nread,
606 (unsigned long)sizeof(pid));
607 correct = false;
610 if (pid2 != pid) {
611 printf("data corruption!\n");
612 correct = False;
615 status = cli_close(c, fnum);
616 if (!NT_STATUS_IS_OK(status)) {
617 printf("close failed (%s)\n", nt_errstr(status));
618 correct = False;
621 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
622 if (!NT_STATUS_IS_OK(status)) {
623 printf("unlink failed (%s)\n", nt_errstr(status));
624 correct = False;
627 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
628 if (!NT_STATUS_IS_OK(status)) {
629 printf("unlock failed (%s)\n", nt_errstr(status));
630 correct = False;
634 cli_close(c, fnum2);
635 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
637 printf("%d\n", i);
639 return correct;
642 static bool run_torture(int dummy)
644 struct cli_state *cli;
645 bool ret;
647 cli = current_cli;
649 smbXcli_conn_set_sockopt(cli->conn, sockops);
651 ret = rw_torture(cli);
653 if (!torture_close_connection(cli)) {
654 ret = False;
657 return ret;
660 static bool rw_torture3(struct cli_state *c, char *lockfname)
662 uint16_t fnum = (uint16_t)-1;
663 unsigned int i = 0;
664 char buf[131072];
665 char buf_rd[131072];
666 unsigned count;
667 unsigned countprev = 0;
668 size_t sent = 0;
669 bool correct = True;
670 NTSTATUS status = NT_STATUS_OK;
672 srandom(1);
673 for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
675 SIVAL(buf, i, sys_random());
678 if (procnum == 0)
680 status = cli_unlink(
681 c, lockfname,
682 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
683 if (!NT_STATUS_IS_OK(status)) {
684 printf("unlink failed (%s) (normal, this file should "
685 "not exist)\n", nt_errstr(status));
688 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
689 DENY_NONE, &fnum);
690 if (!NT_STATUS_IS_OK(status)) {
691 printf("first open read/write of %s failed (%s)\n",
692 lockfname, nt_errstr(status));
693 return False;
696 else
698 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
700 status = cli_openx(c, lockfname, O_RDONLY,
701 DENY_NONE, &fnum);
702 if (NT_STATUS_IS_OK(status)) {
703 break;
705 smb_msleep(10);
707 if (!NT_STATUS_IS_OK(status)) {
708 printf("second open read-only of %s failed (%s)\n",
709 lockfname, nt_errstr(status));
710 return False;
714 i = 0;
715 for (count = 0; count < sizeof(buf); count += sent)
717 if (count >= countprev) {
718 printf("%d %8d\r", i, count);
719 fflush(stdout);
720 i++;
721 countprev += (sizeof(buf) / 20);
724 if (procnum == 0)
726 sent = ((unsigned)sys_random()%(20))+ 1;
727 if (sent > sizeof(buf) - count)
729 sent = sizeof(buf) - count;
732 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
733 count, sent, NULL);
734 if (!NT_STATUS_IS_OK(status)) {
735 printf("write failed (%s)\n",
736 nt_errstr(status));
737 correct = False;
740 else
742 status = cli_read(c, fnum, buf_rd+count, count,
743 sizeof(buf)-count, &sent);
744 if(!NT_STATUS_IS_OK(status)) {
745 printf("read failed offset:%d size:%ld (%s)\n",
746 count, (unsigned long)sizeof(buf)-count,
747 nt_errstr(status));
748 correct = False;
749 sent = 0;
750 } else if (sent > 0) {
751 if (memcmp(buf_rd+count, buf+count, sent) != 0)
753 printf("read/write compare failed\n");
754 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
755 correct = False;
756 break;
763 status = cli_close(c, fnum);
764 if (!NT_STATUS_IS_OK(status)) {
765 printf("close failed (%s)\n", nt_errstr(status));
766 correct = False;
769 return correct;
772 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
774 const char *lockfname = "\\torture2.lck";
775 uint16_t fnum1;
776 uint16_t fnum2;
777 int i;
778 char buf[131072];
779 char buf_rd[131072];
780 bool correct = True;
781 size_t bytes_read;
782 NTSTATUS status;
784 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
785 if (!NT_STATUS_IS_OK(status)) {
786 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
789 status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
790 DENY_NONE, &fnum1);
791 if (!NT_STATUS_IS_OK(status)) {
792 printf("first open read/write of %s failed (%s)\n",
793 lockfname, nt_errstr(status));
794 return False;
797 status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
798 if (!NT_STATUS_IS_OK(status)) {
799 printf("second open read-only of %s failed (%s)\n",
800 lockfname, nt_errstr(status));
801 cli_close(c1, fnum1);
802 return False;
805 for (i = 0; i < torture_numops; i++)
807 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
808 if (i % 10 == 0) {
809 printf("%d\r", i); fflush(stdout);
812 generate_random_buffer((unsigned char *)buf, buf_size);
814 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
815 buf_size, NULL);
816 if (!NT_STATUS_IS_OK(status)) {
817 printf("write failed (%s)\n", nt_errstr(status));
818 correct = False;
819 break;
822 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
823 if(!NT_STATUS_IS_OK(status)) {
824 printf("read failed (%s)\n", nt_errstr(status));
825 correct = false;
826 break;
827 } else if (bytes_read != buf_size) {
828 printf("read failed\n");
829 printf("read %ld, expected %ld\n",
830 (unsigned long)bytes_read,
831 (unsigned long)buf_size);
832 correct = False;
833 break;
836 if (memcmp(buf_rd, buf, buf_size) != 0)
838 printf("read/write compare failed\n");
839 correct = False;
840 break;
844 status = cli_close(c2, fnum2);
845 if (!NT_STATUS_IS_OK(status)) {
846 printf("close failed (%s)\n", nt_errstr(status));
847 correct = False;
850 status = cli_close(c1, fnum1);
851 if (!NT_STATUS_IS_OK(status)) {
852 printf("close failed (%s)\n", nt_errstr(status));
853 correct = False;
856 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
857 if (!NT_STATUS_IS_OK(status)) {
858 printf("unlink failed (%s)\n", nt_errstr(status));
859 correct = False;
862 return correct;
865 static bool run_readwritetest(int dummy)
867 struct cli_state *cli1, *cli2;
868 bool test1, test2 = False;
870 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
871 return False;
873 smbXcli_conn_set_sockopt(cli1->conn, sockops);
874 smbXcli_conn_set_sockopt(cli2->conn, sockops);
876 printf("starting readwritetest\n");
878 test1 = rw_torture2(cli1, cli2);
879 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
881 if (test1) {
882 test2 = rw_torture2(cli1, cli1);
883 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
886 if (!torture_close_connection(cli1)) {
887 test1 = False;
890 if (!torture_close_connection(cli2)) {
891 test2 = False;
894 return (test1 && test2);
897 static bool run_readwritemulti(int dummy)
899 struct cli_state *cli;
900 bool test;
902 cli = current_cli;
904 smbXcli_conn_set_sockopt(cli->conn, sockops);
906 printf("run_readwritemulti: fname %s\n", randomfname);
907 test = rw_torture3(cli, randomfname);
909 if (!torture_close_connection(cli)) {
910 test = False;
913 return test;
916 static bool run_readwritelarge_internal(void)
918 static struct cli_state *cli1;
919 uint16_t fnum1;
920 const char *lockfname = "\\large.dat";
921 off_t fsize;
922 char buf[126*1024];
923 bool correct = True;
924 NTSTATUS status;
926 if (!torture_open_connection(&cli1, 0)) {
927 return False;
929 smbXcli_conn_set_sockopt(cli1->conn, sockops);
930 memset(buf,'\0',sizeof(buf));
932 printf("starting readwritelarge_internal\n");
934 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
936 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
937 DENY_NONE, &fnum1);
938 if (!NT_STATUS_IS_OK(status)) {
939 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
940 return False;
943 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
945 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
946 NULL, NULL, NULL);
947 if (!NT_STATUS_IS_OK(status)) {
948 printf("qfileinfo failed (%s)\n", nt_errstr(status));
949 correct = False;
952 if (fsize == sizeof(buf))
953 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
954 (unsigned long)fsize);
955 else {
956 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
957 (unsigned long)fsize);
958 correct = False;
961 status = cli_close(cli1, fnum1);
962 if (!NT_STATUS_IS_OK(status)) {
963 printf("close failed (%s)\n", nt_errstr(status));
964 correct = False;
967 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
968 if (!NT_STATUS_IS_OK(status)) {
969 printf("unlink failed (%s)\n", nt_errstr(status));
970 correct = False;
973 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
974 DENY_NONE, &fnum1);
975 if (!NT_STATUS_IS_OK(status)) {
976 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
977 return False;
980 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
982 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
983 NULL, NULL, NULL);
984 if (!NT_STATUS_IS_OK(status)) {
985 printf("qfileinfo failed (%s)\n", nt_errstr(status));
986 correct = False;
989 if (fsize == sizeof(buf))
990 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
991 (unsigned long)fsize);
992 else {
993 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
994 (unsigned long)fsize);
995 correct = False;
998 #if 0
999 /* ToDo - set allocation. JRA */
1000 if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1001 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1002 return False;
1004 if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1005 NULL, NULL)) {
1006 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1007 correct = False;
1009 if (fsize != 0)
1010 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1011 #endif
1013 status = cli_close(cli1, fnum1);
1014 if (!NT_STATUS_IS_OK(status)) {
1015 printf("close failed (%s)\n", nt_errstr(status));
1016 correct = False;
1019 if (!torture_close_connection(cli1)) {
1020 correct = False;
1022 return correct;
1025 static bool run_readwritelarge(int dummy)
1027 return run_readwritelarge_internal();
1030 static bool run_readwritelarge_signtest(int dummy)
1032 bool ret;
1033 signing_state = SMB_SIGNING_REQUIRED;
1034 ret = run_readwritelarge_internal();
1035 signing_state = SMB_SIGNING_DEFAULT;
1036 return ret;
1039 int line_count = 0;
1040 int nbio_id;
1042 #define ival(s) strtol(s, NULL, 0)
1044 /* run a test that simulates an approximate netbench client load */
1045 static bool run_netbench(int client)
1047 struct cli_state *cli;
1048 int i;
1049 char line[1024];
1050 char cname[20];
1051 FILE *f;
1052 const char *params[20];
1053 bool correct = True;
1055 cli = current_cli;
1057 nbio_id = client;
1059 smbXcli_conn_set_sockopt(cli->conn, sockops);
1061 nb_setup(cli);
1063 slprintf(cname,sizeof(cname)-1, "client%d", client);
1065 f = fopen(client_txt, "r");
1067 if (!f) {
1068 perror(client_txt);
1069 return False;
1072 while (fgets(line, sizeof(line)-1, f)) {
1073 char *saveptr;
1074 line_count++;
1076 line[strlen(line)-1] = 0;
1078 /* printf("[%d] %s\n", line_count, line); */
1080 all_string_sub(line,"client1", cname, sizeof(line));
1082 /* parse the command parameters */
1083 params[0] = strtok_r(line, " ", &saveptr);
1084 i = 0;
1085 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1087 params[i] = "";
1089 if (i < 2) continue;
1091 if (!strncmp(params[0],"SMB", 3)) {
1092 printf("ERROR: You are using a dbench 1 load file\n");
1093 exit(1);
1096 if (!strcmp(params[0],"NTCreateX")) {
1097 nb_createx(params[1], ival(params[2]), ival(params[3]),
1098 ival(params[4]));
1099 } else if (!strcmp(params[0],"Close")) {
1100 nb_close(ival(params[1]));
1101 } else if (!strcmp(params[0],"Rename")) {
1102 nb_rename(params[1], params[2]);
1103 } else if (!strcmp(params[0],"Unlink")) {
1104 nb_unlink(params[1]);
1105 } else if (!strcmp(params[0],"Deltree")) {
1106 nb_deltree(params[1]);
1107 } else if (!strcmp(params[0],"Rmdir")) {
1108 nb_rmdir(params[1]);
1109 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1110 nb_qpathinfo(params[1]);
1111 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1112 nb_qfileinfo(ival(params[1]));
1113 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1114 nb_qfsinfo(ival(params[1]));
1115 } else if (!strcmp(params[0],"FIND_FIRST")) {
1116 nb_findfirst(params[1]);
1117 } else if (!strcmp(params[0],"WriteX")) {
1118 nb_writex(ival(params[1]),
1119 ival(params[2]), ival(params[3]), ival(params[4]));
1120 } else if (!strcmp(params[0],"ReadX")) {
1121 nb_readx(ival(params[1]),
1122 ival(params[2]), ival(params[3]), ival(params[4]));
1123 } else if (!strcmp(params[0],"Flush")) {
1124 nb_flush(ival(params[1]));
1125 } else {
1126 printf("Unknown operation %s\n", params[0]);
1127 exit(1);
1130 fclose(f);
1132 nb_cleanup();
1134 if (!torture_close_connection(cli)) {
1135 correct = False;
1138 return correct;
1142 /* run a test that simulates an approximate netbench client load */
1143 static bool run_nbench(int dummy)
1145 double t;
1146 bool correct = True;
1148 nbio_shmem(torture_nprocs);
1150 nbio_id = -1;
1152 signal(SIGALRM, nb_alarm);
1153 alarm(1);
1154 t = create_procs(run_netbench, &correct);
1155 alarm(0);
1157 printf("\nThroughput %g MB/sec\n",
1158 1.0e-6 * nbio_total() / t);
1159 return correct;
1164 This test checks for two things:
1166 1) correct support for retaining locks over a close (ie. the server
1167 must not use posix semantics)
1168 2) support for lock timeouts
1170 static bool run_locktest1(int dummy)
1172 struct cli_state *cli1, *cli2;
1173 const char *fname = "\\lockt1.lck";
1174 uint16_t fnum1, fnum2, fnum3;
1175 time_t t1, t2;
1176 unsigned lock_timeout;
1177 NTSTATUS status;
1179 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1180 return False;
1182 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1183 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1185 printf("starting locktest1\n");
1187 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1189 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1190 &fnum1);
1191 if (!NT_STATUS_IS_OK(status)) {
1192 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1193 return False;
1196 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1197 if (!NT_STATUS_IS_OK(status)) {
1198 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1199 return False;
1202 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1203 if (!NT_STATUS_IS_OK(status)) {
1204 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1205 return False;
1208 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1209 if (!NT_STATUS_IS_OK(status)) {
1210 printf("lock1 failed (%s)\n", nt_errstr(status));
1211 return false;
1214 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1215 if (NT_STATUS_IS_OK(status)) {
1216 printf("lock2 succeeded! This is a locking bug\n");
1217 return false;
1218 } else {
1219 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1220 NT_STATUS_LOCK_NOT_GRANTED)) {
1221 return false;
1225 lock_timeout = (1 + (random() % 20));
1226 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1227 t1 = time(NULL);
1228 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1229 if (NT_STATUS_IS_OK(status)) {
1230 printf("lock3 succeeded! This is a locking bug\n");
1231 return false;
1232 } else {
1233 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1234 NT_STATUS_FILE_LOCK_CONFLICT)) {
1235 return false;
1238 t2 = time(NULL);
1240 if (ABS(t2 - t1) < lock_timeout-1) {
1241 printf("error: This server appears not to support timed lock requests\n");
1244 printf("server slept for %u seconds for a %u second timeout\n",
1245 (unsigned int)(t2-t1), lock_timeout);
1247 status = cli_close(cli1, fnum2);
1248 if (!NT_STATUS_IS_OK(status)) {
1249 printf("close1 failed (%s)\n", nt_errstr(status));
1250 return False;
1253 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1254 if (NT_STATUS_IS_OK(status)) {
1255 printf("lock4 succeeded! This is a locking bug\n");
1256 return false;
1257 } else {
1258 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1259 NT_STATUS_FILE_LOCK_CONFLICT)) {
1260 return false;
1264 status = cli_close(cli1, fnum1);
1265 if (!NT_STATUS_IS_OK(status)) {
1266 printf("close2 failed (%s)\n", nt_errstr(status));
1267 return False;
1270 status = cli_close(cli2, fnum3);
1271 if (!NT_STATUS_IS_OK(status)) {
1272 printf("close3 failed (%s)\n", nt_errstr(status));
1273 return False;
1276 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1277 if (!NT_STATUS_IS_OK(status)) {
1278 printf("unlink failed (%s)\n", nt_errstr(status));
1279 return False;
1283 if (!torture_close_connection(cli1)) {
1284 return False;
1287 if (!torture_close_connection(cli2)) {
1288 return False;
1291 printf("Passed locktest1\n");
1292 return True;
1296 this checks to see if a secondary tconx can use open files from an
1297 earlier tconx
1299 static bool run_tcon_test(int dummy)
1301 static struct cli_state *cli;
1302 const char *fname = "\\tcontest.tmp";
1303 uint16_t fnum1;
1304 uint16_t cnum1, cnum2, cnum3;
1305 uint16_t vuid1, vuid2;
1306 char buf[4];
1307 bool ret = True;
1308 NTSTATUS status;
1310 memset(buf, '\0', sizeof(buf));
1312 if (!torture_open_connection(&cli, 0)) {
1313 return False;
1315 smbXcli_conn_set_sockopt(cli->conn, sockops);
1317 printf("starting tcontest\n");
1319 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1321 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1322 if (!NT_STATUS_IS_OK(status)) {
1323 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1324 return False;
1327 cnum1 = cli_state_get_tid(cli);
1328 vuid1 = cli_state_get_uid(cli);
1330 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1331 if (!NT_STATUS_IS_OK(status)) {
1332 printf("initial write failed (%s)", nt_errstr(status));
1333 return False;
1336 status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1337 if (!NT_STATUS_IS_OK(status)) {
1338 printf("%s refused 2nd tree connect (%s)\n", host,
1339 nt_errstr(status));
1340 cli_shutdown(cli);
1341 return False;
1344 cnum2 = cli_state_get_tid(cli);
1345 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1346 vuid2 = cli_state_get_uid(cli) + 1;
1348 /* try a write with the wrong tid */
1349 cli_state_set_tid(cli, cnum2);
1351 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1352 if (NT_STATUS_IS_OK(status)) {
1353 printf("* server allows write with wrong TID\n");
1354 ret = False;
1355 } else {
1356 printf("server fails write with wrong TID : %s\n",
1357 nt_errstr(status));
1361 /* try a write with an invalid tid */
1362 cli_state_set_tid(cli, cnum3);
1364 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1365 if (NT_STATUS_IS_OK(status)) {
1366 printf("* server allows write with invalid TID\n");
1367 ret = False;
1368 } else {
1369 printf("server fails write with invalid TID : %s\n",
1370 nt_errstr(status));
1373 /* try a write with an invalid vuid */
1374 cli_state_set_uid(cli, vuid2);
1375 cli_state_set_tid(cli, cnum1);
1377 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1378 if (NT_STATUS_IS_OK(status)) {
1379 printf("* server allows write with invalid VUID\n");
1380 ret = False;
1381 } else {
1382 printf("server fails write with invalid VUID : %s\n",
1383 nt_errstr(status));
1386 cli_state_set_tid(cli, cnum1);
1387 cli_state_set_uid(cli, vuid1);
1389 status = cli_close(cli, fnum1);
1390 if (!NT_STATUS_IS_OK(status)) {
1391 printf("close failed (%s)\n", nt_errstr(status));
1392 return False;
1395 cli_state_set_tid(cli, cnum2);
1397 status = cli_tdis(cli);
1398 if (!NT_STATUS_IS_OK(status)) {
1399 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1400 return False;
1403 cli_state_set_tid(cli, cnum1);
1405 if (!torture_close_connection(cli)) {
1406 return False;
1409 return ret;
1414 checks for old style tcon support
1416 static bool run_tcon2_test(int dummy)
1418 static struct cli_state *cli;
1419 uint16_t cnum, max_xmit;
1420 char *service;
1421 NTSTATUS status;
1423 if (!torture_open_connection(&cli, 0)) {
1424 return False;
1426 smbXcli_conn_set_sockopt(cli->conn, sockops);
1428 printf("starting tcon2 test\n");
1430 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1431 return false;
1434 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1436 SAFE_FREE(service);
1438 if (!NT_STATUS_IS_OK(status)) {
1439 printf("tcon2 failed : %s\n", nt_errstr(status));
1440 } else {
1441 printf("tcon OK : max_xmit=%d cnum=%d\n",
1442 (int)max_xmit, (int)cnum);
1445 if (!torture_close_connection(cli)) {
1446 return False;
1449 printf("Passed tcon2 test\n");
1450 return True;
1453 static bool tcon_devtest(struct cli_state *cli,
1454 const char *myshare, const char *devtype,
1455 const char *return_devtype,
1456 NTSTATUS expected_error)
1458 NTSTATUS status;
1459 bool ret;
1461 status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1463 if (NT_STATUS_IS_OK(expected_error)) {
1464 if (NT_STATUS_IS_OK(status)) {
1465 if (strcmp(cli->dev, return_devtype) == 0) {
1466 ret = True;
1467 } else {
1468 printf("tconX to share %s with type %s "
1469 "succeeded but returned the wrong "
1470 "device type (got [%s] but should have got [%s])\n",
1471 myshare, devtype, cli->dev, return_devtype);
1472 ret = False;
1474 } else {
1475 printf("tconX to share %s with type %s "
1476 "should have succeeded but failed\n",
1477 myshare, devtype);
1478 ret = False;
1480 cli_tdis(cli);
1481 } else {
1482 if (NT_STATUS_IS_OK(status)) {
1483 printf("tconx to share %s with type %s "
1484 "should have failed but succeeded\n",
1485 myshare, devtype);
1486 ret = False;
1487 } else {
1488 if (NT_STATUS_EQUAL(status, expected_error)) {
1489 ret = True;
1490 } else {
1491 printf("Returned unexpected error\n");
1492 ret = False;
1496 return ret;
1500 checks for correct tconX support
1502 static bool run_tcon_devtype_test(int dummy)
1504 static struct cli_state *cli1 = NULL;
1505 int flags = 0;
1506 NTSTATUS status;
1507 bool ret = True;
1509 status = cli_full_connection_creds(&cli1,
1510 myname,
1511 host,
1512 NULL, /* dest_ss */
1513 port_to_use,
1514 NULL, /* service */
1515 NULL, /* service_type */
1516 torture_creds,
1517 flags,
1518 signing_state);
1520 if (!NT_STATUS_IS_OK(status)) {
1521 printf("could not open connection\n");
1522 return False;
1525 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1526 ret = False;
1528 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1529 ret = False;
1531 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1532 ret = False;
1534 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1535 ret = False;
1537 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1538 ret = False;
1540 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1541 ret = False;
1543 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1544 ret = False;
1546 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1547 ret = False;
1549 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1550 ret = False;
1552 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1553 ret = False;
1555 cli_shutdown(cli1);
1557 if (ret)
1558 printf("Passed tcondevtest\n");
1560 return ret;
1565 This test checks that
1567 1) the server supports multiple locking contexts on the one SMB
1568 connection, distinguished by PID.
1570 2) the server correctly fails overlapping locks made by the same PID (this
1571 goes against POSIX behaviour, which is why it is tricky to implement)
1573 3) the server denies unlock requests by an incorrect client PID
1575 static bool run_locktest2(int dummy)
1577 static struct cli_state *cli;
1578 const char *fname = "\\lockt2.lck";
1579 uint16_t fnum1, fnum2, fnum3;
1580 bool correct = True;
1581 NTSTATUS status;
1583 if (!torture_open_connection(&cli, 0)) {
1584 return False;
1587 smbXcli_conn_set_sockopt(cli->conn, sockops);
1589 printf("starting locktest2\n");
1591 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1593 cli_setpid(cli, 1);
1595 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1596 if (!NT_STATUS_IS_OK(status)) {
1597 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1598 return False;
1601 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1602 if (!NT_STATUS_IS_OK(status)) {
1603 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1604 return False;
1607 cli_setpid(cli, 2);
1609 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1610 if (!NT_STATUS_IS_OK(status)) {
1611 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1612 return False;
1615 cli_setpid(cli, 1);
1617 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1618 if (!NT_STATUS_IS_OK(status)) {
1619 printf("lock1 failed (%s)\n", nt_errstr(status));
1620 return false;
1623 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1624 if (NT_STATUS_IS_OK(status)) {
1625 printf("WRITE lock1 succeeded! This is a locking bug\n");
1626 correct = false;
1627 } else {
1628 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1629 NT_STATUS_LOCK_NOT_GRANTED)) {
1630 return false;
1634 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1635 if (NT_STATUS_IS_OK(status)) {
1636 printf("WRITE lock2 succeeded! This is a locking bug\n");
1637 correct = false;
1638 } else {
1639 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1640 NT_STATUS_LOCK_NOT_GRANTED)) {
1641 return false;
1645 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1646 if (NT_STATUS_IS_OK(status)) {
1647 printf("READ lock2 succeeded! This is a locking bug\n");
1648 correct = false;
1649 } else {
1650 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1651 NT_STATUS_FILE_LOCK_CONFLICT)) {
1652 return false;
1656 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1657 if (!NT_STATUS_IS_OK(status)) {
1658 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1660 cli_setpid(cli, 2);
1661 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1662 printf("unlock at 100 succeeded! This is a locking bug\n");
1663 correct = False;
1666 status = cli_unlock(cli, fnum1, 0, 4);
1667 if (NT_STATUS_IS_OK(status)) {
1668 printf("unlock1 succeeded! This is a locking bug\n");
1669 correct = false;
1670 } else {
1671 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1672 NT_STATUS_RANGE_NOT_LOCKED)) {
1673 return false;
1677 status = cli_unlock(cli, fnum1, 0, 8);
1678 if (NT_STATUS_IS_OK(status)) {
1679 printf("unlock2 succeeded! This is a locking bug\n");
1680 correct = false;
1681 } else {
1682 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1683 NT_STATUS_RANGE_NOT_LOCKED)) {
1684 return false;
1688 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1689 if (NT_STATUS_IS_OK(status)) {
1690 printf("lock3 succeeded! This is a locking bug\n");
1691 correct = false;
1692 } else {
1693 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1694 NT_STATUS_LOCK_NOT_GRANTED)) {
1695 return false;
1699 cli_setpid(cli, 1);
1701 status = cli_close(cli, fnum1);
1702 if (!NT_STATUS_IS_OK(status)) {
1703 printf("close1 failed (%s)\n", nt_errstr(status));
1704 return False;
1707 status = cli_close(cli, fnum2);
1708 if (!NT_STATUS_IS_OK(status)) {
1709 printf("close2 failed (%s)\n", nt_errstr(status));
1710 return False;
1713 status = cli_close(cli, fnum3);
1714 if (!NT_STATUS_IS_OK(status)) {
1715 printf("close3 failed (%s)\n", nt_errstr(status));
1716 return False;
1719 if (!torture_close_connection(cli)) {
1720 correct = False;
1723 printf("locktest2 finished\n");
1725 return correct;
1730 This test checks that
1732 1) the server supports the full offset range in lock requests
1734 static bool run_locktest3(int dummy)
1736 static struct cli_state *cli1, *cli2;
1737 const char *fname = "\\lockt3.lck";
1738 uint16_t fnum1, fnum2;
1739 int i;
1740 uint32_t offset;
1741 bool correct = True;
1742 NTSTATUS status;
1744 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1746 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1747 return False;
1749 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1750 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1752 printf("starting locktest3\n");
1754 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1756 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1757 &fnum1);
1758 if (!NT_STATUS_IS_OK(status)) {
1759 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1760 return False;
1763 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1764 if (!NT_STATUS_IS_OK(status)) {
1765 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1766 return False;
1769 for (offset=i=0;i<torture_numops;i++) {
1770 NEXT_OFFSET;
1772 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1773 if (!NT_STATUS_IS_OK(status)) {
1774 printf("lock1 %d failed (%s)\n",
1776 nt_errstr(status));
1777 return False;
1780 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1781 if (!NT_STATUS_IS_OK(status)) {
1782 printf("lock2 %d failed (%s)\n",
1784 nt_errstr(status));
1785 return False;
1789 for (offset=i=0;i<torture_numops;i++) {
1790 NEXT_OFFSET;
1792 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1793 if (NT_STATUS_IS_OK(status)) {
1794 printf("error: lock1 %d succeeded!\n", i);
1795 return False;
1798 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1799 if (NT_STATUS_IS_OK(status)) {
1800 printf("error: lock2 %d succeeded!\n", i);
1801 return False;
1804 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1805 if (NT_STATUS_IS_OK(status)) {
1806 printf("error: lock3 %d succeeded!\n", i);
1807 return False;
1810 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1811 if (NT_STATUS_IS_OK(status)) {
1812 printf("error: lock4 %d succeeded!\n", i);
1813 return False;
1817 for (offset=i=0;i<torture_numops;i++) {
1818 NEXT_OFFSET;
1820 status = cli_unlock(cli1, fnum1, offset-1, 1);
1821 if (!NT_STATUS_IS_OK(status)) {
1822 printf("unlock1 %d failed (%s)\n",
1824 nt_errstr(status));
1825 return False;
1828 status = cli_unlock(cli2, fnum2, offset-2, 1);
1829 if (!NT_STATUS_IS_OK(status)) {
1830 printf("unlock2 %d failed (%s)\n",
1832 nt_errstr(status));
1833 return False;
1837 status = cli_close(cli1, fnum1);
1838 if (!NT_STATUS_IS_OK(status)) {
1839 printf("close1 failed (%s)\n", nt_errstr(status));
1840 return False;
1843 status = cli_close(cli2, fnum2);
1844 if (!NT_STATUS_IS_OK(status)) {
1845 printf("close2 failed (%s)\n", nt_errstr(status));
1846 return False;
1849 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1850 if (!NT_STATUS_IS_OK(status)) {
1851 printf("unlink failed (%s)\n", nt_errstr(status));
1852 return False;
1855 if (!torture_close_connection(cli1)) {
1856 correct = False;
1859 if (!torture_close_connection(cli2)) {
1860 correct = False;
1863 printf("finished locktest3\n");
1865 return correct;
1868 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1869 char *buf, off_t offset, size_t size,
1870 size_t *nread, size_t expect)
1872 NTSTATUS status;
1873 size_t l_nread;
1875 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1877 if(!NT_STATUS_IS_OK(status)) {
1878 return false;
1879 } else if (l_nread != expect) {
1880 return false;
1883 if (nread) {
1884 *nread = l_nread;
1887 return true;
1890 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1891 printf("** "); correct = False; \
1895 looks at overlapping locks
1897 static bool run_locktest4(int dummy)
1899 static struct cli_state *cli1, *cli2;
1900 const char *fname = "\\lockt4.lck";
1901 uint16_t fnum1, fnum2, f;
1902 bool ret;
1903 char buf[1000];
1904 bool correct = True;
1905 NTSTATUS status;
1907 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1908 return False;
1911 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1912 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1914 printf("starting locktest4\n");
1916 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1918 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1919 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1921 memset(buf, 0, sizeof(buf));
1923 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1924 NULL);
1925 if (!NT_STATUS_IS_OK(status)) {
1926 printf("Failed to create file: %s\n", nt_errstr(status));
1927 correct = False;
1928 goto fail;
1931 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1932 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1933 EXPECTED(ret, False);
1934 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1936 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1937 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1938 EXPECTED(ret, True);
1939 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1941 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1942 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1943 EXPECTED(ret, False);
1944 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1946 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1947 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1948 EXPECTED(ret, True);
1949 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1951 ret = (cli_setpid(cli1, 1),
1952 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1953 (cli_setpid(cli1, 2),
1954 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1955 EXPECTED(ret, False);
1956 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1958 ret = (cli_setpid(cli1, 1),
1959 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1960 (cli_setpid(cli1, 2),
1961 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1962 EXPECTED(ret, True);
1963 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1965 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1966 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1967 EXPECTED(ret, True);
1968 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1970 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1971 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1972 EXPECTED(ret, False);
1973 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1975 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1976 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1977 EXPECTED(ret, False);
1978 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1980 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1981 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
1982 EXPECTED(ret, True);
1983 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1985 ret = (cli_setpid(cli1, 1),
1986 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
1987 (cli_setpid(cli1, 2),
1988 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
1989 EXPECTED(ret, False);
1990 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1992 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
1993 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
1994 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
1995 EXPECTED(ret, False);
1996 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
1999 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2000 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2001 EXPECTED(ret, False);
2002 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2004 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2005 ret = NT_STATUS_IS_OK(status);
2006 if (ret) {
2007 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2008 NULL);
2009 ret = NT_STATUS_IS_OK(status);
2011 EXPECTED(ret, False);
2012 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2015 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2016 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2017 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2018 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2019 EXPECTED(ret, True);
2020 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2023 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2024 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2025 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2026 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2027 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2028 150, 4, NULL))) &&
2029 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2030 EXPECTED(ret, True);
2031 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2033 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2034 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2035 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2036 160, 4, NULL)) &&
2037 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2038 EXPECTED(ret, True);
2039 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2041 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2042 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2043 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2044 170, 4, NULL)) &&
2045 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2046 EXPECTED(ret, True);
2047 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2049 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2050 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2051 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2052 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2053 190, 4, NULL)) &&
2054 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2055 EXPECTED(ret, True);
2056 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2058 cli_close(cli1, fnum1);
2059 cli_close(cli2, fnum2);
2060 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2061 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2062 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2063 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2064 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2065 NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2066 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2067 cli_close(cli1, f);
2068 cli_close(cli1, fnum1);
2069 EXPECTED(ret, True);
2070 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2072 fail:
2073 cli_close(cli1, fnum1);
2074 cli_close(cli2, fnum2);
2075 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2076 torture_close_connection(cli1);
2077 torture_close_connection(cli2);
2079 printf("finished locktest4\n");
2080 return correct;
2084 looks at lock upgrade/downgrade.
2086 static bool run_locktest5(int dummy)
2088 static struct cli_state *cli1, *cli2;
2089 const char *fname = "\\lockt5.lck";
2090 uint16_t fnum1, fnum2, fnum3;
2091 bool ret;
2092 char buf[1000];
2093 bool correct = True;
2094 NTSTATUS status;
2096 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2097 return False;
2100 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2101 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2103 printf("starting locktest5\n");
2105 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2107 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2108 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2109 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2111 memset(buf, 0, sizeof(buf));
2113 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2114 NULL);
2115 if (!NT_STATUS_IS_OK(status)) {
2116 printf("Failed to create file: %s\n", nt_errstr(status));
2117 correct = False;
2118 goto fail;
2121 /* Check for NT bug... */
2122 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2123 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2124 cli_close(cli1, fnum1);
2125 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2126 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2127 ret = NT_STATUS_IS_OK(status);
2128 EXPECTED(ret, True);
2129 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2130 cli_close(cli1, fnum1);
2131 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2132 cli_unlock(cli1, fnum3, 0, 1);
2134 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2135 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2136 EXPECTED(ret, True);
2137 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2139 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2140 ret = NT_STATUS_IS_OK(status);
2141 EXPECTED(ret, False);
2143 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2145 /* Unlock the process 2 lock. */
2146 cli_unlock(cli2, fnum2, 0, 4);
2148 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2149 ret = NT_STATUS_IS_OK(status);
2150 EXPECTED(ret, False);
2152 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2154 /* Unlock the process 1 fnum3 lock. */
2155 cli_unlock(cli1, fnum3, 0, 4);
2157 /* Stack 2 more locks here. */
2158 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2159 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2161 EXPECTED(ret, True);
2162 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2164 /* Unlock the first process lock, then check this was the WRITE lock that was
2165 removed. */
2167 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2168 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2170 EXPECTED(ret, True);
2171 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2173 /* Unlock the process 2 lock. */
2174 cli_unlock(cli2, fnum2, 0, 4);
2176 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2178 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2179 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2180 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2182 EXPECTED(ret, True);
2183 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2185 /* Ensure the next unlock fails. */
2186 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2187 EXPECTED(ret, False);
2188 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2190 /* Ensure connection 2 can get a write lock. */
2191 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2192 ret = NT_STATUS_IS_OK(status);
2193 EXPECTED(ret, True);
2195 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2198 fail:
2199 cli_close(cli1, fnum1);
2200 cli_close(cli2, fnum2);
2201 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2202 if (!torture_close_connection(cli1)) {
2203 correct = False;
2205 if (!torture_close_connection(cli2)) {
2206 correct = False;
2209 printf("finished locktest5\n");
2211 return correct;
2215 tries the unusual lockingX locktype bits
2217 static bool run_locktest6(int dummy)
2219 static struct cli_state *cli;
2220 const char *fname[1] = { "\\lock6.txt" };
2221 int i;
2222 uint16_t fnum;
2223 NTSTATUS status;
2225 if (!torture_open_connection(&cli, 0)) {
2226 return False;
2229 smbXcli_conn_set_sockopt(cli->conn, sockops);
2231 printf("starting locktest6\n");
2233 for (i=0;i<1;i++) {
2234 printf("Testing %s\n", fname[i]);
2236 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2238 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2239 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2240 cli_close(cli, fnum);
2241 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2243 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2244 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2245 cli_close(cli, fnum);
2246 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2248 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2251 torture_close_connection(cli);
2253 printf("finished locktest6\n");
2254 return True;
2257 static bool run_locktest7(int dummy)
2259 struct cli_state *cli1;
2260 const char *fname = "\\lockt7.lck";
2261 uint16_t fnum1;
2262 char buf[200];
2263 bool correct = False;
2264 size_t nread;
2265 NTSTATUS status;
2267 if (!torture_open_connection(&cli1, 0)) {
2268 return False;
2271 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2273 printf("starting locktest7\n");
2275 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2277 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2279 memset(buf, 0, sizeof(buf));
2281 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2282 NULL);
2283 if (!NT_STATUS_IS_OK(status)) {
2284 printf("Failed to create file: %s\n", nt_errstr(status));
2285 goto fail;
2288 cli_setpid(cli1, 1);
2290 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2291 if (!NT_STATUS_IS_OK(status)) {
2292 printf("Unable to apply read lock on range 130:4, "
2293 "error was %s\n", nt_errstr(status));
2294 goto fail;
2295 } else {
2296 printf("pid1 successfully locked range 130:4 for READ\n");
2299 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2300 if (!NT_STATUS_IS_OK(status)) {
2301 printf("pid1 unable to read the range 130:4, error was %s\n",
2302 nt_errstr(status));
2303 goto fail;
2304 } else if (nread != 4) {
2305 printf("pid1 unable to read the range 130:4, "
2306 "recv %ld req %d\n", (unsigned long)nread, 4);
2307 goto fail;
2308 } else {
2309 printf("pid1 successfully read the range 130:4\n");
2312 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2313 if (!NT_STATUS_IS_OK(status)) {
2314 printf("pid1 unable to write to the range 130:4, error was "
2315 "%s\n", nt_errstr(status));
2316 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2317 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2318 goto fail;
2320 } else {
2321 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2322 goto fail;
2325 cli_setpid(cli1, 2);
2327 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2328 if (!NT_STATUS_IS_OK(status)) {
2329 printf("pid2 unable to read the range 130:4, error was %s\n",
2330 nt_errstr(status));
2331 goto fail;
2332 } else if (nread != 4) {
2333 printf("pid2 unable to read the range 130:4, "
2334 "recv %ld req %d\n", (unsigned long)nread, 4);
2335 goto fail;
2336 } else {
2337 printf("pid2 successfully read the range 130:4\n");
2340 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2341 if (!NT_STATUS_IS_OK(status)) {
2342 printf("pid2 unable to write to the range 130:4, error was "
2343 "%s\n", nt_errstr(status));
2344 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2345 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2346 goto fail;
2348 } else {
2349 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2350 goto fail;
2353 cli_setpid(cli1, 1);
2354 cli_unlock(cli1, fnum1, 130, 4);
2356 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2357 if (!NT_STATUS_IS_OK(status)) {
2358 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2359 goto fail;
2360 } else {
2361 printf("pid1 successfully locked range 130:4 for WRITE\n");
2364 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2365 if (!NT_STATUS_IS_OK(status)) {
2366 printf("pid1 unable to read the range 130:4, error was %s\n",
2367 nt_errstr(status));
2368 goto fail;
2369 } else if (nread != 4) {
2370 printf("pid1 unable to read the range 130:4, "
2371 "recv %ld req %d\n", (unsigned long)nread, 4);
2372 goto fail;
2373 } else {
2374 printf("pid1 successfully read the range 130:4\n");
2377 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2378 if (!NT_STATUS_IS_OK(status)) {
2379 printf("pid1 unable to write to the range 130:4, error was "
2380 "%s\n", nt_errstr(status));
2381 goto fail;
2382 } else {
2383 printf("pid1 successfully wrote to the range 130:4\n");
2386 cli_setpid(cli1, 2);
2388 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2389 if (!NT_STATUS_IS_OK(status)) {
2390 printf("pid2 unable to read the range 130:4, error was "
2391 "%s\n", nt_errstr(status));
2392 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2393 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2394 goto fail;
2396 } else {
2397 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2398 (unsigned long)nread);
2399 goto fail;
2402 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2403 if (!NT_STATUS_IS_OK(status)) {
2404 printf("pid2 unable to write to the range 130:4, error was "
2405 "%s\n", nt_errstr(status));
2406 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2407 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2408 goto fail;
2410 } else {
2411 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2412 goto fail;
2415 cli_unlock(cli1, fnum1, 130, 0);
2416 correct = True;
2418 fail:
2419 cli_close(cli1, fnum1);
2420 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2421 torture_close_connection(cli1);
2423 printf("finished locktest7\n");
2424 return correct;
2428 * This demonstrates a problem with our use of GPFS share modes: A file
2429 * descriptor sitting in the pending close queue holding a GPFS share mode
2430 * blocks opening a file another time. Happens with Word 2007 temp files.
2431 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2432 * open is denied with NT_STATUS_SHARING_VIOLATION.
2435 static bool run_locktest8(int dummy)
2437 struct cli_state *cli1;
2438 const char *fname = "\\lockt8.lck";
2439 uint16_t fnum1, fnum2;
2440 char buf[200];
2441 bool correct = False;
2442 NTSTATUS status;
2444 if (!torture_open_connection(&cli1, 0)) {
2445 return False;
2448 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2450 printf("starting locktest8\n");
2452 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2454 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2455 &fnum1);
2456 if (!NT_STATUS_IS_OK(status)) {
2457 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2458 return false;
2461 memset(buf, 0, sizeof(buf));
2463 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2464 if (!NT_STATUS_IS_OK(status)) {
2465 d_fprintf(stderr, "cli_openx second time returned %s\n",
2466 nt_errstr(status));
2467 goto fail;
2470 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2471 if (!NT_STATUS_IS_OK(status)) {
2472 printf("Unable to apply read lock on range 1:1, error was "
2473 "%s\n", nt_errstr(status));
2474 goto fail;
2477 status = cli_close(cli1, fnum1);
2478 if (!NT_STATUS_IS_OK(status)) {
2479 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2480 goto fail;
2483 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2484 if (!NT_STATUS_IS_OK(status)) {
2485 d_fprintf(stderr, "cli_openx third time returned %s\n",
2486 nt_errstr(status));
2487 goto fail;
2490 correct = true;
2492 fail:
2493 cli_close(cli1, fnum1);
2494 cli_close(cli1, fnum2);
2495 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2496 torture_close_connection(cli1);
2498 printf("finished locktest8\n");
2499 return correct;
2503 * This test is designed to be run in conjunction with
2504 * external NFS or POSIX locks taken in the filesystem.
2505 * It checks that the smbd server will block until the
2506 * lock is released and then acquire it. JRA.
2509 static bool got_alarm;
2510 static struct cli_state *alarm_cli;
2512 static void alarm_handler(int dummy)
2514 got_alarm = True;
2517 static void alarm_handler_parent(int dummy)
2519 smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_OK);
2522 static void do_local_lock(int read_fd, int write_fd)
2524 int fd;
2525 char c = '\0';
2526 struct flock lock;
2527 const char *local_pathname = NULL;
2528 int ret;
2530 local_pathname = talloc_asprintf(talloc_tos(),
2531 "%s/lockt9.lck", local_path);
2532 if (!local_pathname) {
2533 printf("child: alloc fail\n");
2534 exit(1);
2537 unlink(local_pathname);
2538 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2539 if (fd == -1) {
2540 printf("child: open of %s failed %s.\n",
2541 local_pathname, strerror(errno));
2542 exit(1);
2545 /* Now take a fcntl lock. */
2546 lock.l_type = F_WRLCK;
2547 lock.l_whence = SEEK_SET;
2548 lock.l_start = 0;
2549 lock.l_len = 4;
2550 lock.l_pid = getpid();
2552 ret = fcntl(fd,F_SETLK,&lock);
2553 if (ret == -1) {
2554 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2555 local_pathname, strerror(errno));
2556 exit(1);
2557 } else {
2558 printf("child: got lock 0:4 on file %s.\n",
2559 local_pathname );
2560 fflush(stdout);
2563 CatchSignal(SIGALRM, alarm_handler);
2564 alarm(5);
2565 /* Signal the parent. */
2566 if (write(write_fd, &c, 1) != 1) {
2567 printf("child: start signal fail %s.\n",
2568 strerror(errno));
2569 exit(1);
2571 alarm(0);
2573 alarm(10);
2574 /* Wait for the parent to be ready. */
2575 if (read(read_fd, &c, 1) != 1) {
2576 printf("child: reply signal fail %s.\n",
2577 strerror(errno));
2578 exit(1);
2580 alarm(0);
2582 sleep(5);
2583 close(fd);
2584 printf("child: released lock 0:4 on file %s.\n",
2585 local_pathname );
2586 fflush(stdout);
2587 exit(0);
2590 static bool run_locktest9(int dummy)
2592 struct cli_state *cli1;
2593 const char *fname = "\\lockt9.lck";
2594 uint16_t fnum;
2595 bool correct = False;
2596 int pipe_in[2], pipe_out[2];
2597 pid_t child_pid;
2598 char c = '\0';
2599 int ret;
2600 struct timeval start;
2601 double seconds;
2602 NTSTATUS status;
2604 printf("starting locktest9\n");
2606 if (local_path == NULL) {
2607 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2608 return false;
2611 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2612 return false;
2615 child_pid = fork();
2616 if (child_pid == -1) {
2617 return false;
2620 if (child_pid == 0) {
2621 /* Child. */
2622 do_local_lock(pipe_out[0], pipe_in[1]);
2623 exit(0);
2626 close(pipe_out[0]);
2627 close(pipe_in[1]);
2628 pipe_out[0] = -1;
2629 pipe_in[1] = -1;
2631 /* Parent. */
2632 ret = read(pipe_in[0], &c, 1);
2633 if (ret != 1) {
2634 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2635 strerror(errno));
2636 return false;
2639 if (!torture_open_connection(&cli1, 0)) {
2640 return false;
2643 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2645 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE,
2646 &fnum);
2647 if (!NT_STATUS_IS_OK(status)) {
2648 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2649 return false;
2652 /* Ensure the child has the lock. */
2653 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2654 if (NT_STATUS_IS_OK(status)) {
2655 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2656 goto fail;
2657 } else {
2658 d_printf("Child has the lock.\n");
2661 /* Tell the child to wait 5 seconds then exit. */
2662 ret = write(pipe_out[1], &c, 1);
2663 if (ret != 1) {
2664 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2665 strerror(errno));
2666 goto fail;
2669 /* Wait 20 seconds for the lock. */
2670 alarm_cli = cli1;
2671 CatchSignal(SIGALRM, alarm_handler_parent);
2672 alarm(20);
2674 start = timeval_current();
2676 status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2677 if (!NT_STATUS_IS_OK(status)) {
2678 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2679 "%s\n", nt_errstr(status));
2680 goto fail_nofd;
2682 alarm(0);
2684 seconds = timeval_elapsed(&start);
2686 printf("Parent got the lock after %.2f seconds.\n",
2687 seconds);
2689 status = cli_close(cli1, fnum);
2690 if (!NT_STATUS_IS_OK(status)) {
2691 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2692 goto fail;
2695 correct = true;
2697 fail:
2698 cli_close(cli1, fnum);
2699 torture_close_connection(cli1);
2701 fail_nofd:
2703 printf("finished locktest9\n");
2704 return correct;
2708 test whether fnums and tids open on one VC are available on another (a major
2709 security hole)
2711 static bool run_fdpasstest(int dummy)
2713 struct cli_state *cli1, *cli2;
2714 const char *fname = "\\fdpass.tst";
2715 uint16_t fnum1;
2716 char buf[1024];
2717 NTSTATUS status;
2719 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2720 return False;
2722 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2723 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2725 printf("starting fdpasstest\n");
2727 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2729 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2730 &fnum1);
2731 if (!NT_STATUS_IS_OK(status)) {
2732 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2733 return False;
2736 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2737 13, NULL);
2738 if (!NT_STATUS_IS_OK(status)) {
2739 printf("write failed (%s)\n", nt_errstr(status));
2740 return False;
2743 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
2744 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2745 cli_setpid(cli2, cli_getpid(cli1));
2747 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
2748 printf("read succeeded! nasty security hole [%s]\n", buf);
2749 return false;
2752 cli_close(cli1, fnum1);
2753 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2755 torture_close_connection(cli1);
2756 torture_close_connection(cli2);
2758 printf("finished fdpasstest\n");
2759 return True;
2762 static bool run_fdsesstest(int dummy)
2764 struct cli_state *cli;
2765 uint16_t new_vuid;
2766 uint16_t saved_vuid;
2767 uint16_t new_cnum;
2768 uint16_t saved_cnum;
2769 const char *fname = "\\fdsess.tst";
2770 const char *fname1 = "\\fdsess1.tst";
2771 uint16_t fnum1;
2772 uint16_t fnum2;
2773 char buf[1024];
2774 bool ret = True;
2775 NTSTATUS status;
2777 if (!torture_open_connection(&cli, 0))
2778 return False;
2779 smbXcli_conn_set_sockopt(cli->conn, sockops);
2781 if (!torture_cli_session_setup2(cli, &new_vuid))
2782 return False;
2784 saved_cnum = cli_state_get_tid(cli);
2785 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
2786 return False;
2787 new_cnum = cli_state_get_tid(cli);
2788 cli_state_set_tid(cli, saved_cnum);
2790 printf("starting fdsesstest\n");
2792 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2793 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2795 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2796 if (!NT_STATUS_IS_OK(status)) {
2797 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2798 return False;
2801 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2802 NULL);
2803 if (!NT_STATUS_IS_OK(status)) {
2804 printf("write failed (%s)\n", nt_errstr(status));
2805 return False;
2808 saved_vuid = cli_state_get_uid(cli);
2809 cli_state_set_uid(cli, new_vuid);
2811 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2812 printf("read succeeded with different vuid! "
2813 "nasty security hole [%s]\n", buf);
2814 ret = false;
2816 /* Try to open a file with different vuid, samba cnum. */
2817 if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2818 printf("create with different vuid, same cnum succeeded.\n");
2819 cli_close(cli, fnum2);
2820 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2821 } else {
2822 printf("create with different vuid, same cnum failed.\n");
2823 printf("This will cause problems with service clients.\n");
2824 ret = False;
2827 cli_state_set_uid(cli, saved_vuid);
2829 /* Try with same vuid, different cnum. */
2830 cli_state_set_tid(cli, new_cnum);
2832 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2833 printf("read succeeded with different cnum![%s]\n", buf);
2834 ret = false;
2837 cli_state_set_tid(cli, saved_cnum);
2838 cli_close(cli, fnum1);
2839 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2841 torture_close_connection(cli);
2843 printf("finished fdsesstest\n");
2844 return ret;
2848 This test checks that
2850 1) the server does not allow an unlink on a file that is open
2852 static bool run_unlinktest(int dummy)
2854 struct cli_state *cli;
2855 const char *fname = "\\unlink.tst";
2856 uint16_t fnum;
2857 bool correct = True;
2858 NTSTATUS status;
2860 if (!torture_open_connection(&cli, 0)) {
2861 return False;
2864 smbXcli_conn_set_sockopt(cli->conn, sockops);
2866 printf("starting unlink test\n");
2868 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2870 cli_setpid(cli, 1);
2872 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2873 if (!NT_STATUS_IS_OK(status)) {
2874 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2875 return False;
2878 status = cli_unlink(cli, fname,
2879 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2880 if (NT_STATUS_IS_OK(status)) {
2881 printf("error: server allowed unlink on an open file\n");
2882 correct = False;
2883 } else {
2884 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
2885 NT_STATUS_SHARING_VIOLATION);
2888 cli_close(cli, fnum);
2889 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2891 if (!torture_close_connection(cli)) {
2892 correct = False;
2895 printf("unlink test finished\n");
2897 return correct;
2902 test how many open files this server supports on the one socket
2904 static bool run_maxfidtest(int dummy)
2906 struct cli_state *cli;
2907 fstring fname;
2908 uint16_t fnums[0x11000];
2909 int i;
2910 int retries=4;
2911 bool correct = True;
2912 NTSTATUS status;
2914 cli = current_cli;
2916 if (retries <= 0) {
2917 printf("failed to connect\n");
2918 return False;
2921 smbXcli_conn_set_sockopt(cli->conn, sockops);
2923 for (i=0; i<0x11000; i++) {
2924 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2925 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2926 &fnums[i]);
2927 if (!NT_STATUS_IS_OK(status)) {
2928 printf("open of %s failed (%s)\n",
2929 fname, nt_errstr(status));
2930 printf("maximum fnum is %d\n", i);
2931 break;
2933 printf("%6d\r", i);
2935 printf("%6d\n", i);
2936 i--;
2938 printf("cleaning up\n");
2939 for (;i>=0;i--) {
2940 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2941 cli_close(cli, fnums[i]);
2943 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2944 if (!NT_STATUS_IS_OK(status)) {
2945 printf("unlink of %s failed (%s)\n",
2946 fname, nt_errstr(status));
2947 correct = False;
2949 printf("%6d\r", i);
2951 printf("%6d\n", 0);
2953 printf("maxfid test finished\n");
2954 if (!torture_close_connection(cli)) {
2955 correct = False;
2957 return correct;
2960 /* generate a random buffer */
2961 static void rand_buf(char *buf, int len)
2963 while (len--) {
2964 *buf = (char)sys_random();
2965 buf++;
2969 /* send smb negprot commands, not reading the response */
2970 static bool run_negprot_nowait(int dummy)
2972 struct tevent_context *ev;
2973 int i;
2974 struct cli_state *cli;
2975 bool correct = True;
2977 printf("starting negprot nowait test\n");
2979 ev = samba_tevent_context_init(talloc_tos());
2980 if (ev == NULL) {
2981 return false;
2984 if (!(cli = open_nbt_connection())) {
2985 TALLOC_FREE(ev);
2986 return False;
2989 for (i=0;i<50000;i++) {
2990 struct tevent_req *req;
2992 req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
2993 PROTOCOL_CORE, PROTOCOL_NT1, 0);
2994 if (req == NULL) {
2995 TALLOC_FREE(ev);
2996 return false;
2998 if (!tevent_req_poll(req, ev)) {
2999 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3000 strerror(errno));
3001 TALLOC_FREE(ev);
3002 return false;
3004 TALLOC_FREE(req);
3007 if (torture_close_connection(cli)) {
3008 correct = False;
3011 printf("finished negprot nowait test\n");
3013 return correct;
3016 /* send smb negprot commands, not reading the response */
3017 static bool run_bad_nbt_session(int dummy)
3019 struct nmb_name called, calling;
3020 struct sockaddr_storage ss;
3021 NTSTATUS status;
3022 int fd;
3023 bool ret;
3025 printf("starting bad nbt session test\n");
3027 make_nmb_name(&calling, myname, 0x0);
3028 make_nmb_name(&called , host, 0x20);
3030 if (!resolve_name(host, &ss, 0x20, true)) {
3031 d_fprintf(stderr, "Could not resolve name %s\n", host);
3032 return false;
3035 status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3036 if (!NT_STATUS_IS_OK(status)) {
3037 d_fprintf(stderr, "open_socket_out failed: %s\n",
3038 nt_errstr(status));
3039 return false;
3042 ret = cli_bad_session_request(fd, &calling, &called);
3043 close(fd);
3044 if (!ret) {
3045 d_fprintf(stderr, "open_socket_out failed: %s\n",
3046 nt_errstr(status));
3047 return false;
3050 printf("finished bad nbt session test\n");
3051 return true;
3054 /* send random IPC commands */
3055 static bool run_randomipc(int dummy)
3057 char *rparam = NULL;
3058 char *rdata = NULL;
3059 unsigned int rdrcnt,rprcnt;
3060 char param[1024];
3061 int api, param_len, i;
3062 struct cli_state *cli;
3063 bool correct = True;
3064 int count = 50000;
3066 printf("starting random ipc test\n");
3068 if (!torture_open_connection(&cli, 0)) {
3069 return False;
3072 for (i=0;i<count;i++) {
3073 api = sys_random() % 500;
3074 param_len = (sys_random() % 64);
3076 rand_buf(param, param_len);
3078 SSVAL(param,0,api);
3080 cli_api(cli,
3081 param, param_len, 8,
3082 NULL, 0, CLI_BUFFER_SIZE,
3083 &rparam, &rprcnt,
3084 &rdata, &rdrcnt);
3085 if (i % 100 == 0) {
3086 printf("%d/%d\r", i,count);
3089 printf("%d/%d\n", i, count);
3091 if (!torture_close_connection(cli)) {
3092 correct = False;
3095 SAFE_FREE(rparam);
3096 SAFE_FREE(rdata);
3098 printf("finished random ipc test\n");
3100 return correct;
3105 static void browse_callback(const char *sname, uint32_t stype,
3106 const char *comment, void *state)
3108 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3114 This test checks the browse list code
3117 static bool run_browsetest(int dummy)
3119 static struct cli_state *cli;
3120 bool correct = True;
3122 printf("starting browse test\n");
3124 if (!torture_open_connection(&cli, 0)) {
3125 return False;
3128 printf("domain list:\n");
3129 cli_NetServerEnum(cli, cli->server_domain,
3130 SV_TYPE_DOMAIN_ENUM,
3131 browse_callback, NULL);
3133 printf("machine list:\n");
3134 cli_NetServerEnum(cli, cli->server_domain,
3135 SV_TYPE_ALL,
3136 browse_callback, NULL);
3138 if (!torture_close_connection(cli)) {
3139 correct = False;
3142 printf("browse test finished\n");
3144 return correct;
3150 This checks how the getatr calls works
3152 static bool run_attrtest(int dummy)
3154 struct cli_state *cli;
3155 uint16_t fnum;
3156 time_t t, t2;
3157 const char *fname = "\\attrib123456789.tst";
3158 bool correct = True;
3159 NTSTATUS status;
3161 printf("starting attrib test\n");
3163 if (!torture_open_connection(&cli, 0)) {
3164 return False;
3167 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3168 cli_openx(cli, fname,
3169 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3170 cli_close(cli, fnum);
3172 status = cli_getatr(cli, fname, NULL, NULL, &t);
3173 if (!NT_STATUS_IS_OK(status)) {
3174 printf("getatr failed (%s)\n", nt_errstr(status));
3175 correct = False;
3178 if (abs(t - time(NULL)) > 60*60*24*10) {
3179 printf("ERROR: SMBgetatr bug. time is %s",
3180 ctime(&t));
3181 t = time(NULL);
3182 correct = True;
3185 t2 = t-60*60*24; /* 1 day ago */
3187 status = cli_setatr(cli, fname, 0, t2);
3188 if (!NT_STATUS_IS_OK(status)) {
3189 printf("setatr failed (%s)\n", nt_errstr(status));
3190 correct = True;
3193 status = cli_getatr(cli, fname, NULL, NULL, &t);
3194 if (!NT_STATUS_IS_OK(status)) {
3195 printf("getatr failed (%s)\n", nt_errstr(status));
3196 correct = True;
3199 if (t != t2) {
3200 printf("ERROR: getatr/setatr bug. times are\n%s",
3201 ctime(&t));
3202 printf("%s", ctime(&t2));
3203 correct = True;
3206 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3208 if (!torture_close_connection(cli)) {
3209 correct = False;
3212 printf("attrib test finished\n");
3214 return correct;
3219 This checks a couple of trans2 calls
3221 static bool run_trans2test(int dummy)
3223 struct cli_state *cli;
3224 uint16_t fnum;
3225 off_t size;
3226 time_t c_time, a_time, m_time;
3227 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3228 const char *fname = "\\trans2.tst";
3229 const char *dname = "\\trans2";
3230 const char *fname2 = "\\trans2\\trans2.tst";
3231 char *pname;
3232 bool correct = True;
3233 NTSTATUS status;
3234 uint32_t fs_attr;
3236 printf("starting trans2 test\n");
3238 if (!torture_open_connection(&cli, 0)) {
3239 return False;
3242 status = cli_get_fs_attr_info(cli, &fs_attr);
3243 if (!NT_STATUS_IS_OK(status)) {
3244 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3245 nt_errstr(status));
3246 correct = false;
3249 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3250 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3251 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3252 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3253 if (!NT_STATUS_IS_OK(status)) {
3254 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3255 correct = False;
3258 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3259 if (!NT_STATUS_IS_OK(status)) {
3260 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3261 correct = False;
3263 else if (strcmp(pname, fname)) {
3264 printf("qfilename gave different name? [%s] [%s]\n",
3265 fname, pname);
3266 correct = False;
3269 cli_close(cli, fnum);
3271 sleep(2);
3273 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3274 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3275 &fnum);
3276 if (!NT_STATUS_IS_OK(status)) {
3277 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3278 return False;
3280 cli_close(cli, fnum);
3282 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3283 NULL);
3284 if (!NT_STATUS_IS_OK(status)) {
3285 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3286 correct = False;
3287 } else {
3288 time_t t = time(NULL);
3290 if (c_time != m_time) {
3291 printf("create time=%s", ctime(&c_time));
3292 printf("modify time=%s", ctime(&m_time));
3293 printf("This system appears to have sticky create times\n");
3295 if ((abs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
3296 printf("access time=%s", ctime(&a_time));
3297 printf("This system appears to set a midnight access time\n");
3298 correct = False;
3301 if (abs(m_time - t) > 60*60*24*7) {
3302 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3303 correct = False;
3308 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3309 cli_openx(cli, fname,
3310 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3311 cli_close(cli, fnum);
3312 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3313 &m_time_ts, &size, NULL, NULL);
3314 if (!NT_STATUS_IS_OK(status)) {
3315 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3316 correct = False;
3317 } else {
3318 if (w_time_ts.tv_sec < 60*60*24*2) {
3319 printf("write time=%s", ctime(&w_time_ts.tv_sec));
3320 printf("This system appears to set a initial 0 write time\n");
3321 correct = False;
3325 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3328 /* check if the server updates the directory modification time
3329 when creating a new file */
3330 status = cli_mkdir(cli, dname);
3331 if (!NT_STATUS_IS_OK(status)) {
3332 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3333 correct = False;
3335 sleep(3);
3336 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3337 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3338 if (!NT_STATUS_IS_OK(status)) {
3339 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3340 correct = False;
3343 cli_openx(cli, fname2,
3344 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3345 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3346 cli_close(cli, fnum);
3347 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3348 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3349 if (!NT_STATUS_IS_OK(status)) {
3350 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3351 correct = False;
3352 } else {
3353 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3354 == 0) {
3355 printf("This system does not update directory modification times\n");
3356 correct = False;
3359 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3360 cli_rmdir(cli, dname);
3362 if (!torture_close_connection(cli)) {
3363 correct = False;
3366 printf("trans2 test finished\n");
3368 return correct;
3372 This checks new W2K calls.
3375 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3377 uint8_t *buf = NULL;
3378 uint32_t len;
3379 NTSTATUS status;
3381 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3382 CLI_BUFFER_SIZE, NULL, &buf, &len);
3383 if (!NT_STATUS_IS_OK(status)) {
3384 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3385 nt_errstr(status));
3386 } else {
3387 printf("qfileinfo: level %d, len = %u\n", level, len);
3388 dump_data(0, (uint8_t *)buf, len);
3389 printf("\n");
3391 TALLOC_FREE(buf);
3392 return status;
3395 static bool run_w2ktest(int dummy)
3397 struct cli_state *cli;
3398 uint16_t fnum;
3399 const char *fname = "\\w2ktest\\w2k.tst";
3400 int level;
3401 bool correct = True;
3403 printf("starting w2k test\n");
3405 if (!torture_open_connection(&cli, 0)) {
3406 return False;
3409 cli_openx(cli, fname,
3410 O_RDWR | O_CREAT , DENY_NONE, &fnum);
3412 for (level = 1004; level < 1040; level++) {
3413 new_trans(cli, fnum, level);
3416 cli_close(cli, fnum);
3418 if (!torture_close_connection(cli)) {
3419 correct = False;
3422 printf("w2k test finished\n");
3424 return correct;
3429 this is a harness for some oplock tests
3431 static bool run_oplock1(int dummy)
3433 struct cli_state *cli1;
3434 const char *fname = "\\lockt1.lck";
3435 uint16_t fnum1;
3436 bool correct = True;
3437 NTSTATUS status;
3439 printf("starting oplock test 1\n");
3441 if (!torture_open_connection(&cli1, 0)) {
3442 return False;
3445 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3447 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3449 cli1->use_oplocks = True;
3451 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3452 &fnum1);
3453 if (!NT_STATUS_IS_OK(status)) {
3454 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3455 return False;
3458 cli1->use_oplocks = False;
3460 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3461 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3463 status = cli_close(cli1, fnum1);
3464 if (!NT_STATUS_IS_OK(status)) {
3465 printf("close2 failed (%s)\n", nt_errstr(status));
3466 return False;
3469 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3470 if (!NT_STATUS_IS_OK(status)) {
3471 printf("unlink failed (%s)\n", nt_errstr(status));
3472 return False;
3475 if (!torture_close_connection(cli1)) {
3476 correct = False;
3479 printf("finished oplock test 1\n");
3481 return correct;
3484 static bool run_oplock2(int dummy)
3486 struct cli_state *cli1, *cli2;
3487 const char *fname = "\\lockt2.lck";
3488 uint16_t fnum1, fnum2;
3489 int saved_use_oplocks = use_oplocks;
3490 char buf[4];
3491 bool correct = True;
3492 volatile bool *shared_correct;
3493 size_t nread;
3494 NTSTATUS status;
3496 shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
3497 *shared_correct = True;
3499 use_level_II_oplocks = True;
3500 use_oplocks = True;
3502 printf("starting oplock test 2\n");
3504 if (!torture_open_connection(&cli1, 0)) {
3505 use_level_II_oplocks = False;
3506 use_oplocks = saved_use_oplocks;
3507 return False;
3510 if (!torture_open_connection(&cli2, 1)) {
3511 use_level_II_oplocks = False;
3512 use_oplocks = saved_use_oplocks;
3513 return False;
3516 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3518 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3519 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3521 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3522 &fnum1);
3523 if (!NT_STATUS_IS_OK(status)) {
3524 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3525 return False;
3528 /* Don't need the globals any more. */
3529 use_level_II_oplocks = False;
3530 use_oplocks = saved_use_oplocks;
3532 if (fork() == 0) {
3533 /* Child code */
3534 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3535 if (!NT_STATUS_IS_OK(status)) {
3536 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3537 *shared_correct = False;
3538 exit(0);
3541 sleep(2);
3543 status = cli_close(cli2, fnum2);
3544 if (!NT_STATUS_IS_OK(status)) {
3545 printf("close2 failed (%s)\n", nt_errstr(status));
3546 *shared_correct = False;
3549 exit(0);
3552 sleep(2);
3554 /* Ensure cli1 processes the break. Empty file should always return 0
3555 * bytes. */
3556 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
3557 if (!NT_STATUS_IS_OK(status)) {
3558 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
3559 correct = false;
3560 } else if (nread != 0) {
3561 printf("read on empty fnum1 failed. recv %ld expected %d\n",
3562 (unsigned long)nread, 0);
3563 correct = false;
3566 /* Should now be at level II. */
3567 /* Test if sending a write locks causes a break to none. */
3568 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3569 if (!NT_STATUS_IS_OK(status)) {
3570 printf("lock failed (%s)\n", nt_errstr(status));
3571 correct = False;
3574 cli_unlock(cli1, fnum1, 0, 4);
3576 sleep(2);
3578 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3579 if (!NT_STATUS_IS_OK(status)) {
3580 printf("lock failed (%s)\n", nt_errstr(status));
3581 correct = False;
3584 cli_unlock(cli1, fnum1, 0, 4);
3586 sleep(2);
3588 cli_read(cli1, fnum1, buf, 0, 4, NULL);
3590 status = cli_close(cli1, fnum1);
3591 if (!NT_STATUS_IS_OK(status)) {
3592 printf("close1 failed (%s)\n", nt_errstr(status));
3593 correct = False;
3596 sleep(4);
3598 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3599 if (!NT_STATUS_IS_OK(status)) {
3600 printf("unlink failed (%s)\n", nt_errstr(status));
3601 correct = False;
3604 if (!torture_close_connection(cli1)) {
3605 correct = False;
3608 if (!*shared_correct) {
3609 correct = False;
3612 printf("finished oplock test 2\n");
3614 return correct;
3617 struct oplock4_state {
3618 struct tevent_context *ev;
3619 struct cli_state *cli;
3620 bool *got_break;
3621 uint16_t *fnum2;
3624 static void oplock4_got_break(struct tevent_req *req);
3625 static void oplock4_got_open(struct tevent_req *req);
3627 static bool run_oplock4(int dummy)
3629 struct tevent_context *ev;
3630 struct cli_state *cli1, *cli2;
3631 struct tevent_req *oplock_req, *open_req;
3632 const char *fname = "\\lockt4.lck";
3633 const char *fname_ln = "\\lockt4_ln.lck";
3634 uint16_t fnum1, fnum2;
3635 int saved_use_oplocks = use_oplocks;
3636 NTSTATUS status;
3637 bool correct = true;
3639 bool got_break;
3641 struct oplock4_state *state;
3643 printf("starting oplock test 4\n");
3645 if (!torture_open_connection(&cli1, 0)) {
3646 use_level_II_oplocks = false;
3647 use_oplocks = saved_use_oplocks;
3648 return false;
3651 if (!torture_open_connection(&cli2, 1)) {
3652 use_level_II_oplocks = false;
3653 use_oplocks = saved_use_oplocks;
3654 return false;
3657 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3658 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3660 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3661 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3663 /* Create the file. */
3664 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3665 &fnum1);
3666 if (!NT_STATUS_IS_OK(status)) {
3667 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3668 return false;
3671 status = cli_close(cli1, fnum1);
3672 if (!NT_STATUS_IS_OK(status)) {
3673 printf("close1 failed (%s)\n", nt_errstr(status));
3674 return false;
3677 /* Now create a hardlink. */
3678 status = cli_nt_hardlink(cli1, fname, fname_ln);
3679 if (!NT_STATUS_IS_OK(status)) {
3680 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3681 return false;
3684 /* Prove that opening hardlinks cause deny modes to conflict. */
3685 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3686 if (!NT_STATUS_IS_OK(status)) {
3687 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3688 return false;
3691 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3692 if (NT_STATUS_IS_OK(status)) {
3693 printf("open of %s succeeded - should fail with sharing violation.\n",
3694 fname_ln);
3695 return false;
3698 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3699 printf("open of %s should fail with sharing violation. Got %s\n",
3700 fname_ln, nt_errstr(status));
3701 return false;
3704 status = cli_close(cli1, fnum1);
3705 if (!NT_STATUS_IS_OK(status)) {
3706 printf("close1 failed (%s)\n", nt_errstr(status));
3707 return false;
3710 cli1->use_oplocks = true;
3711 cli2->use_oplocks = true;
3713 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3714 if (!NT_STATUS_IS_OK(status)) {
3715 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3716 return false;
3719 ev = samba_tevent_context_init(talloc_tos());
3720 if (ev == NULL) {
3721 printf("tevent_context_init failed\n");
3722 return false;
3725 state = talloc(ev, struct oplock4_state);
3726 if (state == NULL) {
3727 printf("talloc failed\n");
3728 return false;
3730 state->ev = ev;
3731 state->cli = cli1;
3732 state->got_break = &got_break;
3733 state->fnum2 = &fnum2;
3735 oplock_req = cli_smb_oplock_break_waiter_send(
3736 talloc_tos(), ev, cli1);
3737 if (oplock_req == NULL) {
3738 printf("cli_smb_oplock_break_waiter_send failed\n");
3739 return false;
3741 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3743 open_req = cli_openx_send(
3744 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3745 if (open_req == NULL) {
3746 printf("cli_openx_send failed\n");
3747 return false;
3749 tevent_req_set_callback(open_req, oplock4_got_open, state);
3751 got_break = false;
3752 fnum2 = 0xffff;
3754 while (!got_break || fnum2 == 0xffff) {
3755 int ret;
3756 ret = tevent_loop_once(ev);
3757 if (ret == -1) {
3758 printf("tevent_loop_once failed: %s\n",
3759 strerror(errno));
3760 return false;
3764 status = cli_close(cli2, fnum2);
3765 if (!NT_STATUS_IS_OK(status)) {
3766 printf("close2 failed (%s)\n", nt_errstr(status));
3767 correct = false;
3770 status = cli_close(cli1, fnum1);
3771 if (!NT_STATUS_IS_OK(status)) {
3772 printf("close1 failed (%s)\n", nt_errstr(status));
3773 correct = false;
3776 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3777 if (!NT_STATUS_IS_OK(status)) {
3778 printf("unlink failed (%s)\n", nt_errstr(status));
3779 correct = false;
3782 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3783 if (!NT_STATUS_IS_OK(status)) {
3784 printf("unlink failed (%s)\n", nt_errstr(status));
3785 correct = false;
3788 if (!torture_close_connection(cli1)) {
3789 correct = false;
3792 if (!got_break) {
3793 correct = false;
3796 printf("finished oplock test 4\n");
3798 return correct;
3801 static void oplock4_got_break(struct tevent_req *req)
3803 struct oplock4_state *state = tevent_req_callback_data(
3804 req, struct oplock4_state);
3805 uint16_t fnum;
3806 uint8_t level;
3807 NTSTATUS status;
3809 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3810 TALLOC_FREE(req);
3811 if (!NT_STATUS_IS_OK(status)) {
3812 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3813 nt_errstr(status));
3814 return;
3816 *state->got_break = true;
3818 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3819 NO_OPLOCK);
3820 if (req == NULL) {
3821 printf("cli_oplock_ack_send failed\n");
3822 return;
3826 static void oplock4_got_open(struct tevent_req *req)
3828 struct oplock4_state *state = tevent_req_callback_data(
3829 req, struct oplock4_state);
3830 NTSTATUS status;
3832 status = cli_openx_recv(req, state->fnum2);
3833 if (!NT_STATUS_IS_OK(status)) {
3834 printf("cli_openx_recv returned %s\n", nt_errstr(status));
3835 *state->fnum2 = 0xffff;
3840 Test delete on close semantics.
3842 static bool run_deletetest(int dummy)
3844 struct cli_state *cli1 = NULL;
3845 struct cli_state *cli2 = NULL;
3846 const char *fname = "\\delete.file";
3847 uint16_t fnum1 = (uint16_t)-1;
3848 uint16_t fnum2 = (uint16_t)-1;
3849 bool correct = false;
3850 NTSTATUS status;
3852 printf("starting delete test\n");
3854 if (!torture_open_connection(&cli1, 0)) {
3855 return False;
3858 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3860 /* Test 1 - this should delete the file on close. */
3862 cli_setatr(cli1, fname, 0, 0);
3863 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3865 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3866 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3867 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
3868 if (!NT_STATUS_IS_OK(status)) {
3869 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3870 goto fail;
3873 status = cli_close(cli1, fnum1);
3874 if (!NT_STATUS_IS_OK(status)) {
3875 printf("[1] close failed (%s)\n", nt_errstr(status));
3876 goto fail;
3879 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3880 if (NT_STATUS_IS_OK(status)) {
3881 printf("[1] open of %s succeeded (should fail)\n", fname);
3882 goto fail;
3885 printf("first delete on close test succeeded.\n");
3887 /* Test 2 - this should delete the file on close. */
3889 cli_setatr(cli1, fname, 0, 0);
3890 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3892 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3893 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3894 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
3895 if (!NT_STATUS_IS_OK(status)) {
3896 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3897 goto fail;
3900 status = cli_nt_delete_on_close(cli1, fnum1, true);
3901 if (!NT_STATUS_IS_OK(status)) {
3902 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3903 goto fail;
3906 status = cli_close(cli1, fnum1);
3907 if (!NT_STATUS_IS_OK(status)) {
3908 printf("[2] close failed (%s)\n", nt_errstr(status));
3909 goto fail;
3912 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
3913 if (NT_STATUS_IS_OK(status)) {
3914 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3915 status = cli_close(cli1, fnum1);
3916 if (!NT_STATUS_IS_OK(status)) {
3917 printf("[2] close failed (%s)\n", nt_errstr(status));
3919 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3920 goto fail;
3923 printf("second delete on close test succeeded.\n");
3925 /* Test 3 - ... */
3926 cli_setatr(cli1, fname, 0, 0);
3927 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3929 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3930 FILE_ATTRIBUTE_NORMAL,
3931 FILE_SHARE_READ|FILE_SHARE_WRITE,
3932 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
3933 if (!NT_STATUS_IS_OK(status)) {
3934 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
3935 goto fail;
3938 /* This should fail with a sharing violation - open for delete is only compatible
3939 with SHARE_DELETE. */
3941 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3942 FILE_ATTRIBUTE_NORMAL,
3943 FILE_SHARE_READ|FILE_SHARE_WRITE,
3944 FILE_OPEN, 0, 0, &fnum2, NULL);
3945 if (NT_STATUS_IS_OK(status)) {
3946 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
3947 goto fail;
3950 /* This should succeed. */
3951 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3952 FILE_ATTRIBUTE_NORMAL,
3953 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3954 FILE_OPEN, 0, 0, &fnum2, NULL);
3955 if (!NT_STATUS_IS_OK(status)) {
3956 printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
3957 goto fail;
3960 status = cli_nt_delete_on_close(cli1, fnum1, true);
3961 if (!NT_STATUS_IS_OK(status)) {
3962 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
3963 goto fail;
3966 status = cli_close(cli1, fnum1);
3967 if (!NT_STATUS_IS_OK(status)) {
3968 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
3969 goto fail;
3972 status = cli_close(cli1, fnum2);
3973 if (!NT_STATUS_IS_OK(status)) {
3974 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
3975 goto fail;
3978 /* This should fail - file should no longer be there. */
3980 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
3981 if (NT_STATUS_IS_OK(status)) {
3982 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
3983 status = cli_close(cli1, fnum1);
3984 if (!NT_STATUS_IS_OK(status)) {
3985 printf("[3] close failed (%s)\n", nt_errstr(status));
3987 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3988 goto fail;
3991 printf("third delete on close test succeeded.\n");
3993 /* Test 4 ... */
3994 cli_setatr(cli1, fname, 0, 0);
3995 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3997 status = cli_ntcreate(cli1, fname, 0,
3998 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3999 FILE_ATTRIBUTE_NORMAL,
4000 FILE_SHARE_READ|FILE_SHARE_WRITE,
4001 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4002 if (!NT_STATUS_IS_OK(status)) {
4003 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4004 goto fail;
4007 /* This should succeed. */
4008 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4009 FILE_ATTRIBUTE_NORMAL,
4010 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4011 FILE_OPEN, 0, 0, &fnum2, NULL);
4012 if (!NT_STATUS_IS_OK(status)) {
4013 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4014 goto fail;
4017 status = cli_close(cli1, fnum2);
4018 if (!NT_STATUS_IS_OK(status)) {
4019 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4020 goto fail;
4023 status = cli_nt_delete_on_close(cli1, fnum1, true);
4024 if (!NT_STATUS_IS_OK(status)) {
4025 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4026 goto fail;
4029 /* This should fail - no more opens once delete on close set. */
4030 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4031 FILE_ATTRIBUTE_NORMAL,
4032 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4033 FILE_OPEN, 0, 0, &fnum2, NULL);
4034 if (NT_STATUS_IS_OK(status)) {
4035 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
4036 goto fail;
4039 status = cli_close(cli1, fnum1);
4040 if (!NT_STATUS_IS_OK(status)) {
4041 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4042 goto fail;
4045 printf("fourth delete on close test succeeded.\n");
4047 /* Test 5 ... */
4048 cli_setatr(cli1, fname, 0, 0);
4049 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4051 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4052 if (!NT_STATUS_IS_OK(status)) {
4053 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4054 goto fail;
4057 /* This should fail - only allowed on NT opens with DELETE access. */
4059 status = cli_nt_delete_on_close(cli1, fnum1, true);
4060 if (NT_STATUS_IS_OK(status)) {
4061 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4062 goto fail;
4065 status = cli_close(cli1, fnum1);
4066 if (!NT_STATUS_IS_OK(status)) {
4067 printf("[5] close failed (%s)\n", nt_errstr(status));
4068 goto fail;
4071 printf("fifth delete on close test succeeded.\n");
4073 /* Test 6 ... */
4074 cli_setatr(cli1, fname, 0, 0);
4075 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4077 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4078 FILE_ATTRIBUTE_NORMAL,
4079 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4080 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4081 if (!NT_STATUS_IS_OK(status)) {
4082 printf("[6] open of %s failed (%s)\n", fname,
4083 nt_errstr(status));
4084 goto fail;
4087 /* This should fail - only allowed on NT opens with DELETE access. */
4089 status = cli_nt_delete_on_close(cli1, fnum1, true);
4090 if (NT_STATUS_IS_OK(status)) {
4091 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4092 goto fail;
4095 status = cli_close(cli1, fnum1);
4096 if (!NT_STATUS_IS_OK(status)) {
4097 printf("[6] close failed (%s)\n", nt_errstr(status));
4098 goto fail;
4101 printf("sixth delete on close test succeeded.\n");
4103 /* Test 7 ... */
4104 cli_setatr(cli1, fname, 0, 0);
4105 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4107 status = cli_ntcreate(cli1, fname, 0,
4108 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4109 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4110 0, 0, &fnum1, NULL);
4111 if (!NT_STATUS_IS_OK(status)) {
4112 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4113 goto fail;
4116 status = cli_nt_delete_on_close(cli1, fnum1, true);
4117 if (!NT_STATUS_IS_OK(status)) {
4118 printf("[7] setting delete_on_close on file failed !\n");
4119 goto fail;
4122 status = cli_nt_delete_on_close(cli1, fnum1, false);
4123 if (!NT_STATUS_IS_OK(status)) {
4124 printf("[7] unsetting delete_on_close on file failed !\n");
4125 goto fail;
4128 status = cli_close(cli1, fnum1);
4129 if (!NT_STATUS_IS_OK(status)) {
4130 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
4131 goto fail;
4134 /* This next open should succeed - we reset the flag. */
4135 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4136 if (!NT_STATUS_IS_OK(status)) {
4137 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4138 goto fail;
4141 status = cli_close(cli1, fnum1);
4142 if (!NT_STATUS_IS_OK(status)) {
4143 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4144 goto fail;
4147 printf("seventh delete on close test succeeded.\n");
4149 /* Test 8 ... */
4150 cli_setatr(cli1, fname, 0, 0);
4151 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4153 if (!torture_open_connection(&cli2, 1)) {
4154 printf("[8] failed to open second connection.\n");
4155 goto fail;
4158 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4160 status = cli_ntcreate(cli1, fname, 0,
4161 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4162 FILE_ATTRIBUTE_NORMAL,
4163 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4164 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4165 if (!NT_STATUS_IS_OK(status)) {
4166 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4167 goto fail;
4170 status = cli_ntcreate(cli2, fname, 0,
4171 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4172 FILE_ATTRIBUTE_NORMAL,
4173 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4174 FILE_OPEN, 0, 0, &fnum2, NULL);
4175 if (!NT_STATUS_IS_OK(status)) {
4176 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4177 goto fail;
4180 status = cli_nt_delete_on_close(cli1, fnum1, true);
4181 if (!NT_STATUS_IS_OK(status)) {
4182 printf("[8] setting delete_on_close on file failed !\n");
4183 goto fail;
4186 status = cli_close(cli1, fnum1);
4187 if (!NT_STATUS_IS_OK(status)) {
4188 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4189 goto fail;
4192 status = cli_close(cli2, fnum2);
4193 if (!NT_STATUS_IS_OK(status)) {
4194 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4195 goto fail;
4198 /* This should fail.. */
4199 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4200 if (NT_STATUS_IS_OK(status)) {
4201 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4202 goto fail;
4205 printf("eighth delete on close test succeeded.\n");
4207 /* Test 9 ... */
4209 /* This should fail - we need to set DELETE_ACCESS. */
4210 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4211 FILE_ATTRIBUTE_NORMAL,
4212 FILE_SHARE_NONE,
4213 FILE_OVERWRITE_IF,
4214 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4215 if (NT_STATUS_IS_OK(status)) {
4216 printf("[9] open of %s succeeded should have failed!\n", fname);
4217 goto fail;
4220 printf("ninth delete on close test succeeded.\n");
4222 /* Test 10 ... */
4224 status = cli_ntcreate(cli1, fname, 0,
4225 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4226 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4227 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4228 0, &fnum1, NULL);
4229 if (!NT_STATUS_IS_OK(status)) {
4230 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4231 goto fail;
4234 /* This should delete the file. */
4235 status = cli_close(cli1, fnum1);
4236 if (!NT_STATUS_IS_OK(status)) {
4237 printf("[10] close failed (%s)\n", nt_errstr(status));
4238 goto fail;
4241 /* This should fail.. */
4242 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4243 if (NT_STATUS_IS_OK(status)) {
4244 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4245 goto fail;
4248 printf("tenth delete on close test succeeded.\n");
4250 /* Test 11 ... */
4252 cli_setatr(cli1, fname, 0, 0);
4253 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4255 /* Can we open a read-only file with delete access? */
4257 /* Create a readonly file. */
4258 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4259 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4260 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4261 if (!NT_STATUS_IS_OK(status)) {
4262 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4263 goto fail;
4266 status = cli_close(cli1, fnum1);
4267 if (!NT_STATUS_IS_OK(status)) {
4268 printf("[11] close failed (%s)\n", nt_errstr(status));
4269 goto fail;
4272 /* Now try open for delete access. */
4273 status = cli_ntcreate(cli1, fname, 0,
4274 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4276 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4277 FILE_OPEN, 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 cli_close(cli1, fnum1);
4285 printf("eleventh delete on close test succeeded.\n");
4288 * Test 12
4289 * like test 4 but with initial delete on close
4292 cli_setatr(cli1, fname, 0, 0);
4293 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4295 status = cli_ntcreate(cli1, fname, 0,
4296 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4297 FILE_ATTRIBUTE_NORMAL,
4298 FILE_SHARE_READ|FILE_SHARE_WRITE,
4299 FILE_OVERWRITE_IF,
4300 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4301 if (!NT_STATUS_IS_OK(status)) {
4302 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4303 goto fail;
4306 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4307 FILE_ATTRIBUTE_NORMAL,
4308 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4309 FILE_OPEN, 0, 0, &fnum2, NULL);
4310 if (!NT_STATUS_IS_OK(status)) {
4311 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
4312 goto fail;
4315 status = cli_close(cli1, fnum2);
4316 if (!NT_STATUS_IS_OK(status)) {
4317 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
4318 goto fail;
4321 status = cli_nt_delete_on_close(cli1, fnum1, true);
4322 if (!NT_STATUS_IS_OK(status)) {
4323 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
4324 goto fail;
4327 /* This should fail - no more opens once delete on close set. */
4328 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4329 FILE_ATTRIBUTE_NORMAL,
4330 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4331 FILE_OPEN, 0, 0, &fnum2, NULL);
4332 if (NT_STATUS_IS_OK(status)) {
4333 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
4334 goto fail;
4337 status = cli_nt_delete_on_close(cli1, fnum1, false);
4338 if (!NT_STATUS_IS_OK(status)) {
4339 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
4340 goto fail;
4343 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4344 FILE_ATTRIBUTE_NORMAL,
4345 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4346 FILE_OPEN, 0, 0, &fnum2, NULL);
4347 if (!NT_STATUS_IS_OK(status)) {
4348 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
4349 goto fail;
4352 status = cli_close(cli1, fnum2);
4353 if (!NT_STATUS_IS_OK(status)) {
4354 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
4355 goto fail;
4358 status = cli_close(cli1, fnum1);
4359 if (!NT_STATUS_IS_OK(status)) {
4360 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
4361 goto fail;
4365 * setting delete on close on the handle does
4366 * not unset the initial delete on close...
4368 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4369 FILE_ATTRIBUTE_NORMAL,
4370 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4371 FILE_OPEN, 0, 0, &fnum2, NULL);
4372 if (NT_STATUS_IS_OK(status)) {
4373 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
4374 goto fail;
4375 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4376 printf("ntcreate returned %s, expected "
4377 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
4378 nt_errstr(status));
4379 goto fail;
4382 printf("twelfth delete on close test succeeded.\n");
4385 printf("finished delete test\n");
4387 correct = true;
4389 fail:
4390 /* FIXME: This will crash if we aborted before cli2 got
4391 * intialized, because these functions don't handle
4392 * uninitialized connections. */
4394 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4395 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4396 cli_setatr(cli1, fname, 0, 0);
4397 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4399 if (cli1 && !torture_close_connection(cli1)) {
4400 correct = False;
4402 if (cli2 && !torture_close_connection(cli2)) {
4403 correct = False;
4405 return correct;
4410 Test wildcard delete.
4412 static bool run_wild_deletetest(int dummy)
4414 struct cli_state *cli = NULL;
4415 const char *dname = "\\WTEST";
4416 const char *fname = "\\WTEST\\A";
4417 const char *wunlink_name = "\\WTEST\\*";
4418 uint16_t fnum1 = (uint16_t)-1;
4419 bool correct = false;
4420 NTSTATUS status;
4422 printf("starting wildcard delete test\n");
4424 if (!torture_open_connection(&cli, 0)) {
4425 return false;
4428 smbXcli_conn_set_sockopt(cli->conn, sockops);
4430 cli_unlink(cli, fname, 0);
4431 cli_rmdir(cli, dname);
4432 status = cli_mkdir(cli, dname);
4433 if (!NT_STATUS_IS_OK(status)) {
4434 printf("mkdir of %s failed %s!\n", dname, nt_errstr(status));
4435 goto fail;
4437 status = cli_openx(cli, fname, O_CREAT|O_RDONLY, DENY_NONE, &fnum1);
4438 if (!NT_STATUS_IS_OK(status)) {
4439 printf("open of %s failed %s!\n", fname, nt_errstr(status));
4440 goto fail;
4442 status = cli_close(cli, fnum1);
4443 fnum1 = -1;
4446 * Note the unlink attribute-type of zero. This should
4447 * map into FILE_ATTRIBUTE_NORMAL at the server even
4448 * on a wildcard delete.
4451 status = cli_unlink(cli, wunlink_name, 0);
4452 if (!NT_STATUS_IS_OK(status)) {
4453 printf("unlink of %s failed %s!\n",
4454 wunlink_name, nt_errstr(status));
4455 goto fail;
4458 printf("finished wildcard delete test\n");
4460 correct = true;
4462 fail:
4464 if (fnum1 != (uint16_t)-1) cli_close(cli, fnum1);
4465 cli_unlink(cli, fname, 0);
4466 cli_rmdir(cli, dname);
4468 if (cli && !torture_close_connection(cli)) {
4469 correct = false;
4471 return correct;
4474 static bool run_deletetest_ln(int dummy)
4476 struct cli_state *cli;
4477 const char *fname = "\\delete1";
4478 const char *fname_ln = "\\delete1_ln";
4479 uint16_t fnum;
4480 uint16_t fnum1;
4481 NTSTATUS status;
4482 bool correct = true;
4483 time_t t;
4485 printf("starting deletetest-ln\n");
4487 if (!torture_open_connection(&cli, 0)) {
4488 return false;
4491 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4492 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4494 smbXcli_conn_set_sockopt(cli->conn, sockops);
4496 /* Create the file. */
4497 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4498 if (!NT_STATUS_IS_OK(status)) {
4499 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4500 return false;
4503 status = cli_close(cli, fnum);
4504 if (!NT_STATUS_IS_OK(status)) {
4505 printf("close1 failed (%s)\n", nt_errstr(status));
4506 return false;
4509 /* Now create a hardlink. */
4510 status = cli_nt_hardlink(cli, fname, fname_ln);
4511 if (!NT_STATUS_IS_OK(status)) {
4512 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4513 return false;
4516 /* Open the original file. */
4517 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4518 FILE_ATTRIBUTE_NORMAL,
4519 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4520 FILE_OPEN_IF, 0, 0, &fnum, NULL);
4521 if (!NT_STATUS_IS_OK(status)) {
4522 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4523 return false;
4526 /* Unlink the hard link path. */
4527 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4528 FILE_ATTRIBUTE_NORMAL,
4529 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4530 FILE_OPEN_IF, 0, 0, &fnum1, NULL);
4531 if (!NT_STATUS_IS_OK(status)) {
4532 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4533 return false;
4535 status = cli_nt_delete_on_close(cli, fnum1, true);
4536 if (!NT_STATUS_IS_OK(status)) {
4537 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4538 __location__, fname_ln, nt_errstr(status));
4539 return false;
4542 status = cli_close(cli, fnum1);
4543 if (!NT_STATUS_IS_OK(status)) {
4544 printf("close %s failed (%s)\n",
4545 fname_ln, nt_errstr(status));
4546 return false;
4549 status = cli_close(cli, fnum);
4550 if (!NT_STATUS_IS_OK(status)) {
4551 printf("close %s failed (%s)\n",
4552 fname, nt_errstr(status));
4553 return false;
4556 /* Ensure the original file is still there. */
4557 status = cli_getatr(cli, fname, NULL, NULL, &t);
4558 if (!NT_STATUS_IS_OK(status)) {
4559 printf("%s getatr on file %s failed (%s)\n",
4560 __location__,
4561 fname,
4562 nt_errstr(status));
4563 correct = False;
4566 /* Ensure the link path is gone. */
4567 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4568 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4569 printf("%s, getatr for file %s returned wrong error code %s "
4570 "- should have been deleted\n",
4571 __location__,
4572 fname_ln, nt_errstr(status));
4573 correct = False;
4576 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4577 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4579 if (!torture_close_connection(cli)) {
4580 correct = false;
4583 printf("finished deletetest-ln\n");
4585 return correct;
4589 print out server properties
4591 static bool run_properties(int dummy)
4593 struct cli_state *cli;
4594 bool correct = True;
4596 printf("starting properties test\n");
4598 ZERO_STRUCT(cli);
4600 if (!torture_open_connection(&cli, 0)) {
4601 return False;
4604 smbXcli_conn_set_sockopt(cli->conn, sockops);
4606 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
4608 if (!torture_close_connection(cli)) {
4609 correct = False;
4612 return correct;
4617 /* FIRST_DESIRED_ACCESS 0xf019f */
4618 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4619 FILE_READ_EA| /* 0xf */ \
4620 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
4621 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
4622 DELETE_ACCESS|READ_CONTROL_ACCESS|\
4623 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
4624 /* SECOND_DESIRED_ACCESS 0xe0080 */
4625 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4626 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4627 WRITE_OWNER_ACCESS /* 0xe0000 */
4629 #if 0
4630 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4631 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4632 FILE_READ_DATA|\
4633 WRITE_OWNER_ACCESS /* */
4634 #endif
4637 Test ntcreate calls made by xcopy
4639 static bool run_xcopy(int dummy)
4641 static struct cli_state *cli1;
4642 const char *fname = "\\test.txt";
4643 bool correct = True;
4644 uint16_t fnum1, fnum2;
4645 NTSTATUS status;
4647 printf("starting xcopy test\n");
4649 if (!torture_open_connection(&cli1, 0)) {
4650 return False;
4653 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4654 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4655 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
4656 if (!NT_STATUS_IS_OK(status)) {
4657 printf("First open failed - %s\n", nt_errstr(status));
4658 return False;
4661 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4662 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4663 FILE_OPEN, 0x200000, 0, &fnum2, NULL);
4664 if (!NT_STATUS_IS_OK(status)) {
4665 printf("second open failed - %s\n", nt_errstr(status));
4666 return False;
4669 if (!torture_close_connection(cli1)) {
4670 correct = False;
4673 return correct;
4677 Test rename on files open with share delete and no share delete.
4679 static bool run_rename(int dummy)
4681 static struct cli_state *cli1;
4682 const char *fname = "\\test.txt";
4683 const char *fname1 = "\\test1.txt";
4684 bool correct = True;
4685 uint16_t fnum1;
4686 uint16_t attr;
4687 NTSTATUS status;
4689 printf("starting rename test\n");
4691 if (!torture_open_connection(&cli1, 0)) {
4692 return False;
4695 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4696 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4698 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4699 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4700 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4701 if (!NT_STATUS_IS_OK(status)) {
4702 printf("First open failed - %s\n", nt_errstr(status));
4703 return False;
4706 status = cli_rename(cli1, fname, fname1, false);
4707 if (!NT_STATUS_IS_OK(status)) {
4708 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4709 } else {
4710 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4711 correct = False;
4714 status = cli_close(cli1, fnum1);
4715 if (!NT_STATUS_IS_OK(status)) {
4716 printf("close - 1 failed (%s)\n", nt_errstr(status));
4717 return False;
4720 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4721 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4722 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4723 #if 0
4724 FILE_SHARE_DELETE|FILE_SHARE_NONE,
4725 #else
4726 FILE_SHARE_DELETE|FILE_SHARE_READ,
4727 #endif
4728 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4729 if (!NT_STATUS_IS_OK(status)) {
4730 printf("Second open failed - %s\n", nt_errstr(status));
4731 return False;
4734 status = cli_rename(cli1, fname, fname1, false);
4735 if (!NT_STATUS_IS_OK(status)) {
4736 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4737 correct = False;
4738 } else {
4739 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4742 status = cli_close(cli1, fnum1);
4743 if (!NT_STATUS_IS_OK(status)) {
4744 printf("close - 2 failed (%s)\n", nt_errstr(status));
4745 return False;
4748 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4749 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4751 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4752 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4753 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4754 if (!NT_STATUS_IS_OK(status)) {
4755 printf("Third open failed - %s\n", nt_errstr(status));
4756 return False;
4760 #if 0
4762 uint16_t fnum2;
4764 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4765 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
4766 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4767 return False;
4769 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4770 printf("[8] setting delete_on_close on file failed !\n");
4771 return False;
4774 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4775 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4776 return False;
4779 #endif
4781 status = cli_rename(cli1, fname, fname1, false);
4782 if (!NT_STATUS_IS_OK(status)) {
4783 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4784 correct = False;
4785 } else {
4786 printf("Third rename succeeded (SHARE_NONE)\n");
4789 status = cli_close(cli1, fnum1);
4790 if (!NT_STATUS_IS_OK(status)) {
4791 printf("close - 3 failed (%s)\n", nt_errstr(status));
4792 return False;
4795 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4796 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4798 /*----*/
4800 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4801 FILE_ATTRIBUTE_NORMAL,
4802 FILE_SHARE_READ | FILE_SHARE_WRITE,
4803 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4804 if (!NT_STATUS_IS_OK(status)) {
4805 printf("Fourth open failed - %s\n", nt_errstr(status));
4806 return False;
4809 status = cli_rename(cli1, fname, fname1, false);
4810 if (!NT_STATUS_IS_OK(status)) {
4811 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4812 } else {
4813 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4814 correct = False;
4817 status = cli_close(cli1, fnum1);
4818 if (!NT_STATUS_IS_OK(status)) {
4819 printf("close - 4 failed (%s)\n", nt_errstr(status));
4820 return False;
4823 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4824 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4826 /*--*/
4828 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4829 FILE_ATTRIBUTE_NORMAL,
4830 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4831 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4832 if (!NT_STATUS_IS_OK(status)) {
4833 printf("Fifth open failed - %s\n", nt_errstr(status));
4834 return False;
4837 status = cli_rename(cli1, fname, fname1, false);
4838 if (!NT_STATUS_IS_OK(status)) {
4839 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4840 correct = False;
4841 } else {
4842 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4846 * Now check if the first name still exists ...
4849 /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4850 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4851 FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
4852 printf("Opening original file after rename of open file fails: %s\n",
4853 cli_errstr(cli1));
4855 else {
4856 printf("Opening original file after rename of open file works ...\n");
4857 (void)cli_close(cli1, fnum2);
4858 } */
4860 /*--*/
4861 status = cli_close(cli1, fnum1);
4862 if (!NT_STATUS_IS_OK(status)) {
4863 printf("close - 5 failed (%s)\n", nt_errstr(status));
4864 return False;
4867 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4868 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4869 if (!NT_STATUS_IS_OK(status)) {
4870 printf("getatr on file %s failed - %s ! \n",
4871 fname1, nt_errstr(status));
4872 correct = False;
4873 } else {
4874 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4875 printf("Renamed file %s has wrong attr 0x%x "
4876 "(should be 0x%x)\n",
4877 fname1,
4878 attr,
4879 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4880 correct = False;
4881 } else {
4882 printf("Renamed file %s has archive bit set\n", fname1);
4886 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4887 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4889 if (!torture_close_connection(cli1)) {
4890 correct = False;
4893 return correct;
4897 Test rename into a directory with an ACL denying it.
4899 static bool run_rename_access(int dummy)
4901 static struct cli_state *cli = NULL;
4902 static struct cli_state *posix_cli = NULL;
4903 const char *src = "test.txt";
4904 const char *dname = "dir";
4905 const char *dst = "dir\\test.txt";
4906 const char *dsrc = "test.dir";
4907 const char *ddst = "dir\\test.dir";
4908 uint16_t fnum = (uint16_t)-1;
4909 struct security_descriptor *sd = NULL;
4910 struct security_descriptor *newsd = NULL;
4911 NTSTATUS status;
4912 TALLOC_CTX *frame = NULL;
4914 frame = talloc_stackframe();
4915 printf("starting rename access test\n");
4917 /* Windows connection. */
4918 if (!torture_open_connection(&cli, 0)) {
4919 goto fail;
4922 smbXcli_conn_set_sockopt(cli->conn, sockops);
4924 /* Posix connection. */
4925 if (!torture_open_connection(&posix_cli, 0)) {
4926 goto fail;
4929 smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
4931 status = torture_setup_unix_extensions(posix_cli);
4932 if (!NT_STATUS_IS_OK(status)) {
4933 goto fail;
4936 /* Start with a clean slate. */
4937 cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4938 cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4939 cli_rmdir(cli, dsrc);
4940 cli_rmdir(cli, ddst);
4941 cli_rmdir(cli, dname);
4944 * Setup the destination directory with a DENY ACE to
4945 * prevent new files within it.
4947 status = cli_ntcreate(cli,
4948 dname,
4950 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
4951 WRITE_DAC_ACCESS|FILE_READ_DATA|
4952 WRITE_OWNER_ACCESS,
4953 FILE_ATTRIBUTE_DIRECTORY,
4954 FILE_SHARE_READ|FILE_SHARE_WRITE,
4955 FILE_CREATE,
4956 FILE_DIRECTORY_FILE,
4958 &fnum,
4959 NULL);
4960 if (!NT_STATUS_IS_OK(status)) {
4961 printf("Create of %s - %s\n", dname, nt_errstr(status));
4962 goto fail;
4965 status = cli_query_secdesc(cli,
4966 fnum,
4967 frame,
4968 &sd);
4969 if (!NT_STATUS_IS_OK(status)) {
4970 printf("cli_query_secdesc failed for %s (%s)\n",
4971 dname, nt_errstr(status));
4972 goto fail;
4975 newsd = security_descriptor_dacl_create(frame,
4977 NULL,
4978 NULL,
4979 SID_WORLD,
4980 SEC_ACE_TYPE_ACCESS_DENIED,
4981 SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
4983 NULL);
4984 if (newsd == NULL) {
4985 goto fail;
4987 sd->dacl = security_acl_concatenate(frame,
4988 newsd->dacl,
4989 sd->dacl);
4990 if (sd->dacl == NULL) {
4991 goto fail;
4993 status = cli_set_secdesc(cli, fnum, sd);
4994 if (!NT_STATUS_IS_OK(status)) {
4995 printf("cli_set_secdesc failed for %s (%s)\n",
4996 dname, nt_errstr(status));
4997 goto fail;
4999 status = cli_close(cli, fnum);
5000 if (!NT_STATUS_IS_OK(status)) {
5001 printf("close failed for %s (%s)\n",
5002 dname, nt_errstr(status));
5003 goto fail;
5005 /* Now go around the back and chmod to 777 via POSIX. */
5006 status = cli_posix_chmod(posix_cli, dname, 0777);
5007 if (!NT_STATUS_IS_OK(status)) {
5008 printf("cli_posix_chmod failed for %s (%s)\n",
5009 dname, nt_errstr(status));
5010 goto fail;
5013 /* Check we can't create a file within dname via Windows. */
5014 status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5015 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5016 cli_close(posix_cli, fnum);
5017 printf("Create of %s should be ACCESS denied, was %s\n",
5018 dst, nt_errstr(status));
5019 goto fail;
5022 /* Make the sample file/directory. */
5023 status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5024 if (!NT_STATUS_IS_OK(status)) {
5025 printf("open of %s failed (%s)\n", src, nt_errstr(status));
5026 goto fail;
5028 status = cli_close(cli, fnum);
5029 if (!NT_STATUS_IS_OK(status)) {
5030 printf("cli_close failed (%s)\n", nt_errstr(status));
5031 goto fail;
5034 status = cli_mkdir(cli, dsrc);
5035 if (!NT_STATUS_IS_OK(status)) {
5036 printf("cli_mkdir of %s failed (%s)\n",
5037 dsrc, nt_errstr(status));
5038 goto fail;
5042 * OK - renames of the new file and directory into the
5043 * dst directory should fail.
5046 status = cli_rename(cli, src, dst, false);
5047 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5048 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
5049 src, dst, nt_errstr(status));
5050 goto fail;
5052 status = cli_rename(cli, dsrc, ddst, false);
5053 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5054 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
5055 src, dst, nt_errstr(status));
5056 goto fail;
5059 TALLOC_FREE(frame);
5060 return true;
5062 fail:
5064 if (posix_cli) {
5065 torture_close_connection(posix_cli);
5068 if (cli) {
5069 if (fnum != (uint64_t)-1) {
5070 cli_close(cli, fnum);
5072 cli_unlink(cli, src,
5073 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5074 cli_unlink(cli, dst,
5075 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5076 cli_rmdir(cli, dsrc);
5077 cli_rmdir(cli, ddst);
5078 cli_rmdir(cli, dname);
5080 torture_close_connection(cli);
5083 TALLOC_FREE(frame);
5084 return false;
5088 Test owner rights ACE.
5090 static bool run_owner_rights(int dummy)
5092 static struct cli_state *cli = NULL;
5093 const char *fname = "owner_rights.txt";
5094 uint16_t fnum = (uint16_t)-1;
5095 struct security_descriptor *sd = NULL;
5096 struct security_descriptor *newsd = NULL;
5097 NTSTATUS status;
5098 TALLOC_CTX *frame = NULL;
5100 frame = talloc_stackframe();
5101 printf("starting owner rights test\n");
5103 /* Windows connection. */
5104 if (!torture_open_connection(&cli, 0)) {
5105 goto fail;
5108 smbXcli_conn_set_sockopt(cli->conn, sockops);
5110 /* Start with a clean slate. */
5111 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5113 /* Create the test file. */
5114 /* Now try and open for read and write-dac. */
5115 status = cli_ntcreate(cli,
5116 fname,
5118 GENERIC_ALL_ACCESS,
5119 FILE_ATTRIBUTE_NORMAL,
5120 FILE_SHARE_READ|FILE_SHARE_WRITE|
5121 FILE_SHARE_DELETE,
5122 FILE_CREATE,
5125 &fnum,
5126 NULL);
5127 if (!NT_STATUS_IS_OK(status)) {
5128 printf("Create of %s - %s\n", fname, nt_errstr(status));
5129 goto fail;
5132 /* Get the original SD. */
5133 status = cli_query_secdesc(cli,
5134 fnum,
5135 frame,
5136 &sd);
5137 if (!NT_STATUS_IS_OK(status)) {
5138 printf("cli_query_secdesc failed for %s (%s)\n",
5139 fname, nt_errstr(status));
5140 goto fail;
5144 * Add an "owner-rights" ACE denying WRITE_DATA,
5145 * and an "owner-rights" ACE allowing READ_DATA.
5148 newsd = security_descriptor_dacl_create(frame,
5150 NULL,
5151 NULL,
5152 SID_OWNER_RIGHTS,
5153 SEC_ACE_TYPE_ACCESS_DENIED,
5154 FILE_WRITE_DATA,
5156 SID_OWNER_RIGHTS,
5157 SEC_ACE_TYPE_ACCESS_ALLOWED,
5158 FILE_READ_DATA,
5160 NULL);
5161 if (newsd == NULL) {
5162 goto fail;
5164 sd->dacl = security_acl_concatenate(frame,
5165 newsd->dacl,
5166 sd->dacl);
5167 if (sd->dacl == NULL) {
5168 goto fail;
5170 status = cli_set_secdesc(cli, fnum, sd);
5171 if (!NT_STATUS_IS_OK(status)) {
5172 printf("cli_set_secdesc failed for %s (%s)\n",
5173 fname, nt_errstr(status));
5174 goto fail;
5176 status = cli_close(cli, fnum);
5177 if (!NT_STATUS_IS_OK(status)) {
5178 printf("close failed for %s (%s)\n",
5179 fname, nt_errstr(status));
5180 goto fail;
5182 fnum = (uint16_t)-1;
5184 /* Try and open for FILE_WRITE_DATA */
5185 status = cli_ntcreate(cli,
5186 fname,
5188 FILE_WRITE_DATA,
5189 FILE_ATTRIBUTE_NORMAL,
5190 FILE_SHARE_READ|FILE_SHARE_WRITE|
5191 FILE_SHARE_DELETE,
5192 FILE_OPEN,
5195 &fnum,
5196 NULL);
5197 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5198 printf("Open of %s - %s\n", fname, nt_errstr(status));
5199 goto fail;
5202 /* Now try and open for FILE_READ_DATA */
5203 status = cli_ntcreate(cli,
5204 fname,
5206 FILE_READ_DATA,
5207 FILE_ATTRIBUTE_NORMAL,
5208 FILE_SHARE_READ|FILE_SHARE_WRITE|
5209 FILE_SHARE_DELETE,
5210 FILE_OPEN,
5213 &fnum,
5214 NULL);
5215 if (!NT_STATUS_IS_OK(status)) {
5216 printf("Open of %s - %s\n", fname, nt_errstr(status));
5217 goto fail;
5220 status = cli_close(cli, fnum);
5221 if (!NT_STATUS_IS_OK(status)) {
5222 printf("close failed for %s (%s)\n",
5223 fname, nt_errstr(status));
5224 goto fail;
5227 /* Restore clean slate. */
5228 TALLOC_FREE(sd);
5229 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5231 /* Create the test file. */
5232 status = cli_ntcreate(cli,
5233 fname,
5235 GENERIC_ALL_ACCESS,
5236 FILE_ATTRIBUTE_NORMAL,
5237 FILE_SHARE_READ|FILE_SHARE_WRITE|
5238 FILE_SHARE_DELETE,
5239 FILE_CREATE,
5242 &fnum,
5243 NULL);
5244 if (!NT_STATUS_IS_OK(status)) {
5245 printf("Create of %s - %s\n", fname, nt_errstr(status));
5246 goto fail;
5249 /* Get the original SD. */
5250 status = cli_query_secdesc(cli,
5251 fnum,
5252 frame,
5253 &sd);
5254 if (!NT_STATUS_IS_OK(status)) {
5255 printf("cli_query_secdesc failed for %s (%s)\n",
5256 fname, nt_errstr(status));
5257 goto fail;
5261 * Add an "owner-rights ACE denying WRITE_DATA,
5262 * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
5265 newsd = security_descriptor_dacl_create(frame,
5267 NULL,
5268 NULL,
5269 SID_OWNER_RIGHTS,
5270 SEC_ACE_TYPE_ACCESS_DENIED,
5271 FILE_WRITE_DATA,
5273 SID_OWNER_RIGHTS,
5274 SEC_ACE_TYPE_ACCESS_ALLOWED,
5275 FILE_READ_DATA|FILE_WRITE_DATA,
5277 NULL);
5278 if (newsd == NULL) {
5279 goto fail;
5281 sd->dacl = security_acl_concatenate(frame,
5282 newsd->dacl,
5283 sd->dacl);
5284 if (sd->dacl == NULL) {
5285 goto fail;
5287 status = cli_set_secdesc(cli, fnum, sd);
5288 if (!NT_STATUS_IS_OK(status)) {
5289 printf("cli_set_secdesc failed for %s (%s)\n",
5290 fname, nt_errstr(status));
5291 goto fail;
5293 status = cli_close(cli, fnum);
5294 if (!NT_STATUS_IS_OK(status)) {
5295 printf("close failed for %s (%s)\n",
5296 fname, nt_errstr(status));
5297 goto fail;
5299 fnum = (uint16_t)-1;
5301 /* Try and open for FILE_WRITE_DATA */
5302 status = cli_ntcreate(cli,
5303 fname,
5305 FILE_WRITE_DATA,
5306 FILE_ATTRIBUTE_NORMAL,
5307 FILE_SHARE_READ|FILE_SHARE_WRITE|
5308 FILE_SHARE_DELETE,
5309 FILE_OPEN,
5312 &fnum,
5313 NULL);
5314 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5315 printf("Open of %s - %s\n", fname, nt_errstr(status));
5316 goto fail;
5319 /* Now try and open for FILE_READ_DATA */
5320 status = cli_ntcreate(cli,
5321 fname,
5323 FILE_READ_DATA,
5324 FILE_ATTRIBUTE_NORMAL,
5325 FILE_SHARE_READ|FILE_SHARE_WRITE|
5326 FILE_SHARE_DELETE,
5327 FILE_OPEN,
5330 &fnum,
5331 NULL);
5332 if (!NT_STATUS_IS_OK(status)) {
5333 printf("Open of %s - %s\n", fname, nt_errstr(status));
5334 goto fail;
5337 status = cli_close(cli, fnum);
5338 if (!NT_STATUS_IS_OK(status)) {
5339 printf("close failed for %s (%s)\n",
5340 fname, nt_errstr(status));
5341 goto fail;
5344 /* Restore clean slate. */
5345 TALLOC_FREE(sd);
5346 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5349 /* Create the test file. */
5350 status = cli_ntcreate(cli,
5351 fname,
5353 GENERIC_ALL_ACCESS,
5354 FILE_ATTRIBUTE_NORMAL,
5355 FILE_SHARE_READ|FILE_SHARE_WRITE|
5356 FILE_SHARE_DELETE,
5357 FILE_CREATE,
5360 &fnum,
5361 NULL);
5362 if (!NT_STATUS_IS_OK(status)) {
5363 printf("Create of %s - %s\n", fname, nt_errstr(status));
5364 goto fail;
5367 /* Get the original SD. */
5368 status = cli_query_secdesc(cli,
5369 fnum,
5370 frame,
5371 &sd);
5372 if (!NT_STATUS_IS_OK(status)) {
5373 printf("cli_query_secdesc failed for %s (%s)\n",
5374 fname, nt_errstr(status));
5375 goto fail;
5379 * Add an "authenticated users" ACE allowing READ_DATA,
5380 * add an "owner-rights" denying READ_DATA,
5381 * and an "authenticated users" ACE allowing WRITE_DATA.
5384 newsd = security_descriptor_dacl_create(frame,
5386 NULL,
5387 NULL,
5388 SID_NT_AUTHENTICATED_USERS,
5389 SEC_ACE_TYPE_ACCESS_ALLOWED,
5390 FILE_READ_DATA,
5392 SID_OWNER_RIGHTS,
5393 SEC_ACE_TYPE_ACCESS_DENIED,
5394 FILE_READ_DATA,
5396 SID_NT_AUTHENTICATED_USERS,
5397 SEC_ACE_TYPE_ACCESS_ALLOWED,
5398 FILE_WRITE_DATA,
5400 NULL);
5401 if (newsd == NULL) {
5402 printf("newsd == NULL\n");
5403 goto fail;
5405 sd->dacl = security_acl_concatenate(frame,
5406 newsd->dacl,
5407 sd->dacl);
5408 if (sd->dacl == NULL) {
5409 printf("sd->dacl == NULL\n");
5410 goto fail;
5412 status = cli_set_secdesc(cli, fnum, sd);
5413 if (!NT_STATUS_IS_OK(status)) {
5414 printf("cli_set_secdesc failed for %s (%s)\n",
5415 fname, nt_errstr(status));
5416 goto fail;
5418 status = cli_close(cli, fnum);
5419 if (!NT_STATUS_IS_OK(status)) {
5420 printf("close failed for %s (%s)\n",
5421 fname, nt_errstr(status));
5422 goto fail;
5424 fnum = (uint16_t)-1;
5426 /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
5427 status = cli_ntcreate(cli,
5428 fname,
5430 FILE_READ_DATA|FILE_WRITE_DATA,
5431 FILE_ATTRIBUTE_NORMAL,
5432 FILE_SHARE_READ|FILE_SHARE_WRITE|
5433 FILE_SHARE_DELETE,
5434 FILE_OPEN,
5437 &fnum,
5438 NULL);
5439 if (!NT_STATUS_IS_OK(status)) {
5440 printf("Open of %s - %s\n", fname, nt_errstr(status));
5441 goto fail;
5444 status = cli_close(cli, fnum);
5445 if (!NT_STATUS_IS_OK(status)) {
5446 printf("close failed for %s (%s)\n",
5447 fname, nt_errstr(status));
5448 goto fail;
5451 cli_unlink(cli, fname,
5452 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5454 TALLOC_FREE(frame);
5455 return true;
5457 fail:
5459 if (cli) {
5460 if (fnum != (uint16_t)-1) {
5461 cli_close(cli, fnum);
5463 cli_unlink(cli, fname,
5464 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5465 torture_close_connection(cli);
5468 TALLOC_FREE(frame);
5469 return false;
5472 static bool run_pipe_number(int dummy)
5474 struct cli_state *cli1;
5475 const char *pipe_name = "\\SPOOLSS";
5476 uint16_t fnum;
5477 int num_pipes = 0;
5478 NTSTATUS status;
5480 printf("starting pipenumber test\n");
5481 if (!torture_open_connection(&cli1, 0)) {
5482 return False;
5485 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5486 while(1) {
5487 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
5488 FILE_ATTRIBUTE_NORMAL,
5489 FILE_SHARE_READ|FILE_SHARE_WRITE,
5490 FILE_OPEN_IF, 0, 0, &fnum, NULL);
5491 if (!NT_STATUS_IS_OK(status)) {
5492 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
5493 break;
5495 num_pipes++;
5496 printf("\r%6d", num_pipes);
5499 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
5500 torture_close_connection(cli1);
5501 return True;
5505 Test open mode returns on read-only files.
5507 static bool run_opentest(int dummy)
5509 static struct cli_state *cli1;
5510 static struct cli_state *cli2;
5511 const char *fname = "\\readonly.file";
5512 uint16_t fnum1, fnum2;
5513 char buf[20];
5514 off_t fsize;
5515 bool correct = True;
5516 char *tmp_path;
5517 NTSTATUS status;
5519 printf("starting open test\n");
5521 if (!torture_open_connection(&cli1, 0)) {
5522 return False;
5525 cli_setatr(cli1, fname, 0, 0);
5526 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5528 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5530 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
5531 if (!NT_STATUS_IS_OK(status)) {
5532 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5533 return False;
5536 status = cli_close(cli1, fnum1);
5537 if (!NT_STATUS_IS_OK(status)) {
5538 printf("close2 failed (%s)\n", nt_errstr(status));
5539 return False;
5542 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
5543 if (!NT_STATUS_IS_OK(status)) {
5544 printf("cli_setatr failed (%s)\n", nt_errstr(status));
5545 return False;
5548 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
5549 if (!NT_STATUS_IS_OK(status)) {
5550 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5551 return False;
5554 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
5555 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
5557 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
5558 NT_STATUS_ACCESS_DENIED)) {
5559 printf("correct error code ERRDOS/ERRnoaccess returned\n");
5562 printf("finished open test 1\n");
5564 cli_close(cli1, fnum1);
5566 /* Now try not readonly and ensure ERRbadshare is returned. */
5568 cli_setatr(cli1, fname, 0, 0);
5570 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
5571 if (!NT_STATUS_IS_OK(status)) {
5572 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5573 return False;
5576 /* This will fail - but the error should be ERRshare. */
5577 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
5579 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
5580 NT_STATUS_SHARING_VIOLATION)) {
5581 printf("correct error code ERRDOS/ERRbadshare returned\n");
5584 status = cli_close(cli1, fnum1);
5585 if (!NT_STATUS_IS_OK(status)) {
5586 printf("close2 failed (%s)\n", nt_errstr(status));
5587 return False;
5590 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5592 printf("finished open test 2\n");
5594 /* Test truncate open disposition on file opened for read. */
5595 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
5596 if (!NT_STATUS_IS_OK(status)) {
5597 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
5598 return False;
5601 /* write 20 bytes. */
5603 memset(buf, '\0', 20);
5605 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
5606 if (!NT_STATUS_IS_OK(status)) {
5607 printf("write failed (%s)\n", nt_errstr(status));
5608 correct = False;
5611 status = cli_close(cli1, fnum1);
5612 if (!NT_STATUS_IS_OK(status)) {
5613 printf("(3) close1 failed (%s)\n", nt_errstr(status));
5614 return False;
5617 /* Ensure size == 20. */
5618 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5619 if (!NT_STATUS_IS_OK(status)) {
5620 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5621 return False;
5624 if (fsize != 20) {
5625 printf("(3) file size != 20\n");
5626 return False;
5629 /* Now test if we can truncate a file opened for readonly. */
5630 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
5631 if (!NT_STATUS_IS_OK(status)) {
5632 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
5633 return False;
5636 status = cli_close(cli1, fnum1);
5637 if (!NT_STATUS_IS_OK(status)) {
5638 printf("close2 failed (%s)\n", nt_errstr(status));
5639 return False;
5642 /* Ensure size == 0. */
5643 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5644 if (!NT_STATUS_IS_OK(status)) {
5645 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5646 return False;
5649 if (fsize != 0) {
5650 printf("(3) file size != 0\n");
5651 return False;
5653 printf("finished open test 3\n");
5655 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5657 printf("Do ctemp tests\n");
5658 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
5659 if (!NT_STATUS_IS_OK(status)) {
5660 printf("ctemp failed (%s)\n", nt_errstr(status));
5661 return False;
5664 printf("ctemp gave path %s\n", tmp_path);
5665 status = cli_close(cli1, fnum1);
5666 if (!NT_STATUS_IS_OK(status)) {
5667 printf("close of temp failed (%s)\n", nt_errstr(status));
5670 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5671 if (!NT_STATUS_IS_OK(status)) {
5672 printf("unlink of temp failed (%s)\n", nt_errstr(status));
5675 /* Test the non-io opens... */
5677 if (!torture_open_connection(&cli2, 1)) {
5678 return False;
5681 cli_setatr(cli2, fname, 0, 0);
5682 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5684 smbXcli_conn_set_sockopt(cli2->conn, sockops);
5686 printf("TEST #1 testing 2 non-io opens (no delete)\n");
5687 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5688 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5689 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5690 if (!NT_STATUS_IS_OK(status)) {
5691 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5692 return False;
5695 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5696 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5697 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5698 if (!NT_STATUS_IS_OK(status)) {
5699 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5700 return False;
5703 status = cli_close(cli1, fnum1);
5704 if (!NT_STATUS_IS_OK(status)) {
5705 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5706 return False;
5709 status = cli_close(cli2, fnum2);
5710 if (!NT_STATUS_IS_OK(status)) {
5711 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5712 return False;
5715 printf("non-io open test #1 passed.\n");
5717 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5719 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5721 status = cli_ntcreate(cli1, fname, 0,
5722 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5723 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5724 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5725 if (!NT_STATUS_IS_OK(status)) {
5726 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5727 return False;
5730 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5731 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5732 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5733 if (!NT_STATUS_IS_OK(status)) {
5734 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5735 return False;
5738 status = cli_close(cli1, fnum1);
5739 if (!NT_STATUS_IS_OK(status)) {
5740 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5741 return False;
5744 status = cli_close(cli2, fnum2);
5745 if (!NT_STATUS_IS_OK(status)) {
5746 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5747 return False;
5750 printf("non-io open test #2 passed.\n");
5752 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5754 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5756 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5757 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5758 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5759 if (!NT_STATUS_IS_OK(status)) {
5760 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5761 return False;
5764 status = cli_ntcreate(cli2, fname, 0,
5765 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5766 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5767 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5768 if (!NT_STATUS_IS_OK(status)) {
5769 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5770 return False;
5773 status = cli_close(cli1, fnum1);
5774 if (!NT_STATUS_IS_OK(status)) {
5775 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5776 return False;
5779 status = cli_close(cli2, fnum2);
5780 if (!NT_STATUS_IS_OK(status)) {
5781 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5782 return False;
5785 printf("non-io open test #3 passed.\n");
5787 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5789 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5791 status = cli_ntcreate(cli1, fname, 0,
5792 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5793 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5794 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5795 if (!NT_STATUS_IS_OK(status)) {
5796 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5797 return False;
5800 status = cli_ntcreate(cli2, fname, 0,
5801 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5802 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5803 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5804 if (NT_STATUS_IS_OK(status)) {
5805 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5806 return False;
5809 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5811 status = cli_close(cli1, fnum1);
5812 if (!NT_STATUS_IS_OK(status)) {
5813 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5814 return False;
5817 printf("non-io open test #4 passed.\n");
5819 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5821 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5823 status = cli_ntcreate(cli1, fname, 0,
5824 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5825 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5826 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5827 if (!NT_STATUS_IS_OK(status)) {
5828 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5829 return False;
5832 status = cli_ntcreate(cli2, fname, 0,
5833 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5834 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5835 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5836 if (!NT_STATUS_IS_OK(status)) {
5837 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5838 return False;
5841 status = cli_close(cli1, fnum1);
5842 if (!NT_STATUS_IS_OK(status)) {
5843 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5844 return False;
5847 status = cli_close(cli2, fnum2);
5848 if (!NT_STATUS_IS_OK(status)) {
5849 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5850 return False;
5853 printf("non-io open test #5 passed.\n");
5855 printf("TEST #6 testing 1 non-io open, one io open\n");
5857 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5859 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5860 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5861 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5862 if (!NT_STATUS_IS_OK(status)) {
5863 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5864 return False;
5867 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5868 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5869 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5870 if (!NT_STATUS_IS_OK(status)) {
5871 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5872 return False;
5875 status = cli_close(cli1, fnum1);
5876 if (!NT_STATUS_IS_OK(status)) {
5877 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5878 return False;
5881 status = cli_close(cli2, fnum2);
5882 if (!NT_STATUS_IS_OK(status)) {
5883 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5884 return False;
5887 printf("non-io open test #6 passed.\n");
5889 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5891 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5893 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5894 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5895 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5896 if (!NT_STATUS_IS_OK(status)) {
5897 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5898 return False;
5901 status = cli_ntcreate(cli2, fname, 0,
5902 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5903 FILE_ATTRIBUTE_NORMAL,
5904 FILE_SHARE_READ|FILE_SHARE_DELETE,
5905 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5906 if (NT_STATUS_IS_OK(status)) {
5907 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5908 return False;
5911 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5913 status = cli_close(cli1, fnum1);
5914 if (!NT_STATUS_IS_OK(status)) {
5915 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5916 return False;
5919 printf("non-io open test #7 passed.\n");
5921 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5923 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5924 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5925 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5926 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5927 if (!NT_STATUS_IS_OK(status)) {
5928 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5929 correct = false;
5930 goto out;
5933 /* Write to ensure we have to update the file time. */
5934 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5935 NULL);
5936 if (!NT_STATUS_IS_OK(status)) {
5937 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5938 correct = false;
5939 goto out;
5942 status = cli_close(cli1, fnum1);
5943 if (!NT_STATUS_IS_OK(status)) {
5944 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5945 correct = false;
5948 out:
5950 if (!torture_close_connection(cli1)) {
5951 correct = False;
5953 if (!torture_close_connection(cli2)) {
5954 correct = False;
5957 return correct;
5960 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5962 uint16_t major, minor;
5963 uint32_t caplow, caphigh;
5964 NTSTATUS status;
5966 if (!SERVER_HAS_UNIX_CIFS(cli)) {
5967 printf("Server doesn't support UNIX CIFS extensions.\n");
5968 return NT_STATUS_NOT_SUPPORTED;
5971 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5972 &caphigh);
5973 if (!NT_STATUS_IS_OK(status)) {
5974 printf("Server didn't return UNIX CIFS extensions: %s\n",
5975 nt_errstr(status));
5976 return status;
5979 status = cli_set_unix_extensions_capabilities(cli, major, minor,
5980 caplow, caphigh);
5981 if (!NT_STATUS_IS_OK(status)) {
5982 printf("Server doesn't support setting UNIX CIFS extensions: "
5983 "%s.\n", nt_errstr(status));
5984 return status;
5987 return NT_STATUS_OK;
5991 Test POSIX open /mkdir calls.
5993 static bool run_simple_posix_open_test(int dummy)
5995 static struct cli_state *cli1;
5996 const char *fname = "posix:file";
5997 const char *hname = "posix:hlink";
5998 const char *sname = "posix:symlink";
5999 const char *dname = "posix:dir";
6000 char buf[10];
6001 char namebuf[11];
6002 uint16_t fnum1 = (uint16_t)-1;
6003 SMB_STRUCT_STAT sbuf;
6004 bool correct = false;
6005 NTSTATUS status;
6006 size_t nread;
6007 const char *fname_windows = "windows_file";
6008 uint16_t fnum2 = (uint16_t)-1;
6010 printf("Starting simple POSIX open test\n");
6012 if (!torture_open_connection(&cli1, 0)) {
6013 return false;
6016 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6018 status = torture_setup_unix_extensions(cli1);
6019 if (!NT_STATUS_IS_OK(status)) {
6020 return false;
6023 cli_setatr(cli1, fname, 0, 0);
6024 cli_posix_unlink(cli1, fname);
6025 cli_setatr(cli1, dname, 0, 0);
6026 cli_posix_rmdir(cli1, dname);
6027 cli_setatr(cli1, hname, 0, 0);
6028 cli_posix_unlink(cli1, hname);
6029 cli_setatr(cli1, sname, 0, 0);
6030 cli_posix_unlink(cli1, sname);
6031 cli_setatr(cli1, fname_windows, 0, 0);
6032 cli_posix_unlink(cli1, fname_windows);
6034 /* Create a directory. */
6035 status = cli_posix_mkdir(cli1, dname, 0777);
6036 if (!NT_STATUS_IS_OK(status)) {
6037 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
6038 goto out;
6041 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
6042 0600, &fnum1);
6043 if (!NT_STATUS_IS_OK(status)) {
6044 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6045 goto out;
6048 /* Test ftruncate - set file size. */
6049 status = cli_ftruncate(cli1, fnum1, 1000);
6050 if (!NT_STATUS_IS_OK(status)) {
6051 printf("ftruncate failed (%s)\n", nt_errstr(status));
6052 goto out;
6055 /* Ensure st_size == 1000 */
6056 status = cli_posix_stat(cli1, fname, &sbuf);
6057 if (!NT_STATUS_IS_OK(status)) {
6058 printf("stat failed (%s)\n", nt_errstr(status));
6059 goto out;
6062 if (sbuf.st_ex_size != 1000) {
6063 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
6064 goto out;
6067 /* Ensure st_mode == 0600 */
6068 if ((sbuf.st_ex_mode & 07777) != 0600) {
6069 printf("posix_open - bad permissions 0%o != 0600\n",
6070 (unsigned int)(sbuf.st_ex_mode & 07777));
6071 goto out;
6074 /* Test ftruncate - set file size back to zero. */
6075 status = cli_ftruncate(cli1, fnum1, 0);
6076 if (!NT_STATUS_IS_OK(status)) {
6077 printf("ftruncate failed (%s)\n", nt_errstr(status));
6078 goto out;
6081 status = cli_close(cli1, fnum1);
6082 if (!NT_STATUS_IS_OK(status)) {
6083 printf("close failed (%s)\n", nt_errstr(status));
6084 goto out;
6087 /* Now open the file again for read only. */
6088 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
6089 if (!NT_STATUS_IS_OK(status)) {
6090 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
6091 goto out;
6094 /* Now unlink while open. */
6095 status = cli_posix_unlink(cli1, fname);
6096 if (!NT_STATUS_IS_OK(status)) {
6097 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
6098 goto out;
6101 status = cli_close(cli1, fnum1);
6102 if (!NT_STATUS_IS_OK(status)) {
6103 printf("close(2) failed (%s)\n", nt_errstr(status));
6104 goto out;
6107 /* Ensure the file has gone. */
6108 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
6109 if (NT_STATUS_IS_OK(status)) {
6110 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
6111 goto out;
6114 /* Create again to test open with O_TRUNC. */
6115 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
6116 if (!NT_STATUS_IS_OK(status)) {
6117 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6118 goto out;
6121 /* Test ftruncate - set file size. */
6122 status = cli_ftruncate(cli1, fnum1, 1000);
6123 if (!NT_STATUS_IS_OK(status)) {
6124 printf("ftruncate failed (%s)\n", nt_errstr(status));
6125 goto out;
6128 /* Ensure st_size == 1000 */
6129 status = cli_posix_stat(cli1, fname, &sbuf);
6130 if (!NT_STATUS_IS_OK(status)) {
6131 printf("stat failed (%s)\n", nt_errstr(status));
6132 goto out;
6135 if (sbuf.st_ex_size != 1000) {
6136 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
6137 goto out;
6140 status = cli_close(cli1, fnum1);
6141 if (!NT_STATUS_IS_OK(status)) {
6142 printf("close(2) failed (%s)\n", nt_errstr(status));
6143 goto out;
6146 /* Re-open with O_TRUNC. */
6147 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
6148 if (!NT_STATUS_IS_OK(status)) {
6149 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6150 goto out;
6153 /* Ensure st_size == 0 */
6154 status = cli_posix_stat(cli1, fname, &sbuf);
6155 if (!NT_STATUS_IS_OK(status)) {
6156 printf("stat failed (%s)\n", nt_errstr(status));
6157 goto out;
6160 if (sbuf.st_ex_size != 0) {
6161 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
6162 goto out;
6165 status = cli_close(cli1, fnum1);
6166 if (!NT_STATUS_IS_OK(status)) {
6167 printf("close failed (%s)\n", nt_errstr(status));
6168 goto out;
6171 status = cli_posix_unlink(cli1, fname);
6172 if (!NT_STATUS_IS_OK(status)) {
6173 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
6174 goto out;
6177 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
6178 if (!NT_STATUS_IS_OK(status)) {
6179 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
6180 dname, nt_errstr(status));
6181 goto out;
6184 cli_close(cli1, fnum1);
6186 /* What happens when we try and POSIX open a directory for write ? */
6187 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
6188 if (NT_STATUS_IS_OK(status)) {
6189 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
6190 goto out;
6191 } else {
6192 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
6193 NT_STATUS_FILE_IS_A_DIRECTORY)) {
6194 goto out;
6198 /* Create the file. */
6199 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
6200 0600, &fnum1);
6201 if (!NT_STATUS_IS_OK(status)) {
6202 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6203 goto out;
6206 /* Write some data into it. */
6207 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
6208 NULL);
6209 if (!NT_STATUS_IS_OK(status)) {
6210 printf("cli_write failed: %s\n", nt_errstr(status));
6211 goto out;
6214 cli_close(cli1, fnum1);
6216 /* Now create a hardlink. */
6217 status = cli_posix_hardlink(cli1, fname, hname);
6218 if (!NT_STATUS_IS_OK(status)) {
6219 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
6220 goto out;
6223 /* Now create a symlink. */
6224 status = cli_posix_symlink(cli1, fname, sname);
6225 if (!NT_STATUS_IS_OK(status)) {
6226 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
6227 goto out;
6230 /* Open the hardlink for read. */
6231 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
6232 if (!NT_STATUS_IS_OK(status)) {
6233 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
6234 goto out;
6237 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
6238 if (!NT_STATUS_IS_OK(status)) {
6239 printf("POSIX read of %s failed (%s)\n", hname,
6240 nt_errstr(status));
6241 goto out;
6242 } else if (nread != 10) {
6243 printf("POSIX read of %s failed. Received %ld, expected %d\n",
6244 hname, (unsigned long)nread, 10);
6245 goto out;
6248 if (memcmp(buf, "TEST DATA\n", 10)) {
6249 printf("invalid data read from hardlink\n");
6250 goto out;
6253 /* Do a POSIX lock/unlock. */
6254 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
6255 if (!NT_STATUS_IS_OK(status)) {
6256 printf("POSIX lock failed %s\n", nt_errstr(status));
6257 goto out;
6260 /* Punch a hole in the locked area. */
6261 status = cli_posix_unlock(cli1, fnum1, 10, 80);
6262 if (!NT_STATUS_IS_OK(status)) {
6263 printf("POSIX unlock failed %s\n", nt_errstr(status));
6264 goto out;
6267 cli_close(cli1, fnum1);
6269 /* Open the symlink for read - this should fail. A POSIX
6270 client should not be doing opens on a symlink. */
6271 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
6272 if (NT_STATUS_IS_OK(status)) {
6273 printf("POSIX open of %s succeeded (should have failed)\n", sname);
6274 goto out;
6275 } else {
6276 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
6277 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
6278 printf("POSIX open of %s should have failed "
6279 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
6280 "failed with %s instead.\n",
6281 sname, nt_errstr(status));
6282 goto out;
6286 status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
6287 if (!NT_STATUS_IS_OK(status)) {
6288 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
6289 goto out;
6292 if (strcmp(namebuf, fname) != 0) {
6293 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
6294 sname, fname, namebuf);
6295 goto out;
6298 status = cli_posix_rmdir(cli1, dname);
6299 if (!NT_STATUS_IS_OK(status)) {
6300 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
6301 goto out;
6304 /* Check directory opens with a specific permission. */
6305 status = cli_posix_mkdir(cli1, dname, 0700);
6306 if (!NT_STATUS_IS_OK(status)) {
6307 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
6308 goto out;
6311 /* Ensure st_mode == 0700 */
6312 status = cli_posix_stat(cli1, dname, &sbuf);
6313 if (!NT_STATUS_IS_OK(status)) {
6314 printf("stat failed (%s)\n", nt_errstr(status));
6315 goto out;
6318 if ((sbuf.st_ex_mode & 07777) != 0700) {
6319 printf("posix_mkdir - bad permissions 0%o != 0700\n",
6320 (unsigned int)(sbuf.st_ex_mode & 07777));
6321 goto out;
6325 * Now create a Windows file, and attempt a POSIX unlink.
6326 * This should fail with a sharing violation but due to:
6328 * [Bug 9571] Unlink after open causes smbd to panic
6330 * ensure we've fixed the lock ordering violation.
6333 status = cli_ntcreate(cli1, fname_windows, 0,
6334 FILE_READ_DATA|FILE_WRITE_DATA, 0,
6335 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6336 FILE_CREATE,
6337 0x0, 0x0, &fnum2, NULL);
6338 if (!NT_STATUS_IS_OK(status)) {
6339 printf("Windows create of %s failed (%s)\n", fname_windows,
6340 nt_errstr(status));
6341 goto out;
6344 /* Now try posix_unlink. */
6345 status = cli_posix_unlink(cli1, fname_windows);
6346 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6347 printf("POSIX unlink of %s should fail "
6348 "with NT_STATUS_SHARING_VIOLATION "
6349 "got %s instead !\n",
6350 fname_windows,
6351 nt_errstr(status));
6352 goto out;
6355 cli_close(cli1, fnum2);
6357 printf("Simple POSIX open test passed\n");
6358 correct = true;
6360 out:
6362 if (fnum1 != (uint16_t)-1) {
6363 cli_close(cli1, fnum1);
6364 fnum1 = (uint16_t)-1;
6367 if (fnum2 != (uint16_t)-1) {
6368 cli_close(cli1, fnum2);
6369 fnum2 = (uint16_t)-1;
6372 cli_setatr(cli1, sname, 0, 0);
6373 cli_posix_unlink(cli1, sname);
6374 cli_setatr(cli1, hname, 0, 0);
6375 cli_posix_unlink(cli1, hname);
6376 cli_setatr(cli1, fname, 0, 0);
6377 cli_posix_unlink(cli1, fname);
6378 cli_setatr(cli1, dname, 0, 0);
6379 cli_posix_rmdir(cli1, dname);
6380 cli_setatr(cli1, fname_windows, 0, 0);
6381 cli_posix_unlink(cli1, fname_windows);
6383 if (!torture_close_connection(cli1)) {
6384 correct = false;
6387 return correct;
6391 Test POSIX and Windows ACLs are rejected on symlinks.
6393 static bool run_acl_symlink_test(int dummy)
6395 static struct cli_state *cli;
6396 const char *fname = "posix_file";
6397 const char *sname = "posix_symlink";
6398 uint16_t fnum = (uint16_t)-1;
6399 bool correct = false;
6400 NTSTATUS status;
6401 char *posix_acl = NULL;
6402 size_t posix_acl_len = 0;
6403 char *posix_acl_sym = NULL;
6404 size_t posix_acl_len_sym = 0;
6405 struct security_descriptor *sd = NULL;
6406 struct security_descriptor *sd_sym = NULL;
6407 TALLOC_CTX *frame = NULL;
6409 frame = talloc_stackframe();
6411 printf("Starting acl symlink test\n");
6413 if (!torture_open_connection(&cli, 0)) {
6414 TALLOC_FREE(frame);
6415 return false;
6418 smbXcli_conn_set_sockopt(cli->conn, sockops);
6420 status = torture_setup_unix_extensions(cli);
6421 if (!NT_STATUS_IS_OK(status)) {
6422 TALLOC_FREE(frame);
6423 return false;
6426 cli_setatr(cli, fname, 0, 0);
6427 cli_posix_unlink(cli, fname);
6428 cli_setatr(cli, sname, 0, 0);
6429 cli_posix_unlink(cli, sname);
6431 status = cli_ntcreate(cli,
6432 fname,
6434 READ_CONTROL_ACCESS,
6436 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6437 FILE_CREATE,
6438 0x0,
6439 0x0,
6440 &fnum,
6441 NULL);
6443 if (!NT_STATUS_IS_OK(status)) {
6444 printf("cli_ntcreate of %s failed (%s)\n",
6445 fname,
6446 nt_errstr(status));
6447 goto out;
6450 /* Get the Windows ACL on the file. */
6451 status = cli_query_secdesc(cli,
6452 fnum,
6453 frame,
6454 &sd);
6455 if (!NT_STATUS_IS_OK(status)) {
6456 printf("cli_query_secdesc failed (%s)\n",
6457 nt_errstr(status));
6458 goto out;
6461 /* Get the POSIX ACL on the file. */
6462 status = cli_posix_getacl(cli,
6463 fname,
6464 frame,
6465 &posix_acl_len,
6466 &posix_acl);
6468 if (!NT_STATUS_IS_OK(status)) {
6469 printf("cli_posix_getacl failed (%s)\n",
6470 nt_errstr(status));
6471 goto out;
6474 status = cli_close(cli, fnum);
6475 if (!NT_STATUS_IS_OK(status)) {
6476 printf("close failed (%s)\n", nt_errstr(status));
6477 goto out;
6479 fnum = (uint16_t)-1;
6481 /* Now create a symlink. */
6482 status = cli_posix_symlink(cli, fname, sname);
6483 if (!NT_STATUS_IS_OK(status)) {
6484 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
6485 sname,
6486 fname,
6487 nt_errstr(status));
6488 goto out;
6491 /* Open a handle on the symlink. */
6492 status = cli_ntcreate(cli,
6493 sname,
6495 READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
6497 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6498 FILE_OPEN,
6499 0x0,
6500 0x0,
6501 &fnum,
6502 NULL);
6504 if (!NT_STATUS_IS_OK(status)) {
6505 printf("cli_posix_open of %s failed (%s)\n",
6506 sname,
6507 nt_errstr(status));
6508 goto out;
6511 /* Get the Windows ACL on the symlink handle. Should fail */
6512 status = cli_query_secdesc(cli,
6513 fnum,
6514 frame,
6515 &sd_sym);
6517 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6518 printf("cli_query_secdesc on a symlink gave %s. "
6519 "Should be NT_STATUS_ACCESS_DENIED.\n",
6520 nt_errstr(status));
6521 goto out;
6524 /* Get the POSIX ACL on the symlink pathname. Should fail. */
6525 status = cli_posix_getacl(cli,
6526 sname,
6527 frame,
6528 &posix_acl_len_sym,
6529 &posix_acl_sym);
6531 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6532 printf("cli_posix_getacl on a symlink gave %s. "
6533 "Should be NT_STATUS_ACCESS_DENIED.\n",
6534 nt_errstr(status));
6535 goto out;
6538 /* Set the Windows ACL on the symlink handle. Should fail */
6539 status = cli_set_security_descriptor(cli,
6540 fnum,
6541 SECINFO_DACL,
6542 sd);
6544 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6545 printf("cli_query_secdesc on a symlink gave %s. "
6546 "Should be NT_STATUS_ACCESS_DENIED.\n",
6547 nt_errstr(status));
6548 goto out;
6551 /* Set the POSIX ACL on the symlink pathname. Should fail. */
6552 status = cli_posix_setacl(cli,
6553 sname,
6554 posix_acl,
6555 posix_acl_len);
6557 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6558 printf("cli_posix_getacl on a symlink gave %s. "
6559 "Should be NT_STATUS_ACCESS_DENIED.\n",
6560 nt_errstr(status));
6561 goto out;
6564 printf("ACL symlink test passed\n");
6565 correct = true;
6567 out:
6569 if (fnum != (uint16_t)-1) {
6570 cli_close(cli, fnum);
6571 fnum = (uint16_t)-1;
6574 cli_setatr(cli, sname, 0, 0);
6575 cli_posix_unlink(cli, sname);
6576 cli_setatr(cli, fname, 0, 0);
6577 cli_posix_unlink(cli, fname);
6579 if (!torture_close_connection(cli)) {
6580 correct = false;
6583 TALLOC_FREE(frame);
6584 return correct;
6588 Test POSIX can delete a file containing streams.
6590 static bool run_posix_stream_delete(int dummy)
6592 struct cli_state *cli1 = NULL;
6593 struct cli_state *cli2 = NULL;
6594 const char *fname = "streamfile";
6595 const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
6596 uint16_t fnum1 = (uint16_t)-1;
6597 bool correct = false;
6598 NTSTATUS status;
6599 TALLOC_CTX *frame = NULL;
6601 frame = talloc_stackframe();
6603 printf("Starting POSIX stream delete test\n");
6605 if (!torture_open_connection(&cli1, 0) ||
6606 !torture_open_connection(&cli2, 1)) {
6607 TALLOC_FREE(frame);
6608 return false;
6611 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6612 smbXcli_conn_set_sockopt(cli2->conn, sockops);
6614 status = torture_setup_unix_extensions(cli2);
6615 if (!NT_STATUS_IS_OK(status)) {
6616 goto out;
6619 cli_setatr(cli1, fname, 0, 0);
6620 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6622 /* Create the file. */
6623 status = cli_ntcreate(cli1,
6624 fname,
6626 READ_CONTROL_ACCESS,
6628 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6629 FILE_CREATE,
6630 0x0,
6631 0x0,
6632 &fnum1,
6633 NULL);
6635 if (!NT_STATUS_IS_OK(status)) {
6636 printf("cli_ntcreate of %s failed (%s)\n",
6637 fname,
6638 nt_errstr(status));
6639 goto out;
6642 status = cli_close(cli1, fnum1);
6643 if (!NT_STATUS_IS_OK(status)) {
6644 printf("cli_close of %s failed (%s)\n",
6645 fname,
6646 nt_errstr(status));
6647 goto out;
6649 fnum1 = (uint16_t)-1;
6651 /* Now create the stream. */
6652 status = cli_ntcreate(cli1,
6653 stream_fname,
6655 FILE_WRITE_DATA,
6657 FILE_SHARE_READ|FILE_SHARE_WRITE,
6658 FILE_CREATE,
6659 0x0,
6660 0x0,
6661 &fnum1,
6662 NULL);
6664 if (!NT_STATUS_IS_OK(status)) {
6665 printf("cli_ntcreate of %s failed (%s)\n",
6666 stream_fname,
6667 nt_errstr(status));
6668 goto out;
6671 /* Leave the stream handle open... */
6673 /* POSIX unlink should fail. */
6674 status = cli_posix_unlink(cli2, fname);
6675 if (NT_STATUS_IS_OK(status)) {
6676 printf("cli_posix_unlink of %s succeeded, should have failed\n",
6677 fname);
6678 goto out;
6681 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6682 printf("cli_posix_unlink of %s failed with (%s) "
6683 "should have been NT_STATUS_SHARING_VIOLATION\n",
6684 fname,
6685 nt_errstr(status));
6686 goto out;
6689 /* Close the stream handle. */
6690 status = cli_close(cli1, fnum1);
6691 if (!NT_STATUS_IS_OK(status)) {
6692 printf("cli_close of %s failed (%s)\n",
6693 stream_fname,
6694 nt_errstr(status));
6695 goto out;
6697 fnum1 = (uint16_t)-1;
6699 /* POSIX unlink after stream handle closed should succeed. */
6700 status = cli_posix_unlink(cli2, fname);
6701 if (!NT_STATUS_IS_OK(status)) {
6702 printf("cli_posix_unlink of %s failed (%s)\n",
6703 fname,
6704 nt_errstr(status));
6705 goto out;
6708 printf("POSIX stream delete test passed\n");
6709 correct = true;
6711 out:
6713 if (fnum1 != (uint16_t)-1) {
6714 cli_close(cli1, fnum1);
6715 fnum1 = (uint16_t)-1;
6718 cli_setatr(cli1, fname, 0, 0);
6719 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6721 if (!torture_close_connection(cli1)) {
6722 correct = false;
6724 if (!torture_close_connection(cli2)) {
6725 correct = false;
6728 TALLOC_FREE(frame);
6729 return correct;
6733 Test setting EA's are rejected on symlinks.
6735 static bool run_ea_symlink_test(int dummy)
6737 static struct cli_state *cli;
6738 const char *fname = "posix_file_ea";
6739 const char *sname = "posix_symlink_ea";
6740 const char *ea_name = "testea_name";
6741 const char *ea_value = "testea_value";
6742 uint16_t fnum = (uint16_t)-1;
6743 bool correct = false;
6744 NTSTATUS status;
6745 size_t i, num_eas;
6746 struct ea_struct *eas = NULL;
6747 TALLOC_CTX *frame = NULL;
6749 frame = talloc_stackframe();
6751 printf("Starting EA symlink test\n");
6753 if (!torture_open_connection(&cli, 0)) {
6754 TALLOC_FREE(frame);
6755 return false;
6758 smbXcli_conn_set_sockopt(cli->conn, sockops);
6760 status = torture_setup_unix_extensions(cli);
6761 if (!NT_STATUS_IS_OK(status)) {
6762 TALLOC_FREE(frame);
6763 return false;
6766 cli_setatr(cli, fname, 0, 0);
6767 cli_posix_unlink(cli, fname);
6768 cli_setatr(cli, sname, 0, 0);
6769 cli_posix_unlink(cli, sname);
6771 status = cli_ntcreate(cli,
6772 fname,
6774 READ_CONTROL_ACCESS,
6776 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6777 FILE_CREATE,
6778 0x0,
6779 0x0,
6780 &fnum,
6781 NULL);
6783 if (!NT_STATUS_IS_OK(status)) {
6784 printf("cli_ntcreate of %s failed (%s)\n",
6785 fname,
6786 nt_errstr(status));
6787 goto out;
6790 status = cli_close(cli, fnum);
6791 if (!NT_STATUS_IS_OK(status)) {
6792 printf("close failed (%s)\n",
6793 nt_errstr(status));
6794 goto out;
6796 fnum = (uint16_t)-1;
6798 /* Set an EA on the path. */
6799 status = cli_set_ea_path(cli,
6800 fname,
6801 ea_name,
6802 ea_value,
6803 strlen(ea_value)+1);
6805 if (!NT_STATUS_IS_OK(status)) {
6806 printf("cli_set_ea_path failed (%s)\n",
6807 nt_errstr(status));
6808 goto out;
6811 /* Now create a symlink. */
6812 status = cli_posix_symlink(cli, fname, sname);
6813 if (!NT_STATUS_IS_OK(status)) {
6814 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
6815 sname,
6816 fname,
6817 nt_errstr(status));
6818 goto out;
6821 /* Get the EA list on the path. Should return value set. */
6822 status = cli_get_ea_list_path(cli,
6823 fname,
6824 frame,
6825 &num_eas,
6826 &eas);
6828 if (!NT_STATUS_IS_OK(status)) {
6829 printf("cli_get_ea_list_path failed (%s)\n",
6830 nt_errstr(status));
6831 goto out;
6834 /* Ensure the EA we set is there. */
6835 for (i=0; i<num_eas; i++) {
6836 if (strcmp(eas[i].name, ea_name) == 0 &&
6837 eas[i].value.length == strlen(ea_value)+1 &&
6838 memcmp(eas[i].value.data,
6839 ea_value,
6840 eas[i].value.length) == 0) {
6841 break;
6845 if (i == num_eas) {
6846 printf("Didn't find EA on pathname %s\n",
6847 fname);
6848 goto out;
6851 num_eas = 0;
6852 TALLOC_FREE(eas);
6854 /* Get the EA list on the symlink. Should return empty list. */
6855 status = cli_get_ea_list_path(cli,
6856 sname,
6857 frame,
6858 &num_eas,
6859 &eas);
6861 if (!NT_STATUS_IS_OK(status)) {
6862 printf("cli_get_ea_list_path failed (%s)\n",
6863 nt_errstr(status));
6864 goto out;
6867 if (num_eas != 0) {
6868 printf("cli_get_ea_list_path failed (%s)\n",
6869 nt_errstr(status));
6870 goto out;
6873 /* Set an EA on the symlink. Should fail. */
6874 status = cli_set_ea_path(cli,
6875 sname,
6876 ea_name,
6877 ea_value,
6878 strlen(ea_value)+1);
6880 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6881 printf("cli_set_ea_path on a symlink gave %s. "
6882 "Should be NT_STATUS_ACCESS_DENIED.\n",
6883 nt_errstr(status));
6884 goto out;
6887 printf("EA symlink test passed\n");
6888 correct = true;
6890 out:
6892 if (fnum != (uint16_t)-1) {
6893 cli_close(cli, fnum);
6894 fnum = (uint16_t)-1;
6897 cli_setatr(cli, sname, 0, 0);
6898 cli_posix_unlink(cli, sname);
6899 cli_setatr(cli, fname, 0, 0);
6900 cli_posix_unlink(cli, fname);
6902 if (!torture_close_connection(cli)) {
6903 correct = false;
6906 TALLOC_FREE(frame);
6907 return correct;
6911 Test POSIX locks are OFD-locks.
6913 static bool run_posix_ofd_lock_test(int dummy)
6915 static struct cli_state *cli;
6916 const char *fname = "posix_file";
6917 uint16_t fnum1 = (uint16_t)-1;
6918 uint16_t fnum2 = (uint16_t)-1;
6919 bool correct = false;
6920 NTSTATUS status;
6921 TALLOC_CTX *frame = NULL;
6923 frame = talloc_stackframe();
6925 printf("Starting POSIX ofd-lock test\n");
6927 if (!torture_open_connection(&cli, 0)) {
6928 TALLOC_FREE(frame);
6929 return false;
6932 smbXcli_conn_set_sockopt(cli->conn, sockops);
6934 status = torture_setup_unix_extensions(cli);
6935 if (!NT_STATUS_IS_OK(status)) {
6936 TALLOC_FREE(frame);
6937 return false;
6940 cli_setatr(cli, fname, 0, 0);
6941 cli_posix_unlink(cli, fname);
6943 /* Open the file twice. */
6944 status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
6945 0600, &fnum1);
6946 if (!NT_STATUS_IS_OK(status)) {
6947 printf("First POSIX open of %s failed\n", fname);
6948 goto out;
6951 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
6952 if (!NT_STATUS_IS_OK(status)) {
6953 printf("First POSIX open of %s failed\n", fname);
6954 goto out;
6957 /* Set a 0-50 lock on fnum1. */
6958 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
6959 if (!NT_STATUS_IS_OK(status)) {
6960 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
6961 goto out;
6964 /* Set a 60-100 lock on fnum2. */
6965 status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
6966 if (!NT_STATUS_IS_OK(status)) {
6967 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
6968 goto out;
6971 /* close fnum1 - 0-50 lock should go away. */
6972 status = cli_close(cli, fnum1);
6973 if (!NT_STATUS_IS_OK(status)) {
6974 printf("close failed (%s)\n",
6975 nt_errstr(status));
6976 goto out;
6978 fnum1 = (uint16_t)-1;
6980 /* Change the lock context. */
6981 cli_setpid(cli, cli_getpid(cli) + 1);
6983 /* Re-open fnum1. */
6984 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
6985 if (!NT_STATUS_IS_OK(status)) {
6986 printf("Third POSIX open of %s failed\n", fname);
6987 goto out;
6990 /* 60-100 lock should still be there. */
6991 status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
6992 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
6993 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
6994 goto out;
6997 /* 0-50 lock should be gone. */
6998 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
6999 if (!NT_STATUS_IS_OK(status)) {
7000 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
7001 goto out;
7004 printf("POSIX OFD lock test passed\n");
7005 correct = true;
7007 out:
7009 if (fnum1 != (uint16_t)-1) {
7010 cli_close(cli, fnum1);
7011 fnum1 = (uint16_t)-1;
7013 if (fnum2 != (uint16_t)-1) {
7014 cli_close(cli, fnum2);
7015 fnum2 = (uint16_t)-1;
7018 cli_setatr(cli, fname, 0, 0);
7019 cli_posix_unlink(cli, fname);
7021 if (!torture_close_connection(cli)) {
7022 correct = false;
7025 TALLOC_FREE(frame);
7026 return correct;
7029 static uint32_t open_attrs_table[] = {
7030 FILE_ATTRIBUTE_NORMAL,
7031 FILE_ATTRIBUTE_ARCHIVE,
7032 FILE_ATTRIBUTE_READONLY,
7033 FILE_ATTRIBUTE_HIDDEN,
7034 FILE_ATTRIBUTE_SYSTEM,
7036 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
7037 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
7038 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
7039 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
7040 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
7041 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
7043 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
7044 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
7045 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
7046 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
7049 struct trunc_open_results {
7050 unsigned int num;
7051 uint32_t init_attr;
7052 uint32_t trunc_attr;
7053 uint32_t result_attr;
7056 static struct trunc_open_results attr_results[] = {
7057 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
7058 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
7059 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
7060 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
7061 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
7062 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
7063 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7064 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7065 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
7066 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7067 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7068 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
7069 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7070 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7071 { 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 },
7072 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7073 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7074 { 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 },
7075 { 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 },
7076 { 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 },
7077 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7078 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7079 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
7080 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7081 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7082 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
7085 static bool run_openattrtest(int dummy)
7087 static struct cli_state *cli1;
7088 const char *fname = "\\openattr.file";
7089 uint16_t fnum1;
7090 bool correct = True;
7091 uint16_t attr;
7092 unsigned int i, j, k, l;
7093 NTSTATUS status;
7095 printf("starting open attr test\n");
7097 if (!torture_open_connection(&cli1, 0)) {
7098 return False;
7101 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7103 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
7104 cli_setatr(cli1, fname, 0, 0);
7105 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7107 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
7108 open_attrs_table[i], FILE_SHARE_NONE,
7109 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7110 if (!NT_STATUS_IS_OK(status)) {
7111 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
7112 return False;
7115 status = cli_close(cli1, fnum1);
7116 if (!NT_STATUS_IS_OK(status)) {
7117 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
7118 return False;
7121 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
7122 status = cli_ntcreate(cli1, fname, 0,
7123 FILE_READ_DATA|FILE_WRITE_DATA,
7124 open_attrs_table[j],
7125 FILE_SHARE_NONE, FILE_OVERWRITE,
7126 0, 0, &fnum1, NULL);
7127 if (!NT_STATUS_IS_OK(status)) {
7128 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
7129 if (attr_results[l].num == k) {
7130 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
7131 k, open_attrs_table[i],
7132 open_attrs_table[j],
7133 fname, NT_STATUS_V(status), nt_errstr(status));
7134 correct = False;
7138 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7139 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
7140 k, open_attrs_table[i], open_attrs_table[j],
7141 nt_errstr(status));
7142 correct = False;
7144 #if 0
7145 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
7146 #endif
7147 k++;
7148 continue;
7151 status = cli_close(cli1, fnum1);
7152 if (!NT_STATUS_IS_OK(status)) {
7153 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
7154 return False;
7157 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
7158 if (!NT_STATUS_IS_OK(status)) {
7159 printf("getatr(2) failed (%s)\n", nt_errstr(status));
7160 return False;
7163 #if 0
7164 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
7165 k, open_attrs_table[i], open_attrs_table[j], attr );
7166 #endif
7168 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
7169 if (attr_results[l].num == k) {
7170 if (attr != attr_results[l].result_attr ||
7171 open_attrs_table[i] != attr_results[l].init_attr ||
7172 open_attrs_table[j] != attr_results[l].trunc_attr) {
7173 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
7174 open_attrs_table[i],
7175 open_attrs_table[j],
7176 (unsigned int)attr,
7177 attr_results[l].result_attr);
7178 correct = False;
7180 break;
7183 k++;
7187 cli_setatr(cli1, fname, 0, 0);
7188 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7190 printf("open attr test %s.\n", correct ? "passed" : "failed");
7192 if (!torture_close_connection(cli1)) {
7193 correct = False;
7195 return correct;
7198 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
7199 const char *name, void *state)
7201 int *matched = (int *)state;
7202 if (matched != NULL) {
7203 *matched += 1;
7205 return NT_STATUS_OK;
7209 test directory listing speed
7211 static bool run_dirtest(int dummy)
7213 int i;
7214 static struct cli_state *cli;
7215 uint16_t fnum;
7216 struct timeval core_start;
7217 bool correct = True;
7218 int matched;
7220 printf("starting directory test\n");
7222 if (!torture_open_connection(&cli, 0)) {
7223 return False;
7226 smbXcli_conn_set_sockopt(cli->conn, sockops);
7228 srandom(0);
7229 for (i=0;i<torture_numops;i++) {
7230 fstring fname;
7231 slprintf(fname, sizeof(fname), "\\%x", (int)random());
7232 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
7233 fprintf(stderr,"Failed to open %s\n", fname);
7234 return False;
7236 cli_close(cli, fnum);
7239 core_start = timeval_current();
7241 matched = 0;
7242 cli_list(cli, "a*.*", 0, list_fn, &matched);
7243 printf("Matched %d\n", matched);
7245 matched = 0;
7246 cli_list(cli, "b*.*", 0, list_fn, &matched);
7247 printf("Matched %d\n", matched);
7249 matched = 0;
7250 cli_list(cli, "xyzabc", 0, list_fn, &matched);
7251 printf("Matched %d\n", matched);
7253 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
7255 srandom(0);
7256 for (i=0;i<torture_numops;i++) {
7257 fstring fname;
7258 slprintf(fname, sizeof(fname), "\\%x", (int)random());
7259 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7262 if (!torture_close_connection(cli)) {
7263 correct = False;
7266 printf("finished dirtest\n");
7268 return correct;
7271 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
7272 void *state)
7274 struct cli_state *pcli = (struct cli_state *)state;
7275 fstring fname;
7276 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
7278 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7279 return NT_STATUS_OK;
7281 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7282 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
7283 printf("del_fn: failed to rmdir %s\n,", fname );
7284 } else {
7285 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
7286 printf("del_fn: failed to unlink %s\n,", fname );
7288 return NT_STATUS_OK;
7293 sees what IOCTLs are supported
7295 bool torture_ioctl_test(int dummy)
7297 static struct cli_state *cli;
7298 uint16_t device, function;
7299 uint16_t fnum;
7300 const char *fname = "\\ioctl.dat";
7301 DATA_BLOB blob;
7302 NTSTATUS status;
7304 if (!torture_open_connection(&cli, 0)) {
7305 return False;
7308 printf("starting ioctl test\n");
7310 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7312 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7313 if (!NT_STATUS_IS_OK(status)) {
7314 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7315 return False;
7318 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
7319 printf("ioctl device info: %s\n", nt_errstr(status));
7321 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
7322 printf("ioctl job info: %s\n", nt_errstr(status));
7324 for (device=0;device<0x100;device++) {
7325 printf("ioctl test with device = 0x%x\n", device);
7326 for (function=0;function<0x100;function++) {
7327 uint32_t code = (device<<16) | function;
7329 status = cli_raw_ioctl(cli, fnum, code, &blob);
7331 if (NT_STATUS_IS_OK(status)) {
7332 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
7333 (int)blob.length);
7334 data_blob_free(&blob);
7339 if (!torture_close_connection(cli)) {
7340 return False;
7343 return True;
7348 tries varients of chkpath
7350 bool torture_chkpath_test(int dummy)
7352 static struct cli_state *cli;
7353 uint16_t fnum;
7354 bool ret;
7355 NTSTATUS status;
7357 if (!torture_open_connection(&cli, 0)) {
7358 return False;
7361 printf("starting chkpath test\n");
7363 /* cleanup from an old run */
7364 cli_rmdir(cli, "\\chkpath.dir\\dir2");
7365 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7366 cli_rmdir(cli, "\\chkpath.dir");
7368 status = cli_mkdir(cli, "\\chkpath.dir");
7369 if (!NT_STATUS_IS_OK(status)) {
7370 printf("mkdir1 failed : %s\n", nt_errstr(status));
7371 return False;
7374 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
7375 if (!NT_STATUS_IS_OK(status)) {
7376 printf("mkdir2 failed : %s\n", nt_errstr(status));
7377 return False;
7380 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
7381 DENY_NONE, &fnum);
7382 if (!NT_STATUS_IS_OK(status)) {
7383 printf("open1 failed (%s)\n", nt_errstr(status));
7384 return False;
7386 cli_close(cli, fnum);
7388 status = cli_chkpath(cli, "\\chkpath.dir");
7389 if (!NT_STATUS_IS_OK(status)) {
7390 printf("chkpath1 failed: %s\n", nt_errstr(status));
7391 ret = False;
7394 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
7395 if (!NT_STATUS_IS_OK(status)) {
7396 printf("chkpath2 failed: %s\n", nt_errstr(status));
7397 ret = False;
7400 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
7401 if (!NT_STATUS_IS_OK(status)) {
7402 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
7403 NT_STATUS_NOT_A_DIRECTORY);
7404 } else {
7405 printf("* chkpath on a file should fail\n");
7406 ret = False;
7409 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
7410 if (!NT_STATUS_IS_OK(status)) {
7411 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
7412 NT_STATUS_OBJECT_NAME_NOT_FOUND);
7413 } else {
7414 printf("* chkpath on a non existent file should fail\n");
7415 ret = False;
7418 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
7419 if (!NT_STATUS_IS_OK(status)) {
7420 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
7421 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7422 } else {
7423 printf("* chkpath on a non existent component should fail\n");
7424 ret = False;
7427 cli_rmdir(cli, "\\chkpath.dir\\dir2");
7428 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7429 cli_rmdir(cli, "\\chkpath.dir");
7431 if (!torture_close_connection(cli)) {
7432 return False;
7435 return ret;
7438 static bool run_eatest(int dummy)
7440 static struct cli_state *cli;
7441 const char *fname = "\\eatest.txt";
7442 bool correct = True;
7443 uint16_t fnum;
7444 int i;
7445 size_t num_eas;
7446 struct ea_struct *ea_list = NULL;
7447 TALLOC_CTX *mem_ctx = talloc_init("eatest");
7448 NTSTATUS status;
7450 printf("starting eatest\n");
7452 if (!torture_open_connection(&cli, 0)) {
7453 talloc_destroy(mem_ctx);
7454 return False;
7457 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7459 status = cli_ntcreate(cli, fname, 0,
7460 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
7461 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
7462 0x4044, 0, &fnum, NULL);
7463 if (!NT_STATUS_IS_OK(status)) {
7464 printf("open failed - %s\n", nt_errstr(status));
7465 talloc_destroy(mem_ctx);
7466 return False;
7469 for (i = 0; i < 10; i++) {
7470 fstring ea_name, ea_val;
7472 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
7473 memset(ea_val, (char)i+1, i+1);
7474 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
7475 if (!NT_STATUS_IS_OK(status)) {
7476 printf("ea_set of name %s failed - %s\n", ea_name,
7477 nt_errstr(status));
7478 talloc_destroy(mem_ctx);
7479 return False;
7483 cli_close(cli, fnum);
7484 for (i = 0; i < 10; i++) {
7485 fstring ea_name, ea_val;
7487 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
7488 memset(ea_val, (char)i+1, i+1);
7489 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
7490 if (!NT_STATUS_IS_OK(status)) {
7491 printf("ea_set of name %s failed - %s\n", ea_name,
7492 nt_errstr(status));
7493 talloc_destroy(mem_ctx);
7494 return False;
7498 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
7499 if (!NT_STATUS_IS_OK(status)) {
7500 printf("ea_get list failed - %s\n", nt_errstr(status));
7501 correct = False;
7504 printf("num_eas = %d\n", (int)num_eas);
7506 if (num_eas != 20) {
7507 printf("Should be 20 EA's stored... failing.\n");
7508 correct = False;
7511 for (i = 0; i < num_eas; i++) {
7512 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
7513 dump_data(0, ea_list[i].value.data,
7514 ea_list[i].value.length);
7517 /* Setting EA's to zero length deletes them. Test this */
7518 printf("Now deleting all EA's - case indepenent....\n");
7520 #if 1
7521 cli_set_ea_path(cli, fname, "", "", 0);
7522 #else
7523 for (i = 0; i < 20; i++) {
7524 fstring ea_name;
7525 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
7526 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
7527 if (!NT_STATUS_IS_OK(status)) {
7528 printf("ea_set of name %s failed - %s\n", ea_name,
7529 nt_errstr(status));
7530 talloc_destroy(mem_ctx);
7531 return False;
7534 #endif
7536 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
7537 if (!NT_STATUS_IS_OK(status)) {
7538 printf("ea_get list failed - %s\n", nt_errstr(status));
7539 correct = False;
7542 printf("num_eas = %d\n", (int)num_eas);
7543 for (i = 0; i < num_eas; i++) {
7544 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
7545 dump_data(0, ea_list[i].value.data,
7546 ea_list[i].value.length);
7549 if (num_eas != 0) {
7550 printf("deleting EA's failed.\n");
7551 correct = False;
7554 /* Try and delete a non existent EA. */
7555 status = cli_set_ea_path(cli, fname, "foo", "", 0);
7556 if (!NT_STATUS_IS_OK(status)) {
7557 printf("deleting non-existent EA 'foo' should succeed. %s\n",
7558 nt_errstr(status));
7559 correct = False;
7562 talloc_destroy(mem_ctx);
7563 if (!torture_close_connection(cli)) {
7564 correct = False;
7567 return correct;
7570 static bool run_dirtest1(int dummy)
7572 int i;
7573 static struct cli_state *cli;
7574 uint16_t fnum;
7575 int num_seen;
7576 bool correct = True;
7578 printf("starting directory test\n");
7580 if (!torture_open_connection(&cli, 0)) {
7581 return False;
7584 smbXcli_conn_set_sockopt(cli->conn, sockops);
7586 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
7587 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
7588 cli_rmdir(cli, "\\LISTDIR");
7589 cli_mkdir(cli, "\\LISTDIR");
7591 /* Create 1000 files and 1000 directories. */
7592 for (i=0;i<1000;i++) {
7593 fstring fname;
7594 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
7595 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
7596 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
7597 0, 0, &fnum, NULL))) {
7598 fprintf(stderr,"Failed to open %s\n", fname);
7599 return False;
7601 cli_close(cli, fnum);
7603 for (i=0;i<1000;i++) {
7604 fstring fname;
7605 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
7606 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
7607 fprintf(stderr,"Failed to open %s\n", fname);
7608 return False;
7612 /* Now ensure that doing an old list sees both files and directories. */
7613 num_seen = 0;
7614 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7615 printf("num_seen = %d\n", num_seen );
7616 /* We should see 100 files + 1000 directories + . and .. */
7617 if (num_seen != 2002)
7618 correct = False;
7620 /* Ensure if we have the "must have" bits we only see the
7621 * relevent entries.
7623 num_seen = 0;
7624 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7625 printf("num_seen = %d\n", num_seen );
7626 if (num_seen != 1002)
7627 correct = False;
7629 num_seen = 0;
7630 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7631 printf("num_seen = %d\n", num_seen );
7632 if (num_seen != 1000)
7633 correct = False;
7635 /* Delete everything. */
7636 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
7637 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
7638 cli_rmdir(cli, "\\LISTDIR");
7640 #if 0
7641 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
7642 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
7643 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
7644 #endif
7646 if (!torture_close_connection(cli)) {
7647 correct = False;
7650 printf("finished dirtest1\n");
7652 return correct;
7655 static bool run_error_map_extract(int dummy) {
7657 static struct cli_state *c_dos;
7658 static struct cli_state *c_nt;
7659 NTSTATUS status;
7661 uint32_t error;
7663 uint32_t errnum;
7664 uint8_t errclass;
7666 NTSTATUS nt_status;
7668 fstring user;
7670 /* NT-Error connection */
7672 disable_spnego = true;
7673 if (!(c_nt = open_nbt_connection())) {
7674 disable_spnego = false;
7675 return False;
7677 disable_spnego = false;
7679 status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
7680 PROTOCOL_NT1);
7682 if (!NT_STATUS_IS_OK(status)) {
7683 printf("%s rejected the NT-error negprot (%s)\n", host,
7684 nt_errstr(status));
7685 cli_shutdown(c_nt);
7686 return False;
7689 status = cli_session_setup_anon(c_nt);
7690 if (!NT_STATUS_IS_OK(status)) {
7691 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
7692 return False;
7695 /* DOS-Error connection */
7697 disable_spnego = true;
7698 force_dos_errors = true;
7699 if (!(c_dos = open_nbt_connection())) {
7700 disable_spnego = false;
7701 force_dos_errors = false;
7702 return False;
7704 disable_spnego = false;
7705 force_dos_errors = false;
7707 status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
7708 PROTOCOL_NT1);
7709 if (!NT_STATUS_IS_OK(status)) {
7710 printf("%s rejected the DOS-error negprot (%s)\n", host,
7711 nt_errstr(status));
7712 cli_shutdown(c_dos);
7713 return False;
7716 status = cli_session_setup_anon(c_dos);
7717 if (!NT_STATUS_IS_OK(status)) {
7718 printf("%s rejected the DOS-error initial session setup (%s)\n",
7719 host, nt_errstr(status));
7720 return False;
7723 c_nt->map_dos_errors = false;
7724 c_dos->map_dos_errors = false;
7726 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
7727 struct cli_credentials *user_creds = NULL;
7729 fstr_sprintf(user, "%X", error);
7731 user_creds = cli_session_creds_init(talloc_tos(),
7732 user,
7733 workgroup,
7734 NULL, /* realm */
7735 password,
7736 false, /* use_kerberos */
7737 false, /* fallback_after_kerberos */
7738 false, /* use_ccache */
7739 false); /* password_is_nt_hash */
7740 if (user_creds == NULL) {
7741 printf("cli_session_creds_init(%s) failed\n", user);
7742 return false;
7745 status = cli_session_setup_creds(c_nt, user_creds);
7746 if (NT_STATUS_IS_OK(status)) {
7747 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
7750 /* Case #1: 32-bit NT errors */
7751 if (!NT_STATUS_IS_DOS(status)) {
7752 nt_status = status;
7753 } else {
7754 printf("/** Dos error on NT connection! (%s) */\n",
7755 nt_errstr(status));
7756 nt_status = NT_STATUS(0xc0000000);
7759 status = cli_session_setup_creds(c_dos, user_creds);
7760 if (NT_STATUS_IS_OK(status)) {
7761 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
7764 /* Case #1: 32-bit NT errors */
7765 if (NT_STATUS_IS_DOS(status)) {
7766 printf("/** NT error on DOS connection! (%s) */\n",
7767 nt_errstr(status));
7768 errnum = errclass = 0;
7769 } else {
7770 errclass = NT_STATUS_DOS_CLASS(status);
7771 errnum = NT_STATUS_DOS_CODE(status);
7774 if (NT_STATUS_V(nt_status) != error) {
7775 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
7776 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
7777 get_nt_error_c_code(talloc_tos(), nt_status));
7780 printf("\t{%s,\t%s,\t%s},\n",
7781 smb_dos_err_class(errclass),
7782 smb_dos_err_name(errclass, errnum),
7783 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
7785 TALLOC_FREE(user_creds);
7787 return True;
7790 static bool run_sesssetup_bench(int dummy)
7792 static struct cli_state *c;
7793 const char *fname = "\\file.dat";
7794 uint16_t fnum;
7795 NTSTATUS status;
7796 int i;
7798 if (!torture_open_connection(&c, 0)) {
7799 return false;
7802 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7803 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7804 FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
7805 if (!NT_STATUS_IS_OK(status)) {
7806 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7807 return false;
7810 for (i=0; i<torture_numops; i++) {
7811 status = cli_session_setup_creds(c, torture_creds);
7812 if (!NT_STATUS_IS_OK(status)) {
7813 d_printf("(%s) cli_session_setup_creds failed: %s\n",
7814 __location__, nt_errstr(status));
7815 return false;
7818 d_printf("\r%d ", (int)cli_state_get_uid(c));
7820 status = cli_ulogoff(c);
7821 if (!NT_STATUS_IS_OK(status)) {
7822 d_printf("(%s) cli_ulogoff failed: %s\n",
7823 __location__, nt_errstr(status));
7824 return false;
7828 return true;
7831 static bool subst_test(const char *str, const char *user, const char *domain,
7832 uid_t uid, gid_t gid, const char *expected)
7834 char *subst;
7835 bool result = true;
7837 subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
7839 if (strcmp(subst, expected) != 0) {
7840 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
7841 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
7842 expected);
7843 result = false;
7846 TALLOC_FREE(subst);
7847 return result;
7850 static void chain1_open_completion(struct tevent_req *req)
7852 uint16_t fnum;
7853 NTSTATUS status;
7854 status = cli_openx_recv(req, &fnum);
7855 TALLOC_FREE(req);
7857 d_printf("cli_openx_recv returned %s: %d\n",
7858 nt_errstr(status),
7859 NT_STATUS_IS_OK(status) ? fnum : -1);
7862 static void chain1_write_completion(struct tevent_req *req)
7864 size_t written;
7865 NTSTATUS status;
7866 status = cli_write_andx_recv(req, &written);
7867 TALLOC_FREE(req);
7869 d_printf("cli_write_andx_recv returned %s: %d\n",
7870 nt_errstr(status),
7871 NT_STATUS_IS_OK(status) ? (int)written : -1);
7874 static void chain1_close_completion(struct tevent_req *req)
7876 NTSTATUS status;
7877 bool *done = (bool *)tevent_req_callback_data_void(req);
7879 status = cli_close_recv(req);
7880 *done = true;
7882 TALLOC_FREE(req);
7884 d_printf("cli_close returned %s\n", nt_errstr(status));
7887 static bool run_chain1(int dummy)
7889 struct cli_state *cli1;
7890 struct tevent_context *evt = samba_tevent_context_init(NULL);
7891 struct tevent_req *reqs[3], *smbreqs[3];
7892 bool done = false;
7893 const char *str = "foobar";
7894 NTSTATUS status;
7896 printf("starting chain1 test\n");
7897 if (!torture_open_connection(&cli1, 0)) {
7898 return False;
7901 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7903 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, "\\test",
7904 O_CREAT|O_RDWR, 0, &smbreqs[0]);
7905 if (reqs[0] == NULL) return false;
7906 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
7909 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
7910 (const uint8_t *)str, 0, strlen(str)+1,
7911 smbreqs, 1, &smbreqs[1]);
7912 if (reqs[1] == NULL) return false;
7913 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
7915 reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
7916 if (reqs[2] == NULL) return false;
7917 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
7919 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
7920 if (!NT_STATUS_IS_OK(status)) {
7921 return false;
7924 while (!done) {
7925 tevent_loop_once(evt);
7928 torture_close_connection(cli1);
7929 return True;
7932 static void chain2_sesssetup_completion(struct tevent_req *req)
7934 NTSTATUS status;
7935 status = cli_session_setup_guest_recv(req);
7936 d_printf("sesssetup returned %s\n", nt_errstr(status));
7939 static void chain2_tcon_completion(struct tevent_req *req)
7941 bool *done = (bool *)tevent_req_callback_data_void(req);
7942 NTSTATUS status;
7943 status = cli_tcon_andx_recv(req);
7944 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
7945 *done = true;
7948 static bool run_chain2(int dummy)
7950 struct cli_state *cli1;
7951 struct tevent_context *evt = samba_tevent_context_init(NULL);
7952 struct tevent_req *reqs[2], *smbreqs[2];
7953 bool done = false;
7954 NTSTATUS status;
7956 printf("starting chain2 test\n");
7957 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
7958 port_to_use, SMB_SIGNING_DEFAULT, 0);
7959 if (!NT_STATUS_IS_OK(status)) {
7960 return False;
7963 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7965 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
7966 &smbreqs[0]);
7967 if (reqs[0] == NULL) return false;
7968 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
7970 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
7971 "?????", NULL, 0, &smbreqs[1]);
7972 if (reqs[1] == NULL) return false;
7973 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
7975 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
7976 if (!NT_STATUS_IS_OK(status)) {
7977 return false;
7980 while (!done) {
7981 tevent_loop_once(evt);
7984 torture_close_connection(cli1);
7985 return True;
7989 struct torture_createdel_state {
7990 struct tevent_context *ev;
7991 struct cli_state *cli;
7994 static void torture_createdel_created(struct tevent_req *subreq);
7995 static void torture_createdel_closed(struct tevent_req *subreq);
7997 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
7998 struct tevent_context *ev,
7999 struct cli_state *cli,
8000 const char *name)
8002 struct tevent_req *req, *subreq;
8003 struct torture_createdel_state *state;
8005 req = tevent_req_create(mem_ctx, &state,
8006 struct torture_createdel_state);
8007 if (req == NULL) {
8008 return NULL;
8010 state->ev = ev;
8011 state->cli = cli;
8013 subreq = cli_ntcreate_send(
8014 state, ev, cli, name, 0,
8015 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
8016 FILE_ATTRIBUTE_NORMAL,
8017 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8018 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
8020 if (tevent_req_nomem(subreq, req)) {
8021 return tevent_req_post(req, ev);
8023 tevent_req_set_callback(subreq, torture_createdel_created, req);
8024 return req;
8027 static void torture_createdel_created(struct tevent_req *subreq)
8029 struct tevent_req *req = tevent_req_callback_data(
8030 subreq, struct tevent_req);
8031 struct torture_createdel_state *state = tevent_req_data(
8032 req, struct torture_createdel_state);
8033 NTSTATUS status;
8034 uint16_t fnum;
8036 status = cli_ntcreate_recv(subreq, &fnum, NULL);
8037 TALLOC_FREE(subreq);
8038 if (tevent_req_nterror(req, status)) {
8039 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
8040 nt_errstr(status)));
8041 return;
8044 subreq = cli_close_send(state, state->ev, state->cli, fnum);
8045 if (tevent_req_nomem(subreq, req)) {
8046 return;
8048 tevent_req_set_callback(subreq, torture_createdel_closed, req);
8051 static void torture_createdel_closed(struct tevent_req *subreq)
8053 struct tevent_req *req = tevent_req_callback_data(
8054 subreq, struct tevent_req);
8055 NTSTATUS status;
8057 status = cli_close_recv(subreq);
8058 if (tevent_req_nterror(req, status)) {
8059 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
8060 return;
8062 tevent_req_done(req);
8065 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
8067 return tevent_req_simple_recv_ntstatus(req);
8070 struct torture_createdels_state {
8071 struct tevent_context *ev;
8072 struct cli_state *cli;
8073 const char *base_name;
8074 int sent;
8075 int received;
8076 int num_files;
8077 struct tevent_req **reqs;
8080 static void torture_createdels_done(struct tevent_req *subreq);
8082 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
8083 struct tevent_context *ev,
8084 struct cli_state *cli,
8085 const char *base_name,
8086 int num_parallel,
8087 int num_files)
8089 struct tevent_req *req;
8090 struct torture_createdels_state *state;
8091 int i;
8093 req = tevent_req_create(mem_ctx, &state,
8094 struct torture_createdels_state);
8095 if (req == NULL) {
8096 return NULL;
8098 state->ev = ev;
8099 state->cli = cli;
8100 state->base_name = talloc_strdup(state, base_name);
8101 if (tevent_req_nomem(state->base_name, req)) {
8102 return tevent_req_post(req, ev);
8104 state->num_files = MAX(num_parallel, num_files);
8105 state->sent = 0;
8106 state->received = 0;
8108 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
8109 if (tevent_req_nomem(state->reqs, req)) {
8110 return tevent_req_post(req, ev);
8113 for (i=0; i<num_parallel; i++) {
8114 char *name;
8116 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
8117 state->sent);
8118 if (tevent_req_nomem(name, req)) {
8119 return tevent_req_post(req, ev);
8121 state->reqs[i] = torture_createdel_send(
8122 state->reqs, state->ev, state->cli, name);
8123 if (tevent_req_nomem(state->reqs[i], req)) {
8124 return tevent_req_post(req, ev);
8126 name = talloc_move(state->reqs[i], &name);
8127 tevent_req_set_callback(state->reqs[i],
8128 torture_createdels_done, req);
8129 state->sent += 1;
8131 return req;
8134 static void torture_createdels_done(struct tevent_req *subreq)
8136 struct tevent_req *req = tevent_req_callback_data(
8137 subreq, struct tevent_req);
8138 struct torture_createdels_state *state = tevent_req_data(
8139 req, struct torture_createdels_state);
8140 size_t num_parallel = talloc_array_length(state->reqs);
8141 NTSTATUS status;
8142 char *name;
8143 int i;
8145 status = torture_createdel_recv(subreq);
8146 if (!NT_STATUS_IS_OK(status)){
8147 DEBUG(10, ("torture_createdel_recv returned %s\n",
8148 nt_errstr(status)));
8149 TALLOC_FREE(subreq);
8150 tevent_req_nterror(req, status);
8151 return;
8154 for (i=0; i<num_parallel; i++) {
8155 if (subreq == state->reqs[i]) {
8156 break;
8159 if (i == num_parallel) {
8160 DEBUG(10, ("received something we did not send\n"));
8161 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
8162 return;
8164 TALLOC_FREE(state->reqs[i]);
8166 if (state->sent >= state->num_files) {
8167 tevent_req_done(req);
8168 return;
8171 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
8172 state->sent);
8173 if (tevent_req_nomem(name, req)) {
8174 return;
8176 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
8177 state->cli, name);
8178 if (tevent_req_nomem(state->reqs[i], req)) {
8179 return;
8181 name = talloc_move(state->reqs[i], &name);
8182 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
8183 state->sent += 1;
8186 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
8188 return tevent_req_simple_recv_ntstatus(req);
8191 struct swallow_notify_state {
8192 struct tevent_context *ev;
8193 struct cli_state *cli;
8194 uint16_t fnum;
8195 uint32_t completion_filter;
8196 bool recursive;
8197 bool (*fn)(uint32_t action, const char *name, void *priv);
8198 void *priv;
8201 static void swallow_notify_done(struct tevent_req *subreq);
8203 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
8204 struct tevent_context *ev,
8205 struct cli_state *cli,
8206 uint16_t fnum,
8207 uint32_t completion_filter,
8208 bool recursive,
8209 bool (*fn)(uint32_t action,
8210 const char *name,
8211 void *priv),
8212 void *priv)
8214 struct tevent_req *req, *subreq;
8215 struct swallow_notify_state *state;
8217 req = tevent_req_create(mem_ctx, &state,
8218 struct swallow_notify_state);
8219 if (req == NULL) {
8220 return NULL;
8222 state->ev = ev;
8223 state->cli = cli;
8224 state->fnum = fnum;
8225 state->completion_filter = completion_filter;
8226 state->recursive = recursive;
8227 state->fn = fn;
8228 state->priv = priv;
8230 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
8231 0xffff, state->completion_filter,
8232 state->recursive);
8233 if (tevent_req_nomem(subreq, req)) {
8234 return tevent_req_post(req, ev);
8236 tevent_req_set_callback(subreq, swallow_notify_done, req);
8237 return req;
8240 static void swallow_notify_done(struct tevent_req *subreq)
8242 struct tevent_req *req = tevent_req_callback_data(
8243 subreq, struct tevent_req);
8244 struct swallow_notify_state *state = tevent_req_data(
8245 req, struct swallow_notify_state);
8246 NTSTATUS status;
8247 uint32_t i, num_changes;
8248 struct notify_change *changes;
8250 status = cli_notify_recv(subreq, state, &num_changes, &changes);
8251 TALLOC_FREE(subreq);
8252 if (!NT_STATUS_IS_OK(status)) {
8253 DEBUG(10, ("cli_notify_recv returned %s\n",
8254 nt_errstr(status)));
8255 tevent_req_nterror(req, status);
8256 return;
8259 for (i=0; i<num_changes; i++) {
8260 state->fn(changes[i].action, changes[i].name, state->priv);
8262 TALLOC_FREE(changes);
8264 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
8265 0xffff, state->completion_filter,
8266 state->recursive);
8267 if (tevent_req_nomem(subreq, req)) {
8268 return;
8270 tevent_req_set_callback(subreq, swallow_notify_done, req);
8273 static bool print_notifies(uint32_t action, const char *name, void *priv)
8275 if (DEBUGLEVEL > 5) {
8276 d_printf("%d %s\n", (int)action, name);
8278 return true;
8281 static void notify_bench_done(struct tevent_req *req)
8283 int *num_finished = (int *)tevent_req_callback_data_void(req);
8284 *num_finished += 1;
8287 static bool run_notify_bench(int dummy)
8289 const char *dname = "\\notify-bench";
8290 struct tevent_context *ev;
8291 NTSTATUS status;
8292 uint16_t dnum;
8293 struct tevent_req *req1;
8294 struct tevent_req *req2 = NULL;
8295 int i, num_unc_names;
8296 int num_finished = 0;
8298 printf("starting notify-bench test\n");
8300 if (use_multishare_conn) {
8301 char **unc_list;
8302 unc_list = file_lines_load(multishare_conn_fname,
8303 &num_unc_names, 0, NULL);
8304 if (!unc_list || num_unc_names <= 0) {
8305 d_printf("Failed to load unc names list from '%s'\n",
8306 multishare_conn_fname);
8307 return false;
8309 TALLOC_FREE(unc_list);
8310 } else {
8311 num_unc_names = 1;
8314 ev = samba_tevent_context_init(talloc_tos());
8315 if (ev == NULL) {
8316 d_printf("tevent_context_init failed\n");
8317 return false;
8320 for (i=0; i<num_unc_names; i++) {
8321 struct cli_state *cli;
8322 char *base_fname;
8324 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
8325 dname, i);
8326 if (base_fname == NULL) {
8327 return false;
8330 if (!torture_open_connection(&cli, i)) {
8331 return false;
8334 status = cli_ntcreate(cli, dname, 0,
8335 MAXIMUM_ALLOWED_ACCESS,
8336 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
8337 FILE_SHARE_DELETE,
8338 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
8339 &dnum, NULL);
8341 if (!NT_STATUS_IS_OK(status)) {
8342 d_printf("Could not create %s: %s\n", dname,
8343 nt_errstr(status));
8344 return false;
8347 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
8348 FILE_NOTIFY_CHANGE_FILE_NAME |
8349 FILE_NOTIFY_CHANGE_DIR_NAME |
8350 FILE_NOTIFY_CHANGE_ATTRIBUTES |
8351 FILE_NOTIFY_CHANGE_LAST_WRITE,
8352 false, print_notifies, NULL);
8353 if (req1 == NULL) {
8354 d_printf("Could not create notify request\n");
8355 return false;
8358 req2 = torture_createdels_send(talloc_tos(), ev, cli,
8359 base_fname, 10, torture_numops);
8360 if (req2 == NULL) {
8361 d_printf("Could not create createdels request\n");
8362 return false;
8364 TALLOC_FREE(base_fname);
8366 tevent_req_set_callback(req2, notify_bench_done,
8367 &num_finished);
8370 while (num_finished < num_unc_names) {
8371 int ret;
8372 ret = tevent_loop_once(ev);
8373 if (ret != 0) {
8374 d_printf("tevent_loop_once failed\n");
8375 return false;
8379 if (!tevent_req_poll(req2, ev)) {
8380 d_printf("tevent_req_poll failed\n");
8383 status = torture_createdels_recv(req2);
8384 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
8386 return true;
8389 static bool run_mangle1(int dummy)
8391 struct cli_state *cli;
8392 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
8393 uint16_t fnum;
8394 fstring alt_name;
8395 NTSTATUS status;
8396 time_t change_time, access_time, write_time;
8397 off_t size;
8398 uint16_t mode;
8400 printf("starting mangle1 test\n");
8401 if (!torture_open_connection(&cli, 0)) {
8402 return False;
8405 smbXcli_conn_set_sockopt(cli->conn, sockops);
8407 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8408 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8409 0, 0, &fnum, NULL);
8410 if (!NT_STATUS_IS_OK(status)) {
8411 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8412 return false;
8414 cli_close(cli, fnum);
8416 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
8417 if (!NT_STATUS_IS_OK(status)) {
8418 d_printf("cli_qpathinfo_alt_name failed: %s\n",
8419 nt_errstr(status));
8420 return false;
8422 d_printf("alt_name: %s\n", alt_name);
8424 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
8425 if (!NT_STATUS_IS_OK(status)) {
8426 d_printf("cli_openx(%s) failed: %s\n", alt_name,
8427 nt_errstr(status));
8428 return false;
8430 cli_close(cli, fnum);
8432 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
8433 &write_time, &size, &mode);
8434 if (!NT_STATUS_IS_OK(status)) {
8435 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
8436 nt_errstr(status));
8437 return false;
8440 return true;
8443 static NTSTATUS mangle_illegal_list_shortname_fn(const char *mntpoint,
8444 struct file_info *f,
8445 const char *mask,
8446 void *state)
8448 if (f->short_name == NULL) {
8449 return NT_STATUS_OK;
8452 if (strlen(f->short_name) == 0) {
8453 return NT_STATUS_OK;
8456 printf("unexpected shortname: %s\n", f->short_name);
8458 return NT_STATUS_OBJECT_NAME_INVALID;
8461 static NTSTATUS mangle_illegal_list_name_fn(const char *mntpoint,
8462 struct file_info *f,
8463 const char *mask,
8464 void *state)
8466 char *name = state;
8468 printf("name: %s\n", f->name);
8469 fstrcpy(name, f->name);
8470 return NT_STATUS_OK;
8473 static bool run_mangle_illegal(int dummy)
8475 struct cli_state *cli = NULL;
8476 struct cli_state *cli_posix = NULL;
8477 const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
8478 const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
8479 char *mangled_path = NULL;
8480 uint16_t fnum;
8481 fstring name;
8482 fstring alt_name;
8483 NTSTATUS status;
8485 printf("starting mangle-illegal test\n");
8487 if (!torture_open_connection(&cli, 0)) {
8488 return False;
8491 smbXcli_conn_set_sockopt(cli->conn, sockops);
8493 if (!torture_open_connection(&cli_posix, 0)) {
8494 return false;
8497 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
8499 status = torture_setup_unix_extensions(cli_posix);
8500 if (!NT_STATUS_IS_OK(status)) {
8501 return false;
8504 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
8505 status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
8506 if (!NT_STATUS_IS_OK(status)) {
8507 printf("mkdir1 failed : %s\n", nt_errstr(status));
8508 return False;
8512 * Create a file with illegal NTFS characters and test that we
8513 * get a usable mangled name
8516 cli_setatr(cli_posix, illegal_fname, 0, 0);
8517 cli_posix_unlink(cli_posix, illegal_fname);
8519 status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
8520 0600, &fnum);
8521 if (!NT_STATUS_IS_OK(status)) {
8522 printf("POSIX create of %s failed (%s)\n",
8523 illegal_fname, nt_errstr(status));
8524 return false;
8527 status = cli_close(cli_posix, fnum);
8528 if (!NT_STATUS_IS_OK(status)) {
8529 printf("close failed (%s)\n", nt_errstr(status));
8530 return false;
8533 status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
8534 if (!NT_STATUS_IS_OK(status)) {
8535 d_printf("cli_list failed: %s\n", nt_errstr(status));
8536 return false;
8539 mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
8540 if (mangled_path == NULL) {
8541 return false;
8544 status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
8545 if (!NT_STATUS_IS_OK(status)) {
8546 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
8547 TALLOC_FREE(mangled_path);
8548 return false;
8550 TALLOC_FREE(mangled_path);
8551 cli_close(cli, fnum);
8553 cli_setatr(cli_posix, illegal_fname, 0, 0);
8554 cli_posix_unlink(cli_posix, illegal_fname);
8557 * Create a file with a long name and check that we got *no* short name.
8560 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8561 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8562 0, 0, &fnum, NULL);
8563 if (!NT_STATUS_IS_OK(status)) {
8564 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8565 return false;
8567 cli_close(cli, fnum);
8569 status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
8570 if (!NT_STATUS_IS_OK(status)) {
8571 d_printf("cli_list failed\n");
8572 return false;
8575 cli_unlink(cli, fname, 0);
8576 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
8578 if (!torture_close_connection(cli_posix)) {
8579 return false;
8582 if (!torture_close_connection(cli)) {
8583 return false;
8586 return true;
8589 static size_t null_source(uint8_t *buf, size_t n, void *priv)
8591 size_t *to_pull = (size_t *)priv;
8592 size_t thistime = *to_pull;
8594 thistime = MIN(thistime, n);
8595 if (thistime == 0) {
8596 return 0;
8599 memset(buf, 0, thistime);
8600 *to_pull -= thistime;
8601 return thistime;
8604 static bool run_windows_write(int dummy)
8606 struct cli_state *cli1;
8607 uint16_t fnum;
8608 int i;
8609 bool ret = false;
8610 const char *fname = "\\writetest.txt";
8611 struct timeval start_time;
8612 double seconds;
8613 double kbytes;
8614 NTSTATUS status;
8616 printf("starting windows_write test\n");
8617 if (!torture_open_connection(&cli1, 0)) {
8618 return False;
8621 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
8622 if (!NT_STATUS_IS_OK(status)) {
8623 printf("open failed (%s)\n", nt_errstr(status));
8624 return False;
8627 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8629 start_time = timeval_current();
8631 for (i=0; i<torture_numops; i++) {
8632 uint8_t c = 0;
8633 off_t start = i * torture_blocksize;
8634 size_t to_pull = torture_blocksize - 1;
8636 status = cli_writeall(cli1, fnum, 0, &c,
8637 start + torture_blocksize - 1, 1, NULL);
8638 if (!NT_STATUS_IS_OK(status)) {
8639 printf("cli_write failed: %s\n", nt_errstr(status));
8640 goto fail;
8643 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
8644 null_source, &to_pull);
8645 if (!NT_STATUS_IS_OK(status)) {
8646 printf("cli_push returned: %s\n", nt_errstr(status));
8647 goto fail;
8651 seconds = timeval_elapsed(&start_time);
8652 kbytes = (double)torture_blocksize * torture_numops;
8653 kbytes /= 1024;
8655 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
8656 (double)seconds, (int)(kbytes/seconds));
8658 ret = true;
8659 fail:
8660 cli_close(cli1, fnum);
8661 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8662 torture_close_connection(cli1);
8663 return ret;
8666 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
8668 size_t max_pdu = 0x1FFFF;
8670 if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
8671 max_pdu = 0xFFFFFF;
8674 if (smb1cli_conn_signing_is_active(cli->conn)) {
8675 max_pdu = 0x1FFFF;
8678 if (smb1cli_conn_encryption_on(cli->conn)) {
8679 max_pdu = CLI_BUFFER_SIZE;
8682 if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
8683 len_requested &= 0xFFFF;
8686 return MIN(len_requested,
8687 max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
8690 static bool check_read_call(struct cli_state *cli,
8691 uint16_t fnum,
8692 uint8_t *buf,
8693 size_t len_requested)
8695 NTSTATUS status;
8696 struct tevent_req *subreq = NULL;
8697 ssize_t len_read = 0;
8698 size_t len_expected = 0;
8699 struct tevent_context *ev = NULL;
8701 ev = samba_tevent_context_init(talloc_tos());
8702 if (ev == NULL) {
8703 return false;
8706 subreq = cli_read_andx_send(talloc_tos(),
8708 cli,
8709 fnum,
8711 len_requested);
8713 if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
8714 return false;
8717 status = cli_read_andx_recv(subreq, &len_read, &buf);
8718 if (!NT_STATUS_IS_OK(status)) {
8719 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
8720 return false;
8723 TALLOC_FREE(subreq);
8724 TALLOC_FREE(ev);
8726 len_expected = calc_expected_return(cli, len_requested);
8728 if (len_expected > 0x10000 && len_read == 0x10000) {
8729 /* Windows servers only return a max of 0x10000,
8730 doesn't matter if you set CAP_LARGE_READX in
8731 the client sessionsetupX call or not. */
8732 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
8733 (unsigned int)len_requested);
8734 } else if (len_read != len_expected) {
8735 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
8736 (unsigned int)len_requested,
8737 (unsigned int)len_read,
8738 (unsigned int)len_expected);
8739 return false;
8740 } else {
8741 d_printf("Correct read reply.\n");
8744 return true;
8747 /* Test large readX variants. */
8748 static bool large_readx_tests(struct cli_state *cli,
8749 uint16_t fnum,
8750 uint8_t *buf)
8752 /* A read of 0xFFFF0001 should *always* return 1 byte. */
8753 if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
8754 return false;
8756 /* A read of 0x10000 should return 0x10000 bytes. */
8757 if (check_read_call(cli, fnum, buf, 0x10000) == false) {
8758 return false;
8760 /* A read of 0x10000 should return 0x10001 bytes. */
8761 if (check_read_call(cli, fnum, buf, 0x10001) == false) {
8762 return false;
8764 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
8765 the requested number of bytes. */
8766 if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
8767 return false;
8769 /* A read of 1MB should return 1MB bytes (on Samba). */
8770 if (check_read_call(cli, fnum, buf, 0x100000) == false) {
8771 return false;
8774 if (check_read_call(cli, fnum, buf, 0x20001) == false) {
8775 return false;
8777 if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
8778 return false;
8780 if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
8781 return false;
8783 return true;
8786 static bool run_large_readx(int dummy)
8788 uint8_t *buf = NULL;
8789 struct cli_state *cli1 = NULL;
8790 struct cli_state *cli2 = NULL;
8791 bool correct = false;
8792 const char *fname = "\\large_readx.dat";
8793 NTSTATUS status;
8794 uint16_t fnum1 = UINT16_MAX;
8795 uint32_t normal_caps = 0;
8796 size_t file_size = 20*1024*1024;
8797 TALLOC_CTX *frame = talloc_stackframe();
8798 size_t i;
8799 struct {
8800 const char *name;
8801 enum smb_signing_setting signing_setting;
8802 enum protocol_types protocol;
8803 } runs[] = {
8805 .name = "NT1",
8806 .signing_setting = SMB_SIGNING_IF_REQUIRED,
8807 .protocol = PROTOCOL_NT1,
8809 .name = "NT1 - SIGNING_REQUIRED",
8810 .signing_setting = SMB_SIGNING_REQUIRED,
8811 .protocol = PROTOCOL_NT1,
8815 printf("starting large_readx test\n");
8817 if (!torture_open_connection(&cli1, 0)) {
8818 goto out;
8821 normal_caps = smb1cli_conn_capabilities(cli1->conn);
8823 if (!(normal_caps & CAP_LARGE_READX)) {
8824 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
8825 (unsigned int)normal_caps);
8826 goto out;
8829 /* Create a file of size 4MB. */
8830 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
8831 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8832 0, 0, &fnum1, NULL);
8834 if (!NT_STATUS_IS_OK(status)) {
8835 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8836 goto out;
8839 /* Write file_size bytes. */
8840 buf = talloc_zero_array(frame, uint8_t, file_size);
8841 if (buf == NULL) {
8842 goto out;
8845 status = cli_writeall(cli1,
8846 fnum1,
8848 buf,
8850 file_size,
8851 NULL);
8852 if (!NT_STATUS_IS_OK(status)) {
8853 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
8854 goto out;
8857 status = cli_close(cli1, fnum1);
8858 if (!NT_STATUS_IS_OK(status)) {
8859 d_printf("cli_close failed: %s\n", nt_errstr(status));
8860 goto out;
8863 fnum1 = UINT16_MAX;
8865 for (i=0; i < ARRAY_SIZE(runs); i++) {
8866 enum smb_signing_setting saved_signing_setting = signing_state;
8867 uint16_t fnum2 = -1;
8869 if (do_encrypt &&
8870 (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
8872 d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
8873 continue;
8876 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
8878 signing_state = runs[i].signing_setting;
8879 cli2 = open_nbt_connection();
8880 signing_state = saved_signing_setting;
8881 if (cli2 == NULL) {
8882 goto out;
8885 status = smbXcli_negprot(cli2->conn,
8886 cli2->timeout,
8887 runs[i].protocol,
8888 runs[i].protocol);
8889 if (!NT_STATUS_IS_OK(status)) {
8890 goto out;
8893 status = cli_session_setup_creds(cli2, torture_creds);
8894 if (!NT_STATUS_IS_OK(status)) {
8895 goto out;
8898 status = cli_tree_connect(cli2,
8899 share,
8900 "?????",
8901 password);
8902 if (!NT_STATUS_IS_OK(status)) {
8903 goto out;
8906 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
8908 normal_caps = smb1cli_conn_capabilities(cli2->conn);
8910 if (!(normal_caps & CAP_LARGE_READX)) {
8911 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
8912 (unsigned int)normal_caps);
8913 goto out;
8916 if (do_encrypt) {
8917 if (force_cli_encryption(cli2, share) == false) {
8918 goto out;
8920 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
8921 uint16_t major, minor;
8922 uint32_t caplow, caphigh;
8924 status = cli_unix_extensions_version(cli2,
8925 &major, &minor,
8926 &caplow, &caphigh);
8927 if (!NT_STATUS_IS_OK(status)) {
8928 goto out;
8932 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
8933 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
8934 0, 0, &fnum2, NULL);
8935 if (!NT_STATUS_IS_OK(status)) {
8936 d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
8937 goto out;
8940 /* All reads must return less than file_size bytes. */
8941 if (!large_readx_tests(cli2, fnum2, buf)) {
8942 goto out;
8945 status = cli_close(cli2, fnum2);
8946 if (!NT_STATUS_IS_OK(status)) {
8947 d_printf("cli_close failed: %s\n", nt_errstr(status));
8948 goto out;
8950 fnum2 = -1;
8952 if (!torture_close_connection(cli2)) {
8953 goto out;
8955 cli2 = NULL;
8958 correct = true;
8959 printf("Success on large_readx test\n");
8961 out:
8963 if (cli2) {
8964 if (!torture_close_connection(cli2)) {
8965 correct = false;
8969 if (cli1) {
8970 if (fnum1 != UINT16_MAX) {
8971 status = cli_close(cli1, fnum1);
8972 if (!NT_STATUS_IS_OK(status)) {
8973 d_printf("cli_close failed: %s\n", nt_errstr(status));
8975 fnum1 = UINT16_MAX;
8978 status = cli_unlink(cli1, fname,
8979 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8980 if (!NT_STATUS_IS_OK(status)) {
8981 printf("unlink failed (%s)\n", nt_errstr(status));
8984 if (!torture_close_connection(cli1)) {
8985 correct = false;
8989 TALLOC_FREE(frame);
8991 printf("finished large_readx test\n");
8992 return correct;
8995 static bool run_cli_echo(int dummy)
8997 struct cli_state *cli;
8998 NTSTATUS status;
9000 printf("starting cli_echo test\n");
9001 if (!torture_open_connection(&cli, 0)) {
9002 return false;
9004 smbXcli_conn_set_sockopt(cli->conn, sockops);
9006 status = cli_echo(cli, 5, data_blob_const("hello", 5));
9008 d_printf("cli_echo returned %s\n", nt_errstr(status));
9010 torture_close_connection(cli);
9011 return NT_STATUS_IS_OK(status);
9014 static bool run_uid_regression_test(int dummy)
9016 static struct cli_state *cli;
9017 int16_t old_vuid;
9018 int16_t old_cnum;
9019 bool correct = True;
9020 NTSTATUS status;
9022 printf("starting uid regression test\n");
9024 if (!torture_open_connection(&cli, 0)) {
9025 return False;
9028 smbXcli_conn_set_sockopt(cli->conn, sockops);
9030 /* Ok - now save then logoff our current user. */
9031 old_vuid = cli_state_get_uid(cli);
9033 status = cli_ulogoff(cli);
9034 if (!NT_STATUS_IS_OK(status)) {
9035 d_printf("(%s) cli_ulogoff failed: %s\n",
9036 __location__, nt_errstr(status));
9037 correct = false;
9038 goto out;
9041 cli_state_set_uid(cli, old_vuid);
9043 /* Try an operation. */
9044 status = cli_mkdir(cli, "\\uid_reg_test");
9045 if (NT_STATUS_IS_OK(status)) {
9046 d_printf("(%s) cli_mkdir succeeded\n",
9047 __location__);
9048 correct = false;
9049 goto out;
9050 } else {
9051 /* Should be bad uid. */
9052 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
9053 NT_STATUS_USER_SESSION_DELETED)) {
9054 correct = false;
9055 goto out;
9059 old_cnum = cli_state_get_tid(cli);
9061 /* Now try a SMBtdis with the invald vuid set to zero. */
9062 cli_state_set_uid(cli, 0);
9064 /* This should succeed. */
9065 status = cli_tdis(cli);
9067 if (NT_STATUS_IS_OK(status)) {
9068 d_printf("First tdis with invalid vuid should succeed.\n");
9069 } else {
9070 d_printf("First tdis failed (%s)\n", nt_errstr(status));
9071 correct = false;
9072 goto out;
9075 cli_state_set_uid(cli, old_vuid);
9076 cli_state_set_tid(cli, old_cnum);
9078 /* This should fail. */
9079 status = cli_tdis(cli);
9080 if (NT_STATUS_IS_OK(status)) {
9081 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
9082 correct = false;
9083 goto out;
9084 } else {
9085 /* Should be bad tid. */
9086 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
9087 NT_STATUS_NETWORK_NAME_DELETED)) {
9088 correct = false;
9089 goto out;
9093 cli_rmdir(cli, "\\uid_reg_test");
9095 out:
9097 cli_shutdown(cli);
9098 return correct;
9102 static const char *illegal_chars = "*\\/?<>|\":";
9103 static char force_shortname_chars[] = " +,.[];=\177";
9105 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
9106 const char *mask, void *state)
9108 struct cli_state *pcli = (struct cli_state *)state;
9109 fstring fname;
9110 NTSTATUS status = NT_STATUS_OK;
9112 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
9114 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9115 return NT_STATUS_OK;
9117 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
9118 status = cli_rmdir(pcli, fname);
9119 if (!NT_STATUS_IS_OK(status)) {
9120 printf("del_fn: failed to rmdir %s\n,", fname );
9122 } else {
9123 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9124 if (!NT_STATUS_IS_OK(status)) {
9125 printf("del_fn: failed to unlink %s\n,", fname );
9128 return status;
9131 struct sn_state {
9132 int matched;
9133 int i;
9134 bool val;
9137 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
9138 const char *name, void *state)
9140 struct sn_state *s = (struct sn_state *)state;
9141 int i = s->i;
9143 #if 0
9144 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
9145 i, finfo->name, finfo->short_name);
9146 #endif
9148 if (strchr(force_shortname_chars, i)) {
9149 if (!finfo->short_name) {
9150 /* Shortname not created when it should be. */
9151 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
9152 __location__, finfo->name, i);
9153 s->val = true;
9155 } else if (finfo->short_name){
9156 /* Shortname created when it should not be. */
9157 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
9158 __location__, finfo->short_name, finfo->name);
9159 s->val = true;
9161 s->matched += 1;
9162 return NT_STATUS_OK;
9165 static bool run_shortname_test(int dummy)
9167 static struct cli_state *cli;
9168 bool correct = True;
9169 int i;
9170 struct sn_state s;
9171 char fname[40];
9172 NTSTATUS status;
9174 printf("starting shortname test\n");
9176 if (!torture_open_connection(&cli, 0)) {
9177 return False;
9180 smbXcli_conn_set_sockopt(cli->conn, sockops);
9182 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
9183 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
9184 cli_rmdir(cli, "\\shortname");
9186 status = cli_mkdir(cli, "\\shortname");
9187 if (!NT_STATUS_IS_OK(status)) {
9188 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
9189 __location__, nt_errstr(status));
9190 correct = false;
9191 goto out;
9194 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
9195 correct = false;
9196 goto out;
9198 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
9199 correct = false;
9200 goto out;
9203 s.val = false;
9205 for (i = 32; i < 128; i++) {
9206 uint16_t fnum = (uint16_t)-1;
9208 s.i = i;
9210 if (strchr(illegal_chars, i)) {
9211 continue;
9213 fname[15] = i;
9215 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
9216 FILE_SHARE_READ|FILE_SHARE_WRITE,
9217 FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
9218 if (!NT_STATUS_IS_OK(status)) {
9219 d_printf("(%s) cli_nt_create of %s failed: %s\n",
9220 __location__, fname, nt_errstr(status));
9221 correct = false;
9222 goto out;
9224 cli_close(cli, fnum);
9226 s.matched = 0;
9227 status = cli_list(cli, "\\shortname\\test*.*", 0,
9228 shortname_list_fn, &s);
9229 if (s.matched != 1) {
9230 d_printf("(%s) failed to list %s: %s\n",
9231 __location__, fname, nt_errstr(status));
9232 correct = false;
9233 goto out;
9236 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9237 if (!NT_STATUS_IS_OK(status)) {
9238 d_printf("(%s) failed to delete %s: %s\n",
9239 __location__, fname, nt_errstr(status));
9240 correct = false;
9241 goto out;
9244 if (s.val) {
9245 correct = false;
9246 goto out;
9250 out:
9252 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
9253 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
9254 cli_rmdir(cli, "\\shortname");
9255 torture_close_connection(cli);
9256 return correct;
9259 static void pagedsearch_cb(struct tevent_req *req)
9261 TLDAPRC rc;
9262 struct tldap_message *msg;
9263 char *dn;
9265 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
9266 if (!TLDAP_RC_IS_SUCCESS(rc)) {
9267 d_printf("tldap_search_paged_recv failed: %s\n",
9268 tldap_rc2string(rc));
9269 return;
9271 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
9272 TALLOC_FREE(msg);
9273 return;
9275 if (!tldap_entry_dn(msg, &dn)) {
9276 d_printf("tldap_entry_dn failed\n");
9277 return;
9279 d_printf("%s\n", dn);
9280 TALLOC_FREE(msg);
9283 static bool run_tldap(int dummy)
9285 struct tldap_context *ld;
9286 int fd;
9287 TLDAPRC rc;
9288 NTSTATUS status;
9289 struct sockaddr_storage addr;
9290 struct tevent_context *ev;
9291 struct tevent_req *req;
9292 char *basedn;
9293 const char *filter;
9295 if (!resolve_name(host, &addr, 0, false)) {
9296 d_printf("could not find host %s\n", host);
9297 return false;
9299 status = open_socket_out(&addr, 389, 9999, &fd);
9300 if (!NT_STATUS_IS_OK(status)) {
9301 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
9302 return false;
9305 ld = tldap_context_create(talloc_tos(), fd);
9306 if (ld == NULL) {
9307 close(fd);
9308 d_printf("tldap_context_create failed\n");
9309 return false;
9312 rc = tldap_fetch_rootdse(ld);
9313 if (!TLDAP_RC_IS_SUCCESS(rc)) {
9314 d_printf("tldap_fetch_rootdse failed: %s\n",
9315 tldap_errstr(talloc_tos(), ld, rc));
9316 return false;
9319 basedn = tldap_talloc_single_attribute(
9320 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
9321 if (basedn == NULL) {
9322 d_printf("no defaultNamingContext\n");
9323 return false;
9325 d_printf("defaultNamingContext: %s\n", basedn);
9327 ev = samba_tevent_context_init(talloc_tos());
9328 if (ev == NULL) {
9329 d_printf("tevent_context_init failed\n");
9330 return false;
9333 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
9334 TLDAP_SCOPE_SUB, "(objectclass=*)",
9335 NULL, 0, 0,
9336 NULL, 0, NULL, 0, 0, 0, 0, 5);
9337 if (req == NULL) {
9338 d_printf("tldap_search_paged_send failed\n");
9339 return false;
9341 tevent_req_set_callback(req, pagedsearch_cb, NULL);
9343 tevent_req_poll(req, ev);
9345 TALLOC_FREE(req);
9347 /* test search filters against rootDSE */
9348 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
9349 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
9351 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
9352 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
9353 talloc_tos(), NULL);
9354 if (!TLDAP_RC_IS_SUCCESS(rc)) {
9355 d_printf("tldap_search with complex filter failed: %s\n",
9356 tldap_errstr(talloc_tos(), ld, rc));
9357 return false;
9360 TALLOC_FREE(ld);
9361 return true;
9364 /* Torture test to ensure no regression of :
9365 https://bugzilla.samba.org/show_bug.cgi?id=7084
9368 static bool run_dir_createtime(int dummy)
9370 struct cli_state *cli;
9371 const char *dname = "\\testdir";
9372 const char *fname = "\\testdir\\testfile";
9373 NTSTATUS status;
9374 struct timespec create_time;
9375 struct timespec create_time1;
9376 uint16_t fnum;
9377 bool ret = false;
9379 if (!torture_open_connection(&cli, 0)) {
9380 return false;
9383 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9384 cli_rmdir(cli, dname);
9386 status = cli_mkdir(cli, dname);
9387 if (!NT_STATUS_IS_OK(status)) {
9388 printf("mkdir failed: %s\n", nt_errstr(status));
9389 goto out;
9392 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
9393 NULL, NULL, NULL);
9394 if (!NT_STATUS_IS_OK(status)) {
9395 printf("cli_qpathinfo2 returned %s\n",
9396 nt_errstr(status));
9397 goto out;
9400 /* Sleep 3 seconds, then create a file. */
9401 sleep(3);
9403 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
9404 DENY_NONE, &fnum);
9405 if (!NT_STATUS_IS_OK(status)) {
9406 printf("cli_openx failed: %s\n", nt_errstr(status));
9407 goto out;
9410 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
9411 NULL, NULL, NULL);
9412 if (!NT_STATUS_IS_OK(status)) {
9413 printf("cli_qpathinfo2 (2) returned %s\n",
9414 nt_errstr(status));
9415 goto out;
9418 if (timespec_compare(&create_time1, &create_time)) {
9419 printf("run_dir_createtime: create time was updated (error)\n");
9420 } else {
9421 printf("run_dir_createtime: create time was not updated (correct)\n");
9422 ret = true;
9425 out:
9427 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9428 cli_rmdir(cli, dname);
9429 if (!torture_close_connection(cli)) {
9430 ret = false;
9432 return ret;
9436 static bool run_streamerror(int dummy)
9438 struct cli_state *cli;
9439 const char *dname = "\\testdir";
9440 const char *streamname =
9441 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
9442 NTSTATUS status;
9443 time_t change_time, access_time, write_time;
9444 off_t size;
9445 uint16_t mode, fnum;
9446 bool ret = true;
9448 if (!torture_open_connection(&cli, 0)) {
9449 return false;
9452 cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9453 cli_rmdir(cli, dname);
9455 status = cli_mkdir(cli, dname);
9456 if (!NT_STATUS_IS_OK(status)) {
9457 printf("mkdir failed: %s\n", nt_errstr(status));
9458 return false;
9461 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
9462 &write_time, &size, &mode);
9463 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
9464 printf("pathinfo returned %s, expected "
9465 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
9466 nt_errstr(status));
9467 ret = false;
9470 status = cli_ntcreate(cli, streamname, 0x16,
9471 FILE_READ_DATA|FILE_READ_EA|
9472 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
9473 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
9474 FILE_OPEN, 0, 0, &fnum, NULL);
9476 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
9477 printf("ntcreate returned %s, expected "
9478 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
9479 nt_errstr(status));
9480 ret = false;
9484 cli_rmdir(cli, dname);
9485 return ret;
9488 struct pidtest_state {
9489 bool success;
9490 uint16_t vwv[1];
9491 DATA_BLOB data;
9494 static void pid_echo_done(struct tevent_req *subreq);
9496 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
9497 struct tevent_context *ev,
9498 struct cli_state *cli)
9500 struct tevent_req *req, *subreq;
9501 struct pidtest_state *state;
9503 req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
9504 if (req == NULL) {
9505 return NULL;
9508 SSVAL(state->vwv, 0, 1);
9509 state->data = data_blob_const("hello", 5);
9511 subreq = smb1cli_req_send(state,
9513 cli->conn,
9514 SMBecho,
9515 0, 0, /* *_flags */
9516 0, 0, /* *_flags2 */
9517 cli->timeout,
9518 0xDEADBEEF, /* pid */
9519 NULL, /* tcon */
9520 NULL, /* session */
9521 ARRAY_SIZE(state->vwv), state->vwv,
9522 state->data.length, state->data.data);
9524 if (tevent_req_nomem(subreq, req)) {
9525 return tevent_req_post(req, ev);
9527 tevent_req_set_callback(subreq, pid_echo_done, req);
9528 return req;
9531 static void pid_echo_done(struct tevent_req *subreq)
9533 struct tevent_req *req = tevent_req_callback_data(
9534 subreq, struct tevent_req);
9535 struct pidtest_state *state = tevent_req_data(
9536 req, struct pidtest_state);
9537 NTSTATUS status;
9538 uint32_t num_bytes;
9539 uint8_t *bytes = NULL;
9540 struct iovec *recv_iov = NULL;
9541 uint8_t *phdr = NULL;
9542 uint16_t pidlow = 0;
9543 uint16_t pidhigh = 0;
9544 struct smb1cli_req_expected_response expected[] = {
9546 .status = NT_STATUS_OK,
9547 .wct = 1,
9551 status = smb1cli_req_recv(subreq, state,
9552 &recv_iov,
9553 &phdr,
9554 NULL, /* pwct */
9555 NULL, /* pvwv */
9556 NULL, /* pvwv_offset */
9557 &num_bytes,
9558 &bytes,
9559 NULL, /* pbytes_offset */
9560 NULL, /* pinbuf */
9561 expected, ARRAY_SIZE(expected));
9563 TALLOC_FREE(subreq);
9565 if (!NT_STATUS_IS_OK(status)) {
9566 tevent_req_nterror(req, status);
9567 return;
9570 if (num_bytes != state->data.length) {
9571 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9572 return;
9575 if (memcmp(bytes, state->data.data, num_bytes) != 0) {
9576 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9577 return;
9580 /* Check pid low/high == DEADBEEF */
9581 pidlow = SVAL(phdr, HDR_PID);
9582 if (pidlow != 0xBEEF){
9583 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
9584 (unsigned int)pidlow);
9585 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9586 return;
9588 pidhigh = SVAL(phdr, HDR_PIDHIGH);
9589 if (pidhigh != 0xDEAD){
9590 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
9591 (unsigned int)pidhigh);
9592 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9593 return;
9596 tevent_req_done(req);
9599 static NTSTATUS pid_echo_recv(struct tevent_req *req)
9601 return tevent_req_simple_recv_ntstatus(req);
9604 static bool run_pidhigh(int dummy)
9606 bool success = false;
9607 struct cli_state *cli = NULL;
9608 NTSTATUS status;
9609 struct tevent_context *ev = NULL;
9610 struct tevent_req *req = NULL;
9611 TALLOC_CTX *frame = talloc_stackframe();
9613 printf("starting pid high test\n");
9614 if (!torture_open_connection(&cli, 0)) {
9615 return false;
9617 smbXcli_conn_set_sockopt(cli->conn, sockops);
9619 ev = samba_tevent_context_init(frame);
9620 if (ev == NULL) {
9621 goto fail;
9624 req = pid_echo_send(frame, ev, cli);
9625 if (req == NULL) {
9626 goto fail;
9629 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
9630 goto fail;
9633 status = pid_echo_recv(req);
9634 if (NT_STATUS_IS_OK(status)) {
9635 printf("pid high test ok\n");
9636 success = true;
9639 fail:
9641 TALLOC_FREE(frame);
9642 torture_close_connection(cli);
9643 return success;
9647 Test Windows open on a bad POSIX symlink.
9649 static bool run_symlink_open_test(int dummy)
9651 static struct cli_state *cli;
9652 const char *fname = "non_existant_file";
9653 const char *sname = "dangling_symlink";
9654 uint16_t fnum = (uint16_t)-1;
9655 bool correct = false;
9656 NTSTATUS status;
9657 TALLOC_CTX *frame = NULL;
9659 frame = talloc_stackframe();
9661 printf("Starting Windows bad symlink open test\n");
9663 if (!torture_open_connection(&cli, 0)) {
9664 TALLOC_FREE(frame);
9665 return false;
9668 smbXcli_conn_set_sockopt(cli->conn, sockops);
9670 status = torture_setup_unix_extensions(cli);
9671 if (!NT_STATUS_IS_OK(status)) {
9672 TALLOC_FREE(frame);
9673 return false;
9676 /* Ensure nothing exists. */
9677 cli_setatr(cli, fname, 0, 0);
9678 cli_posix_unlink(cli, fname);
9679 cli_setatr(cli, sname, 0, 0);
9680 cli_posix_unlink(cli, sname);
9682 /* Create a symlink pointing nowhere. */
9683 status = cli_posix_symlink(cli, fname, sname);
9684 if (!NT_STATUS_IS_OK(status)) {
9685 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
9686 sname,
9687 fname,
9688 nt_errstr(status));
9689 goto out;
9692 /* Now ensure that a Windows open doesn't hang. */
9693 status = cli_ntcreate(cli,
9694 sname,
9696 FILE_READ_DATA|FILE_WRITE_DATA,
9698 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9699 FILE_OPEN_IF,
9700 0x0,
9701 0x0,
9702 &fnum,
9703 NULL);
9706 * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
9707 * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
9708 * we use O_NOFOLLOW on the server or not.
9710 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
9711 NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
9713 correct = true;
9714 } else {
9715 printf("cli_ntcreate of %s returned %s - should return"
9716 " either (%s) or (%s)\n",
9717 sname,
9718 nt_errstr(status),
9719 nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
9720 nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
9721 goto out;
9724 correct = true;
9726 out:
9728 if (fnum != (uint16_t)-1) {
9729 cli_close(cli, fnum);
9730 fnum = (uint16_t)-1;
9733 cli_setatr(cli, sname, 0, 0);
9734 cli_posix_unlink(cli, sname);
9735 cli_setatr(cli, fname, 0, 0);
9736 cli_posix_unlink(cli, fname);
9738 if (!torture_close_connection(cli)) {
9739 correct = false;
9742 TALLOC_FREE(frame);
9743 return correct;
9746 static bool run_local_substitute(int dummy)
9748 bool ok = true;
9750 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
9751 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
9752 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
9753 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
9754 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
9755 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
9756 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
9757 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
9759 /* Different captialization rules in sub_basic... */
9761 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
9762 "blaDOM") == 0);
9764 return ok;
9767 static bool run_local_base64(int dummy)
9769 int i;
9770 bool ret = true;
9772 for (i=1; i<2000; i++) {
9773 DATA_BLOB blob1, blob2;
9774 char *b64;
9776 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
9777 blob1.length = i;
9778 generate_random_buffer(blob1.data, blob1.length);
9780 b64 = base64_encode_data_blob(talloc_tos(), blob1);
9781 if (b64 == NULL) {
9782 d_fprintf(stderr, "base64_encode_data_blob failed "
9783 "for %d bytes\n", i);
9784 ret = false;
9786 blob2 = base64_decode_data_blob(b64);
9787 TALLOC_FREE(b64);
9789 if (data_blob_cmp(&blob1, &blob2)) {
9790 d_fprintf(stderr, "data_blob_cmp failed for %d "
9791 "bytes\n", i);
9792 ret = false;
9794 TALLOC_FREE(blob1.data);
9795 data_blob_free(&blob2);
9797 return ret;
9800 static void parse_fn(time_t timeout, DATA_BLOB blob, void *private_data)
9802 return;
9805 static bool run_local_gencache(int dummy)
9807 char *val;
9808 time_t tm;
9809 DATA_BLOB blob;
9810 char v;
9811 struct memcache *mem;
9812 int i;
9814 mem = memcache_init(NULL, 0);
9815 if (mem == NULL) {
9816 d_printf("%s: memcache_init failed\n", __location__);
9817 return false;
9819 memcache_set_global(mem);
9821 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
9822 d_printf("%s: gencache_set() failed\n", __location__);
9823 return False;
9826 if (!gencache_get("foo", NULL, NULL, NULL)) {
9827 d_printf("%s: gencache_get() failed\n", __location__);
9828 return False;
9831 for (i=0; i<1000000; i++) {
9832 gencache_parse("foo", parse_fn, NULL);
9835 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
9836 d_printf("%s: gencache_get() failed\n", __location__);
9837 return False;
9839 TALLOC_FREE(val);
9841 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
9842 d_printf("%s: gencache_get() failed\n", __location__);
9843 return False;
9846 if (strcmp(val, "bar") != 0) {
9847 d_printf("%s: gencache_get() returned %s, expected %s\n",
9848 __location__, val, "bar");
9849 TALLOC_FREE(val);
9850 return False;
9853 TALLOC_FREE(val);
9855 if (!gencache_del("foo")) {
9856 d_printf("%s: gencache_del() failed\n", __location__);
9857 return False;
9859 if (gencache_del("foo")) {
9860 d_printf("%s: second gencache_del() succeeded\n",
9861 __location__);
9862 return False;
9865 if (gencache_get("foo", talloc_tos(), &val, &tm)) {
9866 d_printf("%s: gencache_get() on deleted entry "
9867 "succeeded\n", __location__);
9868 return False;
9871 blob = data_blob_string_const_null("bar");
9872 tm = time(NULL) + 60;
9874 if (!gencache_set_data_blob("foo", &blob, tm)) {
9875 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
9876 return False;
9879 if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
9880 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
9881 return False;
9884 if (strcmp((const char *)blob.data, "bar") != 0) {
9885 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
9886 __location__, (const char *)blob.data, "bar");
9887 data_blob_free(&blob);
9888 return False;
9891 data_blob_free(&blob);
9893 if (!gencache_del("foo")) {
9894 d_printf("%s: gencache_del() failed\n", __location__);
9895 return False;
9897 if (gencache_del("foo")) {
9898 d_printf("%s: second gencache_del() succeeded\n",
9899 __location__);
9900 return False;
9903 if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
9904 d_printf("%s: gencache_get_data_blob() on deleted entry "
9905 "succeeded\n", __location__);
9906 return False;
9909 v = 1;
9910 blob.data = (uint8_t *)&v;
9911 blob.length = sizeof(v);
9913 if (!gencache_set_data_blob("blob", &blob, tm)) {
9914 d_printf("%s: gencache_set_data_blob() failed\n",
9915 __location__);
9916 return false;
9918 if (gencache_get("blob", talloc_tos(), &val, &tm)) {
9919 d_printf("%s: gencache_get succeeded\n", __location__);
9920 return false;
9923 return True;
9926 static bool rbt_testval(struct db_context *db, const char *key,
9927 const char *value)
9929 struct db_record *rec;
9930 TDB_DATA data = string_tdb_data(value);
9931 bool ret = false;
9932 NTSTATUS status;
9933 TDB_DATA dbvalue;
9935 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
9936 if (rec == NULL) {
9937 d_fprintf(stderr, "fetch_locked failed\n");
9938 goto done;
9940 status = dbwrap_record_store(rec, data, 0);
9941 if (!NT_STATUS_IS_OK(status)) {
9942 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
9943 goto done;
9945 TALLOC_FREE(rec);
9947 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
9948 if (rec == NULL) {
9949 d_fprintf(stderr, "second fetch_locked failed\n");
9950 goto done;
9953 dbvalue = dbwrap_record_get_value(rec);
9954 if ((dbvalue.dsize != data.dsize)
9955 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
9956 d_fprintf(stderr, "Got wrong data back\n");
9957 goto done;
9960 ret = true;
9961 done:
9962 TALLOC_FREE(rec);
9963 return ret;
9966 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
9968 int *count2 = (int *)private_data;
9969 (*count2)++;
9970 return 0;
9973 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
9975 int *count2 = (int *)private_data;
9976 (*count2)++;
9977 dbwrap_record_delete(rec);
9978 return 0;
9981 static bool run_local_rbtree(int dummy)
9983 struct db_context *db;
9984 bool ret = false;
9985 int i;
9986 NTSTATUS status;
9987 int count = 0;
9988 int count2 = 0;
9990 db = db_open_rbt(NULL);
9992 if (db == NULL) {
9993 d_fprintf(stderr, "db_open_rbt failed\n");
9994 return false;
9997 for (i=0; i<1000; i++) {
9998 char *key, *value;
10000 if (asprintf(&key, "key%ld", random()) == -1) {
10001 goto done;
10003 if (asprintf(&value, "value%ld", random()) == -1) {
10004 SAFE_FREE(key);
10005 goto done;
10008 if (!rbt_testval(db, key, value)) {
10009 SAFE_FREE(key);
10010 SAFE_FREE(value);
10011 goto done;
10014 SAFE_FREE(value);
10015 if (asprintf(&value, "value%ld", random()) == -1) {
10016 SAFE_FREE(key);
10017 goto done;
10020 if (!rbt_testval(db, key, value)) {
10021 SAFE_FREE(key);
10022 SAFE_FREE(value);
10023 goto done;
10026 SAFE_FREE(key);
10027 SAFE_FREE(value);
10030 ret = true;
10031 count = 0; count2 = 0;
10032 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
10033 &count2, &count);
10034 printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10035 if ((count != count2) || (count != 1000)) {
10036 ret = false;
10038 count = 0; count2 = 0;
10039 status = dbwrap_traverse(db, local_rbtree_traverse_delete,
10040 &count2, &count);
10041 printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10042 if ((count != count2) || (count != 1000)) {
10043 ret = false;
10045 count = 0; count2 = 0;
10046 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
10047 &count2, &count);
10048 printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10049 if ((count != count2) || (count != 0)) {
10050 ret = false;
10053 done:
10054 TALLOC_FREE(db);
10055 return ret;
10060 local test for character set functions
10062 This is a very simple test for the functionality in convert_string_error()
10064 static bool run_local_convert_string(int dummy)
10066 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
10067 const char *test_strings[2] = { "March", "M\303\244rz" };
10068 char dst[7];
10069 int i;
10071 for (i=0; i<2; i++) {
10072 const char *str = test_strings[i];
10073 int len = strlen(str);
10074 size_t converted_size;
10075 bool ret;
10077 memset(dst, 'X', sizeof(dst));
10079 /* first try with real source length */
10080 ret = convert_string_error(CH_UNIX, CH_UTF8,
10081 str, len,
10082 dst, sizeof(dst),
10083 &converted_size);
10084 if (ret != true) {
10085 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
10086 goto failed;
10089 if (converted_size != len) {
10090 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
10091 str, len, (int)converted_size);
10092 goto failed;
10095 if (strncmp(str, dst, converted_size) != 0) {
10096 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
10097 goto failed;
10100 if (strlen(str) != converted_size) {
10101 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
10102 (int)strlen(str), (int)converted_size);
10103 goto failed;
10106 if (dst[converted_size] != 'X') {
10107 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
10108 goto failed;
10111 /* now with srclen==-1, this causes the nul to be
10112 * converted too */
10113 ret = convert_string_error(CH_UNIX, CH_UTF8,
10114 str, -1,
10115 dst, sizeof(dst),
10116 &converted_size);
10117 if (ret != true) {
10118 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
10119 goto failed;
10122 if (converted_size != len+1) {
10123 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
10124 str, len, (int)converted_size);
10125 goto failed;
10128 if (strncmp(str, dst, converted_size) != 0) {
10129 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
10130 goto failed;
10133 if (len+1 != converted_size) {
10134 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
10135 len+1, (int)converted_size);
10136 goto failed;
10139 if (dst[converted_size] != 'X') {
10140 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
10141 goto failed;
10147 TALLOC_FREE(tmp_ctx);
10148 return true;
10149 failed:
10150 TALLOC_FREE(tmp_ctx);
10151 return false;
10155 struct talloc_dict_test {
10156 int content;
10159 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
10161 int *count = (int *)priv;
10162 *count += 1;
10163 return 0;
10166 static bool run_local_talloc_dict(int dummy)
10168 struct talloc_dict *dict;
10169 struct talloc_dict_test *t;
10170 int key, count, res;
10171 bool ok;
10173 dict = talloc_dict_init(talloc_tos());
10174 if (dict == NULL) {
10175 return false;
10178 t = talloc(talloc_tos(), struct talloc_dict_test);
10179 if (t == NULL) {
10180 return false;
10183 key = 1;
10184 t->content = 1;
10185 ok = talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), &t);
10186 if (!ok) {
10187 return false;
10190 count = 0;
10191 res = talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count);
10192 if (res == -1) {
10193 return false;
10196 if (count != 1) {
10197 return false;
10200 if (count != res) {
10201 return false;
10204 TALLOC_FREE(dict);
10206 return true;
10209 static bool run_local_string_to_sid(int dummy) {
10210 struct dom_sid sid;
10212 if (string_to_sid(&sid, "S--1-5-32-545")) {
10213 printf("allowing S--1-5-32-545\n");
10214 return false;
10216 if (string_to_sid(&sid, "S-1-5-32-+545")) {
10217 printf("allowing S-1-5-32-+545\n");
10218 return false;
10220 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")) {
10221 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
10222 return false;
10224 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
10225 printf("allowing S-1-5-32-545-abc\n");
10226 return false;
10228 if (string_to_sid(&sid, "S-300-5-32-545")) {
10229 printf("allowing S-300-5-32-545\n");
10230 return false;
10232 if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
10233 printf("allowing S-1-0xfffffffffffffe-32-545\n");
10234 return false;
10236 if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
10237 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
10238 return false;
10240 if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
10241 printf("could not parse S-1-0xfffffffffffe-32-545\n");
10242 return false;
10244 if (!string_to_sid(&sid, "S-1-5-32-545")) {
10245 printf("could not parse S-1-5-32-545\n");
10246 return false;
10248 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
10249 printf("mis-parsed S-1-5-32-545 as %s\n",
10250 sid_string_tos(&sid));
10251 return false;
10253 return true;
10256 static bool sid_to_string_test(const char *expected) {
10257 char *str;
10258 bool res = true;
10259 struct dom_sid sid;
10261 if (!string_to_sid(&sid, expected)) {
10262 printf("could not parse %s\n", expected);
10263 return false;
10266 str = dom_sid_string(NULL, &sid);
10267 if (strcmp(str, expected)) {
10268 printf("Comparison failed (%s != %s)\n", str, expected);
10269 res = false;
10271 TALLOC_FREE(str);
10272 return res;
10275 static bool run_local_sid_to_string(int dummy) {
10276 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
10277 return false;
10278 if (!sid_to_string_test("S-1-545"))
10279 return false;
10280 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
10281 return false;
10282 return true;
10285 static bool run_local_binary_to_sid(int dummy) {
10286 struct dom_sid *sid = talloc(NULL, struct dom_sid);
10287 static const uint8_t good_binary_sid[] = {
10288 0x1, /* revision number */
10289 15, /* num auths */
10290 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10291 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10292 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10293 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10294 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10295 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10296 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10297 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10298 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10299 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10300 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10301 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10302 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10303 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10304 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10305 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10308 static const uint8_t long_binary_sid[] = {
10309 0x1, /* revision number */
10310 15, /* num auths */
10311 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10312 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10313 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10314 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10315 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10316 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10317 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10318 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10319 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10320 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10321 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10322 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10323 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10324 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10325 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10326 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10327 0x1, 0x1, 0x1, 0x1, /* auth[15] */
10328 0x1, 0x1, 0x1, 0x1, /* auth[16] */
10329 0x1, 0x1, 0x1, 0x1, /* auth[17] */
10332 static const uint8_t long_binary_sid2[] = {
10333 0x1, /* revision number */
10334 32, /* num auths */
10335 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10336 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10337 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10338 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10339 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10340 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10341 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10342 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10343 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10344 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10345 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10346 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10347 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10348 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10349 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10350 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10351 0x1, 0x1, 0x1, 0x1, /* auth[15] */
10352 0x1, 0x1, 0x1, 0x1, /* auth[16] */
10353 0x1, 0x1, 0x1, 0x1, /* auth[17] */
10354 0x1, 0x1, 0x1, 0x1, /* auth[18] */
10355 0x1, 0x1, 0x1, 0x1, /* auth[19] */
10356 0x1, 0x1, 0x1, 0x1, /* auth[20] */
10357 0x1, 0x1, 0x1, 0x1, /* auth[21] */
10358 0x1, 0x1, 0x1, 0x1, /* auth[22] */
10359 0x1, 0x1, 0x1, 0x1, /* auth[23] */
10360 0x1, 0x1, 0x1, 0x1, /* auth[24] */
10361 0x1, 0x1, 0x1, 0x1, /* auth[25] */
10362 0x1, 0x1, 0x1, 0x1, /* auth[26] */
10363 0x1, 0x1, 0x1, 0x1, /* auth[27] */
10364 0x1, 0x1, 0x1, 0x1, /* auth[28] */
10365 0x1, 0x1, 0x1, 0x1, /* auth[29] */
10366 0x1, 0x1, 0x1, 0x1, /* auth[30] */
10367 0x1, 0x1, 0x1, 0x1, /* auth[31] */
10370 if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
10371 return false;
10373 if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
10374 return false;
10376 if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
10377 return false;
10379 return true;
10382 /* Split a path name into filename and stream name components. Canonicalise
10383 * such that an implicit $DATA token is always explicit.
10385 * The "specification" of this function can be found in the
10386 * run_local_stream_name() function in torture.c, I've tried those
10387 * combinations against a W2k3 server.
10390 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
10391 char **pbase, char **pstream)
10393 char *base = NULL;
10394 char *stream = NULL;
10395 char *sname; /* stream name */
10396 const char *stype; /* stream type */
10398 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
10400 sname = strchr_m(fname, ':');
10402 if (sname == NULL) {
10403 if (pbase != NULL) {
10404 base = talloc_strdup(mem_ctx, fname);
10405 NT_STATUS_HAVE_NO_MEMORY(base);
10407 goto done;
10410 if (pbase != NULL) {
10411 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
10412 NT_STATUS_HAVE_NO_MEMORY(base);
10415 sname += 1;
10417 stype = strchr_m(sname, ':');
10419 if (stype == NULL) {
10420 sname = talloc_strdup(mem_ctx, sname);
10421 stype = "$DATA";
10423 else {
10424 if (strcasecmp_m(stype, ":$DATA") != 0) {
10426 * If there is an explicit stream type, so far we only
10427 * allow $DATA. Is there anything else allowed? -- vl
10429 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
10430 TALLOC_FREE(base);
10431 return NT_STATUS_OBJECT_NAME_INVALID;
10433 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
10434 stype += 1;
10437 if (sname == NULL) {
10438 TALLOC_FREE(base);
10439 return NT_STATUS_NO_MEMORY;
10442 if (sname[0] == '\0') {
10444 * no stream name, so no stream
10446 goto done;
10449 if (pstream != NULL) {
10450 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
10451 if (stream == NULL) {
10452 TALLOC_FREE(sname);
10453 TALLOC_FREE(base);
10454 return NT_STATUS_NO_MEMORY;
10457 * upper-case the type field
10459 (void)strupper_m(strchr_m(stream, ':')+1);
10462 done:
10463 if (pbase != NULL) {
10464 *pbase = base;
10466 if (pstream != NULL) {
10467 *pstream = stream;
10469 return NT_STATUS_OK;
10472 static bool test_stream_name(const char *fname, const char *expected_base,
10473 const char *expected_stream,
10474 NTSTATUS expected_status)
10476 NTSTATUS status;
10477 char *base = NULL;
10478 char *stream = NULL;
10480 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
10481 if (!NT_STATUS_EQUAL(status, expected_status)) {
10482 goto error;
10485 if (!NT_STATUS_IS_OK(status)) {
10486 return true;
10489 if (base == NULL) goto error;
10491 if (strcmp(expected_base, base) != 0) goto error;
10493 if ((expected_stream != NULL) && (stream == NULL)) goto error;
10494 if ((expected_stream == NULL) && (stream != NULL)) goto error;
10496 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
10497 goto error;
10499 TALLOC_FREE(base);
10500 TALLOC_FREE(stream);
10501 return true;
10503 error:
10504 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
10505 fname, expected_base ? expected_base : "<NULL>",
10506 expected_stream ? expected_stream : "<NULL>",
10507 nt_errstr(expected_status));
10508 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
10509 base ? base : "<NULL>", stream ? stream : "<NULL>",
10510 nt_errstr(status));
10511 TALLOC_FREE(base);
10512 TALLOC_FREE(stream);
10513 return false;
10516 static bool run_local_stream_name(int dummy)
10518 bool ret = true;
10520 ret &= test_stream_name(
10521 "bla", "bla", NULL, NT_STATUS_OK);
10522 ret &= test_stream_name(
10523 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
10524 ret &= test_stream_name(
10525 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
10526 ret &= test_stream_name(
10527 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
10528 ret &= test_stream_name(
10529 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
10530 ret &= test_stream_name(
10531 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
10532 ret &= test_stream_name(
10533 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
10534 ret &= test_stream_name(
10535 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
10537 return ret;
10540 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
10542 if (a.length != b.length) {
10543 printf("a.length=%d != b.length=%d\n",
10544 (int)a.length, (int)b.length);
10545 return false;
10547 if (memcmp(a.data, b.data, a.length) != 0) {
10548 printf("a.data and b.data differ\n");
10549 return false;
10551 return true;
10554 static bool run_local_memcache(int dummy)
10556 struct memcache *cache;
10557 DATA_BLOB k1, k2;
10558 DATA_BLOB d1, d2, d3;
10559 DATA_BLOB v1, v2, v3;
10561 TALLOC_CTX *mem_ctx;
10562 char *str1, *str2;
10563 size_t size1, size2;
10564 bool ret = false;
10566 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
10568 if (cache == NULL) {
10569 printf("memcache_init failed\n");
10570 return false;
10573 d1 = data_blob_const("d1", 2);
10574 d2 = data_blob_const("d2", 2);
10575 d3 = data_blob_const("d3", 2);
10577 k1 = data_blob_const("d1", 2);
10578 k2 = data_blob_const("d2", 2);
10580 memcache_add(cache, STAT_CACHE, k1, d1);
10581 memcache_add(cache, GETWD_CACHE, k2, d2);
10583 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
10584 printf("could not find k1\n");
10585 return false;
10587 if (!data_blob_equal(d1, v1)) {
10588 return false;
10591 if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
10592 printf("could not find k2\n");
10593 return false;
10595 if (!data_blob_equal(d2, v2)) {
10596 return false;
10599 memcache_add(cache, STAT_CACHE, k1, d3);
10601 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
10602 printf("could not find replaced k1\n");
10603 return false;
10605 if (!data_blob_equal(d3, v3)) {
10606 return false;
10609 memcache_add(cache, GETWD_CACHE, k1, d1);
10611 if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
10612 printf("Did find k2, should have been purged\n");
10613 return false;
10616 TALLOC_FREE(cache);
10618 cache = memcache_init(NULL, 0);
10620 mem_ctx = talloc_init("foo");
10622 str1 = talloc_strdup(mem_ctx, "string1");
10623 str2 = talloc_strdup(mem_ctx, "string2");
10625 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
10626 data_blob_string_const("torture"), &str1);
10627 size1 = talloc_total_size(cache);
10629 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
10630 data_blob_string_const("torture"), &str2);
10631 size2 = talloc_total_size(cache);
10633 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
10635 if (size2 > size1) {
10636 printf("memcache leaks memory!\n");
10637 goto fail;
10640 ret = true;
10641 fail:
10642 TALLOC_FREE(cache);
10643 return ret;
10646 static void wbclient_done(struct tevent_req *req)
10648 wbcErr wbc_err;
10649 struct winbindd_response *wb_resp;
10650 int *i = (int *)tevent_req_callback_data_void(req);
10652 wbc_err = wb_trans_recv(req, req, &wb_resp);
10653 TALLOC_FREE(req);
10654 *i += 1;
10655 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
10658 static bool run_wbclient_multi_ping(int dummy)
10660 struct tevent_context *ev;
10661 struct wb_context **wb_ctx;
10662 struct winbindd_request wb_req;
10663 bool result = false;
10664 int i, j;
10666 BlockSignals(True, SIGPIPE);
10668 ev = tevent_context_init(talloc_tos());
10669 if (ev == NULL) {
10670 goto fail;
10673 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
10674 if (wb_ctx == NULL) {
10675 goto fail;
10678 ZERO_STRUCT(wb_req);
10679 wb_req.cmd = WINBINDD_PING;
10681 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
10683 for (i=0; i<torture_nprocs; i++) {
10684 wb_ctx[i] = wb_context_init(ev, NULL);
10685 if (wb_ctx[i] == NULL) {
10686 goto fail;
10688 for (j=0; j<torture_numops; j++) {
10689 struct tevent_req *req;
10690 req = wb_trans_send(ev, ev, wb_ctx[i],
10691 (j % 2) == 0, &wb_req);
10692 if (req == NULL) {
10693 goto fail;
10695 tevent_req_set_callback(req, wbclient_done, &i);
10699 i = 0;
10701 while (i < torture_nprocs * torture_numops) {
10702 tevent_loop_once(ev);
10705 result = true;
10706 fail:
10707 TALLOC_FREE(ev);
10708 return result;
10711 static void getaddrinfo_finished(struct tevent_req *req)
10713 char *name = (char *)tevent_req_callback_data_void(req);
10714 struct addrinfo *ainfo;
10715 int res;
10717 res = getaddrinfo_recv(req, &ainfo);
10718 if (res != 0) {
10719 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
10720 return;
10722 d_printf("gai(%s) succeeded\n", name);
10723 freeaddrinfo(ainfo);
10726 static bool run_getaddrinfo_send(int dummy)
10728 TALLOC_CTX *frame = talloc_stackframe();
10729 struct fncall_context *ctx;
10730 struct tevent_context *ev;
10731 bool result = false;
10732 const char *names[4] = { "www.samba.org", "notfound.samba.org",
10733 "www.slashdot.org", "heise.de" };
10734 struct tevent_req *reqs[4];
10735 int i;
10737 ev = samba_tevent_context_init(frame);
10738 if (ev == NULL) {
10739 goto fail;
10742 ctx = fncall_context_init(frame, 4);
10744 for (i=0; i<ARRAY_SIZE(names); i++) {
10745 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
10746 NULL);
10747 if (reqs[i] == NULL) {
10748 goto fail;
10750 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
10751 discard_const_p(void, names[i]));
10754 for (i=0; i<ARRAY_SIZE(reqs); i++) {
10755 tevent_loop_once(ev);
10758 result = true;
10759 fail:
10760 TALLOC_FREE(frame);
10761 return result;
10764 static bool dbtrans_inc(struct db_context *db)
10766 struct db_record *rec;
10767 uint32_t val;
10768 bool ret = false;
10769 NTSTATUS status;
10770 TDB_DATA value;
10772 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
10773 if (rec == NULL) {
10774 printf(__location__ "fetch_lock failed\n");
10775 return false;
10778 value = dbwrap_record_get_value(rec);
10780 if (value.dsize != sizeof(uint32_t)) {
10781 printf(__location__ "value.dsize = %d\n",
10782 (int)value.dsize);
10783 goto fail;
10786 memcpy(&val, value.dptr, sizeof(val));
10787 val += 1;
10789 status = dbwrap_record_store(
10790 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
10791 if (!NT_STATUS_IS_OK(status)) {
10792 printf(__location__ "store failed: %s\n",
10793 nt_errstr(status));
10794 goto fail;
10797 ret = true;
10798 fail:
10799 TALLOC_FREE(rec);
10800 return ret;
10803 static bool run_local_dbtrans(int dummy)
10805 struct db_context *db;
10806 struct db_record *rec;
10807 NTSTATUS status;
10808 uint32_t initial;
10809 int res;
10810 TDB_DATA value;
10812 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
10813 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
10814 DBWRAP_FLAG_NONE);
10815 if (db == NULL) {
10816 printf("Could not open transtest.db\n");
10817 return false;
10820 res = dbwrap_transaction_start(db);
10821 if (res != 0) {
10822 printf(__location__ "transaction_start failed\n");
10823 return false;
10826 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
10827 if (rec == NULL) {
10828 printf(__location__ "fetch_lock failed\n");
10829 return false;
10832 value = dbwrap_record_get_value(rec);
10834 if (value.dptr == NULL) {
10835 initial = 0;
10836 status = dbwrap_record_store(
10837 rec, make_tdb_data((uint8_t *)&initial,
10838 sizeof(initial)),
10840 if (!NT_STATUS_IS_OK(status)) {
10841 printf(__location__ "store returned %s\n",
10842 nt_errstr(status));
10843 return false;
10847 TALLOC_FREE(rec);
10849 res = dbwrap_transaction_commit(db);
10850 if (res != 0) {
10851 printf(__location__ "transaction_commit failed\n");
10852 return false;
10855 while (true) {
10856 uint32_t val, val2;
10857 int i;
10859 res = dbwrap_transaction_start(db);
10860 if (res != 0) {
10861 printf(__location__ "transaction_start failed\n");
10862 break;
10865 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
10866 if (!NT_STATUS_IS_OK(status)) {
10867 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
10868 nt_errstr(status));
10869 break;
10872 for (i=0; i<10; i++) {
10873 if (!dbtrans_inc(db)) {
10874 return false;
10878 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
10879 if (!NT_STATUS_IS_OK(status)) {
10880 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
10881 nt_errstr(status));
10882 break;
10885 if (val2 != val + 10) {
10886 printf(__location__ "val=%d, val2=%d\n",
10887 (int)val, (int)val2);
10888 break;
10891 printf("val2=%d\r", val2);
10893 res = dbwrap_transaction_commit(db);
10894 if (res != 0) {
10895 printf(__location__ "transaction_commit failed\n");
10896 break;
10900 TALLOC_FREE(db);
10901 return true;
10905 * Just a dummy test to be run under a debugger. There's no real way
10906 * to inspect the tevent_select specific function from outside of
10907 * tevent_select.c.
10910 static bool run_local_tevent_select(int dummy)
10912 struct tevent_context *ev;
10913 struct tevent_fd *fd1, *fd2;
10914 bool result = false;
10916 ev = tevent_context_init_byname(NULL, "select");
10917 if (ev == NULL) {
10918 d_fprintf(stderr, "tevent_context_init_byname failed\n");
10919 goto fail;
10922 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
10923 if (fd1 == NULL) {
10924 d_fprintf(stderr, "tevent_add_fd failed\n");
10925 goto fail;
10927 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
10928 if (fd2 == NULL) {
10929 d_fprintf(stderr, "tevent_add_fd failed\n");
10930 goto fail;
10932 TALLOC_FREE(fd2);
10934 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
10935 if (fd2 == NULL) {
10936 d_fprintf(stderr, "tevent_add_fd failed\n");
10937 goto fail;
10940 result = true;
10941 fail:
10942 TALLOC_FREE(ev);
10943 return result;
10946 static bool run_local_hex_encode_buf(int dummy)
10948 char buf[17];
10949 uint8_t src[8];
10950 int i;
10952 for (i=0; i<sizeof(src); i++) {
10953 src[i] = i;
10955 hex_encode_buf(buf, src, sizeof(src));
10956 if (strcmp(buf, "0001020304050607") != 0) {
10957 return false;
10959 hex_encode_buf(buf, NULL, 0);
10960 if (buf[0] != '\0') {
10961 return false;
10963 return true;
10966 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
10967 "0.0.0.0",
10968 "::0",
10969 "1.2.3.1",
10970 "0.0.0.0",
10971 "0.0.0.0",
10972 "1.2.3.2",
10973 "1.2.3.3",
10974 "1.2.3.4",
10975 "1.2.3.5",
10976 "::0",
10977 "1.2.3.6",
10978 "1.2.3.7",
10979 "::0",
10980 "::0",
10981 "::0",
10982 "1.2.3.8",
10983 "1.2.3.9",
10984 "1.2.3.10",
10985 "1.2.3.11",
10986 "1.2.3.12",
10987 "1.2.3.13",
10988 "1001:1111:1111:1000:0:1111:1111:1111",
10989 "1.2.3.1",
10990 "1.2.3.2",
10991 "1.2.3.3",
10992 "1.2.3.12",
10993 "::0",
10994 "::0"
10997 static const char *remove_duplicate_addrs2_test_strings_result[] = {
10998 "1.2.3.1",
10999 "1.2.3.2",
11000 "1.2.3.3",
11001 "1.2.3.4",
11002 "1.2.3.5",
11003 "1.2.3.6",
11004 "1.2.3.7",
11005 "1.2.3.8",
11006 "1.2.3.9",
11007 "1.2.3.10",
11008 "1.2.3.11",
11009 "1.2.3.12",
11010 "1.2.3.13",
11011 "1001:1111:1111:1000:0:1111:1111:1111"
11014 static bool run_local_remove_duplicate_addrs2(int dummy)
11016 struct ip_service test_vector[28];
11017 int count, i;
11019 /* Construct the sockaddr_storage test vector. */
11020 for (i = 0; i < 28; i++) {
11021 struct addrinfo hints;
11022 struct addrinfo *res = NULL;
11023 int ret;
11025 memset(&hints, '\0', sizeof(hints));
11026 hints.ai_flags = AI_NUMERICHOST;
11027 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
11028 NULL,
11029 &hints,
11030 &res);
11031 if (ret) {
11032 fprintf(stderr, "getaddrinfo failed on [%s]\n",
11033 remove_duplicate_addrs2_test_strings_vector[i]);
11034 return false;
11036 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
11037 memcpy(&test_vector[i].ss,
11038 res->ai_addr,
11039 res->ai_addrlen);
11040 freeaddrinfo(res);
11043 count = remove_duplicate_addrs2(test_vector, i);
11045 if (count != 14) {
11046 fprintf(stderr, "count wrong (%d) should be 14\n",
11047 count);
11048 return false;
11051 for (i = 0; i < count; i++) {
11052 char addr[INET6_ADDRSTRLEN];
11054 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
11056 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
11057 fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
11059 addr,
11060 remove_duplicate_addrs2_test_strings_result[i]);
11061 return false;
11065 printf("run_local_remove_duplicate_addrs2: success\n");
11066 return true;
11069 static bool run_local_tdb_opener(int dummy)
11071 TDB_CONTEXT *t;
11072 unsigned v = 0;
11074 while (1) {
11075 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
11076 O_RDWR|O_CREAT, 0755);
11077 if (t == NULL) {
11078 perror("tdb_open failed");
11079 return false;
11081 tdb_close(t);
11083 v += 1;
11084 printf("\r%u", v);
11086 return true;
11089 static bool run_local_tdb_writer(int dummy)
11091 TDB_CONTEXT *t;
11092 unsigned v = 0;
11093 TDB_DATA val;
11095 t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
11096 if (t == 0) {
11097 perror("tdb_open failed");
11098 return 1;
11101 val.dptr = (uint8_t *)&v;
11102 val.dsize = sizeof(v);
11104 while (1) {
11105 TDB_DATA data;
11106 int ret;
11108 ret = tdb_store(t, val, val, 0);
11109 if (ret != 0) {
11110 printf("%s\n", tdb_errorstr(t));
11112 v += 1;
11113 printf("\r%u", v);
11115 data = tdb_fetch(t, val);
11116 if (data.dptr != NULL) {
11117 SAFE_FREE(data.dptr);
11120 return true;
11123 static bool run_local_canonicalize_path(int dummy)
11125 const char *src[] = {
11126 "/foo/..",
11127 "/..",
11128 "/foo/bar/../baz",
11129 "/foo/././",
11130 "/../foo",
11131 ".././././",
11132 ".././././../../../boo",
11133 "./..",
11134 NULL
11136 const char *dst[] = {
11137 "/",
11138 "/",
11139 "/foo/baz",
11140 "/foo",
11141 "/foo",
11142 "/",
11143 "/boo",
11144 "/",
11145 NULL
11147 unsigned int i;
11149 for (i = 0; src[i] != NULL; i++) {
11150 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
11151 if (d == NULL) {
11152 perror("talloc fail\n");
11153 return false;
11155 if (strcmp(d, dst[i]) != 0) {
11156 d_fprintf(stderr,
11157 "canonicalize missmatch %s -> %s != %s",
11158 src[i], d, dst[i]);
11159 return false;
11161 talloc_free(d);
11163 return true;
11166 static bool run_ign_bad_negprot(int dummy)
11168 struct tevent_context *ev;
11169 struct tevent_req *req;
11170 struct smbXcli_conn *conn;
11171 struct sockaddr_storage ss;
11172 NTSTATUS status;
11173 int fd;
11174 bool ok;
11176 printf("starting ignore bad negprot\n");
11178 ok = resolve_name(host, &ss, 0x20, true);
11179 if (!ok) {
11180 d_fprintf(stderr, "Could not resolve name %s\n", host);
11181 return false;
11184 status = open_socket_out(&ss, 445, 10000, &fd);
11185 if (!NT_STATUS_IS_OK(status)) {
11186 d_fprintf(stderr, "open_socket_out failed: %s\n",
11187 nt_errstr(status));
11188 return false;
11191 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
11192 NULL, 0);
11193 if (conn == NULL) {
11194 d_fprintf(stderr, "smbXcli_conn_create failed\n");
11195 return false;
11198 status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
11199 if (NT_STATUS_IS_OK(status)) {
11200 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
11201 return false;
11204 ev = samba_tevent_context_init(talloc_tos());
11205 if (ev == NULL) {
11206 d_fprintf(stderr, "samba_tevent_context_init failed\n");
11207 return false;
11210 req = smb1cli_session_setup_nt1_send(
11211 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
11212 data_blob_null, data_blob_null, 0x40,
11213 "Windows 2000 2195", "Windows 2000 5.0");
11214 if (req == NULL) {
11215 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
11216 return false;
11219 ok = tevent_req_poll_ntstatus(req, ev, &status);
11220 if (!ok) {
11221 d_fprintf(stderr, "tevent_req_poll failed\n");
11222 return false;
11225 status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
11226 NULL, NULL);
11227 if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
11228 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
11229 "%s, expected NT_STATUS_CONNECTION_RESET\n",
11230 nt_errstr(status));
11231 return false;
11234 TALLOC_FREE(conn);
11236 printf("starting ignore bad negprot\n");
11238 return true;
11241 static double create_procs(bool (*fn)(int), bool *result)
11243 int i, status;
11244 volatile pid_t *child_status;
11245 volatile bool *child_status_out;
11246 int synccount;
11247 int tries = 8;
11248 struct timeval start;
11250 synccount = 0;
11252 child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
11253 if (!child_status) {
11254 printf("Failed to setup shared memory\n");
11255 return -1;
11258 child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
11259 if (!child_status_out) {
11260 printf("Failed to setup result status shared memory\n");
11261 return -1;
11264 for (i = 0; i < torture_nprocs; i++) {
11265 child_status[i] = 0;
11266 child_status_out[i] = True;
11269 start = timeval_current();
11271 for (i=0;i<torture_nprocs;i++) {
11272 procnum = i;
11273 if (fork() == 0) {
11274 pid_t mypid = getpid();
11275 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
11277 slprintf(myname,sizeof(myname),"CLIENT%d", i);
11279 while (1) {
11280 if (torture_open_connection(&current_cli, i)) break;
11281 if (tries-- == 0) {
11282 printf("pid %d failed to start\n", (int)getpid());
11283 _exit(1);
11285 smb_msleep(10);
11288 child_status[i] = getpid();
11290 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
11292 child_status_out[i] = fn(i);
11293 _exit(0);
11297 do {
11298 synccount = 0;
11299 for (i=0;i<torture_nprocs;i++) {
11300 if (child_status[i]) synccount++;
11302 if (synccount == torture_nprocs) break;
11303 smb_msleep(10);
11304 } while (timeval_elapsed(&start) < 30);
11306 if (synccount != torture_nprocs) {
11307 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
11308 *result = False;
11309 return timeval_elapsed(&start);
11312 /* start the client load */
11313 start = timeval_current();
11315 for (i=0;i<torture_nprocs;i++) {
11316 child_status[i] = 0;
11319 printf("%d clients started\n", torture_nprocs);
11321 for (i=0;i<torture_nprocs;i++) {
11322 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
11325 printf("\n");
11327 for (i=0;i<torture_nprocs;i++) {
11328 if (!child_status_out[i]) {
11329 *result = False;
11332 return timeval_elapsed(&start);
11335 #define FLAG_MULTIPROC 1
11337 static struct {
11338 const char *name;
11339 bool (*fn)(int);
11340 unsigned flags;
11341 } torture_ops[] = {
11342 {"FDPASS", run_fdpasstest, 0},
11343 {"LOCK1", run_locktest1, 0},
11344 {"LOCK2", run_locktest2, 0},
11345 {"LOCK3", run_locktest3, 0},
11346 {"LOCK4", run_locktest4, 0},
11347 {"LOCK5", run_locktest5, 0},
11348 {"LOCK6", run_locktest6, 0},
11349 {"LOCK7", run_locktest7, 0},
11350 {"LOCK8", run_locktest8, 0},
11351 {"LOCK9", run_locktest9, 0},
11352 {"UNLINK", run_unlinktest, 0},
11353 {"BROWSE", run_browsetest, 0},
11354 {"ATTR", run_attrtest, 0},
11355 {"TRANS2", run_trans2test, 0},
11356 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
11357 {"TORTURE",run_torture, FLAG_MULTIPROC},
11358 {"RANDOMIPC", run_randomipc, 0},
11359 {"NEGNOWAIT", run_negprot_nowait, 0},
11360 {"NBENCH", run_nbench, 0},
11361 {"NBENCH2", run_nbench2, 0},
11362 {"OPLOCK1", run_oplock1, 0},
11363 {"OPLOCK2", run_oplock2, 0},
11364 {"OPLOCK4", run_oplock4, 0},
11365 {"DIR", run_dirtest, 0},
11366 {"DIR1", run_dirtest1, 0},
11367 {"DIR-CREATETIME", run_dir_createtime, 0},
11368 {"DENY1", torture_denytest1, 0},
11369 {"DENY2", torture_denytest2, 0},
11370 {"TCON", run_tcon_test, 0},
11371 {"TCONDEV", run_tcon_devtype_test, 0},
11372 {"RW1", run_readwritetest, 0},
11373 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
11374 {"RW3", run_readwritelarge, 0},
11375 {"RW-SIGNING", run_readwritelarge_signtest, 0},
11376 {"OPEN", run_opentest, 0},
11377 {"POSIX", run_simple_posix_open_test, 0},
11378 {"POSIX-APPEND", run_posix_append, 0},
11379 {"POSIX-SYMLINK-ACL", run_acl_symlink_test, 0},
11380 {"POSIX-SYMLINK-EA", run_ea_symlink_test, 0},
11381 {"POSIX-STREAM-DELETE", run_posix_stream_delete, 0},
11382 {"POSIX-OFD-LOCK", run_posix_ofd_lock_test, 0},
11383 {"WINDOWS-BAD-SYMLINK", run_symlink_open_test, 0},
11384 {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
11385 {"ASYNC-ECHO", run_async_echo, 0},
11386 { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
11387 { "SHORTNAME-TEST", run_shortname_test, 0},
11388 { "ADDRCHANGE", run_addrchange, 0},
11389 #if 1
11390 {"OPENATTR", run_openattrtest, 0},
11391 #endif
11392 {"XCOPY", run_xcopy, 0},
11393 {"RENAME", run_rename, 0},
11394 {"RENAME-ACCESS", run_rename_access, 0},
11395 {"OWNER-RIGHTS", run_owner_rights, 0},
11396 {"DELETE", run_deletetest, 0},
11397 {"WILDDELETE", run_wild_deletetest, 0},
11398 {"DELETE-LN", run_deletetest_ln, 0},
11399 {"PROPERTIES", run_properties, 0},
11400 {"MANGLE", torture_mangle, 0},
11401 {"MANGLE1", run_mangle1, 0},
11402 {"MANGLE-ILLEGAL", run_mangle_illegal, 0},
11403 {"W2K", run_w2ktest, 0},
11404 {"TRANS2SCAN", torture_trans2_scan, 0},
11405 {"NTTRANSSCAN", torture_nttrans_scan, 0},
11406 {"UTABLE", torture_utable, 0},
11407 {"CASETABLE", torture_casetable, 0},
11408 {"ERRMAPEXTRACT", run_error_map_extract, 0},
11409 {"PIPE_NUMBER", run_pipe_number, 0},
11410 {"TCON2", run_tcon2_test, 0},
11411 {"IOCTL", torture_ioctl_test, 0},
11412 {"CHKPATH", torture_chkpath_test, 0},
11413 {"FDSESS", run_fdsesstest, 0},
11414 { "EATEST", run_eatest, 0},
11415 { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
11416 { "CHAIN1", run_chain1, 0},
11417 { "CHAIN2", run_chain2, 0},
11418 { "CHAIN3", run_chain3, 0},
11419 { "WINDOWS-WRITE", run_windows_write, 0},
11420 { "LARGE_READX", run_large_readx, 0},
11421 { "NTTRANS-CREATE", run_nttrans_create, 0},
11422 { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
11423 { "CLI_ECHO", run_cli_echo, 0},
11424 { "GETADDRINFO", run_getaddrinfo_send, 0},
11425 { "TLDAP", run_tldap },
11426 { "STREAMERROR", run_streamerror },
11427 { "NOTIFY-BENCH", run_notify_bench },
11428 { "NOTIFY-BENCH2", run_notify_bench2 },
11429 { "NOTIFY-BENCH3", run_notify_bench3 },
11430 { "BAD-NBT-SESSION", run_bad_nbt_session },
11431 { "IGN-BAD-NEGPROT", run_ign_bad_negprot },
11432 { "SMB-ANY-CONNECT", run_smb_any_connect },
11433 { "NOTIFY-ONLINE", run_notify_online },
11434 { "SMB2-BASIC", run_smb2_basic },
11435 { "SMB2-NEGPROT", run_smb2_negprot },
11436 { "SMB2-SESSION-RECONNECT", run_smb2_session_reconnect },
11437 { "SMB2-TCON-DEPENDENCE", run_smb2_tcon_dependence },
11438 { "SMB2-MULTI-CHANNEL", run_smb2_multi_channel },
11439 { "SMB2-SESSION-REAUTH", run_smb2_session_reauth },
11440 { "SMB2-FTRUNCATE", run_smb2_ftruncate },
11441 { "CLEANUP1", run_cleanup1 },
11442 { "CLEANUP2", run_cleanup2 },
11443 { "CLEANUP3", run_cleanup3 },
11444 { "CLEANUP4", run_cleanup4 },
11445 { "OPLOCK-CANCEL", run_oplock_cancel },
11446 { "PIDHIGH", run_pidhigh },
11447 { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
11448 { "LOCAL-GENCACHE", run_local_gencache, 0},
11449 { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
11450 { "LOCAL-DBWRAP-WATCH1", run_dbwrap_watch1, 0 },
11451 { "LOCAL-DBWRAP-WATCH2", run_dbwrap_watch2, 0 },
11452 { "LOCAL-MESSAGING-READ1", run_messaging_read1, 0 },
11453 { "LOCAL-MESSAGING-READ2", run_messaging_read2, 0 },
11454 { "LOCAL-MESSAGING-READ3", run_messaging_read3, 0 },
11455 { "LOCAL-MESSAGING-READ4", run_messaging_read4, 0 },
11456 { "LOCAL-MESSAGING-FDPASS1", run_messaging_fdpass1, 0 },
11457 { "LOCAL-MESSAGING-FDPASS2", run_messaging_fdpass2, 0 },
11458 { "LOCAL-MESSAGING-FDPASS2a", run_messaging_fdpass2a, 0 },
11459 { "LOCAL-MESSAGING-FDPASS2b", run_messaging_fdpass2b, 0 },
11460 { "LOCAL-BASE64", run_local_base64, 0},
11461 { "LOCAL-RBTREE", run_local_rbtree, 0},
11462 { "LOCAL-MEMCACHE", run_local_memcache, 0},
11463 { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
11464 { "WBCLIENT-MULTI-PING", run_wbclient_multi_ping, 0},
11465 { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
11466 { "LOCAL-sid_to_string", run_local_sid_to_string, 0},
11467 { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
11468 { "LOCAL-DBTRANS", run_local_dbtrans, 0},
11469 { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
11470 { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
11471 { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
11472 { "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0},
11473 { "LOCAL-IDMAP-TDB-COMMON", run_idmap_tdb_common_test, 0},
11474 { "LOCAL-remove_duplicate_addrs2", run_local_remove_duplicate_addrs2, 0},
11475 { "local-tdb-opener", run_local_tdb_opener, 0 },
11476 { "local-tdb-writer", run_local_tdb_writer, 0 },
11477 { "LOCAL-DBWRAP-CTDB", run_local_dbwrap_ctdb, 0 },
11478 { "LOCAL-BENCH-PTHREADPOOL", run_bench_pthreadpool, 0 },
11479 { "LOCAL-PTHREADPOOL-TEVENT", run_pthreadpool_tevent, 0 },
11480 { "LOCAL-G-LOCK1", run_g_lock1, 0 },
11481 { "LOCAL-G-LOCK2", run_g_lock2, 0 },
11482 { "LOCAL-G-LOCK3", run_g_lock3, 0 },
11483 { "LOCAL-CANONICALIZE-PATH", run_local_canonicalize_path, 0 },
11484 { "qpathinfo-bufsize", run_qpathinfo_bufsize, 0 },
11485 {NULL, NULL, 0}};
11488 * dummy function to satisfy linker dependency
11490 struct tevent_context *winbind_event_context(void);
11491 struct tevent_context *winbind_event_context(void)
11493 return NULL;
11496 /****************************************************************************
11497 run a specified test or "ALL"
11498 ****************************************************************************/
11499 static bool run_test(const char *name)
11501 bool ret = True;
11502 bool result = True;
11503 bool found = False;
11504 int i;
11505 double t;
11506 if (strequal(name,"ALL")) {
11507 for (i=0;torture_ops[i].name;i++) {
11508 run_test(torture_ops[i].name);
11510 found = True;
11513 for (i=0;torture_ops[i].name;i++) {
11514 fstr_sprintf(randomfname, "\\XX%x",
11515 (unsigned)random());
11517 if (strequal(name, torture_ops[i].name)) {
11518 found = True;
11519 printf("Running %s\n", name);
11520 if (torture_ops[i].flags & FLAG_MULTIPROC) {
11521 t = create_procs(torture_ops[i].fn, &result);
11522 if (!result) {
11523 ret = False;
11524 printf("TEST %s FAILED!\n", name);
11526 } else {
11527 struct timeval start;
11528 start = timeval_current();
11529 if (!torture_ops[i].fn(0)) {
11530 ret = False;
11531 printf("TEST %s FAILED!\n", name);
11533 t = timeval_elapsed(&start);
11535 printf("%s took %g secs\n\n", name, t);
11539 if (!found) {
11540 printf("Did not find a test named %s\n", name);
11541 ret = False;
11544 return ret;
11548 static void usage(void)
11550 int i;
11552 printf("WARNING samba4 test suite is much more complete nowadays.\n");
11553 printf("Please use samba4 torture.\n\n");
11555 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
11557 printf("\t-d debuglevel\n");
11558 printf("\t-U user%%pass\n");
11559 printf("\t-k use kerberos\n");
11560 printf("\t-N numprocs\n");
11561 printf("\t-n my_netbios_name\n");
11562 printf("\t-W workgroup\n");
11563 printf("\t-o num_operations\n");
11564 printf("\t-O socket_options\n");
11565 printf("\t-m maximum protocol\n");
11566 printf("\t-L use oplocks\n");
11567 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
11568 printf("\t-A showall\n");
11569 printf("\t-p port\n");
11570 printf("\t-s seed\n");
11571 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
11572 printf("\t-f filename filename to test\n");
11573 printf("\t-e encrypt\n");
11574 printf("\n\n");
11576 printf("tests are:");
11577 for (i=0;torture_ops[i].name;i++) {
11578 printf(" %s", torture_ops[i].name);
11580 printf("\n");
11582 printf("default test is ALL\n");
11584 exit(1);
11587 /****************************************************************************
11588 main program
11589 ****************************************************************************/
11590 int main(int argc,char *argv[])
11592 int opt, i;
11593 char *p;
11594 int gotuser = 0;
11595 int gotpass = 0;
11596 bool correct = True;
11597 TALLOC_CTX *frame = talloc_stackframe();
11598 int seed = time(NULL);
11600 #ifdef HAVE_SETBUFFER
11601 setbuffer(stdout, NULL, 0);
11602 #endif
11604 setup_logging("smbtorture", DEBUG_STDOUT);
11606 smb_init_locale();
11607 fault_setup();
11609 if (is_default_dyn_CONFIGFILE()) {
11610 if(getenv("SMB_CONF_PATH")) {
11611 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
11614 lp_load_global(get_dyn_CONFIGFILE());
11615 load_interfaces();
11617 if (argc < 2) {
11618 usage();
11621 for(p = argv[1]; *p; p++)
11622 if(*p == '\\')
11623 *p = '/';
11625 if (strncmp(argv[1], "//", 2)) {
11626 usage();
11629 fstrcpy(host, &argv[1][2]);
11630 p = strchr_m(&host[2],'/');
11631 if (!p) {
11632 usage();
11634 *p = 0;
11635 fstrcpy(share, p+1);
11637 fstrcpy(myname, get_myname(talloc_tos()));
11638 if (!*myname) {
11639 fprintf(stderr, "Failed to get my hostname.\n");
11640 return 1;
11643 if (*username == 0 && getenv("LOGNAME")) {
11644 fstrcpy(username,getenv("LOGNAME"));
11647 argc--;
11648 argv++;
11650 fstrcpy(workgroup, lp_workgroup());
11652 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
11653 != EOF) {
11654 switch (opt) {
11655 case 'p':
11656 port_to_use = atoi(optarg);
11657 break;
11658 case 's':
11659 seed = atoi(optarg);
11660 break;
11661 case 'W':
11662 fstrcpy(workgroup,optarg);
11663 break;
11664 case 'm':
11665 lp_set_cmdline("client max protocol", optarg);
11666 break;
11667 case 'N':
11668 torture_nprocs = atoi(optarg);
11669 break;
11670 case 'o':
11671 torture_numops = atoi(optarg);
11672 break;
11673 case 'd':
11674 lp_set_cmdline("log level", optarg);
11675 break;
11676 case 'O':
11677 sockops = optarg;
11678 break;
11679 case 'L':
11680 use_oplocks = True;
11681 break;
11682 case 'l':
11683 local_path = optarg;
11684 break;
11685 case 'A':
11686 torture_showall = True;
11687 break;
11688 case 'n':
11689 fstrcpy(myname, optarg);
11690 break;
11691 case 'c':
11692 client_txt = optarg;
11693 break;
11694 case 'e':
11695 do_encrypt = true;
11696 break;
11697 case 'k':
11698 #ifdef HAVE_KRB5
11699 use_kerberos = True;
11700 #else
11701 d_printf("No kerberos support compiled in\n");
11702 exit(1);
11703 #endif
11704 break;
11705 case 'U':
11706 gotuser = 1;
11707 fstrcpy(username,optarg);
11708 p = strchr_m(username,'%');
11709 if (p) {
11710 *p = 0;
11711 fstrcpy(password, p+1);
11712 gotpass = 1;
11714 break;
11715 case 'b':
11716 fstrcpy(multishare_conn_fname, optarg);
11717 use_multishare_conn = True;
11718 break;
11719 case 'B':
11720 torture_blocksize = atoi(optarg);
11721 break;
11722 case 'f':
11723 test_filename = SMB_STRDUP(optarg);
11724 break;
11725 default:
11726 printf("Unknown option %c (%d)\n", (char)opt, opt);
11727 usage();
11731 d_printf("using seed %d\n", seed);
11733 srandom(seed);
11735 if(use_kerberos && !gotuser) gotpass = True;
11737 while (!gotpass) {
11738 char pwd[256] = {0};
11739 int rc;
11741 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
11742 if (rc == 0) {
11743 fstrcpy(password, pwd);
11744 gotpass = 1;
11748 printf("host=%s share=%s user=%s myname=%s\n",
11749 host, share, username, myname);
11751 torture_creds = cli_session_creds_init(frame,
11752 username,
11753 workgroup,
11754 NULL, /* realm */
11755 password,
11756 use_kerberos,
11757 false, /* fallback_after_kerberos */
11758 false, /* use_ccache */
11759 false); /* password_is_nt_hash */
11760 if (torture_creds == NULL) {
11761 d_printf("cli_session_creds_init() failed.\n");
11762 exit(1);
11765 if (argc == optind) {
11766 correct = run_test("ALL");
11767 } else {
11768 for (i=optind;i<argc;i++) {
11769 if (!run_test(argv[i])) {
11770 correct = False;
11775 TALLOC_FREE(frame);
11777 if (correct) {
11778 return(0);
11779 } else {
11780 return(1);