smbd: Make reopen_from_fsp() public
[samba4-gss.git] / source3 / torture / torture.c
blobb6f4312a45e2a71f451ab8fe126bff898852b545
1 /*
2 Unix SMB/CIFS implementation.
3 SMB torture tester
4 Copyright (C) Andrew Tridgell 1997-1998
5 Copyright (C) Jeremy Allison 2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "system/shmem.h"
23 #include "libsmb/namequery.h"
24 #include "wbc_async.h"
25 #include "torture/proto.h"
26 #include "libcli/security/security.h"
27 #include "tldap.h"
28 #include "tldap_util.h"
29 #include "tldap_gensec_bind.h"
30 #include "tldap_tls_connect.h"
31 #include "../librpc/gen_ndr/svcctl.h"
32 #include "../lib/util/memcache.h"
33 #include "nsswitch/winbind_client.h"
34 #include "dbwrap/dbwrap.h"
35 #include "dbwrap/dbwrap_open.h"
36 #include "dbwrap/dbwrap_rbt.h"
37 #include "async_smb.h"
38 #include "libsmb/libsmb.h"
39 #include "libsmb/clirap.h"
40 #include "trans2.h"
41 #include "libsmb/nmblib.h"
42 #include "../lib/util/tevent_ntstatus.h"
43 #include "util_tdb.h"
44 #include "../libcli/smb/read_smb.h"
45 #include "../libcli/smb/smbXcli_base.h"
46 #include "lib/util/sys_rw_data.h"
47 #include "lib/util/base64.h"
48 #include "lib/util/time.h"
49 #include "lib/gencache.h"
50 #include "lib/util/sys_rw.h"
51 #include "lib/util/asn1.h"
52 #include "lib/util/util_file.h"
53 #include "lib/param/param.h"
54 #include "auth/gensec/gensec.h"
55 #include "lib/util/string_wrappers.h"
56 #include "source3/lib/substitute.h"
57 #include "ads.h"
58 #include "source4/lib/tls/tls.h"
59 #include <ldb.h>
61 #include <gnutls/gnutls.h>
62 #include <gnutls/crypto.h>
64 extern char *optarg;
65 extern int optind;
67 fstring host, workgroup, share, password, username, myname;
68 struct cli_credentials *torture_creds;
69 static const char *sockops="TCP_NODELAY";
70 int torture_nprocs=1;
71 static int port_to_use=0;
72 int torture_numops=100;
73 int torture_blocksize=1024*1024;
74 static int procnum; /* records process count number when forking */
75 static struct cli_state *current_cli;
76 static fstring randomfname;
77 static bool use_oplocks;
78 static bool use_level_II_oplocks;
79 static const char *client_txt = "client_oplocks.txt";
80 static bool disable_spnego;
81 static bool use_kerberos;
82 static bool force_dos_errors;
83 static fstring multishare_conn_fname;
84 static bool use_multishare_conn = False;
85 static bool do_encrypt;
86 static const char *local_path = NULL;
87 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
88 char *test_filename;
90 bool torture_showall = False;
92 static double create_procs(bool (*fn)(int), bool *result);
94 /********************************************************************
95 Ensure a connection is encrypted.
96 ********************************************************************/
98 static bool force_cli_encryption(struct cli_state *c,
99 const char *sharename)
101 uint16_t major, minor;
102 uint32_t caplow, caphigh;
103 NTSTATUS status;
105 if (!SERVER_HAS_UNIX_CIFS(c)) {
106 d_printf("Encryption required and "
107 "server that doesn't support "
108 "UNIX extensions - failing connect\n");
109 return false;
112 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
113 &caphigh);
114 if (!NT_STATUS_IS_OK(status)) {
115 d_printf("Encryption required and "
116 "can't get UNIX CIFS extensions "
117 "version from server: %s\n", nt_errstr(status));
118 return false;
121 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
122 d_printf("Encryption required and "
123 "share %s doesn't support "
124 "encryption.\n", sharename);
125 return false;
128 status = cli_smb1_setup_encryption(c, torture_creds);
129 if (!NT_STATUS_IS_OK(status)) {
130 d_printf("Encryption required and "
131 "setup failed with error %s.\n",
132 nt_errstr(status));
133 return false;
136 return true;
140 static struct cli_state *open_nbt_connection(void)
142 struct cli_state *c;
143 NTSTATUS status;
144 int flags = 0;
146 if (disable_spnego) {
147 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
150 if (use_oplocks) {
151 flags |= CLI_FULL_CONNECTION_OPLOCKS;
154 if (use_level_II_oplocks) {
155 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
158 if (force_dos_errors) {
159 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
162 status = cli_connect_nb(NULL,
163 host,
164 NULL,
165 port_to_use,
166 0x20,
167 myname,
168 signing_state,
169 flags,
170 &c);
171 if (!NT_STATUS_IS_OK(status)) {
172 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
173 return NULL;
176 cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
178 return c;
181 /****************************************************************************
182 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
183 ****************************************************************************/
185 static bool cli_bad_session_request(int fd,
186 struct nmb_name *calling, struct nmb_name *called)
188 TALLOC_CTX *frame;
189 uint8_t len_buf[4];
190 struct iovec iov[3];
191 ssize_t len;
192 uint8_t *inbuf;
193 int err;
194 bool ret = false;
195 uint8_t message_type;
196 uint8_t error;
197 struct tevent_context *ev;
198 struct tevent_req *req;
200 frame = talloc_stackframe();
202 iov[0].iov_base = len_buf;
203 iov[0].iov_len = sizeof(len_buf);
205 /* put in the destination name */
207 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
208 called->name_type);
209 if (iov[1].iov_base == NULL) {
210 goto fail;
212 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
213 talloc_get_size(iov[1].iov_base));
215 /* and my name */
217 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
218 calling->name_type);
219 if (iov[2].iov_base == NULL) {
220 goto fail;
222 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
223 talloc_get_size(iov[2].iov_base));
225 /* Deliberately corrupt the name len (first byte) */
226 *((uint8_t *)iov[2].iov_base) = 100;
228 /* send a session request (RFC 1002) */
229 /* setup the packet length
230 * Remove four bytes from the length count, since the length
231 * field in the NBT Session Service header counts the number
232 * of bytes which follow. The cli_send_smb() function knows
233 * about this and accounts for those four bytes.
234 * CRH.
237 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
238 SCVAL(len_buf,0,0x81);
240 len = write_data_iov(fd, iov, 3);
241 if (len == -1) {
242 goto fail;
245 ev = samba_tevent_context_init(frame);
246 if (ev == NULL) {
247 goto fail;
249 req = read_smb_send(frame, ev, fd);
250 if (req == NULL) {
251 goto fail;
253 if (!tevent_req_poll(req, ev)) {
254 goto fail;
256 len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
257 if (len == -1) {
258 errno = err;
259 goto fail;
261 TALLOC_FREE(ev);
263 message_type = CVAL(inbuf, 0);
264 if (message_type != 0x83) {
265 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
266 message_type);
267 goto fail;
270 if (smb_len(inbuf) != 1) {
271 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
272 (int)smb_len(inbuf));
273 goto fail;
276 error = CVAL(inbuf, 4);
277 if (error != 0x82) {
278 d_fprintf(stderr, "Expected error 0x82, got %d\n",
279 (int)error);
280 goto fail;
283 ret = true;
284 fail:
285 TALLOC_FREE(frame);
286 return ret;
289 /* Insert a NULL at the first separator of the given path and return a pointer
290 * to the remainder of the string.
292 static char *
293 terminate_path_at_separator(char * path)
295 char * p;
297 if (!path) {
298 return NULL;
301 if ((p = strchr_m(path, '/'))) {
302 *p = '\0';
303 return p + 1;
306 if ((p = strchr_m(path, '\\'))) {
307 *p = '\0';
308 return p + 1;
311 /* No separator. */
312 return NULL;
316 parse a //server/share type UNC name
318 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
319 char **hostname, char **sharename)
321 char *p;
323 *hostname = *sharename = NULL;
325 if (strncmp(unc_name, "\\\\", 2) &&
326 strncmp(unc_name, "//", 2)) {
327 return False;
330 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
331 p = terminate_path_at_separator(*hostname);
333 if (p && *p) {
334 *sharename = talloc_strdup(mem_ctx, p);
335 terminate_path_at_separator(*sharename);
338 if (*hostname && *sharename) {
339 return True;
342 TALLOC_FREE(*hostname);
343 TALLOC_FREE(*sharename);
344 return False;
347 static bool torture_open_connection_share(struct cli_state **c,
348 const char *hostname,
349 const char *sharename,
350 int flags)
352 NTSTATUS status;
354 status = cli_full_connection_creds(NULL,
356 myname,
357 hostname,
358 NULL, /* dest_ss */
359 port_to_use,
360 sharename,
361 "?????",
362 torture_creds,
363 flags);
364 if (!NT_STATUS_IS_OK(status)) {
365 printf("failed to open share connection: //%s/%s port:%d - %s\n",
366 hostname, sharename, port_to_use, nt_errstr(status));
367 return False;
370 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
372 if (do_encrypt) {
373 return force_cli_encryption(*c,
374 sharename);
376 return True;
379 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
381 char **unc_list = NULL;
382 int num_unc_names = 0;
383 bool result;
385 if (use_multishare_conn==True) {
386 char *h, *s;
387 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
388 if (!unc_list || num_unc_names <= 0) {
389 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
390 exit(1);
393 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
394 NULL, &h, &s)) {
395 printf("Failed to parse UNC name %s\n",
396 unc_list[conn_index % num_unc_names]);
397 TALLOC_FREE(unc_list);
398 exit(1);
401 result = torture_open_connection_share(c, h, s, flags);
403 /* h, s were copied earlier */
404 TALLOC_FREE(unc_list);
405 return result;
408 return torture_open_connection_share(c, host, share, flags);
411 bool torture_open_connection(struct cli_state **c, int conn_index)
413 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
415 if (use_oplocks) {
416 flags |= CLI_FULL_CONNECTION_OPLOCKS;
418 if (use_level_II_oplocks) {
419 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
422 return torture_open_connection_flags(c, conn_index, flags);
425 bool torture_init_connection(struct cli_state **pcli)
427 struct cli_state *cli;
429 cli = open_nbt_connection();
430 if (cli == NULL) {
431 return false;
434 *pcli = cli;
435 return true;
438 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
440 uint16_t old_vuid = cli_state_get_uid(cli);
441 NTSTATUS status;
442 bool ret;
444 cli_state_set_uid(cli, 0);
445 status = cli_session_setup_creds(cli, torture_creds);
446 ret = NT_STATUS_IS_OK(status);
447 *new_vuid = cli_state_get_uid(cli);
448 cli_state_set_uid(cli, old_vuid);
449 return ret;
453 bool torture_close_connection(struct cli_state *c)
455 bool ret = True;
456 NTSTATUS status;
458 status = cli_tdis(c);
459 if (!NT_STATUS_IS_OK(status)) {
460 printf("tdis failed (%s)\n", nt_errstr(status));
461 ret = False;
464 cli_shutdown(c);
466 return ret;
469 void torture_conn_set_sockopt(struct cli_state *cli)
471 smbXcli_conn_set_sockopt(cli->conn, sockops);
474 static NTSTATUS torture_delete_fn(struct file_info *finfo,
475 const char *pattern,
476 void *state)
478 NTSTATUS status;
479 char *filename = NULL;
480 char *dirname = NULL;
481 char *p = NULL;
482 TALLOC_CTX *frame = talloc_stackframe();
483 struct cli_state *cli = (struct cli_state *)state;
485 if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
486 TALLOC_FREE(frame);
487 return NT_STATUS_OK;
490 dirname = talloc_strdup(frame, pattern);
491 if (dirname == NULL) {
492 TALLOC_FREE(frame);
493 return NT_STATUS_NO_MEMORY;
495 p = strrchr_m(dirname, '\\');
496 if (p != NULL) {
497 /* Remove the terminating '\' */
498 *p = '\0';
500 if (dirname[0] != '\0') {
501 filename = talloc_asprintf(frame,
502 "%s\\%s",
503 dirname,
504 finfo->name);
505 } else {
506 filename = talloc_asprintf(frame,
507 "%s",
508 finfo->name);
510 if (filename == NULL) {
511 TALLOC_FREE(frame);
512 return NT_STATUS_NO_MEMORY;
514 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
515 char *subdirname = talloc_asprintf(frame,
516 "%s\\*",
517 filename);
518 if (subdirname == NULL) {
519 TALLOC_FREE(frame);
520 return NT_STATUS_NO_MEMORY;
522 status = cli_list(cli,
523 subdirname,
524 FILE_ATTRIBUTE_DIRECTORY |
525 FILE_ATTRIBUTE_HIDDEN |
526 FILE_ATTRIBUTE_SYSTEM,
527 torture_delete_fn,
528 cli);
529 if (!NT_STATUS_IS_OK(status)) {
530 printf("torture_delete_fn: cli_list "
531 "of %s failed (%s)\n",
532 subdirname,
533 nt_errstr(status));
534 TALLOC_FREE(frame);
535 return status;
537 status = cli_rmdir(cli, filename);
538 } else {
539 status = cli_unlink(cli,
540 filename,
541 FILE_ATTRIBUTE_SYSTEM |
542 FILE_ATTRIBUTE_HIDDEN);
544 if (!NT_STATUS_IS_OK(status)) {
545 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
546 printf("torture_delete_fn: cli_rmdir"
547 " of %s failed (%s)\n",
548 filename,
549 nt_errstr(status));
550 } else {
551 printf("torture_delete_fn: cli_unlink"
552 " of %s failed (%s)\n",
553 filename,
554 nt_errstr(status));
557 TALLOC_FREE(frame);
558 return status;
561 void torture_deltree(struct cli_state *cli, const char *dname)
563 char *mask = NULL;
564 NTSTATUS status;
566 /* It might be a file */
567 (void)cli_unlink(cli,
568 dname,
569 FILE_ATTRIBUTE_SYSTEM |
570 FILE_ATTRIBUTE_HIDDEN);
572 mask = talloc_asprintf(cli,
573 "%s\\*",
574 dname);
575 if (mask == NULL) {
576 printf("torture_deltree: talloc_asprintf failed\n");
577 return;
580 status = cli_list(cli,
581 mask,
582 FILE_ATTRIBUTE_DIRECTORY |
583 FILE_ATTRIBUTE_HIDDEN|
584 FILE_ATTRIBUTE_SYSTEM,
585 torture_delete_fn,
586 cli);
587 if (!NT_STATUS_IS_OK(status)) {
588 printf("torture_deltree: cli_list of %s failed (%s)\n",
589 mask,
590 nt_errstr(status));
592 TALLOC_FREE(mask);
593 status = cli_rmdir(cli, dname);
594 if (!NT_STATUS_IS_OK(status)) {
595 printf("torture_deltree: cli_rmdir of %s failed (%s)\n",
596 dname,
597 nt_errstr(status));
601 /* check if the server produced the expected dos or nt error code */
602 static bool check_both_error(int line, NTSTATUS status,
603 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
605 if (NT_STATUS_IS_DOS(status)) {
606 uint8_t cclass;
607 uint32_t num;
609 /* Check DOS error */
610 cclass = NT_STATUS_DOS_CLASS(status);
611 num = NT_STATUS_DOS_CODE(status);
613 if (eclass != cclass || ecode != num) {
614 printf("unexpected error code class=%d code=%d\n",
615 (int)cclass, (int)num);
616 printf(" expected %d/%d %s (line=%d)\n",
617 (int)eclass, (int)ecode, nt_errstr(nterr), line);
618 return false;
620 } else {
621 /* Check NT error */
622 if (!NT_STATUS_EQUAL(nterr, status)) {
623 printf("unexpected error code %s\n",
624 nt_errstr(status));
625 printf(" expected %s (line=%d)\n",
626 nt_errstr(nterr), line);
627 return false;
631 return true;
635 /* check if the server produced the expected error code */
636 static bool check_error(int line, NTSTATUS status,
637 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
639 if (NT_STATUS_IS_DOS(status)) {
640 uint8_t cclass;
641 uint32_t num;
643 /* Check DOS error */
645 cclass = NT_STATUS_DOS_CLASS(status);
646 num = NT_STATUS_DOS_CODE(status);
648 if (eclass != cclass || ecode != num) {
649 printf("unexpected error code class=%d code=%d\n",
650 (int)cclass, (int)num);
651 printf(" expected %d/%d %s (line=%d)\n",
652 (int)eclass, (int)ecode, nt_errstr(nterr),
653 line);
654 return False;
657 } else {
658 /* Check NT error */
660 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
661 printf("unexpected error code %s\n",
662 nt_errstr(status));
663 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
664 line);
665 return False;
669 return True;
672 NTSTATUS cli_qpathinfo1(struct cli_state *cli,
673 const char *fname,
674 time_t *change_time,
675 time_t *access_time,
676 time_t *write_time,
677 off_t *size,
678 uint32_t *pattr)
680 int timezone = smb1cli_conn_server_time_zone(cli->conn);
681 time_t (*date_fn)(const void *buf, int serverzone) = NULL;
682 uint8_t *rdata = NULL;
683 uint32_t num_rdata;
684 NTSTATUS status;
686 status = cli_qpathinfo(talloc_tos(),
687 cli,
688 fname,
689 SMB_INFO_STANDARD,
691 CLI_BUFFER_SIZE,
692 &rdata,
693 &num_rdata);
694 if (!NT_STATUS_IS_OK(status)) {
695 return status;
697 if (cli->win95) {
698 date_fn = make_unix_date;
699 } else {
700 date_fn = make_unix_date2;
703 if (change_time) {
704 *change_time = date_fn(rdata + 0, timezone);
706 if (access_time) {
707 *access_time = date_fn(rdata + 4, timezone);
709 if (write_time) {
710 *write_time = date_fn(rdata + 8, timezone);
712 if (size) {
713 *size = PULL_LE_U32(rdata, 12);
715 if (pattr) {
716 *pattr = PULL_LE_U16(rdata, l1_attrFile);
718 return NT_STATUS_OK;
721 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
723 NTSTATUS status;
725 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
727 while (!NT_STATUS_IS_OK(status)) {
728 if (!check_both_error(__LINE__, status, ERRDOS,
729 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
730 return false;
733 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
736 return true;
740 static bool rw_torture(struct cli_state *c)
742 const char *lockfname = "\\torture.lck";
743 fstring fname;
744 uint16_t fnum;
745 uint16_t fnum2;
746 pid_t pid2, pid = getpid();
747 int i, j;
748 char buf[1024];
749 bool correct = True;
750 size_t nread = 0;
751 NTSTATUS status;
753 memset(buf, '\0', sizeof(buf));
755 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
756 DENY_NONE, &fnum2);
757 if (!NT_STATUS_IS_OK(status)) {
758 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
760 if (!NT_STATUS_IS_OK(status)) {
761 printf("open of %s failed (%s)\n",
762 lockfname, nt_errstr(status));
763 return False;
766 for (i=0;i<torture_numops;i++) {
767 unsigned n = (unsigned)sys_random()%10;
769 if (i % 10 == 0) {
770 printf("%d\r", i); fflush(stdout);
772 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
774 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
775 return False;
778 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
779 DENY_ALL, &fnum);
780 if (!NT_STATUS_IS_OK(status)) {
781 printf("open failed (%s)\n", nt_errstr(status));
782 correct = False;
783 break;
786 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
787 sizeof(pid), NULL);
788 if (!NT_STATUS_IS_OK(status)) {
789 printf("write failed (%s)\n", nt_errstr(status));
790 correct = False;
793 for (j=0;j<50;j++) {
794 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
795 sizeof(pid)+(j*sizeof(buf)),
796 sizeof(buf), NULL);
797 if (!NT_STATUS_IS_OK(status)) {
798 printf("write failed (%s)\n",
799 nt_errstr(status));
800 correct = False;
804 pid2 = 0;
806 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
807 &nread);
808 if (!NT_STATUS_IS_OK(status)) {
809 printf("read failed (%s)\n", nt_errstr(status));
810 correct = false;
811 } else if (nread != sizeof(pid)) {
812 printf("read/write compare failed: "
813 "recv %ld req %ld\n", (unsigned long)nread,
814 (unsigned long)sizeof(pid));
815 correct = false;
818 if (pid2 != pid) {
819 printf("data corruption!\n");
820 correct = False;
823 status = cli_close(c, fnum);
824 if (!NT_STATUS_IS_OK(status)) {
825 printf("close failed (%s)\n", nt_errstr(status));
826 correct = False;
829 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
830 if (!NT_STATUS_IS_OK(status)) {
831 printf("unlink failed (%s)\n", nt_errstr(status));
832 correct = False;
835 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
836 if (!NT_STATUS_IS_OK(status)) {
837 printf("unlock failed (%s)\n", nt_errstr(status));
838 correct = False;
842 cli_close(c, fnum2);
843 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
845 printf("%d\n", i);
847 return correct;
850 static bool run_torture(int dummy)
852 struct cli_state *cli;
853 bool ret;
855 cli = current_cli;
857 smbXcli_conn_set_sockopt(cli->conn, sockops);
859 ret = rw_torture(cli);
861 if (!torture_close_connection(cli)) {
862 ret = False;
865 return ret;
868 static bool rw_torture3(struct cli_state *c, char *lockfname)
870 uint16_t fnum = (uint16_t)-1;
871 unsigned int i = 0;
872 char buf[131072];
873 char buf_rd[131072];
874 unsigned count;
875 unsigned countprev = 0;
876 size_t sent = 0;
877 bool correct = True;
878 NTSTATUS status = NT_STATUS_OK;
880 srandom(1);
881 for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
883 SIVAL(buf, i, sys_random());
886 if (procnum == 0)
888 status = cli_unlink(
889 c, lockfname,
890 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
891 if (!NT_STATUS_IS_OK(status)) {
892 printf("unlink failed (%s) (normal, this file should "
893 "not exist)\n", nt_errstr(status));
896 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
897 DENY_NONE, &fnum);
898 if (!NT_STATUS_IS_OK(status)) {
899 printf("first open read/write of %s failed (%s)\n",
900 lockfname, nt_errstr(status));
901 return False;
904 else
906 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
908 status = cli_openx(c, lockfname, O_RDONLY,
909 DENY_NONE, &fnum);
910 if (NT_STATUS_IS_OK(status)) {
911 break;
913 smb_msleep(10);
915 if (!NT_STATUS_IS_OK(status)) {
916 printf("second open read-only of %s failed (%s)\n",
917 lockfname, nt_errstr(status));
918 return False;
922 i = 0;
923 for (count = 0; count < sizeof(buf); count += sent)
925 if (count >= countprev) {
926 printf("%d %8d\r", i, count);
927 fflush(stdout);
928 i++;
929 countprev += (sizeof(buf) / 20);
932 if (procnum == 0)
934 sent = ((unsigned)sys_random()%(20))+ 1;
935 if (sent > sizeof(buf) - count)
937 sent = sizeof(buf) - count;
940 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
941 count, sent, NULL);
942 if (!NT_STATUS_IS_OK(status)) {
943 printf("write failed (%s)\n",
944 nt_errstr(status));
945 correct = False;
948 else
950 status = cli_read(c, fnum, buf_rd+count, count,
951 sizeof(buf)-count, &sent);
952 if(!NT_STATUS_IS_OK(status)) {
953 printf("read failed offset:%d size:%ld (%s)\n",
954 count, (unsigned long)sizeof(buf)-count,
955 nt_errstr(status));
956 correct = False;
957 sent = 0;
958 } else if (sent > 0) {
959 if (memcmp(buf_rd+count, buf+count, sent) != 0)
961 printf("read/write compare failed\n");
962 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
963 correct = False;
964 break;
971 status = cli_close(c, fnum);
972 if (!NT_STATUS_IS_OK(status)) {
973 printf("close failed (%s)\n", nt_errstr(status));
974 correct = False;
977 return correct;
980 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
982 const char *lockfname = "\\torture2.lck";
983 uint16_t fnum1;
984 uint16_t fnum2;
985 int i;
986 char buf[131072];
987 char buf_rd[131072];
988 bool correct = True;
989 size_t bytes_read;
990 NTSTATUS status;
992 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
993 if (!NT_STATUS_IS_OK(status)) {
994 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
997 status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
998 DENY_NONE, &fnum1);
999 if (!NT_STATUS_IS_OK(status)) {
1000 printf("first open read/write of %s failed (%s)\n",
1001 lockfname, nt_errstr(status));
1002 return False;
1005 status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
1006 if (!NT_STATUS_IS_OK(status)) {
1007 printf("second open read-only of %s failed (%s)\n",
1008 lockfname, nt_errstr(status));
1009 cli_close(c1, fnum1);
1010 return False;
1013 for (i = 0; i < torture_numops; i++)
1015 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
1016 if (i % 10 == 0) {
1017 printf("%d\r", i); fflush(stdout);
1020 generate_random_buffer((unsigned char *)buf, buf_size);
1022 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
1023 buf_size, NULL);
1024 if (!NT_STATUS_IS_OK(status)) {
1025 printf("write failed (%s)\n", nt_errstr(status));
1026 correct = False;
1027 break;
1030 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
1031 if(!NT_STATUS_IS_OK(status)) {
1032 printf("read failed (%s)\n", nt_errstr(status));
1033 correct = false;
1034 break;
1035 } else if (bytes_read != buf_size) {
1036 printf("read failed\n");
1037 printf("read %ld, expected %ld\n",
1038 (unsigned long)bytes_read,
1039 (unsigned long)buf_size);
1040 correct = False;
1041 break;
1044 if (memcmp(buf_rd, buf, buf_size) != 0)
1046 printf("read/write compare failed\n");
1047 correct = False;
1048 break;
1052 status = cli_close(c2, fnum2);
1053 if (!NT_STATUS_IS_OK(status)) {
1054 printf("close failed (%s)\n", nt_errstr(status));
1055 correct = False;
1058 status = cli_close(c1, fnum1);
1059 if (!NT_STATUS_IS_OK(status)) {
1060 printf("close failed (%s)\n", nt_errstr(status));
1061 correct = False;
1064 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1065 if (!NT_STATUS_IS_OK(status)) {
1066 printf("unlink failed (%s)\n", nt_errstr(status));
1067 correct = False;
1070 return correct;
1073 static bool run_readwritetest(int dummy)
1075 struct cli_state *cli1, *cli2;
1076 bool test1, test2 = False;
1078 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1079 return False;
1081 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1082 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1084 printf("starting readwritetest\n");
1086 test1 = rw_torture2(cli1, cli2);
1087 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
1089 if (test1) {
1090 test2 = rw_torture2(cli1, cli1);
1091 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
1094 if (!torture_close_connection(cli1)) {
1095 test1 = False;
1098 if (!torture_close_connection(cli2)) {
1099 test2 = False;
1102 return (test1 && test2);
1105 static bool run_readwritemulti(int dummy)
1107 struct cli_state *cli;
1108 bool test;
1110 cli = current_cli;
1112 smbXcli_conn_set_sockopt(cli->conn, sockops);
1114 printf("run_readwritemulti: fname %s\n", randomfname);
1115 test = rw_torture3(cli, randomfname);
1117 if (!torture_close_connection(cli)) {
1118 test = False;
1121 return test;
1124 static bool run_readwritelarge_internal(void)
1126 static struct cli_state *cli1;
1127 uint16_t fnum1;
1128 const char *lockfname = "\\large.dat";
1129 off_t fsize;
1130 char buf[126*1024];
1131 bool correct = True;
1132 NTSTATUS status;
1134 if (!torture_open_connection(&cli1, 0)) {
1135 return False;
1137 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1138 memset(buf,'\0',sizeof(buf));
1140 printf("starting readwritelarge_internal\n");
1142 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1144 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1145 DENY_NONE, &fnum1);
1146 if (!NT_STATUS_IS_OK(status)) {
1147 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1148 return False;
1151 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1153 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1154 NULL, NULL, NULL);
1155 if (!NT_STATUS_IS_OK(status)) {
1156 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1157 correct = False;
1160 if (fsize == sizeof(buf))
1161 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1162 (unsigned long)fsize);
1163 else {
1164 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1165 (unsigned long)fsize);
1166 correct = False;
1169 status = cli_close(cli1, fnum1);
1170 if (!NT_STATUS_IS_OK(status)) {
1171 printf("close failed (%s)\n", nt_errstr(status));
1172 correct = False;
1175 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1176 if (!NT_STATUS_IS_OK(status)) {
1177 printf("unlink failed (%s)\n", nt_errstr(status));
1178 correct = False;
1181 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1182 DENY_NONE, &fnum1);
1183 if (!NT_STATUS_IS_OK(status)) {
1184 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1185 return False;
1188 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1190 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1191 NULL, NULL, NULL);
1192 if (!NT_STATUS_IS_OK(status)) {
1193 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1194 correct = False;
1197 if (fsize == sizeof(buf))
1198 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1199 (unsigned long)fsize);
1200 else {
1201 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1202 (unsigned long)fsize);
1203 correct = False;
1206 status = cli_close(cli1, fnum1);
1207 if (!NT_STATUS_IS_OK(status)) {
1208 printf("close failed (%s)\n", nt_errstr(status));
1209 correct = False;
1212 if (!torture_close_connection(cli1)) {
1213 correct = False;
1215 return correct;
1218 static bool run_readwritelarge(int dummy)
1220 return run_readwritelarge_internal();
1223 static bool run_readwritelarge_signtest(int dummy)
1225 bool ret;
1226 signing_state = SMB_SIGNING_REQUIRED;
1227 ret = run_readwritelarge_internal();
1228 signing_state = SMB_SIGNING_DEFAULT;
1229 return ret;
1232 int line_count = 0;
1233 int nbio_id;
1235 #define ival(s) strtol(s, NULL, 0)
1237 /* run a test that simulates an approximate netbench client load */
1238 static bool run_netbench(int client)
1240 struct cli_state *cli;
1241 int i;
1242 char line[1024];
1243 char cname[20];
1244 FILE *f;
1245 const char *params[20];
1246 bool correct = True;
1248 cli = current_cli;
1250 nbio_id = client;
1252 smbXcli_conn_set_sockopt(cli->conn, sockops);
1254 nb_setup(cli);
1256 slprintf(cname,sizeof(cname)-1, "client%d", client);
1258 f = fopen(client_txt, "r");
1260 if (!f) {
1261 perror(client_txt);
1262 return False;
1265 while (fgets(line, sizeof(line)-1, f)) {
1266 char *saveptr;
1267 line_count++;
1269 line[strlen(line)-1] = 0;
1271 /* printf("[%d] %s\n", line_count, line); */
1273 all_string_sub(line,"client1", cname, sizeof(line));
1275 /* parse the command parameters */
1276 params[0] = strtok_r(line, " ", &saveptr);
1277 i = 0;
1278 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1280 params[i] = "";
1282 if (i < 2) continue;
1284 if (!strncmp(params[0],"SMB", 3)) {
1285 printf("ERROR: You are using a dbench 1 load file\n");
1286 exit(1);
1289 if (!strcmp(params[0],"NTCreateX")) {
1290 nb_createx(params[1], ival(params[2]), ival(params[3]),
1291 ival(params[4]));
1292 } else if (!strcmp(params[0],"Close")) {
1293 nb_close(ival(params[1]));
1294 } else if (!strcmp(params[0],"Rename")) {
1295 nb_rename(params[1], params[2]);
1296 } else if (!strcmp(params[0],"Unlink")) {
1297 nb_unlink(params[1]);
1298 } else if (!strcmp(params[0],"Deltree")) {
1299 nb_deltree(params[1]);
1300 } else if (!strcmp(params[0],"Rmdir")) {
1301 nb_rmdir(params[1]);
1302 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1303 nb_qpathinfo(params[1]);
1304 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1305 nb_qfileinfo(ival(params[1]));
1306 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1307 nb_qfsinfo(ival(params[1]));
1308 } else if (!strcmp(params[0],"FIND_FIRST")) {
1309 nb_findfirst(params[1]);
1310 } else if (!strcmp(params[0],"WriteX")) {
1311 nb_writex(ival(params[1]),
1312 ival(params[2]), ival(params[3]), ival(params[4]));
1313 } else if (!strcmp(params[0],"ReadX")) {
1314 nb_readx(ival(params[1]),
1315 ival(params[2]), ival(params[3]), ival(params[4]));
1316 } else if (!strcmp(params[0],"Flush")) {
1317 nb_flush(ival(params[1]));
1318 } else {
1319 printf("Unknown operation %s\n", params[0]);
1320 exit(1);
1323 fclose(f);
1325 nb_cleanup();
1327 if (!torture_close_connection(cli)) {
1328 correct = False;
1331 return correct;
1335 /* run a test that simulates an approximate netbench client load */
1336 static bool run_nbench(int dummy)
1338 double t;
1339 bool correct = True;
1341 nbio_shmem(torture_nprocs);
1343 nbio_id = -1;
1345 signal(SIGALRM, nb_alarm);
1346 alarm(1);
1347 t = create_procs(run_netbench, &correct);
1348 alarm(0);
1350 printf("\nThroughput %g MB/sec\n",
1351 1.0e-6 * nbio_total() / t);
1352 return correct;
1357 This test checks for two things:
1359 1) correct support for retaining locks over a close (ie. the server
1360 must not use posix semantics)
1361 2) support for lock timeouts
1363 static bool run_locktest1(int dummy)
1365 struct cli_state *cli1, *cli2;
1366 const char *fname = "\\lockt1.lck";
1367 uint16_t fnum1, fnum2, fnum3;
1368 time_t t1, t2;
1369 unsigned lock_timeout;
1370 NTSTATUS status;
1372 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1373 return False;
1375 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1376 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1378 printf("starting locktest1\n");
1380 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1382 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1383 &fnum1);
1384 if (!NT_STATUS_IS_OK(status)) {
1385 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1386 return False;
1389 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1390 if (!NT_STATUS_IS_OK(status)) {
1391 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1392 return False;
1395 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1396 if (!NT_STATUS_IS_OK(status)) {
1397 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1398 return False;
1401 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1402 if (!NT_STATUS_IS_OK(status)) {
1403 printf("lock1 failed (%s)\n", nt_errstr(status));
1404 return false;
1407 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1408 if (NT_STATUS_IS_OK(status)) {
1409 printf("lock2 succeeded! This is a locking bug\n");
1410 return false;
1411 } else {
1412 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1413 NT_STATUS_LOCK_NOT_GRANTED)) {
1414 return false;
1418 lock_timeout = (1 + (random() % 20));
1419 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1420 t1 = time(NULL);
1421 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1422 if (NT_STATUS_IS_OK(status)) {
1423 printf("lock3 succeeded! This is a locking bug\n");
1424 return false;
1425 } else {
1426 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1427 NT_STATUS_FILE_LOCK_CONFLICT)) {
1428 return false;
1431 t2 = time(NULL);
1433 if (ABS(t2 - t1) < lock_timeout-1) {
1434 printf("error: This server appears not to support timed lock requests\n");
1437 printf("server slept for %u seconds for a %u second timeout\n",
1438 (unsigned int)(t2-t1), lock_timeout);
1440 status = cli_close(cli1, fnum2);
1441 if (!NT_STATUS_IS_OK(status)) {
1442 printf("close1 failed (%s)\n", nt_errstr(status));
1443 return False;
1446 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1447 if (NT_STATUS_IS_OK(status)) {
1448 printf("lock4 succeeded! This is a locking bug\n");
1449 return false;
1450 } else {
1451 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1452 NT_STATUS_FILE_LOCK_CONFLICT)) {
1453 return false;
1457 status = cli_close(cli1, fnum1);
1458 if (!NT_STATUS_IS_OK(status)) {
1459 printf("close2 failed (%s)\n", nt_errstr(status));
1460 return False;
1463 status = cli_close(cli2, fnum3);
1464 if (!NT_STATUS_IS_OK(status)) {
1465 printf("close3 failed (%s)\n", nt_errstr(status));
1466 return False;
1469 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1470 if (!NT_STATUS_IS_OK(status)) {
1471 printf("unlink failed (%s)\n", nt_errstr(status));
1472 return False;
1476 if (!torture_close_connection(cli1)) {
1477 return False;
1480 if (!torture_close_connection(cli2)) {
1481 return False;
1484 printf("Passed locktest1\n");
1485 return True;
1489 this checks to see if a secondary tconx can use open files from an
1490 earlier tconx
1492 static bool run_tcon_test(int dummy)
1494 static struct cli_state *cli;
1495 const char *fname = "\\tcontest.tmp";
1496 uint16_t fnum1;
1497 uint32_t cnum1, cnum2, cnum3;
1498 struct smbXcli_tcon *orig_tcon = NULL;
1499 char *orig_share = NULL;
1500 uint16_t vuid1, vuid2;
1501 char buf[4];
1502 bool ret = True;
1503 NTSTATUS status;
1505 memset(buf, '\0', sizeof(buf));
1507 if (!torture_open_connection(&cli, 0)) {
1508 return False;
1510 smbXcli_conn_set_sockopt(cli->conn, sockops);
1512 printf("starting tcontest\n");
1514 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1516 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1517 if (!NT_STATUS_IS_OK(status)) {
1518 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1519 return False;
1522 cnum1 = cli_state_get_tid(cli);
1523 vuid1 = cli_state_get_uid(cli);
1525 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1526 if (!NT_STATUS_IS_OK(status)) {
1527 printf("initial write failed (%s)", nt_errstr(status));
1528 return False;
1531 cli_state_save_tcon_share(cli, &orig_tcon, &orig_share);
1533 status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1534 if (!NT_STATUS_IS_OK(status)) {
1535 printf("%s refused 2nd tree connect (%s)\n", host,
1536 nt_errstr(status));
1537 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1538 cli_shutdown(cli);
1539 return False;
1542 cnum2 = cli_state_get_tid(cli);
1543 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1544 vuid2 = cli_state_get_uid(cli) + 1;
1546 /* try a write with the wrong tid */
1547 cli_state_set_tid(cli, cnum2);
1549 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1550 if (NT_STATUS_IS_OK(status)) {
1551 printf("* server allows write with wrong TID\n");
1552 ret = False;
1553 } else {
1554 printf("server fails write with wrong TID : %s\n",
1555 nt_errstr(status));
1559 /* try a write with an invalid tid */
1560 cli_state_set_tid(cli, cnum3);
1562 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1563 if (NT_STATUS_IS_OK(status)) {
1564 printf("* server allows write with invalid TID\n");
1565 ret = False;
1566 } else {
1567 printf("server fails write with invalid TID : %s\n",
1568 nt_errstr(status));
1571 /* try a write with an invalid vuid */
1572 cli_state_set_uid(cli, vuid2);
1573 cli_state_set_tid(cli, cnum1);
1575 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1576 if (NT_STATUS_IS_OK(status)) {
1577 printf("* server allows write with invalid VUID\n");
1578 ret = False;
1579 } else {
1580 printf("server fails write with invalid VUID : %s\n",
1581 nt_errstr(status));
1584 cli_state_set_tid(cli, cnum1);
1585 cli_state_set_uid(cli, vuid1);
1587 status = cli_close(cli, fnum1);
1588 if (!NT_STATUS_IS_OK(status)) {
1589 printf("close failed (%s)\n", nt_errstr(status));
1590 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1591 cli_shutdown(cli);
1592 return False;
1595 cli_state_set_tid(cli, cnum2);
1597 status = cli_tdis(cli);
1598 if (!NT_STATUS_IS_OK(status)) {
1599 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1600 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1601 cli_shutdown(cli);
1602 return False;
1605 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1607 cli_state_set_tid(cli, cnum1);
1609 if (!torture_close_connection(cli)) {
1610 return False;
1613 return ret;
1618 checks for old style tcon support
1620 static bool run_tcon2_test(int dummy)
1622 static struct cli_state *cli;
1623 uint16_t cnum, max_xmit;
1624 char *service;
1625 NTSTATUS status;
1627 if (!torture_open_connection(&cli, 0)) {
1628 return False;
1630 smbXcli_conn_set_sockopt(cli->conn, sockops);
1632 printf("starting tcon2 test\n");
1634 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1635 return false;
1638 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1640 SAFE_FREE(service);
1642 if (!NT_STATUS_IS_OK(status)) {
1643 printf("tcon2 failed : %s\n", nt_errstr(status));
1644 } else {
1645 printf("tcon OK : max_xmit=%d cnum=%d\n",
1646 (int)max_xmit, (int)cnum);
1649 if (!torture_close_connection(cli)) {
1650 return False;
1653 printf("Passed tcon2 test\n");
1654 return True;
1657 static bool tcon_devtest(struct cli_state *cli,
1658 const char *myshare, const char *devtype,
1659 const char *return_devtype,
1660 NTSTATUS expected_error)
1662 NTSTATUS status;
1663 bool ret;
1665 status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1667 if (NT_STATUS_IS_OK(expected_error)) {
1668 if (NT_STATUS_IS_OK(status)) {
1669 if (return_devtype != NULL &&
1670 strequal(cli->dev, return_devtype)) {
1671 ret = True;
1672 } else {
1673 printf("tconX to share %s with type %s "
1674 "succeeded but returned the wrong "
1675 "device type (got [%s] but should have got [%s])\n",
1676 myshare, devtype, cli->dev, return_devtype);
1677 ret = False;
1679 } else {
1680 printf("tconX to share %s with type %s "
1681 "should have succeeded but failed\n",
1682 myshare, devtype);
1683 ret = False;
1685 cli_tdis(cli);
1686 } else {
1687 if (NT_STATUS_IS_OK(status)) {
1688 printf("tconx to share %s with type %s "
1689 "should have failed but succeeded\n",
1690 myshare, devtype);
1691 ret = False;
1692 } else {
1693 if (NT_STATUS_EQUAL(status, expected_error)) {
1694 ret = True;
1695 } else {
1696 printf("Returned unexpected error\n");
1697 ret = False;
1701 return ret;
1705 checks for correct tconX support
1707 static bool run_tcon_devtype_test(int dummy)
1709 static struct cli_state *cli1 = NULL;
1710 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1711 NTSTATUS status;
1712 bool ret = True;
1714 status = cli_full_connection_creds(NULL,
1715 &cli1,
1716 myname,
1717 host,
1718 NULL, /* dest_ss */
1719 port_to_use,
1720 NULL, /* service */
1721 NULL, /* service_type */
1722 torture_creds,
1723 flags);
1725 if (!NT_STATUS_IS_OK(status)) {
1726 printf("could not open connection\n");
1727 return False;
1730 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1731 ret = False;
1733 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1734 ret = False;
1736 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1737 ret = False;
1739 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1740 ret = False;
1742 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1743 ret = False;
1745 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1746 ret = False;
1748 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1749 ret = False;
1751 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1752 ret = False;
1754 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1755 ret = False;
1757 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1758 ret = False;
1760 cli_shutdown(cli1);
1762 if (ret)
1763 printf("Passed tcondevtest\n");
1765 return ret;
1770 This test checks that
1772 1) the server supports multiple locking contexts on the one SMB
1773 connection, distinguished by PID.
1775 2) the server correctly fails overlapping locks made by the same PID (this
1776 goes against POSIX behaviour, which is why it is tricky to implement)
1778 3) the server denies unlock requests by an incorrect client PID
1780 static bool run_locktest2(int dummy)
1782 static struct cli_state *cli;
1783 const char *fname = "\\lockt2.lck";
1784 uint16_t fnum1, fnum2, fnum3;
1785 bool correct = True;
1786 NTSTATUS status;
1788 if (!torture_open_connection(&cli, 0)) {
1789 return False;
1792 smbXcli_conn_set_sockopt(cli->conn, sockops);
1794 printf("starting locktest2\n");
1796 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1798 cli_setpid(cli, 1);
1800 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1801 if (!NT_STATUS_IS_OK(status)) {
1802 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1803 return False;
1806 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1807 if (!NT_STATUS_IS_OK(status)) {
1808 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1809 return False;
1812 cli_setpid(cli, 2);
1814 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1815 if (!NT_STATUS_IS_OK(status)) {
1816 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1817 return False;
1820 cli_setpid(cli, 1);
1822 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1823 if (!NT_STATUS_IS_OK(status)) {
1824 printf("lock1 failed (%s)\n", nt_errstr(status));
1825 return false;
1828 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1829 if (NT_STATUS_IS_OK(status)) {
1830 printf("WRITE lock1 succeeded! This is a locking bug\n");
1831 correct = false;
1832 } else {
1833 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1834 NT_STATUS_LOCK_NOT_GRANTED)) {
1835 return false;
1839 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1840 if (NT_STATUS_IS_OK(status)) {
1841 printf("WRITE lock2 succeeded! This is a locking bug\n");
1842 correct = false;
1843 } else {
1844 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1845 NT_STATUS_LOCK_NOT_GRANTED)) {
1846 return false;
1850 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1851 if (NT_STATUS_IS_OK(status)) {
1852 printf("READ lock2 succeeded! This is a locking bug\n");
1853 correct = false;
1854 } else {
1855 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1856 NT_STATUS_FILE_LOCK_CONFLICT)) {
1857 return false;
1861 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1862 if (!NT_STATUS_IS_OK(status)) {
1863 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1865 cli_setpid(cli, 2);
1866 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1867 printf("unlock at 100 succeeded! This is a locking bug\n");
1868 correct = False;
1871 status = cli_unlock(cli, fnum1, 0, 4);
1872 if (NT_STATUS_IS_OK(status)) {
1873 printf("unlock1 succeeded! This is a locking bug\n");
1874 correct = false;
1875 } else {
1876 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1877 NT_STATUS_RANGE_NOT_LOCKED)) {
1878 return false;
1882 status = cli_unlock(cli, fnum1, 0, 8);
1883 if (NT_STATUS_IS_OK(status)) {
1884 printf("unlock2 succeeded! This is a locking bug\n");
1885 correct = false;
1886 } else {
1887 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1888 NT_STATUS_RANGE_NOT_LOCKED)) {
1889 return false;
1893 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1894 if (NT_STATUS_IS_OK(status)) {
1895 printf("lock3 succeeded! This is a locking bug\n");
1896 correct = false;
1897 } else {
1898 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1899 NT_STATUS_LOCK_NOT_GRANTED)) {
1900 return false;
1904 cli_setpid(cli, 1);
1906 status = cli_close(cli, fnum1);
1907 if (!NT_STATUS_IS_OK(status)) {
1908 printf("close1 failed (%s)\n", nt_errstr(status));
1909 return False;
1912 status = cli_close(cli, fnum2);
1913 if (!NT_STATUS_IS_OK(status)) {
1914 printf("close2 failed (%s)\n", nt_errstr(status));
1915 return False;
1918 status = cli_close(cli, fnum3);
1919 if (!NT_STATUS_IS_OK(status)) {
1920 printf("close3 failed (%s)\n", nt_errstr(status));
1921 return False;
1924 if (!torture_close_connection(cli)) {
1925 correct = False;
1928 printf("locktest2 finished\n");
1930 return correct;
1935 This test checks that
1937 1) the server supports the full offset range in lock requests
1939 static bool run_locktest3(int dummy)
1941 static struct cli_state *cli1, *cli2;
1942 const char *fname = "\\lockt3.lck";
1943 uint16_t fnum1, fnum2;
1944 int i;
1945 uint32_t offset;
1946 bool correct = True;
1947 NTSTATUS status;
1949 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1951 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1952 return False;
1954 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1955 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1957 printf("starting locktest3\n");
1959 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1961 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1962 &fnum1);
1963 if (!NT_STATUS_IS_OK(status)) {
1964 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1965 return False;
1968 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1969 if (!NT_STATUS_IS_OK(status)) {
1970 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1971 return False;
1974 for (offset=i=0;i<torture_numops;i++) {
1975 NEXT_OFFSET;
1977 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1978 if (!NT_STATUS_IS_OK(status)) {
1979 printf("lock1 %d failed (%s)\n",
1981 nt_errstr(status));
1982 return False;
1985 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1986 if (!NT_STATUS_IS_OK(status)) {
1987 printf("lock2 %d failed (%s)\n",
1989 nt_errstr(status));
1990 return False;
1994 for (offset=i=0;i<torture_numops;i++) {
1995 NEXT_OFFSET;
1997 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1998 if (NT_STATUS_IS_OK(status)) {
1999 printf("error: lock1 %d succeeded!\n", i);
2000 return False;
2003 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
2004 if (NT_STATUS_IS_OK(status)) {
2005 printf("error: lock2 %d succeeded!\n", i);
2006 return False;
2009 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
2010 if (NT_STATUS_IS_OK(status)) {
2011 printf("error: lock3 %d succeeded!\n", i);
2012 return False;
2015 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
2016 if (NT_STATUS_IS_OK(status)) {
2017 printf("error: lock4 %d succeeded!\n", i);
2018 return False;
2022 for (offset=i=0;i<torture_numops;i++) {
2023 NEXT_OFFSET;
2025 status = cli_unlock(cli1, fnum1, offset-1, 1);
2026 if (!NT_STATUS_IS_OK(status)) {
2027 printf("unlock1 %d failed (%s)\n",
2029 nt_errstr(status));
2030 return False;
2033 status = cli_unlock(cli2, fnum2, offset-2, 1);
2034 if (!NT_STATUS_IS_OK(status)) {
2035 printf("unlock2 %d failed (%s)\n",
2037 nt_errstr(status));
2038 return False;
2042 status = cli_close(cli1, fnum1);
2043 if (!NT_STATUS_IS_OK(status)) {
2044 printf("close1 failed (%s)\n", nt_errstr(status));
2045 return False;
2048 status = cli_close(cli2, fnum2);
2049 if (!NT_STATUS_IS_OK(status)) {
2050 printf("close2 failed (%s)\n", nt_errstr(status));
2051 return False;
2054 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2055 if (!NT_STATUS_IS_OK(status)) {
2056 printf("unlink failed (%s)\n", nt_errstr(status));
2057 return False;
2060 if (!torture_close_connection(cli1)) {
2061 correct = False;
2064 if (!torture_close_connection(cli2)) {
2065 correct = False;
2068 printf("finished locktest3\n");
2070 return correct;
2073 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
2074 char *buf, off_t offset, size_t size,
2075 size_t *nread, size_t expect)
2077 NTSTATUS status;
2078 size_t l_nread;
2080 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
2082 if(!NT_STATUS_IS_OK(status)) {
2083 return false;
2084 } else if (l_nread != expect) {
2085 return false;
2088 if (nread) {
2089 *nread = l_nread;
2092 return true;
2095 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2096 printf("** "); correct = False; \
2100 looks at overlapping locks
2102 static bool run_locktest4(int dummy)
2104 static struct cli_state *cli1, *cli2;
2105 const char *fname = "\\lockt4.lck";
2106 uint16_t fnum1, fnum2, f;
2107 bool ret;
2108 char buf[1000];
2109 bool correct = True;
2110 NTSTATUS status;
2112 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2113 return False;
2116 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2117 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2119 printf("starting locktest4\n");
2121 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2123 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2124 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2126 memset(buf, 0, sizeof(buf));
2128 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2129 NULL);
2130 if (!NT_STATUS_IS_OK(status)) {
2131 printf("Failed to create file: %s\n", nt_errstr(status));
2132 correct = False;
2133 goto fail;
2136 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2137 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
2138 EXPECTED(ret, False);
2139 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2141 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2142 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2143 EXPECTED(ret, True);
2144 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2146 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2147 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2148 EXPECTED(ret, False);
2149 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2151 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2152 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2153 EXPECTED(ret, True);
2154 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2156 ret = (cli_setpid(cli1, 1),
2157 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2158 (cli_setpid(cli1, 2),
2159 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2160 EXPECTED(ret, False);
2161 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2163 ret = (cli_setpid(cli1, 1),
2164 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2165 (cli_setpid(cli1, 2),
2166 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2167 EXPECTED(ret, True);
2168 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2170 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2171 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2172 EXPECTED(ret, True);
2173 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2175 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2176 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2177 EXPECTED(ret, False);
2178 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2180 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2181 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2182 EXPECTED(ret, False);
2183 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2185 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2186 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2187 EXPECTED(ret, True);
2188 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2190 ret = (cli_setpid(cli1, 1),
2191 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2192 (cli_setpid(cli1, 2),
2193 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2194 EXPECTED(ret, False);
2195 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2197 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2198 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2199 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2200 EXPECTED(ret, False);
2201 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2204 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2205 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2206 EXPECTED(ret, False);
2207 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2209 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2210 ret = NT_STATUS_IS_OK(status);
2211 if (ret) {
2212 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2213 NULL);
2214 ret = NT_STATUS_IS_OK(status);
2216 EXPECTED(ret, False);
2217 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2220 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2221 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2222 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2223 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2224 EXPECTED(ret, True);
2225 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2228 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2229 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2230 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2231 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2232 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2233 150, 4, NULL))) &&
2234 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2235 EXPECTED(ret, True);
2236 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2238 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2239 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2240 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2241 160, 4, NULL)) &&
2242 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2243 EXPECTED(ret, True);
2244 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2246 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2247 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2248 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2249 170, 4, NULL)) &&
2250 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2251 EXPECTED(ret, True);
2252 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2254 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2255 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2256 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2257 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2258 190, 4, NULL)) &&
2259 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2260 EXPECTED(ret, True);
2261 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2263 cli_close(cli1, fnum1);
2264 cli_close(cli2, fnum2);
2265 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2266 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2267 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2268 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2269 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2270 NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2271 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2272 cli_close(cli1, f);
2273 cli_close(cli1, fnum1);
2274 EXPECTED(ret, True);
2275 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2277 fail:
2278 cli_close(cli1, fnum1);
2279 cli_close(cli2, fnum2);
2280 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2281 torture_close_connection(cli1);
2282 torture_close_connection(cli2);
2284 printf("finished locktest4\n");
2285 return correct;
2289 looks at lock upgrade/downgrade.
2291 static bool run_locktest5(int dummy)
2293 static struct cli_state *cli1, *cli2;
2294 const char *fname = "\\lockt5.lck";
2295 uint16_t fnum1, fnum2, fnum3;
2296 bool ret;
2297 char buf[1000];
2298 bool correct = True;
2299 NTSTATUS status;
2301 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2302 return False;
2305 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2306 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2308 printf("starting locktest5\n");
2310 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2312 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2313 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2314 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2316 memset(buf, 0, sizeof(buf));
2318 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2319 NULL);
2320 if (!NT_STATUS_IS_OK(status)) {
2321 printf("Failed to create file: %s\n", nt_errstr(status));
2322 correct = False;
2323 goto fail;
2326 /* Check for NT bug... */
2327 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2328 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2329 cli_close(cli1, fnum1);
2330 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2331 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2332 ret = NT_STATUS_IS_OK(status);
2333 EXPECTED(ret, True);
2334 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2335 cli_close(cli1, fnum1);
2336 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2337 cli_unlock(cli1, fnum3, 0, 1);
2339 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2340 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2341 EXPECTED(ret, True);
2342 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2344 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2345 ret = NT_STATUS_IS_OK(status);
2346 EXPECTED(ret, False);
2348 printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2350 /* Unlock the process 2 lock. */
2351 cli_unlock(cli2, fnum2, 0, 4);
2353 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2354 ret = NT_STATUS_IS_OK(status);
2355 EXPECTED(ret, False);
2357 printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2359 /* Unlock the process 1 fnum3 lock. */
2360 cli_unlock(cli1, fnum3, 0, 4);
2362 /* Stack 2 more locks here. */
2363 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2364 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2366 EXPECTED(ret, True);
2367 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2369 /* Unlock the first process lock, then check this was the WRITE lock that was
2370 removed. */
2372 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2373 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2375 EXPECTED(ret, True);
2376 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2378 /* Unlock the process 2 lock. */
2379 cli_unlock(cli2, fnum2, 0, 4);
2381 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2383 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2384 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2385 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2387 EXPECTED(ret, True);
2388 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2390 /* Ensure the next unlock fails. */
2391 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2392 EXPECTED(ret, False);
2393 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2395 /* Ensure connection 2 can get a write lock. */
2396 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2397 ret = NT_STATUS_IS_OK(status);
2398 EXPECTED(ret, True);
2400 printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2403 fail:
2404 cli_close(cli1, fnum1);
2405 cli_close(cli2, fnum2);
2406 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2407 if (!torture_close_connection(cli1)) {
2408 correct = False;
2410 if (!torture_close_connection(cli2)) {
2411 correct = False;
2414 printf("finished locktest5\n");
2416 return correct;
2420 tries the unusual lockingX locktype bits
2422 static bool run_locktest6(int dummy)
2424 static struct cli_state *cli;
2425 const char *fname[1] = { "\\lock6.txt" };
2426 int i;
2427 uint16_t fnum;
2428 NTSTATUS status;
2430 if (!torture_open_connection(&cli, 0)) {
2431 return False;
2434 smbXcli_conn_set_sockopt(cli->conn, sockops);
2436 printf("starting locktest6\n");
2438 for (i=0;i<1;i++) {
2439 printf("Testing %s\n", fname[i]);
2441 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2443 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2444 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2445 cli_close(cli, fnum);
2446 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2448 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2449 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2450 cli_close(cli, fnum);
2451 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2453 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2456 torture_close_connection(cli);
2458 printf("finished locktest6\n");
2459 return True;
2462 static bool run_locktest7(int dummy)
2464 struct cli_state *cli1;
2465 const char *fname = "\\lockt7.lck";
2466 uint16_t fnum1;
2467 char buf[200];
2468 bool correct = False;
2469 size_t nread;
2470 NTSTATUS status;
2472 if (!torture_open_connection(&cli1, 0)) {
2473 return False;
2476 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2478 printf("starting locktest7\n");
2480 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2482 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2484 memset(buf, 0, sizeof(buf));
2486 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2487 NULL);
2488 if (!NT_STATUS_IS_OK(status)) {
2489 printf("Failed to create file: %s\n", nt_errstr(status));
2490 goto fail;
2493 cli_setpid(cli1, 1);
2495 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2496 if (!NT_STATUS_IS_OK(status)) {
2497 printf("Unable to apply read lock on range 130:4, "
2498 "error was %s\n", nt_errstr(status));
2499 goto fail;
2500 } else {
2501 printf("pid1 successfully locked range 130:4 for READ\n");
2504 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2505 if (!NT_STATUS_IS_OK(status)) {
2506 printf("pid1 unable to read the range 130:4, error was %s\n",
2507 nt_errstr(status));
2508 goto fail;
2509 } else if (nread != 4) {
2510 printf("pid1 unable to read the range 130:4, "
2511 "recv %ld req %d\n", (unsigned long)nread, 4);
2512 goto fail;
2513 } else {
2514 printf("pid1 successfully read the range 130:4\n");
2517 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2518 if (!NT_STATUS_IS_OK(status)) {
2519 printf("pid1 unable to write to the range 130:4, error was "
2520 "%s\n", nt_errstr(status));
2521 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2522 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2523 goto fail;
2525 } else {
2526 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2527 goto fail;
2530 cli_setpid(cli1, 2);
2532 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2533 if (!NT_STATUS_IS_OK(status)) {
2534 printf("pid2 unable to read the range 130:4, error was %s\n",
2535 nt_errstr(status));
2536 goto fail;
2537 } else if (nread != 4) {
2538 printf("pid2 unable to read the range 130:4, "
2539 "recv %ld req %d\n", (unsigned long)nread, 4);
2540 goto fail;
2541 } else {
2542 printf("pid2 successfully read the range 130:4\n");
2545 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2546 if (!NT_STATUS_IS_OK(status)) {
2547 printf("pid2 unable to write to the range 130:4, error was "
2548 "%s\n", nt_errstr(status));
2549 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2550 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2551 goto fail;
2553 } else {
2554 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2555 goto fail;
2558 cli_setpid(cli1, 1);
2559 cli_unlock(cli1, fnum1, 130, 4);
2561 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2562 if (!NT_STATUS_IS_OK(status)) {
2563 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2564 goto fail;
2565 } else {
2566 printf("pid1 successfully locked range 130:4 for WRITE\n");
2569 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2570 if (!NT_STATUS_IS_OK(status)) {
2571 printf("pid1 unable to read the range 130:4, error was %s\n",
2572 nt_errstr(status));
2573 goto fail;
2574 } else if (nread != 4) {
2575 printf("pid1 unable to read the range 130:4, "
2576 "recv %ld req %d\n", (unsigned long)nread, 4);
2577 goto fail;
2578 } else {
2579 printf("pid1 successfully read the range 130:4\n");
2582 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2583 if (!NT_STATUS_IS_OK(status)) {
2584 printf("pid1 unable to write to the range 130:4, error was "
2585 "%s\n", nt_errstr(status));
2586 goto fail;
2587 } else {
2588 printf("pid1 successfully wrote to the range 130:4\n");
2591 cli_setpid(cli1, 2);
2593 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2594 if (!NT_STATUS_IS_OK(status)) {
2595 printf("pid2 unable to read the range 130:4, error was "
2596 "%s\n", nt_errstr(status));
2597 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2598 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2599 goto fail;
2601 } else {
2602 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2603 (unsigned long)nread);
2604 goto fail;
2607 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2608 if (!NT_STATUS_IS_OK(status)) {
2609 printf("pid2 unable to write to the range 130:4, error was "
2610 "%s\n", nt_errstr(status));
2611 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2612 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2613 goto fail;
2615 } else {
2616 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2617 goto fail;
2620 cli_unlock(cli1, fnum1, 130, 0);
2621 correct = True;
2623 fail:
2624 cli_close(cli1, fnum1);
2625 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2626 torture_close_connection(cli1);
2628 printf("finished locktest7\n");
2629 return correct;
2633 * This demonstrates a problem with our use of GPFS share modes: A file
2634 * descriptor sitting in the pending close queue holding a GPFS share mode
2635 * blocks opening a file another time. Happens with Word 2007 temp files.
2636 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2637 * open is denied with NT_STATUS_SHARING_VIOLATION.
2640 static bool run_locktest8(int dummy)
2642 struct cli_state *cli1;
2643 const char *fname = "\\lockt8.lck";
2644 uint16_t fnum1, fnum2;
2645 char buf[200];
2646 bool correct = False;
2647 NTSTATUS status;
2649 if (!torture_open_connection(&cli1, 0)) {
2650 return False;
2653 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2655 printf("starting locktest8\n");
2657 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2659 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2660 &fnum1);
2661 if (!NT_STATUS_IS_OK(status)) {
2662 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2663 return false;
2666 memset(buf, 0, sizeof(buf));
2668 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2669 if (!NT_STATUS_IS_OK(status)) {
2670 d_fprintf(stderr, "cli_openx second time returned %s\n",
2671 nt_errstr(status));
2672 goto fail;
2675 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2676 if (!NT_STATUS_IS_OK(status)) {
2677 printf("Unable to apply read lock on range 1:1, error was "
2678 "%s\n", nt_errstr(status));
2679 goto fail;
2682 status = cli_close(cli1, fnum1);
2683 if (!NT_STATUS_IS_OK(status)) {
2684 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2685 goto fail;
2688 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2689 if (!NT_STATUS_IS_OK(status)) {
2690 d_fprintf(stderr, "cli_openx third time returned %s\n",
2691 nt_errstr(status));
2692 goto fail;
2695 correct = true;
2697 fail:
2698 cli_close(cli1, fnum1);
2699 cli_close(cli1, fnum2);
2700 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2701 torture_close_connection(cli1);
2703 printf("finished locktest8\n");
2704 return correct;
2708 * This test is designed to be run in conjunction with
2709 * external NFS or POSIX locks taken in the filesystem.
2710 * It checks that the smbd server will block until the
2711 * lock is released and then acquire it. JRA.
2714 static bool got_alarm;
2715 static struct cli_state *alarm_cli;
2717 static void alarm_handler(int dummy)
2719 got_alarm = True;
2722 static void alarm_handler_parent(int dummy)
2724 smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2727 static void do_local_lock(const char *fname, int read_fd, int write_fd)
2729 int fd;
2730 char c = '\0';
2731 struct flock lock;
2732 const char *local_pathname = NULL;
2733 int ret;
2735 local_pathname = talloc_asprintf(talloc_tos(),
2736 "%s/%s", local_path, fname);
2737 if (!local_pathname) {
2738 printf("child: alloc fail\n");
2739 exit(1);
2742 unlink(local_pathname);
2743 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2744 if (fd == -1) {
2745 printf("child: open of %s failed %s.\n",
2746 local_pathname, strerror(errno));
2747 exit(1);
2750 /* Now take a fcntl lock. */
2751 lock.l_type = F_WRLCK;
2752 lock.l_whence = SEEK_SET;
2753 lock.l_start = 0;
2754 lock.l_len = 4;
2755 lock.l_pid = getpid();
2757 ret = fcntl(fd,F_SETLK,&lock);
2758 if (ret == -1) {
2759 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2760 local_pathname, strerror(errno));
2761 exit(1);
2762 } else {
2763 printf("child: got lock 0:4 on file %s.\n",
2764 local_pathname );
2765 fflush(stdout);
2768 CatchSignal(SIGALRM, alarm_handler);
2769 alarm(5);
2770 /* Signal the parent. */
2771 if (write(write_fd, &c, 1) != 1) {
2772 printf("child: start signal fail %s.\n",
2773 strerror(errno));
2774 exit(1);
2776 alarm(0);
2778 alarm(10);
2779 /* Wait for the parent to be ready. */
2780 if (read(read_fd, &c, 1) != 1) {
2781 printf("child: reply signal fail %s.\n",
2782 strerror(errno));
2783 exit(1);
2785 alarm(0);
2787 sleep(5);
2788 close(fd);
2789 printf("child: released lock 0:4 on file %s.\n",
2790 local_pathname );
2791 fflush(stdout);
2792 exit(0);
2795 static bool _run_locktest9X(const char *fname, int timeout)
2797 struct cli_state *cli1;
2798 char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2799 uint16_t fnum;
2800 bool correct = False;
2801 int pipe_in[2], pipe_out[2];
2802 pid_t child_pid;
2803 char c = '\0';
2804 int ret;
2805 struct timeval start;
2806 double seconds;
2807 NTSTATUS status;
2809 printf("starting locktest9X: %s\n", fname);
2811 if (local_path == NULL) {
2812 d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2813 return false;
2816 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2817 return false;
2820 child_pid = fork();
2821 if (child_pid == -1) {
2822 return false;
2825 if (child_pid == 0) {
2826 /* Child. */
2827 do_local_lock(fname, pipe_out[0], pipe_in[1]);
2828 exit(0);
2831 close(pipe_out[0]);
2832 close(pipe_in[1]);
2833 pipe_out[0] = -1;
2834 pipe_in[1] = -1;
2836 /* Parent. */
2837 ret = read(pipe_in[0], &c, 1);
2838 if (ret != 1) {
2839 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2840 strerror(errno));
2841 return false;
2844 if (!torture_open_connection(&cli1, 0)) {
2845 return false;
2848 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2850 status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2851 &fnum);
2852 if (!NT_STATUS_IS_OK(status)) {
2853 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2854 return false;
2857 /* Ensure the child has the lock. */
2858 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2859 if (NT_STATUS_IS_OK(status)) {
2860 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2861 goto fail;
2862 } else {
2863 d_printf("Child has the lock.\n");
2866 /* Tell the child to wait 5 seconds then exit. */
2867 ret = write(pipe_out[1], &c, 1);
2868 if (ret != 1) {
2869 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2870 strerror(errno));
2871 goto fail;
2874 /* Wait 20 seconds for the lock. */
2875 alarm_cli = cli1;
2876 CatchSignal(SIGALRM, alarm_handler_parent);
2877 alarm(20);
2879 start = timeval_current();
2881 status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2882 if (!NT_STATUS_IS_OK(status)) {
2883 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2884 "%s\n", nt_errstr(status));
2885 goto fail_nofd;
2887 alarm(0);
2889 seconds = timeval_elapsed(&start);
2891 printf("Parent got the lock after %.2f seconds.\n",
2892 seconds);
2894 status = cli_close(cli1, fnum);
2895 if (!NT_STATUS_IS_OK(status)) {
2896 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2897 goto fail;
2900 correct = true;
2902 fail:
2903 cli_close(cli1, fnum);
2904 torture_close_connection(cli1);
2906 fail_nofd:
2908 printf("finished locktest9X: %s\n", fname);
2909 return correct;
2912 static bool run_locktest9a(int dummy)
2914 return _run_locktest9X("lock9a.dat", -1);
2917 static bool run_locktest9b(int dummy)
2919 return _run_locktest9X("lock9b.dat", 10000);
2922 struct locktest10_state {
2923 bool ok;
2924 bool done;
2927 static void locktest10_lockingx_done(struct tevent_req *subreq);
2928 static void locktest10_read_andx_done(struct tevent_req *subreq);
2930 static bool run_locktest10(int dummy)
2932 struct tevent_context *ev = NULL;
2933 struct cli_state *cli1 = NULL;
2934 struct cli_state *cli2 = NULL;
2935 struct smb1_lock_element lck = { 0 };
2936 struct tevent_req *reqs[2] = { NULL };
2937 struct tevent_req *smbreqs[2] = { NULL };
2938 const char fname[] = "\\lockt10.lck";
2939 uint16_t fnum1, fnum2;
2940 bool ret = false;
2941 bool ok;
2942 uint8_t data = 1;
2943 struct locktest10_state state = { .ok = true };
2944 NTSTATUS status;
2946 printf("starting locktest10\n");
2948 ev = samba_tevent_context_init(NULL);
2949 if (ev == NULL) {
2950 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2951 goto done;
2954 ok = torture_open_connection(&cli1, 0);
2955 if (!ok) {
2956 goto done;
2958 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2960 ok = torture_open_connection(&cli2, 1);
2961 if (!ok) {
2962 goto done;
2964 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2966 status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2967 if (!NT_STATUS_IS_OK(status)) {
2968 d_fprintf(stderr,
2969 "cli_openx failed: %s\n",
2970 nt_errstr(status));
2971 goto done;
2974 status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2975 if (!NT_STATUS_IS_OK(status)) {
2976 d_fprintf(stderr,
2977 "cli_writeall failed: %s\n",
2978 nt_errstr(status));
2979 goto done;
2982 status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2983 if (!NT_STATUS_IS_OK(status)) {
2984 d_fprintf(stderr,
2985 "cli_openx failed: %s\n",
2986 nt_errstr(status));
2987 goto done;
2990 status = cli_locktype(
2991 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2992 if (!NT_STATUS_IS_OK(status)) {
2993 d_fprintf(stderr,
2994 "cli_locktype failed: %s\n",
2995 nt_errstr(status));
2996 goto done;
2999 lck = (struct smb1_lock_element) {
3000 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
3003 reqs[0] = cli_lockingx_create(
3004 ev, /* mem_ctx */
3005 ev, /* tevent_context */
3006 cli1, /* cli */
3007 fnum1, /* fnum */
3008 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3009 0, /* newoplocklevel */
3010 1, /* timeout */
3011 0, /* num_unlocks */
3012 NULL, /* unlocks */
3013 1, /* num_locks */
3014 &lck, /* locks */
3015 &smbreqs[0]); /* psmbreq */
3016 if (reqs[0] == NULL) {
3017 d_fprintf(stderr, "cli_lockingx_create failed\n");
3018 goto done;
3020 tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
3022 reqs[1] = cli_read_andx_create(
3023 ev, /* mem_ctx */
3024 ev, /* ev */
3025 cli1, /* cli */
3026 fnum1, /* fnum */
3027 0, /* offset */
3028 1, /* size */
3029 &smbreqs[1]); /* psmbreq */
3030 if (reqs[1] == NULL) {
3031 d_fprintf(stderr, "cli_read_andx_create failed\n");
3032 goto done;
3034 tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
3036 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
3037 if (!NT_STATUS_IS_OK(status)) {
3038 d_fprintf(stderr,
3039 "smb1cli_req_chain_submit failed: %s\n",
3040 nt_errstr(status));
3041 goto done;
3044 while (!state.done) {
3045 tevent_loop_once(ev);
3048 torture_close_connection(cli1);
3050 if (state.ok) {
3051 ret = true;
3053 done:
3054 return ret;
3057 static void locktest10_lockingx_done(struct tevent_req *subreq)
3059 struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3060 NTSTATUS status;
3062 status = cli_lockingx_recv(subreq);
3063 TALLOC_FREE(subreq);
3065 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3066 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3067 state->ok = false;
3071 static void locktest10_read_andx_done(struct tevent_req *subreq)
3073 struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3074 ssize_t received = -1;
3075 uint8_t *rcvbuf = NULL;
3076 NTSTATUS status;
3078 status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3080 if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
3081 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
3082 state->ok = false;
3085 state->done = true;
3086 TALLOC_FREE(subreq);
3089 static bool run_locktest11(int dummy)
3091 struct cli_state *cli1;
3092 const char *fname = "\\lockt11.lck";
3093 NTSTATUS status;
3094 uint16_t fnum;
3095 bool ret = false;
3097 if (!torture_open_connection(&cli1, 0)) {
3098 return false;
3101 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3103 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3105 status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
3106 if (!NT_STATUS_IS_OK(status)) {
3107 d_fprintf(stderr,
3108 "cli_openx returned %s\n",
3109 nt_errstr(status));
3110 return false;
3114 * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3115 * returns NT_STATUS_OK
3118 status = cli_lockingx(
3119 cli1, /* cli */
3120 fnum, /* fnum */
3121 LOCKING_ANDX_CANCEL_LOCK, /* typeoflock */
3122 0, /* newoplocklevel */
3123 0, /* timeout */
3124 0, /* num_unlocks */
3125 NULL, /* unlocks */
3126 0, /* num_locks */
3127 NULL); /* locks */
3129 if (!NT_STATUS_IS_OK(status)) {
3130 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
3131 goto fail;
3134 ret = true;
3135 fail:
3136 cli_close(cli1, fnum);
3137 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3139 return ret;
3142 struct deferred_close_state {
3143 struct tevent_context *ev;
3144 struct cli_state *cli;
3145 uint16_t fnum;
3148 static void deferred_close_waited(struct tevent_req *subreq);
3149 static void deferred_close_done(struct tevent_req *subreq);
3151 static struct tevent_req *deferred_close_send(
3152 TALLOC_CTX *mem_ctx,
3153 struct tevent_context *ev,
3154 int wait_secs,
3155 struct cli_state *cli,
3156 uint16_t fnum)
3158 struct tevent_req *req = NULL, *subreq = NULL;
3159 struct deferred_close_state *state = NULL;
3160 struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
3162 req = tevent_req_create(
3163 mem_ctx, &state, struct deferred_close_state);
3164 if (req == NULL) {
3165 return NULL;
3167 state->ev = ev;
3168 state->cli = cli;
3169 state->fnum = fnum;
3171 subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
3172 if (tevent_req_nomem(subreq, req)) {
3173 return tevent_req_post(req, ev);
3175 tevent_req_set_callback(subreq, deferred_close_waited, req);
3176 return req;
3179 static void deferred_close_waited(struct tevent_req *subreq)
3181 struct tevent_req *req = tevent_req_callback_data(
3182 subreq, struct tevent_req);
3183 struct deferred_close_state *state = tevent_req_data(
3184 req, struct deferred_close_state);
3185 bool ok;
3187 ok = tevent_wakeup_recv(subreq);
3188 TALLOC_FREE(subreq);
3189 if (!ok) {
3190 tevent_req_oom(req);
3191 return;
3194 subreq = cli_close_send(state, state->ev, state->cli, state->fnum, 0);
3195 if (tevent_req_nomem(subreq, req)) {
3196 return;
3198 tevent_req_set_callback(subreq, deferred_close_done, req);
3201 static void deferred_close_done(struct tevent_req *subreq)
3203 NTSTATUS status = cli_close_recv(subreq);
3204 tevent_req_simple_finish_ntstatus(subreq, status);
3207 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3209 return tevent_req_simple_recv_ntstatus(req);
3212 struct lockread_state {
3213 struct smb1_lock_element lck;
3214 struct tevent_req *reqs[2];
3215 struct tevent_req *smbreqs[2];
3216 NTSTATUS lock_status;
3217 NTSTATUS read_status;
3218 uint8_t *readbuf;
3221 static void lockread_lockingx_done(struct tevent_req *subreq);
3222 static void lockread_read_andx_done(struct tevent_req *subreq);
3224 static struct tevent_req *lockread_send(
3225 TALLOC_CTX *mem_ctx,
3226 struct tevent_context *ev,
3227 struct cli_state *cli,
3228 uint16_t fnum)
3230 struct tevent_req *req = NULL;
3231 struct lockread_state *state = NULL;
3232 NTSTATUS status;
3234 req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3235 if (req == NULL) {
3236 return NULL;
3239 state->lck = (struct smb1_lock_element) {
3240 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3243 state->reqs[0] = cli_lockingx_create(
3244 ev, /* mem_ctx */
3245 ev, /* tevent_context */
3246 cli, /* cli */
3247 fnum, /* fnum */
3248 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3249 0, /* newoplocklevel */
3250 10000, /* timeout */
3251 0, /* num_unlocks */
3252 NULL, /* unlocks */
3253 1, /* num_locks */
3254 &state->lck, /* locks */
3255 &state->smbreqs[0]); /* psmbreq */
3256 if (tevent_req_nomem(state->reqs[0], req)) {
3257 return tevent_req_post(req, ev);
3259 tevent_req_set_callback(
3260 state->reqs[0], lockread_lockingx_done, req);
3262 state->reqs[1] = cli_read_andx_create(
3263 ev, /* mem_ctx */
3264 ev, /* ev */
3265 cli, /* cli */
3266 fnum, /* fnum */
3267 0, /* offset */
3268 1, /* size */
3269 &state->smbreqs[1]); /* psmbreq */
3270 if (tevent_req_nomem(state->reqs[1], req)) {
3271 return tevent_req_post(req, ev);
3273 tevent_req_set_callback(
3274 state->reqs[1], lockread_read_andx_done, req);
3276 status = smb1cli_req_chain_submit(state->smbreqs, 2);
3277 if (tevent_req_nterror(req, status)) {
3278 return tevent_req_post(req, ev);
3280 return req;
3283 static void lockread_lockingx_done(struct tevent_req *subreq)
3285 struct tevent_req *req = tevent_req_callback_data(
3286 subreq, struct tevent_req);
3287 struct lockread_state *state = tevent_req_data(
3288 req, struct lockread_state);
3289 state->lock_status = cli_lockingx_recv(subreq);
3290 TALLOC_FREE(subreq);
3291 d_fprintf(stderr,
3292 "lockingx returned %s\n",
3293 nt_errstr(state->lock_status));
3296 static void lockread_read_andx_done(struct tevent_req *subreq)
3298 struct tevent_req *req = tevent_req_callback_data(
3299 subreq, struct tevent_req);
3300 struct lockread_state *state = tevent_req_data(
3301 req, struct lockread_state);
3302 ssize_t received = -1;
3303 uint8_t *rcvbuf = NULL;
3305 state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3307 d_fprintf(stderr,
3308 "read returned %s\n",
3309 nt_errstr(state->read_status));
3311 if (!NT_STATUS_IS_OK(state->read_status)) {
3312 TALLOC_FREE(subreq);
3313 tevent_req_done(req);
3314 return;
3317 if (received > 0) {
3318 state->readbuf = talloc_memdup(state, rcvbuf, received);
3319 TALLOC_FREE(subreq);
3320 if (tevent_req_nomem(state->readbuf, req)) {
3321 return;
3324 TALLOC_FREE(subreq);
3325 tevent_req_done(req);
3328 static NTSTATUS lockread_recv(
3329 struct tevent_req *req,
3330 NTSTATUS *lock_status,
3331 NTSTATUS *read_status,
3332 TALLOC_CTX *mem_ctx,
3333 uint8_t **read_buf)
3335 struct lockread_state *state = tevent_req_data(
3336 req, struct lockread_state);
3337 NTSTATUS status;
3339 if (tevent_req_is_nterror(req, &status)) {
3340 return status;
3343 *lock_status = state->lock_status;
3344 *read_status = state->read_status;
3345 if (state->readbuf != NULL) {
3346 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3347 } else {
3348 *read_buf = NULL;
3351 return NT_STATUS_OK;
3354 struct lock12_state {
3355 uint8_t dummy;
3358 static void lock12_closed(struct tevent_req *subreq);
3359 static void lock12_read(struct tevent_req *subreq);
3361 static struct tevent_req *lock12_send(
3362 TALLOC_CTX *mem_ctx,
3363 struct tevent_context *ev,
3364 struct cli_state *cli,
3365 uint16_t fnum1,
3366 uint16_t fnum2)
3368 struct tevent_req *req = NULL, *subreq = NULL;
3369 struct lock12_state *state = NULL;
3371 req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3372 if (req == NULL) {
3373 return NULL;
3376 subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3377 if (tevent_req_nomem(subreq, req)) {
3378 return tevent_req_post(req, ev);
3380 tevent_req_set_callback(subreq, lock12_closed, req);
3382 subreq = lockread_send(state, ev, cli, fnum2);
3383 if (tevent_req_nomem(subreq, req)) {
3384 return tevent_req_post(req, ev);
3386 tevent_req_set_callback(subreq, lock12_read, req);
3388 return req;
3391 static void lock12_closed(struct tevent_req *subreq)
3393 struct tevent_req *req = tevent_req_callback_data(
3394 subreq, struct tevent_req);
3395 NTSTATUS status;
3397 status = deferred_close_recv(subreq);
3398 TALLOC_FREE(subreq);
3399 DBG_DEBUG("close returned %s\n", nt_errstr(status));
3400 if (tevent_req_nterror(req, status)) {
3401 return;
3405 static void lock12_read(struct tevent_req *subreq)
3407 struct tevent_req *req = tevent_req_callback_data(
3408 subreq, struct tevent_req);
3409 struct lock12_state *state = tevent_req_data(
3410 req, struct lock12_state);
3411 NTSTATUS status, lock_status, read_status;
3412 uint8_t *buf = NULL;
3414 status = lockread_recv(
3415 subreq, &lock_status, &read_status, state, &buf);
3416 TALLOC_FREE(subreq);
3417 if (tevent_req_nterror(req, status) ||
3418 tevent_req_nterror(req, lock_status) ||
3419 tevent_req_nterror(req, read_status)) {
3420 return;
3422 tevent_req_done(req);
3425 static NTSTATUS lock12_recv(struct tevent_req *req)
3428 NTSTATUS status;
3430 if (tevent_req_is_nterror(req, &status)) {
3431 return status;
3433 return NT_STATUS_OK;
3436 static bool run_locktest12(int dummy)
3438 struct tevent_context *ev = NULL;
3439 struct tevent_req *req = NULL;
3440 struct cli_state *cli = NULL;
3441 const char fname[] = "\\lockt12.lck";
3442 uint16_t fnum1, fnum2;
3443 bool ret = false;
3444 bool ok;
3445 uint8_t data = 1;
3446 NTSTATUS status;
3448 printf("starting locktest12\n");
3450 ev = samba_tevent_context_init(NULL);
3451 if (ev == NULL) {
3452 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3453 goto done;
3456 ok = torture_open_connection(&cli, 0);
3457 if (!ok) {
3458 goto done;
3460 smbXcli_conn_set_sockopt(cli->conn, sockops);
3462 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3463 if (!NT_STATUS_IS_OK(status)) {
3464 d_fprintf(stderr,
3465 "cli_openx failed: %s\n",
3466 nt_errstr(status));
3467 goto done;
3470 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3471 if (!NT_STATUS_IS_OK(status)) {
3472 d_fprintf(stderr,
3473 "cli_openx failed: %s\n",
3474 nt_errstr(status));
3475 goto done;
3478 status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3479 if (!NT_STATUS_IS_OK(status)) {
3480 d_fprintf(stderr,
3481 "cli_writeall failed: %s\n",
3482 nt_errstr(status));
3483 goto done;
3486 status = cli_locktype(
3487 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3488 if (!NT_STATUS_IS_OK(status)) {
3489 d_fprintf(stderr,
3490 "cli_locktype failed: %s\n",
3491 nt_errstr(status));
3492 goto done;
3495 req = lock12_send(ev, ev, cli, fnum1, fnum2);
3496 if (req == NULL) {
3497 d_fprintf(stderr, "lock12_send failed\n");
3498 goto done;
3501 ok = tevent_req_poll_ntstatus(req, ev, &status);
3502 if (!ok) {
3503 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3504 goto done;
3507 if (!NT_STATUS_IS_OK(status)) {
3508 d_fprintf(stderr,
3509 "tevent_req_poll_ntstatus returned %s\n",
3510 nt_errstr(status));
3511 goto done;
3514 status = lock12_recv(req);
3515 if (!NT_STATUS_IS_OK(status)) {
3516 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3517 goto done;
3520 ret = true;
3521 done:
3522 if (cli != NULL) {
3523 torture_close_connection(cli);
3525 return ret;
3528 struct lock_ntcancel_state {
3529 struct timeval start;
3530 struct smb1_lock_element lck;
3531 struct tevent_req *subreq;
3534 static void lock_ntcancel_waited(struct tevent_req *subreq);
3535 static void lock_ntcancel_done(struct tevent_req *subreq);
3537 static struct tevent_req *lock_ntcancel_send(
3538 TALLOC_CTX *mem_ctx,
3539 struct tevent_context *ev,
3540 struct cli_state *cli,
3541 uint16_t fnum)
3543 struct tevent_req *req = NULL, *subreq = NULL;
3544 struct lock_ntcancel_state *state = NULL;
3546 req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3547 if (req == NULL) {
3548 return NULL;
3550 state->lck = (struct smb1_lock_element) {
3551 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3553 state->start = timeval_current();
3555 state->subreq = cli_lockingx_send(
3556 state, /* mem_ctx */
3557 ev, /* tevent_context */
3558 cli, /* cli */
3559 fnum, /* fnum */
3560 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3561 0, /* newoplocklevel */
3562 10000, /* timeout */
3563 0, /* num_unlocks */
3564 NULL, /* unlocks */
3565 1, /* num_locks */
3566 &state->lck); /* locks */
3567 if (tevent_req_nomem(state->subreq, req)) {
3568 return tevent_req_post(req, ev);
3570 tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3572 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3573 if (tevent_req_nomem(subreq, req)) {
3574 return tevent_req_post(req, ev);
3576 tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3577 return req;
3580 static void lock_ntcancel_waited(struct tevent_req *subreq)
3582 struct tevent_req *req = tevent_req_callback_data(
3583 subreq, struct tevent_req);
3584 struct lock_ntcancel_state *state = tevent_req_data(
3585 req, struct lock_ntcancel_state);
3586 bool ok;
3588 ok = tevent_wakeup_recv(subreq);
3589 TALLOC_FREE(subreq);
3590 if (!ok) {
3591 tevent_req_oom(req);
3592 return;
3595 ok = tevent_req_cancel(state->subreq);
3596 if (!ok) {
3597 d_fprintf(stderr, "Could not cancel subreq\n");
3598 tevent_req_oom(req);
3599 return;
3603 static void lock_ntcancel_done(struct tevent_req *subreq)
3605 struct tevent_req *req = tevent_req_callback_data(
3606 subreq, struct tevent_req);
3607 struct lock_ntcancel_state *state = tevent_req_data(
3608 req, struct lock_ntcancel_state);
3609 NTSTATUS status;
3610 double elapsed;
3612 status = cli_lockingx_recv(subreq);
3613 TALLOC_FREE(subreq);
3615 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3616 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3617 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3618 return;
3621 elapsed = timeval_elapsed(&state->start);
3623 if (elapsed > 3) {
3624 d_printf("cli_lockingx was too slow, cancel did not work\n");
3625 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3626 return;
3629 tevent_req_done(req);
3632 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3634 return tevent_req_simple_recv_ntstatus(req);
3637 static bool run_locktest13(int dummy)
3639 struct tevent_context *ev = NULL;
3640 struct tevent_req *req = NULL;
3641 struct cli_state *cli = NULL;
3642 const char fname[] = "\\lockt13.lck";
3643 uint16_t fnum1, fnum2;
3644 bool ret = false;
3645 bool ok;
3646 uint8_t data = 1;
3647 NTSTATUS status;
3649 printf("starting locktest13\n");
3651 ev = samba_tevent_context_init(NULL);
3652 if (ev == NULL) {
3653 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3654 goto done;
3657 ok = torture_open_connection(&cli, 0);
3658 if (!ok) {
3659 goto done;
3661 smbXcli_conn_set_sockopt(cli->conn, sockops);
3663 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3664 if (!NT_STATUS_IS_OK(status)) {
3665 d_fprintf(stderr,
3666 "cli_openx failed: %s\n",
3667 nt_errstr(status));
3668 goto done;
3671 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3672 if (!NT_STATUS_IS_OK(status)) {
3673 d_fprintf(stderr,
3674 "cli_openx failed: %s\n",
3675 nt_errstr(status));
3676 goto done;
3679 status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3680 if (!NT_STATUS_IS_OK(status)) {
3681 d_fprintf(stderr,
3682 "cli_writeall failed: %s\n",
3683 nt_errstr(status));
3684 goto done;
3687 status = cli_locktype(
3688 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3689 if (!NT_STATUS_IS_OK(status)) {
3690 d_fprintf(stderr,
3691 "cli_locktype failed: %s\n",
3692 nt_errstr(status));
3693 goto done;
3696 req = lock_ntcancel_send(ev, ev, cli, fnum2);
3697 if (req == NULL) {
3698 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3699 goto done;
3702 ok = tevent_req_poll_ntstatus(req, ev, &status);
3703 if (!ok) {
3704 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3705 goto done;
3708 if (!NT_STATUS_IS_OK(status)) {
3709 d_fprintf(stderr,
3710 "tevent_req_poll_ntstatus returned %s\n",
3711 nt_errstr(status));
3712 goto done;
3715 status = lock_ntcancel_recv(req);
3716 if (!NT_STATUS_IS_OK(status)) {
3717 d_fprintf(stderr,
3718 "lock_ntcancel returned %s\n",
3719 nt_errstr(status));
3720 goto done;
3723 ret = true;
3724 done:
3725 if (cli != NULL) {
3726 torture_close_connection(cli);
3728 return ret;
3732 test whether fnums and tids open on one VC are available on another (a major
3733 security hole)
3735 static bool run_fdpasstest(int dummy)
3737 struct cli_state *cli1, *cli2;
3738 const char *fname = "\\fdpass.tst";
3739 uint16_t fnum1;
3740 char buf[1024];
3741 NTSTATUS status;
3743 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3744 return False;
3746 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3747 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3749 printf("starting fdpasstest\n");
3751 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3753 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3754 &fnum1);
3755 if (!NT_STATUS_IS_OK(status)) {
3756 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3757 return False;
3760 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3761 13, NULL);
3762 if (!NT_STATUS_IS_OK(status)) {
3763 printf("write failed (%s)\n", nt_errstr(status));
3764 return False;
3767 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3768 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3769 cli_setpid(cli2, cli_getpid(cli1));
3771 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3772 printf("read succeeded! nasty security hole [%s]\n", buf);
3773 return false;
3776 cli_close(cli1, fnum1);
3777 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3779 torture_close_connection(cli1);
3780 torture_close_connection(cli2);
3782 printf("finished fdpasstest\n");
3783 return True;
3786 static bool run_fdsesstest(int dummy)
3788 struct cli_state *cli;
3789 uint16_t new_vuid;
3790 uint16_t saved_vuid;
3791 uint32_t new_cnum;
3792 uint32_t saved_cnum;
3793 const char *fname = "\\fdsess.tst";
3794 const char *fname1 = "\\fdsess1.tst";
3795 uint16_t fnum1;
3796 uint16_t fnum2;
3797 char buf[1024];
3798 bool ret = True;
3799 NTSTATUS status;
3801 if (!torture_open_connection(&cli, 0))
3802 return False;
3803 smbXcli_conn_set_sockopt(cli->conn, sockops);
3805 if (!torture_cli_session_setup2(cli, &new_vuid))
3806 return False;
3808 saved_cnum = cli_state_get_tid(cli);
3809 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3810 return False;
3811 new_cnum = cli_state_get_tid(cli);
3812 cli_state_set_tid(cli, saved_cnum);
3814 printf("starting fdsesstest\n");
3816 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3817 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3819 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3820 if (!NT_STATUS_IS_OK(status)) {
3821 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3822 return False;
3825 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3826 NULL);
3827 if (!NT_STATUS_IS_OK(status)) {
3828 printf("write failed (%s)\n", nt_errstr(status));
3829 return False;
3832 saved_vuid = cli_state_get_uid(cli);
3833 cli_state_set_uid(cli, new_vuid);
3835 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3836 printf("read succeeded with different vuid! "
3837 "nasty security hole [%s]\n", buf);
3838 ret = false;
3840 /* Try to open a file with different vuid, samba cnum. */
3841 if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3842 printf("create with different vuid, same cnum succeeded.\n");
3843 cli_close(cli, fnum2);
3844 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3845 } else {
3846 printf("create with different vuid, same cnum failed.\n");
3847 printf("This will cause problems with service clients.\n");
3848 ret = False;
3851 cli_state_set_uid(cli, saved_vuid);
3853 /* Try with same vuid, different cnum. */
3854 cli_state_set_tid(cli, new_cnum);
3856 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3857 printf("read succeeded with different cnum![%s]\n", buf);
3858 ret = false;
3861 cli_state_set_tid(cli, saved_cnum);
3862 cli_close(cli, fnum1);
3863 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3865 torture_close_connection(cli);
3867 printf("finished fdsesstest\n");
3868 return ret;
3872 This test checks that
3874 1) the server does not allow an unlink on a file that is open
3876 static bool run_unlinktest(int dummy)
3878 struct cli_state *cli;
3879 const char *fname = "\\unlink.tst";
3880 uint16_t fnum;
3881 bool correct = True;
3882 NTSTATUS status;
3884 if (!torture_open_connection(&cli, 0)) {
3885 return False;
3888 smbXcli_conn_set_sockopt(cli->conn, sockops);
3890 printf("starting unlink test\n");
3892 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3894 cli_setpid(cli, 1);
3896 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3897 if (!NT_STATUS_IS_OK(status)) {
3898 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3899 return False;
3902 status = cli_unlink(cli, fname,
3903 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3904 if (NT_STATUS_IS_OK(status)) {
3905 printf("error: server allowed unlink on an open file\n");
3906 correct = False;
3907 } else {
3908 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3909 NT_STATUS_SHARING_VIOLATION);
3912 cli_close(cli, fnum);
3913 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3915 if (!torture_close_connection(cli)) {
3916 correct = False;
3919 printf("unlink test finished\n");
3921 return correct;
3926 test how many open files this server supports on the one socket
3928 static bool run_maxfidtest(int dummy)
3930 struct cli_state *cli;
3931 fstring fname;
3932 uint16_t fnums[0x11000];
3933 int i;
3934 int retries=4;
3935 bool correct = True;
3936 NTSTATUS status;
3938 cli = current_cli;
3940 if (retries <= 0) {
3941 printf("failed to connect\n");
3942 return False;
3945 smbXcli_conn_set_sockopt(cli->conn, sockops);
3947 for (i=0; i<0x11000; i++) {
3948 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3949 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3950 &fnums[i]);
3951 if (!NT_STATUS_IS_OK(status)) {
3952 printf("open of %s failed (%s)\n",
3953 fname, nt_errstr(status));
3954 printf("maximum fnum is %d\n", i);
3955 break;
3957 printf("%6d\r", i);
3959 printf("%6d\n", i);
3960 i--;
3962 printf("cleaning up\n");
3963 for (;i>=0;i--) {
3964 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3965 cli_close(cli, fnums[i]);
3967 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3968 if (!NT_STATUS_IS_OK(status)) {
3969 printf("unlink of %s failed (%s)\n",
3970 fname, nt_errstr(status));
3971 correct = False;
3973 printf("%6d\r", i);
3975 printf("%6d\n", 0);
3977 printf("maxfid test finished\n");
3978 if (!torture_close_connection(cli)) {
3979 correct = False;
3981 return correct;
3984 /* send smb negprot commands, not reading the response */
3985 static bool run_negprot_nowait(int dummy)
3987 struct tevent_context *ev;
3988 int i;
3989 struct cli_state *cli;
3990 bool correct = True;
3992 printf("starting negprot nowait test\n");
3994 ev = samba_tevent_context_init(talloc_tos());
3995 if (ev == NULL) {
3996 return false;
3999 if (!(cli = open_nbt_connection())) {
4000 TALLOC_FREE(ev);
4001 return False;
4004 for (i=0;i<50000;i++) {
4005 struct tevent_req *req;
4007 req = smbXcli_negprot_send(
4010 cli->conn,
4011 cli->timeout,
4012 PROTOCOL_CORE,
4013 PROTOCOL_NT1,
4015 NULL);
4016 if (req == NULL) {
4017 TALLOC_FREE(ev);
4018 return false;
4020 if (!tevent_req_poll(req, ev)) {
4021 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
4022 strerror(errno));
4023 TALLOC_FREE(ev);
4024 return false;
4026 TALLOC_FREE(req);
4029 if (torture_close_connection(cli)) {
4030 correct = False;
4033 printf("finished negprot nowait test\n");
4035 return correct;
4038 /* send smb negprot commands, not reading the response */
4039 static bool run_bad_nbt_session(int dummy)
4041 struct nmb_name called, calling;
4042 struct sockaddr_storage ss;
4043 NTSTATUS status;
4044 int fd;
4045 bool ret;
4047 printf("starting bad nbt session test\n");
4049 make_nmb_name(&calling, myname, 0x0);
4050 make_nmb_name(&called , host, 0x20);
4052 if (!resolve_name(host, &ss, 0x20, true)) {
4053 d_fprintf(stderr, "Could not resolve name %s\n", host);
4054 return false;
4057 status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4058 if (!NT_STATUS_IS_OK(status)) {
4059 d_fprintf(stderr, "open_socket_out failed: %s\n",
4060 nt_errstr(status));
4061 return false;
4064 ret = cli_bad_session_request(fd, &calling, &called);
4065 close(fd);
4066 if (!ret) {
4067 d_fprintf(stderr, "open_socket_out failed: %s\n",
4068 nt_errstr(status));
4069 return false;
4072 printf("finished bad nbt session test\n");
4073 return true;
4076 /* send random IPC commands */
4077 static bool run_randomipc(int dummy)
4079 int i;
4080 struct cli_state *cli;
4081 bool correct = True;
4082 int count = 50000;
4084 printf("starting random ipc test\n");
4086 if (!torture_open_connection(&cli, 0)) {
4087 return False;
4090 for (i=0;i<count;i++) {
4091 int api = sys_random() % 500;
4092 int param_len = (sys_random() % 64);
4093 uint8_t param[1024];
4094 uint8_t *rparam = NULL;
4095 uint8_t *rdata = NULL;
4096 uint32_t rdrcnt, rprcnt;
4098 generate_random_buffer(param, param_len);
4100 SSVAL(param,0,api);
4102 cli_trans(talloc_tos(), /* mem_ctx */
4103 cli, /* cli */
4104 SMBtrans, /* cmd */
4105 "\\PIPE\\LANMAN", /* name */
4106 0, /* fid */
4107 0, /* function */
4108 0, /* flags */
4109 NULL, /* setup */
4110 0, /* num_setup */
4111 0, /* max_setup */
4112 param, /* param */
4113 param_len, /* num_param */
4114 8, /* max_param */
4115 NULL, /* data */
4116 0, /* num_data */
4117 CLI_BUFFER_SIZE, /* max_data, for W2K */
4118 NULL, /* recv_flags2 */
4119 NULL, /* rsetup */
4120 0, /* min_rsetup */
4121 NULL, /* num_rsetup */
4122 &rparam, /* rparam */
4123 0, /* min_rparam */
4124 &rprcnt, /* num_rparam */
4125 &rdata, /* rdata */
4126 0, /* min_rdata */
4127 &rdrcnt); /* num_rdata */
4128 if (i % 100 == 0) {
4129 printf("%d/%d\r", i,count);
4131 TALLOC_FREE(rparam);
4132 TALLOC_FREE(rdata);
4134 printf("%d/%d\n", i, count);
4136 if (!torture_close_connection(cli)) {
4137 correct = False;
4140 printf("finished random ipc test\n");
4142 return correct;
4147 static void browse_callback(const char *sname, uint32_t stype,
4148 const char *comment, void *state)
4150 printf("\t%20.20s %08x %s\n", sname, stype, comment);
4156 This test checks the browse list code
4159 static bool run_browsetest(int dummy)
4161 static struct cli_state *cli;
4162 bool correct = True;
4164 printf("starting browse test\n");
4166 if (!torture_open_connection(&cli, 0)) {
4167 return False;
4170 printf("domain list:\n");
4171 cli_NetServerEnum(cli, cli->server_domain,
4172 SV_TYPE_DOMAIN_ENUM,
4173 browse_callback, NULL);
4175 printf("machine list:\n");
4176 cli_NetServerEnum(cli, cli->server_domain,
4177 SV_TYPE_ALL,
4178 browse_callback, NULL);
4180 if (!torture_close_connection(cli)) {
4181 correct = False;
4184 printf("browse test finished\n");
4186 return correct;
4190 static bool check_attributes(struct cli_state *cli,
4191 const char *fname,
4192 uint32_t expected_attrs)
4194 uint32_t attrs = 0;
4195 NTSTATUS status = cli_getatr(cli,
4196 fname,
4197 &attrs,
4198 NULL,
4199 NULL);
4200 if (!NT_STATUS_IS_OK(status)) {
4201 printf("cli_getatr failed with %s\n",
4202 nt_errstr(status));
4203 return false;
4205 if (attrs != expected_attrs) {
4206 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4207 (unsigned int)attrs,
4208 (unsigned int)expected_attrs);
4209 return false;
4211 return true;
4215 This checks how the getatr calls works
4217 static bool run_attrtest(int dummy)
4219 struct cli_state *cli;
4220 uint16_t fnum;
4221 time_t t, t2;
4222 const char *fname = "\\attrib123456789.tst";
4223 bool correct = True;
4224 NTSTATUS status;
4226 printf("starting attrib test\n");
4228 if (!torture_open_connection(&cli, 0)) {
4229 return False;
4232 /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4233 status = cli_unlink(cli, fname, 0x20000);
4234 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4235 correct = false;
4236 goto out;
4239 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4240 cli_openx(cli, fname,
4241 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4242 cli_close(cli, fnum);
4244 status = cli_getatr(cli, fname, NULL, NULL, &t);
4245 if (!NT_STATUS_IS_OK(status)) {
4246 printf("getatr failed (%s)\n", nt_errstr(status));
4247 correct = False;
4250 if (labs(t - time(NULL)) > 60*60*24*10) {
4251 printf("ERROR: SMBgetatr bug. time is %s",
4252 ctime(&t));
4253 t = time(NULL);
4254 correct = True;
4257 t2 = t-60*60*24; /* 1 day ago */
4259 /* Ensure we can't set with out-of-range (unknown) attribute. */
4260 status = cli_setatr(cli, fname, 0x20000, t2);
4261 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4262 correct = false;
4263 goto out;
4266 status = cli_setatr(cli, fname, 0, t2);
4267 if (!NT_STATUS_IS_OK(status)) {
4268 printf("setatr failed (%s)\n", nt_errstr(status));
4269 correct = True;
4272 status = cli_getatr(cli, fname, NULL, NULL, &t);
4273 if (!NT_STATUS_IS_OK(status)) {
4274 printf("getatr failed (%s)\n", nt_errstr(status));
4275 correct = True;
4278 if (t != t2) {
4279 printf("ERROR: getatr/setatr bug. times are\n%s",
4280 ctime(&t));
4281 printf("%s", ctime(&t2));
4282 correct = True;
4285 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4287 /* Check cli_setpathinfo_ext() */
4288 /* Re-create the file. */
4289 status = cli_openx(cli, fname,
4290 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4291 if (!NT_STATUS_IS_OK(status)) {
4292 printf("Failed to recreate %s (%s)\n",
4293 fname, nt_errstr(status));
4294 correct = false;
4296 cli_close(cli, fnum);
4298 status = cli_setpathinfo_ext(
4299 cli,
4300 fname,
4301 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4302 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4303 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4304 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4305 FILE_ATTRIBUTE_SYSTEM |
4306 FILE_ATTRIBUTE_HIDDEN |
4307 FILE_ATTRIBUTE_READONLY);
4308 if (!NT_STATUS_IS_OK(status)) {
4309 printf("cli_setpathinfo_ext failed with %s\n",
4310 nt_errstr(status));
4311 correct = false;
4314 /* Check attributes are correct. */
4315 correct = check_attributes(cli,
4316 fname,
4317 FILE_ATTRIBUTE_SYSTEM |
4318 FILE_ATTRIBUTE_HIDDEN |
4319 FILE_ATTRIBUTE_READONLY);
4320 if (correct == false) {
4321 goto out;
4324 /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4325 status = cli_setpathinfo_ext(
4326 cli,
4327 fname,
4328 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4329 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4330 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4331 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4332 FILE_ATTRIBUTE_NORMAL);
4333 if (!NT_STATUS_IS_OK(status)) {
4334 printf("cli_setpathinfo_ext failed with %s\n",
4335 nt_errstr(status));
4336 correct = false;
4339 /* Check attributes are correct. */
4340 correct = check_attributes(cli,
4341 fname,
4342 FILE_ATTRIBUTE_SYSTEM |
4343 FILE_ATTRIBUTE_HIDDEN |
4344 FILE_ATTRIBUTE_READONLY);
4345 if (correct == false) {
4346 goto out;
4349 /* Setting to (uint16_t)-1 should also be ignored. */
4350 status = cli_setpathinfo_ext(
4351 cli,
4352 fname,
4353 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4354 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4355 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4356 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4357 (uint32_t)-1);
4358 if (!NT_STATUS_IS_OK(status)) {
4359 printf("cli_setpathinfo_ext failed with %s\n",
4360 nt_errstr(status));
4361 correct = false;
4364 /* Check attributes are correct. */
4365 correct = check_attributes(cli,
4366 fname,
4367 FILE_ATTRIBUTE_SYSTEM |
4368 FILE_ATTRIBUTE_HIDDEN |
4369 FILE_ATTRIBUTE_READONLY);
4370 if (correct == false) {
4371 goto out;
4374 /* Setting to 0 should clear them all. */
4375 status = cli_setpathinfo_ext(
4376 cli,
4377 fname,
4378 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4379 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4380 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4381 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4383 if (!NT_STATUS_IS_OK(status)) {
4384 printf("cli_setpathinfo_ext failed with %s\n",
4385 nt_errstr(status));
4386 correct = false;
4389 /* Check attributes are correct. */
4390 correct = check_attributes(cli,
4391 fname,
4392 FILE_ATTRIBUTE_NORMAL);
4393 if (correct == false) {
4394 goto out;
4397 out:
4399 cli_unlink(cli,
4400 fname,
4401 FILE_ATTRIBUTE_SYSTEM |
4402 FILE_ATTRIBUTE_HIDDEN|
4403 FILE_ATTRIBUTE_READONLY);
4405 if (!torture_close_connection(cli)) {
4406 correct = False;
4409 printf("attrib test finished\n");
4411 return correct;
4414 static NTSTATUS cli_qfilename(
4415 struct cli_state *cli,
4416 uint16_t fnum,
4417 TALLOC_CTX *mem_ctx,
4418 char **_name)
4420 uint16_t recv_flags2;
4421 uint8_t *rdata;
4422 uint32_t num_rdata;
4423 NTSTATUS status;
4424 char *name = NULL;
4425 uint32_t namelen;
4427 status = cli_qfileinfo(talloc_tos(),
4428 cli,
4429 fnum,
4430 FSCC_FILE_NAME_INFORMATION,
4432 CLI_BUFFER_SIZE,
4433 &recv_flags2,
4434 &rdata,
4435 &num_rdata);
4436 if (!NT_STATUS_IS_OK(status)) {
4437 return status;
4440 namelen = IVAL(rdata, 0);
4441 if (namelen > (num_rdata - 4)) {
4442 TALLOC_FREE(rdata);
4443 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4446 pull_string_talloc(mem_ctx,
4447 (const char *)rdata,
4448 recv_flags2,
4449 &name,
4450 rdata + 4,
4451 namelen,
4452 STR_UNICODE);
4453 if (name == NULL) {
4454 status = map_nt_error_from_unix(errno);
4455 TALLOC_FREE(rdata);
4456 return status;
4459 *_name = name;
4460 TALLOC_FREE(rdata);
4461 return NT_STATUS_OK;
4465 This checks a couple of trans2 calls
4467 static bool run_trans2test(int dummy)
4469 struct cli_state *cli;
4470 uint16_t fnum;
4471 off_t size;
4472 time_t c_time, a_time, m_time;
4473 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4474 const char *fname = "\\trans2.tst";
4475 const char *dname = "\\trans2";
4476 const char *fname2 = "\\trans2\\trans2.tst";
4477 char *pname = NULL;
4478 bool correct = True;
4479 NTSTATUS status;
4480 uint32_t fs_attr;
4481 uint64_t ino;
4483 printf("starting trans2 test\n");
4485 if (!torture_open_connection(&cli, 0)) {
4486 return False;
4489 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4490 /* Ensure ino is zero, SMB2 gets a real one. */
4491 ino = 0;
4492 } else {
4493 /* Ensure ino is -1, SMB1 never gets a real one. */
4494 ino = (uint64_t)-1;
4497 status = cli_get_fs_attr_info(cli, &fs_attr);
4498 if (!NT_STATUS_IS_OK(status)) {
4499 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4500 nt_errstr(status));
4501 correct = false;
4504 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4505 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4506 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4507 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4508 if (!NT_STATUS_IS_OK(status)) {
4509 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4510 correct = False;
4513 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4514 if (!NT_STATUS_IS_OK(status)) {
4515 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4516 correct = False;
4518 else if (strcmp(pname, fname)) {
4519 printf("qfilename gave different name? [%s] [%s]\n",
4520 fname, pname);
4521 correct = False;
4524 cli_close(cli, fnum);
4526 sleep(2);
4528 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4529 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4530 &fnum);
4531 if (!NT_STATUS_IS_OK(status)) {
4532 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4533 return False;
4535 cli_close(cli, fnum);
4537 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4538 NULL);
4539 if (!NT_STATUS_IS_OK(status)) {
4540 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4541 correct = False;
4542 } else {
4543 time_t t = time(NULL);
4545 if (c_time != m_time) {
4546 printf("create time=%s", ctime(&c_time));
4547 printf("modify time=%s", ctime(&m_time));
4548 printf("This system appears to have sticky create times\n");
4550 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4551 printf("access time=%s", ctime(&a_time));
4552 printf("This system appears to set a midnight access time\n");
4553 correct = False;
4556 if (labs(m_time - t) > 60*60*24*7) {
4557 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4558 correct = False;
4563 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4564 cli_openx(cli, fname,
4565 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4566 cli_close(cli, fnum);
4567 status = cli_qpathinfo2(cli,
4568 fname,
4569 &c_time_ts,
4570 &a_time_ts,
4571 &w_time_ts,
4572 &m_time_ts,
4573 &size,
4574 NULL,
4575 &ino,
4576 NULL);
4577 if (!NT_STATUS_IS_OK(status)) {
4578 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4579 correct = False;
4580 } else {
4581 if (w_time_ts.tv_sec < 60*60*24*2) {
4582 printf("write time=%s", ctime(&w_time_ts.tv_sec));
4583 printf("This system appears to set a initial 0 write time\n");
4584 correct = False;
4586 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4587 /* SMB2 should always return an inode. */
4588 if (ino == 0) {
4589 printf("SMB2 bad inode (0)\n");
4590 correct = false;
4592 } else {
4593 /* SMB1 must always return zero here. */
4594 if (ino != 0) {
4595 printf("SMB1 bad inode (!0)\n");
4596 correct = false;
4601 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4604 /* check if the server updates the directory modification time
4605 when creating a new file */
4606 status = cli_mkdir(cli, dname);
4607 if (!NT_STATUS_IS_OK(status)) {
4608 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4609 correct = False;
4611 sleep(3);
4612 status = cli_qpathinfo2(cli,
4613 "\\trans2\\",
4614 &c_time_ts,
4615 &a_time_ts,
4616 &w_time_ts,
4617 &m_time_ts,
4618 &size,
4619 NULL,
4620 NULL,
4621 NULL);
4622 if (!NT_STATUS_IS_OK(status)) {
4623 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4624 correct = False;
4627 cli_openx(cli, fname2,
4628 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4629 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4630 cli_close(cli, fnum);
4631 status = cli_qpathinfo2(cli,
4632 "\\trans2\\",
4633 &c_time_ts,
4634 &a_time_ts,
4635 &w_time_ts,
4636 &m_time2_ts,
4637 &size,
4638 NULL,
4639 NULL,
4640 NULL);
4641 if (!NT_STATUS_IS_OK(status)) {
4642 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4643 correct = False;
4644 } else {
4645 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4646 == 0) {
4647 printf("This system does not update directory modification times\n");
4648 correct = False;
4651 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4652 cli_rmdir(cli, dname);
4654 if (!torture_close_connection(cli)) {
4655 correct = False;
4658 printf("trans2 test finished\n");
4660 return correct;
4664 This checks new W2K calls.
4667 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4669 uint8_t *buf = NULL;
4670 uint32_t len;
4671 NTSTATUS status;
4673 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4674 CLI_BUFFER_SIZE, NULL, &buf, &len);
4675 if (!NT_STATUS_IS_OK(status)) {
4676 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4677 nt_errstr(status));
4678 } else {
4679 printf("qfileinfo: level %d, len = %u\n", level, len);
4680 dump_data(0, (uint8_t *)buf, len);
4681 printf("\n");
4683 TALLOC_FREE(buf);
4684 return status;
4687 static bool run_w2ktest(int dummy)
4689 struct cli_state *cli;
4690 uint16_t fnum;
4691 const char *fname = "\\w2ktest\\w2k.tst";
4692 int level;
4693 bool correct = True;
4695 printf("starting w2k test\n");
4697 if (!torture_open_connection(&cli, 0)) {
4698 return False;
4701 cli_openx(cli, fname,
4702 O_RDWR | O_CREAT , DENY_NONE, &fnum);
4704 for (level = 1004; level < 1040; level++) {
4705 new_trans(cli, fnum, level);
4708 cli_close(cli, fnum);
4710 if (!torture_close_connection(cli)) {
4711 correct = False;
4714 printf("w2k test finished\n");
4716 return correct;
4721 this is a harness for some oplock tests
4723 static bool run_oplock1(int dummy)
4725 struct cli_state *cli1;
4726 const char *fname = "\\lockt1.lck";
4727 uint16_t fnum1;
4728 bool correct = True;
4729 NTSTATUS status;
4731 printf("starting oplock test 1\n");
4733 if (!torture_open_connection(&cli1, 0)) {
4734 return False;
4737 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4739 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4741 cli1->use_oplocks = True;
4743 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4744 &fnum1);
4745 if (!NT_STATUS_IS_OK(status)) {
4746 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4747 return False;
4750 cli1->use_oplocks = False;
4752 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4753 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4755 status = cli_close(cli1, fnum1);
4756 if (!NT_STATUS_IS_OK(status)) {
4757 printf("close2 failed (%s)\n", nt_errstr(status));
4758 return False;
4761 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4762 if (!NT_STATUS_IS_OK(status)) {
4763 printf("unlink failed (%s)\n", nt_errstr(status));
4764 return False;
4767 if (!torture_close_connection(cli1)) {
4768 correct = False;
4771 printf("finished oplock test 1\n");
4773 return correct;
4776 static bool run_oplock2(int dummy)
4778 struct cli_state *cli1, *cli2;
4779 const char *fname = "\\lockt2.lck";
4780 uint16_t fnum1, fnum2;
4781 int saved_use_oplocks = use_oplocks;
4782 char buf[4];
4783 bool correct = True;
4784 volatile bool *shared_correct;
4785 size_t nread;
4786 NTSTATUS status;
4788 shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4789 *shared_correct = True;
4791 use_level_II_oplocks = True;
4792 use_oplocks = True;
4794 printf("starting oplock test 2\n");
4796 if (!torture_open_connection(&cli1, 0)) {
4797 use_level_II_oplocks = False;
4798 use_oplocks = saved_use_oplocks;
4799 return False;
4802 if (!torture_open_connection(&cli2, 1)) {
4803 use_level_II_oplocks = False;
4804 use_oplocks = saved_use_oplocks;
4805 return False;
4808 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4810 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4811 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4813 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4814 &fnum1);
4815 if (!NT_STATUS_IS_OK(status)) {
4816 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4817 return False;
4820 /* Don't need the globals any more. */
4821 use_level_II_oplocks = False;
4822 use_oplocks = saved_use_oplocks;
4824 if (fork() == 0) {
4825 /* Child code */
4826 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4827 if (!NT_STATUS_IS_OK(status)) {
4828 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4829 *shared_correct = False;
4830 exit(0);
4833 sleep(2);
4835 status = cli_close(cli2, fnum2);
4836 if (!NT_STATUS_IS_OK(status)) {
4837 printf("close2 failed (%s)\n", nt_errstr(status));
4838 *shared_correct = False;
4841 exit(0);
4844 sleep(2);
4846 /* Ensure cli1 processes the break. Empty file should always return 0
4847 * bytes. */
4848 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4849 if (!NT_STATUS_IS_OK(status)) {
4850 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4851 correct = false;
4852 } else if (nread != 0) {
4853 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4854 (unsigned long)nread, 0);
4855 correct = false;
4858 /* Should now be at level II. */
4859 /* Test if sending a write locks causes a break to none. */
4860 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4861 if (!NT_STATUS_IS_OK(status)) {
4862 printf("lock failed (%s)\n", nt_errstr(status));
4863 correct = False;
4866 cli_unlock(cli1, fnum1, 0, 4);
4868 sleep(2);
4870 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4871 if (!NT_STATUS_IS_OK(status)) {
4872 printf("lock failed (%s)\n", nt_errstr(status));
4873 correct = False;
4876 cli_unlock(cli1, fnum1, 0, 4);
4878 sleep(2);
4880 cli_read(cli1, fnum1, buf, 0, 4, NULL);
4882 status = cli_close(cli1, fnum1);
4883 if (!NT_STATUS_IS_OK(status)) {
4884 printf("close1 failed (%s)\n", nt_errstr(status));
4885 correct = False;
4888 sleep(4);
4890 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4891 if (!NT_STATUS_IS_OK(status)) {
4892 printf("unlink failed (%s)\n", nt_errstr(status));
4893 correct = False;
4896 if (!torture_close_connection(cli1)) {
4897 correct = False;
4900 if (!*shared_correct) {
4901 correct = False;
4904 printf("finished oplock test 2\n");
4906 return correct;
4909 struct oplock4_state {
4910 struct tevent_context *ev;
4911 struct cli_state *cli;
4912 bool *got_break;
4913 uint16_t *fnum2;
4916 static void oplock4_got_break(struct tevent_req *req);
4917 static void oplock4_got_open(struct tevent_req *req);
4919 static bool run_oplock4(int dummy)
4921 struct tevent_context *ev;
4922 struct cli_state *cli1, *cli2;
4923 struct tevent_req *oplock_req, *open_req;
4924 const char *fname = "\\lockt4.lck";
4925 const char *fname_ln = "\\lockt4_ln.lck";
4926 uint16_t fnum1, fnum2;
4927 int saved_use_oplocks = use_oplocks;
4928 NTSTATUS status;
4929 bool correct = true;
4931 bool got_break;
4933 struct oplock4_state *state;
4935 printf("starting oplock test 4\n");
4937 if (!torture_open_connection(&cli1, 0)) {
4938 use_level_II_oplocks = false;
4939 use_oplocks = saved_use_oplocks;
4940 return false;
4943 if (!torture_open_connection(&cli2, 1)) {
4944 use_level_II_oplocks = false;
4945 use_oplocks = saved_use_oplocks;
4946 return false;
4949 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4950 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4952 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4953 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4955 /* Create the file. */
4956 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4957 &fnum1);
4958 if (!NT_STATUS_IS_OK(status)) {
4959 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4960 return false;
4963 status = cli_close(cli1, fnum1);
4964 if (!NT_STATUS_IS_OK(status)) {
4965 printf("close1 failed (%s)\n", nt_errstr(status));
4966 return false;
4969 /* Now create a hardlink. */
4970 status = cli_hardlink(cli1, fname, fname_ln);
4971 if (!NT_STATUS_IS_OK(status)) {
4972 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4973 return false;
4976 /* Prove that opening hardlinks cause deny modes to conflict. */
4977 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4978 if (!NT_STATUS_IS_OK(status)) {
4979 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4980 return false;
4983 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4984 if (NT_STATUS_IS_OK(status)) {
4985 printf("open of %s succeeded - should fail with sharing violation.\n",
4986 fname_ln);
4987 return false;
4990 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4991 printf("open of %s should fail with sharing violation. Got %s\n",
4992 fname_ln, nt_errstr(status));
4993 return false;
4996 status = cli_close(cli1, fnum1);
4997 if (!NT_STATUS_IS_OK(status)) {
4998 printf("close1 failed (%s)\n", nt_errstr(status));
4999 return false;
5002 cli1->use_oplocks = true;
5003 cli2->use_oplocks = true;
5005 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5006 if (!NT_STATUS_IS_OK(status)) {
5007 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5008 return false;
5011 ev = samba_tevent_context_init(talloc_tos());
5012 if (ev == NULL) {
5013 printf("tevent_context_init failed\n");
5014 return false;
5017 state = talloc(ev, struct oplock4_state);
5018 if (state == NULL) {
5019 printf("talloc failed\n");
5020 return false;
5022 state->ev = ev;
5023 state->cli = cli1;
5024 state->got_break = &got_break;
5025 state->fnum2 = &fnum2;
5027 oplock_req = cli_smb_oplock_break_waiter_send(
5028 talloc_tos(), ev, cli1);
5029 if (oplock_req == NULL) {
5030 printf("cli_smb_oplock_break_waiter_send failed\n");
5031 return false;
5033 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
5035 open_req = cli_openx_send(
5036 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
5037 if (open_req == NULL) {
5038 printf("cli_openx_send failed\n");
5039 return false;
5041 tevent_req_set_callback(open_req, oplock4_got_open, state);
5043 got_break = false;
5044 fnum2 = 0xffff;
5046 while (!got_break || fnum2 == 0xffff) {
5047 int ret;
5048 ret = tevent_loop_once(ev);
5049 if (ret == -1) {
5050 printf("tevent_loop_once failed: %s\n",
5051 strerror(errno));
5052 return false;
5056 status = cli_close(cli2, fnum2);
5057 if (!NT_STATUS_IS_OK(status)) {
5058 printf("close2 failed (%s)\n", nt_errstr(status));
5059 correct = false;
5062 status = cli_close(cli1, fnum1);
5063 if (!NT_STATUS_IS_OK(status)) {
5064 printf("close1 failed (%s)\n", nt_errstr(status));
5065 correct = false;
5068 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5069 if (!NT_STATUS_IS_OK(status)) {
5070 printf("unlink failed (%s)\n", nt_errstr(status));
5071 correct = false;
5074 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5075 if (!NT_STATUS_IS_OK(status)) {
5076 printf("unlink failed (%s)\n", nt_errstr(status));
5077 correct = false;
5080 if (!torture_close_connection(cli1)) {
5081 correct = false;
5084 if (!got_break) {
5085 correct = false;
5088 printf("finished oplock test 4\n");
5090 return correct;
5093 static void oplock4_got_break(struct tevent_req *req)
5095 struct oplock4_state *state = tevent_req_callback_data(
5096 req, struct oplock4_state);
5097 uint16_t fnum;
5098 uint8_t level;
5099 NTSTATUS status;
5101 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
5102 TALLOC_FREE(req);
5103 if (!NT_STATUS_IS_OK(status)) {
5104 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5105 nt_errstr(status));
5106 return;
5108 *state->got_break = true;
5110 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5111 NO_OPLOCK);
5112 if (req == NULL) {
5113 printf("cli_oplock_ack_send failed\n");
5114 return;
5118 static void oplock4_got_open(struct tevent_req *req)
5120 struct oplock4_state *state = tevent_req_callback_data(
5121 req, struct oplock4_state);
5122 NTSTATUS status;
5124 status = cli_openx_recv(req, state->fnum2);
5125 if (!NT_STATUS_IS_OK(status)) {
5126 printf("cli_openx_recv returned %s\n", nt_errstr(status));
5127 *state->fnum2 = 0xffff;
5131 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5133 struct oplock5_state {
5134 int pipe_down_fd;
5138 * Async open the file that has a kernel oplock, do an echo to get
5139 * that 100% across, close the file to signal to the child fd that the
5140 * oplock can be dropped, wait for the open reply.
5143 static void oplock5_opened(struct tevent_req *subreq);
5144 static void oplock5_pong(struct tevent_req *subreq);
5145 static void oplock5_timedout(struct tevent_req *subreq);
5147 static struct tevent_req *oplock5_send(
5148 TALLOC_CTX *mem_ctx,
5149 struct tevent_context *ev,
5150 struct cli_state *cli,
5151 const char *fname,
5152 int pipe_down_fd)
5154 struct tevent_req *req = NULL, *subreq = NULL;
5155 struct oplock5_state *state = NULL;
5156 static uint8_t data = 0;
5158 req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5159 if (req == NULL) {
5160 return NULL;
5162 state->pipe_down_fd = pipe_down_fd;
5164 subreq = cli_ntcreate_send(
5165 state,
5167 cli,
5168 fname,
5169 0, /* CreatFlags */
5170 SEC_FILE_READ_DATA, /* DesiredAccess */
5171 FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
5172 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5173 FILE_OPEN, /* CreateDisposition */
5174 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5175 0, /* Impersonation */
5176 0); /* SecurityFlags */
5177 if (tevent_req_nomem(subreq, req)) {
5178 return tevent_req_post(req, ev);
5180 tevent_req_set_callback(subreq, oplock5_opened, req);
5182 subreq = cli_echo_send(
5183 state,
5185 cli,
5187 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5188 if (tevent_req_nomem(subreq, req)) {
5189 return tevent_req_post(req, ev);
5191 tevent_req_set_callback(subreq, oplock5_pong, req);
5193 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5194 if (tevent_req_nomem(subreq, req)) {
5195 return tevent_req_post(req, ev);
5197 tevent_req_set_callback(subreq, oplock5_timedout, req);
5199 return req;
5202 static void oplock5_opened(struct tevent_req *subreq)
5204 struct tevent_req *req = tevent_req_callback_data(
5205 subreq, struct tevent_req);
5206 NTSTATUS status;
5207 uint16_t fnum;
5209 status = cli_ntcreate_recv(subreq, &fnum, NULL);
5210 TALLOC_FREE(subreq);
5211 if (tevent_req_nterror(req, status)) {
5212 return;
5214 tevent_req_done(req);
5217 static void oplock5_pong(struct tevent_req *subreq)
5219 struct tevent_req *req = tevent_req_callback_data(
5220 subreq, struct tevent_req);
5221 struct oplock5_state *state = tevent_req_data(
5222 req, struct oplock5_state);
5223 NTSTATUS status;
5225 status = cli_echo_recv(subreq);
5226 TALLOC_FREE(subreq);
5227 if (tevent_req_nterror(req, status)) {
5228 return;
5231 close(state->pipe_down_fd);
5234 static void oplock5_timedout(struct tevent_req *subreq)
5236 struct tevent_req *req = tevent_req_callback_data(
5237 subreq, struct tevent_req);
5238 bool ok;
5240 ok = tevent_wakeup_recv(subreq);
5241 TALLOC_FREE(subreq);
5242 if (!ok) {
5243 tevent_req_oom(req);
5244 return;
5246 tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5249 static NTSTATUS oplock5_recv(struct tevent_req *req)
5251 return tevent_req_simple_recv_ntstatus(req);
5254 static bool run_oplock5(int dummy)
5256 struct tevent_context *ev = NULL;
5257 struct tevent_req *req = NULL;
5258 struct cli_state *cli = NULL;
5259 const char *fname = "oplock5.txt";
5260 int pipe_down[2], pipe_up[2];
5261 pid_t child_pid;
5262 uint8_t c = '\0';
5263 NTSTATUS status;
5264 int ret;
5265 bool ok;
5267 printf("starting oplock5\n");
5269 if (local_path == NULL) {
5270 d_fprintf(stderr, "oplock5 must be given a local path via "
5271 "-l <localpath>\n");
5272 return false;
5275 ret = pipe(pipe_down);
5276 if (ret == -1) {
5277 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5278 return false;
5280 ret = pipe(pipe_up);
5281 if (ret == -1) {
5282 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5283 return false;
5286 child_pid = fork();
5287 if (child_pid == -1) {
5288 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5289 return false;
5292 if (child_pid == 0) {
5293 char *local_file = NULL;
5294 int fd;
5296 close(pipe_down[1]);
5297 close(pipe_up[0]);
5299 local_file = talloc_asprintf(
5300 talloc_tos(), "%s/%s", local_path, fname);
5301 if (local_file == 0) {
5302 c = 1;
5303 goto do_write;
5305 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5306 if (fd == -1) {
5307 d_fprintf(stderr,
5308 "open(%s) in child failed: %s\n",
5309 local_file,
5310 strerror(errno));
5311 c = 2;
5312 goto do_write;
5315 signal(SIGIO, SIG_IGN);
5317 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5318 if (ret == -1) {
5319 d_fprintf(stderr,
5320 "SETLEASE in child failed: %s\n",
5321 strerror(errno));
5322 c = 3;
5323 goto do_write;
5326 do_write:
5327 ret = sys_write(pipe_up[1], &c, sizeof(c));
5328 if (ret == -1) {
5329 d_fprintf(stderr,
5330 "sys_write failed: %s\n",
5331 strerror(errno));
5332 exit(4);
5334 ret = sys_read(pipe_down[0], &c, sizeof(c));
5335 if (ret == -1) {
5336 d_fprintf(stderr,
5337 "sys_read failed: %s\n",
5338 strerror(errno));
5339 exit(5);
5341 exit(0);
5344 close(pipe_up[1]);
5345 close(pipe_down[0]);
5347 ret = sys_read(pipe_up[0], &c, sizeof(c));
5348 if (ret != 1) {
5349 d_fprintf(stderr,
5350 "sys_read failed: %s\n",
5351 strerror(errno));
5352 return false;
5354 if (c != 0) {
5355 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5356 return false;
5359 ok = torture_open_connection(&cli, 0);
5360 if (!ok) {
5361 d_fprintf(stderr, "torture_open_connection failed\n");
5362 return false;
5365 ev = samba_tevent_context_init(talloc_tos());
5366 if (ev == NULL) {
5367 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5368 return false;
5371 req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5372 if (req == NULL) {
5373 d_fprintf(stderr, "oplock5_send failed\n");
5374 return false;
5377 ok = tevent_req_poll_ntstatus(req, ev, &status);
5378 if (!ok) {
5379 d_fprintf(stderr,
5380 "tevent_req_poll_ntstatus failed: %s\n",
5381 nt_errstr(status));
5382 return false;
5385 status = oplock5_recv(req);
5386 TALLOC_FREE(req);
5387 if (!NT_STATUS_IS_OK(status)) {
5388 d_fprintf(stderr,
5389 "oplock5 failed: %s\n",
5390 nt_errstr(status));
5391 return false;
5394 return true;
5397 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5400 Test delete on close semantics.
5402 static bool run_deletetest(int dummy)
5404 struct cli_state *cli1 = NULL;
5405 struct cli_state *cli2 = NULL;
5406 const char *fname = "\\delete.file";
5407 uint16_t fnum1 = (uint16_t)-1;
5408 uint16_t fnum2 = (uint16_t)-1;
5409 bool correct = false;
5410 NTSTATUS status;
5412 printf("starting delete test\n");
5414 if (!torture_open_connection(&cli1, 0)) {
5415 return False;
5418 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5420 /* Test 1 - this should delete the file on close. */
5422 cli_setatr(cli1, fname, 0, 0);
5423 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5425 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5426 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5427 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5428 if (!NT_STATUS_IS_OK(status)) {
5429 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5430 goto fail;
5433 status = cli_close(cli1, fnum1);
5434 if (!NT_STATUS_IS_OK(status)) {
5435 printf("[1] close failed (%s)\n", nt_errstr(status));
5436 goto fail;
5439 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5440 if (NT_STATUS_IS_OK(status)) {
5441 printf("[1] open of %s succeeded (should fail)\n", fname);
5442 goto fail;
5445 printf("first delete on close test succeeded.\n");
5447 /* Test 2 - this should delete the file on close. */
5449 cli_setatr(cli1, fname, 0, 0);
5450 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5452 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5453 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5454 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5455 if (!NT_STATUS_IS_OK(status)) {
5456 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5457 goto fail;
5460 status = cli_nt_delete_on_close(cli1, fnum1, true);
5461 if (!NT_STATUS_IS_OK(status)) {
5462 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5463 goto fail;
5466 status = cli_close(cli1, fnum1);
5467 if (!NT_STATUS_IS_OK(status)) {
5468 printf("[2] close failed (%s)\n", nt_errstr(status));
5469 goto fail;
5472 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5473 if (NT_STATUS_IS_OK(status)) {
5474 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5475 status = cli_close(cli1, fnum1);
5476 if (!NT_STATUS_IS_OK(status)) {
5477 printf("[2] close failed (%s)\n", nt_errstr(status));
5479 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5480 goto fail;
5483 printf("second delete on close test succeeded.\n");
5485 /* Test 3 - ... */
5486 cli_setatr(cli1, fname, 0, 0);
5487 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5489 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5490 FILE_ATTRIBUTE_NORMAL,
5491 FILE_SHARE_READ|FILE_SHARE_WRITE,
5492 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5493 if (!NT_STATUS_IS_OK(status)) {
5494 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5495 goto fail;
5498 /* This should fail with a sharing violation - open for delete is only compatible
5499 with SHARE_DELETE. */
5501 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5502 FILE_ATTRIBUTE_NORMAL,
5503 FILE_SHARE_READ|FILE_SHARE_WRITE,
5504 FILE_OPEN, 0, 0, &fnum2, NULL);
5505 if (NT_STATUS_IS_OK(status)) {
5506 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
5507 goto fail;
5510 /* This should succeed. */
5511 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5512 FILE_ATTRIBUTE_NORMAL,
5513 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5514 FILE_OPEN, 0, 0, &fnum2, NULL);
5515 if (!NT_STATUS_IS_OK(status)) {
5516 printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5517 goto fail;
5520 status = cli_nt_delete_on_close(cli1, fnum1, true);
5521 if (!NT_STATUS_IS_OK(status)) {
5522 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5523 goto fail;
5526 status = cli_close(cli1, fnum1);
5527 if (!NT_STATUS_IS_OK(status)) {
5528 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5529 goto fail;
5532 status = cli_close(cli1, fnum2);
5533 if (!NT_STATUS_IS_OK(status)) {
5534 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5535 goto fail;
5538 /* This should fail - file should no longer be there. */
5540 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5541 if (NT_STATUS_IS_OK(status)) {
5542 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5543 status = cli_close(cli1, fnum1);
5544 if (!NT_STATUS_IS_OK(status)) {
5545 printf("[3] close failed (%s)\n", nt_errstr(status));
5547 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5548 goto fail;
5551 printf("third delete on close test succeeded.\n");
5553 /* Test 4 ... */
5554 cli_setatr(cli1, fname, 0, 0);
5555 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5557 status = cli_ntcreate(cli1, fname, 0,
5558 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5559 FILE_ATTRIBUTE_NORMAL,
5560 FILE_SHARE_READ|FILE_SHARE_WRITE,
5561 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5562 if (!NT_STATUS_IS_OK(status)) {
5563 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5564 goto fail;
5567 /* This should succeed. */
5568 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5569 FILE_ATTRIBUTE_NORMAL,
5570 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5571 FILE_OPEN, 0, 0, &fnum2, NULL);
5572 if (!NT_STATUS_IS_OK(status)) {
5573 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5574 goto fail;
5577 status = cli_close(cli1, fnum2);
5578 if (!NT_STATUS_IS_OK(status)) {
5579 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5580 goto fail;
5583 status = cli_nt_delete_on_close(cli1, fnum1, true);
5584 if (!NT_STATUS_IS_OK(status)) {
5585 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5586 goto fail;
5589 /* This should fail - no more opens once delete on close set. */
5590 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5591 FILE_ATTRIBUTE_NORMAL,
5592 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5593 FILE_OPEN, 0, 0, &fnum2, NULL);
5594 if (NT_STATUS_IS_OK(status)) {
5595 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
5596 goto fail;
5599 status = cli_close(cli1, fnum1);
5600 if (!NT_STATUS_IS_OK(status)) {
5601 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5602 goto fail;
5605 printf("fourth delete on close test succeeded.\n");
5607 /* Test 5 ... */
5608 cli_setatr(cli1, fname, 0, 0);
5609 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5611 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5612 if (!NT_STATUS_IS_OK(status)) {
5613 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5614 goto fail;
5617 /* This should fail - only allowed on NT opens with DELETE access. */
5619 status = cli_nt_delete_on_close(cli1, fnum1, true);
5620 if (NT_STATUS_IS_OK(status)) {
5621 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5622 goto fail;
5625 status = cli_close(cli1, fnum1);
5626 if (!NT_STATUS_IS_OK(status)) {
5627 printf("[5] close failed (%s)\n", nt_errstr(status));
5628 goto fail;
5631 printf("fifth delete on close test succeeded.\n");
5633 /* Test 6 ... */
5634 cli_setatr(cli1, fname, 0, 0);
5635 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5637 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5638 FILE_ATTRIBUTE_NORMAL,
5639 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5640 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5641 if (!NT_STATUS_IS_OK(status)) {
5642 printf("[6] open of %s failed (%s)\n", fname,
5643 nt_errstr(status));
5644 goto fail;
5647 /* This should fail - only allowed on NT opens with DELETE access. */
5649 status = cli_nt_delete_on_close(cli1, fnum1, true);
5650 if (NT_STATUS_IS_OK(status)) {
5651 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5652 goto fail;
5655 status = cli_close(cli1, fnum1);
5656 if (!NT_STATUS_IS_OK(status)) {
5657 printf("[6] close failed (%s)\n", nt_errstr(status));
5658 goto fail;
5661 printf("sixth delete on close test succeeded.\n");
5663 /* Test 7 ... */
5664 cli_setatr(cli1, fname, 0, 0);
5665 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5667 status = cli_ntcreate(cli1, fname, 0,
5668 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5669 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5670 0, 0, &fnum1, NULL);
5671 if (!NT_STATUS_IS_OK(status)) {
5672 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5673 goto fail;
5676 status = cli_nt_delete_on_close(cli1, fnum1, true);
5677 if (!NT_STATUS_IS_OK(status)) {
5678 printf("[7] setting delete_on_close on file failed !\n");
5679 goto fail;
5682 status = cli_nt_delete_on_close(cli1, fnum1, false);
5683 if (!NT_STATUS_IS_OK(status)) {
5684 printf("[7] unsetting delete_on_close on file failed !\n");
5685 goto fail;
5688 status = cli_close(cli1, fnum1);
5689 if (!NT_STATUS_IS_OK(status)) {
5690 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5691 goto fail;
5694 /* This next open should succeed - we reset the flag. */
5695 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5696 if (!NT_STATUS_IS_OK(status)) {
5697 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5698 goto fail;
5701 status = cli_close(cli1, fnum1);
5702 if (!NT_STATUS_IS_OK(status)) {
5703 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5704 goto fail;
5707 printf("seventh delete on close test succeeded.\n");
5709 /* Test 8 ... */
5710 cli_setatr(cli1, fname, 0, 0);
5711 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5713 if (!torture_open_connection(&cli2, 1)) {
5714 printf("[8] failed to open second connection.\n");
5715 goto fail;
5718 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5720 status = cli_ntcreate(cli1, fname, 0,
5721 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5722 FILE_ATTRIBUTE_NORMAL,
5723 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5724 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5725 if (!NT_STATUS_IS_OK(status)) {
5726 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5727 goto fail;
5730 status = cli_ntcreate(cli2, fname, 0,
5731 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5732 FILE_ATTRIBUTE_NORMAL,
5733 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5734 FILE_OPEN, 0, 0, &fnum2, NULL);
5735 if (!NT_STATUS_IS_OK(status)) {
5736 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5737 goto fail;
5740 status = cli_nt_delete_on_close(cli1, fnum1, true);
5741 if (!NT_STATUS_IS_OK(status)) {
5742 printf("[8] setting delete_on_close on file failed !\n");
5743 goto fail;
5746 status = cli_close(cli1, fnum1);
5747 if (!NT_STATUS_IS_OK(status)) {
5748 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5749 goto fail;
5752 status = cli_close(cli2, fnum2);
5753 if (!NT_STATUS_IS_OK(status)) {
5754 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5755 goto fail;
5758 /* This should fail.. */
5759 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5760 if (NT_STATUS_IS_OK(status)) {
5761 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5762 goto fail;
5765 printf("eighth delete on close test succeeded.\n");
5767 /* Test 9 ... */
5769 /* This should fail - we need to set DELETE_ACCESS. */
5770 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5771 FILE_ATTRIBUTE_NORMAL,
5772 FILE_SHARE_NONE,
5773 FILE_OVERWRITE_IF,
5774 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5775 if (NT_STATUS_IS_OK(status)) {
5776 printf("[9] open of %s succeeded should have failed!\n", fname);
5777 goto fail;
5780 printf("ninth delete on close test succeeded.\n");
5782 /* Test 10 ... */
5784 status = cli_ntcreate(cli1, fname, 0,
5785 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5786 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5787 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5788 0, &fnum1, NULL);
5789 if (!NT_STATUS_IS_OK(status)) {
5790 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5791 goto fail;
5794 /* This should delete the file. */
5795 status = cli_close(cli1, fnum1);
5796 if (!NT_STATUS_IS_OK(status)) {
5797 printf("[10] close failed (%s)\n", nt_errstr(status));
5798 goto fail;
5801 /* This should fail.. */
5802 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5803 if (NT_STATUS_IS_OK(status)) {
5804 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5805 goto fail;
5808 printf("tenth delete on close test succeeded.\n");
5810 /* Test 11 ... */
5812 cli_setatr(cli1, fname, 0, 0);
5813 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5815 /* Can we open a read-only file with delete access? */
5817 /* Create a readonly file. */
5818 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5819 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5820 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5821 if (!NT_STATUS_IS_OK(status)) {
5822 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5823 goto fail;
5826 status = cli_close(cli1, fnum1);
5827 if (!NT_STATUS_IS_OK(status)) {
5828 printf("[11] close failed (%s)\n", nt_errstr(status));
5829 goto fail;
5832 /* Now try open for delete access. */
5833 status = cli_ntcreate(cli1, fname, 0,
5834 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5836 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5837 FILE_OPEN, 0, 0, &fnum1, NULL);
5838 if (!NT_STATUS_IS_OK(status)) {
5839 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5840 goto fail;
5843 cli_close(cli1, fnum1);
5845 printf("eleventh delete on close test succeeded.\n");
5848 * Test 12
5849 * like test 4 but with initial delete on close
5852 cli_setatr(cli1, fname, 0, 0);
5853 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5855 status = cli_ntcreate(cli1, fname, 0,
5856 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5857 FILE_ATTRIBUTE_NORMAL,
5858 FILE_SHARE_READ|FILE_SHARE_WRITE,
5859 FILE_OVERWRITE_IF,
5860 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5861 if (!NT_STATUS_IS_OK(status)) {
5862 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5863 goto fail;
5866 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5867 FILE_ATTRIBUTE_NORMAL,
5868 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5869 FILE_OPEN, 0, 0, &fnum2, NULL);
5870 if (!NT_STATUS_IS_OK(status)) {
5871 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5872 goto fail;
5875 status = cli_close(cli1, fnum2);
5876 if (!NT_STATUS_IS_OK(status)) {
5877 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5878 goto fail;
5881 status = cli_nt_delete_on_close(cli1, fnum1, true);
5882 if (!NT_STATUS_IS_OK(status)) {
5883 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5884 goto fail;
5887 /* This should fail - no more opens once delete on close set. */
5888 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5889 FILE_ATTRIBUTE_NORMAL,
5890 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5891 FILE_OPEN, 0, 0, &fnum2, NULL);
5892 if (NT_STATUS_IS_OK(status)) {
5893 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5894 goto fail;
5897 status = cli_nt_delete_on_close(cli1, fnum1, false);
5898 if (!NT_STATUS_IS_OK(status)) {
5899 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5900 goto fail;
5903 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5904 FILE_ATTRIBUTE_NORMAL,
5905 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5906 FILE_OPEN, 0, 0, &fnum2, NULL);
5907 if (!NT_STATUS_IS_OK(status)) {
5908 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5909 goto fail;
5912 status = cli_close(cli1, fnum2);
5913 if (!NT_STATUS_IS_OK(status)) {
5914 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5915 goto fail;
5918 status = cli_close(cli1, fnum1);
5919 if (!NT_STATUS_IS_OK(status)) {
5920 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5921 goto fail;
5925 * setting delete on close on the handle does
5926 * not unset the initial delete on close...
5928 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5929 FILE_ATTRIBUTE_NORMAL,
5930 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5931 FILE_OPEN, 0, 0, &fnum2, NULL);
5932 if (NT_STATUS_IS_OK(status)) {
5933 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5934 goto fail;
5935 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5936 printf("ntcreate returned %s, expected "
5937 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5938 nt_errstr(status));
5939 goto fail;
5942 printf("twelfth delete on close test succeeded.\n");
5945 printf("finished delete test\n");
5947 correct = true;
5949 fail:
5950 /* FIXME: This will crash if we aborted before cli2 got
5951 * initialized, because these functions don't handle
5952 * uninitialized connections. */
5954 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5955 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5956 cli_setatr(cli1, fname, 0, 0);
5957 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5959 if (cli1 && !torture_close_connection(cli1)) {
5960 correct = False;
5962 if (cli2 && !torture_close_connection(cli2)) {
5963 correct = False;
5965 return correct;
5968 struct delete_stream_state {
5969 bool closed;
5972 static void delete_stream_unlinked(struct tevent_req *subreq);
5973 static void delete_stream_closed(struct tevent_req *subreq);
5975 static struct tevent_req *delete_stream_send(
5976 TALLOC_CTX *mem_ctx,
5977 struct tevent_context *ev,
5978 struct cli_state *cli,
5979 const char *base_fname,
5980 uint16_t stream_fnum)
5982 struct tevent_req *req = NULL, *subreq = NULL;
5983 struct delete_stream_state *state = NULL;
5985 req = tevent_req_create(
5986 mem_ctx, &state, struct delete_stream_state);
5987 if (req == NULL) {
5988 return NULL;
5991 subreq = cli_unlink_send(
5992 state,
5994 cli,
5995 base_fname,
5996 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5997 if (tevent_req_nomem(subreq, req)) {
5998 return tevent_req_post(req, ev);
6000 tevent_req_set_callback(subreq, delete_stream_unlinked, req);
6002 subreq = cli_close_send(state, ev, cli, stream_fnum, 0);
6003 if (tevent_req_nomem(subreq, req)) {
6004 return tevent_req_post(req, ev);
6006 tevent_req_set_callback(subreq, delete_stream_closed, req);
6008 return req;
6011 static void delete_stream_unlinked(struct tevent_req *subreq)
6013 struct tevent_req *req = tevent_req_callback_data(
6014 subreq, struct tevent_req);
6015 struct delete_stream_state *state = tevent_req_data(
6016 req, struct delete_stream_state);
6017 NTSTATUS status;
6019 status = cli_unlink_recv(subreq);
6020 TALLOC_FREE(subreq);
6021 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6022 printf("cli_unlink returned %s\n",
6023 nt_errstr(status));
6024 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6025 return;
6027 if (!state->closed) {
6028 /* close reply should have come in first */
6029 printf("Not closed\n");
6030 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6031 return;
6033 tevent_req_done(req);
6036 static void delete_stream_closed(struct tevent_req *subreq)
6038 struct tevent_req *req = tevent_req_callback_data(
6039 subreq, struct tevent_req);
6040 struct delete_stream_state *state = tevent_req_data(
6041 req, struct delete_stream_state);
6042 NTSTATUS status;
6044 status = cli_close_recv(subreq);
6045 TALLOC_FREE(subreq);
6046 if (tevent_req_nterror(req, status)) {
6047 return;
6049 /* also waiting for the unlink to come back */
6050 state->closed = true;
6053 static NTSTATUS delete_stream_recv(struct tevent_req *req)
6055 return tevent_req_simple_recv_ntstatus(req);
6058 static bool run_delete_stream(int dummy)
6060 struct tevent_context *ev = NULL;
6061 struct tevent_req *req = NULL;
6062 struct cli_state *cli = NULL;
6063 const char fname[] = "delete_stream";
6064 const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
6065 uint16_t fnum1, fnum2;
6066 NTSTATUS status;
6067 bool ok;
6069 printf("Starting stream delete test\n");
6071 ok = torture_open_connection(&cli, 0);
6072 if (!ok) {
6073 return false;
6076 cli_setatr(cli, fname, 0, 0);
6077 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6079 /* Create the file. */
6080 status = cli_ntcreate(
6081 cli,
6082 fname,
6084 READ_CONTROL_ACCESS,
6086 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6087 FILE_CREATE,
6088 0x0,
6089 0x0,
6090 &fnum1,
6091 NULL);
6092 if (!NT_STATUS_IS_OK(status)) {
6093 d_fprintf(stderr,
6094 "cli_ntcreate of %s failed (%s)\n",
6095 fname,
6096 nt_errstr(status));
6097 return false;
6099 status = cli_close(cli, fnum1);
6100 if (!NT_STATUS_IS_OK(status)) {
6101 d_fprintf(stderr,
6102 "cli_close of %s failed (%s)\n",
6103 fname,
6104 nt_errstr(status));
6105 return false;
6108 /* Now create the stream. */
6109 status = cli_ntcreate(
6110 cli,
6111 fname_stream,
6113 FILE_WRITE_DATA,
6115 FILE_SHARE_READ|FILE_SHARE_WRITE,
6116 FILE_CREATE,
6117 0x0,
6118 0x0,
6119 &fnum1,
6120 NULL);
6122 if (!NT_STATUS_IS_OK(status)) {
6123 d_fprintf(stderr,
6124 "cli_ntcreate of %s failed (%s)\n",
6125 fname_stream,
6126 nt_errstr(status));
6127 return false;
6130 /* open it a second time */
6132 status = cli_ntcreate(
6133 cli,
6134 fname_stream,
6136 FILE_WRITE_DATA,
6138 FILE_SHARE_READ|FILE_SHARE_WRITE,
6139 FILE_OPEN,
6140 0x0,
6141 0x0,
6142 &fnum2,
6143 NULL);
6145 if (!NT_STATUS_IS_OK(status)) {
6146 d_fprintf(stderr,
6147 "2nd cli_ntcreate of %s failed (%s)\n",
6148 fname_stream,
6149 nt_errstr(status));
6150 return false;
6153 ev = samba_tevent_context_init(talloc_tos());
6154 if (ev == NULL) {
6155 d_fprintf(stderr, "samba_tevent_context_init failed\n");
6156 return false;
6159 req = delete_stream_send(ev, ev, cli, fname, fnum1);
6160 if (req == NULL) {
6161 d_fprintf(stderr, "delete_stream_send failed\n");
6162 return false;
6165 ok = tevent_req_poll_ntstatus(req, ev, &status);
6166 if (!ok) {
6167 d_fprintf(stderr,
6168 "tevent_req_poll_ntstatus failed: %s\n",
6169 nt_errstr(status));
6170 return false;
6173 status = delete_stream_recv(req);
6174 TALLOC_FREE(req);
6175 if (!NT_STATUS_IS_OK(status)) {
6176 d_fprintf(stderr,
6177 "delete_stream failed: %s\n",
6178 nt_errstr(status));
6179 return false;
6182 status = cli_close(cli, fnum2);
6183 if (!NT_STATUS_IS_OK(status)) {
6184 d_fprintf(stderr,
6185 "close failed: %s\n",
6186 nt_errstr(status));
6187 return false;
6190 status = cli_unlink(
6191 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6192 if (!NT_STATUS_IS_OK(status)) {
6193 d_fprintf(stderr,
6194 "unlink failed: %s\n",
6195 nt_errstr(status));
6196 return false;
6199 return true;
6203 Exercise delete on close semantics - use on the PRINT1 share in torture
6204 testing.
6206 static bool run_delete_print_test(int dummy)
6208 struct cli_state *cli1 = NULL;
6209 const char *fname = "print_delete.file";
6210 uint16_t fnum1 = (uint16_t)-1;
6211 bool correct = false;
6212 const char *buf = "print file data\n";
6213 NTSTATUS status;
6215 printf("starting print delete test\n");
6217 if (!torture_open_connection(&cli1, 0)) {
6218 return false;
6221 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6223 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6224 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6225 0, 0, &fnum1, NULL);
6226 if (!NT_STATUS_IS_OK(status)) {
6227 printf("open of %s failed (%s)\n",
6228 fname,
6229 nt_errstr(status));
6230 goto fail;
6233 status = cli_writeall(cli1,
6234 fnum1,
6236 (const uint8_t *)buf,
6237 0, /* offset */
6238 strlen(buf), /* size */
6239 NULL);
6240 if (!NT_STATUS_IS_OK(status)) {
6241 printf("writing print file data failed (%s)\n",
6242 nt_errstr(status));
6243 goto fail;
6246 status = cli_nt_delete_on_close(cli1, fnum1, true);
6247 if (!NT_STATUS_IS_OK(status)) {
6248 printf("setting delete_on_close failed (%s)\n",
6249 nt_errstr(status));
6250 goto fail;
6253 status = cli_close(cli1, fnum1);
6254 if (!NT_STATUS_IS_OK(status)) {
6255 printf("close failed (%s)\n", nt_errstr(status));
6256 goto fail;
6259 printf("finished print delete test\n");
6261 correct = true;
6263 fail:
6265 if (fnum1 != (uint16_t)-1) {
6266 cli_close(cli1, fnum1);
6269 if (cli1 && !torture_close_connection(cli1)) {
6270 correct = false;
6272 return correct;
6275 static bool run_deletetest_ln(int dummy)
6277 struct cli_state *cli;
6278 const char *fname = "\\delete1";
6279 const char *fname_ln = "\\delete1_ln";
6280 uint16_t fnum;
6281 uint16_t fnum1;
6282 NTSTATUS status;
6283 bool correct = true;
6284 time_t t;
6286 printf("starting deletetest-ln\n");
6288 if (!torture_open_connection(&cli, 0)) {
6289 return false;
6292 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6293 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6295 smbXcli_conn_set_sockopt(cli->conn, sockops);
6297 /* Create the file. */
6298 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6299 if (!NT_STATUS_IS_OK(status)) {
6300 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6301 return false;
6304 status = cli_close(cli, fnum);
6305 if (!NT_STATUS_IS_OK(status)) {
6306 printf("close1 failed (%s)\n", nt_errstr(status));
6307 return false;
6310 /* Now create a hardlink. */
6311 status = cli_hardlink(cli, fname, fname_ln);
6312 if (!NT_STATUS_IS_OK(status)) {
6313 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6314 return false;
6317 /* Open the original file. */
6318 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6319 FILE_ATTRIBUTE_NORMAL,
6320 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6321 FILE_OPEN_IF, 0, 0, &fnum, NULL);
6322 if (!NT_STATUS_IS_OK(status)) {
6323 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6324 return false;
6327 /* Unlink the hard link path. */
6328 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6329 FILE_ATTRIBUTE_NORMAL,
6330 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6331 FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6332 if (!NT_STATUS_IS_OK(status)) {
6333 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6334 return false;
6336 status = cli_nt_delete_on_close(cli, fnum1, true);
6337 if (!NT_STATUS_IS_OK(status)) {
6338 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6339 __location__, fname_ln, nt_errstr(status));
6340 return false;
6343 status = cli_close(cli, fnum1);
6344 if (!NT_STATUS_IS_OK(status)) {
6345 printf("close %s failed (%s)\n",
6346 fname_ln, nt_errstr(status));
6347 return false;
6350 status = cli_close(cli, fnum);
6351 if (!NT_STATUS_IS_OK(status)) {
6352 printf("close %s failed (%s)\n",
6353 fname, nt_errstr(status));
6354 return false;
6357 /* Ensure the original file is still there. */
6358 status = cli_getatr(cli, fname, NULL, NULL, &t);
6359 if (!NT_STATUS_IS_OK(status)) {
6360 printf("%s getatr on file %s failed (%s)\n",
6361 __location__,
6362 fname,
6363 nt_errstr(status));
6364 correct = False;
6367 /* Ensure the link path is gone. */
6368 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6369 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6370 printf("%s, getatr for file %s returned wrong error code %s "
6371 "- should have been deleted\n",
6372 __location__,
6373 fname_ln, nt_errstr(status));
6374 correct = False;
6377 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6378 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6380 if (!torture_close_connection(cli)) {
6381 correct = false;
6384 printf("finished deletetest-ln\n");
6386 return correct;
6390 print out server properties
6392 static bool run_properties(int dummy)
6394 struct cli_state *cli;
6395 bool correct = True;
6397 printf("starting properties test\n");
6399 ZERO_STRUCT(cli);
6401 if (!torture_open_connection(&cli, 0)) {
6402 return False;
6405 smbXcli_conn_set_sockopt(cli->conn, sockops);
6407 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6409 if (!torture_close_connection(cli)) {
6410 correct = False;
6413 return correct;
6418 /* FIRST_DESIRED_ACCESS 0xf019f */
6419 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6420 FILE_READ_EA| /* 0xf */ \
6421 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
6422 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
6423 DELETE_ACCESS|READ_CONTROL_ACCESS|\
6424 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
6425 /* SECOND_DESIRED_ACCESS 0xe0080 */
6426 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6427 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6428 WRITE_OWNER_ACCESS /* 0xe0000 */
6430 #if 0
6431 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6432 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6433 FILE_READ_DATA|\
6434 WRITE_OWNER_ACCESS /* */
6435 #endif
6438 Test ntcreate calls made by xcopy
6440 static bool run_xcopy(int dummy)
6442 static struct cli_state *cli1;
6443 const char *fname = "\\test.txt";
6444 bool correct = True;
6445 uint16_t fnum1, fnum2;
6446 NTSTATUS status;
6448 printf("starting xcopy test\n");
6450 if (!torture_open_connection(&cli1, 0)) {
6451 return False;
6454 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6455 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6456 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6457 if (!NT_STATUS_IS_OK(status)) {
6458 printf("First open failed - %s\n", nt_errstr(status));
6459 return False;
6462 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6463 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6464 FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6465 if (!NT_STATUS_IS_OK(status)) {
6466 printf("second open failed - %s\n", nt_errstr(status));
6467 return False;
6470 if (!torture_close_connection(cli1)) {
6471 correct = False;
6474 return correct;
6478 Test rename on files open with share delete and no share delete.
6480 static bool run_rename(int dummy)
6482 static struct cli_state *cli1;
6483 const char *fname = "\\test.txt";
6484 const char *fname1 = "\\test1.txt";
6485 bool correct = True;
6486 uint16_t fnum1;
6487 uint32_t attr;
6488 NTSTATUS status;
6490 printf("starting rename test\n");
6492 if (!torture_open_connection(&cli1, 0)) {
6493 return False;
6496 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6497 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6499 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6500 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6501 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6502 if (!NT_STATUS_IS_OK(status)) {
6503 printf("First open failed - %s\n", nt_errstr(status));
6504 return False;
6507 status = cli_rename(cli1, fname, fname1, false);
6508 if (!NT_STATUS_IS_OK(status)) {
6509 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6510 } else {
6511 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6512 correct = False;
6515 status = cli_close(cli1, fnum1);
6516 if (!NT_STATUS_IS_OK(status)) {
6517 printf("close - 1 failed (%s)\n", nt_errstr(status));
6518 return False;
6521 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6522 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6523 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6524 #if 0
6525 FILE_SHARE_DELETE|FILE_SHARE_NONE,
6526 #else
6527 FILE_SHARE_DELETE|FILE_SHARE_READ,
6528 #endif
6529 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6530 if (!NT_STATUS_IS_OK(status)) {
6531 printf("Second open failed - %s\n", nt_errstr(status));
6532 return False;
6535 status = cli_rename(cli1, fname, fname1, false);
6536 if (!NT_STATUS_IS_OK(status)) {
6537 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6538 correct = False;
6539 } else {
6540 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6543 status = cli_close(cli1, fnum1);
6544 if (!NT_STATUS_IS_OK(status)) {
6545 printf("close - 2 failed (%s)\n", nt_errstr(status));
6546 return False;
6549 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6550 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6552 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6553 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6554 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6555 if (!NT_STATUS_IS_OK(status)) {
6556 printf("Third open failed - %s\n", nt_errstr(status));
6557 return False;
6561 status = cli_rename(cli1, fname, fname1, false);
6562 if (!NT_STATUS_IS_OK(status)) {
6563 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6564 correct = False;
6565 } else {
6566 printf("Third rename succeeded (SHARE_NONE)\n");
6569 status = cli_close(cli1, fnum1);
6570 if (!NT_STATUS_IS_OK(status)) {
6571 printf("close - 3 failed (%s)\n", nt_errstr(status));
6572 return False;
6575 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6576 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6578 /*----*/
6580 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6581 FILE_ATTRIBUTE_NORMAL,
6582 FILE_SHARE_READ | FILE_SHARE_WRITE,
6583 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6584 if (!NT_STATUS_IS_OK(status)) {
6585 printf("Fourth open failed - %s\n", nt_errstr(status));
6586 return False;
6589 status = cli_rename(cli1, fname, fname1, false);
6590 if (!NT_STATUS_IS_OK(status)) {
6591 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6592 } else {
6593 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6594 correct = False;
6597 status = cli_close(cli1, fnum1);
6598 if (!NT_STATUS_IS_OK(status)) {
6599 printf("close - 4 failed (%s)\n", nt_errstr(status));
6600 return False;
6603 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6604 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6606 /*--*/
6608 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6609 FILE_ATTRIBUTE_NORMAL,
6610 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6611 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6612 if (!NT_STATUS_IS_OK(status)) {
6613 printf("Fifth open failed - %s\n", nt_errstr(status));
6614 return False;
6617 status = cli_rename(cli1, fname, fname1, false);
6618 if (!NT_STATUS_IS_OK(status)) {
6619 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6620 correct = False;
6621 } else {
6622 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6625 /*--*/
6626 status = cli_close(cli1, fnum1);
6627 if (!NT_STATUS_IS_OK(status)) {
6628 printf("close - 5 failed (%s)\n", nt_errstr(status));
6629 return False;
6632 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6633 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6634 if (!NT_STATUS_IS_OK(status)) {
6635 printf("getatr on file %s failed - %s ! \n",
6636 fname1, nt_errstr(status));
6637 correct = False;
6638 } else {
6639 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6640 printf("Renamed file %s has wrong attr 0x%x "
6641 "(should be 0x%x)\n",
6642 fname1,
6643 attr,
6644 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6645 correct = False;
6646 } else {
6647 printf("Renamed file %s has archive bit set\n", fname1);
6651 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6652 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6654 if (!torture_close_connection(cli1)) {
6655 correct = False;
6658 return correct;
6662 Test rename into a directory with an ACL denying it.
6664 static bool run_rename_access(int dummy)
6666 static struct cli_state *cli = NULL;
6667 static struct cli_state *posix_cli = NULL;
6668 const char *src = "test.txt";
6669 const char *dname = "dir";
6670 const char *dst = "dir\\test.txt";
6671 const char *dsrc = "test.dir";
6672 const char *ddst = "dir\\test.dir";
6673 uint16_t fnum = (uint16_t)-1;
6674 struct security_descriptor *sd = NULL;
6675 struct security_descriptor *newsd = NULL;
6676 NTSTATUS status;
6677 TALLOC_CTX *frame = NULL;
6679 frame = talloc_stackframe();
6680 printf("starting rename access test\n");
6682 /* Windows connection. */
6683 if (!torture_open_connection(&cli, 0)) {
6684 goto fail;
6687 smbXcli_conn_set_sockopt(cli->conn, sockops);
6689 /* Posix connection. */
6690 if (!torture_open_connection(&posix_cli, 0)) {
6691 goto fail;
6694 smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6696 status = torture_setup_unix_extensions(posix_cli);
6697 if (!NT_STATUS_IS_OK(status)) {
6698 goto fail;
6701 /* Start with a clean slate. */
6702 cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6703 cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6704 cli_rmdir(cli, dsrc);
6705 cli_rmdir(cli, ddst);
6706 cli_rmdir(cli, dname);
6709 * Setup the destination directory with a DENY ACE to
6710 * prevent new files within it.
6712 status = cli_ntcreate(cli,
6713 dname,
6715 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6716 WRITE_DAC_ACCESS|FILE_READ_DATA|
6717 WRITE_OWNER_ACCESS,
6718 FILE_ATTRIBUTE_DIRECTORY,
6719 FILE_SHARE_READ|FILE_SHARE_WRITE,
6720 FILE_CREATE,
6721 FILE_DIRECTORY_FILE,
6723 &fnum,
6724 NULL);
6725 if (!NT_STATUS_IS_OK(status)) {
6726 printf("Create of %s - %s\n", dname, nt_errstr(status));
6727 goto fail;
6730 status = cli_query_secdesc(cli,
6731 fnum,
6732 frame,
6733 &sd);
6734 if (!NT_STATUS_IS_OK(status)) {
6735 printf("cli_query_secdesc failed for %s (%s)\n",
6736 dname, nt_errstr(status));
6737 goto fail;
6740 newsd = security_descriptor_dacl_create(frame,
6742 NULL,
6743 NULL,
6744 SID_WORLD,
6745 SEC_ACE_TYPE_ACCESS_DENIED,
6746 SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6748 NULL);
6749 if (newsd == NULL) {
6750 goto fail;
6752 sd->dacl = security_acl_concatenate(frame,
6753 newsd->dacl,
6754 sd->dacl);
6755 if (sd->dacl == NULL) {
6756 goto fail;
6758 status = cli_set_secdesc(cli, fnum, sd);
6759 if (!NT_STATUS_IS_OK(status)) {
6760 printf("cli_set_secdesc failed for %s (%s)\n",
6761 dname, nt_errstr(status));
6762 goto fail;
6764 status = cli_close(cli, fnum);
6765 if (!NT_STATUS_IS_OK(status)) {
6766 printf("close failed for %s (%s)\n",
6767 dname, nt_errstr(status));
6768 goto fail;
6770 /* Now go around the back and chmod to 777 via POSIX. */
6771 status = cli_chmod(posix_cli, dname, 0777);
6772 if (!NT_STATUS_IS_OK(status)) {
6773 printf("cli_chmod failed for %s (%s)\n",
6774 dname,
6775 nt_errstr(status));
6776 goto fail;
6779 /* Check we can't create a file within dname via Windows. */
6780 status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6781 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6782 cli_close(posix_cli, fnum);
6783 printf("Create of %s should be ACCESS denied, was %s\n",
6784 dst, nt_errstr(status));
6785 goto fail;
6788 /* Make the sample file/directory. */
6789 status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6790 if (!NT_STATUS_IS_OK(status)) {
6791 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6792 goto fail;
6794 status = cli_close(cli, fnum);
6795 if (!NT_STATUS_IS_OK(status)) {
6796 printf("cli_close failed (%s)\n", nt_errstr(status));
6797 goto fail;
6800 status = cli_mkdir(cli, dsrc);
6801 if (!NT_STATUS_IS_OK(status)) {
6802 printf("cli_mkdir of %s failed (%s)\n",
6803 dsrc, nt_errstr(status));
6804 goto fail;
6808 * OK - renames of the new file and directory into the
6809 * dst directory should fail.
6812 status = cli_rename(cli, src, dst, false);
6813 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6814 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6815 src, dst, nt_errstr(status));
6816 goto fail;
6818 status = cli_rename(cli, dsrc, ddst, false);
6819 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6820 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6821 src, dst, nt_errstr(status));
6822 goto fail;
6825 TALLOC_FREE(frame);
6826 return true;
6828 fail:
6830 if (posix_cli) {
6831 torture_close_connection(posix_cli);
6834 if (cli) {
6835 if (fnum != (uint16_t)-1) {
6836 cli_close(cli, fnum);
6838 cli_unlink(cli, src,
6839 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6840 cli_unlink(cli, dst,
6841 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6842 cli_rmdir(cli, dsrc);
6843 cli_rmdir(cli, ddst);
6844 cli_rmdir(cli, dname);
6846 torture_close_connection(cli);
6849 TALLOC_FREE(frame);
6850 return false;
6854 Test owner rights ACE.
6856 static bool run_owner_rights(int dummy)
6858 static struct cli_state *cli = NULL;
6859 const char *fname = "owner_rights.txt";
6860 uint16_t fnum = (uint16_t)-1;
6861 struct security_descriptor *sd = NULL;
6862 struct security_descriptor *newsd = NULL;
6863 NTSTATUS status;
6864 TALLOC_CTX *frame = NULL;
6866 frame = talloc_stackframe();
6867 printf("starting owner rights test\n");
6869 /* Windows connection. */
6870 if (!torture_open_connection(&cli, 0)) {
6871 goto fail;
6874 smbXcli_conn_set_sockopt(cli->conn, sockops);
6876 /* Start with a clean slate. */
6877 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6879 /* Create the test file. */
6880 /* Now try and open for read and write-dac. */
6881 status = cli_ntcreate(cli,
6882 fname,
6884 GENERIC_ALL_ACCESS,
6885 FILE_ATTRIBUTE_NORMAL,
6886 FILE_SHARE_READ|FILE_SHARE_WRITE|
6887 FILE_SHARE_DELETE,
6888 FILE_CREATE,
6891 &fnum,
6892 NULL);
6893 if (!NT_STATUS_IS_OK(status)) {
6894 printf("Create of %s - %s\n", fname, nt_errstr(status));
6895 goto fail;
6898 /* Get the original SD. */
6899 status = cli_query_secdesc(cli,
6900 fnum,
6901 frame,
6902 &sd);
6903 if (!NT_STATUS_IS_OK(status)) {
6904 printf("cli_query_secdesc failed for %s (%s)\n",
6905 fname, nt_errstr(status));
6906 goto fail;
6910 * Add an "owner-rights" ACE denying WRITE_DATA,
6911 * and an "owner-rights" ACE allowing READ_DATA.
6914 newsd = security_descriptor_dacl_create(frame,
6916 NULL,
6917 NULL,
6918 SID_OWNER_RIGHTS,
6919 SEC_ACE_TYPE_ACCESS_DENIED,
6920 FILE_WRITE_DATA,
6922 SID_OWNER_RIGHTS,
6923 SEC_ACE_TYPE_ACCESS_ALLOWED,
6924 FILE_READ_DATA,
6926 NULL);
6927 if (newsd == NULL) {
6928 goto fail;
6930 sd->dacl = security_acl_concatenate(frame,
6931 newsd->dacl,
6932 sd->dacl);
6933 if (sd->dacl == NULL) {
6934 goto fail;
6936 status = cli_set_secdesc(cli, fnum, sd);
6937 if (!NT_STATUS_IS_OK(status)) {
6938 printf("cli_set_secdesc failed for %s (%s)\n",
6939 fname, nt_errstr(status));
6940 goto fail;
6942 status = cli_close(cli, fnum);
6943 if (!NT_STATUS_IS_OK(status)) {
6944 printf("close failed for %s (%s)\n",
6945 fname, nt_errstr(status));
6946 goto fail;
6948 fnum = (uint16_t)-1;
6950 /* Try and open for FILE_WRITE_DATA */
6951 status = cli_ntcreate(cli,
6952 fname,
6954 FILE_WRITE_DATA,
6955 FILE_ATTRIBUTE_NORMAL,
6956 FILE_SHARE_READ|FILE_SHARE_WRITE|
6957 FILE_SHARE_DELETE,
6958 FILE_OPEN,
6961 &fnum,
6962 NULL);
6963 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6964 printf("Open of %s - %s\n", fname, nt_errstr(status));
6965 goto fail;
6968 /* Now try and open for FILE_READ_DATA */
6969 status = cli_ntcreate(cli,
6970 fname,
6972 FILE_READ_DATA,
6973 FILE_ATTRIBUTE_NORMAL,
6974 FILE_SHARE_READ|FILE_SHARE_WRITE|
6975 FILE_SHARE_DELETE,
6976 FILE_OPEN,
6979 &fnum,
6980 NULL);
6981 if (!NT_STATUS_IS_OK(status)) {
6982 printf("Open of %s - %s\n", fname, nt_errstr(status));
6983 goto fail;
6986 status = cli_close(cli, fnum);
6987 if (!NT_STATUS_IS_OK(status)) {
6988 printf("close failed for %s (%s)\n",
6989 fname, nt_errstr(status));
6990 goto fail;
6993 /* Restore clean slate. */
6994 TALLOC_FREE(sd);
6995 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6997 /* Create the test file. */
6998 status = cli_ntcreate(cli,
6999 fname,
7001 GENERIC_ALL_ACCESS,
7002 FILE_ATTRIBUTE_NORMAL,
7003 FILE_SHARE_READ|FILE_SHARE_WRITE|
7004 FILE_SHARE_DELETE,
7005 FILE_CREATE,
7008 &fnum,
7009 NULL);
7010 if (!NT_STATUS_IS_OK(status)) {
7011 printf("Create of %s - %s\n", fname, nt_errstr(status));
7012 goto fail;
7015 /* Get the original SD. */
7016 status = cli_query_secdesc(cli,
7017 fnum,
7018 frame,
7019 &sd);
7020 if (!NT_STATUS_IS_OK(status)) {
7021 printf("cli_query_secdesc failed for %s (%s)\n",
7022 fname, nt_errstr(status));
7023 goto fail;
7027 * Add an "owner-rights ACE denying WRITE_DATA,
7028 * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
7031 newsd = security_descriptor_dacl_create(frame,
7033 NULL,
7034 NULL,
7035 SID_OWNER_RIGHTS,
7036 SEC_ACE_TYPE_ACCESS_DENIED,
7037 FILE_WRITE_DATA,
7039 SID_OWNER_RIGHTS,
7040 SEC_ACE_TYPE_ACCESS_ALLOWED,
7041 FILE_READ_DATA|FILE_WRITE_DATA,
7043 NULL);
7044 if (newsd == NULL) {
7045 goto fail;
7047 sd->dacl = security_acl_concatenate(frame,
7048 newsd->dacl,
7049 sd->dacl);
7050 if (sd->dacl == NULL) {
7051 goto fail;
7053 status = cli_set_secdesc(cli, fnum, sd);
7054 if (!NT_STATUS_IS_OK(status)) {
7055 printf("cli_set_secdesc failed for %s (%s)\n",
7056 fname, nt_errstr(status));
7057 goto fail;
7059 status = cli_close(cli, fnum);
7060 if (!NT_STATUS_IS_OK(status)) {
7061 printf("close failed for %s (%s)\n",
7062 fname, nt_errstr(status));
7063 goto fail;
7065 fnum = (uint16_t)-1;
7067 /* Try and open for FILE_WRITE_DATA */
7068 status = cli_ntcreate(cli,
7069 fname,
7071 FILE_WRITE_DATA,
7072 FILE_ATTRIBUTE_NORMAL,
7073 FILE_SHARE_READ|FILE_SHARE_WRITE|
7074 FILE_SHARE_DELETE,
7075 FILE_OPEN,
7078 &fnum,
7079 NULL);
7080 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7081 printf("Open of %s - %s\n", fname, nt_errstr(status));
7082 goto fail;
7085 /* Now try and open for FILE_READ_DATA */
7086 status = cli_ntcreate(cli,
7087 fname,
7089 FILE_READ_DATA,
7090 FILE_ATTRIBUTE_NORMAL,
7091 FILE_SHARE_READ|FILE_SHARE_WRITE|
7092 FILE_SHARE_DELETE,
7093 FILE_OPEN,
7096 &fnum,
7097 NULL);
7098 if (!NT_STATUS_IS_OK(status)) {
7099 printf("Open of %s - %s\n", fname, nt_errstr(status));
7100 goto fail;
7103 status = cli_close(cli, fnum);
7104 if (!NT_STATUS_IS_OK(status)) {
7105 printf("close failed for %s (%s)\n",
7106 fname, nt_errstr(status));
7107 goto fail;
7110 /* Restore clean slate. */
7111 TALLOC_FREE(sd);
7112 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7115 /* Create the test file. */
7116 status = cli_ntcreate(cli,
7117 fname,
7119 GENERIC_ALL_ACCESS,
7120 FILE_ATTRIBUTE_NORMAL,
7121 FILE_SHARE_READ|FILE_SHARE_WRITE|
7122 FILE_SHARE_DELETE,
7123 FILE_CREATE,
7126 &fnum,
7127 NULL);
7128 if (!NT_STATUS_IS_OK(status)) {
7129 printf("Create of %s - %s\n", fname, nt_errstr(status));
7130 goto fail;
7133 /* Get the original SD. */
7134 status = cli_query_secdesc(cli,
7135 fnum,
7136 frame,
7137 &sd);
7138 if (!NT_STATUS_IS_OK(status)) {
7139 printf("cli_query_secdesc failed for %s (%s)\n",
7140 fname, nt_errstr(status));
7141 goto fail;
7145 * Add an "authenticated users" ACE allowing READ_DATA,
7146 * add an "owner-rights" denying READ_DATA,
7147 * and an "authenticated users" ACE allowing WRITE_DATA.
7150 newsd = security_descriptor_dacl_create(frame,
7152 NULL,
7153 NULL,
7154 SID_NT_AUTHENTICATED_USERS,
7155 SEC_ACE_TYPE_ACCESS_ALLOWED,
7156 FILE_READ_DATA,
7158 SID_OWNER_RIGHTS,
7159 SEC_ACE_TYPE_ACCESS_DENIED,
7160 FILE_READ_DATA,
7162 SID_NT_AUTHENTICATED_USERS,
7163 SEC_ACE_TYPE_ACCESS_ALLOWED,
7164 FILE_WRITE_DATA,
7166 NULL);
7167 if (newsd == NULL) {
7168 printf("newsd == NULL\n");
7169 goto fail;
7171 sd->dacl = security_acl_concatenate(frame,
7172 newsd->dacl,
7173 sd->dacl);
7174 if (sd->dacl == NULL) {
7175 printf("sd->dacl == NULL\n");
7176 goto fail;
7178 status = cli_set_secdesc(cli, fnum, sd);
7179 if (!NT_STATUS_IS_OK(status)) {
7180 printf("cli_set_secdesc failed for %s (%s)\n",
7181 fname, nt_errstr(status));
7182 goto fail;
7184 status = cli_close(cli, fnum);
7185 if (!NT_STATUS_IS_OK(status)) {
7186 printf("close failed for %s (%s)\n",
7187 fname, nt_errstr(status));
7188 goto fail;
7190 fnum = (uint16_t)-1;
7192 /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7193 status = cli_ntcreate(cli,
7194 fname,
7196 FILE_READ_DATA|FILE_WRITE_DATA,
7197 FILE_ATTRIBUTE_NORMAL,
7198 FILE_SHARE_READ|FILE_SHARE_WRITE|
7199 FILE_SHARE_DELETE,
7200 FILE_OPEN,
7203 &fnum,
7204 NULL);
7205 if (!NT_STATUS_IS_OK(status)) {
7206 printf("Open of %s - %s\n", fname, nt_errstr(status));
7207 goto fail;
7210 status = cli_close(cli, fnum);
7211 if (!NT_STATUS_IS_OK(status)) {
7212 printf("close failed for %s (%s)\n",
7213 fname, nt_errstr(status));
7214 goto fail;
7217 cli_unlink(cli, fname,
7218 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7220 TALLOC_FREE(frame);
7221 return true;
7223 fail:
7225 if (cli) {
7226 if (fnum != (uint16_t)-1) {
7227 cli_close(cli, fnum);
7229 cli_unlink(cli, fname,
7230 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7231 torture_close_connection(cli);
7234 TALLOC_FREE(frame);
7235 return false;
7239 * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7240 * Note this test only works with a user with SeSecurityPrivilege set.
7242 * NB. This is also tested in samba3.base.createx_access
7243 * but this makes it very explicit what we're looking for.
7245 static bool run_smb1_system_security(int dummy)
7247 static struct cli_state *cli = NULL;
7248 const char *fname = "system_security.txt";
7249 uint16_t fnum = (uint16_t)-1;
7250 NTSTATUS status;
7251 TALLOC_CTX *frame = NULL;
7253 frame = talloc_stackframe();
7254 printf("starting smb1 system security test\n");
7256 /* SMB1 connection - torture_open_connection() forces this. */
7257 if (!torture_open_connection(&cli, 0)) {
7258 goto fail;
7261 smbXcli_conn_set_sockopt(cli->conn, sockops);
7263 /* Start with a clean slate. */
7264 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7266 /* Create the test file. */
7267 status = cli_ntcreate(cli,
7268 fname,
7270 GENERIC_ALL_ACCESS,
7271 FILE_ATTRIBUTE_NORMAL,
7272 FILE_SHARE_READ|FILE_SHARE_WRITE|
7273 FILE_SHARE_DELETE,
7274 FILE_CREATE,
7277 &fnum,
7278 NULL);
7279 if (!NT_STATUS_IS_OK(status)) {
7280 printf("Create of %s - %s\n", fname, nt_errstr(status));
7281 goto fail;
7284 status = cli_close(cli, fnum);
7286 /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7288 * On SMB1 this succeeds - SMB2 it fails,
7289 * see the SMB2-SACL test.
7291 status = cli_ntcreate(cli,
7292 fname,
7294 SEC_FLAG_SYSTEM_SECURITY,
7295 FILE_ATTRIBUTE_NORMAL,
7296 FILE_SHARE_READ|FILE_SHARE_WRITE|
7297 FILE_SHARE_DELETE,
7298 FILE_OPEN,
7301 &fnum,
7302 NULL);
7303 if (!NT_STATUS_IS_OK(status)) {
7304 printf("Open of %s - %s\n", fname, nt_errstr(status));
7305 goto fail;
7308 status = cli_close(cli, fnum);
7310 cli_unlink(cli, fname,
7311 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7313 torture_close_connection(cli);
7314 TALLOC_FREE(frame);
7315 return true;
7317 fail:
7319 if (cli) {
7320 if (fnum != (uint16_t)-1) {
7321 cli_close(cli, fnum);
7323 cli_unlink(cli, fname,
7324 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7325 torture_close_connection(cli);
7328 TALLOC_FREE(frame);
7329 return false;
7332 static bool run_pipe_number(int dummy)
7334 struct cli_state *cli1;
7335 const char *pipe_name = "\\SPOOLSS";
7336 uint16_t fnum;
7337 int num_pipes = 0;
7338 NTSTATUS status;
7340 printf("starting pipenumber test\n");
7341 if (!torture_open_connection(&cli1, 0)) {
7342 return False;
7345 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7346 while(1) {
7347 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7348 FILE_ATTRIBUTE_NORMAL,
7349 FILE_SHARE_READ|FILE_SHARE_WRITE,
7350 FILE_OPEN_IF, 0, 0, &fnum, NULL);
7351 if (!NT_STATUS_IS_OK(status)) {
7352 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7353 break;
7355 num_pipes++;
7356 printf("\r%6d", num_pipes);
7359 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7360 torture_close_connection(cli1);
7361 return True;
7365 Test open mode returns on read-only files.
7367 static bool run_opentest(int dummy)
7369 static struct cli_state *cli1;
7370 static struct cli_state *cli2;
7371 const char *fname = "\\readonly.file";
7372 uint16_t fnum1, fnum2;
7373 char buf[20];
7374 off_t fsize;
7375 bool correct = True;
7376 char *tmp_path;
7377 NTSTATUS status;
7379 printf("starting open test\n");
7381 if (!torture_open_connection(&cli1, 0)) {
7382 return False;
7385 cli_setatr(cli1, fname, 0, 0);
7386 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7388 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7390 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7391 if (!NT_STATUS_IS_OK(status)) {
7392 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7393 return False;
7396 status = cli_close(cli1, fnum1);
7397 if (!NT_STATUS_IS_OK(status)) {
7398 printf("close2 failed (%s)\n", nt_errstr(status));
7399 return False;
7402 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7403 if (!NT_STATUS_IS_OK(status)) {
7404 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7405 return False;
7408 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7409 if (!NT_STATUS_IS_OK(status)) {
7410 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7411 return False;
7414 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7415 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7417 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7418 NT_STATUS_ACCESS_DENIED)) {
7419 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7422 printf("finished open test 1\n");
7424 cli_close(cli1, fnum1);
7426 /* Now try not readonly and ensure ERRbadshare is returned. */
7428 cli_setatr(cli1, fname, 0, 0);
7430 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7431 if (!NT_STATUS_IS_OK(status)) {
7432 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7433 return False;
7436 /* This will fail - but the error should be ERRshare. */
7437 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7439 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7440 NT_STATUS_SHARING_VIOLATION)) {
7441 printf("correct error code ERRDOS/ERRbadshare returned\n");
7444 status = cli_close(cli1, fnum1);
7445 if (!NT_STATUS_IS_OK(status)) {
7446 printf("close2 failed (%s)\n", nt_errstr(status));
7447 return False;
7450 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7452 printf("finished open test 2\n");
7454 /* Test truncate open disposition on file opened for read. */
7455 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7456 if (!NT_STATUS_IS_OK(status)) {
7457 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7458 return False;
7461 /* write 20 bytes. */
7463 memset(buf, '\0', 20);
7465 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7466 if (!NT_STATUS_IS_OK(status)) {
7467 printf("write failed (%s)\n", nt_errstr(status));
7468 correct = False;
7471 status = cli_close(cli1, fnum1);
7472 if (!NT_STATUS_IS_OK(status)) {
7473 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7474 return False;
7477 /* Ensure size == 20. */
7478 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7479 if (!NT_STATUS_IS_OK(status)) {
7480 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7481 return False;
7484 if (fsize != 20) {
7485 printf("(3) file size != 20\n");
7486 return False;
7489 /* Now test if we can truncate a file opened for readonly. */
7490 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7491 if (!NT_STATUS_IS_OK(status)) {
7492 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7493 return False;
7496 status = cli_close(cli1, fnum1);
7497 if (!NT_STATUS_IS_OK(status)) {
7498 printf("close2 failed (%s)\n", nt_errstr(status));
7499 return False;
7502 /* Ensure size == 0. */
7503 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7504 if (!NT_STATUS_IS_OK(status)) {
7505 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7506 return False;
7509 if (fsize != 0) {
7510 printf("(3) file size != 0\n");
7511 return False;
7513 printf("finished open test 3\n");
7515 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7517 printf("Do ctemp tests\n");
7518 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7519 if (!NT_STATUS_IS_OK(status)) {
7520 printf("ctemp failed (%s)\n", nt_errstr(status));
7521 return False;
7524 printf("ctemp gave path %s\n", tmp_path);
7525 status = cli_close(cli1, fnum1);
7526 if (!NT_STATUS_IS_OK(status)) {
7527 printf("close of temp failed (%s)\n", nt_errstr(status));
7530 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7531 if (!NT_STATUS_IS_OK(status)) {
7532 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7535 /* Test the non-io opens... */
7537 if (!torture_open_connection(&cli2, 1)) {
7538 return False;
7541 cli_setatr(cli2, fname, 0, 0);
7542 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7544 smbXcli_conn_set_sockopt(cli2->conn, sockops);
7546 printf("TEST #1 testing 2 non-io opens (no delete)\n");
7547 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7548 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7549 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7550 if (!NT_STATUS_IS_OK(status)) {
7551 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7552 return False;
7555 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7556 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7557 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7558 if (!NT_STATUS_IS_OK(status)) {
7559 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7560 return False;
7563 status = cli_close(cli1, fnum1);
7564 if (!NT_STATUS_IS_OK(status)) {
7565 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7566 return False;
7569 status = cli_close(cli2, fnum2);
7570 if (!NT_STATUS_IS_OK(status)) {
7571 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7572 return False;
7575 printf("non-io open test #1 passed.\n");
7577 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7579 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7581 status = cli_ntcreate(cli1, fname, 0,
7582 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7583 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7584 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7585 if (!NT_STATUS_IS_OK(status)) {
7586 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7587 return False;
7590 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7591 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7592 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7593 if (!NT_STATUS_IS_OK(status)) {
7594 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7595 return False;
7598 status = cli_close(cli1, fnum1);
7599 if (!NT_STATUS_IS_OK(status)) {
7600 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7601 return False;
7604 status = cli_close(cli2, fnum2);
7605 if (!NT_STATUS_IS_OK(status)) {
7606 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7607 return False;
7610 printf("non-io open test #2 passed.\n");
7612 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7614 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7616 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7617 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7618 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7619 if (!NT_STATUS_IS_OK(status)) {
7620 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7621 return False;
7624 status = cli_ntcreate(cli2, fname, 0,
7625 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7626 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7627 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7628 if (!NT_STATUS_IS_OK(status)) {
7629 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7630 return False;
7633 status = cli_close(cli1, fnum1);
7634 if (!NT_STATUS_IS_OK(status)) {
7635 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7636 return False;
7639 status = cli_close(cli2, fnum2);
7640 if (!NT_STATUS_IS_OK(status)) {
7641 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7642 return False;
7645 printf("non-io open test #3 passed.\n");
7647 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7649 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7651 status = cli_ntcreate(cli1, fname, 0,
7652 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7653 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7654 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7655 if (!NT_STATUS_IS_OK(status)) {
7656 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7657 return False;
7660 status = cli_ntcreate(cli2, fname, 0,
7661 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7662 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7663 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7664 if (NT_STATUS_IS_OK(status)) {
7665 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7666 return False;
7669 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7671 status = cli_close(cli1, fnum1);
7672 if (!NT_STATUS_IS_OK(status)) {
7673 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7674 return False;
7677 printf("non-io open test #4 passed.\n");
7679 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7681 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7683 status = cli_ntcreate(cli1, fname, 0,
7684 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7685 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7686 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7687 if (!NT_STATUS_IS_OK(status)) {
7688 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7689 return False;
7692 status = cli_ntcreate(cli2, fname, 0,
7693 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7694 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7695 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7696 if (!NT_STATUS_IS_OK(status)) {
7697 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7698 return False;
7701 status = cli_close(cli1, fnum1);
7702 if (!NT_STATUS_IS_OK(status)) {
7703 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7704 return False;
7707 status = cli_close(cli2, fnum2);
7708 if (!NT_STATUS_IS_OK(status)) {
7709 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7710 return False;
7713 printf("non-io open test #5 passed.\n");
7715 printf("TEST #6 testing 1 non-io open, one io open\n");
7717 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7719 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7720 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7721 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7722 if (!NT_STATUS_IS_OK(status)) {
7723 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7724 return False;
7727 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7728 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7729 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7730 if (!NT_STATUS_IS_OK(status)) {
7731 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7732 return False;
7735 status = cli_close(cli1, fnum1);
7736 if (!NT_STATUS_IS_OK(status)) {
7737 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7738 return False;
7741 status = cli_close(cli2, fnum2);
7742 if (!NT_STATUS_IS_OK(status)) {
7743 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7744 return False;
7747 printf("non-io open test #6 passed.\n");
7749 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7751 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7753 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7754 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7755 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7756 if (!NT_STATUS_IS_OK(status)) {
7757 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7758 return False;
7761 status = cli_ntcreate(cli2, fname, 0,
7762 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7763 FILE_ATTRIBUTE_NORMAL,
7764 FILE_SHARE_READ|FILE_SHARE_DELETE,
7765 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7766 if (NT_STATUS_IS_OK(status)) {
7767 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7768 return False;
7771 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7773 status = cli_close(cli1, fnum1);
7774 if (!NT_STATUS_IS_OK(status)) {
7775 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7776 return False;
7779 printf("non-io open test #7 passed.\n");
7781 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7783 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7784 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7785 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7786 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7787 if (!NT_STATUS_IS_OK(status)) {
7788 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7789 correct = false;
7790 goto out;
7793 /* Write to ensure we have to update the file time. */
7794 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7795 NULL);
7796 if (!NT_STATUS_IS_OK(status)) {
7797 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7798 correct = false;
7799 goto out;
7802 status = cli_close(cli1, fnum1);
7803 if (!NT_STATUS_IS_OK(status)) {
7804 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7805 correct = false;
7808 out:
7810 if (!torture_close_connection(cli1)) {
7811 correct = False;
7813 if (!torture_close_connection(cli2)) {
7814 correct = False;
7817 return correct;
7820 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7822 uint16_t major, minor;
7823 uint32_t caplow, caphigh;
7824 NTSTATUS status;
7826 if (!SERVER_HAS_UNIX_CIFS(cli)) {
7827 printf("Server doesn't support UNIX CIFS extensions.\n");
7828 return NT_STATUS_NOT_SUPPORTED;
7831 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7832 &caphigh);
7833 if (!NT_STATUS_IS_OK(status)) {
7834 printf("Server didn't return UNIX CIFS extensions: %s\n",
7835 nt_errstr(status));
7836 return status;
7839 status = cli_set_unix_extensions_capabilities(cli, major, minor,
7840 caplow, caphigh);
7841 if (!NT_STATUS_IS_OK(status)) {
7842 printf("Server doesn't support setting UNIX CIFS extensions: "
7843 "%s.\n", nt_errstr(status));
7844 return status;
7847 return NT_STATUS_OK;
7851 Test POSIX open /mkdir calls.
7853 static bool run_simple_posix_open_test(int dummy)
7855 static struct cli_state *cli1;
7856 const char *fname = "posix:file";
7857 const char *hname = "posix:hlink";
7858 const char *sname = "posix:symlink";
7859 const char *dname = "posix:dir";
7860 char buf[10];
7861 char *target = NULL;
7862 uint16_t fnum1 = (uint16_t)-1;
7863 SMB_STRUCT_STAT sbuf;
7864 bool correct = false;
7865 NTSTATUS status;
7866 size_t nread;
7867 const char *fname_windows = "windows_file";
7868 uint16_t fnum2 = (uint16_t)-1;
7869 bool ok;
7871 printf("Starting simple POSIX open test\n");
7873 if (!torture_open_connection(&cli1, 0)) {
7874 return false;
7877 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7879 status = torture_setup_unix_extensions(cli1);
7880 if (!NT_STATUS_IS_OK(status)) {
7881 return false;
7884 cli_setatr(cli1, fname, 0, 0);
7885 cli_posix_unlink(cli1, fname);
7886 cli_setatr(cli1, dname, 0, 0);
7887 cli_posix_rmdir(cli1, dname);
7888 cli_setatr(cli1, hname, 0, 0);
7889 cli_posix_unlink(cli1, hname);
7890 cli_setatr(cli1, sname, 0, 0);
7891 cli_posix_unlink(cli1, sname);
7892 cli_setatr(cli1, fname_windows, 0, 0);
7893 cli_posix_unlink(cli1, fname_windows);
7895 /* Create a directory. */
7896 status = cli_posix_mkdir(cli1, dname, 0777);
7897 if (!NT_STATUS_IS_OK(status)) {
7898 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7899 goto out;
7902 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7903 0600, &fnum1);
7904 if (!NT_STATUS_IS_OK(status)) {
7905 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7906 goto out;
7909 /* Test ftruncate - set file size. */
7910 status = cli_ftruncate(cli1, fnum1, 1000);
7911 if (!NT_STATUS_IS_OK(status)) {
7912 printf("ftruncate failed (%s)\n", nt_errstr(status));
7913 goto out;
7916 /* Ensure st_size == 1000 */
7917 status = cli_posix_stat(cli1, fname, &sbuf);
7918 if (!NT_STATUS_IS_OK(status)) {
7919 printf("stat failed (%s)\n", nt_errstr(status));
7920 goto out;
7923 if (sbuf.st_ex_size != 1000) {
7924 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7925 goto out;
7928 /* Ensure st_mode == 0600 */
7929 if ((sbuf.st_ex_mode & 07777) != 0600) {
7930 printf("posix_open - bad permissions 0%o != 0600\n",
7931 (unsigned int)(sbuf.st_ex_mode & 07777));
7932 goto out;
7935 /* Test ftruncate - set file size back to zero. */
7936 status = cli_ftruncate(cli1, fnum1, 0);
7937 if (!NT_STATUS_IS_OK(status)) {
7938 printf("ftruncate failed (%s)\n", nt_errstr(status));
7939 goto out;
7942 status = cli_close(cli1, fnum1);
7943 if (!NT_STATUS_IS_OK(status)) {
7944 printf("close failed (%s)\n", nt_errstr(status));
7945 goto out;
7948 /* Now open the file again for read only. */
7949 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7950 if (!NT_STATUS_IS_OK(status)) {
7951 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7952 goto out;
7955 /* Now unlink while open. */
7956 status = cli_posix_unlink(cli1, fname);
7957 if (!NT_STATUS_IS_OK(status)) {
7958 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7959 goto out;
7962 status = cli_close(cli1, fnum1);
7963 if (!NT_STATUS_IS_OK(status)) {
7964 printf("close(2) failed (%s)\n", nt_errstr(status));
7965 goto out;
7968 /* Ensure the file has gone. */
7969 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7970 if (NT_STATUS_IS_OK(status)) {
7971 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7972 goto out;
7975 /* Create again to test open with O_TRUNC. */
7976 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7977 if (!NT_STATUS_IS_OK(status)) {
7978 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7979 goto out;
7982 /* Test ftruncate - set file size. */
7983 status = cli_ftruncate(cli1, fnum1, 1000);
7984 if (!NT_STATUS_IS_OK(status)) {
7985 printf("ftruncate failed (%s)\n", nt_errstr(status));
7986 goto out;
7989 /* Ensure st_size == 1000 */
7990 status = cli_posix_stat(cli1, fname, &sbuf);
7991 if (!NT_STATUS_IS_OK(status)) {
7992 printf("stat failed (%s)\n", nt_errstr(status));
7993 goto out;
7996 if (sbuf.st_ex_size != 1000) {
7997 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7998 goto out;
8001 status = cli_close(cli1, fnum1);
8002 if (!NT_STATUS_IS_OK(status)) {
8003 printf("close(2) failed (%s)\n", nt_errstr(status));
8004 goto out;
8007 /* Re-open with O_TRUNC. */
8008 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
8009 if (!NT_STATUS_IS_OK(status)) {
8010 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
8011 goto out;
8014 /* Ensure st_size == 0 */
8015 status = cli_posix_stat(cli1, fname, &sbuf);
8016 if (!NT_STATUS_IS_OK(status)) {
8017 printf("stat failed (%s)\n", nt_errstr(status));
8018 goto out;
8021 if (sbuf.st_ex_size != 0) {
8022 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
8023 goto out;
8026 status = cli_close(cli1, fnum1);
8027 if (!NT_STATUS_IS_OK(status)) {
8028 printf("close failed (%s)\n", nt_errstr(status));
8029 goto out;
8032 status = cli_posix_unlink(cli1, fname);
8033 if (!NT_STATUS_IS_OK(status)) {
8034 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
8035 goto out;
8038 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
8039 if (!NT_STATUS_IS_OK(status)) {
8040 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
8041 dname, nt_errstr(status));
8042 goto out;
8045 cli_close(cli1, fnum1);
8047 /* What happens when we try and POSIX open a directory for write ? */
8048 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
8049 if (NT_STATUS_IS_OK(status)) {
8050 printf("POSIX open of directory %s succeeded, "
8051 "should have failed.\n",
8052 dname);
8053 goto out;
8054 } else {
8055 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
8056 NT_STATUS_FILE_IS_A_DIRECTORY)) {
8057 goto out;
8061 /* Create the file. */
8062 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8063 0600, &fnum1);
8064 if (!NT_STATUS_IS_OK(status)) {
8065 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
8066 goto out;
8069 /* Write some data into it. */
8070 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
8071 NULL);
8072 if (!NT_STATUS_IS_OK(status)) {
8073 printf("cli_write failed: %s\n", nt_errstr(status));
8074 goto out;
8077 cli_close(cli1, fnum1);
8079 /* Now create a hardlink. */
8080 status = cli_posix_hardlink(cli1, fname, hname);
8081 if (!NT_STATUS_IS_OK(status)) {
8082 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
8083 goto out;
8086 /* Now create a symlink. */
8087 status = cli_posix_symlink(cli1, fname, sname);
8088 if (!NT_STATUS_IS_OK(status)) {
8089 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
8090 goto out;
8093 /* Open the hardlink for read. */
8094 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
8095 if (!NT_STATUS_IS_OK(status)) {
8096 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
8097 goto out;
8100 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
8101 if (!NT_STATUS_IS_OK(status)) {
8102 printf("POSIX read of %s failed (%s)\n", hname,
8103 nt_errstr(status));
8104 goto out;
8105 } else if (nread != 10) {
8106 printf("POSIX read of %s failed. Received %ld, expected %d\n",
8107 hname, (unsigned long)nread, 10);
8108 goto out;
8111 if (memcmp(buf, "TEST DATA\n", 10)) {
8112 printf("invalid data read from hardlink\n");
8113 goto out;
8116 /* Do a POSIX lock/unlock. */
8117 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8118 if (!NT_STATUS_IS_OK(status)) {
8119 printf("POSIX lock failed %s\n", nt_errstr(status));
8120 goto out;
8123 /* Punch a hole in the locked area. */
8124 status = cli_posix_unlock(cli1, fnum1, 10, 80);
8125 if (!NT_STATUS_IS_OK(status)) {
8126 printf("POSIX unlock failed %s\n", nt_errstr(status));
8127 goto out;
8130 cli_close(cli1, fnum1);
8132 /* Open the symlink for read - this should fail. A POSIX
8133 client should not be doing opens on a symlink. */
8134 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8135 if (NT_STATUS_IS_OK(status)) {
8136 printf("POSIX open of %s succeeded (should have failed)\n", sname);
8137 goto out;
8139 ok = check_both_error(
8140 __LINE__, status, ERRDOS, ERRbadpath,
8141 NT_STATUS_OBJECT_NAME_NOT_FOUND);
8142 if (!ok) {
8143 printf("POSIX open of %s should have failed "
8144 "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8145 "failed with %s instead.\n",
8146 sname, nt_errstr(status));
8147 goto out;
8150 status = cli_readlink(cli1, sname, talloc_tos(), &target, NULL, NULL);
8151 if (!NT_STATUS_IS_OK(status)) {
8152 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8153 goto out;
8156 if (strcmp(target, fname) != 0) {
8157 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8158 sname, fname, target);
8159 goto out;
8162 status = cli_posix_rmdir(cli1, dname);
8163 if (!NT_STATUS_IS_OK(status)) {
8164 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8165 goto out;
8168 /* Check directory opens with a specific permission. */
8169 status = cli_posix_mkdir(cli1, dname, 0700);
8170 if (!NT_STATUS_IS_OK(status)) {
8171 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8172 goto out;
8175 /* Ensure st_mode == 0700 */
8176 status = cli_posix_stat(cli1, dname, &sbuf);
8177 if (!NT_STATUS_IS_OK(status)) {
8178 printf("stat failed (%s)\n", nt_errstr(status));
8179 goto out;
8182 if ((sbuf.st_ex_mode & 07777) != 0700) {
8183 printf("posix_mkdir - bad permissions 0%o != 0700\n",
8184 (unsigned int)(sbuf.st_ex_mode & 07777));
8185 goto out;
8189 * Now create a Windows file, and attempt a POSIX unlink.
8190 * This should fail with a sharing violation but due to:
8192 * [Bug 9571] Unlink after open causes smbd to panic
8194 * ensure we've fixed the lock ordering violation.
8197 status = cli_ntcreate(cli1, fname_windows, 0,
8198 FILE_READ_DATA|FILE_WRITE_DATA, 0,
8199 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8200 FILE_CREATE,
8201 0x0, 0x0, &fnum2, NULL);
8202 if (!NT_STATUS_IS_OK(status)) {
8203 printf("Windows create of %s failed (%s)\n", fname_windows,
8204 nt_errstr(status));
8205 goto out;
8208 /* Now try posix_unlink. */
8209 status = cli_posix_unlink(cli1, fname_windows);
8210 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8211 printf("POSIX unlink of %s should fail "
8212 "with NT_STATUS_SHARING_VIOLATION "
8213 "got %s instead !\n",
8214 fname_windows,
8215 nt_errstr(status));
8216 goto out;
8219 cli_close(cli1, fnum2);
8221 printf("Simple POSIX open test passed\n");
8222 correct = true;
8224 out:
8226 if (fnum1 != (uint16_t)-1) {
8227 cli_close(cli1, fnum1);
8228 fnum1 = (uint16_t)-1;
8231 if (fnum2 != (uint16_t)-1) {
8232 cli_close(cli1, fnum2);
8233 fnum2 = (uint16_t)-1;
8236 cli_setatr(cli1, sname, 0, 0);
8237 cli_posix_unlink(cli1, sname);
8238 cli_setatr(cli1, hname, 0, 0);
8239 cli_posix_unlink(cli1, hname);
8240 cli_setatr(cli1, fname, 0, 0);
8241 cli_posix_unlink(cli1, fname);
8242 cli_setatr(cli1, dname, 0, 0);
8243 cli_posix_rmdir(cli1, dname);
8244 cli_setatr(cli1, fname_windows, 0, 0);
8245 cli_posix_unlink(cli1, fname_windows);
8247 if (!torture_close_connection(cli1)) {
8248 correct = false;
8251 return correct;
8255 Test POSIX and Windows ACLs are rejected on symlinks.
8257 static bool run_acl_symlink_test(int dummy)
8259 static struct cli_state *cli;
8260 const char *fname = "posix_file";
8261 const char *sname = "posix_symlink";
8262 uint16_t fnum = (uint16_t)-1;
8263 bool correct = false;
8264 NTSTATUS status;
8265 char *posix_acl = NULL;
8266 size_t posix_acl_len = 0;
8267 char *posix_acl_sym = NULL;
8268 size_t posix_acl_len_sym = 0;
8269 struct security_descriptor *sd = NULL;
8270 TALLOC_CTX *frame = NULL;
8272 frame = talloc_stackframe();
8274 printf("Starting acl symlink test\n");
8276 if (!torture_open_connection(&cli, 0)) {
8277 TALLOC_FREE(frame);
8278 return false;
8281 smbXcli_conn_set_sockopt(cli->conn, sockops);
8283 status = torture_setup_unix_extensions(cli);
8284 if (!NT_STATUS_IS_OK(status)) {
8285 TALLOC_FREE(frame);
8286 return false;
8289 cli_setatr(cli, fname, 0, 0);
8290 cli_posix_unlink(cli, fname);
8291 cli_setatr(cli, sname, 0, 0);
8292 cli_posix_unlink(cli, sname);
8294 status = cli_ntcreate(cli,
8295 fname,
8297 READ_CONTROL_ACCESS,
8299 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8300 FILE_CREATE,
8301 0x0,
8302 0x0,
8303 &fnum,
8304 NULL);
8306 if (!NT_STATUS_IS_OK(status)) {
8307 printf("cli_ntcreate of %s failed (%s)\n",
8308 fname,
8309 nt_errstr(status));
8310 goto out;
8313 /* Get the Windows ACL on the file. */
8314 status = cli_query_secdesc(cli,
8315 fnum,
8316 frame,
8317 &sd);
8318 if (!NT_STATUS_IS_OK(status)) {
8319 printf("cli_query_secdesc failed (%s)\n",
8320 nt_errstr(status));
8321 goto out;
8324 /* Get the POSIX ACL on the file. */
8325 status = cli_posix_getacl(cli,
8326 fname,
8327 frame,
8328 &posix_acl_len,
8329 &posix_acl);
8331 if (!NT_STATUS_IS_OK(status)) {
8332 printf("cli_posix_getacl failed (%s)\n",
8333 nt_errstr(status));
8334 goto out;
8337 status = cli_close(cli, fnum);
8338 if (!NT_STATUS_IS_OK(status)) {
8339 printf("close failed (%s)\n", nt_errstr(status));
8340 goto out;
8342 fnum = (uint16_t)-1;
8344 /* Now create a symlink. */
8345 status = cli_posix_symlink(cli, fname, sname);
8346 if (!NT_STATUS_IS_OK(status)) {
8347 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8348 sname,
8349 fname,
8350 nt_errstr(status));
8351 goto out;
8354 /* Open a handle on the symlink for SD set/get should fail. */
8355 status = cli_ntcreate(cli,
8356 sname,
8358 READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8360 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8361 FILE_OPEN,
8362 0x0,
8363 0x0,
8364 &fnum,
8365 NULL);
8367 if (NT_STATUS_IS_OK(status)) {
8368 printf("Symlink open for getsd/setsd of %s "
8369 "succeeded (should fail)\n",
8370 sname);
8371 goto out;
8374 /* Try a stat-open on the symlink, should also fail. */
8375 status = cli_ntcreate(cli,
8376 sname,
8378 FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8380 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8381 FILE_OPEN,
8382 0x0,
8383 0x0,
8384 &fnum,
8385 NULL);
8387 if (NT_STATUS_IS_OK(status)) {
8388 printf("Stat-open of symlink succeeded (should fail)\n");
8389 goto out;
8392 /* Get the POSIX ACL on the symlink pathname. Should fail. */
8393 status = cli_posix_getacl(cli,
8394 sname,
8395 frame,
8396 &posix_acl_len_sym,
8397 &posix_acl_sym);
8399 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8400 printf("cli_posix_getacl on a symlink gave %s. "
8401 "Should be NT_STATUS_ACCESS_DENIED.\n",
8402 nt_errstr(status));
8403 goto out;
8406 /* Set the POSIX ACL on the symlink pathname. Should fail. */
8407 status = cli_posix_setacl(cli,
8408 sname,
8409 posix_acl,
8410 posix_acl_len);
8412 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8413 printf("cli_posix_setacl on a symlink gave %s. "
8414 "Should be NT_STATUS_ACCESS_DENIED.\n",
8415 nt_errstr(status));
8416 goto out;
8419 printf("ACL symlink test passed\n");
8420 correct = true;
8422 out:
8424 if (fnum != (uint16_t)-1) {
8425 cli_close(cli, fnum);
8426 fnum = (uint16_t)-1;
8429 cli_setatr(cli, sname, 0, 0);
8430 cli_posix_unlink(cli, sname);
8431 cli_setatr(cli, fname, 0, 0);
8432 cli_posix_unlink(cli, fname);
8434 if (!torture_close_connection(cli)) {
8435 correct = false;
8438 TALLOC_FREE(frame);
8439 return correct;
8443 Test POSIX can delete a file containing streams.
8445 static bool run_posix_stream_delete(int dummy)
8447 struct cli_state *cli1 = NULL;
8448 struct cli_state *cli2 = NULL;
8449 const char *fname = "streamfile";
8450 const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8451 uint16_t fnum1 = (uint16_t)-1;
8452 bool correct = false;
8453 NTSTATUS status;
8454 TALLOC_CTX *frame = NULL;
8456 frame = talloc_stackframe();
8458 printf("Starting POSIX stream delete test\n");
8460 if (!torture_open_connection(&cli1, 0) ||
8461 !torture_open_connection(&cli2, 1)) {
8462 TALLOC_FREE(frame);
8463 return false;
8466 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8467 smbXcli_conn_set_sockopt(cli2->conn, sockops);
8469 status = torture_setup_unix_extensions(cli2);
8470 if (!NT_STATUS_IS_OK(status)) {
8471 goto out;
8474 cli_setatr(cli1, fname, 0, 0);
8475 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8477 /* Create the file. */
8478 status = cli_ntcreate(cli1,
8479 fname,
8481 READ_CONTROL_ACCESS,
8483 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8484 FILE_CREATE,
8485 0x0,
8486 0x0,
8487 &fnum1,
8488 NULL);
8490 if (!NT_STATUS_IS_OK(status)) {
8491 printf("cli_ntcreate of %s failed (%s)\n",
8492 fname,
8493 nt_errstr(status));
8494 goto out;
8497 status = cli_close(cli1, fnum1);
8498 if (!NT_STATUS_IS_OK(status)) {
8499 printf("cli_close of %s failed (%s)\n",
8500 fname,
8501 nt_errstr(status));
8502 goto out;
8504 fnum1 = (uint16_t)-1;
8506 /* Now create the stream. */
8507 status = cli_ntcreate(cli1,
8508 stream_fname,
8510 FILE_WRITE_DATA,
8512 FILE_SHARE_READ|FILE_SHARE_WRITE,
8513 FILE_CREATE,
8514 0x0,
8515 0x0,
8516 &fnum1,
8517 NULL);
8519 if (!NT_STATUS_IS_OK(status)) {
8520 printf("cli_ntcreate of %s failed (%s)\n",
8521 stream_fname,
8522 nt_errstr(status));
8523 goto out;
8526 /* Leave the stream handle open... */
8528 /* POSIX unlink should fail. */
8529 status = cli_posix_unlink(cli2, fname);
8530 if (NT_STATUS_IS_OK(status)) {
8531 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8532 fname);
8533 goto out;
8536 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8537 printf("cli_posix_unlink of %s failed with (%s) "
8538 "should have been NT_STATUS_SHARING_VIOLATION\n",
8539 fname,
8540 nt_errstr(status));
8541 goto out;
8544 /* Close the stream handle. */
8545 status = cli_close(cli1, fnum1);
8546 if (!NT_STATUS_IS_OK(status)) {
8547 printf("cli_close of %s failed (%s)\n",
8548 stream_fname,
8549 nt_errstr(status));
8550 goto out;
8552 fnum1 = (uint16_t)-1;
8554 /* POSIX unlink after stream handle closed should succeed. */
8555 status = cli_posix_unlink(cli2, fname);
8556 if (!NT_STATUS_IS_OK(status)) {
8557 printf("cli_posix_unlink of %s failed (%s)\n",
8558 fname,
8559 nt_errstr(status));
8560 goto out;
8563 printf("POSIX stream delete test passed\n");
8564 correct = true;
8566 out:
8568 if (fnum1 != (uint16_t)-1) {
8569 cli_close(cli1, fnum1);
8570 fnum1 = (uint16_t)-1;
8573 cli_setatr(cli1, fname, 0, 0);
8574 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8576 if (!torture_close_connection(cli1)) {
8577 correct = false;
8579 if (!torture_close_connection(cli2)) {
8580 correct = false;
8583 TALLOC_FREE(frame);
8584 return correct;
8588 Test setting EA's are rejected on symlinks.
8590 static bool run_ea_symlink_test(int dummy)
8592 static struct cli_state *cli;
8593 const char *fname = "posix_file_ea";
8594 const char *sname = "posix_symlink_ea";
8595 const char *ea_name = "testea_name";
8596 const char *ea_value = "testea_value";
8597 uint16_t fnum = (uint16_t)-1;
8598 bool correct = false;
8599 NTSTATUS status;
8600 size_t i, num_eas;
8601 struct ea_struct *eas = NULL;
8602 TALLOC_CTX *frame = NULL;
8604 frame = talloc_stackframe();
8606 printf("Starting EA symlink test\n");
8608 if (!torture_open_connection(&cli, 0)) {
8609 TALLOC_FREE(frame);
8610 return false;
8613 smbXcli_conn_set_sockopt(cli->conn, sockops);
8615 status = torture_setup_unix_extensions(cli);
8616 if (!NT_STATUS_IS_OK(status)) {
8617 TALLOC_FREE(frame);
8618 return false;
8621 cli_setatr(cli, fname, 0, 0);
8622 cli_posix_unlink(cli, fname);
8623 cli_setatr(cli, sname, 0, 0);
8624 cli_posix_unlink(cli, sname);
8626 status = cli_ntcreate(cli,
8627 fname,
8629 READ_CONTROL_ACCESS,
8631 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8632 FILE_CREATE,
8633 0x0,
8634 0x0,
8635 &fnum,
8636 NULL);
8638 if (!NT_STATUS_IS_OK(status)) {
8639 printf("cli_ntcreate of %s failed (%s)\n",
8640 fname,
8641 nt_errstr(status));
8642 goto out;
8645 status = cli_close(cli, fnum);
8646 if (!NT_STATUS_IS_OK(status)) {
8647 printf("close failed (%s)\n",
8648 nt_errstr(status));
8649 goto out;
8651 fnum = (uint16_t)-1;
8653 /* Set an EA on the path. */
8654 status = cli_set_ea_path(cli,
8655 fname,
8656 ea_name,
8657 ea_value,
8658 strlen(ea_value)+1);
8660 if (!NT_STATUS_IS_OK(status)) {
8661 printf("cli_set_ea_path failed (%s)\n",
8662 nt_errstr(status));
8663 goto out;
8666 /* Now create a symlink. */
8667 status = cli_posix_symlink(cli, fname, sname);
8668 if (!NT_STATUS_IS_OK(status)) {
8669 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8670 sname,
8671 fname,
8672 nt_errstr(status));
8673 goto out;
8676 /* Get the EA list on the path. Should return value set. */
8677 status = cli_get_ea_list_path(cli,
8678 fname,
8679 frame,
8680 &num_eas,
8681 &eas);
8683 if (!NT_STATUS_IS_OK(status)) {
8684 printf("cli_get_ea_list_path failed (%s)\n",
8685 nt_errstr(status));
8686 goto out;
8689 /* Ensure the EA we set is there. */
8690 for (i=0; i<num_eas; i++) {
8691 if (strcmp(eas[i].name, ea_name) == 0 &&
8692 eas[i].value.length == strlen(ea_value)+1 &&
8693 memcmp(eas[i].value.data,
8694 ea_value,
8695 eas[i].value.length) == 0) {
8696 break;
8700 if (i == num_eas) {
8701 printf("Didn't find EA on pathname %s\n",
8702 fname);
8703 goto out;
8706 num_eas = 0;
8707 TALLOC_FREE(eas);
8709 /* Get the EA list on the symlink. Should return empty list. */
8710 status = cli_get_ea_list_path(cli,
8711 sname,
8712 frame,
8713 &num_eas,
8714 &eas);
8716 if (!NT_STATUS_IS_OK(status)) {
8717 printf("cli_get_ea_list_path failed (%s)\n",
8718 nt_errstr(status));
8719 goto out;
8722 if (num_eas != 0) {
8723 printf("cli_get_ea_list_path failed (%s)\n",
8724 nt_errstr(status));
8725 goto out;
8728 /* Set an EA on the symlink. Should fail. */
8729 status = cli_set_ea_path(cli,
8730 sname,
8731 ea_name,
8732 ea_value,
8733 strlen(ea_value)+1);
8735 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8736 printf("cli_set_ea_path on a symlink gave %s. "
8737 "Should be NT_STATUS_ACCESS_DENIED.\n",
8738 nt_errstr(status));
8739 goto out;
8742 printf("EA symlink test passed\n");
8743 correct = true;
8745 out:
8747 if (fnum != (uint16_t)-1) {
8748 cli_close(cli, fnum);
8749 fnum = (uint16_t)-1;
8752 cli_setatr(cli, sname, 0, 0);
8753 cli_posix_unlink(cli, sname);
8754 cli_setatr(cli, fname, 0, 0);
8755 cli_posix_unlink(cli, fname);
8757 if (!torture_close_connection(cli)) {
8758 correct = false;
8761 TALLOC_FREE(frame);
8762 return correct;
8766 Test POSIX locks are OFD-locks.
8768 static bool run_posix_ofd_lock_test(int dummy)
8770 static struct cli_state *cli;
8771 const char *fname = "posix_file";
8772 uint16_t fnum1 = (uint16_t)-1;
8773 uint16_t fnum2 = (uint16_t)-1;
8774 bool correct = false;
8775 NTSTATUS status;
8776 TALLOC_CTX *frame = NULL;
8778 frame = talloc_stackframe();
8780 printf("Starting POSIX ofd-lock test\n");
8782 if (!torture_open_connection(&cli, 0)) {
8783 TALLOC_FREE(frame);
8784 return false;
8787 smbXcli_conn_set_sockopt(cli->conn, sockops);
8789 status = torture_setup_unix_extensions(cli);
8790 if (!NT_STATUS_IS_OK(status)) {
8791 TALLOC_FREE(frame);
8792 return false;
8795 cli_setatr(cli, fname, 0, 0);
8796 cli_posix_unlink(cli, fname);
8798 /* Open the file twice. */
8799 status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8800 0600, &fnum1);
8801 if (!NT_STATUS_IS_OK(status)) {
8802 printf("First POSIX open of %s failed\n", fname);
8803 goto out;
8806 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8807 if (!NT_STATUS_IS_OK(status)) {
8808 printf("First POSIX open of %s failed\n", fname);
8809 goto out;
8812 /* Set a 0-50 lock on fnum1. */
8813 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8814 if (!NT_STATUS_IS_OK(status)) {
8815 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8816 goto out;
8819 /* Set a 60-100 lock on fnum2. */
8820 status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8821 if (!NT_STATUS_IS_OK(status)) {
8822 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8823 goto out;
8826 /* close fnum1 - 0-50 lock should go away. */
8827 status = cli_close(cli, fnum1);
8828 if (!NT_STATUS_IS_OK(status)) {
8829 printf("close failed (%s)\n",
8830 nt_errstr(status));
8831 goto out;
8833 fnum1 = (uint16_t)-1;
8835 /* Change the lock context. */
8836 cli_setpid(cli, cli_getpid(cli) + 1);
8838 /* Re-open fnum1. */
8839 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8840 if (!NT_STATUS_IS_OK(status)) {
8841 printf("Third POSIX open of %s failed\n", fname);
8842 goto out;
8845 /* 60-100 lock should still be there. */
8846 status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8847 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8848 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8849 goto out;
8852 /* 0-50 lock should be gone. */
8853 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8854 if (!NT_STATUS_IS_OK(status)) {
8855 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8856 goto out;
8859 printf("POSIX OFD lock test passed\n");
8860 correct = true;
8862 out:
8864 if (fnum1 != (uint16_t)-1) {
8865 cli_close(cli, fnum1);
8866 fnum1 = (uint16_t)-1;
8868 if (fnum2 != (uint16_t)-1) {
8869 cli_close(cli, fnum2);
8870 fnum2 = (uint16_t)-1;
8873 cli_setatr(cli, fname, 0, 0);
8874 cli_posix_unlink(cli, fname);
8876 if (!torture_close_connection(cli)) {
8877 correct = false;
8880 TALLOC_FREE(frame);
8881 return correct;
8884 struct posix_blocking_state {
8885 struct tevent_context *ev;
8886 struct cli_state *cli1;
8887 uint16_t fnum1;
8888 struct cli_state *cli2;
8889 uint16_t fnum2;
8890 bool gotblocked;
8891 bool gotecho;
8894 static void posix_blocking_locked(struct tevent_req *subreq);
8895 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8896 static void posix_blocking_gotecho(struct tevent_req *subreq);
8897 static void posix_blocking_unlocked(struct tevent_req *subreq);
8899 static struct tevent_req *posix_blocking_send(
8900 TALLOC_CTX *mem_ctx,
8901 struct tevent_context *ev,
8902 struct cli_state *cli1,
8903 uint16_t fnum1,
8904 struct cli_state *cli2,
8905 uint16_t fnum2)
8907 struct tevent_req *req = NULL, *subreq = NULL;
8908 struct posix_blocking_state *state = NULL;
8910 req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8911 if (req == NULL) {
8912 return NULL;
8914 state->ev = ev;
8915 state->cli1 = cli1;
8916 state->fnum1 = fnum1;
8917 state->cli2 = cli2;
8918 state->fnum2 = fnum2;
8920 subreq = cli_posix_lock_send(
8921 state,
8922 state->ev,
8923 state->cli1,
8924 state->fnum1,
8927 false,
8928 WRITE_LOCK);
8929 if (tevent_req_nomem(subreq, req)) {
8930 return tevent_req_post(req, ev);
8932 tevent_req_set_callback(subreq, posix_blocking_locked, req);
8933 return req;
8936 static void posix_blocking_locked(struct tevent_req *subreq)
8938 struct tevent_req *req = tevent_req_callback_data(
8939 subreq, struct tevent_req);
8940 struct posix_blocking_state *state = tevent_req_data(
8941 req, struct posix_blocking_state);
8942 NTSTATUS status;
8944 status = cli_posix_lock_recv(subreq);
8945 TALLOC_FREE(subreq);
8946 if (tevent_req_nterror(req, status)) {
8947 return;
8950 subreq = cli_posix_lock_send(
8951 state,
8952 state->ev,
8953 state->cli2,
8954 state->fnum2,
8957 true,
8958 WRITE_LOCK);
8959 if (tevent_req_nomem(subreq, req)) {
8960 return;
8962 tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8964 /* Make sure the blocking request is delivered */
8965 subreq = cli_echo_send(
8966 state,
8967 state->ev,
8968 state->cli2,
8970 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8971 if (tevent_req_nomem(subreq, req)) {
8972 return;
8974 tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8977 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8979 struct tevent_req *req = tevent_req_callback_data(
8980 subreq, struct tevent_req);
8981 struct posix_blocking_state *state = tevent_req_data(
8982 req, struct posix_blocking_state);
8983 NTSTATUS status;
8985 status = cli_posix_lock_recv(subreq);
8986 TALLOC_FREE(subreq);
8987 if (tevent_req_nterror(req, status)) {
8988 return;
8990 if (!state->gotecho) {
8991 printf("blocked req got through before echo\n");
8992 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8993 return;
8995 tevent_req_done(req);
8998 static void posix_blocking_gotecho(struct tevent_req *subreq)
9000 struct tevent_req *req = tevent_req_callback_data(
9001 subreq, struct tevent_req);
9002 struct posix_blocking_state *state = tevent_req_data(
9003 req, struct posix_blocking_state);
9004 NTSTATUS status;
9006 status = cli_echo_recv(subreq);
9007 TALLOC_FREE(subreq);
9008 if (tevent_req_nterror(req, status)) {
9009 return;
9011 if (state->gotblocked) {
9012 printf("blocked req got through before echo\n");
9013 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
9014 return;
9016 state->gotecho = true;
9018 subreq = cli_posix_lock_send(
9019 state,
9020 state->ev,
9021 state->cli1,
9022 state->fnum1,
9025 false,
9026 UNLOCK_LOCK);
9027 if (tevent_req_nomem(subreq, req)) {
9028 return;
9030 tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
9033 static void posix_blocking_unlocked(struct tevent_req *subreq)
9035 struct tevent_req *req = tevent_req_callback_data(
9036 subreq, struct tevent_req);
9037 NTSTATUS status;
9039 status = cli_posix_lock_recv(subreq);
9040 TALLOC_FREE(subreq);
9041 if (tevent_req_nterror(req, status)) {
9042 return;
9044 /* tevent_req_done in posix_blocking_gotlocked */
9047 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
9049 return tevent_req_simple_recv_ntstatus(req);
9052 static bool run_posix_blocking_lock(int dummy)
9054 struct tevent_context *ev = NULL;
9055 struct cli_state *cli1 = NULL, *cli2 = NULL;
9056 const char *fname = "posix_blocking";
9057 uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
9058 struct tevent_req *req = NULL;
9059 NTSTATUS status;
9060 bool ret = false;
9061 bool ok;
9063 printf("Starting posix blocking lock test\n");
9065 ev = samba_tevent_context_init(NULL);
9066 if (ev == NULL) {
9067 return false;
9070 ok = torture_open_connection(&cli1, 0);
9071 if (!ok) {
9072 goto fail;
9074 ok = torture_open_connection(&cli2, 0);
9075 if (!ok) {
9076 goto fail;
9079 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9081 status = torture_setup_unix_extensions(cli1);
9082 if (!NT_STATUS_IS_OK(status)) {
9083 return false;
9086 status = torture_setup_unix_extensions(cli2);
9087 if (!NT_STATUS_IS_OK(status)) {
9088 return false;
9091 cli_setatr(cli1, fname, 0, 0);
9092 cli_posix_unlink(cli1, fname);
9094 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
9095 0600, &fnum1);
9096 if (!NT_STATUS_IS_OK(status)) {
9097 printf("First POSIX open of %s failed: %s\n",
9098 fname,
9099 nt_errstr(status));
9100 goto fail;
9103 status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
9104 if (!NT_STATUS_IS_OK(status)) {
9105 printf("Second POSIX open of %s failed: %s\n",
9106 fname,
9107 nt_errstr(status));
9108 goto fail;
9111 req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9112 if (req == NULL) {
9113 printf("cli_posix_blocking failed\n");
9114 goto fail;
9117 ok = tevent_req_poll_ntstatus(req, ev, &status);
9118 if (!ok) {
9119 printf("tevent_req_poll_ntstatus failed: %s\n",
9120 nt_errstr(status));
9121 goto fail;
9123 status = posix_blocking_recv(req);
9124 TALLOC_FREE(req);
9125 if (!NT_STATUS_IS_OK(status)) {
9126 printf("posix_blocking_recv returned %s\n",
9127 nt_errstr(status));
9128 goto fail;
9131 ret = true;
9132 fail:
9134 if (fnum1 != UINT16_MAX) {
9135 cli_close(cli1, fnum1);
9136 fnum1 = UINT16_MAX;
9138 if (fnum2 != UINT16_MAX) {
9139 cli_close(cli2, fnum2);
9140 fnum2 = UINT16_MAX;
9143 if (cli1 != NULL) {
9144 cli_setatr(cli1, fname, 0, 0);
9145 cli_posix_unlink(cli1, fname);
9148 ok = true;
9150 if (cli1 != NULL) {
9151 ok &= torture_close_connection(cli1);
9152 cli1 = NULL;
9154 if (cli2 != NULL) {
9155 ok &= torture_close_connection(cli2);
9156 cli2 = NULL;
9159 if (!ok) {
9160 ret = false;
9162 TALLOC_FREE(ev);
9163 return ret;
9167 Test POSIX mkdir is case-sensitive.
9169 static bool run_posix_mkdir_test(int dummy)
9171 static struct cli_state *cli;
9172 const char *fname_foo = "POSIX_foo";
9173 const char *fname_foo_Foo = "POSIX_foo/Foo";
9174 const char *fname_foo_foo = "POSIX_foo/foo";
9175 const char *fname_Foo = "POSIX_Foo";
9176 const char *fname_Foo_Foo = "POSIX_Foo/Foo";
9177 const char *fname_Foo_foo = "POSIX_Foo/foo";
9178 bool correct = false;
9179 NTSTATUS status;
9180 TALLOC_CTX *frame = NULL;
9181 uint16_t fnum = (uint16_t)-1;
9183 frame = talloc_stackframe();
9185 printf("Starting POSIX mkdir test\n");
9187 if (!torture_open_connection(&cli, 0)) {
9188 TALLOC_FREE(frame);
9189 return false;
9192 smbXcli_conn_set_sockopt(cli->conn, sockops);
9194 status = torture_setup_unix_extensions(cli);
9195 if (!NT_STATUS_IS_OK(status)) {
9196 TALLOC_FREE(frame);
9197 return false;
9200 cli_posix_rmdir(cli, fname_foo_foo);
9201 cli_posix_rmdir(cli, fname_foo_Foo);
9202 cli_posix_rmdir(cli, fname_foo);
9204 cli_posix_rmdir(cli, fname_Foo_foo);
9205 cli_posix_rmdir(cli, fname_Foo_Foo);
9206 cli_posix_rmdir(cli, fname_Foo);
9209 * Create a file POSIX_foo then try
9210 * and use it in a directory path by
9211 * doing mkdir POSIX_foo/bar.
9212 * The mkdir should fail with
9213 * NT_STATUS_OBJECT_PATH_NOT_FOUND
9216 status = cli_posix_open(cli,
9217 fname_foo,
9218 O_RDWR|O_CREAT,
9219 0666,
9220 &fnum);
9221 if (!NT_STATUS_IS_OK(status)) {
9222 printf("cli_posix_open of %s failed error %s\n",
9223 fname_foo,
9224 nt_errstr(status));
9225 goto out;
9228 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9229 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9230 printf("cli_posix_mkdir of %s should fail with "
9231 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9232 "%s instead\n",
9233 fname_foo_foo,
9234 nt_errstr(status));
9235 goto out;
9238 status = cli_close(cli, fnum);
9239 if (!NT_STATUS_IS_OK(status)) {
9240 printf("cli_close failed %s\n", nt_errstr(status));
9241 goto out;
9243 fnum = (uint16_t)-1;
9245 status = cli_posix_unlink(cli, fname_foo);
9246 if (!NT_STATUS_IS_OK(status)) {
9247 printf("cli_posix_unlink of %s failed error %s\n",
9248 fname_foo,
9249 nt_errstr(status));
9250 goto out;
9254 * Now we've deleted everything, posix_mkdir, posix_rmdir,
9255 * posix_open, posix_unlink, on
9256 * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9257 * not silently create POSIX_foo/foo.
9260 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9261 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9262 printf("cli_posix_mkdir of %s should fail with "
9263 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9264 "%s instead\n",
9265 fname_foo_foo,
9266 nt_errstr(status));
9267 goto out;
9270 status = cli_posix_rmdir(cli, fname_foo_foo);
9271 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9272 printf("cli_posix_rmdir of %s should fail with "
9273 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9274 "%s instead\n",
9275 fname_foo_foo,
9276 nt_errstr(status));
9277 goto out;
9280 status = cli_posix_open(cli,
9281 fname_foo_foo,
9282 O_RDWR|O_CREAT,
9283 0666,
9284 &fnum);
9285 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9286 printf("cli_posix_open of %s should fail with "
9287 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9288 "%s instead\n",
9289 fname_foo_foo,
9290 nt_errstr(status));
9291 goto out;
9294 status = cli_posix_unlink(cli, fname_foo_foo);
9295 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9296 printf("cli_posix_unlink of %s should fail with "
9297 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9298 "%s instead\n",
9299 fname_foo_foo,
9300 nt_errstr(status));
9301 goto out;
9304 status = cli_posix_mkdir(cli, fname_foo, 0777);
9305 if (!NT_STATUS_IS_OK(status)) {
9306 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9307 goto out;
9310 status = cli_posix_mkdir(cli, fname_Foo, 0777);
9311 if (!NT_STATUS_IS_OK(status)) {
9312 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9313 goto out;
9316 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9317 if (!NT_STATUS_IS_OK(status)) {
9318 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9319 goto out;
9322 status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9323 if (!NT_STATUS_IS_OK(status)) {
9324 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9325 goto out;
9328 status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9329 if (!NT_STATUS_IS_OK(status)) {
9330 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9331 goto out;
9334 status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9335 if (!NT_STATUS_IS_OK(status)) {
9336 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9337 goto out;
9340 printf("POSIX mkdir test passed\n");
9341 correct = true;
9343 out:
9345 if (fnum != (uint16_t)-1) {
9346 cli_close(cli, fnum);
9347 fnum = (uint16_t)-1;
9350 cli_posix_rmdir(cli, fname_foo_foo);
9351 cli_posix_rmdir(cli, fname_foo_Foo);
9352 cli_posix_rmdir(cli, fname_foo);
9354 cli_posix_rmdir(cli, fname_Foo_foo);
9355 cli_posix_rmdir(cli, fname_Foo_Foo);
9356 cli_posix_rmdir(cli, fname_Foo);
9358 if (!torture_close_connection(cli)) {
9359 correct = false;
9362 TALLOC_FREE(frame);
9363 return correct;
9366 struct posix_acl_oplock_state {
9367 struct tevent_context *ev;
9368 struct cli_state *cli;
9369 bool *got_break;
9370 bool *acl_ret;
9371 NTSTATUS status;
9374 static void posix_acl_oplock_got_break(struct tevent_req *req)
9376 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9377 req, struct posix_acl_oplock_state);
9378 uint16_t fnum;
9379 uint8_t level;
9380 NTSTATUS status;
9382 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9383 TALLOC_FREE(req);
9384 if (!NT_STATUS_IS_OK(status)) {
9385 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9386 nt_errstr(status));
9387 return;
9389 *state->got_break = true;
9391 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9392 NO_OPLOCK);
9393 if (req == NULL) {
9394 printf("cli_oplock_ack_send failed\n");
9395 return;
9399 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9401 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9402 req, struct posix_acl_oplock_state);
9403 size_t ret_size = 0;
9404 char *ret_data = NULL;
9406 state->status = cli_posix_getacl_recv(req,
9407 state,
9408 &ret_size,
9409 &ret_data);
9411 if (!NT_STATUS_IS_OK(state->status)) {
9412 printf("cli_posix_getacl_recv returned %s\n",
9413 nt_errstr(state->status));
9415 *state->acl_ret = true;
9418 static bool run_posix_acl_oplock_test(int dummy)
9420 struct tevent_context *ev;
9421 struct cli_state *cli1, *cli2;
9422 struct tevent_req *oplock_req, *getacl_req;
9423 const char *fname = "posix_acl_oplock";
9424 uint16_t fnum;
9425 int saved_use_oplocks = use_oplocks;
9426 NTSTATUS status;
9427 bool correct = true;
9428 bool got_break = false;
9429 bool acl_ret = false;
9431 struct posix_acl_oplock_state *state;
9433 printf("starting posix_acl_oplock test\n");
9435 if (!torture_open_connection(&cli1, 0)) {
9436 use_level_II_oplocks = false;
9437 use_oplocks = saved_use_oplocks;
9438 return false;
9441 if (!torture_open_connection(&cli2, 1)) {
9442 use_level_II_oplocks = false;
9443 use_oplocks = saved_use_oplocks;
9444 return false;
9447 /* Setup posix on cli2 only. */
9448 status = torture_setup_unix_extensions(cli2);
9449 if (!NT_STATUS_IS_OK(status)) {
9450 return false;
9453 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9454 smbXcli_conn_set_sockopt(cli2->conn, sockops);
9456 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9458 /* Create the file on the Windows connection. */
9459 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9460 &fnum);
9461 if (!NT_STATUS_IS_OK(status)) {
9462 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9463 return false;
9466 status = cli_close(cli1, fnum);
9467 if (!NT_STATUS_IS_OK(status)) {
9468 printf("close1 failed (%s)\n", nt_errstr(status));
9469 return false;
9472 cli1->use_oplocks = true;
9474 /* Open with oplock. */
9475 status = cli_ntcreate(cli1,
9476 fname,
9478 FILE_READ_DATA,
9479 FILE_ATTRIBUTE_NORMAL,
9480 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9481 FILE_OPEN,
9484 &fnum,
9485 NULL);
9487 if (!NT_STATUS_IS_OK(status)) {
9488 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9489 return false;
9492 ev = samba_tevent_context_init(talloc_tos());
9493 if (ev == NULL) {
9494 printf("tevent_context_init failed\n");
9495 return false;
9498 state = talloc_zero(ev, struct posix_acl_oplock_state);
9499 if (state == NULL) {
9500 printf("talloc failed\n");
9501 return false;
9503 state->ev = ev;
9504 state->cli = cli1;
9505 state->got_break = &got_break;
9506 state->acl_ret = &acl_ret;
9508 oplock_req = cli_smb_oplock_break_waiter_send(
9509 talloc_tos(), ev, cli1);
9510 if (oplock_req == NULL) {
9511 printf("cli_smb_oplock_break_waiter_send failed\n");
9512 return false;
9514 tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9516 /* Get ACL on POSIX connection - should break oplock. */
9517 getacl_req = cli_posix_getacl_send(talloc_tos(),
9519 cli2,
9520 fname);
9521 if (getacl_req == NULL) {
9522 printf("cli_posix_getacl_send failed\n");
9523 return false;
9525 tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9527 while (!got_break || !acl_ret) {
9528 int ret;
9529 ret = tevent_loop_once(ev);
9530 if (ret == -1) {
9531 printf("tevent_loop_once failed: %s\n",
9532 strerror(errno));
9533 return false;
9537 if (!NT_STATUS_IS_OK(state->status)) {
9538 printf("getacl failed (%s)\n", nt_errstr(state->status));
9539 correct = false;
9542 status = cli_close(cli1, fnum);
9543 if (!NT_STATUS_IS_OK(status)) {
9544 printf("close2 failed (%s)\n", nt_errstr(status));
9545 correct = false;
9548 status = cli_unlink(cli1,
9549 fname,
9550 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9551 if (!NT_STATUS_IS_OK(status)) {
9552 printf("unlink failed (%s)\n", nt_errstr(status));
9553 correct = false;
9556 if (!torture_close_connection(cli1)) {
9557 correct = false;
9559 if (!torture_close_connection(cli2)) {
9560 correct = false;
9563 if (!got_break) {
9564 correct = false;
9567 printf("finished posix acl oplock test\n");
9569 return correct;
9572 static bool run_posix_acl_shareroot_test(int dummy)
9574 struct cli_state *cli;
9575 NTSTATUS status;
9576 bool correct = false;
9577 char *posix_acl = NULL;
9578 size_t posix_acl_len = 0;
9579 uint16_t num_file_acls = 0;
9580 uint16_t num_dir_acls = 0;
9581 uint16_t i;
9582 uint32_t expected_size = 0;
9583 bool got_user = false;
9584 bool got_group = false;
9585 bool got_other = false;
9586 TALLOC_CTX *frame = NULL;
9588 frame = talloc_stackframe();
9590 printf("starting posix_acl_shareroot test\n");
9592 if (!torture_open_connection(&cli, 0)) {
9593 TALLOC_FREE(frame);
9594 return false;
9597 smbXcli_conn_set_sockopt(cli->conn, sockops);
9599 status = torture_setup_unix_extensions(cli);
9600 if (!NT_STATUS_IS_OK(status)) {
9601 printf("Failed to setup unix extensions\n");
9602 goto out;
9605 /* Get the POSIX ACL on the root of the share. */
9606 status = cli_posix_getacl(cli,
9607 ".",
9608 frame,
9609 &posix_acl_len,
9610 &posix_acl);
9612 if (!NT_STATUS_IS_OK(status)) {
9613 printf("cli_posix_getacl of '.' failed (%s)\n",
9614 nt_errstr(status));
9615 goto out;
9618 if (posix_acl_len < 6 ||
9619 SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9620 printf("getfacl ., unknown POSIX acl version %u.\n",
9621 (unsigned int)CVAL(posix_acl,0) );
9622 goto out;
9625 num_file_acls = SVAL(posix_acl,2);
9626 num_dir_acls = SVAL(posix_acl,4);
9627 expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9628 SMB_POSIX_ACL_ENTRY_SIZE*
9629 (num_file_acls+num_dir_acls);
9631 if (posix_acl_len != expected_size) {
9632 printf("incorrect POSIX acl buffer size "
9633 "(should be %u, was %u).\n",
9634 (unsigned int)expected_size,
9635 (unsigned int)posix_acl_len);
9636 goto out;
9640 * We don't need to know what the ACL's are
9641 * we just need to know we have at least 3
9642 * file entries (u,g,o).
9645 for (i = 0; i < num_file_acls; i++) {
9646 unsigned char tagtype =
9647 CVAL(posix_acl,
9648 SMB_POSIX_ACL_HEADER_SIZE+
9649 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9651 switch(tagtype) {
9652 case SMB_POSIX_ACL_USER_OBJ:
9653 got_user = true;
9654 break;
9655 case SMB_POSIX_ACL_GROUP_OBJ:
9656 got_group = true;
9657 break;
9658 case SMB_POSIX_ACL_OTHER:
9659 got_other = true;
9660 break;
9661 default:
9662 break;
9666 if (!got_user) {
9667 printf("Missing user entry\n");
9668 goto out;
9671 if (!got_group) {
9672 printf("Missing group entry\n");
9673 goto out;
9676 if (!got_other) {
9677 printf("Missing other entry\n");
9678 goto out;
9681 correct = true;
9683 out:
9685 if (!torture_close_connection(cli)) {
9686 correct = false;
9689 printf("finished posix acl shareroot test\n");
9690 TALLOC_FREE(frame);
9692 return correct;
9695 static uint32_t open_attrs_table[] = {
9696 FILE_ATTRIBUTE_NORMAL,
9697 FILE_ATTRIBUTE_ARCHIVE,
9698 FILE_ATTRIBUTE_READONLY,
9699 FILE_ATTRIBUTE_HIDDEN,
9700 FILE_ATTRIBUTE_SYSTEM,
9702 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9703 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9704 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9705 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9706 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9707 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9709 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9710 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9711 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9712 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9715 struct trunc_open_results {
9716 unsigned int num;
9717 uint32_t init_attr;
9718 uint32_t trunc_attr;
9719 uint32_t result_attr;
9722 static struct trunc_open_results attr_results[] = {
9723 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9724 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9725 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9726 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9727 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9728 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9729 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9730 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9731 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9732 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9733 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9734 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9735 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9736 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9737 { 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 },
9738 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9739 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9740 { 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 },
9741 { 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 },
9742 { 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 },
9743 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9744 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9745 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9746 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9747 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9748 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9751 static bool run_openattrtest(int dummy)
9753 static struct cli_state *cli1;
9754 const char *fname = "\\openattr.file";
9755 uint16_t fnum1;
9756 bool correct = True;
9757 uint32_t attr;
9758 unsigned int i, j, k, l;
9759 NTSTATUS status;
9761 printf("starting open attr test\n");
9763 if (!torture_open_connection(&cli1, 0)) {
9764 return False;
9767 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9769 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9770 cli_setatr(cli1, fname, 0, 0);
9771 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9773 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9774 open_attrs_table[i], FILE_SHARE_NONE,
9775 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9776 if (!NT_STATUS_IS_OK(status)) {
9777 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9778 return False;
9781 status = cli_close(cli1, fnum1);
9782 if (!NT_STATUS_IS_OK(status)) {
9783 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9784 return False;
9787 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9788 status = cli_ntcreate(cli1, fname, 0,
9789 FILE_READ_DATA|FILE_WRITE_DATA,
9790 open_attrs_table[j],
9791 FILE_SHARE_NONE, FILE_OVERWRITE,
9792 0, 0, &fnum1, NULL);
9793 if (!NT_STATUS_IS_OK(status)) {
9794 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9795 if (attr_results[l].num == k) {
9796 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9797 k, open_attrs_table[i],
9798 open_attrs_table[j],
9799 fname, NT_STATUS_V(status), nt_errstr(status));
9800 correct = False;
9804 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9805 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9806 k, open_attrs_table[i], open_attrs_table[j],
9807 nt_errstr(status));
9808 correct = False;
9810 #if 0
9811 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9812 #endif
9813 k++;
9814 continue;
9817 status = cli_close(cli1, fnum1);
9818 if (!NT_STATUS_IS_OK(status)) {
9819 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9820 return False;
9823 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9824 if (!NT_STATUS_IS_OK(status)) {
9825 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9826 return False;
9829 #if 0
9830 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9831 k, open_attrs_table[i], open_attrs_table[j], attr );
9832 #endif
9834 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9835 if (attr_results[l].num == k) {
9836 if (attr != attr_results[l].result_attr ||
9837 open_attrs_table[i] != attr_results[l].init_attr ||
9838 open_attrs_table[j] != attr_results[l].trunc_attr) {
9839 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9840 open_attrs_table[i],
9841 open_attrs_table[j],
9842 (unsigned int)attr,
9843 attr_results[l].result_attr);
9844 correct = False;
9846 break;
9849 k++;
9853 cli_setatr(cli1, fname, 0, 0);
9854 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9856 printf("open attr test %s.\n", correct ? "passed" : "failed");
9858 if (!torture_close_connection(cli1)) {
9859 correct = False;
9861 return correct;
9864 static NTSTATUS list_fn(struct file_info *finfo,
9865 const char *name, void *state)
9867 int *matched = (int *)state;
9868 if (matched != NULL) {
9869 *matched += 1;
9871 return NT_STATUS_OK;
9875 test directory listing speed
9877 static bool run_dirtest(int dummy)
9879 int i;
9880 static struct cli_state *cli;
9881 uint16_t fnum;
9882 struct timeval core_start;
9883 bool correct = True;
9884 int matched;
9886 printf("starting directory test\n");
9888 if (!torture_open_connection(&cli, 0)) {
9889 return False;
9892 smbXcli_conn_set_sockopt(cli->conn, sockops);
9894 srandom(0);
9895 for (i=0;i<torture_numops;i++) {
9896 fstring fname;
9897 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9898 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9899 fprintf(stderr,"Failed to open %s\n", fname);
9900 return False;
9902 cli_close(cli, fnum);
9905 core_start = timeval_current();
9907 matched = 0;
9908 cli_list(cli, "a*.*", 0, list_fn, &matched);
9909 printf("Matched %d\n", matched);
9911 matched = 0;
9912 cli_list(cli, "b*.*", 0, list_fn, &matched);
9913 printf("Matched %d\n", matched);
9915 matched = 0;
9916 cli_list(cli, "xyzabc", 0, list_fn, &matched);
9917 printf("Matched %d\n", matched);
9919 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9921 srandom(0);
9922 for (i=0;i<torture_numops;i++) {
9923 fstring fname;
9924 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9925 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9928 if (!torture_close_connection(cli)) {
9929 correct = False;
9932 printf("finished dirtest\n");
9934 return correct;
9937 static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9938 void *state)
9940 struct cli_state *pcli = (struct cli_state *)state;
9941 fstring fname;
9942 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9944 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9945 return NT_STATUS_OK;
9947 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9948 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9949 printf("del_fn: failed to rmdir %s\n,", fname );
9950 } else {
9951 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9952 printf("del_fn: failed to unlink %s\n,", fname );
9954 return NT_STATUS_OK;
9959 send a raw ioctl - used by the torture code
9961 static NTSTATUS cli_raw_ioctl(struct cli_state *cli,
9962 uint16_t fnum,
9963 uint32_t code,
9964 DATA_BLOB *blob)
9966 uint16_t vwv[3];
9967 NTSTATUS status;
9969 PUSH_LE_U16(vwv + 0, 0, fnum);
9970 PUSH_LE_U16(vwv + 1, 0, code >> 16);
9971 PUSH_LE_U16(vwv + 2, 0, (code & 0xFFFF));
9973 status = cli_smb(talloc_tos(),
9974 cli,
9975 SMBioctl,
9978 vwv,
9980 NULL,
9981 NULL,
9983 NULL,
9984 NULL,
9985 NULL,
9986 NULL);
9987 if (!NT_STATUS_IS_OK(status)) {
9988 return status;
9990 *blob = data_blob_null;
9991 return NT_STATUS_OK;
9995 sees what IOCTLs are supported
9997 bool torture_ioctl_test(int dummy)
9999 static struct cli_state *cli;
10000 uint16_t device, function;
10001 uint16_t fnum;
10002 const char *fname = "\\ioctl.dat";
10003 DATA_BLOB blob;
10004 NTSTATUS status;
10006 if (!torture_open_connection(&cli, 0)) {
10007 return False;
10010 printf("starting ioctl test\n");
10012 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10014 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
10015 if (!NT_STATUS_IS_OK(status)) {
10016 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
10017 return False;
10020 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
10021 printf("ioctl device info: %s\n", nt_errstr(status));
10023 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
10024 printf("ioctl job info: %s\n", nt_errstr(status));
10026 for (device=0;device<0x100;device++) {
10027 printf("ioctl test with device = 0x%x\n", device);
10028 for (function=0;function<0x100;function++) {
10029 uint32_t code = (device<<16) | function;
10031 status = cli_raw_ioctl(cli, fnum, code, &blob);
10033 if (NT_STATUS_IS_OK(status)) {
10034 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
10035 (int)blob.length);
10036 data_blob_free(&blob);
10041 if (!torture_close_connection(cli)) {
10042 return False;
10045 return True;
10050 tries variants of chkpath
10052 bool torture_chkpath_test(int dummy)
10054 static struct cli_state *cli;
10055 uint16_t fnum;
10056 bool ret;
10057 NTSTATUS status;
10059 if (!torture_open_connection(&cli, 0)) {
10060 return False;
10063 printf("starting chkpath test\n");
10065 /* cleanup from an old run */
10066 torture_deltree(cli, "\\chkpath.dir");
10068 status = cli_mkdir(cli, "\\chkpath.dir");
10069 if (!NT_STATUS_IS_OK(status)) {
10070 printf("mkdir1 failed : %s\n", nt_errstr(status));
10071 return False;
10074 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
10075 if (!NT_STATUS_IS_OK(status)) {
10076 printf("mkdir2 failed : %s\n", nt_errstr(status));
10077 return False;
10080 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
10081 DENY_NONE, &fnum);
10082 if (!NT_STATUS_IS_OK(status)) {
10083 printf("open1 failed (%s)\n", nt_errstr(status));
10084 return False;
10086 cli_close(cli, fnum);
10088 status = cli_chkpath(cli, "\\chkpath.dir");
10089 if (!NT_STATUS_IS_OK(status)) {
10090 printf("chkpath1 failed: %s\n", nt_errstr(status));
10091 ret = False;
10094 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
10095 if (!NT_STATUS_IS_OK(status)) {
10096 printf("chkpath2 failed: %s\n", nt_errstr(status));
10097 ret = False;
10100 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
10101 if (!NT_STATUS_IS_OK(status)) {
10102 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10103 NT_STATUS_NOT_A_DIRECTORY);
10104 } else {
10105 printf("* chkpath on a file should fail\n");
10106 ret = False;
10109 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
10110 if (!NT_STATUS_IS_OK(status)) {
10111 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
10112 NT_STATUS_OBJECT_NAME_NOT_FOUND);
10113 } else {
10114 printf("* chkpath on a non existent file should fail\n");
10115 ret = False;
10118 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
10119 if (!NT_STATUS_IS_OK(status)) {
10120 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10121 NT_STATUS_OBJECT_PATH_NOT_FOUND);
10122 } else {
10123 printf("* chkpath on a non existent component should fail\n");
10124 ret = False;
10127 torture_deltree(cli, "\\chkpath.dir");
10129 if (!torture_close_connection(cli)) {
10130 return False;
10133 return ret;
10136 static bool run_eatest(int dummy)
10138 static struct cli_state *cli;
10139 const char *fname = "\\eatest.txt";
10140 bool correct = True;
10141 uint16_t fnum;
10142 size_t i, num_eas;
10143 struct ea_struct *ea_list = NULL;
10144 TALLOC_CTX *mem_ctx = talloc_init("eatest");
10145 NTSTATUS status;
10147 printf("starting eatest\n");
10149 if (!torture_open_connection(&cli, 0)) {
10150 talloc_destroy(mem_ctx);
10151 return False;
10154 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10156 status = cli_ntcreate(cli, fname, 0,
10157 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10158 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10159 0x4044, 0, &fnum, NULL);
10160 if (!NT_STATUS_IS_OK(status)) {
10161 printf("open failed - %s\n", nt_errstr(status));
10162 talloc_destroy(mem_ctx);
10163 return False;
10166 for (i = 0; i < 10; i++) {
10167 fstring ea_name, ea_val;
10169 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10170 memset(ea_val, (char)i+1, i+1);
10171 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10172 if (!NT_STATUS_IS_OK(status)) {
10173 printf("ea_set of name %s failed - %s\n", ea_name,
10174 nt_errstr(status));
10175 talloc_destroy(mem_ctx);
10176 return False;
10180 cli_close(cli, fnum);
10181 for (i = 0; i < 10; i++) {
10182 fstring ea_name, ea_val;
10184 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10185 memset(ea_val, (char)i+1, i+1);
10186 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10187 if (!NT_STATUS_IS_OK(status)) {
10188 printf("ea_set of name %s failed - %s\n", ea_name,
10189 nt_errstr(status));
10190 talloc_destroy(mem_ctx);
10191 return False;
10195 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10196 if (!NT_STATUS_IS_OK(status)) {
10197 printf("ea_get list failed - %s\n", nt_errstr(status));
10198 correct = False;
10201 printf("num_eas = %d\n", (int)num_eas);
10203 if (num_eas != 20) {
10204 printf("Should be 20 EA's stored... failing.\n");
10205 correct = False;
10208 for (i = 0; i < num_eas; i++) {
10209 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10210 dump_data(0, ea_list[i].value.data,
10211 ea_list[i].value.length);
10214 /* Setting EA's to zero length deletes them. Test this */
10215 printf("Now deleting all EA's - case independent....\n");
10217 #if 1
10218 cli_set_ea_path(cli, fname, "", "", 0);
10219 #else
10220 for (i = 0; i < 20; i++) {
10221 fstring ea_name;
10222 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10223 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10224 if (!NT_STATUS_IS_OK(status)) {
10225 printf("ea_set of name %s failed - %s\n", ea_name,
10226 nt_errstr(status));
10227 talloc_destroy(mem_ctx);
10228 return False;
10231 #endif
10233 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10234 if (!NT_STATUS_IS_OK(status)) {
10235 printf("ea_get list failed - %s\n", nt_errstr(status));
10236 correct = False;
10239 printf("num_eas = %d\n", (int)num_eas);
10240 for (i = 0; i < num_eas; i++) {
10241 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10242 dump_data(0, ea_list[i].value.data,
10243 ea_list[i].value.length);
10246 if (num_eas != 0) {
10247 printf("deleting EA's failed.\n");
10248 correct = False;
10251 /* Try and delete a non existent EA. */
10252 status = cli_set_ea_path(cli, fname, "foo", "", 0);
10253 if (!NT_STATUS_IS_OK(status)) {
10254 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10255 nt_errstr(status));
10256 correct = False;
10259 talloc_destroy(mem_ctx);
10260 if (!torture_close_connection(cli)) {
10261 correct = False;
10264 return correct;
10267 static bool run_dirtest1(int dummy)
10269 int i;
10270 static struct cli_state *cli;
10271 uint16_t fnum;
10272 int num_seen;
10273 bool correct = True;
10275 printf("starting directory test\n");
10277 if (!torture_open_connection(&cli, 0)) {
10278 return False;
10281 smbXcli_conn_set_sockopt(cli->conn, sockops);
10283 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10284 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10285 cli_rmdir(cli, "\\LISTDIR");
10286 cli_mkdir(cli, "\\LISTDIR");
10288 /* Create 1000 files and 1000 directories. */
10289 for (i=0;i<1000;i++) {
10290 fstring fname;
10291 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10292 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10293 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10294 0, 0, &fnum, NULL))) {
10295 fprintf(stderr,"Failed to open %s\n", fname);
10296 return False;
10298 cli_close(cli, fnum);
10300 for (i=0;i<1000;i++) {
10301 fstring fname;
10302 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10303 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10304 fprintf(stderr,"Failed to open %s\n", fname);
10305 return False;
10309 /* Now ensure that doing an old list sees both files and directories. */
10310 num_seen = 0;
10311 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10312 printf("num_seen = %d\n", num_seen );
10313 /* We should see 100 files + 1000 directories + . and .. */
10314 if (num_seen != 2002)
10315 correct = False;
10317 /* Ensure if we have the "must have" bits we only see the
10318 * relevant entries.
10320 num_seen = 0;
10321 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10322 printf("num_seen = %d\n", num_seen );
10323 if (num_seen != 1002)
10324 correct = False;
10326 num_seen = 0;
10327 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10328 printf("num_seen = %d\n", num_seen );
10329 if (num_seen != 1000)
10330 correct = False;
10332 /* Delete everything. */
10333 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10334 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10335 cli_rmdir(cli, "\\LISTDIR");
10337 #if 0
10338 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10339 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10340 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10341 #endif
10343 if (!torture_close_connection(cli)) {
10344 correct = False;
10347 printf("finished dirtest1\n");
10349 return correct;
10352 static bool run_error_map_extract(int dummy) {
10354 static struct cli_state *c_dos;
10355 static struct cli_state *c_nt;
10356 NTSTATUS status;
10358 uint32_t error;
10360 uint32_t errnum;
10361 uint8_t errclass;
10363 NTSTATUS nt_status;
10365 fstring user;
10367 /* NT-Error connection */
10369 disable_spnego = true;
10370 if (!(c_nt = open_nbt_connection())) {
10371 disable_spnego = false;
10372 return False;
10374 disable_spnego = false;
10376 status = smbXcli_negprot(c_nt->conn,
10377 c_nt->timeout,
10378 PROTOCOL_CORE,
10379 PROTOCOL_NT1,
10380 NULL,
10381 NULL,
10382 NULL);
10384 if (!NT_STATUS_IS_OK(status)) {
10385 printf("%s rejected the NT-error negprot (%s)\n", host,
10386 nt_errstr(status));
10387 cli_shutdown(c_nt);
10388 return False;
10391 status = cli_session_setup_anon(c_nt);
10392 if (!NT_STATUS_IS_OK(status)) {
10393 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10394 return False;
10397 /* DOS-Error connection */
10399 disable_spnego = true;
10400 force_dos_errors = true;
10401 if (!(c_dos = open_nbt_connection())) {
10402 disable_spnego = false;
10403 force_dos_errors = false;
10404 return False;
10406 disable_spnego = false;
10407 force_dos_errors = false;
10409 status = smbXcli_negprot(c_dos->conn,
10410 c_dos->timeout,
10411 PROTOCOL_CORE,
10412 PROTOCOL_NT1,
10413 NULL,
10414 NULL,
10415 NULL);
10416 if (!NT_STATUS_IS_OK(status)) {
10417 printf("%s rejected the DOS-error negprot (%s)\n", host,
10418 nt_errstr(status));
10419 cli_shutdown(c_dos);
10420 return False;
10423 status = cli_session_setup_anon(c_dos);
10424 if (!NT_STATUS_IS_OK(status)) {
10425 printf("%s rejected the DOS-error initial session setup (%s)\n",
10426 host, nt_errstr(status));
10427 return False;
10430 c_nt->map_dos_errors = false;
10431 c_dos->map_dos_errors = false;
10433 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10434 struct cli_credentials *user_creds = NULL;
10436 fstr_sprintf(user, "%X", error);
10438 user_creds = cli_session_creds_init(talloc_tos(),
10439 user,
10440 workgroup,
10441 NULL, /* realm */
10442 password,
10443 false, /* use_kerberos */
10444 false, /* fallback_after_kerberos */
10445 false, /* use_ccache */
10446 false); /* password_is_nt_hash */
10447 if (user_creds == NULL) {
10448 printf("cli_session_creds_init(%s) failed\n", user);
10449 return false;
10452 status = cli_session_setup_creds(c_nt, user_creds);
10453 if (NT_STATUS_IS_OK(status)) {
10454 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10457 /* Case #1: 32-bit NT errors */
10458 if (!NT_STATUS_IS_DOS(status)) {
10459 nt_status = status;
10460 } else {
10461 printf("/** Dos error on NT connection! (%s) */\n",
10462 nt_errstr(status));
10463 nt_status = NT_STATUS(0xc0000000);
10466 status = cli_session_setup_creds(c_dos, user_creds);
10467 if (NT_STATUS_IS_OK(status)) {
10468 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10471 /* Case #1: 32-bit NT errors */
10472 if (NT_STATUS_IS_DOS(status)) {
10473 printf("/** NT error on DOS connection! (%s) */\n",
10474 nt_errstr(status));
10475 errnum = errclass = 0;
10476 } else {
10477 errclass = NT_STATUS_DOS_CLASS(status);
10478 errnum = NT_STATUS_DOS_CODE(status);
10481 if (NT_STATUS_V(nt_status) != error) {
10482 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10483 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
10484 get_nt_error_c_code(talloc_tos(), nt_status));
10487 printf("\t{%s,\t%s,\t%s},\n",
10488 smb_dos_err_class(errclass),
10489 smb_dos_err_name(errclass, errnum),
10490 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10492 TALLOC_FREE(user_creds);
10494 return True;
10497 static bool run_sesssetup_bench(int dummy)
10499 static struct cli_state *c;
10500 const char *fname = "\\file.dat";
10501 uint16_t fnum;
10502 NTSTATUS status;
10503 int i;
10505 if (!torture_open_connection(&c, 0)) {
10506 return false;
10509 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10510 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10511 FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10512 if (!NT_STATUS_IS_OK(status)) {
10513 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10514 return false;
10517 for (i=0; i<torture_numops; i++) {
10518 status = cli_session_setup_creds(c, torture_creds);
10519 if (!NT_STATUS_IS_OK(status)) {
10520 d_printf("(%s) cli_session_setup_creds failed: %s\n",
10521 __location__, nt_errstr(status));
10522 return false;
10525 d_printf("\r%d ", (int)cli_state_get_uid(c));
10527 status = cli_ulogoff(c);
10528 if (!NT_STATUS_IS_OK(status)) {
10529 d_printf("(%s) cli_ulogoff failed: %s\n",
10530 __location__, nt_errstr(status));
10531 return false;
10535 return true;
10538 static bool subst_test(const char *str, const char *user, const char *domain,
10539 uid_t uid, gid_t gid, const char *expected)
10541 char *subst;
10542 bool result = true;
10544 subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10546 if (strcmp(subst, expected) != 0) {
10547 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10548 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10549 expected);
10550 result = false;
10553 TALLOC_FREE(subst);
10554 return result;
10557 static void chain1_open_completion(struct tevent_req *req)
10559 uint16_t fnum;
10560 NTSTATUS status;
10561 status = cli_openx_recv(req, &fnum);
10562 TALLOC_FREE(req);
10564 d_printf("cli_openx_recv returned %s: %d\n",
10565 nt_errstr(status),
10566 NT_STATUS_IS_OK(status) ? fnum : -1);
10569 static void chain1_write_completion(struct tevent_req *req)
10571 size_t written;
10572 NTSTATUS status;
10573 status = cli_write_andx_recv(req, &written);
10574 TALLOC_FREE(req);
10576 d_printf("cli_write_andx_recv returned %s: %d\n",
10577 nt_errstr(status),
10578 NT_STATUS_IS_OK(status) ? (int)written : -1);
10581 static void chain1_close_completion(struct tevent_req *req)
10583 NTSTATUS status;
10584 bool *done = (bool *)tevent_req_callback_data_void(req);
10586 status = cli_close_recv(req);
10587 *done = true;
10589 TALLOC_FREE(req);
10591 d_printf("cli_close returned %s\n", nt_errstr(status));
10594 static bool run_chain1(int dummy)
10596 struct cli_state *cli1;
10597 struct tevent_context *evt = samba_tevent_context_init(NULL);
10598 struct tevent_req *reqs[3], *smbreqs[3];
10599 bool done = false;
10600 const char *str = "foobar";
10601 const char *fname = "\\test_chain";
10602 NTSTATUS status;
10604 printf("starting chain1 test\n");
10605 if (!torture_open_connection(&cli1, 0)) {
10606 return False;
10609 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10611 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10613 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10614 O_CREAT|O_RDWR, 0, &smbreqs[0]);
10615 if (reqs[0] == NULL) return false;
10616 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10619 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10620 (const uint8_t *)str, 0, strlen(str)+1,
10621 smbreqs, 1, &smbreqs[1]);
10622 if (reqs[1] == NULL) return false;
10623 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10625 reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10626 if (reqs[2] == NULL) return false;
10627 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10629 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10630 if (!NT_STATUS_IS_OK(status)) {
10631 return false;
10634 while (!done) {
10635 tevent_loop_once(evt);
10638 torture_close_connection(cli1);
10639 return True;
10642 static void chain2_sesssetup_completion(struct tevent_req *req)
10644 NTSTATUS status;
10645 status = cli_session_setup_guest_recv(req);
10646 d_printf("sesssetup returned %s\n", nt_errstr(status));
10649 static void chain2_tcon_completion(struct tevent_req *req)
10651 bool *done = (bool *)tevent_req_callback_data_void(req);
10652 NTSTATUS status;
10653 status = cli_tcon_andx_recv(req);
10654 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10655 *done = true;
10658 static bool run_chain2(int dummy)
10660 struct cli_state *cli1;
10661 struct tevent_context *evt = samba_tevent_context_init(NULL);
10662 struct tevent_req *reqs[2], *smbreqs[2];
10663 bool done = false;
10664 NTSTATUS status;
10665 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10667 printf("starting chain2 test\n");
10668 status = cli_start_connection(talloc_tos(),
10669 &cli1,
10670 lp_netbios_name(),
10671 host,
10672 NULL,
10673 port_to_use,
10674 SMB_SIGNING_DEFAULT,
10675 flags);
10676 if (!NT_STATUS_IS_OK(status)) {
10677 return False;
10680 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10682 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10683 &smbreqs[0]);
10684 if (reqs[0] == NULL) return false;
10685 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10687 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10688 "?????", NULL, 0, &smbreqs[1]);
10689 if (reqs[1] == NULL) return false;
10690 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10692 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10693 if (!NT_STATUS_IS_OK(status)) {
10694 return false;
10697 while (!done) {
10698 tevent_loop_once(evt);
10701 torture_close_connection(cli1);
10702 return True;
10706 struct torture_createdel_state {
10707 struct tevent_context *ev;
10708 struct cli_state *cli;
10711 static void torture_createdel_created(struct tevent_req *subreq);
10712 static void torture_createdel_closed(struct tevent_req *subreq);
10714 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10715 struct tevent_context *ev,
10716 struct cli_state *cli,
10717 const char *name)
10719 struct tevent_req *req, *subreq;
10720 struct torture_createdel_state *state;
10722 req = tevent_req_create(mem_ctx, &state,
10723 struct torture_createdel_state);
10724 if (req == NULL) {
10725 return NULL;
10727 state->ev = ev;
10728 state->cli = cli;
10730 subreq = cli_ntcreate_send(
10731 state, ev, cli, name, 0,
10732 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10733 FILE_ATTRIBUTE_NORMAL,
10734 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10735 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10736 SMB2_IMPERSONATION_IMPERSONATION, 0);
10738 if (tevent_req_nomem(subreq, req)) {
10739 return tevent_req_post(req, ev);
10741 tevent_req_set_callback(subreq, torture_createdel_created, req);
10742 return req;
10745 static void torture_createdel_created(struct tevent_req *subreq)
10747 struct tevent_req *req = tevent_req_callback_data(
10748 subreq, struct tevent_req);
10749 struct torture_createdel_state *state = tevent_req_data(
10750 req, struct torture_createdel_state);
10751 NTSTATUS status;
10752 uint16_t fnum;
10754 status = cli_ntcreate_recv(subreq, &fnum, NULL);
10755 TALLOC_FREE(subreq);
10756 if (tevent_req_nterror(req, status)) {
10757 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10758 nt_errstr(status)));
10759 return;
10762 subreq = cli_close_send(state, state->ev, state->cli, fnum, 0);
10763 if (tevent_req_nomem(subreq, req)) {
10764 return;
10766 tevent_req_set_callback(subreq, torture_createdel_closed, req);
10769 static void torture_createdel_closed(struct tevent_req *subreq)
10771 struct tevent_req *req = tevent_req_callback_data(
10772 subreq, struct tevent_req);
10773 NTSTATUS status;
10775 status = cli_close_recv(subreq);
10776 if (tevent_req_nterror(req, status)) {
10777 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10778 return;
10780 tevent_req_done(req);
10783 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10785 return tevent_req_simple_recv_ntstatus(req);
10788 struct torture_createdels_state {
10789 struct tevent_context *ev;
10790 struct cli_state *cli;
10791 const char *base_name;
10792 int sent;
10793 int received;
10794 int num_files;
10795 struct tevent_req **reqs;
10798 static void torture_createdels_done(struct tevent_req *subreq);
10800 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10801 struct tevent_context *ev,
10802 struct cli_state *cli,
10803 const char *base_name,
10804 int num_parallel,
10805 int num_files)
10807 struct tevent_req *req;
10808 struct torture_createdels_state *state;
10809 int i;
10811 req = tevent_req_create(mem_ctx, &state,
10812 struct torture_createdels_state);
10813 if (req == NULL) {
10814 return NULL;
10816 state->ev = ev;
10817 state->cli = cli;
10818 state->base_name = talloc_strdup(state, base_name);
10819 if (tevent_req_nomem(state->base_name, req)) {
10820 return tevent_req_post(req, ev);
10822 state->num_files = MAX(num_parallel, num_files);
10823 state->sent = 0;
10824 state->received = 0;
10826 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10827 if (tevent_req_nomem(state->reqs, req)) {
10828 return tevent_req_post(req, ev);
10831 for (i=0; i<num_parallel; i++) {
10832 char *name;
10834 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10835 state->sent);
10836 if (tevent_req_nomem(name, req)) {
10837 return tevent_req_post(req, ev);
10839 state->reqs[i] = torture_createdel_send(
10840 state->reqs, state->ev, state->cli, name);
10841 if (tevent_req_nomem(state->reqs[i], req)) {
10842 return tevent_req_post(req, ev);
10844 name = talloc_move(state->reqs[i], &name);
10845 tevent_req_set_callback(state->reqs[i],
10846 torture_createdels_done, req);
10847 state->sent += 1;
10849 return req;
10852 static void torture_createdels_done(struct tevent_req *subreq)
10854 struct tevent_req *req = tevent_req_callback_data(
10855 subreq, struct tevent_req);
10856 struct torture_createdels_state *state = tevent_req_data(
10857 req, struct torture_createdels_state);
10858 size_t i, num_parallel = talloc_array_length(state->reqs);
10859 NTSTATUS status;
10860 char *name;
10862 status = torture_createdel_recv(subreq);
10863 if (!NT_STATUS_IS_OK(status)){
10864 DEBUG(10, ("torture_createdel_recv returned %s\n",
10865 nt_errstr(status)));
10866 TALLOC_FREE(subreq);
10867 tevent_req_nterror(req, status);
10868 return;
10871 for (i=0; i<num_parallel; i++) {
10872 if (subreq == state->reqs[i]) {
10873 break;
10876 if (i == num_parallel) {
10877 DEBUG(10, ("received something we did not send\n"));
10878 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10879 return;
10881 TALLOC_FREE(state->reqs[i]);
10883 if (state->sent >= state->num_files) {
10884 tevent_req_done(req);
10885 return;
10888 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10889 state->sent);
10890 if (tevent_req_nomem(name, req)) {
10891 return;
10893 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10894 state->cli, name);
10895 if (tevent_req_nomem(state->reqs[i], req)) {
10896 return;
10898 name = talloc_move(state->reqs[i], &name);
10899 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10900 state->sent += 1;
10903 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10905 return tevent_req_simple_recv_ntstatus(req);
10908 struct swallow_notify_state {
10909 struct tevent_context *ev;
10910 struct cli_state *cli;
10911 uint16_t fnum;
10912 uint32_t completion_filter;
10913 bool recursive;
10914 bool (*fn)(uint32_t action, const char *name, void *priv);
10915 void *priv;
10918 static void swallow_notify_done(struct tevent_req *subreq);
10920 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10921 struct tevent_context *ev,
10922 struct cli_state *cli,
10923 uint16_t fnum,
10924 uint32_t completion_filter,
10925 bool recursive,
10926 bool (*fn)(uint32_t action,
10927 const char *name,
10928 void *priv),
10929 void *priv)
10931 struct tevent_req *req, *subreq;
10932 struct swallow_notify_state *state;
10934 req = tevent_req_create(mem_ctx, &state,
10935 struct swallow_notify_state);
10936 if (req == NULL) {
10937 return NULL;
10939 state->ev = ev;
10940 state->cli = cli;
10941 state->fnum = fnum;
10942 state->completion_filter = completion_filter;
10943 state->recursive = recursive;
10944 state->fn = fn;
10945 state->priv = priv;
10947 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10948 0xffff, state->completion_filter,
10949 state->recursive);
10950 if (tevent_req_nomem(subreq, req)) {
10951 return tevent_req_post(req, ev);
10953 tevent_req_set_callback(subreq, swallow_notify_done, req);
10954 return req;
10957 static void swallow_notify_done(struct tevent_req *subreq)
10959 struct tevent_req *req = tevent_req_callback_data(
10960 subreq, struct tevent_req);
10961 struct swallow_notify_state *state = tevent_req_data(
10962 req, struct swallow_notify_state);
10963 NTSTATUS status;
10964 uint32_t i, num_changes;
10965 struct notify_change *changes;
10967 status = cli_notify_recv(subreq, state, &num_changes, &changes);
10968 TALLOC_FREE(subreq);
10969 if (!NT_STATUS_IS_OK(status)) {
10970 DEBUG(10, ("cli_notify_recv returned %s\n",
10971 nt_errstr(status)));
10972 tevent_req_nterror(req, status);
10973 return;
10976 for (i=0; i<num_changes; i++) {
10977 state->fn(changes[i].action, changes[i].name, state->priv);
10979 TALLOC_FREE(changes);
10981 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10982 0xffff, state->completion_filter,
10983 state->recursive);
10984 if (tevent_req_nomem(subreq, req)) {
10985 return;
10987 tevent_req_set_callback(subreq, swallow_notify_done, req);
10990 static bool print_notifies(uint32_t action, const char *name, void *priv)
10992 if (DEBUGLEVEL > 5) {
10993 d_printf("%d %s\n", (int)action, name);
10995 return true;
10998 static void notify_bench_done(struct tevent_req *req)
11000 int *num_finished = (int *)tevent_req_callback_data_void(req);
11001 *num_finished += 1;
11004 static bool run_notify_bench(int dummy)
11006 const char *dname = "\\notify-bench";
11007 struct tevent_context *ev;
11008 NTSTATUS status;
11009 uint16_t dnum;
11010 struct tevent_req *req1;
11011 struct tevent_req *req2 = NULL;
11012 int i, num_unc_names;
11013 int num_finished = 0;
11015 printf("starting notify-bench test\n");
11017 if (use_multishare_conn) {
11018 char **unc_list;
11019 unc_list = file_lines_load(multishare_conn_fname,
11020 &num_unc_names, 0, NULL);
11021 if (!unc_list || num_unc_names <= 0) {
11022 d_printf("Failed to load unc names list from '%s'\n",
11023 multishare_conn_fname);
11024 return false;
11026 TALLOC_FREE(unc_list);
11027 } else {
11028 num_unc_names = 1;
11031 ev = samba_tevent_context_init(talloc_tos());
11032 if (ev == NULL) {
11033 d_printf("tevent_context_init failed\n");
11034 return false;
11037 for (i=0; i<num_unc_names; i++) {
11038 struct cli_state *cli;
11039 char *base_fname;
11041 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
11042 dname, i);
11043 if (base_fname == NULL) {
11044 return false;
11047 if (!torture_open_connection(&cli, i)) {
11048 return false;
11051 status = cli_ntcreate(cli, dname, 0,
11052 MAXIMUM_ALLOWED_ACCESS,
11053 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
11054 FILE_SHARE_DELETE,
11055 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
11056 &dnum, NULL);
11058 if (!NT_STATUS_IS_OK(status)) {
11059 d_printf("Could not create %s: %s\n", dname,
11060 nt_errstr(status));
11061 return false;
11064 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
11065 FILE_NOTIFY_CHANGE_FILE_NAME |
11066 FILE_NOTIFY_CHANGE_DIR_NAME |
11067 FILE_NOTIFY_CHANGE_ATTRIBUTES |
11068 FILE_NOTIFY_CHANGE_LAST_WRITE,
11069 false, print_notifies, NULL);
11070 if (req1 == NULL) {
11071 d_printf("Could not create notify request\n");
11072 return false;
11075 req2 = torture_createdels_send(talloc_tos(), ev, cli,
11076 base_fname, 10, torture_numops);
11077 if (req2 == NULL) {
11078 d_printf("Could not create createdels request\n");
11079 return false;
11081 TALLOC_FREE(base_fname);
11083 tevent_req_set_callback(req2, notify_bench_done,
11084 &num_finished);
11087 while (num_finished < num_unc_names) {
11088 int ret;
11089 ret = tevent_loop_once(ev);
11090 if (ret != 0) {
11091 d_printf("tevent_loop_once failed\n");
11092 return false;
11096 if (!tevent_req_poll(req2, ev)) {
11097 d_printf("tevent_req_poll failed\n");
11100 status = torture_createdels_recv(req2);
11101 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
11103 return true;
11106 static bool run_mangle1(int dummy)
11108 struct cli_state *cli;
11109 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
11110 uint16_t fnum;
11111 fstring alt_name;
11112 NTSTATUS status;
11114 printf("starting mangle1 test\n");
11115 if (!torture_open_connection(&cli, 0)) {
11116 return False;
11119 smbXcli_conn_set_sockopt(cli->conn, sockops);
11121 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11122 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11123 0, 0, &fnum, NULL);
11124 if (!NT_STATUS_IS_OK(status)) {
11125 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11126 return false;
11128 cli_close(cli, fnum);
11130 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
11131 if (!NT_STATUS_IS_OK(status)) {
11132 d_printf("cli_qpathinfo_alt_name failed: %s\n",
11133 nt_errstr(status));
11134 return false;
11136 d_printf("alt_name: %s\n", alt_name);
11138 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
11139 if (!NT_STATUS_IS_OK(status)) {
11140 d_printf("cli_openx(%s) failed: %s\n", alt_name,
11141 nt_errstr(status));
11142 return false;
11144 cli_close(cli, fnum);
11146 status = cli_qpathinfo1(cli, alt_name, NULL, NULL, NULL, NULL, NULL);
11147 if (!NT_STATUS_IS_OK(status)) {
11148 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
11149 nt_errstr(status));
11150 return false;
11153 return true;
11156 static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
11157 const char *mask,
11158 void *state)
11160 if (f->short_name == NULL) {
11161 return NT_STATUS_OK;
11164 if (strlen(f->short_name) == 0) {
11165 return NT_STATUS_OK;
11168 printf("unexpected shortname: %s\n", f->short_name);
11170 return NT_STATUS_OBJECT_NAME_INVALID;
11173 static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11174 const char *mask,
11175 void *state)
11177 char *name = state;
11179 printf("name: %s\n", f->name);
11180 fstrcpy(name, f->name);
11181 return NT_STATUS_OK;
11184 static bool run_mangle_illegal(int dummy)
11186 struct cli_state *cli = NULL;
11187 struct cli_state *cli_posix = NULL;
11188 const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11189 const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11190 char *mangled_path = NULL;
11191 uint16_t fnum;
11192 fstring name;
11193 fstring alt_name;
11194 NTSTATUS status;
11196 printf("starting mangle-illegal test\n");
11198 if (!torture_open_connection(&cli, 0)) {
11199 return False;
11202 smbXcli_conn_set_sockopt(cli->conn, sockops);
11204 if (!torture_open_connection(&cli_posix, 0)) {
11205 return false;
11208 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11210 status = torture_setup_unix_extensions(cli_posix);
11211 if (!NT_STATUS_IS_OK(status)) {
11212 return false;
11215 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11216 status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11217 if (!NT_STATUS_IS_OK(status)) {
11218 printf("mkdir1 failed : %s\n", nt_errstr(status));
11219 return False;
11223 * Create a file with illegal NTFS characters and test that we
11224 * get a usable mangled name
11227 cli_setatr(cli_posix, illegal_fname, 0, 0);
11228 cli_posix_unlink(cli_posix, illegal_fname);
11230 status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11231 0600, &fnum);
11232 if (!NT_STATUS_IS_OK(status)) {
11233 printf("POSIX create of %s failed (%s)\n",
11234 illegal_fname, nt_errstr(status));
11235 return false;
11238 status = cli_close(cli_posix, fnum);
11239 if (!NT_STATUS_IS_OK(status)) {
11240 printf("close failed (%s)\n", nt_errstr(status));
11241 return false;
11244 status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11245 if (!NT_STATUS_IS_OK(status)) {
11246 d_printf("cli_list failed: %s\n", nt_errstr(status));
11247 return false;
11250 mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11251 if (mangled_path == NULL) {
11252 return false;
11255 status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11256 if (!NT_STATUS_IS_OK(status)) {
11257 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11258 TALLOC_FREE(mangled_path);
11259 return false;
11261 TALLOC_FREE(mangled_path);
11262 cli_close(cli, fnum);
11264 cli_setatr(cli_posix, illegal_fname, 0, 0);
11265 cli_posix_unlink(cli_posix, illegal_fname);
11268 * Create a file with a long name and check that we got *no* short name.
11271 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11272 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11273 0, 0, &fnum, NULL);
11274 if (!NT_STATUS_IS_OK(status)) {
11275 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11276 return false;
11278 cli_close(cli, fnum);
11280 status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11281 if (!NT_STATUS_IS_OK(status)) {
11282 d_printf("cli_list failed\n");
11283 return false;
11286 cli_unlink(cli, fname, 0);
11287 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11289 if (!torture_close_connection(cli_posix)) {
11290 return false;
11293 if (!torture_close_connection(cli)) {
11294 return false;
11297 return true;
11300 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11302 size_t *to_pull = (size_t *)priv;
11303 size_t thistime = *to_pull;
11305 thistime = MIN(thistime, n);
11306 if (thistime == 0) {
11307 return 0;
11310 memset(buf, 0, thistime);
11311 *to_pull -= thistime;
11312 return thistime;
11315 static bool run_windows_write(int dummy)
11317 struct cli_state *cli1;
11318 uint16_t fnum;
11319 int i;
11320 bool ret = false;
11321 const char *fname = "\\writetest.txt";
11322 struct timeval start_time;
11323 double seconds;
11324 double kbytes;
11325 NTSTATUS status;
11327 printf("starting windows_write test\n");
11328 if (!torture_open_connection(&cli1, 0)) {
11329 return False;
11332 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11333 if (!NT_STATUS_IS_OK(status)) {
11334 printf("open failed (%s)\n", nt_errstr(status));
11335 return False;
11338 smbXcli_conn_set_sockopt(cli1->conn, sockops);
11340 start_time = timeval_current();
11342 for (i=0; i<torture_numops; i++) {
11343 uint8_t c = 0;
11344 off_t start = i * torture_blocksize;
11345 size_t to_pull = torture_blocksize - 1;
11347 status = cli_writeall(cli1, fnum, 0, &c,
11348 start + torture_blocksize - 1, 1, NULL);
11349 if (!NT_STATUS_IS_OK(status)) {
11350 printf("cli_write failed: %s\n", nt_errstr(status));
11351 goto fail;
11354 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11355 null_source, &to_pull);
11356 if (!NT_STATUS_IS_OK(status)) {
11357 printf("cli_push returned: %s\n", nt_errstr(status));
11358 goto fail;
11362 seconds = timeval_elapsed(&start_time);
11363 kbytes = (double)torture_blocksize * torture_numops;
11364 kbytes /= 1024;
11366 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11367 (double)seconds, (int)(kbytes/seconds));
11369 ret = true;
11370 fail:
11371 cli_close(cli1, fnum);
11372 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11373 torture_close_connection(cli1);
11374 return ret;
11377 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11379 size_t max_pdu = 0x1FFFF;
11381 if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11382 max_pdu = 0xFFFFFF;
11385 if (smb1cli_conn_signing_is_active(cli->conn)) {
11386 max_pdu = 0x1FFFF;
11389 if (smb1cli_conn_encryption_on(cli->conn)) {
11390 max_pdu = CLI_BUFFER_SIZE;
11393 if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11394 len_requested &= 0xFFFF;
11397 return MIN(len_requested,
11398 max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11401 static bool check_read_call(struct cli_state *cli,
11402 uint16_t fnum,
11403 uint8_t *buf,
11404 size_t len_requested)
11406 NTSTATUS status;
11407 struct tevent_req *subreq = NULL;
11408 ssize_t len_read = 0;
11409 size_t len_expected = 0;
11410 struct tevent_context *ev = NULL;
11412 ev = samba_tevent_context_init(talloc_tos());
11413 if (ev == NULL) {
11414 return false;
11417 subreq = cli_read_andx_send(talloc_tos(),
11419 cli,
11420 fnum,
11422 len_requested);
11424 if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11425 return false;
11428 status = cli_read_andx_recv(subreq, &len_read, &buf);
11429 if (!NT_STATUS_IS_OK(status)) {
11430 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11431 return false;
11434 TALLOC_FREE(subreq);
11435 TALLOC_FREE(ev);
11437 len_expected = calc_expected_return(cli, len_requested);
11439 if (len_expected > 0x10000 && len_read == 0x10000) {
11440 /* Windows servers only return a max of 0x10000,
11441 doesn't matter if you set CAP_LARGE_READX in
11442 the client sessionsetupX call or not. */
11443 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11444 (unsigned int)len_requested);
11445 } else if (len_read != len_expected) {
11446 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11447 (unsigned int)len_requested,
11448 (unsigned int)len_read,
11449 (unsigned int)len_expected);
11450 return false;
11451 } else {
11452 d_printf("Correct read reply.\n");
11455 return true;
11458 /* Test large readX variants. */
11459 static bool large_readx_tests(struct cli_state *cli,
11460 uint16_t fnum,
11461 uint8_t *buf)
11463 /* A read of 0xFFFF0001 should *always* return 1 byte. */
11464 if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11465 return false;
11467 /* A read of 0x10000 should return 0x10000 bytes. */
11468 if (check_read_call(cli, fnum, buf, 0x10000) == false) {
11469 return false;
11471 /* A read of 0x10000 should return 0x10001 bytes. */
11472 if (check_read_call(cli, fnum, buf, 0x10001) == false) {
11473 return false;
11475 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11476 the requested number of bytes. */
11477 if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11478 return false;
11480 /* A read of 1MB should return 1MB bytes (on Samba). */
11481 if (check_read_call(cli, fnum, buf, 0x100000) == false) {
11482 return false;
11485 if (check_read_call(cli, fnum, buf, 0x20001) == false) {
11486 return false;
11488 if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11489 return false;
11491 if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11492 return false;
11494 return true;
11497 static bool run_large_readx(int dummy)
11499 uint8_t *buf = NULL;
11500 struct cli_state *cli1 = NULL;
11501 struct cli_state *cli2 = NULL;
11502 bool correct = false;
11503 const char *fname = "\\large_readx.dat";
11504 NTSTATUS status;
11505 uint16_t fnum1 = UINT16_MAX;
11506 uint32_t normal_caps = 0;
11507 size_t file_size = 20*1024*1024;
11508 TALLOC_CTX *frame = talloc_stackframe();
11509 size_t i;
11510 struct {
11511 const char *name;
11512 enum smb_signing_setting signing_setting;
11513 enum protocol_types protocol;
11514 } runs[] = {
11516 .name = "NT1",
11517 .signing_setting = SMB_SIGNING_IF_REQUIRED,
11518 .protocol = PROTOCOL_NT1,
11520 .name = "NT1 - SIGNING_REQUIRED",
11521 .signing_setting = SMB_SIGNING_REQUIRED,
11522 .protocol = PROTOCOL_NT1,
11526 printf("starting large_readx test\n");
11528 if (!torture_open_connection(&cli1, 0)) {
11529 goto out;
11532 normal_caps = smb1cli_conn_capabilities(cli1->conn);
11534 if (!(normal_caps & CAP_LARGE_READX)) {
11535 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11536 (unsigned int)normal_caps);
11537 goto out;
11540 /* Create a file of size 4MB. */
11541 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11542 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11543 0, 0, &fnum1, NULL);
11545 if (!NT_STATUS_IS_OK(status)) {
11546 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11547 goto out;
11550 /* Write file_size bytes. */
11551 buf = talloc_zero_array(frame, uint8_t, file_size);
11552 if (buf == NULL) {
11553 goto out;
11556 status = cli_writeall(cli1,
11557 fnum1,
11559 buf,
11561 file_size,
11562 NULL);
11563 if (!NT_STATUS_IS_OK(status)) {
11564 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11565 goto out;
11568 status = cli_close(cli1, fnum1);
11569 if (!NT_STATUS_IS_OK(status)) {
11570 d_printf("cli_close failed: %s\n", nt_errstr(status));
11571 goto out;
11574 fnum1 = UINT16_MAX;
11576 for (i=0; i < ARRAY_SIZE(runs); i++) {
11577 enum smb_signing_setting saved_signing_setting = signing_state;
11578 uint16_t fnum2 = -1;
11580 if (do_encrypt &&
11581 (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11583 d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11584 continue;
11587 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11589 signing_state = runs[i].signing_setting;
11590 cli2 = open_nbt_connection();
11591 signing_state = saved_signing_setting;
11592 if (cli2 == NULL) {
11593 goto out;
11596 status = smbXcli_negprot(cli2->conn,
11597 cli2->timeout,
11598 runs[i].protocol,
11599 runs[i].protocol,
11600 NULL,
11601 NULL,
11602 NULL);
11603 if (!NT_STATUS_IS_OK(status)) {
11604 goto out;
11607 status = cli_session_setup_creds(cli2, torture_creds);
11608 if (!NT_STATUS_IS_OK(status)) {
11609 goto out;
11612 status = cli_tree_connect(cli2,
11613 share,
11614 "?????",
11615 password);
11616 if (!NT_STATUS_IS_OK(status)) {
11617 goto out;
11620 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11622 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11624 if (!(normal_caps & CAP_LARGE_READX)) {
11625 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11626 (unsigned int)normal_caps);
11627 goto out;
11630 if (do_encrypt) {
11631 if (force_cli_encryption(cli2, share) == false) {
11632 goto out;
11634 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11635 uint16_t major, minor;
11636 uint32_t caplow, caphigh;
11638 status = cli_unix_extensions_version(cli2,
11639 &major, &minor,
11640 &caplow, &caphigh);
11641 if (!NT_STATUS_IS_OK(status)) {
11642 goto out;
11646 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11647 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11648 0, 0, &fnum2, NULL);
11649 if (!NT_STATUS_IS_OK(status)) {
11650 d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11651 goto out;
11654 /* All reads must return less than file_size bytes. */
11655 if (!large_readx_tests(cli2, fnum2, buf)) {
11656 goto out;
11659 status = cli_close(cli2, fnum2);
11660 if (!NT_STATUS_IS_OK(status)) {
11661 d_printf("cli_close failed: %s\n", nt_errstr(status));
11662 goto out;
11664 fnum2 = -1;
11666 if (!torture_close_connection(cli2)) {
11667 goto out;
11669 cli2 = NULL;
11672 correct = true;
11673 printf("Success on large_readx test\n");
11675 out:
11677 if (cli2) {
11678 if (!torture_close_connection(cli2)) {
11679 correct = false;
11683 if (cli1) {
11684 if (fnum1 != UINT16_MAX) {
11685 status = cli_close(cli1, fnum1);
11686 if (!NT_STATUS_IS_OK(status)) {
11687 d_printf("cli_close failed: %s\n", nt_errstr(status));
11689 fnum1 = UINT16_MAX;
11692 status = cli_unlink(cli1, fname,
11693 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11694 if (!NT_STATUS_IS_OK(status)) {
11695 printf("unlink failed (%s)\n", nt_errstr(status));
11698 if (!torture_close_connection(cli1)) {
11699 correct = false;
11703 TALLOC_FREE(frame);
11705 printf("finished large_readx test\n");
11706 return correct;
11709 static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11710 const char *mask,
11711 void *private_data)
11713 uint32_t *p_attr = (uint32_t *)private_data;
11715 if (strequal(finfo->name, test_filename)) {
11716 *p_attr = finfo->attr;
11719 return NT_STATUS_OK;
11722 static bool run_msdfs_attribute(int dummy)
11724 static struct cli_state *cli;
11725 bool correct = false;
11726 uint32_t attr = 0;
11727 NTSTATUS status;
11729 printf("Starting MSDFS-ATTRIBUTE test\n");
11731 if (test_filename == NULL || test_filename[0] == '\0') {
11732 printf("MSDFS-ATTRIBUTE test "
11733 "needs -f filename-of-msdfs-link\n");
11734 return false;
11738 * NB. We use torture_open_connection_flags() not
11739 * torture_open_connection() as the latter forces
11740 * SMB1.
11742 if (!torture_open_connection_flags(&cli, 0, 0)) {
11743 return false;
11746 smbXcli_conn_set_sockopt(cli->conn, sockops);
11748 status = cli_list(cli,
11749 "*",
11750 FILE_ATTRIBUTE_DIRECTORY,
11751 msdfs_attribute_list_fn,
11752 &attr);
11754 if (!NT_STATUS_IS_OK(status)) {
11755 printf("cli_list failed with %s\n",
11756 nt_errstr(status));
11757 goto out;
11759 if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11760 printf("file %s should have "
11761 "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11762 test_filename,
11763 (unsigned int)attr);
11764 goto out;
11767 if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11768 printf("file %s should have "
11769 "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11770 test_filename,
11771 (unsigned int)attr);
11772 goto out;
11775 correct = true;
11777 out:
11779 torture_close_connection(cli);
11780 return correct;
11783 static bool run_cli_echo(int dummy)
11785 struct cli_state *cli;
11786 NTSTATUS status;
11788 printf("starting cli_echo test\n");
11789 if (!torture_open_connection(&cli, 0)) {
11790 return false;
11792 smbXcli_conn_set_sockopt(cli->conn, sockops);
11794 status = cli_echo(cli, 5, data_blob_const("hello", 5));
11796 d_printf("cli_echo returned %s\n", nt_errstr(status));
11798 torture_close_connection(cli);
11799 return NT_STATUS_IS_OK(status);
11802 static int splice_status(off_t written, void *priv)
11804 return true;
11807 static bool run_cli_splice(int dummy)
11809 uint8_t *buf = NULL;
11810 struct cli_state *cli1 = NULL;
11811 bool correct = false;
11812 const char *fname_src = "\\splice_src.dat";
11813 const char *fname_dst = "\\splice_dst.dat";
11814 NTSTATUS status;
11815 uint16_t fnum1 = UINT16_MAX;
11816 uint16_t fnum2 = UINT16_MAX;
11817 size_t file_size = 2*1024*1024;
11818 size_t splice_size = 1*1024*1024 + 713;
11819 uint8_t digest1[16], digest2[16];
11820 off_t written = 0;
11821 size_t nread = 0;
11822 TALLOC_CTX *frame = talloc_stackframe();
11824 printf("starting cli_splice test\n");
11826 if (!torture_open_connection(&cli1, 0)) {
11827 goto out;
11830 cli_unlink(cli1, fname_src,
11831 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11832 cli_unlink(cli1, fname_dst,
11833 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11835 /* Create a file */
11836 status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11837 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11838 0, 0, &fnum1, NULL);
11840 if (!NT_STATUS_IS_OK(status)) {
11841 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11842 goto out;
11845 /* Write file_size bytes - must be bigger than splice_size. */
11846 buf = talloc_zero_array(frame, uint8_t, file_size);
11847 if (buf == NULL) {
11848 d_printf("talloc_fail\n");
11849 goto out;
11852 /* Fill it with random numbers. */
11853 generate_random_buffer(buf, file_size);
11855 /* MD5 the first 1MB + 713 bytes. */
11856 gnutls_hash_fast(GNUTLS_DIG_MD5,
11857 buf,
11858 splice_size,
11859 digest1);
11861 status = cli_writeall(cli1,
11862 fnum1,
11864 buf,
11866 file_size,
11867 NULL);
11868 if (!NT_STATUS_IS_OK(status)) {
11869 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11870 goto out;
11873 status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11874 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11875 0, 0, &fnum2, NULL);
11877 if (!NT_STATUS_IS_OK(status)) {
11878 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11879 goto out;
11882 /* Now splice 1MB + 713 bytes. */
11883 status = cli_splice(cli1,
11884 cli1,
11885 fnum1,
11886 fnum2,
11887 splice_size,
11890 &written,
11891 splice_status,
11892 NULL);
11894 if (!NT_STATUS_IS_OK(status)) {
11895 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11896 goto out;
11899 /* Clear the old buffer. */
11900 memset(buf, '\0', file_size);
11902 /* Read the new file. */
11903 status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11904 if (!NT_STATUS_IS_OK(status)) {
11905 d_printf("cli_read failed: %s\n", nt_errstr(status));
11906 goto out;
11908 if (nread != splice_size) {
11909 d_printf("bad read of 0x%x, should be 0x%x\n",
11910 (unsigned int)nread,
11911 (unsigned int)splice_size);
11912 goto out;
11915 /* MD5 the first 1MB + 713 bytes. */
11916 gnutls_hash_fast(GNUTLS_DIG_MD5,
11917 buf,
11918 splice_size,
11919 digest2);
11921 /* Must be the same. */
11922 if (memcmp(digest1, digest2, 16) != 0) {
11923 d_printf("bad MD5 compare\n");
11924 goto out;
11927 correct = true;
11928 printf("Success on cli_splice test\n");
11930 out:
11932 if (cli1) {
11933 if (fnum1 != UINT16_MAX) {
11934 cli_close(cli1, fnum1);
11936 if (fnum2 != UINT16_MAX) {
11937 cli_close(cli1, fnum2);
11940 cli_unlink(cli1, fname_src,
11941 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11942 cli_unlink(cli1, fname_dst,
11943 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11945 if (!torture_close_connection(cli1)) {
11946 correct = false;
11950 TALLOC_FREE(frame);
11951 return correct;
11954 static bool run_uid_regression_test(int dummy)
11956 static struct cli_state *cli;
11957 int16_t old_vuid;
11958 int32_t old_cnum;
11959 bool correct = True;
11960 struct smbXcli_tcon *tcon_copy = NULL;
11961 NTSTATUS status;
11963 printf("starting uid regression test\n");
11965 if (!torture_open_connection(&cli, 0)) {
11966 return False;
11969 smbXcli_conn_set_sockopt(cli->conn, sockops);
11971 /* Ok - now save then logoff our current user. */
11972 old_vuid = cli_state_get_uid(cli);
11974 status = cli_ulogoff(cli);
11975 if (!NT_STATUS_IS_OK(status)) {
11976 d_printf("(%s) cli_ulogoff failed: %s\n",
11977 __location__, nt_errstr(status));
11978 correct = false;
11979 goto out;
11982 cli_state_set_uid(cli, old_vuid);
11984 /* Try an operation. */
11985 status = cli_mkdir(cli, "\\uid_reg_test");
11986 if (NT_STATUS_IS_OK(status)) {
11987 d_printf("(%s) cli_mkdir succeeded\n",
11988 __location__);
11989 correct = false;
11990 goto out;
11991 } else {
11992 /* Should be bad uid. */
11993 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11994 NT_STATUS_USER_SESSION_DELETED)) {
11995 correct = false;
11996 goto out;
12000 old_cnum = cli_state_get_tid(cli);
12002 * This is an SMB1-only test.
12003 * Copy the tcon, not "save/restore".
12005 * In SMB1 the cli_tdis() below frees
12006 * cli->smb1.tcon so we need a copy
12007 * of the struct to put back for the
12008 * second tdis call with invalid vuid.
12010 * This is a test-only hack. Real client code
12011 * uses cli_state_save_tcon_share()/cli_state_restore_tcon_share().
12013 tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
12014 if (tcon_copy == NULL) {
12015 correct = false;
12016 goto out;
12019 /* Now try a SMBtdis with the invalid vuid set to zero. */
12020 cli_state_set_uid(cli, 0);
12022 /* This should succeed. */
12023 status = cli_tdis(cli);
12025 if (NT_STATUS_IS_OK(status)) {
12026 d_printf("First tdis with invalid vuid should succeed.\n");
12027 } else {
12028 d_printf("First tdis failed (%s)\n", nt_errstr(status));
12029 correct = false;
12030 cli->smb1.tcon = tcon_copy;
12031 goto out;
12034 cli->smb1.tcon = tcon_copy;
12035 cli_state_set_uid(cli, old_vuid);
12036 cli_state_set_tid(cli, old_cnum);
12038 /* This should fail. */
12039 status = cli_tdis(cli);
12040 if (NT_STATUS_IS_OK(status)) {
12041 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
12042 correct = false;
12043 goto out;
12044 } else {
12045 /* Should be bad tid. */
12046 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
12047 NT_STATUS_NETWORK_NAME_DELETED)) {
12048 correct = false;
12049 goto out;
12053 cli_rmdir(cli, "\\uid_reg_test");
12055 out:
12057 cli_shutdown(cli);
12058 return correct;
12062 static const char *illegal_chars = "*\\/?<>|\":";
12063 static char force_shortname_chars[] = " +,.[];=\177";
12065 static NTSTATUS shortname_del_fn(struct file_info *finfo,
12066 const char *mask, void *state)
12068 struct cli_state *pcli = (struct cli_state *)state;
12069 fstring fname;
12070 NTSTATUS status = NT_STATUS_OK;
12072 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
12074 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
12075 return NT_STATUS_OK;
12077 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
12078 status = cli_rmdir(pcli, fname);
12079 if (!NT_STATUS_IS_OK(status)) {
12080 printf("del_fn: failed to rmdir %s\n,", fname );
12082 } else {
12083 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12084 if (!NT_STATUS_IS_OK(status)) {
12085 printf("del_fn: failed to unlink %s\n,", fname );
12088 return status;
12091 struct sn_state {
12092 int matched;
12093 int i;
12094 bool val;
12097 static NTSTATUS shortname_list_fn(struct file_info *finfo,
12098 const char *name, void *state)
12100 struct sn_state *s = (struct sn_state *)state;
12101 int i = s->i;
12103 #if 0
12104 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
12105 i, finfo->name, finfo->short_name);
12106 #endif
12108 if (strchr(force_shortname_chars, i)) {
12109 if (!finfo->short_name) {
12110 /* Shortname not created when it should be. */
12111 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
12112 __location__, finfo->name, i);
12113 s->val = true;
12115 } else if (finfo->short_name){
12116 /* Shortname created when it should not be. */
12117 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
12118 __location__, finfo->short_name, finfo->name);
12119 s->val = true;
12121 s->matched += 1;
12122 return NT_STATUS_OK;
12125 static bool run_shortname_test(int dummy)
12127 static struct cli_state *cli;
12128 bool correct = True;
12129 int i;
12130 struct sn_state s;
12131 char fname[40];
12132 NTSTATUS status;
12134 printf("starting shortname test\n");
12136 if (!torture_open_connection(&cli, 0)) {
12137 return False;
12140 smbXcli_conn_set_sockopt(cli->conn, sockops);
12142 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12143 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12144 cli_rmdir(cli, "\\shortname");
12146 status = cli_mkdir(cli, "\\shortname");
12147 if (!NT_STATUS_IS_OK(status)) {
12148 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
12149 __location__, nt_errstr(status));
12150 correct = false;
12151 goto out;
12154 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
12155 correct = false;
12156 goto out;
12158 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
12159 correct = false;
12160 goto out;
12163 s.val = false;
12165 for (i = 32; i < 128; i++) {
12166 uint16_t fnum = (uint16_t)-1;
12168 s.i = i;
12170 if (strchr(illegal_chars, i)) {
12171 continue;
12173 fname[15] = i;
12175 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12176 FILE_SHARE_READ|FILE_SHARE_WRITE,
12177 FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12178 if (!NT_STATUS_IS_OK(status)) {
12179 d_printf("(%s) cli_nt_create of %s failed: %s\n",
12180 __location__, fname, nt_errstr(status));
12181 correct = false;
12182 goto out;
12184 cli_close(cli, fnum);
12186 s.matched = 0;
12187 status = cli_list(cli, "\\shortname\\test*.*", 0,
12188 shortname_list_fn, &s);
12189 if (s.matched != 1) {
12190 d_printf("(%s) failed to list %s: %s\n",
12191 __location__, fname, nt_errstr(status));
12192 correct = false;
12193 goto out;
12196 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12197 if (!NT_STATUS_IS_OK(status)) {
12198 d_printf("(%s) failed to delete %s: %s\n",
12199 __location__, fname, nt_errstr(status));
12200 correct = false;
12201 goto out;
12204 if (s.val) {
12205 correct = false;
12206 goto out;
12210 out:
12212 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12213 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12214 cli_rmdir(cli, "\\shortname");
12215 torture_close_connection(cli);
12216 return correct;
12219 TLDAPRC callback_code;
12221 static void pagedsearch_cb(struct tevent_req *req)
12223 TLDAPRC rc;
12224 struct tldap_message *msg;
12225 char *dn;
12227 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12228 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12229 d_printf("tldap_search_paged_recv failed: %s\n",
12230 tldap_rc2string(rc));
12231 callback_code = rc;
12232 return;
12234 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12235 TALLOC_FREE(msg);
12236 return;
12238 if (!tldap_entry_dn(msg, &dn)) {
12239 d_printf("tldap_entry_dn failed\n");
12240 return;
12242 d_printf("%s\n", dn);
12243 TALLOC_FREE(msg);
12246 enum tldap_extended_val {
12247 EXTENDED_ZERO = 0,
12248 EXTENDED_ONE = 1,
12249 EXTENDED_NONE = 2,
12253 * Construct an extended dn control with either no value, 0 or 1
12255 * No value and 0 are equivalent (non-hyphenated GUID)
12256 * 1 has the hyphenated GUID
12258 static struct tldap_control *
12259 tldap_build_extended_control(enum tldap_extended_val val)
12261 struct tldap_control empty_control;
12262 struct asn1_data *data;
12264 ZERO_STRUCT(empty_control);
12266 if (val != EXTENDED_NONE) {
12267 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12269 if (!data) {
12270 return NULL;
12273 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12274 return NULL;
12277 if (!asn1_write_Integer(data, (int)val)) {
12278 return NULL;
12281 if (!asn1_pop_tag(data)) {
12282 return NULL;
12285 if (!asn1_blob(data, &empty_control.value)) {
12286 return NULL;
12290 empty_control.oid = "1.2.840.113556.1.4.529";
12291 empty_control.critical = true;
12293 return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12297 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12298 enum tldap_extended_val control_val)
12300 struct tldap_control *control = tldap_build_extended_control(control_val);
12301 char *dn = NULL;
12302 struct tldap_message **msg;
12303 TLDAPRC rc;
12305 rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12306 "(objectClass=*)", NULL, 0, 0,
12307 control, 1, NULL,
12308 0, 0, 0, 0, talloc_tos(), &msg);
12309 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12310 d_printf("tldap_search for domain DN failed: %s\n",
12311 tldap_errstr(talloc_tos(), ld, rc));
12312 return false;
12315 if (!tldap_entry_dn(msg[0], &dn)) {
12316 d_printf("tldap_search domain DN fetch failed: %s\n",
12317 tldap_errstr(talloc_tos(), ld, rc));
12318 return false;
12321 d_printf("%s\n", dn);
12323 uint32_t time_low;
12324 uint32_t time_mid, time_hi_and_version;
12325 uint32_t clock_seq[2];
12326 uint32_t node[6];
12327 char next;
12329 switch (control_val) {
12330 case EXTENDED_NONE:
12331 case EXTENDED_ZERO:
12333 * When reading GUIDs with hyphens, scanf will treat
12334 * hyphen as a hex character (and counts as part of the
12335 * width). This creates leftover GUID string which we
12336 * check will for with 'next' and closing '>'.
12338 if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12339 &time_low, &time_mid,
12340 &time_hi_and_version, &clock_seq[0],
12341 &clock_seq[1], &node[0], &node[1],
12342 &node[2], &node[3], &node[4],
12343 &node[5], &next)) {
12344 /* This GUID is good */
12345 } else {
12346 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12347 return false;
12350 break;
12351 case EXTENDED_ONE:
12352 if (12 == sscanf(dn,
12353 "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12354 &time_low, &time_mid,
12355 &time_hi_and_version, &clock_seq[0],
12356 &clock_seq[1], &node[0], &node[1],
12357 &node[2], &node[3], &node[4],
12358 &node[5], &next)) {
12359 /* This GUID is good */
12360 } else {
12361 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12362 return false;
12365 break;
12366 default:
12367 return false;
12371 return true;
12374 static bool run_tldap(int dummy)
12376 struct tldap_context *ld;
12377 int fd;
12378 TLDAPRC rc;
12379 NTSTATUS status;
12380 struct sockaddr_storage addr;
12381 struct tevent_context *ev;
12382 struct tevent_req *req;
12383 char *basedn;
12384 const char *filter;
12385 struct loadparm_context *lp_ctx = NULL;
12386 int tcp_port = 389;
12387 bool use_tls = false;
12388 bool use_starttls = false;
12389 int wrap_flags = -1;
12390 uint32_t gensec_features = 0;
12392 lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
12394 wrap_flags = lpcfg_client_ldap_sasl_wrapping(lp_ctx);
12396 if (wrap_flags & ADS_AUTH_SASL_LDAPS) {
12397 use_tls = true;
12398 tcp_port = 636;
12399 } else if (wrap_flags & ADS_AUTH_SASL_STARTTLS) {
12400 use_tls = true;
12401 use_starttls = true;
12403 if (wrap_flags & ADS_AUTH_SASL_SEAL) {
12404 gensec_features |= GENSEC_FEATURE_SEAL;
12406 if (wrap_flags & ADS_AUTH_SASL_SIGN) {
12407 gensec_features |= GENSEC_FEATURE_SIGN;
12410 if (gensec_features != 0) {
12411 gensec_features |= GENSEC_FEATURE_LDAP_STYLE;
12414 if (!resolve_name(host, &addr, 0, false)) {
12415 d_printf("could not find host %s\n", host);
12416 return false;
12418 status = open_socket_out(&addr, tcp_port, 9999, &fd);
12419 if (!NT_STATUS_IS_OK(status)) {
12420 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12421 return false;
12424 ld = tldap_context_create(talloc_tos(), fd);
12425 if (ld == NULL) {
12426 close(fd);
12427 d_printf("tldap_context_create failed\n");
12428 return false;
12431 if (use_tls && !tldap_has_tls_tstream(ld)) {
12432 struct tstream_tls_params *tls_params = NULL;
12434 if (use_starttls) {
12435 rc = tldap_extended(ld,
12436 LDB_EXTENDED_START_TLS_OID,
12437 NULL,
12438 NULL,
12440 NULL,
12442 NULL,
12443 NULL,
12444 NULL);
12445 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12446 DBG_ERR("tldap_extended(%s) failed: %s\n",
12447 LDB_EXTENDED_START_TLS_OID,
12448 tldap_errstr(talloc_tos(), ld, rc));
12449 return false;
12453 status = tstream_tls_params_client_lpcfg(talloc_tos(),
12454 lp_ctx,
12455 host,
12456 &tls_params);
12457 if (!NT_STATUS_IS_OK(status)) {
12458 DBG_ERR("tstream_tls_params_client_lpcfg failed: %s\n",
12459 nt_errstr(status));
12460 return false;
12463 rc = tldap_tls_connect(ld, tls_params);
12464 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12465 DBG_ERR("tldap_tls_connect(%s) failed: %s\n",
12466 host, tldap_errstr(talloc_tos(), ld, rc));
12467 return false;
12471 rc = tldap_fetch_rootdse(ld);
12472 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12473 d_printf("tldap_fetch_rootdse failed: %s\n",
12474 tldap_errstr(talloc_tos(), ld, rc));
12475 return false;
12478 basedn = tldap_talloc_single_attribute(
12479 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12480 if (basedn == NULL) {
12481 d_printf("no defaultNamingContext\n");
12482 return false;
12484 d_printf("defaultNamingContext: %s\n", basedn);
12486 ev = samba_tevent_context_init(talloc_tos());
12487 if (ev == NULL) {
12488 d_printf("tevent_context_init failed\n");
12489 return false;
12492 rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12493 lp_ctx, gensec_features);
12494 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12495 d_printf("tldap_gensec_bind failed\n");
12496 return false;
12499 callback_code = TLDAP_SUCCESS;
12501 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12502 TLDAP_SCOPE_SUB, "(objectclass=*)",
12503 NULL, 0, 0,
12504 NULL, 0, NULL, 0, 0, 0, 0, 5);
12505 if (req == NULL) {
12506 d_printf("tldap_search_paged_send failed\n");
12507 return false;
12509 tevent_req_set_callback(req, pagedsearch_cb, NULL);
12511 tevent_req_poll(req, ev);
12513 TALLOC_FREE(req);
12515 rc = callback_code;
12517 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12518 d_printf("tldap_search with paging failed: %s\n",
12519 tldap_errstr(talloc_tos(), ld, rc));
12520 return false;
12523 /* test search filters against rootDSE */
12524 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12525 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12527 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12528 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12529 talloc_tos(), NULL);
12530 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12531 d_printf("tldap_search with complex filter failed: %s\n",
12532 tldap_errstr(talloc_tos(), ld, rc));
12533 return false;
12537 * Tests to check for regression of:
12539 * https://bugzilla.samba.org/show_bug.cgi?id=14029
12541 * TLDAP used here to pick apart the original string DN (with GUID)
12543 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12544 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12545 tldap_errstr(talloc_tos(), ld, rc));
12546 return false;
12548 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12549 d_printf("tldap_search with extended dn (0) failed: %s\n",
12550 tldap_errstr(talloc_tos(), ld, rc));
12551 return false;
12553 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12554 d_printf("tldap_search with extended dn (1) failed: %s\n",
12555 tldap_errstr(talloc_tos(), ld, rc));
12556 return false;
12559 TALLOC_FREE(ld);
12560 return true;
12563 /* Torture test to ensure no regression of :
12564 https://bugzilla.samba.org/show_bug.cgi?id=7084
12567 static bool run_dir_createtime(int dummy)
12569 struct cli_state *cli;
12570 const char *dname = "\\testdir_createtime";
12571 const char *fname = "\\testdir_createtime\\testfile";
12572 NTSTATUS status;
12573 struct timespec create_time;
12574 struct timespec create_time1;
12575 uint16_t fnum;
12576 bool ret = false;
12577 uint64_t ino;
12579 if (!torture_open_connection(&cli, 0)) {
12580 return false;
12583 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12584 /* Ensure ino is zero, SMB2 gets a real one. */
12585 ino = 0;
12586 } else {
12587 /* Ensure ino is -1, SMB1 never gets a real one. */
12588 ino = (uint64_t)-1;
12591 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12592 cli_rmdir(cli, dname);
12594 status = cli_mkdir(cli, dname);
12595 if (!NT_STATUS_IS_OK(status)) {
12596 printf("mkdir failed: %s\n", nt_errstr(status));
12597 goto out;
12600 status = cli_qpathinfo2(cli,
12601 dname,
12602 &create_time,
12603 NULL,
12604 NULL,
12605 NULL,
12606 NULL,
12607 NULL,
12608 &ino,
12609 NULL);
12610 if (!NT_STATUS_IS_OK(status)) {
12611 printf("cli_qpathinfo2 returned %s\n",
12612 nt_errstr(status));
12613 goto out;
12616 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12617 /* SMB2 should always return an inode. */
12618 if (ino == 0) {
12619 printf("SMB2 bad inode (0)\n");
12620 goto out;
12622 } else {
12623 /* SMB1 must always return zero here. */
12624 if (ino != 0) {
12625 printf("SMB1 bad inode (!0)\n");
12626 goto out;
12630 /* Sleep 3 seconds, then create a file. */
12631 sleep(3);
12633 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12634 DENY_NONE, &fnum);
12635 if (!NT_STATUS_IS_OK(status)) {
12636 printf("cli_openx failed: %s\n", nt_errstr(status));
12637 goto out;
12640 status = cli_qpathinfo2(cli,
12641 dname,
12642 &create_time1,
12643 NULL,
12644 NULL,
12645 NULL,
12646 NULL,
12647 NULL,
12648 NULL,
12649 NULL);
12650 if (!NT_STATUS_IS_OK(status)) {
12651 printf("cli_qpathinfo2 (2) returned %s\n",
12652 nt_errstr(status));
12653 goto out;
12656 if (timespec_compare(&create_time1, &create_time)) {
12657 printf("run_dir_createtime: create time was updated (error)\n");
12658 } else {
12659 printf("run_dir_createtime: create time was not updated (correct)\n");
12660 ret = true;
12663 out:
12665 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12666 cli_rmdir(cli, dname);
12667 if (!torture_close_connection(cli)) {
12668 ret = false;
12670 return ret;
12674 static bool run_streamerror(int dummy)
12676 struct cli_state *cli;
12677 const char *dname = "\\testdir_streamerror";
12678 const char *streamname =
12679 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12680 NTSTATUS status;
12681 time_t change_time, access_time, write_time;
12682 off_t size;
12683 uint16_t fnum;
12684 uint32_t attr;
12685 bool ret = true;
12687 if (!torture_open_connection(&cli, 0)) {
12688 return false;
12691 torture_deltree(cli, dname);
12693 status = cli_mkdir(cli, dname);
12694 if (!NT_STATUS_IS_OK(status)) {
12695 printf("mkdir failed: %s\n", nt_errstr(status));
12696 return false;
12699 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12700 &write_time, &size, &attr);
12701 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12702 printf("pathinfo returned %s, expected "
12703 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12704 nt_errstr(status));
12705 ret = false;
12708 status = cli_ntcreate(cli, streamname, 0x16,
12709 FILE_READ_DATA|FILE_READ_EA|
12710 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12711 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12712 FILE_OPEN, 0, 0, &fnum, NULL);
12714 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12715 printf("ntcreate returned %s, expected "
12716 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12717 nt_errstr(status));
12718 ret = false;
12722 cli_rmdir(cli, dname);
12723 return ret;
12726 struct pidtest_state {
12727 bool success;
12728 uint16_t vwv[1];
12729 DATA_BLOB data;
12732 static void pid_echo_done(struct tevent_req *subreq);
12734 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12735 struct tevent_context *ev,
12736 struct cli_state *cli)
12738 struct tevent_req *req, *subreq;
12739 struct pidtest_state *state;
12741 req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12742 if (req == NULL) {
12743 return NULL;
12746 SSVAL(state->vwv, 0, 1);
12747 state->data = data_blob_const("hello", 5);
12749 subreq = smb1cli_req_send(state,
12751 cli->conn,
12752 SMBecho,
12753 0, 0, /* *_flags */
12754 0, 0, /* *_flags2 */
12755 cli->timeout,
12756 0xDEADBEEF, /* pid */
12757 NULL, /* tcon */
12758 NULL, /* session */
12759 ARRAY_SIZE(state->vwv), state->vwv,
12760 state->data.length, state->data.data);
12762 if (tevent_req_nomem(subreq, req)) {
12763 return tevent_req_post(req, ev);
12765 tevent_req_set_callback(subreq, pid_echo_done, req);
12766 return req;
12769 static void pid_echo_done(struct tevent_req *subreq)
12771 struct tevent_req *req = tevent_req_callback_data(
12772 subreq, struct tevent_req);
12773 struct pidtest_state *state = tevent_req_data(
12774 req, struct pidtest_state);
12775 NTSTATUS status;
12776 uint32_t num_bytes;
12777 uint8_t *bytes = NULL;
12778 struct iovec *recv_iov = NULL;
12779 uint8_t *phdr = NULL;
12780 uint16_t pidlow = 0;
12781 uint16_t pidhigh = 0;
12782 struct smb1cli_req_expected_response expected[] = {
12784 .status = NT_STATUS_OK,
12785 .wct = 1,
12789 status = smb1cli_req_recv(subreq, state,
12790 &recv_iov,
12791 &phdr,
12792 NULL, /* pwct */
12793 NULL, /* pvwv */
12794 NULL, /* pvwv_offset */
12795 &num_bytes,
12796 &bytes,
12797 NULL, /* pbytes_offset */
12798 NULL, /* pinbuf */
12799 expected, ARRAY_SIZE(expected));
12801 TALLOC_FREE(subreq);
12803 if (!NT_STATUS_IS_OK(status)) {
12804 tevent_req_nterror(req, status);
12805 return;
12808 if (num_bytes != state->data.length) {
12809 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12810 return;
12813 if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12814 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12815 return;
12818 /* Check pid low/high == DEADBEEF */
12819 pidlow = SVAL(phdr, HDR_PID);
12820 if (pidlow != 0xBEEF){
12821 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12822 (unsigned int)pidlow);
12823 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12824 return;
12826 pidhigh = SVAL(phdr, HDR_PIDHIGH);
12827 if (pidhigh != 0xDEAD){
12828 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12829 (unsigned int)pidhigh);
12830 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12831 return;
12834 tevent_req_done(req);
12837 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12839 return tevent_req_simple_recv_ntstatus(req);
12842 static bool run_pidhigh(int dummy)
12844 bool success = false;
12845 struct cli_state *cli = NULL;
12846 NTSTATUS status;
12847 struct tevent_context *ev = NULL;
12848 struct tevent_req *req = NULL;
12849 TALLOC_CTX *frame = talloc_stackframe();
12851 printf("starting pid high test\n");
12852 if (!torture_open_connection(&cli, 0)) {
12853 return false;
12855 smbXcli_conn_set_sockopt(cli->conn, sockops);
12857 ev = samba_tevent_context_init(frame);
12858 if (ev == NULL) {
12859 goto fail;
12862 req = pid_echo_send(frame, ev, cli);
12863 if (req == NULL) {
12864 goto fail;
12867 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12868 goto fail;
12871 status = pid_echo_recv(req);
12872 if (NT_STATUS_IS_OK(status)) {
12873 printf("pid high test ok\n");
12874 success = true;
12877 fail:
12879 TALLOC_FREE(frame);
12880 torture_close_connection(cli);
12881 return success;
12885 Test Windows open on a bad POSIX symlink.
12887 static bool run_symlink_open_test(int dummy)
12889 static struct cli_state *cli;
12890 const char *fname = "non_existant_file";
12891 const char *sname = "dangling_symlink";
12892 uint16_t fnum = (uint16_t)-1;
12893 bool correct = false;
12894 NTSTATUS status;
12895 TALLOC_CTX *frame = NULL;
12897 frame = talloc_stackframe();
12899 printf("Starting Windows bad symlink open test\n");
12901 if (!torture_open_connection(&cli, 0)) {
12902 TALLOC_FREE(frame);
12903 return false;
12906 smbXcli_conn_set_sockopt(cli->conn, sockops);
12908 status = torture_setup_unix_extensions(cli);
12909 if (!NT_STATUS_IS_OK(status)) {
12910 TALLOC_FREE(frame);
12911 return false;
12914 /* Ensure nothing exists. */
12915 cli_setatr(cli, fname, 0, 0);
12916 cli_posix_unlink(cli, fname);
12917 cli_setatr(cli, sname, 0, 0);
12918 cli_posix_unlink(cli, sname);
12920 /* Create a symlink pointing nowhere. */
12921 status = cli_posix_symlink(cli, fname, sname);
12922 if (!NT_STATUS_IS_OK(status)) {
12923 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12924 sname,
12925 fname,
12926 nt_errstr(status));
12927 goto out;
12930 /* Now ensure that a Windows open doesn't hang. */
12931 status = cli_ntcreate(cli,
12932 sname,
12934 FILE_READ_DATA|FILE_WRITE_DATA,
12936 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12937 FILE_OPEN_IF,
12938 0x0,
12939 0x0,
12940 &fnum,
12941 NULL);
12944 * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12945 * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12946 * we use O_NOFOLLOW on the server or not.
12948 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12949 NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12951 correct = true;
12952 } else {
12953 printf("cli_ntcreate of %s returned %s - should return"
12954 " either (%s) or (%s)\n",
12955 sname,
12956 nt_errstr(status),
12957 nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12958 nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12959 goto out;
12962 correct = true;
12964 out:
12966 if (fnum != (uint16_t)-1) {
12967 cli_close(cli, fnum);
12968 fnum = (uint16_t)-1;
12971 cli_setatr(cli, sname, 0, 0);
12972 cli_posix_unlink(cli, sname);
12973 cli_setatr(cli, fname, 0, 0);
12974 cli_posix_unlink(cli, fname);
12976 if (!torture_close_connection(cli)) {
12977 correct = false;
12980 TALLOC_FREE(frame);
12981 return correct;
12984 static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12985 const char *name,
12986 void *state)
12988 char **mangled_name_return = (char **)state;
12989 bool is_mangled = strchr(finfo->name, '~');
12991 if (is_mangled) {
12992 *mangled_name_return = talloc_strdup(NULL, finfo->name);
12993 if (*mangled_name_return == NULL) {
12994 return NT_STATUS_NO_MEMORY;
12997 return NT_STATUS_OK;
13000 static bool run_smb1_wild_mangle_unlink_test(int dummy)
13002 static struct cli_state *cli_posix = NULL;
13003 static struct cli_state *cli = NULL;
13004 uint16_t fnum = (uint16_t)-1;
13005 bool correct = false;
13006 const char *dname = "smb1_wild_mangle_unlink";
13007 const char *aname = "smb1_wild_mangle_unlink/a";
13008 const char *star_name = "smb1_wild_mangle_unlink/*";
13009 char *windows_unlink_name = NULL;
13010 char *mangled_name = NULL;
13011 NTSTATUS status;
13013 printf("Starting SMB1 wild mangle unlink test\n");
13015 /* Open a Windows connection. */
13016 if (!torture_open_connection(&cli, 0)) {
13017 return false;
13020 smbXcli_conn_set_sockopt(cli->conn, sockops);
13022 /* Open a POSIX connection. */
13023 if (!torture_open_connection(&cli_posix, 0)) {
13024 goto out;
13027 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
13029 status = torture_setup_unix_extensions(cli_posix);
13030 if (!NT_STATUS_IS_OK(status)) {
13031 printf("server doesn't support POSIX\n");
13032 goto out;
13035 /* Start fresh. */
13036 torture_deltree(cli, dname);
13039 * Create two files - 'a' and '*'.
13040 * We need POSIX extensions for this as '*'
13041 * is not a valid Windows name.
13044 status = cli_mkdir(cli, dname);
13045 if (!NT_STATUS_IS_OK(status)) {
13046 printf("cli_mkdir of %s returned %s\n",
13047 dname,
13048 nt_errstr(status));
13049 goto out;
13052 status = cli_posix_open(cli_posix,
13053 aname,
13054 O_RDWR|O_CREAT|O_EXCL,
13055 0660,
13056 &fnum);
13057 if (!NT_STATUS_IS_OK(status)) {
13058 printf("cli_posix_open (create) of %s returned %s\n",
13059 aname,
13060 nt_errstr(status));
13061 goto out;
13063 status = cli_close(cli_posix, fnum);
13064 if (!NT_STATUS_IS_OK(status)) {
13065 goto out;
13067 status = cli_posix_open(cli_posix,
13068 star_name,
13069 O_RDWR|O_CREAT|O_EXCL,
13070 0660,
13071 &fnum);
13072 if (!NT_STATUS_IS_OK(status)) {
13073 printf("cli_posix_open (create) of %s returned %s\n",
13074 star_name,
13075 nt_errstr(status));
13076 goto out;
13078 status = cli_close(cli_posix, fnum);
13079 if (!NT_STATUS_IS_OK(status)) {
13080 goto out;
13083 status = cli_list(cli,
13084 star_name,
13086 smb1_wild_mangle_list_fn,
13087 &mangled_name);
13088 if (!NT_STATUS_IS_OK(status)) {
13089 printf("cli_list of %s returned %s\n",
13090 star_name,
13091 nt_errstr(status));
13092 goto out;
13095 if (mangled_name == NULL) {
13096 goto out;
13099 printf("mangled_name = %s\n",
13100 mangled_name);
13103 * Try a Windows unlink with the mangled name.
13104 * This should *NOT* unlink the 'a' name.
13107 windows_unlink_name = talloc_asprintf(cli_posix,
13108 "%s\\%s",
13109 dname,
13110 mangled_name);
13112 status = cli_unlink(cli, windows_unlink_name, 0);
13113 if (!NT_STATUS_IS_OK(status)) {
13114 printf("cli_unlink of %s returned %s\n",
13115 windows_unlink_name,
13116 nt_errstr(status));
13117 goto out;
13120 /* Does 'a' still exist ? */
13121 status = cli_posix_open(cli_posix,
13122 aname,
13123 O_RDONLY,
13125 &fnum);
13126 if (!NT_STATUS_IS_OK(status)) {
13127 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13128 aname,
13129 nt_errstr(status));
13130 goto out;
13133 status = cli_close(cli_posix, fnum);
13134 if (!NT_STATUS_IS_OK(status)) {
13135 goto out;
13138 correct = true;
13140 out:
13142 TALLOC_FREE(windows_unlink_name);
13143 TALLOC_FREE(mangled_name);
13145 if (cli != NULL) {
13146 torture_deltree(cli, dname);
13147 torture_close_connection(cli);
13150 if (cli_posix != NULL) {
13151 torture_close_connection(cli_posix);
13154 return correct;
13157 static bool run_smb1_wild_mangle_rename_test(int dummy)
13159 static struct cli_state *cli_posix = NULL;
13160 static struct cli_state *cli = NULL;
13161 uint16_t fnum = (uint16_t)-1;
13162 bool correct = false;
13163 const char *dname = "smb1_wild_mangle_rename";
13164 const char *fooname = "smb1_wild_mangle_rename/foo";
13165 const char *foostar_name = "smb1_wild_mangle_rename/fo*";
13166 const char *wild_name = "smb1_wild_mangle_rename/*";
13167 char *windows_rename_src = NULL;
13168 const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
13169 char *mangled_name = NULL;
13170 NTSTATUS status;
13172 printf("Starting SMB1 wild mangle rename test\n");
13174 if (!torture_open_connection(&cli_posix, 0)) {
13175 return false;
13178 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
13180 status = torture_setup_unix_extensions(cli_posix);
13181 if (!NT_STATUS_IS_OK(status)) {
13182 printf("server doesn't support POSIX\n");
13183 return false;
13186 /* Open a Windows connection. */
13187 if (!torture_open_connection(&cli, 0)) {
13188 goto out;
13191 smbXcli_conn_set_sockopt(cli->conn, sockops);
13193 /* Ensure we start from fresh. */
13194 torture_deltree(cli, dname);
13197 * Create two files - 'foo' and 'fo*'.
13198 * We need POSIX extensions for this as 'fo*'
13199 * is not a valid Windows name.
13202 status = cli_posix_mkdir(cli_posix, dname, 0770);
13203 if (!NT_STATUS_IS_OK(status)) {
13204 printf("cli_posix_mkdir of %s returned %s\n",
13205 dname,
13206 nt_errstr(status));
13207 goto out;
13210 status = cli_posix_open(cli_posix,
13211 fooname,
13212 O_RDWR|O_CREAT|O_EXCL,
13213 0660,
13214 &fnum);
13215 if (!NT_STATUS_IS_OK(status)) {
13216 printf("cli_posix_open (create) of %s returned %s\n",
13217 fooname,
13218 nt_errstr(status));
13219 goto out;
13221 status = cli_close(cli_posix, fnum);
13222 if (!NT_STATUS_IS_OK(status)) {
13223 goto out;
13225 status = cli_posix_open(cli_posix,
13226 foostar_name,
13227 O_RDWR|O_CREAT|O_EXCL,
13228 0660,
13229 &fnum);
13230 if (!NT_STATUS_IS_OK(status)) {
13231 printf("cli_posix_open (create) of %s returned %s\n",
13232 foostar_name,
13233 nt_errstr(status));
13234 goto out;
13236 status = cli_close(cli_posix, fnum);
13237 if (!NT_STATUS_IS_OK(status)) {
13238 goto out;
13242 * Get the mangled name. We can re-use the
13243 * previous smb1_wild_mangle_list_fn for this.
13246 status = cli_list(cli,
13247 wild_name,
13249 smb1_wild_mangle_list_fn,
13250 &mangled_name);
13251 if (!NT_STATUS_IS_OK(status)) {
13252 printf("cli_list of %s returned %s\n",
13253 wild_name,
13254 nt_errstr(status));
13255 goto out;
13258 if (mangled_name == NULL) {
13259 goto out;
13262 printf("mangled_name = %s\n",
13263 mangled_name);
13266 * Try a Windows rename with the mangled name.
13267 * This should *NOT* rename the 'foo' name.
13270 windows_rename_src = talloc_asprintf(cli_posix,
13271 "%s\\%s",
13272 dname,
13273 mangled_name);
13275 status = cli_rename(cli,
13276 windows_rename_src,
13277 windows_rename_dst,
13278 false);
13279 if (!NT_STATUS_IS_OK(status)) {
13280 printf("cli_rename of %s -> %s returned %s\n",
13281 windows_rename_src,
13282 windows_rename_dst,
13283 nt_errstr(status));
13284 goto out;
13287 /* Does 'foo' still exist ? */
13288 status = cli_posix_open(cli_posix,
13289 fooname,
13290 O_RDONLY,
13292 &fnum);
13293 if (!NT_STATUS_IS_OK(status)) {
13294 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13295 fooname,
13296 nt_errstr(status));
13297 goto out;
13300 status = cli_close(cli_posix, fnum);
13301 if (!NT_STATUS_IS_OK(status)) {
13302 goto out;
13305 correct = true;
13307 out:
13309 TALLOC_FREE(mangled_name);
13310 TALLOC_FREE(windows_rename_src);
13312 if (cli != NULL) {
13313 torture_deltree(cli, dname);
13314 torture_close_connection(cli);
13317 torture_close_connection(cli_posix);
13319 return correct;
13323 * Only testing minimal time strings, as the others
13324 * need (locale-dependent) guessing at what strftime does and
13325 * even may differ in builds.
13327 static bool timesubst_test(void)
13329 TALLOC_CTX *ctx = NULL;
13330 /* Sa 23. Dez 04:33:20 CET 2017 */
13331 const struct timeval tv = { 1514000000, 123 };
13332 const char* expect_minimal = "20171223_033320";
13333 const char* expect_minus = "20171223_033320_000123";
13334 char *s;
13335 char *env_tz, *orig_tz = NULL;
13336 bool result = true;
13338 ctx = talloc_new(NULL);
13340 env_tz = getenv("TZ");
13341 if(env_tz) {
13342 orig_tz = talloc_strdup(ctx, env_tz);
13344 setenv("TZ", "UTC", 1);
13346 s = minimal_timeval_string(ctx, &tv, false);
13348 if(!s || strcmp(s, expect_minimal)) {
13349 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13350 "[%s]\n", s ? s : "<nil>", expect_minimal);
13351 result = false;
13353 TALLOC_FREE(s);
13354 s = minimal_timeval_string(ctx, &tv, true);
13355 if(!s || strcmp(s, expect_minus)) {
13356 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13357 "[%s]\n", s ? s : "<nil>", expect_minus);
13358 result = false;
13360 TALLOC_FREE(s);
13362 if(orig_tz) {
13363 setenv("TZ", orig_tz, 1);
13366 TALLOC_FREE(ctx);
13367 return result;
13370 static bool run_local_substitute(int dummy)
13372 bool ok = true;
13374 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13375 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13376 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13377 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13378 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13379 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13380 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13381 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13382 ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13383 /* Substitution depends on current time, so better test the underlying
13384 formatting function. At least covers %t. */
13385 ok &= timesubst_test();
13387 /* Different captialization rules in sub_basic... */
13389 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13390 "blaDOM") == 0);
13392 return ok;
13395 static bool run_local_base64(int dummy)
13397 int i;
13398 bool ret = true;
13400 for (i=1; i<2000; i++) {
13401 DATA_BLOB blob1, blob2;
13402 char *b64;
13404 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13405 blob1.length = i;
13406 generate_random_buffer(blob1.data, blob1.length);
13408 b64 = base64_encode_data_blob(talloc_tos(), blob1);
13409 if (b64 == NULL) {
13410 d_fprintf(stderr, "base64_encode_data_blob failed "
13411 "for %d bytes\n", i);
13412 ret = false;
13414 blob2 = base64_decode_data_blob(b64);
13415 TALLOC_FREE(b64);
13417 if (data_blob_cmp(&blob1, &blob2)) {
13418 d_fprintf(stderr, "data_blob_cmp failed for %d "
13419 "bytes\n", i);
13420 ret = false;
13422 TALLOC_FREE(blob1.data);
13423 data_blob_free(&blob2);
13425 return ret;
13428 static void parse_fn(const struct gencache_timeout *t,
13429 DATA_BLOB blob,
13430 void *private_data)
13432 return;
13435 static bool run_local_gencache(int dummy)
13437 char *val;
13438 time_t tm;
13439 DATA_BLOB blob;
13440 char v;
13441 struct memcache *mem;
13442 int i;
13444 mem = memcache_init(NULL, 0);
13445 if (mem == NULL) {
13446 d_printf("%s: memcache_init failed\n", __location__);
13447 return false;
13449 memcache_set_global(mem);
13451 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13452 d_printf("%s: gencache_set() failed\n", __location__);
13453 return False;
13456 if (!gencache_get("foo", NULL, NULL, NULL)) {
13457 d_printf("%s: gencache_get() failed\n", __location__);
13458 return False;
13461 for (i=0; i<1000000; i++) {
13462 gencache_parse("foo", parse_fn, NULL);
13465 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13466 d_printf("%s: gencache_get() failed\n", __location__);
13467 return False;
13469 TALLOC_FREE(val);
13471 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13472 d_printf("%s: gencache_get() failed\n", __location__);
13473 return False;
13476 if (strcmp(val, "bar") != 0) {
13477 d_printf("%s: gencache_get() returned %s, expected %s\n",
13478 __location__, val, "bar");
13479 TALLOC_FREE(val);
13480 return False;
13483 TALLOC_FREE(val);
13485 if (!gencache_del("foo")) {
13486 d_printf("%s: gencache_del() failed\n", __location__);
13487 return False;
13489 if (gencache_del("foo")) {
13490 d_printf("%s: second gencache_del() succeeded\n",
13491 __location__);
13492 return False;
13495 if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13496 d_printf("%s: gencache_get() on deleted entry "
13497 "succeeded\n", __location__);
13498 return False;
13501 blob = data_blob_string_const_null("bar");
13502 tm = time(NULL) + 60;
13504 if (!gencache_set_data_blob("foo", blob, tm)) {
13505 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13506 return False;
13509 if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13510 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13511 return False;
13514 if (strcmp((const char *)blob.data, "bar") != 0) {
13515 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13516 __location__, (const char *)blob.data, "bar");
13517 data_blob_free(&blob);
13518 return False;
13521 data_blob_free(&blob);
13523 if (!gencache_del("foo")) {
13524 d_printf("%s: gencache_del() failed\n", __location__);
13525 return False;
13527 if (gencache_del("foo")) {
13528 d_printf("%s: second gencache_del() succeeded\n",
13529 __location__);
13530 return False;
13533 if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13534 d_printf("%s: gencache_get_data_blob() on deleted entry "
13535 "succeeded\n", __location__);
13536 return False;
13539 v = 1;
13540 blob.data = (uint8_t *)&v;
13541 blob.length = sizeof(v);
13543 if (!gencache_set_data_blob("blob", blob, tm)) {
13544 d_printf("%s: gencache_set_data_blob() failed\n",
13545 __location__);
13546 return false;
13548 if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13549 d_printf("%s: gencache_get succeeded\n", __location__);
13550 return false;
13553 return True;
13556 static bool rbt_testflags(struct db_context *db, const char *key,
13557 const char *value)
13559 bool ret = false;
13560 NTSTATUS status;
13561 struct db_record *rec;
13563 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13564 if (rec == NULL) {
13565 d_fprintf(stderr, "fetch_locked failed\n");
13566 goto done;
13569 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13570 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13571 d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13572 nt_errstr(status));
13573 goto done;
13576 status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13577 TDB_INSERT);
13578 if (!NT_STATUS_IS_OK(status)) {
13579 d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13580 nt_errstr(status));
13581 goto done;
13584 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13585 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13586 d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13587 nt_errstr(status));
13588 goto done;
13591 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13592 if (!NT_STATUS_IS_OK(status)) {
13593 d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13594 nt_errstr(status));
13595 goto done;
13598 ret = true;
13599 done:
13600 TALLOC_FREE(rec);
13601 return ret;
13604 static bool rbt_testval(struct db_context *db, const char *key,
13605 const char *value)
13607 struct db_record *rec;
13608 TDB_DATA data = string_tdb_data(value);
13609 bool ret = false;
13610 NTSTATUS status;
13611 TDB_DATA dbvalue;
13613 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13614 if (rec == NULL) {
13615 d_fprintf(stderr, "fetch_locked failed\n");
13616 goto done;
13618 status = dbwrap_record_store(rec, data, 0);
13619 if (!NT_STATUS_IS_OK(status)) {
13620 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13621 goto done;
13623 TALLOC_FREE(rec);
13625 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13626 if (rec == NULL) {
13627 d_fprintf(stderr, "second fetch_locked failed\n");
13628 goto done;
13631 dbvalue = dbwrap_record_get_value(rec);
13632 if ((dbvalue.dsize != data.dsize)
13633 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13634 d_fprintf(stderr, "Got wrong data back\n");
13635 goto done;
13638 ret = true;
13639 done:
13640 TALLOC_FREE(rec);
13641 return ret;
13644 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13646 int *count2 = (int *)private_data;
13647 (*count2)++;
13648 return 0;
13651 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13653 int *count2 = (int *)private_data;
13654 (*count2)++;
13655 dbwrap_record_delete(rec);
13656 return 0;
13659 static bool run_local_rbtree(int dummy)
13661 struct db_context *db;
13662 bool ret = false;
13663 int i;
13664 NTSTATUS status;
13665 int count = 0;
13666 int count2 = 0;
13668 db = db_open_rbt(NULL);
13670 if (db == NULL) {
13671 d_fprintf(stderr, "db_open_rbt failed\n");
13672 return false;
13675 if (!rbt_testflags(db, "firstkey", "firstval")) {
13676 goto done;
13679 for (i = 0; i < 999; i++) {
13680 char key[sizeof("key-9223372036854775807-1234")];
13681 char value[sizeof("value-9223372036854775807-1234")];
13683 snprintf(key, sizeof(key), "key%ld-%d", random(), i);
13684 snprintf(value, sizeof(value) ,"value%ld-%d", random(), i);
13686 if (!rbt_testval(db, key, value)) {
13687 goto done;
13690 snprintf(value, sizeof(value) ,"value%ld-%d", random(), i + 1);
13692 if (!rbt_testval(db, key, value)) {
13693 goto done;
13697 ret = true;
13698 count = 0; count2 = 0;
13699 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13700 &count2, &count);
13701 printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13702 if ((count != count2) || (count != 1000)) {
13703 ret = false;
13705 count = 0; count2 = 0;
13706 status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13707 &count2, &count);
13708 printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13709 if ((count != count2) || (count != 1000)) {
13710 ret = false;
13712 count = 0; count2 = 0;
13713 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13714 &count2, &count);
13715 printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13716 if ((count != count2) || (count != 0)) {
13717 ret = false;
13720 done:
13721 TALLOC_FREE(db);
13722 return ret;
13727 local test for character set functions
13729 This is a very simple test for the functionality in convert_string_error()
13731 static bool run_local_convert_string(int dummy)
13733 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13734 const char *test_strings[2] = { "March", "M\303\244rz" };
13735 char dst[7];
13736 int i;
13738 for (i=0; i<2; i++) {
13739 const char *str = test_strings[i];
13740 int len = strlen(str);
13741 size_t converted_size;
13742 bool ret;
13744 memset(dst, 'X', sizeof(dst));
13746 /* first try with real source length */
13747 ret = convert_string_error(CH_UNIX, CH_UTF8,
13748 str, len,
13749 dst, sizeof(dst),
13750 &converted_size);
13751 if (ret != true) {
13752 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13753 goto failed;
13756 if (converted_size != len) {
13757 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13758 str, len, (int)converted_size);
13759 goto failed;
13762 if (strncmp(str, dst, converted_size) != 0) {
13763 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13764 goto failed;
13767 if (strlen(str) != converted_size) {
13768 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13769 (int)strlen(str), (int)converted_size);
13770 goto failed;
13773 if (dst[converted_size] != 'X') {
13774 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13775 goto failed;
13778 /* now with srclen==-1, this causes the nul to be
13779 * converted too */
13780 ret = convert_string_error(CH_UNIX, CH_UTF8,
13781 str, -1,
13782 dst, sizeof(dst),
13783 &converted_size);
13784 if (ret != true) {
13785 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13786 goto failed;
13789 if (converted_size != len+1) {
13790 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13791 str, len, (int)converted_size);
13792 goto failed;
13795 if (strncmp(str, dst, converted_size) != 0) {
13796 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13797 goto failed;
13800 if (len+1 != converted_size) {
13801 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13802 len+1, (int)converted_size);
13803 goto failed;
13806 if (dst[converted_size] != 'X') {
13807 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13808 goto failed;
13814 TALLOC_FREE(tmp_ctx);
13815 return true;
13816 failed:
13817 TALLOC_FREE(tmp_ctx);
13818 return false;
13821 static bool run_local_string_to_sid(int dummy) {
13822 struct dom_sid sid;
13824 if (string_to_sid(&sid, "S--1-5-32-545")) {
13825 printf("allowing S--1-5-32-545\n");
13826 return false;
13828 if (string_to_sid(&sid, "S-1-5-32-+545")) {
13829 printf("allowing S-1-5-32-+545\n");
13830 return false;
13832 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")) {
13833 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13834 return false;
13836 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13837 printf("allowing S-1-5-32-545-abc\n");
13838 return false;
13840 if (string_to_sid(&sid, "S-300-5-32-545")) {
13841 printf("allowing S-300-5-32-545\n");
13842 return false;
13844 if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13845 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13846 return false;
13848 if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13849 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13850 return false;
13852 if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13853 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13854 return false;
13856 if (!string_to_sid(&sid, "S-1-5-32-545")) {
13857 printf("could not parse S-1-5-32-545\n");
13858 return false;
13860 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13861 struct dom_sid_buf buf;
13862 printf("mis-parsed S-1-5-32-545 as %s\n",
13863 dom_sid_str_buf(&sid, &buf));
13864 return false;
13866 return true;
13869 static bool sid_to_string_test(const char *expected) {
13870 char *str;
13871 bool res = true;
13872 struct dom_sid sid;
13874 if (!string_to_sid(&sid, expected)) {
13875 printf("could not parse %s\n", expected);
13876 return false;
13879 str = dom_sid_string(NULL, &sid);
13880 if (strcmp(str, expected)) {
13881 printf("Comparison failed (%s != %s)\n", str, expected);
13882 res = false;
13884 TALLOC_FREE(str);
13885 return res;
13888 static bool run_local_sid_to_string(int dummy) {
13889 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13890 return false;
13891 if (!sid_to_string_test("S-1-545"))
13892 return false;
13893 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13894 return false;
13895 return true;
13898 static bool run_local_binary_to_sid(int dummy) {
13899 ssize_t ret;
13900 struct dom_sid *sid = talloc(NULL, struct dom_sid);
13901 static const uint8_t good_binary_sid[] = {
13902 0x1, /* revision number */
13903 15, /* num auths */
13904 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13905 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13906 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13907 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13908 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13909 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13910 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13911 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13912 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13913 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13914 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13915 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13916 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13917 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13918 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13919 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13922 static const uint8_t long_binary_sid[] = {
13923 0x1, /* revision number */
13924 15, /* num auths */
13925 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13926 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13927 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13928 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13929 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13930 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13931 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13932 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13933 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13934 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13935 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13936 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13937 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13938 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13939 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13940 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13941 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13942 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13943 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13946 static const uint8_t long_binary_sid2[] = {
13947 0x1, /* revision number */
13948 32, /* num auths */
13949 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13950 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13951 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13952 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13953 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13954 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13955 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13956 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13957 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13958 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13959 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13960 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13961 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13962 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13963 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13964 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13965 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13966 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13967 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13968 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13969 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13970 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13971 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13972 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13973 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13974 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13975 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13976 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13977 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13978 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13979 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13980 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13981 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13984 ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13985 if (ret == -1) {
13986 return false;
13988 ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13989 if (ret != -1) {
13990 return false;
13992 ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13993 if (ret != -1) {
13994 return false;
13996 return true;
13999 /* Split a path name into filename and stream name components. Canonicalise
14000 * such that an implicit $DATA token is always explicit.
14002 * The "specification" of this function can be found in the
14003 * run_local_stream_name() function in torture.c, I've tried those
14004 * combinations against a W2k3 server.
14007 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
14008 char **pbase, char **pstream)
14010 char *base = NULL;
14011 char *stream = NULL;
14012 char *sname; /* stream name */
14013 const char *stype; /* stream type */
14015 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
14017 sname = strchr_m(fname, ':');
14019 if (sname == NULL) {
14020 if (pbase != NULL) {
14021 base = talloc_strdup(mem_ctx, fname);
14022 NT_STATUS_HAVE_NO_MEMORY(base);
14024 goto done;
14027 if (pbase != NULL) {
14028 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
14029 NT_STATUS_HAVE_NO_MEMORY(base);
14032 sname += 1;
14034 stype = strchr_m(sname, ':');
14036 if (stype == NULL) {
14037 sname = talloc_strdup(mem_ctx, sname);
14038 stype = "$DATA";
14040 else {
14041 if (strcasecmp_m(stype, ":$DATA") != 0) {
14043 * If there is an explicit stream type, so far we only
14044 * allow $DATA. Is there anything else allowed? -- vl
14046 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
14047 TALLOC_FREE(base);
14048 return NT_STATUS_OBJECT_NAME_INVALID;
14050 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
14051 stype += 1;
14054 if (sname == NULL) {
14055 TALLOC_FREE(base);
14056 return NT_STATUS_NO_MEMORY;
14059 if (sname[0] == '\0') {
14061 * no stream name, so no stream
14063 goto done;
14066 if (pstream != NULL) {
14067 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
14068 if (stream == NULL) {
14069 TALLOC_FREE(sname);
14070 TALLOC_FREE(base);
14071 return NT_STATUS_NO_MEMORY;
14074 * upper-case the type field
14076 (void)strupper_m(strchr_m(stream, ':')+1);
14079 done:
14080 if (pbase != NULL) {
14081 *pbase = base;
14083 if (pstream != NULL) {
14084 *pstream = stream;
14086 return NT_STATUS_OK;
14089 static bool test_stream_name(const char *fname, const char *expected_base,
14090 const char *expected_stream,
14091 NTSTATUS expected_status)
14093 NTSTATUS status;
14094 char *base = NULL;
14095 char *stream = NULL;
14097 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
14098 if (!NT_STATUS_EQUAL(status, expected_status)) {
14099 goto error;
14102 if (!NT_STATUS_IS_OK(status)) {
14103 return true;
14106 if (base == NULL) goto error;
14108 if (strcmp(expected_base, base) != 0) goto error;
14110 if ((expected_stream != NULL) && (stream == NULL)) goto error;
14111 if ((expected_stream == NULL) && (stream != NULL)) goto error;
14113 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
14114 goto error;
14116 TALLOC_FREE(base);
14117 TALLOC_FREE(stream);
14118 return true;
14120 error:
14121 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
14122 fname, expected_base ? expected_base : "<NULL>",
14123 expected_stream ? expected_stream : "<NULL>",
14124 nt_errstr(expected_status));
14125 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
14126 base ? base : "<NULL>", stream ? stream : "<NULL>",
14127 nt_errstr(status));
14128 TALLOC_FREE(base);
14129 TALLOC_FREE(stream);
14130 return false;
14133 static bool run_local_stream_name(int dummy)
14135 bool ret = true;
14137 ret &= test_stream_name(
14138 "bla", "bla", NULL, NT_STATUS_OK);
14139 ret &= test_stream_name(
14140 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
14141 ret &= test_stream_name(
14142 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14143 ret &= test_stream_name(
14144 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
14145 ret &= test_stream_name(
14146 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14147 ret &= test_stream_name(
14148 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
14149 ret &= test_stream_name(
14150 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
14151 ret &= test_stream_name(
14152 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
14154 return ret;
14157 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
14159 if (a.length != b.length) {
14160 printf("a.length=%d != b.length=%d\n",
14161 (int)a.length, (int)b.length);
14162 return false;
14164 if (memcmp(a.data, b.data, a.length) != 0) {
14165 printf("a.data and b.data differ\n");
14166 return false;
14168 return true;
14171 static bool run_local_memcache(int dummy)
14173 struct memcache *cache;
14174 DATA_BLOB k1, k2, k3, k4, k5;
14175 DATA_BLOB d1, d3;
14176 DATA_BLOB v1, v3;
14178 TALLOC_CTX *mem_ctx;
14179 char *ptr1 = NULL;
14180 char *ptr2 = NULL;
14181 char *ptr3 = NULL;
14183 char *str1, *str2;
14184 size_t size1, size2;
14185 bool ret = false;
14187 mem_ctx = talloc_init("foo");
14188 if (mem_ctx == NULL) {
14189 return false;
14192 /* STAT_CACHE TESTS */
14194 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14196 if (cache == NULL) {
14197 printf("memcache_init failed\n");
14198 return false;
14201 d1 = data_blob_const("d1", 2);
14202 d3 = data_blob_const("d3", 2);
14204 k1 = data_blob_const("d1", 2);
14205 k2 = data_blob_const("d2", 2);
14206 k3 = data_blob_const("d3", 2);
14207 k4 = data_blob_const("d4", 2);
14208 k5 = data_blob_const("d5", 2);
14210 memcache_add(cache, STAT_CACHE, k1, d1);
14212 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
14213 printf("could not find k1\n");
14214 return false;
14216 if (!data_blob_equal(d1, v1)) {
14217 return false;
14220 memcache_add(cache, STAT_CACHE, k1, d3);
14222 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
14223 printf("could not find replaced k1\n");
14224 return false;
14226 if (!data_blob_equal(d3, v3)) {
14227 return false;
14230 TALLOC_FREE(cache);
14232 /* GETWD_CACHE TESTS */
14233 str1 = talloc_strdup(mem_ctx, "string1");
14234 if (str1 == NULL) {
14235 return false;
14237 ptr2 = str1; /* Keep an alias for comparison. */
14239 str2 = talloc_strdup(mem_ctx, "string2");
14240 if (str2 == NULL) {
14241 return false;
14244 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14245 if (cache == NULL) {
14246 printf("memcache_init failed\n");
14247 return false;
14250 memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14251 /* str1 == NULL now. */
14252 ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14253 if (ptr1 == NULL) {
14254 printf("could not find k2\n");
14255 return false;
14257 if (ptr1 != ptr2) {
14258 printf("fetch of k2 got wrong string\n");
14259 return false;
14262 /* Add a blob to ensure k2 gets purged. */
14263 d3 = data_blob_talloc_zero(mem_ctx, 180);
14264 memcache_add(cache, STAT_CACHE, k3, d3);
14266 ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14267 if (ptr2 != NULL) {
14268 printf("Did find k2, should have been purged\n");
14269 return false;
14273 * Test that talloc size also is accounted in memcache and
14274 * causes purge of other object.
14277 str1 = talloc_zero_size(mem_ctx, 100);
14278 str2 = talloc_zero_size(mem_ctx, 100);
14280 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14281 memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14283 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14284 if (ptr3 != NULL) {
14285 printf("Did find k4, should have been purged\n");
14286 return false;
14290 * Test that adding a duplicate non-talloced
14291 * key/value on top of a talloced key/value takes account
14292 * of the talloc_freed value size.
14294 TALLOC_FREE(cache);
14295 TALLOC_FREE(mem_ctx);
14297 mem_ctx = talloc_init("key_replace");
14298 if (mem_ctx == NULL) {
14299 return false;
14302 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14303 if (cache == NULL) {
14304 return false;
14308 * Add a 100 byte talloced string. This will
14309 * store a (4 or 8 byte) pointer and record the
14310 * total talloced size.
14312 str1 = talloc_zero_size(mem_ctx, 100);
14313 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14315 * Now overwrite with a small talloced
14316 * value. This should fit in the existing size
14317 * and the total talloced size should be removed
14318 * from the cache size.
14320 str1 = talloc_zero_size(mem_ctx, 2);
14321 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14323 * Now store a 20 byte string. If the
14324 * total talloced size wasn't accounted for
14325 * and removed in the overwrite, then this
14326 * will evict k4.
14328 str2 = talloc_zero_size(mem_ctx, 20);
14329 memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14331 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14332 if (ptr3 == NULL) {
14333 printf("Did not find k4, should not have been purged\n");
14334 return false;
14337 TALLOC_FREE(cache);
14338 TALLOC_FREE(mem_ctx);
14340 mem_ctx = talloc_init("foo");
14341 if (mem_ctx == NULL) {
14342 return false;
14345 cache = memcache_init(NULL, 0);
14346 if (cache == NULL) {
14347 return false;
14350 str1 = talloc_strdup(mem_ctx, "string1");
14351 if (str1 == NULL) {
14352 return false;
14354 str2 = talloc_strdup(mem_ctx, "string2");
14355 if (str2 == NULL) {
14356 return false;
14358 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14359 data_blob_string_const("torture"), &str1);
14360 size1 = talloc_total_size(cache);
14362 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14363 data_blob_string_const("torture"), &str2);
14364 size2 = talloc_total_size(cache);
14366 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14368 if (size2 > size1) {
14369 printf("memcache leaks memory!\n");
14370 goto fail;
14373 ret = true;
14374 fail:
14375 TALLOC_FREE(cache);
14376 return ret;
14379 static void wbclient_done(struct tevent_req *req)
14381 wbcErr wbc_err;
14382 struct winbindd_response *wb_resp;
14383 int *i = (int *)tevent_req_callback_data_void(req);
14385 wbc_err = wb_trans_recv(req, req, &wb_resp);
14386 TALLOC_FREE(req);
14387 *i += 1;
14388 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14391 static bool run_wbclient_multi_ping(int dummy)
14393 struct tevent_context *ev;
14394 struct wb_context **wb_ctx;
14395 struct winbindd_request wb_req;
14396 bool result = false;
14397 int i, j;
14399 BlockSignals(True, SIGPIPE);
14401 ev = tevent_context_init(talloc_tos());
14402 if (ev == NULL) {
14403 goto fail;
14406 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14407 if (wb_ctx == NULL) {
14408 goto fail;
14411 ZERO_STRUCT(wb_req);
14412 wb_req.cmd = WINBINDD_PING;
14414 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14416 for (i=0; i<torture_nprocs; i++) {
14417 wb_ctx[i] = wb_context_init(ev, NULL);
14418 if (wb_ctx[i] == NULL) {
14419 goto fail;
14421 for (j=0; j<torture_numops; j++) {
14422 struct tevent_req *req;
14423 req = wb_trans_send(ev, ev, wb_ctx[i],
14424 (j % 2) == 0, &wb_req);
14425 if (req == NULL) {
14426 goto fail;
14428 tevent_req_set_callback(req, wbclient_done, &i);
14432 i = 0;
14434 while (i < torture_nprocs * torture_numops) {
14435 tevent_loop_once(ev);
14438 result = true;
14439 fail:
14440 TALLOC_FREE(ev);
14441 return result;
14444 static bool dbtrans_inc(struct db_context *db)
14446 struct db_record *rec;
14447 uint32_t val;
14448 bool ret = false;
14449 NTSTATUS status;
14450 TDB_DATA value;
14452 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14453 if (rec == NULL) {
14454 printf(__location__ "fetch_lock failed\n");
14455 return false;
14458 value = dbwrap_record_get_value(rec);
14460 if (value.dsize != sizeof(uint32_t)) {
14461 printf(__location__ "value.dsize = %d\n",
14462 (int)value.dsize);
14463 goto fail;
14466 memcpy(&val, value.dptr, sizeof(val));
14467 val += 1;
14469 status = dbwrap_record_store(
14470 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14471 if (!NT_STATUS_IS_OK(status)) {
14472 printf(__location__ "store failed: %s\n",
14473 nt_errstr(status));
14474 goto fail;
14477 ret = true;
14478 fail:
14479 TALLOC_FREE(rec);
14480 return ret;
14483 static bool run_local_dbtrans(int dummy)
14485 struct db_context *db;
14486 struct db_record *rec;
14487 NTSTATUS status;
14488 uint32_t initial;
14489 int res;
14490 TDB_DATA value;
14492 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14493 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14494 DBWRAP_FLAG_NONE);
14495 if (db == NULL) {
14496 printf("Could not open transtest.db\n");
14497 return false;
14500 res = dbwrap_transaction_start(db);
14501 if (res != 0) {
14502 printf(__location__ "transaction_start failed\n");
14503 return false;
14506 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14507 if (rec == NULL) {
14508 printf(__location__ "fetch_lock failed\n");
14509 return false;
14512 value = dbwrap_record_get_value(rec);
14514 if (value.dptr == NULL) {
14515 initial = 0;
14516 status = dbwrap_record_store(
14517 rec, make_tdb_data((uint8_t *)&initial,
14518 sizeof(initial)),
14520 if (!NT_STATUS_IS_OK(status)) {
14521 printf(__location__ "store returned %s\n",
14522 nt_errstr(status));
14523 return false;
14527 TALLOC_FREE(rec);
14529 res = dbwrap_transaction_commit(db);
14530 if (res != 0) {
14531 printf(__location__ "transaction_commit failed\n");
14532 return false;
14535 while (true) {
14536 uint32_t val, val2;
14537 int i;
14539 res = dbwrap_transaction_start(db);
14540 if (res != 0) {
14541 printf(__location__ "transaction_start failed\n");
14542 break;
14545 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14546 if (!NT_STATUS_IS_OK(status)) {
14547 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14548 nt_errstr(status));
14549 break;
14552 for (i=0; i<10; i++) {
14553 if (!dbtrans_inc(db)) {
14554 return false;
14558 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14559 if (!NT_STATUS_IS_OK(status)) {
14560 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14561 nt_errstr(status));
14562 break;
14565 if (val2 != val + 10) {
14566 printf(__location__ "val=%d, val2=%d\n",
14567 (int)val, (int)val2);
14568 break;
14571 printf("val2=%d\r", val2);
14573 res = dbwrap_transaction_commit(db);
14574 if (res != 0) {
14575 printf(__location__ "transaction_commit failed\n");
14576 break;
14580 TALLOC_FREE(db);
14581 return true;
14585 * Just a dummy test to be run under a debugger. There's no real way
14586 * to inspect the tevent_poll specific function from outside of
14587 * tevent_poll.c.
14590 static bool run_local_tevent_poll(int dummy)
14592 struct tevent_context *ev;
14593 struct tevent_fd *fd1, *fd2;
14594 bool result = false;
14596 ev = tevent_context_init_byname(NULL, "poll");
14597 if (ev == NULL) {
14598 d_fprintf(stderr, "tevent_context_init_byname failed\n");
14599 goto fail;
14602 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14603 if (fd1 == NULL) {
14604 d_fprintf(stderr, "tevent_add_fd failed\n");
14605 goto fail;
14607 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14608 if (fd2 == NULL) {
14609 d_fprintf(stderr, "tevent_add_fd failed\n");
14610 goto fail;
14612 TALLOC_FREE(fd2);
14614 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14615 if (fd2 == NULL) {
14616 d_fprintf(stderr, "tevent_add_fd failed\n");
14617 goto fail;
14620 result = true;
14621 fail:
14622 TALLOC_FREE(ev);
14623 return result;
14626 static bool run_local_hex_encode_buf(int dummy)
14628 char buf[17];
14629 uint8_t src[8];
14630 size_t i;
14632 for (i=0; i<sizeof(src); i++) {
14633 src[i] = i;
14635 hex_encode_buf(buf, src, sizeof(src));
14636 if (strcmp(buf, "0001020304050607") != 0) {
14637 return false;
14639 hex_encode_buf(buf, NULL, 0);
14640 if (buf[0] != '\0') {
14641 return false;
14643 return true;
14646 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14647 "0.0.0.0",
14648 "::0",
14649 "1.2.3.1",
14650 "0.0.0.0",
14651 "0.0.0.0",
14652 "1.2.3.2",
14653 "1.2.3.3",
14654 "1.2.3.4",
14655 "1.2.3.5",
14656 "::0",
14657 "1.2.3.6",
14658 "1.2.3.7",
14659 "::0",
14660 "::0",
14661 "::0",
14662 "1.2.3.8",
14663 "1.2.3.9",
14664 "1.2.3.10",
14665 "1.2.3.11",
14666 "1.2.3.12",
14667 "1.2.3.13",
14668 "1001:1111:1111:1000:0:1111:1111:1111",
14669 "1.2.3.1",
14670 "1.2.3.2",
14671 "1.2.3.3",
14672 "1.2.3.12",
14673 "::0",
14674 "::0"
14677 static const char *remove_duplicate_addrs2_test_strings_result[] = {
14678 "1.2.3.1",
14679 "1.2.3.2",
14680 "1.2.3.3",
14681 "1.2.3.4",
14682 "1.2.3.5",
14683 "1.2.3.6",
14684 "1.2.3.7",
14685 "1.2.3.8",
14686 "1.2.3.9",
14687 "1.2.3.10",
14688 "1.2.3.11",
14689 "1.2.3.12",
14690 "1.2.3.13",
14691 "1001:1111:1111:1000:0:1111:1111:1111"
14694 static bool run_local_remove_duplicate_addrs2(int dummy)
14696 struct samba_sockaddr test_vector[28];
14697 size_t count, i;
14699 /* Construct the sockaddr_storage test vector. */
14700 for (i = 0; i < 28; i++) {
14701 struct addrinfo hints;
14702 struct addrinfo *res = NULL;
14703 int ret;
14705 memset(&hints, '\0', sizeof(hints));
14706 hints.ai_flags = AI_NUMERICHOST;
14707 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14708 NULL,
14709 &hints,
14710 &res);
14711 if (ret) {
14712 fprintf(stderr, "getaddrinfo failed on [%s]\n",
14713 remove_duplicate_addrs2_test_strings_vector[i]);
14714 return false;
14716 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14717 memcpy(&test_vector[i].u.ss,
14718 res->ai_addr,
14719 res->ai_addrlen);
14720 freeaddrinfo(res);
14723 count = remove_duplicate_addrs2(test_vector, i);
14725 if (count != 14) {
14726 fprintf(stderr, "count wrong (%zu) should be 14\n",
14727 count);
14728 return false;
14731 for (i = 0; i < count; i++) {
14732 char addr[INET6_ADDRSTRLEN];
14734 print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14736 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14737 fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14739 addr,
14740 remove_duplicate_addrs2_test_strings_result[i]);
14741 return false;
14745 printf("run_local_remove_duplicate_addrs2: success\n");
14746 return true;
14749 static bool run_local_tdb_opener(int dummy)
14751 TDB_CONTEXT *t;
14752 unsigned v = 0;
14754 while (1) {
14755 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14756 O_RDWR|O_CREAT, 0755);
14757 if (t == NULL) {
14758 perror("tdb_open failed");
14759 return false;
14761 tdb_close(t);
14763 v += 1;
14764 printf("\r%u", v);
14766 return true;
14769 static bool run_local_tdb_writer(int dummy)
14771 TDB_CONTEXT *t;
14772 unsigned v = 0;
14773 TDB_DATA val;
14775 t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14776 if (t == 0) {
14777 perror("tdb_open failed");
14778 return 1;
14781 val.dptr = (uint8_t *)&v;
14782 val.dsize = sizeof(v);
14784 while (1) {
14785 TDB_DATA data;
14786 int ret;
14788 ret = tdb_store(t, val, val, 0);
14789 if (ret != 0) {
14790 printf("%s\n", tdb_errorstr(t));
14792 v += 1;
14793 printf("\r%u", v);
14795 data = tdb_fetch(t, val);
14796 if (data.dptr != NULL) {
14797 SAFE_FREE(data.dptr);
14800 return true;
14803 static bool run_local_canonicalize_path(int dummy)
14805 const char *src[] = {
14806 "/foo/..",
14807 "/..",
14808 "/foo/bar/../baz",
14809 "/foo/././",
14810 "/../foo",
14811 ".././././",
14812 ".././././../../../boo",
14813 "./..",
14814 "/",
14815 "/../../",
14816 "/foo/../",
14817 "/./././",
14818 "/./././.",
14819 "/.../././.",
14820 "/./././.foo",
14821 "/./././.foo.",
14822 "/./././foo.",
14823 "/foo/bar/..",
14824 "/foo/bar/../baz/",
14825 "////////////////",
14826 "/////////./././././.",
14827 "/./.././../.boo/../baz",
14828 "/a/component/path",
14829 "/a/component/path/",
14830 "/a/component/path/..",
14831 "/a/component/../path/",
14832 "///a/./././///component/../////path/",
14833 NULL
14835 const char *dst[] = {
14836 "/",
14837 "/",
14838 "/foo/baz",
14839 "/foo",
14840 "/foo",
14841 "/",
14842 "/boo",
14843 "/",
14844 "/",
14845 "/",
14846 "/",
14847 "/",
14848 "/",
14849 "/...",
14850 "/.foo",
14851 "/.foo.",
14852 "/foo.",
14853 "/foo",
14854 "/foo/baz",
14855 "/",
14856 "/",
14857 "/baz",
14858 "/a/component/path",
14859 "/a/component/path",
14860 "/a/component",
14861 "/a/path",
14862 "/a/path",
14863 NULL
14865 unsigned int i;
14867 for (i = 0; src[i] != NULL; i++) {
14868 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14869 if (d == NULL) {
14870 perror("talloc fail\n");
14871 return false;
14873 if (strcmp(d, dst[i]) != 0) {
14874 d_fprintf(stderr,
14875 "canonicalize mismatch %s -> %s != %s",
14876 src[i], d, dst[i]);
14877 return false;
14879 talloc_free(d);
14881 return true;
14883 struct session_setup_nt1_truncated_state {
14884 uint16_t vwv[13];
14885 uint8_t bytes[20];
14888 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq);
14890 static struct tevent_req *smb1_session_setup_nt1_truncated_send(
14891 TALLOC_CTX *mem_ctx,
14892 struct tevent_context *ev,
14893 struct smbXcli_conn *conn)
14895 uint16_t *vwv = NULL;
14896 uint8_t *bytes = NULL;
14897 const char *pass = "12345678";
14898 const char *uname = "z";
14899 struct session_setup_nt1_truncated_state *state = NULL;
14900 struct tevent_req *req = NULL;
14901 struct tevent_req *subreq = NULL;
14903 req = tevent_req_create(mem_ctx,
14904 &state,
14905 struct session_setup_nt1_truncated_state);
14906 if (req == NULL) {
14907 return NULL;
14909 vwv = &state->vwv[0];
14910 bytes = &state->bytes[0];
14912 SCVAL(vwv+0, 0, 0xff);
14913 SCVAL(vwv+0, 1, 0);
14914 SSVAL(vwv+1, 0, 0);
14915 SSVAL(vwv+2, 0, 8192);
14916 SSVAL(vwv+3, 0, 2);
14917 SSVAL(vwv+4, 0, 1);
14918 SIVAL(vwv+5, 0, 0);
14919 SSVAL(vwv+7, 0, strlen(pass)); /* OEMPasswordLen */
14920 SSVAL(vwv+8, 0, 0); /* UnicodePasswordLen */
14921 SSVAL(vwv+9, 0, 0); /* reserved */
14922 SSVAL(vwv+10, 0, 0); /* reserved */
14923 SIVAL(vwv+11, 0, CAP_STATUS32);
14925 memcpy(bytes, pass, strlen(pass));
14926 bytes += strlen(pass);
14927 memcpy(bytes, uname, strlen(uname)+1);
14929 subreq = smb1cli_req_send(state, ev, conn,
14930 SMBsesssetupX,
14931 0, /* additional_flags */
14932 0, /* clear_flags */
14933 0, /* additional_flags2 */
14934 0, /* clear_flags2 */
14935 10000, /* timeout_msec */
14936 getpid(),
14937 NULL, /* tcon */
14938 NULL, /* session */
14939 13, /* wct */
14940 state->vwv,
14941 strlen(pass), /* Truncate length at password. */
14942 state->bytes);
14943 if (tevent_req_nomem(subreq, req)) {
14944 return tevent_req_post(req, ev);
14946 tevent_req_set_callback(subreq,
14947 smb1_session_setup_nt1_truncated_done,
14948 req);
14949 return req;
14952 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq)
14954 struct tevent_req *req =
14955 tevent_req_callback_data(subreq,
14956 struct tevent_req);
14957 struct session_setup_nt1_truncated_state *state =
14958 tevent_req_data(req,
14959 struct session_setup_nt1_truncated_state);
14960 NTSTATUS status;
14961 struct smb1cli_req_expected_response expected[] = {
14963 .status = NT_STATUS_OK,
14964 .wct = 3,
14968 status = smb1cli_req_recv(subreq, state,
14969 NULL,
14970 NULL,
14971 NULL,
14972 NULL,
14973 NULL, /* pvwv_offset */
14974 NULL,
14975 NULL,
14976 NULL, /* pbytes_offset */
14977 NULL,
14978 expected, ARRAY_SIZE(expected));
14979 TALLOC_FREE(subreq);
14980 if (tevent_req_nterror(req, status)) {
14981 return;
14983 tevent_req_done(req);
14986 static NTSTATUS smb1_session_setup_nt1_truncated_recv(struct tevent_req *req)
14988 return tevent_req_simple_recv_ntstatus(req);
14991 static bool run_smb1_truncated_sesssetup(int dummy)
14993 struct tevent_context *ev;
14994 struct tevent_req *req;
14995 struct smbXcli_conn *conn;
14996 struct sockaddr_storage ss;
14997 NTSTATUS status;
14998 int fd;
14999 bool ok;
15001 printf("Starting send truncated SMB1 sesssetup.\n");
15003 ok = resolve_name(host, &ss, 0x20, true);
15004 if (!ok) {
15005 d_fprintf(stderr, "Could not resolve name %s\n", host);
15006 return false;
15009 status = open_socket_out(&ss, 445, 10000, &fd);
15010 if (!NT_STATUS_IS_OK(status)) {
15011 d_fprintf(stderr, "open_socket_out failed: %s\n",
15012 nt_errstr(status));
15013 return false;
15016 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15017 NULL, 0, NULL);
15018 if (conn == NULL) {
15019 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15020 return false;
15023 status = smbXcli_negprot(conn,
15025 PROTOCOL_NT1,
15026 PROTOCOL_NT1,
15027 NULL,
15028 NULL,
15029 NULL);
15030 if (!NT_STATUS_IS_OK(status)) {
15031 d_fprintf(stderr, "smbXcli_negprot failed!\n");
15032 return false;
15035 ev = samba_tevent_context_init(talloc_tos());
15036 if (ev == NULL) {
15037 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15038 return false;
15041 req = smb1_session_setup_nt1_truncated_send(ev, ev, conn);
15042 if (req == NULL) {
15043 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_send failed\n");
15044 return false;
15047 ok = tevent_req_poll_ntstatus(req, ev, &status);
15048 if (!ok) {
15049 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
15050 nt_errstr(status));
15051 return false;
15054 status = smb1_session_setup_nt1_truncated_recv(req);
15055 if (!NT_STATUS_IS_OK(status)) {
15056 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_recv returned "
15057 "%s, expected NT_STATUS_OK\n",
15058 nt_errstr(status));
15059 return false;
15062 TALLOC_FREE(conn);
15063 return true;
15066 struct smb1_negotiate_exit_state {
15067 int dummy;
15070 static void smb1_negotiate_exit_done(struct tevent_req *subreq);
15072 static struct tevent_req *smb1_negotiate_exit_send(
15073 TALLOC_CTX *mem_ctx,
15074 struct tevent_context *ev,
15075 struct smbXcli_conn *conn)
15077 struct smb1_negotiate_exit_state *state = NULL;
15078 struct tevent_req *req = NULL;
15079 struct tevent_req *subreq = NULL;
15081 req = tevent_req_create(mem_ctx,
15082 &state,
15083 struct smb1_negotiate_exit_state);
15084 if (req == NULL) {
15085 return NULL;
15087 subreq = smb1cli_req_send(state, ev, conn,
15088 SMBexit,
15089 0, /* additional_flags */
15090 0, /* clear_flags */
15091 0, /* additional_flags2 */
15092 0, /* clear_flags2 */
15093 10000, /* timeout_msec */
15094 getpid(),
15095 NULL, /* tcon */
15096 NULL, /* session */
15097 0, /* wct */
15098 NULL,
15100 NULL);
15101 if (tevent_req_nomem(subreq, req)) {
15102 return tevent_req_post(req, ev);
15104 tevent_req_set_callback(subreq,
15105 smb1_negotiate_exit_done,
15106 req);
15107 return req;
15110 static void smb1_negotiate_exit_done(struct tevent_req *subreq)
15112 struct tevent_req *req =
15113 tevent_req_callback_data(subreq,
15114 struct tevent_req);
15115 struct smb1_negotiate_exit_state *state =
15116 tevent_req_data(req,
15117 struct smb1_negotiate_exit_state);
15118 NTSTATUS status;
15119 struct smb1cli_req_expected_response expected[] = {
15121 .status = NT_STATUS_OK,
15122 .wct = 0,
15126 status = smb1cli_req_recv(subreq, state,
15127 NULL,
15128 NULL,
15129 NULL,
15130 NULL,
15131 NULL, /* pvwv_offset */
15132 NULL,
15133 NULL,
15134 NULL, /* pbytes_offset */
15135 NULL,
15136 expected, ARRAY_SIZE(expected));
15137 TALLOC_FREE(subreq);
15138 if (tevent_req_nterror(req, status)) {
15139 return;
15141 tevent_req_done(req);
15144 static NTSTATUS smb1_negotiate_exit_recv(struct tevent_req *req)
15146 return tevent_req_simple_recv_ntstatus(req);
15149 static bool do_smb1_exit(TALLOC_CTX *mem_ctx,
15150 struct tevent_context *ev,
15151 struct smbXcli_conn *conn)
15153 struct tevent_req *req;
15154 bool ok;
15155 NTSTATUS status;
15156 NTSTATUS expected_status = NT_STATUS_DOS(ERRSRV, ERRinvnid);;
15158 req = smb1_negotiate_exit_send(ev, ev, conn);
15159 if (req == NULL) {
15160 d_fprintf(stderr, "smb1_negotiate_exit_send failed\n");
15161 return false;
15164 ok = tevent_req_poll_ntstatus(req, ev, &status);
15165 if (!ok) {
15166 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
15167 nt_errstr(status));
15168 return false;
15171 status = smb1_negotiate_exit_recv(req);
15172 if (!NT_STATUS_EQUAL(status, expected_status)) {
15173 d_fprintf(stderr, "smb1_negotiate_exit_recv returned "
15174 "%s, expected ERRSRV, ERRinvnid\n",
15175 nt_errstr(status));
15176 return false;
15178 return true;
15181 static bool run_smb1_negotiate_exit(int dummy)
15183 struct tevent_context *ev;
15184 struct smbXcli_conn *conn;
15185 struct sockaddr_storage ss;
15186 NTSTATUS status;
15187 int fd;
15188 bool ok;
15190 printf("Starting send SMB1 negotiate+exit.\n");
15192 ok = resolve_name(host, &ss, 0x20, true);
15193 if (!ok) {
15194 d_fprintf(stderr, "Could not resolve name %s\n", host);
15195 return false;
15198 status = open_socket_out(&ss, 445, 10000, &fd);
15199 if (!NT_STATUS_IS_OK(status)) {
15200 d_fprintf(stderr, "open_socket_out failed: %s\n",
15201 nt_errstr(status));
15202 return false;
15205 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15206 NULL, 0, NULL);
15207 if (conn == NULL) {
15208 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15209 return false;
15212 status = smbXcli_negprot(conn,
15214 PROTOCOL_NT1,
15215 PROTOCOL_NT1,
15216 NULL,
15217 NULL,
15218 NULL);
15219 if (!NT_STATUS_IS_OK(status)) {
15220 d_fprintf(stderr, "smbXcli_negprot failed!\n");
15221 return false;
15224 ev = samba_tevent_context_init(talloc_tos());
15225 if (ev == NULL) {
15226 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15227 return false;
15231 * Call do_smb1_exit twice to catch a server crash, the
15232 * server sends the first return code then crashes.
15234 ok = do_smb1_exit(ev, ev, conn);
15235 if (!ok) {
15236 d_fprintf(stderr, "do_smb1_exit (1) failed\n");
15237 return false;
15239 ok = do_smb1_exit(ev, ev, conn);
15240 if (!ok) {
15241 d_fprintf(stderr, "do_smb1_exit (2) failed\n");
15242 return false;
15245 TALLOC_FREE(conn);
15246 return true;
15249 static bool run_smb1_negotiate_tcon(int dummy)
15251 struct cli_state *cli = NULL;
15252 uint16_t cnum = 0;
15253 uint16_t max_xmit = 0;
15254 NTSTATUS status;
15256 printf("Starting send SMB1 negotiate+tcon.\n");
15257 cli = open_nbt_connection();
15258 if (cli == NULL) {
15259 d_fprintf(stderr, "open_nbt_connection failed!\n");
15260 return false;
15262 smbXcli_conn_set_sockopt(cli->conn, sockops);
15264 status = smbXcli_negprot(cli->conn,
15266 PROTOCOL_NT1,
15267 PROTOCOL_NT1,
15268 NULL,
15269 NULL,
15270 NULL);
15271 if (!NT_STATUS_IS_OK(status)) {
15272 d_fprintf(stderr, "smbXcli_negprot failed %s!\n",
15273 nt_errstr(status));
15274 return false;
15276 status = cli_raw_tcon(cli,
15277 share,
15279 "?????",
15280 &max_xmit,
15281 &cnum);
15282 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
15283 d_fprintf(stderr, "cli_raw_tcon failed - got %s "
15284 "(should get NT_STATUS_ACCESS_DENIED)!\n",
15285 nt_errstr(status));
15286 return false;
15288 return true;
15291 static bool run_ign_bad_negprot(int dummy)
15293 struct tevent_context *ev;
15294 struct tevent_req *req;
15295 struct smbXcli_conn *conn;
15296 struct sockaddr_storage ss;
15297 NTSTATUS status;
15298 int fd;
15299 bool ok;
15301 printf("starting ignore bad negprot\n");
15303 ok = resolve_name(host, &ss, 0x20, true);
15304 if (!ok) {
15305 d_fprintf(stderr, "Could not resolve name %s\n", host);
15306 return false;
15309 status = open_socket_out(&ss, 445, 10000, &fd);
15310 if (!NT_STATUS_IS_OK(status)) {
15311 d_fprintf(stderr, "open_socket_out failed: %s\n",
15312 nt_errstr(status));
15313 return false;
15316 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15317 NULL, 0, NULL);
15318 if (conn == NULL) {
15319 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15320 return false;
15323 status = smbXcli_negprot(conn,
15325 PROTOCOL_CORE,
15326 PROTOCOL_CORE,
15327 NULL,
15328 NULL,
15329 NULL);
15330 if (NT_STATUS_IS_OK(status)) {
15331 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
15332 return false;
15335 ev = samba_tevent_context_init(talloc_tos());
15336 if (ev == NULL) {
15337 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15338 return false;
15341 req = smb1cli_session_setup_nt1_send(
15342 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
15343 data_blob_null, data_blob_null, 0x40,
15344 "Windows 2000 2195", "Windows 2000 5.0");
15345 if (req == NULL) {
15346 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
15347 return false;
15350 ok = tevent_req_poll_ntstatus(req, ev, &status);
15351 if (!ok) {
15352 d_fprintf(stderr, "tevent_req_poll failed\n");
15353 return false;
15356 status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
15357 NULL, NULL);
15358 if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
15359 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
15360 "%s, expected NT_STATUS_CONNECTION_RESET\n",
15361 nt_errstr(status));
15362 return false;
15365 TALLOC_FREE(conn);
15367 printf("starting ignore bad negprot\n");
15369 return true;
15373 static double create_procs(bool (*fn)(int), bool *result)
15375 int i, status;
15376 volatile pid_t *child_status;
15377 volatile bool *child_status_out;
15378 int synccount;
15379 int tries = 8;
15380 struct timeval start;
15382 synccount = 0;
15384 child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
15385 if (!child_status) {
15386 printf("Failed to setup shared memory\n");
15387 return -1;
15390 child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
15391 if (!child_status_out) {
15392 printf("Failed to setup result status shared memory\n");
15393 return -1;
15396 for (i = 0; i < torture_nprocs; i++) {
15397 child_status[i] = 0;
15398 child_status_out[i] = True;
15401 start = timeval_current();
15403 for (i=0;i<torture_nprocs;i++) {
15404 procnum = i;
15405 if (fork() == 0) {
15406 pid_t mypid = getpid();
15407 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
15409 slprintf(myname,sizeof(myname),"CLIENT%d", i);
15411 while (1) {
15412 if (torture_open_connection(&current_cli, i)) break;
15413 if (tries-- == 0) {
15414 printf("pid %d failed to start\n", (int)getpid());
15415 _exit(1);
15417 smb_msleep(10);
15420 child_status[i] = getpid();
15422 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
15424 child_status_out[i] = fn(i);
15425 _exit(0);
15429 do {
15430 synccount = 0;
15431 for (i=0;i<torture_nprocs;i++) {
15432 if (child_status[i]) synccount++;
15434 if (synccount == torture_nprocs) break;
15435 smb_msleep(10);
15436 } while (timeval_elapsed(&start) < 30);
15438 if (synccount != torture_nprocs) {
15439 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
15440 *result = False;
15441 return timeval_elapsed(&start);
15444 /* start the client load */
15445 start = timeval_current();
15447 for (i=0;i<torture_nprocs;i++) {
15448 child_status[i] = 0;
15451 printf("%d clients started\n", torture_nprocs);
15453 for (i=0;i<torture_nprocs;i++) {
15454 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
15457 printf("\n");
15459 for (i=0;i<torture_nprocs;i++) {
15460 if (!child_status_out[i]) {
15461 *result = False;
15464 return timeval_elapsed(&start);
15467 #define FLAG_MULTIPROC 1
15469 static struct {
15470 const char *name;
15471 bool (*fn)(int);
15472 unsigned flags;
15473 } torture_ops[] = {
15475 .name = "FDPASS",
15476 .fn = run_fdpasstest,
15479 .name = "LOCK1",
15480 .fn = run_locktest1,
15483 .name = "LOCK2",
15484 .fn = run_locktest2,
15487 .name = "LOCK3",
15488 .fn = run_locktest3,
15491 .name = "LOCK4",
15492 .fn = run_locktest4,
15495 .name = "LOCK5",
15496 .fn = run_locktest5,
15499 .name = "LOCK6",
15500 .fn = run_locktest6,
15503 .name = "LOCK7",
15504 .fn = run_locktest7,
15507 .name = "LOCK8",
15508 .fn = run_locktest8,
15511 .name = "LOCK9A",
15512 .fn = run_locktest9a,
15515 .name = "LOCK9B",
15516 .fn = run_locktest9b,
15519 .name = "LOCK10",
15520 .fn = run_locktest10,
15523 .name = "LOCK11",
15524 .fn = run_locktest11,
15527 .name = "LOCK12",
15528 .fn = run_locktest12,
15531 .name = "LOCK13",
15532 .fn = run_locktest13,
15535 .name = "UNLINK",
15536 .fn = run_unlinktest,
15539 .name = "BROWSE",
15540 .fn = run_browsetest,
15543 .name = "ATTR",
15544 .fn = run_attrtest,
15547 .name = "TRANS2",
15548 .fn = run_trans2test,
15551 .name = "MAXFID",
15552 .fn = run_maxfidtest,
15553 .flags = FLAG_MULTIPROC,
15556 .name = "TORTURE",
15557 .fn = run_torture,
15558 .flags = FLAG_MULTIPROC,
15561 .name = "RANDOMIPC",
15562 .fn = run_randomipc,
15565 .name = "NEGNOWAIT",
15566 .fn = run_negprot_nowait,
15569 .name = "NBENCH",
15570 .fn = run_nbench,
15573 .name = "NBENCH2",
15574 .fn = run_nbench2,
15577 .name = "OPLOCK1",
15578 .fn = run_oplock1,
15581 .name = "OPLOCK2",
15582 .fn = run_oplock2,
15585 .name = "OPLOCK4",
15586 .fn = run_oplock4,
15588 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
15590 .name = "OPLOCK5",
15591 .fn = run_oplock5,
15593 #endif
15595 .name = "DIR",
15596 .fn = run_dirtest,
15599 .name = "DIR1",
15600 .fn = run_dirtest1,
15603 .name = "DIR-CREATETIME",
15604 .fn = run_dir_createtime,
15607 .name = "DENY1",
15608 .fn = torture_denytest1,
15611 .name = "DENY2",
15612 .fn = torture_denytest2,
15615 .name = "TCON",
15616 .fn = run_tcon_test,
15619 .name = "TCONDEV",
15620 .fn = run_tcon_devtype_test,
15623 .name = "RW1",
15624 .fn = run_readwritetest,
15627 .name = "RW2",
15628 .fn = run_readwritemulti,
15629 .flags = FLAG_MULTIPROC
15632 .name = "RW3",
15633 .fn = run_readwritelarge,
15636 .name = "RW-SIGNING",
15637 .fn = run_readwritelarge_signtest,
15640 .name = "OPEN",
15641 .fn = run_opentest,
15644 .name = "POSIX",
15645 .fn = run_simple_posix_open_test,
15648 .name = "POSIX-APPEND",
15649 .fn = run_posix_append,
15652 .name = "POSIX-SYMLINK-ACL",
15653 .fn = run_acl_symlink_test,
15656 .name = "POSIX-SYMLINK-EA",
15657 .fn = run_ea_symlink_test,
15660 .name = "POSIX-STREAM-DELETE",
15661 .fn = run_posix_stream_delete,
15664 .name = "POSIX-OFD-LOCK",
15665 .fn = run_posix_ofd_lock_test,
15668 .name = "POSIX-BLOCKING-LOCK",
15669 .fn = run_posix_blocking_lock,
15672 .name = "POSIX-MKDIR",
15673 .fn = run_posix_mkdir_test,
15676 .name = "POSIX-ACL-OPLOCK",
15677 .fn = run_posix_acl_oplock_test,
15680 .name = "POSIX-ACL-SHAREROOT",
15681 .fn = run_posix_acl_shareroot_test,
15684 .name = "POSIX-LS-WILDCARD",
15685 .fn = run_posix_ls_wildcard_test,
15688 .name = "POSIX-LS-SINGLE",
15689 .fn = run_posix_ls_single_test,
15692 .name = "POSIX-READLINK",
15693 .fn = run_posix_readlink_test,
15696 .name = "POSIX-STAT",
15697 .fn = run_posix_stat_test,
15700 .name = "POSIX-SYMLINK-PARENT",
15701 .fn = run_posix_symlink_parent_test,
15704 .name = "POSIX-SYMLINK-CHMOD",
15705 .fn = run_posix_symlink_chmod_test,
15708 .name = "POSIX-SYMLINK-RENAME",
15709 .fn = run_posix_symlink_rename_test,
15712 .name = "POSIX-DIR-DEFAULT-ACL",
15713 .fn = run_posix_dir_default_acl_test,
15716 .name = "POSIX-SYMLINK-GETPATHINFO",
15717 .fn = run_posix_symlink_getpathinfo_test,
15720 .name = "POSIX-SYMLINK-SETPATHINFO",
15721 .fn = run_posix_symlink_setpathinfo_test,
15724 .name = "WINDOWS-BAD-SYMLINK",
15725 .fn = run_symlink_open_test,
15728 .name = "SMB1-WILD-MANGLE-UNLINK",
15729 .fn = run_smb1_wild_mangle_unlink_test,
15732 .name = "SMB1-WILD-MANGLE-RENAME",
15733 .fn = run_smb1_wild_mangle_rename_test,
15736 .name = "CASE-INSENSITIVE-CREATE",
15737 .fn = run_case_insensitive_create,
15740 .name = "ASYNC-ECHO",
15741 .fn = run_async_echo,
15744 .name = "UID-REGRESSION-TEST",
15745 .fn = run_uid_regression_test,
15748 .name = "SHORTNAME-TEST",
15749 .fn = run_shortname_test,
15752 .name = "ADDRCHANGE",
15753 .fn = run_addrchange,
15755 #if 1
15757 .name = "OPENATTR",
15758 .fn = run_openattrtest,
15760 #endif
15762 .name = "XCOPY",
15763 .fn = run_xcopy,
15766 .name = "RENAME",
15767 .fn = run_rename,
15770 .name = "RENAME-ACCESS",
15771 .fn = run_rename_access,
15774 .name = "OWNER-RIGHTS",
15775 .fn = run_owner_rights,
15778 .name = "DELETE",
15779 .fn = run_deletetest,
15782 .name = "DELETE-STREAM",
15783 .fn = run_delete_stream,
15786 .name = "DELETE-PRINT",
15787 .fn = run_delete_print_test,
15790 .name = "DELETE-LN",
15791 .fn = run_deletetest_ln,
15794 .name = "PROPERTIES",
15795 .fn = run_properties,
15798 .name = "MANGLE",
15799 .fn = torture_mangle,
15802 .name = "MANGLE1",
15803 .fn = run_mangle1,
15806 .name = "MANGLE-ILLEGAL",
15807 .fn = run_mangle_illegal,
15810 .name = "W2K",
15811 .fn = run_w2ktest,
15814 .name = "TRANS2SCAN",
15815 .fn = torture_trans2_scan,
15818 .name = "NTTRANSSCAN",
15819 .fn = torture_nttrans_scan,
15822 .name = "UTABLE",
15823 .fn = torture_utable,
15826 .name = "CASETABLE",
15827 .fn = torture_casetable,
15830 .name = "ERRMAPEXTRACT",
15831 .fn = run_error_map_extract,
15834 .name = "PIPE_NUMBER",
15835 .fn = run_pipe_number,
15838 .name = "TCON2",
15839 .fn = run_tcon2_test,
15842 .name = "IOCTL",
15843 .fn = torture_ioctl_test,
15846 .name = "CHKPATH",
15847 .fn = torture_chkpath_test,
15850 .name = "FDSESS",
15851 .fn = run_fdsesstest,
15854 .name = "EATEST",
15855 .fn = run_eatest,
15858 .name = "SESSSETUP_BENCH",
15859 .fn = run_sesssetup_bench,
15862 .name = "CHAIN1",
15863 .fn = run_chain1,
15866 .name = "CHAIN2",
15867 .fn = run_chain2,
15870 .name = "CHAIN3",
15871 .fn = run_chain3,
15874 .name = "WINDOWS-WRITE",
15875 .fn = run_windows_write,
15878 .name = "LARGE_READX",
15879 .fn = run_large_readx,
15882 .name = "MSDFS-ATTRIBUTE",
15883 .fn = run_msdfs_attribute,
15886 .name = "NTTRANS-CREATE",
15887 .fn = run_nttrans_create,
15890 .name = "NTTRANS-FSCTL",
15891 .fn = run_nttrans_fsctl,
15894 .name = "CLI_ECHO",
15895 .fn = run_cli_echo,
15898 .name = "CLI_SPLICE",
15899 .fn = run_cli_splice,
15902 .name = "TLDAP",
15903 .fn = run_tldap,
15906 .name = "STREAMERROR",
15907 .fn = run_streamerror,
15910 .name = "NOTIFY-BENCH",
15911 .fn = run_notify_bench,
15914 .name = "NOTIFY-BENCH2",
15915 .fn = run_notify_bench2,
15918 .name = "NOTIFY-BENCH3",
15919 .fn = run_notify_bench3,
15922 .name = "BAD-NBT-SESSION",
15923 .fn = run_bad_nbt_session,
15926 .name = "IGN-BAD-NEGPROT",
15927 .fn = run_ign_bad_negprot,
15930 .name = "SMB-ANY-CONNECT",
15931 .fn = run_smb_any_connect,
15934 .name = "NOTIFY-ONLINE",
15935 .fn = run_notify_online,
15938 .name = "SMB2-BASIC",
15939 .fn = run_smb2_basic,
15942 .name = "SMB2-NEGPROT",
15943 .fn = run_smb2_negprot,
15946 .name = "SMB2-ANONYMOUS",
15947 .fn = run_smb2_anonymous,
15950 .name = "SMB2-SESSION-RECONNECT",
15951 .fn = run_smb2_session_reconnect,
15954 .name = "SMB2-TCON-DEPENDENCE",
15955 .fn = run_smb2_tcon_dependence,
15958 .name = "SMB2-MULTI-CHANNEL",
15959 .fn = run_smb2_multi_channel,
15962 .name = "SMB2-SESSION-REAUTH",
15963 .fn = run_smb2_session_reauth,
15966 .name = "SMB2-FTRUNCATE",
15967 .fn = run_smb2_ftruncate,
15970 .name = "SMB2-DIR-FSYNC",
15971 .fn = run_smb2_dir_fsync,
15974 .name = "SMB2-PATH-SLASH",
15975 .fn = run_smb2_path_slash,
15978 .name = "SMB1-SYSTEM-SECURITY",
15979 .fn = run_smb1_system_security,
15982 .name = "SMB2-SACL",
15983 .fn = run_smb2_sacl,
15986 .name = "SMB2-QUOTA1",
15987 .fn = run_smb2_quota1,
15990 .name = "SMB2-INVALID-PIPENAME",
15991 .fn = run_smb2_invalid_pipename,
15994 .name = "SMB2-STREAM-ACL",
15995 .fn = run_smb2_stream_acl,
15998 .name = "SMB2-LIST-DIR-ASYNC",
15999 .fn = run_list_dir_async_test,
16002 .name = "SMB2-DEL-ON-CLOSE-NONEMPTY",
16003 .fn = run_delete_on_close_non_empty,
16006 .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
16007 .fn = run_delete_on_close_nonwrite_delete_yes_test,
16010 .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
16011 .fn = run_delete_on_close_nonwrite_delete_no_test,
16014 .name = "SMB2-DFS-PATHS",
16015 .fn = run_smb2_dfs_paths,
16018 .name = "SMB2-NON-DFS-SHARE",
16019 .fn = run_smb2_non_dfs_share,
16022 .name = "SMB2-DFS-SHARE-NON-DFS-PATH",
16023 .fn = run_smb2_dfs_share_non_dfs_path,
16026 .name = "SMB2-DFS-FILENAME-LEADING-BACKSLASH",
16027 .fn = run_smb2_dfs_filename_leading_backslash,
16030 .name = "SMB2-PIPE-READ-ASYNC-DISCONNECT",
16031 .fn = run_smb2_pipe_read_async_disconnect,
16034 .name = "SMB1-TRUNCATED-SESSSETUP",
16035 .fn = run_smb1_truncated_sesssetup,
16038 .name = "SMB1-NEGOTIATE-EXIT",
16039 .fn = run_smb1_negotiate_exit,
16042 .name = "SMB1-NEGOTIATE-TCON",
16043 .fn = run_smb1_negotiate_tcon,
16046 .name = "SMB1-DFS-PATHS",
16047 .fn = run_smb1_dfs_paths,
16050 .name = "SMB1-DFS-SEARCH-PATHS",
16051 .fn = run_smb1_dfs_search_paths,
16054 .name = "SMB1-DFS-OPERATIONS",
16055 .fn = run_smb1_dfs_operations,
16058 .name = "SMB1-DFS-BADPATH",
16059 .fn = run_smb1_dfs_check_badpath,
16062 .name = "CLEANUP1",
16063 .fn = run_cleanup1,
16066 .name = "CLEANUP2",
16067 .fn = run_cleanup2,
16070 .name = "CLEANUP4",
16071 .fn = run_cleanup4,
16074 .name = "OPLOCK-CANCEL",
16075 .fn = run_oplock_cancel,
16078 .name = "PIDHIGH",
16079 .fn = run_pidhigh,
16082 .name = "LOCAL-SUBSTITUTE",
16083 .fn = run_local_substitute,
16086 .name = "LOCAL-GENCACHE",
16087 .fn = run_local_gencache,
16090 .name = "LOCAL-DBWRAP-WATCH1",
16091 .fn = run_dbwrap_watch1,
16094 .name = "LOCAL-DBWRAP-WATCH2",
16095 .fn = run_dbwrap_watch2,
16098 .name = "LOCAL-DBWRAP-WATCH3",
16099 .fn = run_dbwrap_watch3,
16102 .name = "LOCAL-DBWRAP-WATCH4",
16103 .fn = run_dbwrap_watch4,
16106 .name = "LOCAL-DBWRAP-DO-LOCKED1",
16107 .fn = run_dbwrap_do_locked1,
16110 .name = "LOCAL-MESSAGING-READ1",
16111 .fn = run_messaging_read1,
16114 .name = "LOCAL-MESSAGING-READ2",
16115 .fn = run_messaging_read2,
16118 .name = "LOCAL-MESSAGING-READ3",
16119 .fn = run_messaging_read3,
16122 .name = "LOCAL-MESSAGING-READ4",
16123 .fn = run_messaging_read4,
16126 .name = "LOCAL-MESSAGING-FDPASS1",
16127 .fn = run_messaging_fdpass1,
16130 .name = "LOCAL-MESSAGING-FDPASS2",
16131 .fn = run_messaging_fdpass2,
16134 .name = "LOCAL-MESSAGING-FDPASS2a",
16135 .fn = run_messaging_fdpass2a,
16138 .name = "LOCAL-MESSAGING-FDPASS2b",
16139 .fn = run_messaging_fdpass2b,
16142 .name = "LOCAL-MESSAGING-SEND-ALL",
16143 .fn = run_messaging_send_all,
16146 .name = "LOCAL-BASE64",
16147 .fn = run_local_base64,
16150 .name = "LOCAL-RBTREE",
16151 .fn = run_local_rbtree,
16154 .name = "LOCAL-MEMCACHE",
16155 .fn = run_local_memcache,
16158 .name = "LOCAL-STREAM-NAME",
16159 .fn = run_local_stream_name,
16162 .name = "LOCAL-STR-MATCH-MSWILD",
16163 .fn = run_str_match_mswild,
16166 .name = "LOCAL-STR-MATCH-REGEX-SUB1",
16167 .fn = run_str_match_regex_sub1,
16170 .name = "WBCLIENT-MULTI-PING",
16171 .fn = run_wbclient_multi_ping,
16174 .name = "LOCAL-string_to_sid",
16175 .fn = run_local_string_to_sid,
16178 .name = "LOCAL-sid_to_string",
16179 .fn = run_local_sid_to_string,
16182 .name = "LOCAL-binary_to_sid",
16183 .fn = run_local_binary_to_sid,
16186 .name = "LOCAL-DBTRANS",
16187 .fn = run_local_dbtrans,
16190 .name = "LOCAL-TEVENT-POLL",
16191 .fn = run_local_tevent_poll,
16194 .name = "LOCAL-CONVERT-STRING",
16195 .fn = run_local_convert_string,
16198 .name = "LOCAL-CONV-AUTH-INFO",
16199 .fn = run_local_conv_auth_info,
16202 .name = "LOCAL-hex_encode_buf",
16203 .fn = run_local_hex_encode_buf,
16206 .name = "LOCAL-IDMAP-TDB-COMMON",
16207 .fn = run_idmap_tdb_common_test,
16210 .name = "LOCAL-remove_duplicate_addrs2",
16211 .fn = run_local_remove_duplicate_addrs2,
16214 .name = "local-tdb-opener",
16215 .fn = run_local_tdb_opener,
16218 .name = "local-tdb-writer",
16219 .fn = run_local_tdb_writer,
16222 .name = "LOCAL-DBWRAP-CTDB1",
16223 .fn = run_local_dbwrap_ctdb1,
16226 .name = "LOCAL-BENCH-PTHREADPOOL",
16227 .fn = run_bench_pthreadpool,
16230 .name = "LOCAL-PTHREADPOOL-TEVENT",
16231 .fn = run_pthreadpool_tevent,
16234 .name = "LOCAL-G-LOCK1",
16235 .fn = run_g_lock1,
16238 .name = "LOCAL-G-LOCK2",
16239 .fn = run_g_lock2,
16242 .name = "LOCAL-G-LOCK3",
16243 .fn = run_g_lock3,
16246 .name = "LOCAL-G-LOCK4",
16247 .fn = run_g_lock4,
16250 .name = "LOCAL-G-LOCK4A",
16251 .fn = run_g_lock4a,
16254 .name = "LOCAL-G-LOCK5",
16255 .fn = run_g_lock5,
16258 .name = "LOCAL-G-LOCK6",
16259 .fn = run_g_lock6,
16262 .name = "LOCAL-G-LOCK7",
16263 .fn = run_g_lock7,
16266 .name = "LOCAL-G-LOCK8",
16267 .fn = run_g_lock8,
16270 .name = "LOCAL-G-LOCK-PING-PONG",
16271 .fn = run_g_lock_ping_pong,
16274 .name = "LOCAL-CANONICALIZE-PATH",
16275 .fn = run_local_canonicalize_path,
16278 .name = "LOCAL-NAMEMAP-CACHE1",
16279 .fn = run_local_namemap_cache1,
16282 .name = "LOCAL-IDMAP-CACHE1",
16283 .fn = run_local_idmap_cache1,
16286 .name = "qpathinfo-bufsize",
16287 .fn = run_qpathinfo_bufsize,
16290 .name = "hide-new-files-timeout",
16291 .fn = run_hidenewfiles,
16294 .name = "hide-new-files-timeout-showdirs",
16295 .fn = run_hidenewfiles_showdirs,
16297 #ifdef CLUSTER_SUPPORT
16299 .name = "ctdbd-conn1",
16300 .fn = run_ctdbd_conn1,
16302 #endif
16304 .name = "readdir-timestamp",
16305 .fn = run_readdir_timestamp,
16308 .name = "rpc-scale",
16309 .fn = run_rpc_scale,
16312 .name = "LOCAL-TDB-VALIDATE",
16313 .fn = run_tdb_validate,
16316 .name = NULL,
16320 /****************************************************************************
16321 run a specified test or "ALL"
16322 ****************************************************************************/
16323 static bool run_test(const char *name)
16325 bool ret = True;
16326 bool result = True;
16327 bool found = False;
16328 int i;
16329 double t;
16330 if (strequal(name,"ALL")) {
16331 for (i=0;torture_ops[i].name;i++) {
16332 run_test(torture_ops[i].name);
16334 found = True;
16337 for (i=0;torture_ops[i].name;i++) {
16338 fstr_sprintf(randomfname, "\\XX%x",
16339 (unsigned)random());
16341 if (strequal(name, torture_ops[i].name)) {
16342 found = True;
16343 printf("Running %s\n", name);
16344 if (torture_ops[i].flags & FLAG_MULTIPROC) {
16345 t = create_procs(torture_ops[i].fn, &result);
16346 if (!result) {
16347 ret = False;
16348 printf("TEST %s FAILED!\n", name);
16350 } else {
16351 struct timeval start;
16352 start = timeval_current();
16353 if (!torture_ops[i].fn(0)) {
16354 ret = False;
16355 printf("TEST %s FAILED!\n", name);
16357 t = timeval_elapsed(&start);
16359 printf("%s took %g secs\n\n", name, t);
16363 if (!found) {
16364 printf("Did not find a test named %s\n", name);
16365 ret = False;
16368 return ret;
16372 static void usage(void)
16374 int i;
16376 printf("WARNING samba4 test suite is much more complete nowadays.\n");
16377 printf("Please use samba4 torture.\n\n");
16379 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
16381 printf("\t-d debuglevel\n");
16382 printf("\t-U user%%pass\n");
16383 printf("\t-k use kerberos\n");
16384 printf("\t-N numprocs\n");
16385 printf("\t-n my_netbios_name\n");
16386 printf("\t-W workgroup\n");
16387 printf("\t-o num_operations\n");
16388 printf("\t-O socket_options\n");
16389 printf("\t-m maximum protocol\n");
16390 printf("\t-L use oplocks\n");
16391 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
16392 printf("\t-A showall\n");
16393 printf("\t-p port\n");
16394 printf("\t-s seed\n");
16395 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
16396 printf("\t-f filename filename to test\n");
16397 printf("\t-e encrypt\n");
16398 printf("\t-T 'OPTION=VALUE' smb.conf option line\n");
16399 printf("\n\n");
16401 printf("tests are:");
16402 for (i=0;torture_ops[i].name;i++) {
16403 printf(" %s", torture_ops[i].name);
16405 printf("\n");
16407 printf("default test is ALL\n");
16409 exit(1);
16412 /****************************************************************************
16413 main program
16414 ****************************************************************************/
16415 int main(int argc,char *argv[])
16417 int opt, i;
16418 char *p;
16419 int gotuser = 0;
16420 int gotpass = 0;
16421 bool correct = True;
16422 TALLOC_CTX *frame = talloc_stackframe();
16423 int seed = time(NULL);
16424 struct loadparm_context *lp_ctx = NULL;
16426 #ifdef HAVE_SETBUFFER
16427 setbuffer(stdout, NULL, 0);
16428 #endif
16430 setup_logging("smbtorture", DEBUG_STDOUT);
16432 smb_init_locale();
16433 fault_setup();
16435 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
16436 if (lp_ctx == NULL) {
16437 fprintf(stderr,
16438 "Failed to initialise the global parameter structure.\n");
16439 return 1;
16442 if (is_default_dyn_CONFIGFILE()) {
16443 if(getenv("SMB_CONF_PATH")) {
16444 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
16447 lp_load_global(get_dyn_CONFIGFILE());
16448 load_interfaces();
16450 if (argc < 2) {
16451 usage();
16454 for(p = argv[1]; *p; p++)
16455 if(*p == '\\')
16456 *p = '/';
16458 if (strncmp(argv[1], "//", 2)) {
16459 usage();
16462 fstrcpy(host, &argv[1][2]);
16463 p = strchr_m(&host[2],'/');
16464 if (!p) {
16465 usage();
16467 *p = 0;
16468 fstrcpy(share, p+1);
16470 fstrcpy(myname, get_myname(talloc_tos()));
16471 if (!*myname) {
16472 fprintf(stderr, "Failed to get my hostname.\n");
16473 return 1;
16476 if (*username == 0 && getenv("LOGNAME")) {
16477 fstrcpy(username,getenv("LOGNAME"));
16480 argc--;
16481 argv++;
16483 fstrcpy(workgroup, lp_workgroup());
16485 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:T:"))
16486 != EOF) {
16487 switch (opt) {
16488 case 'p':
16489 port_to_use = atoi(optarg);
16490 break;
16491 case 's':
16492 seed = atoi(optarg);
16493 break;
16494 case 'W':
16495 fstrcpy(workgroup,optarg);
16496 break;
16497 case 'm':
16498 lpcfg_set_cmdline(lp_ctx, "client max protocol", optarg);
16499 break;
16500 case 'N':
16501 torture_nprocs = atoi(optarg);
16502 break;
16503 case 'o':
16504 torture_numops = atoi(optarg);
16505 break;
16506 case 'd':
16507 lpcfg_set_cmdline(lp_ctx, "log level", optarg);
16508 break;
16509 case 'O':
16510 sockops = optarg;
16511 break;
16512 case 'L':
16513 use_oplocks = True;
16514 break;
16515 case 'l':
16516 local_path = optarg;
16517 break;
16518 case 'A':
16519 torture_showall = True;
16520 break;
16521 case 'n':
16522 fstrcpy(myname, optarg);
16523 break;
16524 case 'c':
16525 client_txt = optarg;
16526 break;
16527 case 'e':
16528 do_encrypt = true;
16529 break;
16530 case 'k':
16531 #ifdef HAVE_KRB5
16532 use_kerberos = True;
16533 #else
16534 d_printf("No kerberos support compiled in\n");
16535 exit(1);
16536 #endif
16537 break;
16538 case 'U':
16539 gotuser = 1;
16540 fstrcpy(username,optarg);
16541 p = strchr_m(username,'%');
16542 if (p) {
16543 *p = 0;
16544 fstrcpy(password, p+1);
16545 gotpass = 1;
16547 break;
16548 case 'b':
16549 fstrcpy(multishare_conn_fname, optarg);
16550 use_multishare_conn = True;
16551 break;
16552 case 'B':
16553 torture_blocksize = atoi(optarg);
16554 break;
16555 case 'f':
16556 test_filename = SMB_STRDUP(optarg);
16557 break;
16558 case 'T':
16559 lpcfg_set_option(lp_ctx, optarg);
16560 break;
16561 default:
16562 printf("Unknown option %c (%d)\n", (char)opt, opt);
16563 usage();
16567 d_printf("using seed %d\n", seed);
16569 srandom(seed);
16571 if(use_kerberos && !gotuser) gotpass = True;
16573 while (!gotpass) {
16574 char pwd[256] = {0};
16575 int rc;
16577 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
16578 if (rc == 0) {
16579 fstrcpy(password, pwd);
16580 gotpass = 1;
16584 reopen_logs();
16586 printf("host=%s share=%s user=%s myname=%s\n",
16587 host, share, username, myname);
16589 torture_creds = cli_session_creds_init(frame,
16590 username,
16591 workgroup,
16592 NULL, /* realm */
16593 password,
16594 use_kerberos,
16595 false, /* fallback_after_kerberos */
16596 false, /* use_ccache */
16597 false); /* password_is_nt_hash */
16598 if (torture_creds == NULL) {
16599 d_printf("cli_session_creds_init() failed.\n");
16600 exit(1);
16603 if (argc == optind) {
16604 correct = run_test("ALL");
16605 } else {
16606 for (i=optind;i<argc;i++) {
16607 if (!run_test(argv[i])) {
16608 correct = False;
16613 TALLOC_FREE(frame);
16615 if (correct) {
16616 return(0);
16617 } else {
16618 return(1);