s3: torture: Add a test doing an SMB1 negotiate+exit.
[Samba.git] / source3 / torture / torture.c
blob1e496e74456ad17543d876cd040f2393916a8710
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 "../librpc/gen_ndr/svcctl.h"
31 #include "../lib/util/memcache.h"
32 #include "nsswitch/winbind_client.h"
33 #include "dbwrap/dbwrap.h"
34 #include "dbwrap/dbwrap_open.h"
35 #include "dbwrap/dbwrap_rbt.h"
36 #include "async_smb.h"
37 #include "libsmb/libsmb.h"
38 #include "libsmb/clirap.h"
39 #include "trans2.h"
40 #include "libsmb/nmblib.h"
41 #include "../lib/util/tevent_ntstatus.h"
42 #include "util_tdb.h"
43 #include "../libcli/smb/read_smb.h"
44 #include "../libcli/smb/smbXcli_base.h"
45 #include "lib/util/sys_rw_data.h"
46 #include "lib/util/base64.h"
47 #include "lib/util/time.h"
48 #include "lib/gencache.h"
49 #include "lib/util/sys_rw.h"
50 #include "lib/util/asn1.h"
51 #include "lib/param/param.h"
52 #include "auth/gensec/gensec.h"
53 #include "lib/util/string_wrappers.h"
54 #include "source3/lib/substitute.h"
56 #include <gnutls/gnutls.h>
57 #include <gnutls/crypto.h>
59 extern char *optarg;
60 extern int optind;
62 fstring host, workgroup, share, password, username, myname;
63 struct cli_credentials *torture_creds;
64 static const char *sockops="TCP_NODELAY";
65 int torture_nprocs=1;
66 static int port_to_use=0;
67 int torture_numops=100;
68 int torture_blocksize=1024*1024;
69 static int procnum; /* records process count number when forking */
70 static struct cli_state *current_cli;
71 static fstring randomfname;
72 static bool use_oplocks;
73 static bool use_level_II_oplocks;
74 static const char *client_txt = "client_oplocks.txt";
75 static bool disable_spnego;
76 static bool use_kerberos;
77 static bool force_dos_errors;
78 static fstring multishare_conn_fname;
79 static bool use_multishare_conn = False;
80 static bool do_encrypt;
81 static const char *local_path = NULL;
82 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
83 char *test_filename;
85 bool torture_showall = False;
87 static double create_procs(bool (*fn)(int), bool *result);
89 /********************************************************************
90 Ensure a connection is encrypted.
91 ********************************************************************/
93 static bool force_cli_encryption(struct cli_state *c,
94 const char *sharename)
96 uint16_t major, minor;
97 uint32_t caplow, caphigh;
98 NTSTATUS status;
100 if (!SERVER_HAS_UNIX_CIFS(c)) {
101 d_printf("Encryption required and "
102 "server that doesn't support "
103 "UNIX extensions - failing connect\n");
104 return false;
107 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
108 &caphigh);
109 if (!NT_STATUS_IS_OK(status)) {
110 d_printf("Encryption required and "
111 "can't get UNIX CIFS extensions "
112 "version from server: %s\n", nt_errstr(status));
113 return false;
116 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
117 d_printf("Encryption required and "
118 "share %s doesn't support "
119 "encryption.\n", sharename);
120 return false;
123 status = cli_smb1_setup_encryption(c, torture_creds);
124 if (!NT_STATUS_IS_OK(status)) {
125 d_printf("Encryption required and "
126 "setup failed with error %s.\n",
127 nt_errstr(status));
128 return false;
131 return true;
135 static struct cli_state *open_nbt_connection(void)
137 struct cli_state *c;
138 NTSTATUS status;
139 int flags = 0;
141 if (disable_spnego) {
142 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
145 if (use_oplocks) {
146 flags |= CLI_FULL_CONNECTION_OPLOCKS;
149 if (use_level_II_oplocks) {
150 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
153 if (force_dos_errors) {
154 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
157 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
158 signing_state, flags, &c);
159 if (!NT_STATUS_IS_OK(status)) {
160 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
161 return NULL;
164 cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
166 return c;
169 /****************************************************************************
170 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
171 ****************************************************************************/
173 static bool cli_bad_session_request(int fd,
174 struct nmb_name *calling, struct nmb_name *called)
176 TALLOC_CTX *frame;
177 uint8_t len_buf[4];
178 struct iovec iov[3];
179 ssize_t len;
180 uint8_t *inbuf;
181 int err;
182 bool ret = false;
183 uint8_t message_type;
184 uint8_t error;
185 struct tevent_context *ev;
186 struct tevent_req *req;
188 frame = talloc_stackframe();
190 iov[0].iov_base = len_buf;
191 iov[0].iov_len = sizeof(len_buf);
193 /* put in the destination name */
195 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
196 called->name_type);
197 if (iov[1].iov_base == NULL) {
198 goto fail;
200 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
201 talloc_get_size(iov[1].iov_base));
203 /* and my name */
205 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
206 calling->name_type);
207 if (iov[2].iov_base == NULL) {
208 goto fail;
210 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
211 talloc_get_size(iov[2].iov_base));
213 /* Deliberately corrupt the name len (first byte) */
214 *((uint8_t *)iov[2].iov_base) = 100;
216 /* send a session request (RFC 1002) */
217 /* setup the packet length
218 * Remove four bytes from the length count, since the length
219 * field in the NBT Session Service header counts the number
220 * of bytes which follow. The cli_send_smb() function knows
221 * about this and accounts for those four bytes.
222 * CRH.
225 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
226 SCVAL(len_buf,0,0x81);
228 len = write_data_iov(fd, iov, 3);
229 if (len == -1) {
230 goto fail;
233 ev = samba_tevent_context_init(frame);
234 if (ev == NULL) {
235 goto fail;
237 req = read_smb_send(frame, ev, fd);
238 if (req == NULL) {
239 goto fail;
241 if (!tevent_req_poll(req, ev)) {
242 goto fail;
244 len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
245 if (len == -1) {
246 errno = err;
247 goto fail;
249 TALLOC_FREE(ev);
251 message_type = CVAL(inbuf, 0);
252 if (message_type != 0x83) {
253 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
254 message_type);
255 goto fail;
258 if (smb_len(inbuf) != 1) {
259 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
260 (int)smb_len(inbuf));
261 goto fail;
264 error = CVAL(inbuf, 4);
265 if (error != 0x82) {
266 d_fprintf(stderr, "Expected error 0x82, got %d\n",
267 (int)error);
268 goto fail;
271 ret = true;
272 fail:
273 TALLOC_FREE(frame);
274 return ret;
277 /* Insert a NULL at the first separator of the given path and return a pointer
278 * to the remainder of the string.
280 static char *
281 terminate_path_at_separator(char * path)
283 char * p;
285 if (!path) {
286 return NULL;
289 if ((p = strchr_m(path, '/'))) {
290 *p = '\0';
291 return p + 1;
294 if ((p = strchr_m(path, '\\'))) {
295 *p = '\0';
296 return p + 1;
299 /* No separator. */
300 return NULL;
304 parse a //server/share type UNC name
306 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
307 char **hostname, char **sharename)
309 char *p;
311 *hostname = *sharename = NULL;
313 if (strncmp(unc_name, "\\\\", 2) &&
314 strncmp(unc_name, "//", 2)) {
315 return False;
318 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
319 p = terminate_path_at_separator(*hostname);
321 if (p && *p) {
322 *sharename = talloc_strdup(mem_ctx, p);
323 terminate_path_at_separator(*sharename);
326 if (*hostname && *sharename) {
327 return True;
330 TALLOC_FREE(*hostname);
331 TALLOC_FREE(*sharename);
332 return False;
335 static bool torture_open_connection_share(struct cli_state **c,
336 const char *hostname,
337 const char *sharename,
338 int flags)
340 NTSTATUS status;
342 status = cli_full_connection_creds(c,
343 myname,
344 hostname,
345 NULL, /* dest_ss */
346 port_to_use,
347 sharename,
348 "?????",
349 torture_creds,
350 flags);
351 if (!NT_STATUS_IS_OK(status)) {
352 printf("failed to open share connection: //%s/%s port:%d - %s\n",
353 hostname, sharename, port_to_use, nt_errstr(status));
354 return False;
357 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
359 if (do_encrypt) {
360 return force_cli_encryption(*c,
361 sharename);
363 return True;
366 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
368 char **unc_list = NULL;
369 int num_unc_names = 0;
370 bool result;
372 if (use_multishare_conn==True) {
373 char *h, *s;
374 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
375 if (!unc_list || num_unc_names <= 0) {
376 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
377 exit(1);
380 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
381 NULL, &h, &s)) {
382 printf("Failed to parse UNC name %s\n",
383 unc_list[conn_index % num_unc_names]);
384 TALLOC_FREE(unc_list);
385 exit(1);
388 result = torture_open_connection_share(c, h, s, flags);
390 /* h, s were copied earlier */
391 TALLOC_FREE(unc_list);
392 return result;
395 return torture_open_connection_share(c, host, share, flags);
398 bool torture_open_connection(struct cli_state **c, int conn_index)
400 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
402 if (use_oplocks) {
403 flags |= CLI_FULL_CONNECTION_OPLOCKS;
405 if (use_level_II_oplocks) {
406 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
409 return torture_open_connection_flags(c, conn_index, flags);
412 bool torture_init_connection(struct cli_state **pcli)
414 struct cli_state *cli;
416 cli = open_nbt_connection();
417 if (cli == NULL) {
418 return false;
421 *pcli = cli;
422 return true;
425 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
427 uint16_t old_vuid = cli_state_get_uid(cli);
428 NTSTATUS status;
429 bool ret;
431 cli_state_set_uid(cli, 0);
432 status = cli_session_setup_creds(cli, torture_creds);
433 ret = NT_STATUS_IS_OK(status);
434 *new_vuid = cli_state_get_uid(cli);
435 cli_state_set_uid(cli, old_vuid);
436 return ret;
440 bool torture_close_connection(struct cli_state *c)
442 bool ret = True;
443 NTSTATUS status;
445 status = cli_tdis(c);
446 if (!NT_STATUS_IS_OK(status)) {
447 printf("tdis failed (%s)\n", nt_errstr(status));
448 ret = False;
451 cli_shutdown(c);
453 return ret;
456 void torture_conn_set_sockopt(struct cli_state *cli)
458 smbXcli_conn_set_sockopt(cli->conn, sockops);
461 static NTSTATUS torture_delete_fn(struct file_info *finfo,
462 const char *pattern,
463 void *state)
465 NTSTATUS status;
466 char *filename = NULL;
467 char *dirname = NULL;
468 char *p = NULL;
469 TALLOC_CTX *frame = talloc_stackframe();
470 struct cli_state *cli = (struct cli_state *)state;
472 if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
473 TALLOC_FREE(frame);
474 return NT_STATUS_OK;
477 dirname = talloc_strdup(frame, pattern);
478 if (dirname == NULL) {
479 TALLOC_FREE(frame);
480 return NT_STATUS_NO_MEMORY;
482 p = strrchr_m(dirname, '\\');
483 if (p != NULL) {
484 /* Remove the terminating '\' */
485 *p = '\0';
487 if (dirname[0] != '\0') {
488 filename = talloc_asprintf(frame,
489 "%s\\%s",
490 dirname,
491 finfo->name);
492 } else {
493 filename = talloc_asprintf(frame,
494 "%s",
495 finfo->name);
497 if (filename == NULL) {
498 TALLOC_FREE(frame);
499 return NT_STATUS_NO_MEMORY;
501 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
502 char *subdirname = talloc_asprintf(frame,
503 "%s\\*",
504 filename);
505 if (subdirname == NULL) {
506 TALLOC_FREE(frame);
507 return NT_STATUS_NO_MEMORY;
509 status = cli_list(cli,
510 subdirname,
511 FILE_ATTRIBUTE_DIRECTORY |
512 FILE_ATTRIBUTE_HIDDEN |
513 FILE_ATTRIBUTE_SYSTEM,
514 torture_delete_fn,
515 cli);
516 if (!NT_STATUS_IS_OK(status)) {
517 printf("torture_delete_fn: cli_list "
518 "of %s failed (%s)\n",
519 subdirname,
520 nt_errstr(status));
521 TALLOC_FREE(frame);
522 return status;
524 status = cli_rmdir(cli, filename);
525 } else {
526 status = cli_unlink(cli,
527 filename,
528 FILE_ATTRIBUTE_SYSTEM |
529 FILE_ATTRIBUTE_HIDDEN);
531 if (!NT_STATUS_IS_OK(status)) {
532 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
533 printf("torture_delete_fn: cli_rmdir"
534 " of %s failed (%s)\n",
535 filename,
536 nt_errstr(status));
537 } else {
538 printf("torture_delete_fn: cli_unlink"
539 " of %s failed (%s)\n",
540 filename,
541 nt_errstr(status));
544 TALLOC_FREE(frame);
545 return status;
548 void torture_deltree(struct cli_state *cli, const char *dname)
550 char *mask = NULL;
551 NTSTATUS status;
553 /* It might be a file */
554 (void)cli_unlink(cli,
555 dname,
556 FILE_ATTRIBUTE_SYSTEM |
557 FILE_ATTRIBUTE_HIDDEN);
559 mask = talloc_asprintf(cli,
560 "%s\\*",
561 dname);
562 if (mask == NULL) {
563 printf("torture_deltree: talloc_asprintf failed\n");
564 return;
567 status = cli_list(cli,
568 mask,
569 FILE_ATTRIBUTE_DIRECTORY |
570 FILE_ATTRIBUTE_HIDDEN|
571 FILE_ATTRIBUTE_SYSTEM,
572 torture_delete_fn,
573 cli);
574 if (!NT_STATUS_IS_OK(status)) {
575 printf("torture_deltree: cli_list of %s failed (%s)\n",
576 mask,
577 nt_errstr(status));
579 TALLOC_FREE(mask);
580 status = cli_rmdir(cli, dname);
581 if (!NT_STATUS_IS_OK(status)) {
582 printf("torture_deltree: cli_rmdir of %s failed (%s)\n",
583 dname,
584 nt_errstr(status));
588 /* check if the server produced the expected dos or nt error code */
589 static bool check_both_error(int line, NTSTATUS status,
590 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
592 if (NT_STATUS_IS_DOS(status)) {
593 uint8_t cclass;
594 uint32_t num;
596 /* Check DOS error */
597 cclass = NT_STATUS_DOS_CLASS(status);
598 num = NT_STATUS_DOS_CODE(status);
600 if (eclass != cclass || ecode != num) {
601 printf("unexpected error code class=%d code=%d\n",
602 (int)cclass, (int)num);
603 printf(" expected %d/%d %s (line=%d)\n",
604 (int)eclass, (int)ecode, nt_errstr(nterr), line);
605 return false;
607 } else {
608 /* Check NT error */
609 if (!NT_STATUS_EQUAL(nterr, status)) {
610 printf("unexpected error code %s\n",
611 nt_errstr(status));
612 printf(" expected %s (line=%d)\n",
613 nt_errstr(nterr), line);
614 return false;
618 return true;
622 /* check if the server produced the expected error code */
623 static bool check_error(int line, NTSTATUS status,
624 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
626 if (NT_STATUS_IS_DOS(status)) {
627 uint8_t cclass;
628 uint32_t num;
630 /* Check DOS error */
632 cclass = NT_STATUS_DOS_CLASS(status);
633 num = NT_STATUS_DOS_CODE(status);
635 if (eclass != cclass || ecode != num) {
636 printf("unexpected error code class=%d code=%d\n",
637 (int)cclass, (int)num);
638 printf(" expected %d/%d %s (line=%d)\n",
639 (int)eclass, (int)ecode, nt_errstr(nterr),
640 line);
641 return False;
644 } else {
645 /* Check NT error */
647 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
648 printf("unexpected error code %s\n",
649 nt_errstr(status));
650 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
651 line);
652 return False;
656 return True;
660 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
662 NTSTATUS status;
664 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
666 while (!NT_STATUS_IS_OK(status)) {
667 if (!check_both_error(__LINE__, status, ERRDOS,
668 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
669 return false;
672 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
675 return true;
679 static bool rw_torture(struct cli_state *c)
681 const char *lockfname = "\\torture.lck";
682 fstring fname;
683 uint16_t fnum;
684 uint16_t fnum2;
685 pid_t pid2, pid = getpid();
686 int i, j;
687 char buf[1024];
688 bool correct = True;
689 size_t nread = 0;
690 NTSTATUS status;
692 memset(buf, '\0', sizeof(buf));
694 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
695 DENY_NONE, &fnum2);
696 if (!NT_STATUS_IS_OK(status)) {
697 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
699 if (!NT_STATUS_IS_OK(status)) {
700 printf("open of %s failed (%s)\n",
701 lockfname, nt_errstr(status));
702 return False;
705 for (i=0;i<torture_numops;i++) {
706 unsigned n = (unsigned)sys_random()%10;
708 if (i % 10 == 0) {
709 printf("%d\r", i); fflush(stdout);
711 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
713 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
714 return False;
717 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
718 DENY_ALL, &fnum);
719 if (!NT_STATUS_IS_OK(status)) {
720 printf("open failed (%s)\n", nt_errstr(status));
721 correct = False;
722 break;
725 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
726 sizeof(pid), NULL);
727 if (!NT_STATUS_IS_OK(status)) {
728 printf("write failed (%s)\n", nt_errstr(status));
729 correct = False;
732 for (j=0;j<50;j++) {
733 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
734 sizeof(pid)+(j*sizeof(buf)),
735 sizeof(buf), NULL);
736 if (!NT_STATUS_IS_OK(status)) {
737 printf("write failed (%s)\n",
738 nt_errstr(status));
739 correct = False;
743 pid2 = 0;
745 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
746 &nread);
747 if (!NT_STATUS_IS_OK(status)) {
748 printf("read failed (%s)\n", nt_errstr(status));
749 correct = false;
750 } else if (nread != sizeof(pid)) {
751 printf("read/write compare failed: "
752 "recv %ld req %ld\n", (unsigned long)nread,
753 (unsigned long)sizeof(pid));
754 correct = false;
757 if (pid2 != pid) {
758 printf("data corruption!\n");
759 correct = False;
762 status = cli_close(c, fnum);
763 if (!NT_STATUS_IS_OK(status)) {
764 printf("close failed (%s)\n", nt_errstr(status));
765 correct = False;
768 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
769 if (!NT_STATUS_IS_OK(status)) {
770 printf("unlink failed (%s)\n", nt_errstr(status));
771 correct = False;
774 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
775 if (!NT_STATUS_IS_OK(status)) {
776 printf("unlock failed (%s)\n", nt_errstr(status));
777 correct = False;
781 cli_close(c, fnum2);
782 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
784 printf("%d\n", i);
786 return correct;
789 static bool run_torture(int dummy)
791 struct cli_state *cli;
792 bool ret;
794 cli = current_cli;
796 smbXcli_conn_set_sockopt(cli->conn, sockops);
798 ret = rw_torture(cli);
800 if (!torture_close_connection(cli)) {
801 ret = False;
804 return ret;
807 static bool rw_torture3(struct cli_state *c, char *lockfname)
809 uint16_t fnum = (uint16_t)-1;
810 unsigned int i = 0;
811 char buf[131072];
812 char buf_rd[131072];
813 unsigned count;
814 unsigned countprev = 0;
815 size_t sent = 0;
816 bool correct = True;
817 NTSTATUS status = NT_STATUS_OK;
819 srandom(1);
820 for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
822 SIVAL(buf, i, sys_random());
825 if (procnum == 0)
827 status = cli_unlink(
828 c, lockfname,
829 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
830 if (!NT_STATUS_IS_OK(status)) {
831 printf("unlink failed (%s) (normal, this file should "
832 "not exist)\n", nt_errstr(status));
835 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
836 DENY_NONE, &fnum);
837 if (!NT_STATUS_IS_OK(status)) {
838 printf("first open read/write of %s failed (%s)\n",
839 lockfname, nt_errstr(status));
840 return False;
843 else
845 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
847 status = cli_openx(c, lockfname, O_RDONLY,
848 DENY_NONE, &fnum);
849 if (NT_STATUS_IS_OK(status)) {
850 break;
852 smb_msleep(10);
854 if (!NT_STATUS_IS_OK(status)) {
855 printf("second open read-only of %s failed (%s)\n",
856 lockfname, nt_errstr(status));
857 return False;
861 i = 0;
862 for (count = 0; count < sizeof(buf); count += sent)
864 if (count >= countprev) {
865 printf("%d %8d\r", i, count);
866 fflush(stdout);
867 i++;
868 countprev += (sizeof(buf) / 20);
871 if (procnum == 0)
873 sent = ((unsigned)sys_random()%(20))+ 1;
874 if (sent > sizeof(buf) - count)
876 sent = sizeof(buf) - count;
879 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
880 count, sent, NULL);
881 if (!NT_STATUS_IS_OK(status)) {
882 printf("write failed (%s)\n",
883 nt_errstr(status));
884 correct = False;
887 else
889 status = cli_read(c, fnum, buf_rd+count, count,
890 sizeof(buf)-count, &sent);
891 if(!NT_STATUS_IS_OK(status)) {
892 printf("read failed offset:%d size:%ld (%s)\n",
893 count, (unsigned long)sizeof(buf)-count,
894 nt_errstr(status));
895 correct = False;
896 sent = 0;
897 } else if (sent > 0) {
898 if (memcmp(buf_rd+count, buf+count, sent) != 0)
900 printf("read/write compare failed\n");
901 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
902 correct = False;
903 break;
910 status = cli_close(c, fnum);
911 if (!NT_STATUS_IS_OK(status)) {
912 printf("close failed (%s)\n", nt_errstr(status));
913 correct = False;
916 return correct;
919 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
921 const char *lockfname = "\\torture2.lck";
922 uint16_t fnum1;
923 uint16_t fnum2;
924 int i;
925 char buf[131072];
926 char buf_rd[131072];
927 bool correct = True;
928 size_t bytes_read;
929 NTSTATUS status;
931 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
932 if (!NT_STATUS_IS_OK(status)) {
933 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
936 status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
937 DENY_NONE, &fnum1);
938 if (!NT_STATUS_IS_OK(status)) {
939 printf("first open read/write of %s failed (%s)\n",
940 lockfname, nt_errstr(status));
941 return False;
944 status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
945 if (!NT_STATUS_IS_OK(status)) {
946 printf("second open read-only of %s failed (%s)\n",
947 lockfname, nt_errstr(status));
948 cli_close(c1, fnum1);
949 return False;
952 for (i = 0; i < torture_numops; i++)
954 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
955 if (i % 10 == 0) {
956 printf("%d\r", i); fflush(stdout);
959 generate_random_buffer((unsigned char *)buf, buf_size);
961 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
962 buf_size, NULL);
963 if (!NT_STATUS_IS_OK(status)) {
964 printf("write failed (%s)\n", nt_errstr(status));
965 correct = False;
966 break;
969 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
970 if(!NT_STATUS_IS_OK(status)) {
971 printf("read failed (%s)\n", nt_errstr(status));
972 correct = false;
973 break;
974 } else if (bytes_read != buf_size) {
975 printf("read failed\n");
976 printf("read %ld, expected %ld\n",
977 (unsigned long)bytes_read,
978 (unsigned long)buf_size);
979 correct = False;
980 break;
983 if (memcmp(buf_rd, buf, buf_size) != 0)
985 printf("read/write compare failed\n");
986 correct = False;
987 break;
991 status = cli_close(c2, fnum2);
992 if (!NT_STATUS_IS_OK(status)) {
993 printf("close failed (%s)\n", nt_errstr(status));
994 correct = False;
997 status = cli_close(c1, fnum1);
998 if (!NT_STATUS_IS_OK(status)) {
999 printf("close failed (%s)\n", nt_errstr(status));
1000 correct = False;
1003 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1004 if (!NT_STATUS_IS_OK(status)) {
1005 printf("unlink failed (%s)\n", nt_errstr(status));
1006 correct = False;
1009 return correct;
1012 static bool run_readwritetest(int dummy)
1014 struct cli_state *cli1, *cli2;
1015 bool test1, test2 = False;
1017 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1018 return False;
1020 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1021 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1023 printf("starting readwritetest\n");
1025 test1 = rw_torture2(cli1, cli2);
1026 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
1028 if (test1) {
1029 test2 = rw_torture2(cli1, cli1);
1030 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
1033 if (!torture_close_connection(cli1)) {
1034 test1 = False;
1037 if (!torture_close_connection(cli2)) {
1038 test2 = False;
1041 return (test1 && test2);
1044 static bool run_readwritemulti(int dummy)
1046 struct cli_state *cli;
1047 bool test;
1049 cli = current_cli;
1051 smbXcli_conn_set_sockopt(cli->conn, sockops);
1053 printf("run_readwritemulti: fname %s\n", randomfname);
1054 test = rw_torture3(cli, randomfname);
1056 if (!torture_close_connection(cli)) {
1057 test = False;
1060 return test;
1063 static bool run_readwritelarge_internal(void)
1065 static struct cli_state *cli1;
1066 uint16_t fnum1;
1067 const char *lockfname = "\\large.dat";
1068 off_t fsize;
1069 char buf[126*1024];
1070 bool correct = True;
1071 NTSTATUS status;
1073 if (!torture_open_connection(&cli1, 0)) {
1074 return False;
1076 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1077 memset(buf,'\0',sizeof(buf));
1079 printf("starting readwritelarge_internal\n");
1081 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1083 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1084 DENY_NONE, &fnum1);
1085 if (!NT_STATUS_IS_OK(status)) {
1086 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1087 return False;
1090 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1092 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1093 NULL, NULL, NULL);
1094 if (!NT_STATUS_IS_OK(status)) {
1095 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1096 correct = False;
1099 if (fsize == sizeof(buf))
1100 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1101 (unsigned long)fsize);
1102 else {
1103 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1104 (unsigned long)fsize);
1105 correct = False;
1108 status = cli_close(cli1, fnum1);
1109 if (!NT_STATUS_IS_OK(status)) {
1110 printf("close failed (%s)\n", nt_errstr(status));
1111 correct = False;
1114 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1115 if (!NT_STATUS_IS_OK(status)) {
1116 printf("unlink failed (%s)\n", nt_errstr(status));
1117 correct = False;
1120 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1121 DENY_NONE, &fnum1);
1122 if (!NT_STATUS_IS_OK(status)) {
1123 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1124 return False;
1127 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1129 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1130 NULL, NULL, NULL);
1131 if (!NT_STATUS_IS_OK(status)) {
1132 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1133 correct = False;
1136 if (fsize == sizeof(buf))
1137 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1138 (unsigned long)fsize);
1139 else {
1140 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1141 (unsigned long)fsize);
1142 correct = False;
1145 status = cli_close(cli1, fnum1);
1146 if (!NT_STATUS_IS_OK(status)) {
1147 printf("close failed (%s)\n", nt_errstr(status));
1148 correct = False;
1151 if (!torture_close_connection(cli1)) {
1152 correct = False;
1154 return correct;
1157 static bool run_readwritelarge(int dummy)
1159 return run_readwritelarge_internal();
1162 static bool run_readwritelarge_signtest(int dummy)
1164 bool ret;
1165 signing_state = SMB_SIGNING_REQUIRED;
1166 ret = run_readwritelarge_internal();
1167 signing_state = SMB_SIGNING_DEFAULT;
1168 return ret;
1171 int line_count = 0;
1172 int nbio_id;
1174 #define ival(s) strtol(s, NULL, 0)
1176 /* run a test that simulates an approximate netbench client load */
1177 static bool run_netbench(int client)
1179 struct cli_state *cli;
1180 int i;
1181 char line[1024];
1182 char cname[20];
1183 FILE *f;
1184 const char *params[20];
1185 bool correct = True;
1187 cli = current_cli;
1189 nbio_id = client;
1191 smbXcli_conn_set_sockopt(cli->conn, sockops);
1193 nb_setup(cli);
1195 slprintf(cname,sizeof(cname)-1, "client%d", client);
1197 f = fopen(client_txt, "r");
1199 if (!f) {
1200 perror(client_txt);
1201 return False;
1204 while (fgets(line, sizeof(line)-1, f)) {
1205 char *saveptr;
1206 line_count++;
1208 line[strlen(line)-1] = 0;
1210 /* printf("[%d] %s\n", line_count, line); */
1212 all_string_sub(line,"client1", cname, sizeof(line));
1214 /* parse the command parameters */
1215 params[0] = strtok_r(line, " ", &saveptr);
1216 i = 0;
1217 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1219 params[i] = "";
1221 if (i < 2) continue;
1223 if (!strncmp(params[0],"SMB", 3)) {
1224 printf("ERROR: You are using a dbench 1 load file\n");
1225 exit(1);
1228 if (!strcmp(params[0],"NTCreateX")) {
1229 nb_createx(params[1], ival(params[2]), ival(params[3]),
1230 ival(params[4]));
1231 } else if (!strcmp(params[0],"Close")) {
1232 nb_close(ival(params[1]));
1233 } else if (!strcmp(params[0],"Rename")) {
1234 nb_rename(params[1], params[2]);
1235 } else if (!strcmp(params[0],"Unlink")) {
1236 nb_unlink(params[1]);
1237 } else if (!strcmp(params[0],"Deltree")) {
1238 nb_deltree(params[1]);
1239 } else if (!strcmp(params[0],"Rmdir")) {
1240 nb_rmdir(params[1]);
1241 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1242 nb_qpathinfo(params[1]);
1243 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1244 nb_qfileinfo(ival(params[1]));
1245 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1246 nb_qfsinfo(ival(params[1]));
1247 } else if (!strcmp(params[0],"FIND_FIRST")) {
1248 nb_findfirst(params[1]);
1249 } else if (!strcmp(params[0],"WriteX")) {
1250 nb_writex(ival(params[1]),
1251 ival(params[2]), ival(params[3]), ival(params[4]));
1252 } else if (!strcmp(params[0],"ReadX")) {
1253 nb_readx(ival(params[1]),
1254 ival(params[2]), ival(params[3]), ival(params[4]));
1255 } else if (!strcmp(params[0],"Flush")) {
1256 nb_flush(ival(params[1]));
1257 } else {
1258 printf("Unknown operation %s\n", params[0]);
1259 exit(1);
1262 fclose(f);
1264 nb_cleanup();
1266 if (!torture_close_connection(cli)) {
1267 correct = False;
1270 return correct;
1274 /* run a test that simulates an approximate netbench client load */
1275 static bool run_nbench(int dummy)
1277 double t;
1278 bool correct = True;
1280 nbio_shmem(torture_nprocs);
1282 nbio_id = -1;
1284 signal(SIGALRM, nb_alarm);
1285 alarm(1);
1286 t = create_procs(run_netbench, &correct);
1287 alarm(0);
1289 printf("\nThroughput %g MB/sec\n",
1290 1.0e-6 * nbio_total() / t);
1291 return correct;
1296 This test checks for two things:
1298 1) correct support for retaining locks over a close (ie. the server
1299 must not use posix semantics)
1300 2) support for lock timeouts
1302 static bool run_locktest1(int dummy)
1304 struct cli_state *cli1, *cli2;
1305 const char *fname = "\\lockt1.lck";
1306 uint16_t fnum1, fnum2, fnum3;
1307 time_t t1, t2;
1308 unsigned lock_timeout;
1309 NTSTATUS status;
1311 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1312 return False;
1314 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1315 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1317 printf("starting locktest1\n");
1319 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1321 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1322 &fnum1);
1323 if (!NT_STATUS_IS_OK(status)) {
1324 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1325 return False;
1328 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1329 if (!NT_STATUS_IS_OK(status)) {
1330 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1331 return False;
1334 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1335 if (!NT_STATUS_IS_OK(status)) {
1336 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1337 return False;
1340 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1341 if (!NT_STATUS_IS_OK(status)) {
1342 printf("lock1 failed (%s)\n", nt_errstr(status));
1343 return false;
1346 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1347 if (NT_STATUS_IS_OK(status)) {
1348 printf("lock2 succeeded! This is a locking bug\n");
1349 return false;
1350 } else {
1351 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1352 NT_STATUS_LOCK_NOT_GRANTED)) {
1353 return false;
1357 lock_timeout = (1 + (random() % 20));
1358 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1359 t1 = time(NULL);
1360 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1361 if (NT_STATUS_IS_OK(status)) {
1362 printf("lock3 succeeded! This is a locking bug\n");
1363 return false;
1364 } else {
1365 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1366 NT_STATUS_FILE_LOCK_CONFLICT)) {
1367 return false;
1370 t2 = time(NULL);
1372 if (ABS(t2 - t1) < lock_timeout-1) {
1373 printf("error: This server appears not to support timed lock requests\n");
1376 printf("server slept for %u seconds for a %u second timeout\n",
1377 (unsigned int)(t2-t1), lock_timeout);
1379 status = cli_close(cli1, fnum2);
1380 if (!NT_STATUS_IS_OK(status)) {
1381 printf("close1 failed (%s)\n", nt_errstr(status));
1382 return False;
1385 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1386 if (NT_STATUS_IS_OK(status)) {
1387 printf("lock4 succeeded! This is a locking bug\n");
1388 return false;
1389 } else {
1390 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1391 NT_STATUS_FILE_LOCK_CONFLICT)) {
1392 return false;
1396 status = cli_close(cli1, fnum1);
1397 if (!NT_STATUS_IS_OK(status)) {
1398 printf("close2 failed (%s)\n", nt_errstr(status));
1399 return False;
1402 status = cli_close(cli2, fnum3);
1403 if (!NT_STATUS_IS_OK(status)) {
1404 printf("close3 failed (%s)\n", nt_errstr(status));
1405 return False;
1408 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1409 if (!NT_STATUS_IS_OK(status)) {
1410 printf("unlink failed (%s)\n", nt_errstr(status));
1411 return False;
1415 if (!torture_close_connection(cli1)) {
1416 return False;
1419 if (!torture_close_connection(cli2)) {
1420 return False;
1423 printf("Passed locktest1\n");
1424 return True;
1428 this checks to see if a secondary tconx can use open files from an
1429 earlier tconx
1431 static bool run_tcon_test(int dummy)
1433 static struct cli_state *cli;
1434 const char *fname = "\\tcontest.tmp";
1435 uint16_t fnum1;
1436 uint32_t cnum1, cnum2, cnum3;
1437 struct smbXcli_tcon *orig_tcon = NULL;
1438 char *orig_share = NULL;
1439 uint16_t vuid1, vuid2;
1440 char buf[4];
1441 bool ret = True;
1442 NTSTATUS status;
1444 memset(buf, '\0', sizeof(buf));
1446 if (!torture_open_connection(&cli, 0)) {
1447 return False;
1449 smbXcli_conn_set_sockopt(cli->conn, sockops);
1451 printf("starting tcontest\n");
1453 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1455 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1456 if (!NT_STATUS_IS_OK(status)) {
1457 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1458 return False;
1461 cnum1 = cli_state_get_tid(cli);
1462 vuid1 = cli_state_get_uid(cli);
1464 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1465 if (!NT_STATUS_IS_OK(status)) {
1466 printf("initial write failed (%s)", nt_errstr(status));
1467 return False;
1470 cli_state_save_tcon_share(cli, &orig_tcon, &orig_share);
1472 status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1473 if (!NT_STATUS_IS_OK(status)) {
1474 printf("%s refused 2nd tree connect (%s)\n", host,
1475 nt_errstr(status));
1476 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1477 cli_shutdown(cli);
1478 return False;
1481 cnum2 = cli_state_get_tid(cli);
1482 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1483 vuid2 = cli_state_get_uid(cli) + 1;
1485 /* try a write with the wrong tid */
1486 cli_state_set_tid(cli, cnum2);
1488 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1489 if (NT_STATUS_IS_OK(status)) {
1490 printf("* server allows write with wrong TID\n");
1491 ret = False;
1492 } else {
1493 printf("server fails write with wrong TID : %s\n",
1494 nt_errstr(status));
1498 /* try a write with an invalid tid */
1499 cli_state_set_tid(cli, cnum3);
1501 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1502 if (NT_STATUS_IS_OK(status)) {
1503 printf("* server allows write with invalid TID\n");
1504 ret = False;
1505 } else {
1506 printf("server fails write with invalid TID : %s\n",
1507 nt_errstr(status));
1510 /* try a write with an invalid vuid */
1511 cli_state_set_uid(cli, vuid2);
1512 cli_state_set_tid(cli, cnum1);
1514 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1515 if (NT_STATUS_IS_OK(status)) {
1516 printf("* server allows write with invalid VUID\n");
1517 ret = False;
1518 } else {
1519 printf("server fails write with invalid VUID : %s\n",
1520 nt_errstr(status));
1523 cli_state_set_tid(cli, cnum1);
1524 cli_state_set_uid(cli, vuid1);
1526 status = cli_close(cli, fnum1);
1527 if (!NT_STATUS_IS_OK(status)) {
1528 printf("close failed (%s)\n", nt_errstr(status));
1529 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1530 cli_shutdown(cli);
1531 return False;
1534 cli_state_set_tid(cli, cnum2);
1536 status = cli_tdis(cli);
1537 if (!NT_STATUS_IS_OK(status)) {
1538 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1539 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1540 cli_shutdown(cli);
1541 return False;
1544 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1546 cli_state_set_tid(cli, cnum1);
1548 if (!torture_close_connection(cli)) {
1549 return False;
1552 return ret;
1557 checks for old style tcon support
1559 static bool run_tcon2_test(int dummy)
1561 static struct cli_state *cli;
1562 uint16_t cnum, max_xmit;
1563 char *service;
1564 NTSTATUS status;
1566 if (!torture_open_connection(&cli, 0)) {
1567 return False;
1569 smbXcli_conn_set_sockopt(cli->conn, sockops);
1571 printf("starting tcon2 test\n");
1573 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1574 return false;
1577 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1579 SAFE_FREE(service);
1581 if (!NT_STATUS_IS_OK(status)) {
1582 printf("tcon2 failed : %s\n", nt_errstr(status));
1583 } else {
1584 printf("tcon OK : max_xmit=%d cnum=%d\n",
1585 (int)max_xmit, (int)cnum);
1588 if (!torture_close_connection(cli)) {
1589 return False;
1592 printf("Passed tcon2 test\n");
1593 return True;
1596 static bool tcon_devtest(struct cli_state *cli,
1597 const char *myshare, const char *devtype,
1598 const char *return_devtype,
1599 NTSTATUS expected_error)
1601 NTSTATUS status;
1602 bool ret;
1604 status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1606 if (NT_STATUS_IS_OK(expected_error)) {
1607 if (NT_STATUS_IS_OK(status)) {
1608 if (return_devtype != NULL &&
1609 strequal(cli->dev, return_devtype)) {
1610 ret = True;
1611 } else {
1612 printf("tconX to share %s with type %s "
1613 "succeeded but returned the wrong "
1614 "device type (got [%s] but should have got [%s])\n",
1615 myshare, devtype, cli->dev, return_devtype);
1616 ret = False;
1618 } else {
1619 printf("tconX to share %s with type %s "
1620 "should have succeeded but failed\n",
1621 myshare, devtype);
1622 ret = False;
1624 cli_tdis(cli);
1625 } else {
1626 if (NT_STATUS_IS_OK(status)) {
1627 printf("tconx to share %s with type %s "
1628 "should have failed but succeeded\n",
1629 myshare, devtype);
1630 ret = False;
1631 } else {
1632 if (NT_STATUS_EQUAL(status, expected_error)) {
1633 ret = True;
1634 } else {
1635 printf("Returned unexpected error\n");
1636 ret = False;
1640 return ret;
1644 checks for correct tconX support
1646 static bool run_tcon_devtype_test(int dummy)
1648 static struct cli_state *cli1 = NULL;
1649 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1650 NTSTATUS status;
1651 bool ret = True;
1653 status = cli_full_connection_creds(&cli1,
1654 myname,
1655 host,
1656 NULL, /* dest_ss */
1657 port_to_use,
1658 NULL, /* service */
1659 NULL, /* service_type */
1660 torture_creds,
1661 flags);
1663 if (!NT_STATUS_IS_OK(status)) {
1664 printf("could not open connection\n");
1665 return False;
1668 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1669 ret = False;
1671 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1672 ret = False;
1674 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1675 ret = False;
1677 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1678 ret = False;
1680 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1681 ret = False;
1683 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1684 ret = False;
1686 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1687 ret = False;
1689 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1690 ret = False;
1692 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1693 ret = False;
1695 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1696 ret = False;
1698 cli_shutdown(cli1);
1700 if (ret)
1701 printf("Passed tcondevtest\n");
1703 return ret;
1708 This test checks that
1710 1) the server supports multiple locking contexts on the one SMB
1711 connection, distinguished by PID.
1713 2) the server correctly fails overlapping locks made by the same PID (this
1714 goes against POSIX behaviour, which is why it is tricky to implement)
1716 3) the server denies unlock requests by an incorrect client PID
1718 static bool run_locktest2(int dummy)
1720 static struct cli_state *cli;
1721 const char *fname = "\\lockt2.lck";
1722 uint16_t fnum1, fnum2, fnum3;
1723 bool correct = True;
1724 NTSTATUS status;
1726 if (!torture_open_connection(&cli, 0)) {
1727 return False;
1730 smbXcli_conn_set_sockopt(cli->conn, sockops);
1732 printf("starting locktest2\n");
1734 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1736 cli_setpid(cli, 1);
1738 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1739 if (!NT_STATUS_IS_OK(status)) {
1740 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1741 return False;
1744 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1745 if (!NT_STATUS_IS_OK(status)) {
1746 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1747 return False;
1750 cli_setpid(cli, 2);
1752 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1753 if (!NT_STATUS_IS_OK(status)) {
1754 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1755 return False;
1758 cli_setpid(cli, 1);
1760 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1761 if (!NT_STATUS_IS_OK(status)) {
1762 printf("lock1 failed (%s)\n", nt_errstr(status));
1763 return false;
1766 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1767 if (NT_STATUS_IS_OK(status)) {
1768 printf("WRITE lock1 succeeded! This is a locking bug\n");
1769 correct = false;
1770 } else {
1771 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1772 NT_STATUS_LOCK_NOT_GRANTED)) {
1773 return false;
1777 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1778 if (NT_STATUS_IS_OK(status)) {
1779 printf("WRITE lock2 succeeded! This is a locking bug\n");
1780 correct = false;
1781 } else {
1782 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1783 NT_STATUS_LOCK_NOT_GRANTED)) {
1784 return false;
1788 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1789 if (NT_STATUS_IS_OK(status)) {
1790 printf("READ lock2 succeeded! This is a locking bug\n");
1791 correct = false;
1792 } else {
1793 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1794 NT_STATUS_FILE_LOCK_CONFLICT)) {
1795 return false;
1799 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1800 if (!NT_STATUS_IS_OK(status)) {
1801 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1803 cli_setpid(cli, 2);
1804 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1805 printf("unlock at 100 succeeded! This is a locking bug\n");
1806 correct = False;
1809 status = cli_unlock(cli, fnum1, 0, 4);
1810 if (NT_STATUS_IS_OK(status)) {
1811 printf("unlock1 succeeded! This is a locking bug\n");
1812 correct = false;
1813 } else {
1814 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1815 NT_STATUS_RANGE_NOT_LOCKED)) {
1816 return false;
1820 status = cli_unlock(cli, fnum1, 0, 8);
1821 if (NT_STATUS_IS_OK(status)) {
1822 printf("unlock2 succeeded! This is a locking bug\n");
1823 correct = false;
1824 } else {
1825 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1826 NT_STATUS_RANGE_NOT_LOCKED)) {
1827 return false;
1831 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1832 if (NT_STATUS_IS_OK(status)) {
1833 printf("lock3 succeeded! This is a locking bug\n");
1834 correct = false;
1835 } else {
1836 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1837 NT_STATUS_LOCK_NOT_GRANTED)) {
1838 return false;
1842 cli_setpid(cli, 1);
1844 status = cli_close(cli, fnum1);
1845 if (!NT_STATUS_IS_OK(status)) {
1846 printf("close1 failed (%s)\n", nt_errstr(status));
1847 return False;
1850 status = cli_close(cli, fnum2);
1851 if (!NT_STATUS_IS_OK(status)) {
1852 printf("close2 failed (%s)\n", nt_errstr(status));
1853 return False;
1856 status = cli_close(cli, fnum3);
1857 if (!NT_STATUS_IS_OK(status)) {
1858 printf("close3 failed (%s)\n", nt_errstr(status));
1859 return False;
1862 if (!torture_close_connection(cli)) {
1863 correct = False;
1866 printf("locktest2 finished\n");
1868 return correct;
1873 This test checks that
1875 1) the server supports the full offset range in lock requests
1877 static bool run_locktest3(int dummy)
1879 static struct cli_state *cli1, *cli2;
1880 const char *fname = "\\lockt3.lck";
1881 uint16_t fnum1, fnum2;
1882 int i;
1883 uint32_t offset;
1884 bool correct = True;
1885 NTSTATUS status;
1887 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1889 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1890 return False;
1892 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1893 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1895 printf("starting locktest3\n");
1897 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1899 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1900 &fnum1);
1901 if (!NT_STATUS_IS_OK(status)) {
1902 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1903 return False;
1906 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1907 if (!NT_STATUS_IS_OK(status)) {
1908 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1909 return False;
1912 for (offset=i=0;i<torture_numops;i++) {
1913 NEXT_OFFSET;
1915 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1916 if (!NT_STATUS_IS_OK(status)) {
1917 printf("lock1 %d failed (%s)\n",
1919 nt_errstr(status));
1920 return False;
1923 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1924 if (!NT_STATUS_IS_OK(status)) {
1925 printf("lock2 %d failed (%s)\n",
1927 nt_errstr(status));
1928 return False;
1932 for (offset=i=0;i<torture_numops;i++) {
1933 NEXT_OFFSET;
1935 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1936 if (NT_STATUS_IS_OK(status)) {
1937 printf("error: lock1 %d succeeded!\n", i);
1938 return False;
1941 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1942 if (NT_STATUS_IS_OK(status)) {
1943 printf("error: lock2 %d succeeded!\n", i);
1944 return False;
1947 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1948 if (NT_STATUS_IS_OK(status)) {
1949 printf("error: lock3 %d succeeded!\n", i);
1950 return False;
1953 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1954 if (NT_STATUS_IS_OK(status)) {
1955 printf("error: lock4 %d succeeded!\n", i);
1956 return False;
1960 for (offset=i=0;i<torture_numops;i++) {
1961 NEXT_OFFSET;
1963 status = cli_unlock(cli1, fnum1, offset-1, 1);
1964 if (!NT_STATUS_IS_OK(status)) {
1965 printf("unlock1 %d failed (%s)\n",
1967 nt_errstr(status));
1968 return False;
1971 status = cli_unlock(cli2, fnum2, offset-2, 1);
1972 if (!NT_STATUS_IS_OK(status)) {
1973 printf("unlock2 %d failed (%s)\n",
1975 nt_errstr(status));
1976 return False;
1980 status = cli_close(cli1, fnum1);
1981 if (!NT_STATUS_IS_OK(status)) {
1982 printf("close1 failed (%s)\n", nt_errstr(status));
1983 return False;
1986 status = cli_close(cli2, fnum2);
1987 if (!NT_STATUS_IS_OK(status)) {
1988 printf("close2 failed (%s)\n", nt_errstr(status));
1989 return False;
1992 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1993 if (!NT_STATUS_IS_OK(status)) {
1994 printf("unlink failed (%s)\n", nt_errstr(status));
1995 return False;
1998 if (!torture_close_connection(cli1)) {
1999 correct = False;
2002 if (!torture_close_connection(cli2)) {
2003 correct = False;
2006 printf("finished locktest3\n");
2008 return correct;
2011 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
2012 char *buf, off_t offset, size_t size,
2013 size_t *nread, size_t expect)
2015 NTSTATUS status;
2016 size_t l_nread;
2018 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
2020 if(!NT_STATUS_IS_OK(status)) {
2021 return false;
2022 } else if (l_nread != expect) {
2023 return false;
2026 if (nread) {
2027 *nread = l_nread;
2030 return true;
2033 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2034 printf("** "); correct = False; \
2038 looks at overlapping locks
2040 static bool run_locktest4(int dummy)
2042 static struct cli_state *cli1, *cli2;
2043 const char *fname = "\\lockt4.lck";
2044 uint16_t fnum1, fnum2, f;
2045 bool ret;
2046 char buf[1000];
2047 bool correct = True;
2048 NTSTATUS status;
2050 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2051 return False;
2054 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2055 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2057 printf("starting locktest4\n");
2059 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2061 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2062 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2064 memset(buf, 0, sizeof(buf));
2066 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2067 NULL);
2068 if (!NT_STATUS_IS_OK(status)) {
2069 printf("Failed to create file: %s\n", nt_errstr(status));
2070 correct = False;
2071 goto fail;
2074 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2075 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
2076 EXPECTED(ret, False);
2077 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2079 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2080 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2081 EXPECTED(ret, True);
2082 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2084 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2085 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2086 EXPECTED(ret, False);
2087 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2089 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2090 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2091 EXPECTED(ret, True);
2092 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2094 ret = (cli_setpid(cli1, 1),
2095 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2096 (cli_setpid(cli1, 2),
2097 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2098 EXPECTED(ret, False);
2099 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2101 ret = (cli_setpid(cli1, 1),
2102 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2103 (cli_setpid(cli1, 2),
2104 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2105 EXPECTED(ret, True);
2106 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2108 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2109 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2110 EXPECTED(ret, True);
2111 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2113 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2114 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2115 EXPECTED(ret, False);
2116 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2118 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2119 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2120 EXPECTED(ret, False);
2121 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2123 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2124 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2125 EXPECTED(ret, True);
2126 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2128 ret = (cli_setpid(cli1, 1),
2129 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2130 (cli_setpid(cli1, 2),
2131 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2132 EXPECTED(ret, False);
2133 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2135 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2136 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2137 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2138 EXPECTED(ret, False);
2139 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2142 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2143 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2144 EXPECTED(ret, False);
2145 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2147 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2148 ret = NT_STATUS_IS_OK(status);
2149 if (ret) {
2150 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2151 NULL);
2152 ret = NT_STATUS_IS_OK(status);
2154 EXPECTED(ret, False);
2155 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2158 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2159 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2160 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2161 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2162 EXPECTED(ret, True);
2163 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2166 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2167 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2168 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2169 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2170 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2171 150, 4, NULL))) &&
2172 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2173 EXPECTED(ret, True);
2174 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2176 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2177 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2178 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2179 160, 4, NULL)) &&
2180 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2181 EXPECTED(ret, True);
2182 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2184 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2185 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2186 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2187 170, 4, NULL)) &&
2188 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2189 EXPECTED(ret, True);
2190 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2192 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2193 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2194 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2195 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2196 190, 4, NULL)) &&
2197 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2198 EXPECTED(ret, True);
2199 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2201 cli_close(cli1, fnum1);
2202 cli_close(cli2, fnum2);
2203 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2204 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2205 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2206 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2207 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2208 NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2209 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2210 cli_close(cli1, f);
2211 cli_close(cli1, fnum1);
2212 EXPECTED(ret, True);
2213 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2215 fail:
2216 cli_close(cli1, fnum1);
2217 cli_close(cli2, fnum2);
2218 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2219 torture_close_connection(cli1);
2220 torture_close_connection(cli2);
2222 printf("finished locktest4\n");
2223 return correct;
2227 looks at lock upgrade/downgrade.
2229 static bool run_locktest5(int dummy)
2231 static struct cli_state *cli1, *cli2;
2232 const char *fname = "\\lockt5.lck";
2233 uint16_t fnum1, fnum2, fnum3;
2234 bool ret;
2235 char buf[1000];
2236 bool correct = True;
2237 NTSTATUS status;
2239 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2240 return False;
2243 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2244 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2246 printf("starting locktest5\n");
2248 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2250 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2251 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2252 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2254 memset(buf, 0, sizeof(buf));
2256 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2257 NULL);
2258 if (!NT_STATUS_IS_OK(status)) {
2259 printf("Failed to create file: %s\n", nt_errstr(status));
2260 correct = False;
2261 goto fail;
2264 /* Check for NT bug... */
2265 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2266 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2267 cli_close(cli1, fnum1);
2268 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2269 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2270 ret = NT_STATUS_IS_OK(status);
2271 EXPECTED(ret, True);
2272 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2273 cli_close(cli1, fnum1);
2274 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2275 cli_unlock(cli1, fnum3, 0, 1);
2277 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2278 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2279 EXPECTED(ret, True);
2280 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2282 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2283 ret = NT_STATUS_IS_OK(status);
2284 EXPECTED(ret, False);
2286 printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2288 /* Unlock the process 2 lock. */
2289 cli_unlock(cli2, fnum2, 0, 4);
2291 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2292 ret = NT_STATUS_IS_OK(status);
2293 EXPECTED(ret, False);
2295 printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2297 /* Unlock the process 1 fnum3 lock. */
2298 cli_unlock(cli1, fnum3, 0, 4);
2300 /* Stack 2 more locks here. */
2301 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2302 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2304 EXPECTED(ret, True);
2305 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2307 /* Unlock the first process lock, then check this was the WRITE lock that was
2308 removed. */
2310 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2311 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2313 EXPECTED(ret, True);
2314 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2316 /* Unlock the process 2 lock. */
2317 cli_unlock(cli2, fnum2, 0, 4);
2319 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2321 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2322 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2323 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2325 EXPECTED(ret, True);
2326 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2328 /* Ensure the next unlock fails. */
2329 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2330 EXPECTED(ret, False);
2331 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2333 /* Ensure connection 2 can get a write lock. */
2334 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2335 ret = NT_STATUS_IS_OK(status);
2336 EXPECTED(ret, True);
2338 printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2341 fail:
2342 cli_close(cli1, fnum1);
2343 cli_close(cli2, fnum2);
2344 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2345 if (!torture_close_connection(cli1)) {
2346 correct = False;
2348 if (!torture_close_connection(cli2)) {
2349 correct = False;
2352 printf("finished locktest5\n");
2354 return correct;
2358 tries the unusual lockingX locktype bits
2360 static bool run_locktest6(int dummy)
2362 static struct cli_state *cli;
2363 const char *fname[1] = { "\\lock6.txt" };
2364 int i;
2365 uint16_t fnum;
2366 NTSTATUS status;
2368 if (!torture_open_connection(&cli, 0)) {
2369 return False;
2372 smbXcli_conn_set_sockopt(cli->conn, sockops);
2374 printf("starting locktest6\n");
2376 for (i=0;i<1;i++) {
2377 printf("Testing %s\n", fname[i]);
2379 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2381 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2382 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2383 cli_close(cli, fnum);
2384 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2386 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2387 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2388 cli_close(cli, fnum);
2389 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2391 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2394 torture_close_connection(cli);
2396 printf("finished locktest6\n");
2397 return True;
2400 static bool run_locktest7(int dummy)
2402 struct cli_state *cli1;
2403 const char *fname = "\\lockt7.lck";
2404 uint16_t fnum1;
2405 char buf[200];
2406 bool correct = False;
2407 size_t nread;
2408 NTSTATUS status;
2410 if (!torture_open_connection(&cli1, 0)) {
2411 return False;
2414 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2416 printf("starting locktest7\n");
2418 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2420 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2422 memset(buf, 0, sizeof(buf));
2424 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2425 NULL);
2426 if (!NT_STATUS_IS_OK(status)) {
2427 printf("Failed to create file: %s\n", nt_errstr(status));
2428 goto fail;
2431 cli_setpid(cli1, 1);
2433 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2434 if (!NT_STATUS_IS_OK(status)) {
2435 printf("Unable to apply read lock on range 130:4, "
2436 "error was %s\n", nt_errstr(status));
2437 goto fail;
2438 } else {
2439 printf("pid1 successfully locked range 130:4 for READ\n");
2442 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2443 if (!NT_STATUS_IS_OK(status)) {
2444 printf("pid1 unable to read the range 130:4, error was %s\n",
2445 nt_errstr(status));
2446 goto fail;
2447 } else if (nread != 4) {
2448 printf("pid1 unable to read the range 130:4, "
2449 "recv %ld req %d\n", (unsigned long)nread, 4);
2450 goto fail;
2451 } else {
2452 printf("pid1 successfully read the range 130:4\n");
2455 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2456 if (!NT_STATUS_IS_OK(status)) {
2457 printf("pid1 unable to write to the range 130:4, error was "
2458 "%s\n", nt_errstr(status));
2459 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2460 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2461 goto fail;
2463 } else {
2464 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2465 goto fail;
2468 cli_setpid(cli1, 2);
2470 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2471 if (!NT_STATUS_IS_OK(status)) {
2472 printf("pid2 unable to read the range 130:4, error was %s\n",
2473 nt_errstr(status));
2474 goto fail;
2475 } else if (nread != 4) {
2476 printf("pid2 unable to read the range 130:4, "
2477 "recv %ld req %d\n", (unsigned long)nread, 4);
2478 goto fail;
2479 } else {
2480 printf("pid2 successfully read the range 130:4\n");
2483 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2484 if (!NT_STATUS_IS_OK(status)) {
2485 printf("pid2 unable to write to the range 130:4, error was "
2486 "%s\n", nt_errstr(status));
2487 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2488 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2489 goto fail;
2491 } else {
2492 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2493 goto fail;
2496 cli_setpid(cli1, 1);
2497 cli_unlock(cli1, fnum1, 130, 4);
2499 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2500 if (!NT_STATUS_IS_OK(status)) {
2501 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2502 goto fail;
2503 } else {
2504 printf("pid1 successfully locked range 130:4 for WRITE\n");
2507 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2508 if (!NT_STATUS_IS_OK(status)) {
2509 printf("pid1 unable to read the range 130:4, error was %s\n",
2510 nt_errstr(status));
2511 goto fail;
2512 } else if (nread != 4) {
2513 printf("pid1 unable to read the range 130:4, "
2514 "recv %ld req %d\n", (unsigned long)nread, 4);
2515 goto fail;
2516 } else {
2517 printf("pid1 successfully read the range 130:4\n");
2520 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2521 if (!NT_STATUS_IS_OK(status)) {
2522 printf("pid1 unable to write to the range 130:4, error was "
2523 "%s\n", nt_errstr(status));
2524 goto fail;
2525 } else {
2526 printf("pid1 successfully wrote to the range 130:4\n");
2529 cli_setpid(cli1, 2);
2531 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2532 if (!NT_STATUS_IS_OK(status)) {
2533 printf("pid2 unable to read the range 130:4, error was "
2534 "%s\n", nt_errstr(status));
2535 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2536 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2537 goto fail;
2539 } else {
2540 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2541 (unsigned long)nread);
2542 goto fail;
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_unlock(cli1, fnum1, 130, 0);
2559 correct = True;
2561 fail:
2562 cli_close(cli1, fnum1);
2563 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2564 torture_close_connection(cli1);
2566 printf("finished locktest7\n");
2567 return correct;
2571 * This demonstrates a problem with our use of GPFS share modes: A file
2572 * descriptor sitting in the pending close queue holding a GPFS share mode
2573 * blocks opening a file another time. Happens with Word 2007 temp files.
2574 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2575 * open is denied with NT_STATUS_SHARING_VIOLATION.
2578 static bool run_locktest8(int dummy)
2580 struct cli_state *cli1;
2581 const char *fname = "\\lockt8.lck";
2582 uint16_t fnum1, fnum2;
2583 char buf[200];
2584 bool correct = False;
2585 NTSTATUS status;
2587 if (!torture_open_connection(&cli1, 0)) {
2588 return False;
2591 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2593 printf("starting locktest8\n");
2595 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2597 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2598 &fnum1);
2599 if (!NT_STATUS_IS_OK(status)) {
2600 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2601 return false;
2604 memset(buf, 0, sizeof(buf));
2606 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2607 if (!NT_STATUS_IS_OK(status)) {
2608 d_fprintf(stderr, "cli_openx second time returned %s\n",
2609 nt_errstr(status));
2610 goto fail;
2613 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2614 if (!NT_STATUS_IS_OK(status)) {
2615 printf("Unable to apply read lock on range 1:1, error was "
2616 "%s\n", nt_errstr(status));
2617 goto fail;
2620 status = cli_close(cli1, fnum1);
2621 if (!NT_STATUS_IS_OK(status)) {
2622 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2623 goto fail;
2626 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2627 if (!NT_STATUS_IS_OK(status)) {
2628 d_fprintf(stderr, "cli_openx third time returned %s\n",
2629 nt_errstr(status));
2630 goto fail;
2633 correct = true;
2635 fail:
2636 cli_close(cli1, fnum1);
2637 cli_close(cli1, fnum2);
2638 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2639 torture_close_connection(cli1);
2641 printf("finished locktest8\n");
2642 return correct;
2646 * This test is designed to be run in conjunction with
2647 * external NFS or POSIX locks taken in the filesystem.
2648 * It checks that the smbd server will block until the
2649 * lock is released and then acquire it. JRA.
2652 static bool got_alarm;
2653 static struct cli_state *alarm_cli;
2655 static void alarm_handler(int dummy)
2657 got_alarm = True;
2660 static void alarm_handler_parent(int dummy)
2662 smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2665 static void do_local_lock(const char *fname, int read_fd, int write_fd)
2667 int fd;
2668 char c = '\0';
2669 struct flock lock;
2670 const char *local_pathname = NULL;
2671 int ret;
2673 local_pathname = talloc_asprintf(talloc_tos(),
2674 "%s/%s", local_path, fname);
2675 if (!local_pathname) {
2676 printf("child: alloc fail\n");
2677 exit(1);
2680 unlink(local_pathname);
2681 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2682 if (fd == -1) {
2683 printf("child: open of %s failed %s.\n",
2684 local_pathname, strerror(errno));
2685 exit(1);
2688 /* Now take a fcntl lock. */
2689 lock.l_type = F_WRLCK;
2690 lock.l_whence = SEEK_SET;
2691 lock.l_start = 0;
2692 lock.l_len = 4;
2693 lock.l_pid = getpid();
2695 ret = fcntl(fd,F_SETLK,&lock);
2696 if (ret == -1) {
2697 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2698 local_pathname, strerror(errno));
2699 exit(1);
2700 } else {
2701 printf("child: got lock 0:4 on file %s.\n",
2702 local_pathname );
2703 fflush(stdout);
2706 CatchSignal(SIGALRM, alarm_handler);
2707 alarm(5);
2708 /* Signal the parent. */
2709 if (write(write_fd, &c, 1) != 1) {
2710 printf("child: start signal fail %s.\n",
2711 strerror(errno));
2712 exit(1);
2714 alarm(0);
2716 alarm(10);
2717 /* Wait for the parent to be ready. */
2718 if (read(read_fd, &c, 1) != 1) {
2719 printf("child: reply signal fail %s.\n",
2720 strerror(errno));
2721 exit(1);
2723 alarm(0);
2725 sleep(5);
2726 close(fd);
2727 printf("child: released lock 0:4 on file %s.\n",
2728 local_pathname );
2729 fflush(stdout);
2730 exit(0);
2733 static bool _run_locktest9X(const char *fname, int timeout)
2735 struct cli_state *cli1;
2736 char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2737 uint16_t fnum;
2738 bool correct = False;
2739 int pipe_in[2], pipe_out[2];
2740 pid_t child_pid;
2741 char c = '\0';
2742 int ret;
2743 struct timeval start;
2744 double seconds;
2745 NTSTATUS status;
2747 printf("starting locktest9X: %s\n", fname);
2749 if (local_path == NULL) {
2750 d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2751 return false;
2754 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2755 return false;
2758 child_pid = fork();
2759 if (child_pid == -1) {
2760 return false;
2763 if (child_pid == 0) {
2764 /* Child. */
2765 do_local_lock(fname, pipe_out[0], pipe_in[1]);
2766 exit(0);
2769 close(pipe_out[0]);
2770 close(pipe_in[1]);
2771 pipe_out[0] = -1;
2772 pipe_in[1] = -1;
2774 /* Parent. */
2775 ret = read(pipe_in[0], &c, 1);
2776 if (ret != 1) {
2777 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2778 strerror(errno));
2779 return false;
2782 if (!torture_open_connection(&cli1, 0)) {
2783 return false;
2786 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2788 status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2789 &fnum);
2790 if (!NT_STATUS_IS_OK(status)) {
2791 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2792 return false;
2795 /* Ensure the child has the lock. */
2796 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2797 if (NT_STATUS_IS_OK(status)) {
2798 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2799 goto fail;
2800 } else {
2801 d_printf("Child has the lock.\n");
2804 /* Tell the child to wait 5 seconds then exit. */
2805 ret = write(pipe_out[1], &c, 1);
2806 if (ret != 1) {
2807 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2808 strerror(errno));
2809 goto fail;
2812 /* Wait 20 seconds for the lock. */
2813 alarm_cli = cli1;
2814 CatchSignal(SIGALRM, alarm_handler_parent);
2815 alarm(20);
2817 start = timeval_current();
2819 status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2820 if (!NT_STATUS_IS_OK(status)) {
2821 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2822 "%s\n", nt_errstr(status));
2823 goto fail_nofd;
2825 alarm(0);
2827 seconds = timeval_elapsed(&start);
2829 printf("Parent got the lock after %.2f seconds.\n",
2830 seconds);
2832 status = cli_close(cli1, fnum);
2833 if (!NT_STATUS_IS_OK(status)) {
2834 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2835 goto fail;
2838 correct = true;
2840 fail:
2841 cli_close(cli1, fnum);
2842 torture_close_connection(cli1);
2844 fail_nofd:
2846 printf("finished locktest9X: %s\n", fname);
2847 return correct;
2850 static bool run_locktest9a(int dummy)
2852 return _run_locktest9X("lock9a.dat", -1);
2855 static bool run_locktest9b(int dummy)
2857 return _run_locktest9X("lock9b.dat", 10000);
2860 struct locktest10_state {
2861 bool ok;
2862 bool done;
2865 static void locktest10_lockingx_done(struct tevent_req *subreq);
2866 static void locktest10_read_andx_done(struct tevent_req *subreq);
2868 static bool run_locktest10(int dummy)
2870 struct tevent_context *ev = NULL;
2871 struct cli_state *cli1 = NULL;
2872 struct cli_state *cli2 = NULL;
2873 struct smb1_lock_element lck = { 0 };
2874 struct tevent_req *reqs[2] = { NULL };
2875 struct tevent_req *smbreqs[2] = { NULL };
2876 const char fname[] = "\\lockt10.lck";
2877 uint16_t fnum1, fnum2;
2878 bool ret = false;
2879 bool ok;
2880 uint8_t data = 1;
2881 struct locktest10_state state = { .ok = true };
2882 NTSTATUS status;
2884 printf("starting locktest10\n");
2886 ev = samba_tevent_context_init(NULL);
2887 if (ev == NULL) {
2888 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2889 goto done;
2892 ok = torture_open_connection(&cli1, 0);
2893 if (!ok) {
2894 goto done;
2896 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2898 ok = torture_open_connection(&cli2, 1);
2899 if (!ok) {
2900 goto done;
2902 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2904 status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2905 if (!NT_STATUS_IS_OK(status)) {
2906 d_fprintf(stderr,
2907 "cli_openx failed: %s\n",
2908 nt_errstr(status));
2909 goto done;
2912 status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2913 if (!NT_STATUS_IS_OK(status)) {
2914 d_fprintf(stderr,
2915 "cli_writeall failed: %s\n",
2916 nt_errstr(status));
2917 goto done;
2920 status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2921 if (!NT_STATUS_IS_OK(status)) {
2922 d_fprintf(stderr,
2923 "cli_openx failed: %s\n",
2924 nt_errstr(status));
2925 goto done;
2928 status = cli_locktype(
2929 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2930 if (!NT_STATUS_IS_OK(status)) {
2931 d_fprintf(stderr,
2932 "cli_locktype failed: %s\n",
2933 nt_errstr(status));
2934 goto done;
2937 lck = (struct smb1_lock_element) {
2938 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2941 reqs[0] = cli_lockingx_create(
2942 ev, /* mem_ctx */
2943 ev, /* tevent_context */
2944 cli1, /* cli */
2945 fnum1, /* fnum */
2946 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
2947 0, /* newoplocklevel */
2948 1, /* timeout */
2949 0, /* num_unlocks */
2950 NULL, /* unlocks */
2951 1, /* num_locks */
2952 &lck, /* locks */
2953 &smbreqs[0]); /* psmbreq */
2954 if (reqs[0] == NULL) {
2955 d_fprintf(stderr, "cli_lockingx_create failed\n");
2956 goto done;
2958 tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
2960 reqs[1] = cli_read_andx_create(
2961 ev, /* mem_ctx */
2962 ev, /* ev */
2963 cli1, /* cli */
2964 fnum1, /* fnum */
2965 0, /* offset */
2966 1, /* size */
2967 &smbreqs[1]); /* psmbreq */
2968 if (reqs[1] == NULL) {
2969 d_fprintf(stderr, "cli_read_andx_create failed\n");
2970 goto done;
2972 tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
2974 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
2975 if (!NT_STATUS_IS_OK(status)) {
2976 d_fprintf(stderr,
2977 "smb1cli_req_chain_submit failed: %s\n",
2978 nt_errstr(status));
2979 goto done;
2982 while (!state.done) {
2983 tevent_loop_once(ev);
2986 torture_close_connection(cli1);
2988 if (state.ok) {
2989 ret = true;
2991 done:
2992 return ret;
2995 static void locktest10_lockingx_done(struct tevent_req *subreq)
2997 struct locktest10_state *state = tevent_req_callback_data_void(subreq);
2998 NTSTATUS status;
3000 status = cli_lockingx_recv(subreq);
3001 TALLOC_FREE(subreq);
3003 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3004 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3005 state->ok = false;
3009 static void locktest10_read_andx_done(struct tevent_req *subreq)
3011 struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3012 ssize_t received = -1;
3013 uint8_t *rcvbuf = NULL;
3014 NTSTATUS status;
3016 status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3018 if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
3019 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
3020 state->ok = false;
3023 state->done = true;
3024 TALLOC_FREE(subreq);
3027 static bool run_locktest11(int dummy)
3029 struct cli_state *cli1;
3030 const char *fname = "\\lockt11.lck";
3031 NTSTATUS status;
3032 uint16_t fnum;
3033 bool ret = false;
3035 if (!torture_open_connection(&cli1, 0)) {
3036 return false;
3039 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3041 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3043 status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
3044 if (!NT_STATUS_IS_OK(status)) {
3045 d_fprintf(stderr,
3046 "cli_openx returned %s\n",
3047 nt_errstr(status));
3048 return false;
3052 * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3053 * returns NT_STATUS_OK
3056 status = cli_lockingx(
3057 cli1, /* cli */
3058 fnum, /* fnum */
3059 LOCKING_ANDX_CANCEL_LOCK, /* typeoflock */
3060 0, /* newoplocklevel */
3061 0, /* timeout */
3062 0, /* num_unlocks */
3063 NULL, /* unlocks */
3064 0, /* num_locks */
3065 NULL); /* locks */
3067 if (!NT_STATUS_IS_OK(status)) {
3068 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
3069 goto fail;
3072 ret = true;
3073 fail:
3074 cli_close(cli1, fnum);
3075 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3077 return ret;
3080 struct deferred_close_state {
3081 struct tevent_context *ev;
3082 struct cli_state *cli;
3083 uint16_t fnum;
3086 static void deferred_close_waited(struct tevent_req *subreq);
3087 static void deferred_close_done(struct tevent_req *subreq);
3089 static struct tevent_req *deferred_close_send(
3090 TALLOC_CTX *mem_ctx,
3091 struct tevent_context *ev,
3092 int wait_secs,
3093 struct cli_state *cli,
3094 uint16_t fnum)
3096 struct tevent_req *req = NULL, *subreq = NULL;
3097 struct deferred_close_state *state = NULL;
3098 struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
3100 req = tevent_req_create(
3101 mem_ctx, &state, struct deferred_close_state);
3102 if (req == NULL) {
3103 return NULL;
3105 state->ev = ev;
3106 state->cli = cli;
3107 state->fnum = fnum;
3109 subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
3110 if (tevent_req_nomem(subreq, req)) {
3111 return tevent_req_post(req, ev);
3113 tevent_req_set_callback(subreq, deferred_close_waited, req);
3114 return req;
3117 static void deferred_close_waited(struct tevent_req *subreq)
3119 struct tevent_req *req = tevent_req_callback_data(
3120 subreq, struct tevent_req);
3121 struct deferred_close_state *state = tevent_req_data(
3122 req, struct deferred_close_state);
3123 bool ok;
3125 ok = tevent_wakeup_recv(subreq);
3126 TALLOC_FREE(subreq);
3127 if (!ok) {
3128 tevent_req_oom(req);
3129 return;
3132 subreq = cli_close_send(state, state->ev, state->cli, state->fnum);
3133 if (tevent_req_nomem(subreq, req)) {
3134 return;
3136 tevent_req_set_callback(subreq, deferred_close_done, req);
3139 static void deferred_close_done(struct tevent_req *subreq)
3141 NTSTATUS status = cli_close_recv(subreq);
3142 tevent_req_simple_finish_ntstatus(subreq, status);
3145 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3147 return tevent_req_simple_recv_ntstatus(req);
3150 struct lockread_state {
3151 struct smb1_lock_element lck;
3152 struct tevent_req *reqs[2];
3153 struct tevent_req *smbreqs[2];
3154 NTSTATUS lock_status;
3155 NTSTATUS read_status;
3156 uint8_t *readbuf;
3159 static void lockread_lockingx_done(struct tevent_req *subreq);
3160 static void lockread_read_andx_done(struct tevent_req *subreq);
3162 static struct tevent_req *lockread_send(
3163 TALLOC_CTX *mem_ctx,
3164 struct tevent_context *ev,
3165 struct cli_state *cli,
3166 uint16_t fnum)
3168 struct tevent_req *req = NULL;
3169 struct lockread_state *state = NULL;
3170 NTSTATUS status;
3172 req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3173 if (req == NULL) {
3174 return NULL;
3177 state->lck = (struct smb1_lock_element) {
3178 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3181 state->reqs[0] = cli_lockingx_create(
3182 ev, /* mem_ctx */
3183 ev, /* tevent_context */
3184 cli, /* cli */
3185 fnum, /* fnum */
3186 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3187 0, /* newoplocklevel */
3188 10000, /* timeout */
3189 0, /* num_unlocks */
3190 NULL, /* unlocks */
3191 1, /* num_locks */
3192 &state->lck, /* locks */
3193 &state->smbreqs[0]); /* psmbreq */
3194 if (tevent_req_nomem(state->reqs[0], req)) {
3195 return tevent_req_post(req, ev);
3197 tevent_req_set_callback(
3198 state->reqs[0], lockread_lockingx_done, req);
3200 state->reqs[1] = cli_read_andx_create(
3201 ev, /* mem_ctx */
3202 ev, /* ev */
3203 cli, /* cli */
3204 fnum, /* fnum */
3205 0, /* offset */
3206 1, /* size */
3207 &state->smbreqs[1]); /* psmbreq */
3208 if (tevent_req_nomem(state->reqs[1], req)) {
3209 return tevent_req_post(req, ev);
3211 tevent_req_set_callback(
3212 state->reqs[1], lockread_read_andx_done, req);
3214 status = smb1cli_req_chain_submit(state->smbreqs, 2);
3215 if (tevent_req_nterror(req, status)) {
3216 return tevent_req_post(req, ev);
3218 return req;
3221 static void lockread_lockingx_done(struct tevent_req *subreq)
3223 struct tevent_req *req = tevent_req_callback_data(
3224 subreq, struct tevent_req);
3225 struct lockread_state *state = tevent_req_data(
3226 req, struct lockread_state);
3227 state->lock_status = cli_lockingx_recv(subreq);
3228 TALLOC_FREE(subreq);
3229 d_fprintf(stderr,
3230 "lockingx returned %s\n",
3231 nt_errstr(state->lock_status));
3234 static void lockread_read_andx_done(struct tevent_req *subreq)
3236 struct tevent_req *req = tevent_req_callback_data(
3237 subreq, struct tevent_req);
3238 struct lockread_state *state = tevent_req_data(
3239 req, struct lockread_state);
3240 ssize_t received = -1;
3241 uint8_t *rcvbuf = NULL;
3243 state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3245 d_fprintf(stderr,
3246 "read returned %s\n",
3247 nt_errstr(state->read_status));
3249 if (!NT_STATUS_IS_OK(state->read_status)) {
3250 TALLOC_FREE(subreq);
3251 tevent_req_done(req);
3252 return;
3255 if (received > 0) {
3256 state->readbuf = talloc_memdup(state, rcvbuf, received);
3257 TALLOC_FREE(subreq);
3258 if (tevent_req_nomem(state->readbuf, req)) {
3259 return;
3262 TALLOC_FREE(subreq);
3263 tevent_req_done(req);
3266 static NTSTATUS lockread_recv(
3267 struct tevent_req *req,
3268 NTSTATUS *lock_status,
3269 NTSTATUS *read_status,
3270 TALLOC_CTX *mem_ctx,
3271 uint8_t **read_buf)
3273 struct lockread_state *state = tevent_req_data(
3274 req, struct lockread_state);
3275 NTSTATUS status;
3277 if (tevent_req_is_nterror(req, &status)) {
3278 return status;
3281 *lock_status = state->lock_status;
3282 *read_status = state->read_status;
3283 if (state->readbuf != NULL) {
3284 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3285 } else {
3286 *read_buf = NULL;
3289 return NT_STATUS_OK;
3292 struct lock12_state {
3293 uint8_t dummy;
3296 static void lock12_closed(struct tevent_req *subreq);
3297 static void lock12_read(struct tevent_req *subreq);
3299 static struct tevent_req *lock12_send(
3300 TALLOC_CTX *mem_ctx,
3301 struct tevent_context *ev,
3302 struct cli_state *cli,
3303 uint16_t fnum1,
3304 uint16_t fnum2)
3306 struct tevent_req *req = NULL, *subreq = NULL;
3307 struct lock12_state *state = NULL;
3309 req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3310 if (req == NULL) {
3311 return NULL;
3314 subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3315 if (tevent_req_nomem(subreq, req)) {
3316 return tevent_req_post(req, ev);
3318 tevent_req_set_callback(subreq, lock12_closed, req);
3320 subreq = lockread_send(state, ev, cli, fnum2);
3321 if (tevent_req_nomem(subreq, req)) {
3322 return tevent_req_post(req, ev);
3324 tevent_req_set_callback(subreq, lock12_read, req);
3326 return req;
3329 static void lock12_closed(struct tevent_req *subreq)
3331 struct tevent_req *req = tevent_req_callback_data(
3332 subreq, struct tevent_req);
3333 NTSTATUS status;
3335 status = deferred_close_recv(subreq);
3336 TALLOC_FREE(subreq);
3337 DBG_DEBUG("close returned %s\n", nt_errstr(status));
3338 if (tevent_req_nterror(req, status)) {
3339 return;
3343 static void lock12_read(struct tevent_req *subreq)
3345 struct tevent_req *req = tevent_req_callback_data(
3346 subreq, struct tevent_req);
3347 struct lock12_state *state = tevent_req_data(
3348 req, struct lock12_state);
3349 NTSTATUS status, lock_status, read_status;
3350 uint8_t *buf = NULL;
3352 status = lockread_recv(
3353 subreq, &lock_status, &read_status, state, &buf);
3354 TALLOC_FREE(subreq);
3355 if (tevent_req_nterror(req, status) ||
3356 tevent_req_nterror(req, lock_status) ||
3357 tevent_req_nterror(req, read_status)) {
3358 return;
3360 tevent_req_done(req);
3363 static NTSTATUS lock12_recv(struct tevent_req *req)
3366 NTSTATUS status;
3368 if (tevent_req_is_nterror(req, &status)) {
3369 return status;
3371 return NT_STATUS_OK;
3374 static bool run_locktest12(int dummy)
3376 struct tevent_context *ev = NULL;
3377 struct tevent_req *req = NULL;
3378 struct cli_state *cli = NULL;
3379 const char fname[] = "\\lockt12.lck";
3380 uint16_t fnum1, fnum2;
3381 bool ret = false;
3382 bool ok;
3383 uint8_t data = 1;
3384 NTSTATUS status;
3386 printf("starting locktest12\n");
3388 ev = samba_tevent_context_init(NULL);
3389 if (ev == NULL) {
3390 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3391 goto done;
3394 ok = torture_open_connection(&cli, 0);
3395 if (!ok) {
3396 goto done;
3398 smbXcli_conn_set_sockopt(cli->conn, sockops);
3400 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3401 if (!NT_STATUS_IS_OK(status)) {
3402 d_fprintf(stderr,
3403 "cli_openx failed: %s\n",
3404 nt_errstr(status));
3405 goto done;
3408 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3409 if (!NT_STATUS_IS_OK(status)) {
3410 d_fprintf(stderr,
3411 "cli_openx failed: %s\n",
3412 nt_errstr(status));
3413 goto done;
3416 status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3417 if (!NT_STATUS_IS_OK(status)) {
3418 d_fprintf(stderr,
3419 "cli_writeall failed: %s\n",
3420 nt_errstr(status));
3421 goto done;
3424 status = cli_locktype(
3425 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3426 if (!NT_STATUS_IS_OK(status)) {
3427 d_fprintf(stderr,
3428 "cli_locktype failed: %s\n",
3429 nt_errstr(status));
3430 goto done;
3433 req = lock12_send(ev, ev, cli, fnum1, fnum2);
3434 if (req == NULL) {
3435 d_fprintf(stderr, "lock12_send failed\n");
3436 goto done;
3439 ok = tevent_req_poll_ntstatus(req, ev, &status);
3440 if (!ok) {
3441 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3442 goto done;
3445 if (!NT_STATUS_IS_OK(status)) {
3446 d_fprintf(stderr,
3447 "tevent_req_poll_ntstatus returned %s\n",
3448 nt_errstr(status));
3449 goto done;
3452 status = lock12_recv(req);
3453 if (!NT_STATUS_IS_OK(status)) {
3454 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3455 goto done;
3458 ret = true;
3459 done:
3460 if (cli != NULL) {
3461 torture_close_connection(cli);
3463 return ret;
3466 struct lock_ntcancel_state {
3467 struct timeval start;
3468 struct smb1_lock_element lck;
3469 struct tevent_req *subreq;
3472 static void lock_ntcancel_waited(struct tevent_req *subreq);
3473 static void lock_ntcancel_done(struct tevent_req *subreq);
3475 static struct tevent_req *lock_ntcancel_send(
3476 TALLOC_CTX *mem_ctx,
3477 struct tevent_context *ev,
3478 struct cli_state *cli,
3479 uint16_t fnum)
3481 struct tevent_req *req = NULL, *subreq = NULL;
3482 struct lock_ntcancel_state *state = NULL;
3484 req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3485 if (req == NULL) {
3486 return NULL;
3488 state->lck = (struct smb1_lock_element) {
3489 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3491 state->start = timeval_current();
3493 state->subreq = cli_lockingx_send(
3494 state, /* mem_ctx */
3495 ev, /* tevent_context */
3496 cli, /* cli */
3497 fnum, /* fnum */
3498 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3499 0, /* newoplocklevel */
3500 10000, /* timeout */
3501 0, /* num_unlocks */
3502 NULL, /* unlocks */
3503 1, /* num_locks */
3504 &state->lck); /* locks */
3505 if (tevent_req_nomem(state->subreq, req)) {
3506 return tevent_req_post(req, ev);
3508 tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3510 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3511 if (tevent_req_nomem(subreq, req)) {
3512 return tevent_req_post(req, ev);
3514 tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3515 return req;
3518 static void lock_ntcancel_waited(struct tevent_req *subreq)
3520 struct tevent_req *req = tevent_req_callback_data(
3521 subreq, struct tevent_req);
3522 struct lock_ntcancel_state *state = tevent_req_data(
3523 req, struct lock_ntcancel_state);
3524 bool ok;
3526 ok = tevent_wakeup_recv(subreq);
3527 TALLOC_FREE(subreq);
3528 if (!ok) {
3529 tevent_req_oom(req);
3530 return;
3533 ok = tevent_req_cancel(state->subreq);
3534 if (!ok) {
3535 d_fprintf(stderr, "Could not cancel subreq\n");
3536 tevent_req_oom(req);
3537 return;
3541 static void lock_ntcancel_done(struct tevent_req *subreq)
3543 struct tevent_req *req = tevent_req_callback_data(
3544 subreq, struct tevent_req);
3545 struct lock_ntcancel_state *state = tevent_req_data(
3546 req, struct lock_ntcancel_state);
3547 NTSTATUS status;
3548 double elapsed;
3550 status = cli_lockingx_recv(subreq);
3551 TALLOC_FREE(subreq);
3553 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3554 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3555 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3556 return;
3559 elapsed = timeval_elapsed(&state->start);
3561 if (elapsed > 3) {
3562 d_printf("cli_lockingx was too slow, cancel did not work\n");
3563 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3564 return;
3567 tevent_req_done(req);
3570 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3572 return tevent_req_simple_recv_ntstatus(req);
3575 static bool run_locktest13(int dummy)
3577 struct tevent_context *ev = NULL;
3578 struct tevent_req *req = NULL;
3579 struct cli_state *cli = NULL;
3580 const char fname[] = "\\lockt13.lck";
3581 uint16_t fnum1, fnum2;
3582 bool ret = false;
3583 bool ok;
3584 uint8_t data = 1;
3585 NTSTATUS status;
3587 printf("starting locktest13\n");
3589 ev = samba_tevent_context_init(NULL);
3590 if (ev == NULL) {
3591 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3592 goto done;
3595 ok = torture_open_connection(&cli, 0);
3596 if (!ok) {
3597 goto done;
3599 smbXcli_conn_set_sockopt(cli->conn, sockops);
3601 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3602 if (!NT_STATUS_IS_OK(status)) {
3603 d_fprintf(stderr,
3604 "cli_openx failed: %s\n",
3605 nt_errstr(status));
3606 goto done;
3609 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3610 if (!NT_STATUS_IS_OK(status)) {
3611 d_fprintf(stderr,
3612 "cli_openx failed: %s\n",
3613 nt_errstr(status));
3614 goto done;
3617 status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3618 if (!NT_STATUS_IS_OK(status)) {
3619 d_fprintf(stderr,
3620 "cli_writeall failed: %s\n",
3621 nt_errstr(status));
3622 goto done;
3625 status = cli_locktype(
3626 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3627 if (!NT_STATUS_IS_OK(status)) {
3628 d_fprintf(stderr,
3629 "cli_locktype failed: %s\n",
3630 nt_errstr(status));
3631 goto done;
3634 req = lock_ntcancel_send(ev, ev, cli, fnum2);
3635 if (req == NULL) {
3636 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3637 goto done;
3640 ok = tevent_req_poll_ntstatus(req, ev, &status);
3641 if (!ok) {
3642 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3643 goto done;
3646 if (!NT_STATUS_IS_OK(status)) {
3647 d_fprintf(stderr,
3648 "tevent_req_poll_ntstatus returned %s\n",
3649 nt_errstr(status));
3650 goto done;
3653 status = lock_ntcancel_recv(req);
3654 if (!NT_STATUS_IS_OK(status)) {
3655 d_fprintf(stderr,
3656 "lock_ntcancel returned %s\n",
3657 nt_errstr(status));
3658 goto done;
3661 ret = true;
3662 done:
3663 if (cli != NULL) {
3664 torture_close_connection(cli);
3666 return ret;
3670 test whether fnums and tids open on one VC are available on another (a major
3671 security hole)
3673 static bool run_fdpasstest(int dummy)
3675 struct cli_state *cli1, *cli2;
3676 const char *fname = "\\fdpass.tst";
3677 uint16_t fnum1;
3678 char buf[1024];
3679 NTSTATUS status;
3681 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3682 return False;
3684 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3685 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3687 printf("starting fdpasstest\n");
3689 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3691 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3692 &fnum1);
3693 if (!NT_STATUS_IS_OK(status)) {
3694 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3695 return False;
3698 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3699 13, NULL);
3700 if (!NT_STATUS_IS_OK(status)) {
3701 printf("write failed (%s)\n", nt_errstr(status));
3702 return False;
3705 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3706 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3707 cli_setpid(cli2, cli_getpid(cli1));
3709 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3710 printf("read succeeded! nasty security hole [%s]\n", buf);
3711 return false;
3714 cli_close(cli1, fnum1);
3715 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3717 torture_close_connection(cli1);
3718 torture_close_connection(cli2);
3720 printf("finished fdpasstest\n");
3721 return True;
3724 static bool run_fdsesstest(int dummy)
3726 struct cli_state *cli;
3727 uint16_t new_vuid;
3728 uint16_t saved_vuid;
3729 uint32_t new_cnum;
3730 uint32_t saved_cnum;
3731 const char *fname = "\\fdsess.tst";
3732 const char *fname1 = "\\fdsess1.tst";
3733 uint16_t fnum1;
3734 uint16_t fnum2;
3735 char buf[1024];
3736 bool ret = True;
3737 NTSTATUS status;
3739 if (!torture_open_connection(&cli, 0))
3740 return False;
3741 smbXcli_conn_set_sockopt(cli->conn, sockops);
3743 if (!torture_cli_session_setup2(cli, &new_vuid))
3744 return False;
3746 saved_cnum = cli_state_get_tid(cli);
3747 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3748 return False;
3749 new_cnum = cli_state_get_tid(cli);
3750 cli_state_set_tid(cli, saved_cnum);
3752 printf("starting fdsesstest\n");
3754 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3755 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3757 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3758 if (!NT_STATUS_IS_OK(status)) {
3759 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3760 return False;
3763 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3764 NULL);
3765 if (!NT_STATUS_IS_OK(status)) {
3766 printf("write failed (%s)\n", nt_errstr(status));
3767 return False;
3770 saved_vuid = cli_state_get_uid(cli);
3771 cli_state_set_uid(cli, new_vuid);
3773 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3774 printf("read succeeded with different vuid! "
3775 "nasty security hole [%s]\n", buf);
3776 ret = false;
3778 /* Try to open a file with different vuid, samba cnum. */
3779 if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3780 printf("create with different vuid, same cnum succeeded.\n");
3781 cli_close(cli, fnum2);
3782 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3783 } else {
3784 printf("create with different vuid, same cnum failed.\n");
3785 printf("This will cause problems with service clients.\n");
3786 ret = False;
3789 cli_state_set_uid(cli, saved_vuid);
3791 /* Try with same vuid, different cnum. */
3792 cli_state_set_tid(cli, new_cnum);
3794 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3795 printf("read succeeded with different cnum![%s]\n", buf);
3796 ret = false;
3799 cli_state_set_tid(cli, saved_cnum);
3800 cli_close(cli, fnum1);
3801 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3803 torture_close_connection(cli);
3805 printf("finished fdsesstest\n");
3806 return ret;
3810 This test checks that
3812 1) the server does not allow an unlink on a file that is open
3814 static bool run_unlinktest(int dummy)
3816 struct cli_state *cli;
3817 const char *fname = "\\unlink.tst";
3818 uint16_t fnum;
3819 bool correct = True;
3820 NTSTATUS status;
3822 if (!torture_open_connection(&cli, 0)) {
3823 return False;
3826 smbXcli_conn_set_sockopt(cli->conn, sockops);
3828 printf("starting unlink test\n");
3830 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3832 cli_setpid(cli, 1);
3834 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3835 if (!NT_STATUS_IS_OK(status)) {
3836 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3837 return False;
3840 status = cli_unlink(cli, fname,
3841 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3842 if (NT_STATUS_IS_OK(status)) {
3843 printf("error: server allowed unlink on an open file\n");
3844 correct = False;
3845 } else {
3846 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3847 NT_STATUS_SHARING_VIOLATION);
3850 cli_close(cli, fnum);
3851 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3853 if (!torture_close_connection(cli)) {
3854 correct = False;
3857 printf("unlink test finished\n");
3859 return correct;
3864 test how many open files this server supports on the one socket
3866 static bool run_maxfidtest(int dummy)
3868 struct cli_state *cli;
3869 fstring fname;
3870 uint16_t fnums[0x11000];
3871 int i;
3872 int retries=4;
3873 bool correct = True;
3874 NTSTATUS status;
3876 cli = current_cli;
3878 if (retries <= 0) {
3879 printf("failed to connect\n");
3880 return False;
3883 smbXcli_conn_set_sockopt(cli->conn, sockops);
3885 for (i=0; i<0x11000; i++) {
3886 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3887 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3888 &fnums[i]);
3889 if (!NT_STATUS_IS_OK(status)) {
3890 printf("open of %s failed (%s)\n",
3891 fname, nt_errstr(status));
3892 printf("maximum fnum is %d\n", i);
3893 break;
3895 printf("%6d\r", i);
3897 printf("%6d\n", i);
3898 i--;
3900 printf("cleaning up\n");
3901 for (;i>=0;i--) {
3902 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3903 cli_close(cli, fnums[i]);
3905 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3906 if (!NT_STATUS_IS_OK(status)) {
3907 printf("unlink of %s failed (%s)\n",
3908 fname, nt_errstr(status));
3909 correct = False;
3911 printf("%6d\r", i);
3913 printf("%6d\n", 0);
3915 printf("maxfid test finished\n");
3916 if (!torture_close_connection(cli)) {
3917 correct = False;
3919 return correct;
3922 /* generate a random buffer */
3923 static void rand_buf(char *buf, int len)
3925 while (len--) {
3926 *buf = (char)sys_random();
3927 buf++;
3931 /* send smb negprot commands, not reading the response */
3932 static bool run_negprot_nowait(int dummy)
3934 struct tevent_context *ev;
3935 int i;
3936 struct cli_state *cli;
3937 bool correct = True;
3939 printf("starting negprot nowait test\n");
3941 ev = samba_tevent_context_init(talloc_tos());
3942 if (ev == NULL) {
3943 return false;
3946 if (!(cli = open_nbt_connection())) {
3947 TALLOC_FREE(ev);
3948 return False;
3951 for (i=0;i<50000;i++) {
3952 struct tevent_req *req;
3954 req = smbXcli_negprot_send(
3957 cli->conn,
3958 cli->timeout,
3959 PROTOCOL_CORE,
3960 PROTOCOL_NT1,
3962 NULL);
3963 if (req == NULL) {
3964 TALLOC_FREE(ev);
3965 return false;
3967 if (!tevent_req_poll(req, ev)) {
3968 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3969 strerror(errno));
3970 TALLOC_FREE(ev);
3971 return false;
3973 TALLOC_FREE(req);
3976 if (torture_close_connection(cli)) {
3977 correct = False;
3980 printf("finished negprot nowait test\n");
3982 return correct;
3985 /* send smb negprot commands, not reading the response */
3986 static bool run_bad_nbt_session(int dummy)
3988 struct nmb_name called, calling;
3989 struct sockaddr_storage ss;
3990 NTSTATUS status;
3991 int fd;
3992 bool ret;
3994 printf("starting bad nbt session test\n");
3996 make_nmb_name(&calling, myname, 0x0);
3997 make_nmb_name(&called , host, 0x20);
3999 if (!resolve_name(host, &ss, 0x20, true)) {
4000 d_fprintf(stderr, "Could not resolve name %s\n", host);
4001 return false;
4004 status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4005 if (!NT_STATUS_IS_OK(status)) {
4006 d_fprintf(stderr, "open_socket_out failed: %s\n",
4007 nt_errstr(status));
4008 return false;
4011 ret = cli_bad_session_request(fd, &calling, &called);
4012 close(fd);
4013 if (!ret) {
4014 d_fprintf(stderr, "open_socket_out failed: %s\n",
4015 nt_errstr(status));
4016 return false;
4019 printf("finished bad nbt session test\n");
4020 return true;
4023 /* send random IPC commands */
4024 static bool run_randomipc(int dummy)
4026 char *rparam = NULL;
4027 char *rdata = NULL;
4028 unsigned int rdrcnt,rprcnt;
4029 char param[1024];
4030 int api, param_len, i;
4031 struct cli_state *cli;
4032 bool correct = True;
4033 int count = 50000;
4035 printf("starting random ipc test\n");
4037 if (!torture_open_connection(&cli, 0)) {
4038 return False;
4041 for (i=0;i<count;i++) {
4042 api = sys_random() % 500;
4043 param_len = (sys_random() % 64);
4045 rand_buf(param, param_len);
4047 SSVAL(param,0,api);
4049 cli_api(cli,
4050 param, param_len, 8,
4051 NULL, 0, CLI_BUFFER_SIZE,
4052 &rparam, &rprcnt,
4053 &rdata, &rdrcnt);
4054 if (i % 100 == 0) {
4055 printf("%d/%d\r", i,count);
4058 printf("%d/%d\n", i, count);
4060 if (!torture_close_connection(cli)) {
4061 correct = False;
4064 SAFE_FREE(rparam);
4065 SAFE_FREE(rdata);
4067 printf("finished random ipc test\n");
4069 return correct;
4074 static void browse_callback(const char *sname, uint32_t stype,
4075 const char *comment, void *state)
4077 printf("\t%20.20s %08x %s\n", sname, stype, comment);
4083 This test checks the browse list code
4086 static bool run_browsetest(int dummy)
4088 static struct cli_state *cli;
4089 bool correct = True;
4091 printf("starting browse test\n");
4093 if (!torture_open_connection(&cli, 0)) {
4094 return False;
4097 printf("domain list:\n");
4098 cli_NetServerEnum(cli, cli->server_domain,
4099 SV_TYPE_DOMAIN_ENUM,
4100 browse_callback, NULL);
4102 printf("machine list:\n");
4103 cli_NetServerEnum(cli, cli->server_domain,
4104 SV_TYPE_ALL,
4105 browse_callback, NULL);
4107 if (!torture_close_connection(cli)) {
4108 correct = False;
4111 printf("browse test finished\n");
4113 return correct;
4117 static bool check_attributes(struct cli_state *cli,
4118 const char *fname,
4119 uint32_t expected_attrs)
4121 uint32_t attrs = 0;
4122 NTSTATUS status = cli_getatr(cli,
4123 fname,
4124 &attrs,
4125 NULL,
4126 NULL);
4127 if (!NT_STATUS_IS_OK(status)) {
4128 printf("cli_getatr failed with %s\n",
4129 nt_errstr(status));
4130 return false;
4132 if (attrs != expected_attrs) {
4133 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4134 (unsigned int)attrs,
4135 (unsigned int)expected_attrs);
4136 return false;
4138 return true;
4142 This checks how the getatr calls works
4144 static bool run_attrtest(int dummy)
4146 struct cli_state *cli;
4147 uint16_t fnum;
4148 time_t t, t2;
4149 const char *fname = "\\attrib123456789.tst";
4150 bool correct = True;
4151 NTSTATUS status;
4153 printf("starting attrib test\n");
4155 if (!torture_open_connection(&cli, 0)) {
4156 return False;
4159 /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4160 status = cli_unlink(cli, fname, 0x20000);
4161 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4162 correct = false;
4163 goto out;
4166 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4167 cli_openx(cli, fname,
4168 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4169 cli_close(cli, fnum);
4171 status = cli_getatr(cli, fname, NULL, NULL, &t);
4172 if (!NT_STATUS_IS_OK(status)) {
4173 printf("getatr failed (%s)\n", nt_errstr(status));
4174 correct = False;
4177 if (labs(t - time(NULL)) > 60*60*24*10) {
4178 printf("ERROR: SMBgetatr bug. time is %s",
4179 ctime(&t));
4180 t = time(NULL);
4181 correct = True;
4184 t2 = t-60*60*24; /* 1 day ago */
4186 /* Ensure we can't set with out-of-range (unknown) attribute. */
4187 status = cli_setatr(cli, fname, 0x20000, t2);
4188 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4189 correct = false;
4190 goto out;
4193 status = cli_setatr(cli, fname, 0, t2);
4194 if (!NT_STATUS_IS_OK(status)) {
4195 printf("setatr failed (%s)\n", nt_errstr(status));
4196 correct = True;
4199 status = cli_getatr(cli, fname, NULL, NULL, &t);
4200 if (!NT_STATUS_IS_OK(status)) {
4201 printf("getatr failed (%s)\n", nt_errstr(status));
4202 correct = True;
4205 if (t != t2) {
4206 printf("ERROR: getatr/setatr bug. times are\n%s",
4207 ctime(&t));
4208 printf("%s", ctime(&t2));
4209 correct = True;
4212 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4214 /* Check cli_setpathinfo_ext() */
4215 /* Re-create the file. */
4216 status = cli_openx(cli, fname,
4217 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4218 if (!NT_STATUS_IS_OK(status)) {
4219 printf("Failed to recreate %s (%s)\n",
4220 fname, nt_errstr(status));
4221 correct = false;
4223 cli_close(cli, fnum);
4225 status = cli_setpathinfo_ext(
4226 cli,
4227 fname,
4228 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4229 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4230 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4231 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4232 FILE_ATTRIBUTE_SYSTEM |
4233 FILE_ATTRIBUTE_HIDDEN |
4234 FILE_ATTRIBUTE_READONLY);
4235 if (!NT_STATUS_IS_OK(status)) {
4236 printf("cli_setpathinfo_ext failed with %s\n",
4237 nt_errstr(status));
4238 correct = false;
4241 /* Check attributes are correct. */
4242 correct = check_attributes(cli,
4243 fname,
4244 FILE_ATTRIBUTE_SYSTEM |
4245 FILE_ATTRIBUTE_HIDDEN |
4246 FILE_ATTRIBUTE_READONLY);
4247 if (correct == false) {
4248 goto out;
4251 /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4252 status = cli_setpathinfo_ext(
4253 cli,
4254 fname,
4255 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4256 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4257 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4258 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4259 FILE_ATTRIBUTE_NORMAL);
4260 if (!NT_STATUS_IS_OK(status)) {
4261 printf("cli_setpathinfo_ext failed with %s\n",
4262 nt_errstr(status));
4263 correct = false;
4266 /* Check attributes are correct. */
4267 correct = check_attributes(cli,
4268 fname,
4269 FILE_ATTRIBUTE_SYSTEM |
4270 FILE_ATTRIBUTE_HIDDEN |
4271 FILE_ATTRIBUTE_READONLY);
4272 if (correct == false) {
4273 goto out;
4276 /* Setting to (uint16_t)-1 should also be ignored. */
4277 status = cli_setpathinfo_ext(
4278 cli,
4279 fname,
4280 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4281 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4282 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4283 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4284 (uint32_t)-1);
4285 if (!NT_STATUS_IS_OK(status)) {
4286 printf("cli_setpathinfo_ext failed with %s\n",
4287 nt_errstr(status));
4288 correct = false;
4291 /* Check attributes are correct. */
4292 correct = check_attributes(cli,
4293 fname,
4294 FILE_ATTRIBUTE_SYSTEM |
4295 FILE_ATTRIBUTE_HIDDEN |
4296 FILE_ATTRIBUTE_READONLY);
4297 if (correct == false) {
4298 goto out;
4301 /* Setting to 0 should clear them all. */
4302 status = cli_setpathinfo_ext(
4303 cli,
4304 fname,
4305 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4306 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4307 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4308 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4310 if (!NT_STATUS_IS_OK(status)) {
4311 printf("cli_setpathinfo_ext failed with %s\n",
4312 nt_errstr(status));
4313 correct = false;
4316 /* Check attributes are correct. */
4317 correct = check_attributes(cli,
4318 fname,
4319 FILE_ATTRIBUTE_NORMAL);
4320 if (correct == false) {
4321 goto out;
4324 out:
4326 cli_unlink(cli,
4327 fname,
4328 FILE_ATTRIBUTE_SYSTEM |
4329 FILE_ATTRIBUTE_HIDDEN|
4330 FILE_ATTRIBUTE_READONLY);
4332 if (!torture_close_connection(cli)) {
4333 correct = False;
4336 printf("attrib test finished\n");
4338 return correct;
4341 static NTSTATUS cli_qfilename(
4342 struct cli_state *cli,
4343 uint16_t fnum,
4344 TALLOC_CTX *mem_ctx,
4345 char **_name)
4347 uint16_t recv_flags2;
4348 uint8_t *rdata;
4349 uint32_t num_rdata;
4350 NTSTATUS status;
4351 char *name = NULL;
4352 uint32_t namelen;
4354 status = cli_qfileinfo(talloc_tos(), cli, fnum,
4355 SMB_QUERY_FILE_NAME_INFO,
4356 4, CLI_BUFFER_SIZE, &recv_flags2,
4357 &rdata, &num_rdata);
4358 if (!NT_STATUS_IS_OK(status)) {
4359 return status;
4362 namelen = IVAL(rdata, 0);
4363 if (namelen > (num_rdata - 4)) {
4364 TALLOC_FREE(rdata);
4365 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4368 pull_string_talloc(mem_ctx,
4369 (const char *)rdata,
4370 recv_flags2,
4371 &name,
4372 rdata + 4,
4373 namelen,
4374 STR_UNICODE);
4375 if (name == NULL) {
4376 status = map_nt_error_from_unix(errno);
4377 TALLOC_FREE(rdata);
4378 return status;
4381 *_name = name;
4382 TALLOC_FREE(rdata);
4383 return NT_STATUS_OK;
4387 This checks a couple of trans2 calls
4389 static bool run_trans2test(int dummy)
4391 struct cli_state *cli;
4392 uint16_t fnum;
4393 off_t size;
4394 time_t c_time, a_time, m_time;
4395 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4396 const char *fname = "\\trans2.tst";
4397 const char *dname = "\\trans2";
4398 const char *fname2 = "\\trans2\\trans2.tst";
4399 char *pname = NULL;
4400 bool correct = True;
4401 NTSTATUS status;
4402 uint32_t fs_attr;
4403 uint64_t ino;
4405 printf("starting trans2 test\n");
4407 if (!torture_open_connection(&cli, 0)) {
4408 return False;
4411 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4412 /* Ensure ino is zero, SMB2 gets a real one. */
4413 ino = 0;
4414 } else {
4415 /* Ensure ino is -1, SMB1 never gets a real one. */
4416 ino = (uint64_t)-1;
4419 status = cli_get_fs_attr_info(cli, &fs_attr);
4420 if (!NT_STATUS_IS_OK(status)) {
4421 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4422 nt_errstr(status));
4423 correct = false;
4426 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4427 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4428 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4429 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4430 if (!NT_STATUS_IS_OK(status)) {
4431 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4432 correct = False;
4435 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4436 if (!NT_STATUS_IS_OK(status)) {
4437 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4438 correct = False;
4440 else if (strcmp(pname, fname)) {
4441 printf("qfilename gave different name? [%s] [%s]\n",
4442 fname, pname);
4443 correct = False;
4446 cli_close(cli, fnum);
4448 sleep(2);
4450 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4451 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4452 &fnum);
4453 if (!NT_STATUS_IS_OK(status)) {
4454 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4455 return False;
4457 cli_close(cli, fnum);
4459 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4460 NULL);
4461 if (!NT_STATUS_IS_OK(status)) {
4462 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4463 correct = False;
4464 } else {
4465 time_t t = time(NULL);
4467 if (c_time != m_time) {
4468 printf("create time=%s", ctime(&c_time));
4469 printf("modify time=%s", ctime(&m_time));
4470 printf("This system appears to have sticky create times\n");
4472 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4473 printf("access time=%s", ctime(&a_time));
4474 printf("This system appears to set a midnight access time\n");
4475 correct = False;
4478 if (labs(m_time - t) > 60*60*24*7) {
4479 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4480 correct = False;
4485 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4486 cli_openx(cli, fname,
4487 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4488 cli_close(cli, fnum);
4489 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
4490 &m_time_ts, &size, NULL, &ino);
4491 if (!NT_STATUS_IS_OK(status)) {
4492 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4493 correct = False;
4494 } else {
4495 if (w_time_ts.tv_sec < 60*60*24*2) {
4496 printf("write time=%s", ctime(&w_time_ts.tv_sec));
4497 printf("This system appears to set a initial 0 write time\n");
4498 correct = False;
4500 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4501 /* SMB2 should always return an inode. */
4502 if (ino == 0) {
4503 printf("SMB2 bad inode (0)\n");
4504 correct = false;
4506 } else {
4507 /* SMB1 must always return zero here. */
4508 if (ino != 0) {
4509 printf("SMB1 bad inode (!0)\n");
4510 correct = false;
4515 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4518 /* check if the server updates the directory modification time
4519 when creating a new file */
4520 status = cli_mkdir(cli, dname);
4521 if (!NT_STATUS_IS_OK(status)) {
4522 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4523 correct = False;
4525 sleep(3);
4526 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4527 &w_time_ts, &m_time_ts, &size, NULL, NULL);
4528 if (!NT_STATUS_IS_OK(status)) {
4529 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4530 correct = False;
4533 cli_openx(cli, fname2,
4534 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4535 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4536 cli_close(cli, fnum);
4537 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4538 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
4539 if (!NT_STATUS_IS_OK(status)) {
4540 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4541 correct = False;
4542 } else {
4543 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4544 == 0) {
4545 printf("This system does not update directory modification times\n");
4546 correct = False;
4549 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4550 cli_rmdir(cli, dname);
4552 if (!torture_close_connection(cli)) {
4553 correct = False;
4556 printf("trans2 test finished\n");
4558 return correct;
4562 This checks new W2K calls.
4565 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4567 uint8_t *buf = NULL;
4568 uint32_t len;
4569 NTSTATUS status;
4571 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4572 CLI_BUFFER_SIZE, NULL, &buf, &len);
4573 if (!NT_STATUS_IS_OK(status)) {
4574 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4575 nt_errstr(status));
4576 } else {
4577 printf("qfileinfo: level %d, len = %u\n", level, len);
4578 dump_data(0, (uint8_t *)buf, len);
4579 printf("\n");
4581 TALLOC_FREE(buf);
4582 return status;
4585 static bool run_w2ktest(int dummy)
4587 struct cli_state *cli;
4588 uint16_t fnum;
4589 const char *fname = "\\w2ktest\\w2k.tst";
4590 int level;
4591 bool correct = True;
4593 printf("starting w2k test\n");
4595 if (!torture_open_connection(&cli, 0)) {
4596 return False;
4599 cli_openx(cli, fname,
4600 O_RDWR | O_CREAT , DENY_NONE, &fnum);
4602 for (level = 1004; level < 1040; level++) {
4603 new_trans(cli, fnum, level);
4606 cli_close(cli, fnum);
4608 if (!torture_close_connection(cli)) {
4609 correct = False;
4612 printf("w2k test finished\n");
4614 return correct;
4619 this is a harness for some oplock tests
4621 static bool run_oplock1(int dummy)
4623 struct cli_state *cli1;
4624 const char *fname = "\\lockt1.lck";
4625 uint16_t fnum1;
4626 bool correct = True;
4627 NTSTATUS status;
4629 printf("starting oplock test 1\n");
4631 if (!torture_open_connection(&cli1, 0)) {
4632 return False;
4635 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4637 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4639 cli1->use_oplocks = True;
4641 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4642 &fnum1);
4643 if (!NT_STATUS_IS_OK(status)) {
4644 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4645 return False;
4648 cli1->use_oplocks = False;
4650 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4651 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4653 status = cli_close(cli1, fnum1);
4654 if (!NT_STATUS_IS_OK(status)) {
4655 printf("close2 failed (%s)\n", nt_errstr(status));
4656 return False;
4659 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4660 if (!NT_STATUS_IS_OK(status)) {
4661 printf("unlink failed (%s)\n", nt_errstr(status));
4662 return False;
4665 if (!torture_close_connection(cli1)) {
4666 correct = False;
4669 printf("finished oplock test 1\n");
4671 return correct;
4674 static bool run_oplock2(int dummy)
4676 struct cli_state *cli1, *cli2;
4677 const char *fname = "\\lockt2.lck";
4678 uint16_t fnum1, fnum2;
4679 int saved_use_oplocks = use_oplocks;
4680 char buf[4];
4681 bool correct = True;
4682 volatile bool *shared_correct;
4683 size_t nread;
4684 NTSTATUS status;
4686 shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4687 *shared_correct = True;
4689 use_level_II_oplocks = True;
4690 use_oplocks = True;
4692 printf("starting oplock test 2\n");
4694 if (!torture_open_connection(&cli1, 0)) {
4695 use_level_II_oplocks = False;
4696 use_oplocks = saved_use_oplocks;
4697 return False;
4700 if (!torture_open_connection(&cli2, 1)) {
4701 use_level_II_oplocks = False;
4702 use_oplocks = saved_use_oplocks;
4703 return False;
4706 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4708 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4709 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4711 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4712 &fnum1);
4713 if (!NT_STATUS_IS_OK(status)) {
4714 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4715 return False;
4718 /* Don't need the globals any more. */
4719 use_level_II_oplocks = False;
4720 use_oplocks = saved_use_oplocks;
4722 if (fork() == 0) {
4723 /* Child code */
4724 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4725 if (!NT_STATUS_IS_OK(status)) {
4726 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4727 *shared_correct = False;
4728 exit(0);
4731 sleep(2);
4733 status = cli_close(cli2, fnum2);
4734 if (!NT_STATUS_IS_OK(status)) {
4735 printf("close2 failed (%s)\n", nt_errstr(status));
4736 *shared_correct = False;
4739 exit(0);
4742 sleep(2);
4744 /* Ensure cli1 processes the break. Empty file should always return 0
4745 * bytes. */
4746 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4747 if (!NT_STATUS_IS_OK(status)) {
4748 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4749 correct = false;
4750 } else if (nread != 0) {
4751 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4752 (unsigned long)nread, 0);
4753 correct = false;
4756 /* Should now be at level II. */
4757 /* Test if sending a write locks causes a break to none. */
4758 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4759 if (!NT_STATUS_IS_OK(status)) {
4760 printf("lock failed (%s)\n", nt_errstr(status));
4761 correct = False;
4764 cli_unlock(cli1, fnum1, 0, 4);
4766 sleep(2);
4768 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4769 if (!NT_STATUS_IS_OK(status)) {
4770 printf("lock failed (%s)\n", nt_errstr(status));
4771 correct = False;
4774 cli_unlock(cli1, fnum1, 0, 4);
4776 sleep(2);
4778 cli_read(cli1, fnum1, buf, 0, 4, NULL);
4780 status = cli_close(cli1, fnum1);
4781 if (!NT_STATUS_IS_OK(status)) {
4782 printf("close1 failed (%s)\n", nt_errstr(status));
4783 correct = False;
4786 sleep(4);
4788 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4789 if (!NT_STATUS_IS_OK(status)) {
4790 printf("unlink failed (%s)\n", nt_errstr(status));
4791 correct = False;
4794 if (!torture_close_connection(cli1)) {
4795 correct = False;
4798 if (!*shared_correct) {
4799 correct = False;
4802 printf("finished oplock test 2\n");
4804 return correct;
4807 struct oplock4_state {
4808 struct tevent_context *ev;
4809 struct cli_state *cli;
4810 bool *got_break;
4811 uint16_t *fnum2;
4814 static void oplock4_got_break(struct tevent_req *req);
4815 static void oplock4_got_open(struct tevent_req *req);
4817 static bool run_oplock4(int dummy)
4819 struct tevent_context *ev;
4820 struct cli_state *cli1, *cli2;
4821 struct tevent_req *oplock_req, *open_req;
4822 const char *fname = "\\lockt4.lck";
4823 const char *fname_ln = "\\lockt4_ln.lck";
4824 uint16_t fnum1, fnum2;
4825 int saved_use_oplocks = use_oplocks;
4826 NTSTATUS status;
4827 bool correct = true;
4829 bool got_break;
4831 struct oplock4_state *state;
4833 printf("starting oplock test 4\n");
4835 if (!torture_open_connection(&cli1, 0)) {
4836 use_level_II_oplocks = false;
4837 use_oplocks = saved_use_oplocks;
4838 return false;
4841 if (!torture_open_connection(&cli2, 1)) {
4842 use_level_II_oplocks = false;
4843 use_oplocks = saved_use_oplocks;
4844 return false;
4847 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4848 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4850 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4851 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4853 /* Create the file. */
4854 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4855 &fnum1);
4856 if (!NT_STATUS_IS_OK(status)) {
4857 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4858 return false;
4861 status = cli_close(cli1, fnum1);
4862 if (!NT_STATUS_IS_OK(status)) {
4863 printf("close1 failed (%s)\n", nt_errstr(status));
4864 return false;
4867 /* Now create a hardlink. */
4868 status = cli_hardlink(cli1, fname, fname_ln);
4869 if (!NT_STATUS_IS_OK(status)) {
4870 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4871 return false;
4874 /* Prove that opening hardlinks cause deny modes to conflict. */
4875 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4876 if (!NT_STATUS_IS_OK(status)) {
4877 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4878 return false;
4881 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4882 if (NT_STATUS_IS_OK(status)) {
4883 printf("open of %s succeeded - should fail with sharing violation.\n",
4884 fname_ln);
4885 return false;
4888 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4889 printf("open of %s should fail with sharing violation. Got %s\n",
4890 fname_ln, nt_errstr(status));
4891 return false;
4894 status = cli_close(cli1, fnum1);
4895 if (!NT_STATUS_IS_OK(status)) {
4896 printf("close1 failed (%s)\n", nt_errstr(status));
4897 return false;
4900 cli1->use_oplocks = true;
4901 cli2->use_oplocks = true;
4903 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4904 if (!NT_STATUS_IS_OK(status)) {
4905 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4906 return false;
4909 ev = samba_tevent_context_init(talloc_tos());
4910 if (ev == NULL) {
4911 printf("tevent_context_init failed\n");
4912 return false;
4915 state = talloc(ev, struct oplock4_state);
4916 if (state == NULL) {
4917 printf("talloc failed\n");
4918 return false;
4920 state->ev = ev;
4921 state->cli = cli1;
4922 state->got_break = &got_break;
4923 state->fnum2 = &fnum2;
4925 oplock_req = cli_smb_oplock_break_waiter_send(
4926 talloc_tos(), ev, cli1);
4927 if (oplock_req == NULL) {
4928 printf("cli_smb_oplock_break_waiter_send failed\n");
4929 return false;
4931 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
4933 open_req = cli_openx_send(
4934 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
4935 if (open_req == NULL) {
4936 printf("cli_openx_send failed\n");
4937 return false;
4939 tevent_req_set_callback(open_req, oplock4_got_open, state);
4941 got_break = false;
4942 fnum2 = 0xffff;
4944 while (!got_break || fnum2 == 0xffff) {
4945 int ret;
4946 ret = tevent_loop_once(ev);
4947 if (ret == -1) {
4948 printf("tevent_loop_once failed: %s\n",
4949 strerror(errno));
4950 return false;
4954 status = cli_close(cli2, fnum2);
4955 if (!NT_STATUS_IS_OK(status)) {
4956 printf("close2 failed (%s)\n", nt_errstr(status));
4957 correct = false;
4960 status = cli_close(cli1, fnum1);
4961 if (!NT_STATUS_IS_OK(status)) {
4962 printf("close1 failed (%s)\n", nt_errstr(status));
4963 correct = false;
4966 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4967 if (!NT_STATUS_IS_OK(status)) {
4968 printf("unlink failed (%s)\n", nt_errstr(status));
4969 correct = false;
4972 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4973 if (!NT_STATUS_IS_OK(status)) {
4974 printf("unlink failed (%s)\n", nt_errstr(status));
4975 correct = false;
4978 if (!torture_close_connection(cli1)) {
4979 correct = false;
4982 if (!got_break) {
4983 correct = false;
4986 printf("finished oplock test 4\n");
4988 return correct;
4991 static void oplock4_got_break(struct tevent_req *req)
4993 struct oplock4_state *state = tevent_req_callback_data(
4994 req, struct oplock4_state);
4995 uint16_t fnum;
4996 uint8_t level;
4997 NTSTATUS status;
4999 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
5000 TALLOC_FREE(req);
5001 if (!NT_STATUS_IS_OK(status)) {
5002 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5003 nt_errstr(status));
5004 return;
5006 *state->got_break = true;
5008 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5009 NO_OPLOCK);
5010 if (req == NULL) {
5011 printf("cli_oplock_ack_send failed\n");
5012 return;
5016 static void oplock4_got_open(struct tevent_req *req)
5018 struct oplock4_state *state = tevent_req_callback_data(
5019 req, struct oplock4_state);
5020 NTSTATUS status;
5022 status = cli_openx_recv(req, state->fnum2);
5023 if (!NT_STATUS_IS_OK(status)) {
5024 printf("cli_openx_recv returned %s\n", nt_errstr(status));
5025 *state->fnum2 = 0xffff;
5029 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5031 struct oplock5_state {
5032 int pipe_down_fd;
5036 * Async open the file that has a kernel oplock, do an echo to get
5037 * that 100% across, close the file to signal to the child fd that the
5038 * oplock can be dropped, wait for the open reply.
5041 static void oplock5_opened(struct tevent_req *subreq);
5042 static void oplock5_pong(struct tevent_req *subreq);
5043 static void oplock5_timedout(struct tevent_req *subreq);
5045 static struct tevent_req *oplock5_send(
5046 TALLOC_CTX *mem_ctx,
5047 struct tevent_context *ev,
5048 struct cli_state *cli,
5049 const char *fname,
5050 int pipe_down_fd)
5052 struct tevent_req *req = NULL, *subreq = NULL;
5053 struct oplock5_state *state = NULL;
5054 static uint8_t data = 0;
5056 req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5057 if (req == NULL) {
5058 return NULL;
5060 state->pipe_down_fd = pipe_down_fd;
5062 subreq = cli_ntcreate_send(
5063 state,
5065 cli,
5066 fname,
5067 0, /* CreatFlags */
5068 SEC_FILE_READ_DATA, /* DesiredAccess */
5069 FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
5070 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5071 FILE_OPEN, /* CreateDisposition */
5072 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5073 0, /* Impersonation */
5074 0); /* SecurityFlags */
5075 if (tevent_req_nomem(subreq, req)) {
5076 return tevent_req_post(req, ev);
5078 tevent_req_set_callback(subreq, oplock5_opened, req);
5080 subreq = cli_echo_send(
5081 state,
5083 cli,
5085 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5086 if (tevent_req_nomem(subreq, req)) {
5087 return tevent_req_post(req, ev);
5089 tevent_req_set_callback(subreq, oplock5_pong, req);
5091 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5092 if (tevent_req_nomem(subreq, req)) {
5093 return tevent_req_post(req, ev);
5095 tevent_req_set_callback(subreq, oplock5_timedout, req);
5097 return req;
5100 static void oplock5_opened(struct tevent_req *subreq)
5102 struct tevent_req *req = tevent_req_callback_data(
5103 subreq, struct tevent_req);
5104 NTSTATUS status;
5105 uint16_t fnum;
5107 status = cli_ntcreate_recv(subreq, &fnum, NULL);
5108 TALLOC_FREE(subreq);
5109 if (tevent_req_nterror(req, status)) {
5110 return;
5112 tevent_req_done(req);
5115 static void oplock5_pong(struct tevent_req *subreq)
5117 struct tevent_req *req = tevent_req_callback_data(
5118 subreq, struct tevent_req);
5119 struct oplock5_state *state = tevent_req_data(
5120 req, struct oplock5_state);
5121 NTSTATUS status;
5123 status = cli_echo_recv(subreq);
5124 TALLOC_FREE(subreq);
5125 if (tevent_req_nterror(req, status)) {
5126 return;
5129 close(state->pipe_down_fd);
5132 static void oplock5_timedout(struct tevent_req *subreq)
5134 struct tevent_req *req = tevent_req_callback_data(
5135 subreq, struct tevent_req);
5136 bool ok;
5138 ok = tevent_wakeup_recv(subreq);
5139 TALLOC_FREE(subreq);
5140 if (!ok) {
5141 tevent_req_oom(req);
5142 return;
5144 tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5147 static NTSTATUS oplock5_recv(struct tevent_req *req)
5149 return tevent_req_simple_recv_ntstatus(req);
5152 static bool run_oplock5(int dummy)
5154 struct tevent_context *ev = NULL;
5155 struct tevent_req *req = NULL;
5156 struct cli_state *cli = NULL;
5157 const char *fname = "oplock5.txt";
5158 int pipe_down[2], pipe_up[2];
5159 pid_t child_pid;
5160 uint8_t c = '\0';
5161 NTSTATUS status;
5162 int ret;
5163 bool ok;
5165 printf("starting oplock5\n");
5167 if (local_path == NULL) {
5168 d_fprintf(stderr, "oplock5 must be given a local path via "
5169 "-l <localpath>\n");
5170 return false;
5173 ret = pipe(pipe_down);
5174 if (ret == -1) {
5175 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5176 return false;
5178 ret = pipe(pipe_up);
5179 if (ret == -1) {
5180 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5181 return false;
5184 child_pid = fork();
5185 if (child_pid == -1) {
5186 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5187 return false;
5190 if (child_pid == 0) {
5191 char *local_file = NULL;
5192 int fd;
5194 close(pipe_down[1]);
5195 close(pipe_up[0]);
5197 local_file = talloc_asprintf(
5198 talloc_tos(), "%s/%s", local_path, fname);
5199 if (local_file == 0) {
5200 c = 1;
5201 goto do_write;
5203 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5204 if (fd == -1) {
5205 d_fprintf(stderr,
5206 "open(%s) in child failed: %s\n",
5207 local_file,
5208 strerror(errno));
5209 c = 2;
5210 goto do_write;
5213 signal(SIGIO, SIG_IGN);
5215 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5216 if (ret == -1) {
5217 d_fprintf(stderr,
5218 "SETLEASE in child failed: %s\n",
5219 strerror(errno));
5220 c = 3;
5221 goto do_write;
5224 do_write:
5225 ret = sys_write(pipe_up[1], &c, sizeof(c));
5226 if (ret == -1) {
5227 d_fprintf(stderr,
5228 "sys_write failed: %s\n",
5229 strerror(errno));
5230 exit(4);
5232 ret = sys_read(pipe_down[0], &c, sizeof(c));
5233 if (ret == -1) {
5234 d_fprintf(stderr,
5235 "sys_read failed: %s\n",
5236 strerror(errno));
5237 exit(5);
5239 exit(0);
5242 close(pipe_up[1]);
5243 close(pipe_down[0]);
5245 ret = sys_read(pipe_up[0], &c, sizeof(c));
5246 if (ret != 1) {
5247 d_fprintf(stderr,
5248 "sys_read failed: %s\n",
5249 strerror(errno));
5250 return false;
5252 if (c != 0) {
5253 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5254 return false;
5257 ok = torture_open_connection(&cli, 0);
5258 if (!ok) {
5259 d_fprintf(stderr, "torture_open_connection failed\n");
5260 return false;
5263 ev = samba_tevent_context_init(talloc_tos());
5264 if (ev == NULL) {
5265 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5266 return false;
5269 req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5270 if (req == NULL) {
5271 d_fprintf(stderr, "oplock5_send failed\n");
5272 return false;
5275 ok = tevent_req_poll_ntstatus(req, ev, &status);
5276 if (!ok) {
5277 d_fprintf(stderr,
5278 "tevent_req_poll_ntstatus failed: %s\n",
5279 nt_errstr(status));
5280 return false;
5283 status = oplock5_recv(req);
5284 TALLOC_FREE(req);
5285 if (!NT_STATUS_IS_OK(status)) {
5286 d_fprintf(stderr,
5287 "oplock5 failed: %s\n",
5288 nt_errstr(status));
5289 return false;
5292 return true;
5295 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5298 Test delete on close semantics.
5300 static bool run_deletetest(int dummy)
5302 struct cli_state *cli1 = NULL;
5303 struct cli_state *cli2 = NULL;
5304 const char *fname = "\\delete.file";
5305 uint16_t fnum1 = (uint16_t)-1;
5306 uint16_t fnum2 = (uint16_t)-1;
5307 bool correct = false;
5308 NTSTATUS status;
5310 printf("starting delete test\n");
5312 if (!torture_open_connection(&cli1, 0)) {
5313 return False;
5316 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5318 /* Test 1 - this should delete the file on close. */
5320 cli_setatr(cli1, fname, 0, 0);
5321 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5323 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5324 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5325 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5326 if (!NT_STATUS_IS_OK(status)) {
5327 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5328 goto fail;
5331 status = cli_close(cli1, fnum1);
5332 if (!NT_STATUS_IS_OK(status)) {
5333 printf("[1] close failed (%s)\n", nt_errstr(status));
5334 goto fail;
5337 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5338 if (NT_STATUS_IS_OK(status)) {
5339 printf("[1] open of %s succeeded (should fail)\n", fname);
5340 goto fail;
5343 printf("first delete on close test succeeded.\n");
5345 /* Test 2 - this should delete the file on close. */
5347 cli_setatr(cli1, fname, 0, 0);
5348 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5350 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5351 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5352 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5353 if (!NT_STATUS_IS_OK(status)) {
5354 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5355 goto fail;
5358 status = cli_nt_delete_on_close(cli1, fnum1, true);
5359 if (!NT_STATUS_IS_OK(status)) {
5360 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5361 goto fail;
5364 status = cli_close(cli1, fnum1);
5365 if (!NT_STATUS_IS_OK(status)) {
5366 printf("[2] close failed (%s)\n", nt_errstr(status));
5367 goto fail;
5370 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5371 if (NT_STATUS_IS_OK(status)) {
5372 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5373 status = cli_close(cli1, fnum1);
5374 if (!NT_STATUS_IS_OK(status)) {
5375 printf("[2] close failed (%s)\n", nt_errstr(status));
5377 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5378 goto fail;
5381 printf("second delete on close test succeeded.\n");
5383 /* Test 3 - ... */
5384 cli_setatr(cli1, fname, 0, 0);
5385 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5387 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5388 FILE_ATTRIBUTE_NORMAL,
5389 FILE_SHARE_READ|FILE_SHARE_WRITE,
5390 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5391 if (!NT_STATUS_IS_OK(status)) {
5392 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5393 goto fail;
5396 /* This should fail with a sharing violation - open for delete is only compatible
5397 with SHARE_DELETE. */
5399 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5400 FILE_ATTRIBUTE_NORMAL,
5401 FILE_SHARE_READ|FILE_SHARE_WRITE,
5402 FILE_OPEN, 0, 0, &fnum2, NULL);
5403 if (NT_STATUS_IS_OK(status)) {
5404 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
5405 goto fail;
5408 /* This should succeed. */
5409 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5410 FILE_ATTRIBUTE_NORMAL,
5411 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5412 FILE_OPEN, 0, 0, &fnum2, NULL);
5413 if (!NT_STATUS_IS_OK(status)) {
5414 printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5415 goto fail;
5418 status = cli_nt_delete_on_close(cli1, fnum1, true);
5419 if (!NT_STATUS_IS_OK(status)) {
5420 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5421 goto fail;
5424 status = cli_close(cli1, fnum1);
5425 if (!NT_STATUS_IS_OK(status)) {
5426 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5427 goto fail;
5430 status = cli_close(cli1, fnum2);
5431 if (!NT_STATUS_IS_OK(status)) {
5432 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5433 goto fail;
5436 /* This should fail - file should no longer be there. */
5438 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5439 if (NT_STATUS_IS_OK(status)) {
5440 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5441 status = cli_close(cli1, fnum1);
5442 if (!NT_STATUS_IS_OK(status)) {
5443 printf("[3] close failed (%s)\n", nt_errstr(status));
5445 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5446 goto fail;
5449 printf("third delete on close test succeeded.\n");
5451 /* Test 4 ... */
5452 cli_setatr(cli1, fname, 0, 0);
5453 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5455 status = cli_ntcreate(cli1, fname, 0,
5456 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5457 FILE_ATTRIBUTE_NORMAL,
5458 FILE_SHARE_READ|FILE_SHARE_WRITE,
5459 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5460 if (!NT_STATUS_IS_OK(status)) {
5461 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5462 goto fail;
5465 /* This should succeed. */
5466 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5467 FILE_ATTRIBUTE_NORMAL,
5468 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5469 FILE_OPEN, 0, 0, &fnum2, NULL);
5470 if (!NT_STATUS_IS_OK(status)) {
5471 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5472 goto fail;
5475 status = cli_close(cli1, fnum2);
5476 if (!NT_STATUS_IS_OK(status)) {
5477 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5478 goto fail;
5481 status = cli_nt_delete_on_close(cli1, fnum1, true);
5482 if (!NT_STATUS_IS_OK(status)) {
5483 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5484 goto fail;
5487 /* This should fail - no more opens once delete on close set. */
5488 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5489 FILE_ATTRIBUTE_NORMAL,
5490 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5491 FILE_OPEN, 0, 0, &fnum2, NULL);
5492 if (NT_STATUS_IS_OK(status)) {
5493 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
5494 goto fail;
5497 status = cli_close(cli1, fnum1);
5498 if (!NT_STATUS_IS_OK(status)) {
5499 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5500 goto fail;
5503 printf("fourth delete on close test succeeded.\n");
5505 /* Test 5 ... */
5506 cli_setatr(cli1, fname, 0, 0);
5507 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5509 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5510 if (!NT_STATUS_IS_OK(status)) {
5511 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5512 goto fail;
5515 /* This should fail - only allowed on NT opens with DELETE access. */
5517 status = cli_nt_delete_on_close(cli1, fnum1, true);
5518 if (NT_STATUS_IS_OK(status)) {
5519 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5520 goto fail;
5523 status = cli_close(cli1, fnum1);
5524 if (!NT_STATUS_IS_OK(status)) {
5525 printf("[5] close failed (%s)\n", nt_errstr(status));
5526 goto fail;
5529 printf("fifth delete on close test succeeded.\n");
5531 /* Test 6 ... */
5532 cli_setatr(cli1, fname, 0, 0);
5533 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5535 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5536 FILE_ATTRIBUTE_NORMAL,
5537 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5538 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5539 if (!NT_STATUS_IS_OK(status)) {
5540 printf("[6] open of %s failed (%s)\n", fname,
5541 nt_errstr(status));
5542 goto fail;
5545 /* This should fail - only allowed on NT opens with DELETE access. */
5547 status = cli_nt_delete_on_close(cli1, fnum1, true);
5548 if (NT_STATUS_IS_OK(status)) {
5549 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5550 goto fail;
5553 status = cli_close(cli1, fnum1);
5554 if (!NT_STATUS_IS_OK(status)) {
5555 printf("[6] close failed (%s)\n", nt_errstr(status));
5556 goto fail;
5559 printf("sixth delete on close test succeeded.\n");
5561 /* Test 7 ... */
5562 cli_setatr(cli1, fname, 0, 0);
5563 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5565 status = cli_ntcreate(cli1, fname, 0,
5566 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5567 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5568 0, 0, &fnum1, NULL);
5569 if (!NT_STATUS_IS_OK(status)) {
5570 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5571 goto fail;
5574 status = cli_nt_delete_on_close(cli1, fnum1, true);
5575 if (!NT_STATUS_IS_OK(status)) {
5576 printf("[7] setting delete_on_close on file failed !\n");
5577 goto fail;
5580 status = cli_nt_delete_on_close(cli1, fnum1, false);
5581 if (!NT_STATUS_IS_OK(status)) {
5582 printf("[7] unsetting delete_on_close on file failed !\n");
5583 goto fail;
5586 status = cli_close(cli1, fnum1);
5587 if (!NT_STATUS_IS_OK(status)) {
5588 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5589 goto fail;
5592 /* This next open should succeed - we reset the flag. */
5593 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5594 if (!NT_STATUS_IS_OK(status)) {
5595 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5596 goto fail;
5599 status = cli_close(cli1, fnum1);
5600 if (!NT_STATUS_IS_OK(status)) {
5601 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5602 goto fail;
5605 printf("seventh delete on close test succeeded.\n");
5607 /* Test 8 ... */
5608 cli_setatr(cli1, fname, 0, 0);
5609 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5611 if (!torture_open_connection(&cli2, 1)) {
5612 printf("[8] failed to open second connection.\n");
5613 goto fail;
5616 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5618 status = cli_ntcreate(cli1, fname, 0,
5619 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5620 FILE_ATTRIBUTE_NORMAL,
5621 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5622 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5623 if (!NT_STATUS_IS_OK(status)) {
5624 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5625 goto fail;
5628 status = cli_ntcreate(cli2, fname, 0,
5629 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5630 FILE_ATTRIBUTE_NORMAL,
5631 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5632 FILE_OPEN, 0, 0, &fnum2, NULL);
5633 if (!NT_STATUS_IS_OK(status)) {
5634 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5635 goto fail;
5638 status = cli_nt_delete_on_close(cli1, fnum1, true);
5639 if (!NT_STATUS_IS_OK(status)) {
5640 printf("[8] setting delete_on_close on file failed !\n");
5641 goto fail;
5644 status = cli_close(cli1, fnum1);
5645 if (!NT_STATUS_IS_OK(status)) {
5646 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5647 goto fail;
5650 status = cli_close(cli2, fnum2);
5651 if (!NT_STATUS_IS_OK(status)) {
5652 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5653 goto fail;
5656 /* This should fail.. */
5657 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5658 if (NT_STATUS_IS_OK(status)) {
5659 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5660 goto fail;
5663 printf("eighth delete on close test succeeded.\n");
5665 /* Test 9 ... */
5667 /* This should fail - we need to set DELETE_ACCESS. */
5668 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5669 FILE_ATTRIBUTE_NORMAL,
5670 FILE_SHARE_NONE,
5671 FILE_OVERWRITE_IF,
5672 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5673 if (NT_STATUS_IS_OK(status)) {
5674 printf("[9] open of %s succeeded should have failed!\n", fname);
5675 goto fail;
5678 printf("ninth delete on close test succeeded.\n");
5680 /* Test 10 ... */
5682 status = cli_ntcreate(cli1, fname, 0,
5683 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5684 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5685 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5686 0, &fnum1, NULL);
5687 if (!NT_STATUS_IS_OK(status)) {
5688 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5689 goto fail;
5692 /* This should delete the file. */
5693 status = cli_close(cli1, fnum1);
5694 if (!NT_STATUS_IS_OK(status)) {
5695 printf("[10] close failed (%s)\n", nt_errstr(status));
5696 goto fail;
5699 /* This should fail.. */
5700 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5701 if (NT_STATUS_IS_OK(status)) {
5702 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5703 goto fail;
5706 printf("tenth delete on close test succeeded.\n");
5708 /* Test 11 ... */
5710 cli_setatr(cli1, fname, 0, 0);
5711 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5713 /* Can we open a read-only file with delete access? */
5715 /* Create a readonly file. */
5716 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5717 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5718 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5719 if (!NT_STATUS_IS_OK(status)) {
5720 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5721 goto fail;
5724 status = cli_close(cli1, fnum1);
5725 if (!NT_STATUS_IS_OK(status)) {
5726 printf("[11] close failed (%s)\n", nt_errstr(status));
5727 goto fail;
5730 /* Now try open for delete access. */
5731 status = cli_ntcreate(cli1, fname, 0,
5732 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5734 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5735 FILE_OPEN, 0, 0, &fnum1, NULL);
5736 if (!NT_STATUS_IS_OK(status)) {
5737 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5738 goto fail;
5741 cli_close(cli1, fnum1);
5743 printf("eleventh delete on close test succeeded.\n");
5746 * Test 12
5747 * like test 4 but with initial delete on close
5750 cli_setatr(cli1, fname, 0, 0);
5751 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5753 status = cli_ntcreate(cli1, fname, 0,
5754 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5755 FILE_ATTRIBUTE_NORMAL,
5756 FILE_SHARE_READ|FILE_SHARE_WRITE,
5757 FILE_OVERWRITE_IF,
5758 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5759 if (!NT_STATUS_IS_OK(status)) {
5760 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5761 goto fail;
5764 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5765 FILE_ATTRIBUTE_NORMAL,
5766 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5767 FILE_OPEN, 0, 0, &fnum2, NULL);
5768 if (!NT_STATUS_IS_OK(status)) {
5769 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5770 goto fail;
5773 status = cli_close(cli1, fnum2);
5774 if (!NT_STATUS_IS_OK(status)) {
5775 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5776 goto fail;
5779 status = cli_nt_delete_on_close(cli1, fnum1, true);
5780 if (!NT_STATUS_IS_OK(status)) {
5781 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5782 goto fail;
5785 /* This should fail - no more opens once delete on close set. */
5786 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5787 FILE_ATTRIBUTE_NORMAL,
5788 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5789 FILE_OPEN, 0, 0, &fnum2, NULL);
5790 if (NT_STATUS_IS_OK(status)) {
5791 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5792 goto fail;
5795 status = cli_nt_delete_on_close(cli1, fnum1, false);
5796 if (!NT_STATUS_IS_OK(status)) {
5797 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5798 goto fail;
5801 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5802 FILE_ATTRIBUTE_NORMAL,
5803 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5804 FILE_OPEN, 0, 0, &fnum2, NULL);
5805 if (!NT_STATUS_IS_OK(status)) {
5806 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5807 goto fail;
5810 status = cli_close(cli1, fnum2);
5811 if (!NT_STATUS_IS_OK(status)) {
5812 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5813 goto fail;
5816 status = cli_close(cli1, fnum1);
5817 if (!NT_STATUS_IS_OK(status)) {
5818 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5819 goto fail;
5823 * setting delete on close on the handle does
5824 * not unset the initial delete on close...
5826 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5827 FILE_ATTRIBUTE_NORMAL,
5828 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5829 FILE_OPEN, 0, 0, &fnum2, NULL);
5830 if (NT_STATUS_IS_OK(status)) {
5831 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5832 goto fail;
5833 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5834 printf("ntcreate returned %s, expected "
5835 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5836 nt_errstr(status));
5837 goto fail;
5840 printf("twelfth delete on close test succeeded.\n");
5843 printf("finished delete test\n");
5845 correct = true;
5847 fail:
5848 /* FIXME: This will crash if we aborted before cli2 got
5849 * initialized, because these functions don't handle
5850 * uninitialized connections. */
5852 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5853 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5854 cli_setatr(cli1, fname, 0, 0);
5855 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5857 if (cli1 && !torture_close_connection(cli1)) {
5858 correct = False;
5860 if (cli2 && !torture_close_connection(cli2)) {
5861 correct = False;
5863 return correct;
5866 struct delete_stream_state {
5867 bool closed;
5870 static void delete_stream_unlinked(struct tevent_req *subreq);
5871 static void delete_stream_closed(struct tevent_req *subreq);
5873 static struct tevent_req *delete_stream_send(
5874 TALLOC_CTX *mem_ctx,
5875 struct tevent_context *ev,
5876 struct cli_state *cli,
5877 const char *base_fname,
5878 uint16_t stream_fnum)
5880 struct tevent_req *req = NULL, *subreq = NULL;
5881 struct delete_stream_state *state = NULL;
5883 req = tevent_req_create(
5884 mem_ctx, &state, struct delete_stream_state);
5885 if (req == NULL) {
5886 return NULL;
5889 subreq = cli_unlink_send(
5890 state,
5892 cli,
5893 base_fname,
5894 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5895 if (tevent_req_nomem(subreq, req)) {
5896 return tevent_req_post(req, ev);
5898 tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5900 subreq = cli_close_send(state, ev, cli, stream_fnum);
5901 if (tevent_req_nomem(subreq, req)) {
5902 return tevent_req_post(req, ev);
5904 tevent_req_set_callback(subreq, delete_stream_closed, req);
5906 return req;
5909 static void delete_stream_unlinked(struct tevent_req *subreq)
5911 struct tevent_req *req = tevent_req_callback_data(
5912 subreq, struct tevent_req);
5913 struct delete_stream_state *state = tevent_req_data(
5914 req, struct delete_stream_state);
5915 NTSTATUS status;
5917 status = cli_unlink_recv(subreq);
5918 TALLOC_FREE(subreq);
5919 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5920 printf("cli_unlink returned %s\n",
5921 nt_errstr(status));
5922 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5923 return;
5925 if (!state->closed) {
5926 /* close reply should have come in first */
5927 printf("Not closed\n");
5928 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5929 return;
5931 tevent_req_done(req);
5934 static void delete_stream_closed(struct tevent_req *subreq)
5936 struct tevent_req *req = tevent_req_callback_data(
5937 subreq, struct tevent_req);
5938 struct delete_stream_state *state = tevent_req_data(
5939 req, struct delete_stream_state);
5940 NTSTATUS status;
5942 status = cli_close_recv(subreq);
5943 TALLOC_FREE(subreq);
5944 if (tevent_req_nterror(req, status)) {
5945 return;
5947 /* also waiting for the unlink to come back */
5948 state->closed = true;
5951 static NTSTATUS delete_stream_recv(struct tevent_req *req)
5953 return tevent_req_simple_recv_ntstatus(req);
5956 static bool run_delete_stream(int dummy)
5958 struct tevent_context *ev = NULL;
5959 struct tevent_req *req = NULL;
5960 struct cli_state *cli = NULL;
5961 const char fname[] = "delete_stream";
5962 const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
5963 uint16_t fnum1, fnum2;
5964 NTSTATUS status;
5965 bool ok;
5967 printf("Starting stream delete test\n");
5969 ok = torture_open_connection(&cli, 0);
5970 if (!ok) {
5971 return false;
5974 cli_setatr(cli, fname, 0, 0);
5975 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5977 /* Create the file. */
5978 status = cli_ntcreate(
5979 cli,
5980 fname,
5982 READ_CONTROL_ACCESS,
5984 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5985 FILE_CREATE,
5986 0x0,
5987 0x0,
5988 &fnum1,
5989 NULL);
5990 if (!NT_STATUS_IS_OK(status)) {
5991 d_fprintf(stderr,
5992 "cli_ntcreate of %s failed (%s)\n",
5993 fname,
5994 nt_errstr(status));
5995 return false;
5997 status = cli_close(cli, fnum1);
5998 if (!NT_STATUS_IS_OK(status)) {
5999 d_fprintf(stderr,
6000 "cli_close of %s failed (%s)\n",
6001 fname,
6002 nt_errstr(status));
6003 return false;
6006 /* Now create the stream. */
6007 status = cli_ntcreate(
6008 cli,
6009 fname_stream,
6011 FILE_WRITE_DATA,
6013 FILE_SHARE_READ|FILE_SHARE_WRITE,
6014 FILE_CREATE,
6015 0x0,
6016 0x0,
6017 &fnum1,
6018 NULL);
6020 if (!NT_STATUS_IS_OK(status)) {
6021 d_fprintf(stderr,
6022 "cli_ntcreate of %s failed (%s)\n",
6023 fname_stream,
6024 nt_errstr(status));
6025 return false;
6028 /* open it a second time */
6030 status = cli_ntcreate(
6031 cli,
6032 fname_stream,
6034 FILE_WRITE_DATA,
6036 FILE_SHARE_READ|FILE_SHARE_WRITE,
6037 FILE_OPEN,
6038 0x0,
6039 0x0,
6040 &fnum2,
6041 NULL);
6043 if (!NT_STATUS_IS_OK(status)) {
6044 d_fprintf(stderr,
6045 "2nd cli_ntcreate of %s failed (%s)\n",
6046 fname_stream,
6047 nt_errstr(status));
6048 return false;
6051 ev = samba_tevent_context_init(talloc_tos());
6052 if (ev == NULL) {
6053 d_fprintf(stderr, "samba_tevent_context_init failed\n");
6054 return false;
6057 req = delete_stream_send(ev, ev, cli, fname, fnum1);
6058 if (req == NULL) {
6059 d_fprintf(stderr, "delete_stream_send failed\n");
6060 return false;
6063 ok = tevent_req_poll_ntstatus(req, ev, &status);
6064 if (!ok) {
6065 d_fprintf(stderr,
6066 "tevent_req_poll_ntstatus failed: %s\n",
6067 nt_errstr(status));
6068 return false;
6071 status = delete_stream_recv(req);
6072 TALLOC_FREE(req);
6073 if (!NT_STATUS_IS_OK(status)) {
6074 d_fprintf(stderr,
6075 "delete_stream failed: %s\n",
6076 nt_errstr(status));
6077 return false;
6080 status = cli_close(cli, fnum2);
6081 if (!NT_STATUS_IS_OK(status)) {
6082 d_fprintf(stderr,
6083 "close failed: %s\n",
6084 nt_errstr(status));
6085 return false;
6088 status = cli_unlink(
6089 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6090 if (!NT_STATUS_IS_OK(status)) {
6091 d_fprintf(stderr,
6092 "unlink failed: %s\n",
6093 nt_errstr(status));
6094 return false;
6097 return true;
6101 Exercise delete on close semantics - use on the PRINT1 share in torture
6102 testing.
6104 static bool run_delete_print_test(int dummy)
6106 struct cli_state *cli1 = NULL;
6107 const char *fname = "print_delete.file";
6108 uint16_t fnum1 = (uint16_t)-1;
6109 bool correct = false;
6110 const char *buf = "print file data\n";
6111 NTSTATUS status;
6113 printf("starting print delete test\n");
6115 if (!torture_open_connection(&cli1, 0)) {
6116 return false;
6119 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6121 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6122 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6123 0, 0, &fnum1, NULL);
6124 if (!NT_STATUS_IS_OK(status)) {
6125 printf("open of %s failed (%s)\n",
6126 fname,
6127 nt_errstr(status));
6128 goto fail;
6131 status = cli_writeall(cli1,
6132 fnum1,
6134 (const uint8_t *)buf,
6135 0, /* offset */
6136 strlen(buf), /* size */
6137 NULL);
6138 if (!NT_STATUS_IS_OK(status)) {
6139 printf("writing print file data failed (%s)\n",
6140 nt_errstr(status));
6141 goto fail;
6144 status = cli_nt_delete_on_close(cli1, fnum1, true);
6145 if (!NT_STATUS_IS_OK(status)) {
6146 printf("setting delete_on_close failed (%s)\n",
6147 nt_errstr(status));
6148 goto fail;
6151 status = cli_close(cli1, fnum1);
6152 if (!NT_STATUS_IS_OK(status)) {
6153 printf("close failed (%s)\n", nt_errstr(status));
6154 goto fail;
6157 printf("finished print delete test\n");
6159 correct = true;
6161 fail:
6163 if (fnum1 != (uint16_t)-1) {
6164 cli_close(cli1, fnum1);
6167 if (cli1 && !torture_close_connection(cli1)) {
6168 correct = false;
6170 return correct;
6173 static bool run_deletetest_ln(int dummy)
6175 struct cli_state *cli;
6176 const char *fname = "\\delete1";
6177 const char *fname_ln = "\\delete1_ln";
6178 uint16_t fnum;
6179 uint16_t fnum1;
6180 NTSTATUS status;
6181 bool correct = true;
6182 time_t t;
6184 printf("starting deletetest-ln\n");
6186 if (!torture_open_connection(&cli, 0)) {
6187 return false;
6190 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6191 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6193 smbXcli_conn_set_sockopt(cli->conn, sockops);
6195 /* Create the file. */
6196 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6197 if (!NT_STATUS_IS_OK(status)) {
6198 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6199 return false;
6202 status = cli_close(cli, fnum);
6203 if (!NT_STATUS_IS_OK(status)) {
6204 printf("close1 failed (%s)\n", nt_errstr(status));
6205 return false;
6208 /* Now create a hardlink. */
6209 status = cli_hardlink(cli, fname, fname_ln);
6210 if (!NT_STATUS_IS_OK(status)) {
6211 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6212 return false;
6215 /* Open the original file. */
6216 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6217 FILE_ATTRIBUTE_NORMAL,
6218 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6219 FILE_OPEN_IF, 0, 0, &fnum, NULL);
6220 if (!NT_STATUS_IS_OK(status)) {
6221 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6222 return false;
6225 /* Unlink the hard link path. */
6226 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6227 FILE_ATTRIBUTE_NORMAL,
6228 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6229 FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6230 if (!NT_STATUS_IS_OK(status)) {
6231 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6232 return false;
6234 status = cli_nt_delete_on_close(cli, fnum1, true);
6235 if (!NT_STATUS_IS_OK(status)) {
6236 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6237 __location__, fname_ln, nt_errstr(status));
6238 return false;
6241 status = cli_close(cli, fnum1);
6242 if (!NT_STATUS_IS_OK(status)) {
6243 printf("close %s failed (%s)\n",
6244 fname_ln, nt_errstr(status));
6245 return false;
6248 status = cli_close(cli, fnum);
6249 if (!NT_STATUS_IS_OK(status)) {
6250 printf("close %s failed (%s)\n",
6251 fname, nt_errstr(status));
6252 return false;
6255 /* Ensure the original file is still there. */
6256 status = cli_getatr(cli, fname, NULL, NULL, &t);
6257 if (!NT_STATUS_IS_OK(status)) {
6258 printf("%s getatr on file %s failed (%s)\n",
6259 __location__,
6260 fname,
6261 nt_errstr(status));
6262 correct = False;
6265 /* Ensure the link path is gone. */
6266 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6267 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6268 printf("%s, getatr for file %s returned wrong error code %s "
6269 "- should have been deleted\n",
6270 __location__,
6271 fname_ln, nt_errstr(status));
6272 correct = False;
6275 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6276 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6278 if (!torture_close_connection(cli)) {
6279 correct = false;
6282 printf("finished deletetest-ln\n");
6284 return correct;
6288 print out server properties
6290 static bool run_properties(int dummy)
6292 struct cli_state *cli;
6293 bool correct = True;
6295 printf("starting properties test\n");
6297 ZERO_STRUCT(cli);
6299 if (!torture_open_connection(&cli, 0)) {
6300 return False;
6303 smbXcli_conn_set_sockopt(cli->conn, sockops);
6305 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6307 if (!torture_close_connection(cli)) {
6308 correct = False;
6311 return correct;
6316 /* FIRST_DESIRED_ACCESS 0xf019f */
6317 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6318 FILE_READ_EA| /* 0xf */ \
6319 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
6320 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
6321 DELETE_ACCESS|READ_CONTROL_ACCESS|\
6322 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
6323 /* SECOND_DESIRED_ACCESS 0xe0080 */
6324 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6325 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6326 WRITE_OWNER_ACCESS /* 0xe0000 */
6328 #if 0
6329 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6330 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6331 FILE_READ_DATA|\
6332 WRITE_OWNER_ACCESS /* */
6333 #endif
6336 Test ntcreate calls made by xcopy
6338 static bool run_xcopy(int dummy)
6340 static struct cli_state *cli1;
6341 const char *fname = "\\test.txt";
6342 bool correct = True;
6343 uint16_t fnum1, fnum2;
6344 NTSTATUS status;
6346 printf("starting xcopy test\n");
6348 if (!torture_open_connection(&cli1, 0)) {
6349 return False;
6352 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6353 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6354 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6355 if (!NT_STATUS_IS_OK(status)) {
6356 printf("First open failed - %s\n", nt_errstr(status));
6357 return False;
6360 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6361 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6362 FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6363 if (!NT_STATUS_IS_OK(status)) {
6364 printf("second open failed - %s\n", nt_errstr(status));
6365 return False;
6368 if (!torture_close_connection(cli1)) {
6369 correct = False;
6372 return correct;
6376 Test rename on files open with share delete and no share delete.
6378 static bool run_rename(int dummy)
6380 static struct cli_state *cli1;
6381 const char *fname = "\\test.txt";
6382 const char *fname1 = "\\test1.txt";
6383 bool correct = True;
6384 uint16_t fnum1;
6385 uint32_t attr;
6386 NTSTATUS status;
6388 printf("starting rename test\n");
6390 if (!torture_open_connection(&cli1, 0)) {
6391 return False;
6394 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6395 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6397 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6398 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6399 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6400 if (!NT_STATUS_IS_OK(status)) {
6401 printf("First open failed - %s\n", nt_errstr(status));
6402 return False;
6405 status = cli_rename(cli1, fname, fname1, false);
6406 if (!NT_STATUS_IS_OK(status)) {
6407 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6408 } else {
6409 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6410 correct = False;
6413 status = cli_close(cli1, fnum1);
6414 if (!NT_STATUS_IS_OK(status)) {
6415 printf("close - 1 failed (%s)\n", nt_errstr(status));
6416 return False;
6419 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6420 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6421 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6422 #if 0
6423 FILE_SHARE_DELETE|FILE_SHARE_NONE,
6424 #else
6425 FILE_SHARE_DELETE|FILE_SHARE_READ,
6426 #endif
6427 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6428 if (!NT_STATUS_IS_OK(status)) {
6429 printf("Second open failed - %s\n", nt_errstr(status));
6430 return False;
6433 status = cli_rename(cli1, fname, fname1, false);
6434 if (!NT_STATUS_IS_OK(status)) {
6435 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6436 correct = False;
6437 } else {
6438 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6441 status = cli_close(cli1, fnum1);
6442 if (!NT_STATUS_IS_OK(status)) {
6443 printf("close - 2 failed (%s)\n", nt_errstr(status));
6444 return False;
6447 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6448 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6450 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6451 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6452 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6453 if (!NT_STATUS_IS_OK(status)) {
6454 printf("Third open failed - %s\n", nt_errstr(status));
6455 return False;
6459 status = cli_rename(cli1, fname, fname1, false);
6460 if (!NT_STATUS_IS_OK(status)) {
6461 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6462 correct = False;
6463 } else {
6464 printf("Third rename succeeded (SHARE_NONE)\n");
6467 status = cli_close(cli1, fnum1);
6468 if (!NT_STATUS_IS_OK(status)) {
6469 printf("close - 3 failed (%s)\n", nt_errstr(status));
6470 return False;
6473 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6474 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6476 /*----*/
6478 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6479 FILE_ATTRIBUTE_NORMAL,
6480 FILE_SHARE_READ | FILE_SHARE_WRITE,
6481 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6482 if (!NT_STATUS_IS_OK(status)) {
6483 printf("Fourth open failed - %s\n", nt_errstr(status));
6484 return False;
6487 status = cli_rename(cli1, fname, fname1, false);
6488 if (!NT_STATUS_IS_OK(status)) {
6489 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6490 } else {
6491 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6492 correct = False;
6495 status = cli_close(cli1, fnum1);
6496 if (!NT_STATUS_IS_OK(status)) {
6497 printf("close - 4 failed (%s)\n", nt_errstr(status));
6498 return False;
6501 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6502 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6504 /*--*/
6506 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6507 FILE_ATTRIBUTE_NORMAL,
6508 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6509 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6510 if (!NT_STATUS_IS_OK(status)) {
6511 printf("Fifth open failed - %s\n", nt_errstr(status));
6512 return False;
6515 status = cli_rename(cli1, fname, fname1, false);
6516 if (!NT_STATUS_IS_OK(status)) {
6517 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6518 correct = False;
6519 } else {
6520 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6523 /*--*/
6524 status = cli_close(cli1, fnum1);
6525 if (!NT_STATUS_IS_OK(status)) {
6526 printf("close - 5 failed (%s)\n", nt_errstr(status));
6527 return False;
6530 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6531 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6532 if (!NT_STATUS_IS_OK(status)) {
6533 printf("getatr on file %s failed - %s ! \n",
6534 fname1, nt_errstr(status));
6535 correct = False;
6536 } else {
6537 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6538 printf("Renamed file %s has wrong attr 0x%x "
6539 "(should be 0x%x)\n",
6540 fname1,
6541 attr,
6542 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6543 correct = False;
6544 } else {
6545 printf("Renamed file %s has archive bit set\n", fname1);
6549 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6550 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6552 if (!torture_close_connection(cli1)) {
6553 correct = False;
6556 return correct;
6560 Test rename into a directory with an ACL denying it.
6562 static bool run_rename_access(int dummy)
6564 static struct cli_state *cli = NULL;
6565 static struct cli_state *posix_cli = NULL;
6566 const char *src = "test.txt";
6567 const char *dname = "dir";
6568 const char *dst = "dir\\test.txt";
6569 const char *dsrc = "test.dir";
6570 const char *ddst = "dir\\test.dir";
6571 uint16_t fnum = (uint16_t)-1;
6572 struct security_descriptor *sd = NULL;
6573 struct security_descriptor *newsd = NULL;
6574 NTSTATUS status;
6575 TALLOC_CTX *frame = NULL;
6577 frame = talloc_stackframe();
6578 printf("starting rename access test\n");
6580 /* Windows connection. */
6581 if (!torture_open_connection(&cli, 0)) {
6582 goto fail;
6585 smbXcli_conn_set_sockopt(cli->conn, sockops);
6587 /* Posix connection. */
6588 if (!torture_open_connection(&posix_cli, 0)) {
6589 goto fail;
6592 smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6594 status = torture_setup_unix_extensions(posix_cli);
6595 if (!NT_STATUS_IS_OK(status)) {
6596 goto fail;
6599 /* Start with a clean slate. */
6600 cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6601 cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6602 cli_rmdir(cli, dsrc);
6603 cli_rmdir(cli, ddst);
6604 cli_rmdir(cli, dname);
6607 * Setup the destination directory with a DENY ACE to
6608 * prevent new files within it.
6610 status = cli_ntcreate(cli,
6611 dname,
6613 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6614 WRITE_DAC_ACCESS|FILE_READ_DATA|
6615 WRITE_OWNER_ACCESS,
6616 FILE_ATTRIBUTE_DIRECTORY,
6617 FILE_SHARE_READ|FILE_SHARE_WRITE,
6618 FILE_CREATE,
6619 FILE_DIRECTORY_FILE,
6621 &fnum,
6622 NULL);
6623 if (!NT_STATUS_IS_OK(status)) {
6624 printf("Create of %s - %s\n", dname, nt_errstr(status));
6625 goto fail;
6628 status = cli_query_secdesc(cli,
6629 fnum,
6630 frame,
6631 &sd);
6632 if (!NT_STATUS_IS_OK(status)) {
6633 printf("cli_query_secdesc failed for %s (%s)\n",
6634 dname, nt_errstr(status));
6635 goto fail;
6638 newsd = security_descriptor_dacl_create(frame,
6640 NULL,
6641 NULL,
6642 SID_WORLD,
6643 SEC_ACE_TYPE_ACCESS_DENIED,
6644 SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6646 NULL);
6647 if (newsd == NULL) {
6648 goto fail;
6650 sd->dacl = security_acl_concatenate(frame,
6651 newsd->dacl,
6652 sd->dacl);
6653 if (sd->dacl == NULL) {
6654 goto fail;
6656 status = cli_set_secdesc(cli, fnum, sd);
6657 if (!NT_STATUS_IS_OK(status)) {
6658 printf("cli_set_secdesc failed for %s (%s)\n",
6659 dname, nt_errstr(status));
6660 goto fail;
6662 status = cli_close(cli, fnum);
6663 if (!NT_STATUS_IS_OK(status)) {
6664 printf("close failed for %s (%s)\n",
6665 dname, nt_errstr(status));
6666 goto fail;
6668 /* Now go around the back and chmod to 777 via POSIX. */
6669 status = cli_posix_chmod(posix_cli, dname, 0777);
6670 if (!NT_STATUS_IS_OK(status)) {
6671 printf("cli_posix_chmod failed for %s (%s)\n",
6672 dname, nt_errstr(status));
6673 goto fail;
6676 /* Check we can't create a file within dname via Windows. */
6677 status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6678 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6679 cli_close(posix_cli, fnum);
6680 printf("Create of %s should be ACCESS denied, was %s\n",
6681 dst, nt_errstr(status));
6682 goto fail;
6685 /* Make the sample file/directory. */
6686 status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6687 if (!NT_STATUS_IS_OK(status)) {
6688 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6689 goto fail;
6691 status = cli_close(cli, fnum);
6692 if (!NT_STATUS_IS_OK(status)) {
6693 printf("cli_close failed (%s)\n", nt_errstr(status));
6694 goto fail;
6697 status = cli_mkdir(cli, dsrc);
6698 if (!NT_STATUS_IS_OK(status)) {
6699 printf("cli_mkdir of %s failed (%s)\n",
6700 dsrc, nt_errstr(status));
6701 goto fail;
6705 * OK - renames of the new file and directory into the
6706 * dst directory should fail.
6709 status = cli_rename(cli, src, dst, false);
6710 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6711 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6712 src, dst, nt_errstr(status));
6713 goto fail;
6715 status = cli_rename(cli, dsrc, ddst, false);
6716 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6717 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6718 src, dst, nt_errstr(status));
6719 goto fail;
6722 TALLOC_FREE(frame);
6723 return true;
6725 fail:
6727 if (posix_cli) {
6728 torture_close_connection(posix_cli);
6731 if (cli) {
6732 if (fnum != (uint16_t)-1) {
6733 cli_close(cli, fnum);
6735 cli_unlink(cli, src,
6736 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6737 cli_unlink(cli, dst,
6738 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6739 cli_rmdir(cli, dsrc);
6740 cli_rmdir(cli, ddst);
6741 cli_rmdir(cli, dname);
6743 torture_close_connection(cli);
6746 TALLOC_FREE(frame);
6747 return false;
6751 Test owner rights ACE.
6753 static bool run_owner_rights(int dummy)
6755 static struct cli_state *cli = NULL;
6756 const char *fname = "owner_rights.txt";
6757 uint16_t fnum = (uint16_t)-1;
6758 struct security_descriptor *sd = NULL;
6759 struct security_descriptor *newsd = NULL;
6760 NTSTATUS status;
6761 TALLOC_CTX *frame = NULL;
6763 frame = talloc_stackframe();
6764 printf("starting owner rights test\n");
6766 /* Windows connection. */
6767 if (!torture_open_connection(&cli, 0)) {
6768 goto fail;
6771 smbXcli_conn_set_sockopt(cli->conn, sockops);
6773 /* Start with a clean slate. */
6774 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6776 /* Create the test file. */
6777 /* Now try and open for read and write-dac. */
6778 status = cli_ntcreate(cli,
6779 fname,
6781 GENERIC_ALL_ACCESS,
6782 FILE_ATTRIBUTE_NORMAL,
6783 FILE_SHARE_READ|FILE_SHARE_WRITE|
6784 FILE_SHARE_DELETE,
6785 FILE_CREATE,
6788 &fnum,
6789 NULL);
6790 if (!NT_STATUS_IS_OK(status)) {
6791 printf("Create of %s - %s\n", fname, nt_errstr(status));
6792 goto fail;
6795 /* Get the original SD. */
6796 status = cli_query_secdesc(cli,
6797 fnum,
6798 frame,
6799 &sd);
6800 if (!NT_STATUS_IS_OK(status)) {
6801 printf("cli_query_secdesc failed for %s (%s)\n",
6802 fname, nt_errstr(status));
6803 goto fail;
6807 * Add an "owner-rights" ACE denying WRITE_DATA,
6808 * and an "owner-rights" ACE allowing READ_DATA.
6811 newsd = security_descriptor_dacl_create(frame,
6813 NULL,
6814 NULL,
6815 SID_OWNER_RIGHTS,
6816 SEC_ACE_TYPE_ACCESS_DENIED,
6817 FILE_WRITE_DATA,
6819 SID_OWNER_RIGHTS,
6820 SEC_ACE_TYPE_ACCESS_ALLOWED,
6821 FILE_READ_DATA,
6823 NULL);
6824 if (newsd == NULL) {
6825 goto fail;
6827 sd->dacl = security_acl_concatenate(frame,
6828 newsd->dacl,
6829 sd->dacl);
6830 if (sd->dacl == NULL) {
6831 goto fail;
6833 status = cli_set_secdesc(cli, fnum, sd);
6834 if (!NT_STATUS_IS_OK(status)) {
6835 printf("cli_set_secdesc failed for %s (%s)\n",
6836 fname, nt_errstr(status));
6837 goto fail;
6839 status = cli_close(cli, fnum);
6840 if (!NT_STATUS_IS_OK(status)) {
6841 printf("close failed for %s (%s)\n",
6842 fname, nt_errstr(status));
6843 goto fail;
6845 fnum = (uint16_t)-1;
6847 /* Try and open for FILE_WRITE_DATA */
6848 status = cli_ntcreate(cli,
6849 fname,
6851 FILE_WRITE_DATA,
6852 FILE_ATTRIBUTE_NORMAL,
6853 FILE_SHARE_READ|FILE_SHARE_WRITE|
6854 FILE_SHARE_DELETE,
6855 FILE_OPEN,
6858 &fnum,
6859 NULL);
6860 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6861 printf("Open of %s - %s\n", fname, nt_errstr(status));
6862 goto fail;
6865 /* Now try and open for FILE_READ_DATA */
6866 status = cli_ntcreate(cli,
6867 fname,
6869 FILE_READ_DATA,
6870 FILE_ATTRIBUTE_NORMAL,
6871 FILE_SHARE_READ|FILE_SHARE_WRITE|
6872 FILE_SHARE_DELETE,
6873 FILE_OPEN,
6876 &fnum,
6877 NULL);
6878 if (!NT_STATUS_IS_OK(status)) {
6879 printf("Open of %s - %s\n", fname, nt_errstr(status));
6880 goto fail;
6883 status = cli_close(cli, fnum);
6884 if (!NT_STATUS_IS_OK(status)) {
6885 printf("close failed for %s (%s)\n",
6886 fname, nt_errstr(status));
6887 goto fail;
6890 /* Restore clean slate. */
6891 TALLOC_FREE(sd);
6892 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6894 /* Create the test file. */
6895 status = cli_ntcreate(cli,
6896 fname,
6898 GENERIC_ALL_ACCESS,
6899 FILE_ATTRIBUTE_NORMAL,
6900 FILE_SHARE_READ|FILE_SHARE_WRITE|
6901 FILE_SHARE_DELETE,
6902 FILE_CREATE,
6905 &fnum,
6906 NULL);
6907 if (!NT_STATUS_IS_OK(status)) {
6908 printf("Create of %s - %s\n", fname, nt_errstr(status));
6909 goto fail;
6912 /* Get the original SD. */
6913 status = cli_query_secdesc(cli,
6914 fnum,
6915 frame,
6916 &sd);
6917 if (!NT_STATUS_IS_OK(status)) {
6918 printf("cli_query_secdesc failed for %s (%s)\n",
6919 fname, nt_errstr(status));
6920 goto fail;
6924 * Add an "owner-rights ACE denying WRITE_DATA,
6925 * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6928 newsd = security_descriptor_dacl_create(frame,
6930 NULL,
6931 NULL,
6932 SID_OWNER_RIGHTS,
6933 SEC_ACE_TYPE_ACCESS_DENIED,
6934 FILE_WRITE_DATA,
6936 SID_OWNER_RIGHTS,
6937 SEC_ACE_TYPE_ACCESS_ALLOWED,
6938 FILE_READ_DATA|FILE_WRITE_DATA,
6940 NULL);
6941 if (newsd == NULL) {
6942 goto fail;
6944 sd->dacl = security_acl_concatenate(frame,
6945 newsd->dacl,
6946 sd->dacl);
6947 if (sd->dacl == NULL) {
6948 goto fail;
6950 status = cli_set_secdesc(cli, fnum, sd);
6951 if (!NT_STATUS_IS_OK(status)) {
6952 printf("cli_set_secdesc failed for %s (%s)\n",
6953 fname, nt_errstr(status));
6954 goto fail;
6956 status = cli_close(cli, fnum);
6957 if (!NT_STATUS_IS_OK(status)) {
6958 printf("close failed for %s (%s)\n",
6959 fname, nt_errstr(status));
6960 goto fail;
6962 fnum = (uint16_t)-1;
6964 /* Try and open for FILE_WRITE_DATA */
6965 status = cli_ntcreate(cli,
6966 fname,
6968 FILE_WRITE_DATA,
6969 FILE_ATTRIBUTE_NORMAL,
6970 FILE_SHARE_READ|FILE_SHARE_WRITE|
6971 FILE_SHARE_DELETE,
6972 FILE_OPEN,
6975 &fnum,
6976 NULL);
6977 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6978 printf("Open of %s - %s\n", fname, nt_errstr(status));
6979 goto fail;
6982 /* Now try and open for FILE_READ_DATA */
6983 status = cli_ntcreate(cli,
6984 fname,
6986 FILE_READ_DATA,
6987 FILE_ATTRIBUTE_NORMAL,
6988 FILE_SHARE_READ|FILE_SHARE_WRITE|
6989 FILE_SHARE_DELETE,
6990 FILE_OPEN,
6993 &fnum,
6994 NULL);
6995 if (!NT_STATUS_IS_OK(status)) {
6996 printf("Open of %s - %s\n", fname, nt_errstr(status));
6997 goto fail;
7000 status = cli_close(cli, fnum);
7001 if (!NT_STATUS_IS_OK(status)) {
7002 printf("close failed for %s (%s)\n",
7003 fname, nt_errstr(status));
7004 goto fail;
7007 /* Restore clean slate. */
7008 TALLOC_FREE(sd);
7009 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7012 /* Create the test file. */
7013 status = cli_ntcreate(cli,
7014 fname,
7016 GENERIC_ALL_ACCESS,
7017 FILE_ATTRIBUTE_NORMAL,
7018 FILE_SHARE_READ|FILE_SHARE_WRITE|
7019 FILE_SHARE_DELETE,
7020 FILE_CREATE,
7023 &fnum,
7024 NULL);
7025 if (!NT_STATUS_IS_OK(status)) {
7026 printf("Create of %s - %s\n", fname, nt_errstr(status));
7027 goto fail;
7030 /* Get the original SD. */
7031 status = cli_query_secdesc(cli,
7032 fnum,
7033 frame,
7034 &sd);
7035 if (!NT_STATUS_IS_OK(status)) {
7036 printf("cli_query_secdesc failed for %s (%s)\n",
7037 fname, nt_errstr(status));
7038 goto fail;
7042 * Add an "authenticated users" ACE allowing READ_DATA,
7043 * add an "owner-rights" denying READ_DATA,
7044 * and an "authenticated users" ACE allowing WRITE_DATA.
7047 newsd = security_descriptor_dacl_create(frame,
7049 NULL,
7050 NULL,
7051 SID_NT_AUTHENTICATED_USERS,
7052 SEC_ACE_TYPE_ACCESS_ALLOWED,
7053 FILE_READ_DATA,
7055 SID_OWNER_RIGHTS,
7056 SEC_ACE_TYPE_ACCESS_DENIED,
7057 FILE_READ_DATA,
7059 SID_NT_AUTHENTICATED_USERS,
7060 SEC_ACE_TYPE_ACCESS_ALLOWED,
7061 FILE_WRITE_DATA,
7063 NULL);
7064 if (newsd == NULL) {
7065 printf("newsd == NULL\n");
7066 goto fail;
7068 sd->dacl = security_acl_concatenate(frame,
7069 newsd->dacl,
7070 sd->dacl);
7071 if (sd->dacl == NULL) {
7072 printf("sd->dacl == NULL\n");
7073 goto fail;
7075 status = cli_set_secdesc(cli, fnum, sd);
7076 if (!NT_STATUS_IS_OK(status)) {
7077 printf("cli_set_secdesc failed for %s (%s)\n",
7078 fname, nt_errstr(status));
7079 goto fail;
7081 status = cli_close(cli, fnum);
7082 if (!NT_STATUS_IS_OK(status)) {
7083 printf("close failed for %s (%s)\n",
7084 fname, nt_errstr(status));
7085 goto fail;
7087 fnum = (uint16_t)-1;
7089 /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7090 status = cli_ntcreate(cli,
7091 fname,
7093 FILE_READ_DATA|FILE_WRITE_DATA,
7094 FILE_ATTRIBUTE_NORMAL,
7095 FILE_SHARE_READ|FILE_SHARE_WRITE|
7096 FILE_SHARE_DELETE,
7097 FILE_OPEN,
7100 &fnum,
7101 NULL);
7102 if (!NT_STATUS_IS_OK(status)) {
7103 printf("Open of %s - %s\n", fname, nt_errstr(status));
7104 goto fail;
7107 status = cli_close(cli, fnum);
7108 if (!NT_STATUS_IS_OK(status)) {
7109 printf("close failed for %s (%s)\n",
7110 fname, nt_errstr(status));
7111 goto fail;
7114 cli_unlink(cli, fname,
7115 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7117 TALLOC_FREE(frame);
7118 return true;
7120 fail:
7122 if (cli) {
7123 if (fnum != (uint16_t)-1) {
7124 cli_close(cli, fnum);
7126 cli_unlink(cli, fname,
7127 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7128 torture_close_connection(cli);
7131 TALLOC_FREE(frame);
7132 return false;
7136 * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7137 * Note this test only works with a user with SeSecurityPrivilege set.
7139 * NB. This is also tested in samba3.base.createx_access
7140 * but this makes it very explicit what we're looking for.
7142 static bool run_smb1_system_security(int dummy)
7144 static struct cli_state *cli = NULL;
7145 const char *fname = "system_security.txt";
7146 uint16_t fnum = (uint16_t)-1;
7147 NTSTATUS status;
7148 TALLOC_CTX *frame = NULL;
7150 frame = talloc_stackframe();
7151 printf("starting smb1 system security test\n");
7153 /* SMB1 connection - torture_open_connection() forces this. */
7154 if (!torture_open_connection(&cli, 0)) {
7155 goto fail;
7158 smbXcli_conn_set_sockopt(cli->conn, sockops);
7160 /* Start with a clean slate. */
7161 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7163 /* Create the test file. */
7164 status = cli_ntcreate(cli,
7165 fname,
7167 GENERIC_ALL_ACCESS,
7168 FILE_ATTRIBUTE_NORMAL,
7169 FILE_SHARE_READ|FILE_SHARE_WRITE|
7170 FILE_SHARE_DELETE,
7171 FILE_CREATE,
7174 &fnum,
7175 NULL);
7176 if (!NT_STATUS_IS_OK(status)) {
7177 printf("Create of %s - %s\n", fname, nt_errstr(status));
7178 goto fail;
7181 status = cli_close(cli, fnum);
7183 /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7185 * On SMB1 this succeeds - SMB2 it fails,
7186 * see the SMB2-SACL test.
7188 status = cli_ntcreate(cli,
7189 fname,
7191 SEC_FLAG_SYSTEM_SECURITY,
7192 FILE_ATTRIBUTE_NORMAL,
7193 FILE_SHARE_READ|FILE_SHARE_WRITE|
7194 FILE_SHARE_DELETE,
7195 FILE_OPEN,
7198 &fnum,
7199 NULL);
7200 if (!NT_STATUS_IS_OK(status)) {
7201 printf("Open of %s - %s\n", fname, nt_errstr(status));
7202 goto fail;
7205 status = cli_close(cli, fnum);
7207 cli_unlink(cli, fname,
7208 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7210 torture_close_connection(cli);
7211 TALLOC_FREE(frame);
7212 return true;
7214 fail:
7216 if (cli) {
7217 if (fnum != (uint16_t)-1) {
7218 cli_close(cli, fnum);
7220 cli_unlink(cli, fname,
7221 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7222 torture_close_connection(cli);
7225 TALLOC_FREE(frame);
7226 return false;
7229 static bool run_pipe_number(int dummy)
7231 struct cli_state *cli1;
7232 const char *pipe_name = "\\SPOOLSS";
7233 uint16_t fnum;
7234 int num_pipes = 0;
7235 NTSTATUS status;
7237 printf("starting pipenumber test\n");
7238 if (!torture_open_connection(&cli1, 0)) {
7239 return False;
7242 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7243 while(1) {
7244 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7245 FILE_ATTRIBUTE_NORMAL,
7246 FILE_SHARE_READ|FILE_SHARE_WRITE,
7247 FILE_OPEN_IF, 0, 0, &fnum, NULL);
7248 if (!NT_STATUS_IS_OK(status)) {
7249 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7250 break;
7252 num_pipes++;
7253 printf("\r%6d", num_pipes);
7256 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7257 torture_close_connection(cli1);
7258 return True;
7262 Test open mode returns on read-only files.
7264 static bool run_opentest(int dummy)
7266 static struct cli_state *cli1;
7267 static struct cli_state *cli2;
7268 const char *fname = "\\readonly.file";
7269 uint16_t fnum1, fnum2;
7270 char buf[20];
7271 off_t fsize;
7272 bool correct = True;
7273 char *tmp_path;
7274 NTSTATUS status;
7276 printf("starting open test\n");
7278 if (!torture_open_connection(&cli1, 0)) {
7279 return False;
7282 cli_setatr(cli1, fname, 0, 0);
7283 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7285 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7287 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7288 if (!NT_STATUS_IS_OK(status)) {
7289 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7290 return False;
7293 status = cli_close(cli1, fnum1);
7294 if (!NT_STATUS_IS_OK(status)) {
7295 printf("close2 failed (%s)\n", nt_errstr(status));
7296 return False;
7299 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7300 if (!NT_STATUS_IS_OK(status)) {
7301 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7302 return False;
7305 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7306 if (!NT_STATUS_IS_OK(status)) {
7307 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7308 return False;
7311 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7312 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7314 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7315 NT_STATUS_ACCESS_DENIED)) {
7316 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7319 printf("finished open test 1\n");
7321 cli_close(cli1, fnum1);
7323 /* Now try not readonly and ensure ERRbadshare is returned. */
7325 cli_setatr(cli1, fname, 0, 0);
7327 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7328 if (!NT_STATUS_IS_OK(status)) {
7329 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7330 return False;
7333 /* This will fail - but the error should be ERRshare. */
7334 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7336 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7337 NT_STATUS_SHARING_VIOLATION)) {
7338 printf("correct error code ERRDOS/ERRbadshare returned\n");
7341 status = cli_close(cli1, fnum1);
7342 if (!NT_STATUS_IS_OK(status)) {
7343 printf("close2 failed (%s)\n", nt_errstr(status));
7344 return False;
7347 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7349 printf("finished open test 2\n");
7351 /* Test truncate open disposition on file opened for read. */
7352 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7353 if (!NT_STATUS_IS_OK(status)) {
7354 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7355 return False;
7358 /* write 20 bytes. */
7360 memset(buf, '\0', 20);
7362 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7363 if (!NT_STATUS_IS_OK(status)) {
7364 printf("write failed (%s)\n", nt_errstr(status));
7365 correct = False;
7368 status = cli_close(cli1, fnum1);
7369 if (!NT_STATUS_IS_OK(status)) {
7370 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7371 return False;
7374 /* Ensure size == 20. */
7375 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7376 if (!NT_STATUS_IS_OK(status)) {
7377 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7378 return False;
7381 if (fsize != 20) {
7382 printf("(3) file size != 20\n");
7383 return False;
7386 /* Now test if we can truncate a file opened for readonly. */
7387 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7388 if (!NT_STATUS_IS_OK(status)) {
7389 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7390 return False;
7393 status = cli_close(cli1, fnum1);
7394 if (!NT_STATUS_IS_OK(status)) {
7395 printf("close2 failed (%s)\n", nt_errstr(status));
7396 return False;
7399 /* Ensure size == 0. */
7400 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7401 if (!NT_STATUS_IS_OK(status)) {
7402 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7403 return False;
7406 if (fsize != 0) {
7407 printf("(3) file size != 0\n");
7408 return False;
7410 printf("finished open test 3\n");
7412 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7414 printf("Do ctemp tests\n");
7415 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7416 if (!NT_STATUS_IS_OK(status)) {
7417 printf("ctemp failed (%s)\n", nt_errstr(status));
7418 return False;
7421 printf("ctemp gave path %s\n", tmp_path);
7422 status = cli_close(cli1, fnum1);
7423 if (!NT_STATUS_IS_OK(status)) {
7424 printf("close of temp failed (%s)\n", nt_errstr(status));
7427 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7428 if (!NT_STATUS_IS_OK(status)) {
7429 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7432 /* Test the non-io opens... */
7434 if (!torture_open_connection(&cli2, 1)) {
7435 return False;
7438 cli_setatr(cli2, fname, 0, 0);
7439 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7441 smbXcli_conn_set_sockopt(cli2->conn, sockops);
7443 printf("TEST #1 testing 2 non-io opens (no delete)\n");
7444 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7445 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7446 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7447 if (!NT_STATUS_IS_OK(status)) {
7448 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7449 return False;
7452 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7453 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7454 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7455 if (!NT_STATUS_IS_OK(status)) {
7456 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7457 return False;
7460 status = cli_close(cli1, fnum1);
7461 if (!NT_STATUS_IS_OK(status)) {
7462 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7463 return False;
7466 status = cli_close(cli2, fnum2);
7467 if (!NT_STATUS_IS_OK(status)) {
7468 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7469 return False;
7472 printf("non-io open test #1 passed.\n");
7474 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7476 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7478 status = cli_ntcreate(cli1, fname, 0,
7479 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7480 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7481 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7482 if (!NT_STATUS_IS_OK(status)) {
7483 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7484 return False;
7487 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7488 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7489 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7490 if (!NT_STATUS_IS_OK(status)) {
7491 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7492 return False;
7495 status = cli_close(cli1, fnum1);
7496 if (!NT_STATUS_IS_OK(status)) {
7497 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7498 return False;
7501 status = cli_close(cli2, fnum2);
7502 if (!NT_STATUS_IS_OK(status)) {
7503 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7504 return False;
7507 printf("non-io open test #2 passed.\n");
7509 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7511 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7513 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7514 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7515 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7516 if (!NT_STATUS_IS_OK(status)) {
7517 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7518 return False;
7521 status = cli_ntcreate(cli2, fname, 0,
7522 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7523 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7524 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7525 if (!NT_STATUS_IS_OK(status)) {
7526 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7527 return False;
7530 status = cli_close(cli1, fnum1);
7531 if (!NT_STATUS_IS_OK(status)) {
7532 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7533 return False;
7536 status = cli_close(cli2, fnum2);
7537 if (!NT_STATUS_IS_OK(status)) {
7538 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7539 return False;
7542 printf("non-io open test #3 passed.\n");
7544 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7546 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7548 status = cli_ntcreate(cli1, fname, 0,
7549 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7550 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7551 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7552 if (!NT_STATUS_IS_OK(status)) {
7553 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7554 return False;
7557 status = cli_ntcreate(cli2, fname, 0,
7558 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7559 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7560 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7561 if (NT_STATUS_IS_OK(status)) {
7562 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7563 return False;
7566 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7568 status = cli_close(cli1, fnum1);
7569 if (!NT_STATUS_IS_OK(status)) {
7570 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7571 return False;
7574 printf("non-io open test #4 passed.\n");
7576 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7578 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7580 status = cli_ntcreate(cli1, fname, 0,
7581 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7582 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7583 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7584 if (!NT_STATUS_IS_OK(status)) {
7585 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7586 return False;
7589 status = cli_ntcreate(cli2, fname, 0,
7590 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7591 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7592 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7593 if (!NT_STATUS_IS_OK(status)) {
7594 printf("TEST #5 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 #5 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 #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7607 return False;
7610 printf("non-io open test #5 passed.\n");
7612 printf("TEST #6 testing 1 non-io open, one io open\n");
7614 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7616 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
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 #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7621 return False;
7624 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7625 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7626 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7627 if (!NT_STATUS_IS_OK(status)) {
7628 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7629 return False;
7632 status = cli_close(cli1, fnum1);
7633 if (!NT_STATUS_IS_OK(status)) {
7634 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7635 return False;
7638 status = cli_close(cli2, fnum2);
7639 if (!NT_STATUS_IS_OK(status)) {
7640 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7641 return False;
7644 printf("non-io open test #6 passed.\n");
7646 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7648 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7650 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7651 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7652 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7653 if (!NT_STATUS_IS_OK(status)) {
7654 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7655 return False;
7658 status = cli_ntcreate(cli2, fname, 0,
7659 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7660 FILE_ATTRIBUTE_NORMAL,
7661 FILE_SHARE_READ|FILE_SHARE_DELETE,
7662 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7663 if (NT_STATUS_IS_OK(status)) {
7664 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7665 return False;
7668 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7670 status = cli_close(cli1, fnum1);
7671 if (!NT_STATUS_IS_OK(status)) {
7672 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7673 return False;
7676 printf("non-io open test #7 passed.\n");
7678 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7680 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7681 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7682 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7683 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7684 if (!NT_STATUS_IS_OK(status)) {
7685 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7686 correct = false;
7687 goto out;
7690 /* Write to ensure we have to update the file time. */
7691 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7692 NULL);
7693 if (!NT_STATUS_IS_OK(status)) {
7694 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7695 correct = false;
7696 goto out;
7699 status = cli_close(cli1, fnum1);
7700 if (!NT_STATUS_IS_OK(status)) {
7701 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7702 correct = false;
7705 out:
7707 if (!torture_close_connection(cli1)) {
7708 correct = False;
7710 if (!torture_close_connection(cli2)) {
7711 correct = False;
7714 return correct;
7717 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7719 uint16_t major, minor;
7720 uint32_t caplow, caphigh;
7721 NTSTATUS status;
7723 if (!SERVER_HAS_UNIX_CIFS(cli)) {
7724 printf("Server doesn't support UNIX CIFS extensions.\n");
7725 return NT_STATUS_NOT_SUPPORTED;
7728 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7729 &caphigh);
7730 if (!NT_STATUS_IS_OK(status)) {
7731 printf("Server didn't return UNIX CIFS extensions: %s\n",
7732 nt_errstr(status));
7733 return status;
7736 status = cli_set_unix_extensions_capabilities(cli, major, minor,
7737 caplow, caphigh);
7738 if (!NT_STATUS_IS_OK(status)) {
7739 printf("Server doesn't support setting UNIX CIFS extensions: "
7740 "%s.\n", nt_errstr(status));
7741 return status;
7744 return NT_STATUS_OK;
7748 Test POSIX open /mkdir calls.
7750 static bool run_simple_posix_open_test(int dummy)
7752 static struct cli_state *cli1;
7753 const char *fname = "posix:file";
7754 const char *hname = "posix:hlink";
7755 const char *sname = "posix:symlink";
7756 const char *dname = "posix:dir";
7757 char buf[10];
7758 char *target = NULL;
7759 uint16_t fnum1 = (uint16_t)-1;
7760 SMB_STRUCT_STAT sbuf;
7761 bool correct = false;
7762 NTSTATUS status;
7763 size_t nread;
7764 const char *fname_windows = "windows_file";
7765 uint16_t fnum2 = (uint16_t)-1;
7766 bool ok;
7768 printf("Starting simple POSIX open test\n");
7770 if (!torture_open_connection(&cli1, 0)) {
7771 return false;
7774 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7776 status = torture_setup_unix_extensions(cli1);
7777 if (!NT_STATUS_IS_OK(status)) {
7778 return false;
7781 cli_setatr(cli1, fname, 0, 0);
7782 cli_posix_unlink(cli1, fname);
7783 cli_setatr(cli1, dname, 0, 0);
7784 cli_posix_rmdir(cli1, dname);
7785 cli_setatr(cli1, hname, 0, 0);
7786 cli_posix_unlink(cli1, hname);
7787 cli_setatr(cli1, sname, 0, 0);
7788 cli_posix_unlink(cli1, sname);
7789 cli_setatr(cli1, fname_windows, 0, 0);
7790 cli_posix_unlink(cli1, fname_windows);
7792 /* Create a directory. */
7793 status = cli_posix_mkdir(cli1, dname, 0777);
7794 if (!NT_STATUS_IS_OK(status)) {
7795 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7796 goto out;
7799 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7800 0600, &fnum1);
7801 if (!NT_STATUS_IS_OK(status)) {
7802 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7803 goto out;
7806 /* Test ftruncate - set file size. */
7807 status = cli_ftruncate(cli1, fnum1, 1000);
7808 if (!NT_STATUS_IS_OK(status)) {
7809 printf("ftruncate failed (%s)\n", nt_errstr(status));
7810 goto out;
7813 /* Ensure st_size == 1000 */
7814 status = cli_posix_stat(cli1, fname, &sbuf);
7815 if (!NT_STATUS_IS_OK(status)) {
7816 printf("stat failed (%s)\n", nt_errstr(status));
7817 goto out;
7820 if (sbuf.st_ex_size != 1000) {
7821 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7822 goto out;
7825 /* Ensure st_mode == 0600 */
7826 if ((sbuf.st_ex_mode & 07777) != 0600) {
7827 printf("posix_open - bad permissions 0%o != 0600\n",
7828 (unsigned int)(sbuf.st_ex_mode & 07777));
7829 goto out;
7832 /* Test ftruncate - set file size back to zero. */
7833 status = cli_ftruncate(cli1, fnum1, 0);
7834 if (!NT_STATUS_IS_OK(status)) {
7835 printf("ftruncate failed (%s)\n", nt_errstr(status));
7836 goto out;
7839 status = cli_close(cli1, fnum1);
7840 if (!NT_STATUS_IS_OK(status)) {
7841 printf("close failed (%s)\n", nt_errstr(status));
7842 goto out;
7845 /* Now open the file again for read only. */
7846 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7847 if (!NT_STATUS_IS_OK(status)) {
7848 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7849 goto out;
7852 /* Now unlink while open. */
7853 status = cli_posix_unlink(cli1, fname);
7854 if (!NT_STATUS_IS_OK(status)) {
7855 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7856 goto out;
7859 status = cli_close(cli1, fnum1);
7860 if (!NT_STATUS_IS_OK(status)) {
7861 printf("close(2) failed (%s)\n", nt_errstr(status));
7862 goto out;
7865 /* Ensure the file has gone. */
7866 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7867 if (NT_STATUS_IS_OK(status)) {
7868 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7869 goto out;
7872 /* Create again to test open with O_TRUNC. */
7873 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7874 if (!NT_STATUS_IS_OK(status)) {
7875 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7876 goto out;
7879 /* Test ftruncate - set file size. */
7880 status = cli_ftruncate(cli1, fnum1, 1000);
7881 if (!NT_STATUS_IS_OK(status)) {
7882 printf("ftruncate failed (%s)\n", nt_errstr(status));
7883 goto out;
7886 /* Ensure st_size == 1000 */
7887 status = cli_posix_stat(cli1, fname, &sbuf);
7888 if (!NT_STATUS_IS_OK(status)) {
7889 printf("stat failed (%s)\n", nt_errstr(status));
7890 goto out;
7893 if (sbuf.st_ex_size != 1000) {
7894 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7895 goto out;
7898 status = cli_close(cli1, fnum1);
7899 if (!NT_STATUS_IS_OK(status)) {
7900 printf("close(2) failed (%s)\n", nt_errstr(status));
7901 goto out;
7904 /* Re-open with O_TRUNC. */
7905 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7906 if (!NT_STATUS_IS_OK(status)) {
7907 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7908 goto out;
7911 /* Ensure st_size == 0 */
7912 status = cli_posix_stat(cli1, fname, &sbuf);
7913 if (!NT_STATUS_IS_OK(status)) {
7914 printf("stat failed (%s)\n", nt_errstr(status));
7915 goto out;
7918 if (sbuf.st_ex_size != 0) {
7919 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7920 goto out;
7923 status = cli_close(cli1, fnum1);
7924 if (!NT_STATUS_IS_OK(status)) {
7925 printf("close failed (%s)\n", nt_errstr(status));
7926 goto out;
7929 status = cli_posix_unlink(cli1, fname);
7930 if (!NT_STATUS_IS_OK(status)) {
7931 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7932 goto out;
7935 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
7936 if (!NT_STATUS_IS_OK(status)) {
7937 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
7938 dname, nt_errstr(status));
7939 goto out;
7942 cli_close(cli1, fnum1);
7944 /* What happens when we try and POSIX open a directory for write ? */
7945 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
7946 if (NT_STATUS_IS_OK(status)) {
7947 printf("POSIX open of directory %s succeeded, "
7948 "should have failed.\n",
7949 dname);
7950 goto out;
7951 } else {
7952 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
7953 NT_STATUS_FILE_IS_A_DIRECTORY)) {
7954 goto out;
7958 /* Create the file. */
7959 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7960 0600, &fnum1);
7961 if (!NT_STATUS_IS_OK(status)) {
7962 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7963 goto out;
7966 /* Write some data into it. */
7967 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7968 NULL);
7969 if (!NT_STATUS_IS_OK(status)) {
7970 printf("cli_write failed: %s\n", nt_errstr(status));
7971 goto out;
7974 cli_close(cli1, fnum1);
7976 /* Now create a hardlink. */
7977 status = cli_posix_hardlink(cli1, fname, hname);
7978 if (!NT_STATUS_IS_OK(status)) {
7979 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
7980 goto out;
7983 /* Now create a symlink. */
7984 status = cli_posix_symlink(cli1, fname, sname);
7985 if (!NT_STATUS_IS_OK(status)) {
7986 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
7987 goto out;
7990 /* Open the hardlink for read. */
7991 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
7992 if (!NT_STATUS_IS_OK(status)) {
7993 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
7994 goto out;
7997 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
7998 if (!NT_STATUS_IS_OK(status)) {
7999 printf("POSIX read of %s failed (%s)\n", hname,
8000 nt_errstr(status));
8001 goto out;
8002 } else if (nread != 10) {
8003 printf("POSIX read of %s failed. Received %ld, expected %d\n",
8004 hname, (unsigned long)nread, 10);
8005 goto out;
8008 if (memcmp(buf, "TEST DATA\n", 10)) {
8009 printf("invalid data read from hardlink\n");
8010 goto out;
8013 /* Do a POSIX lock/unlock. */
8014 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8015 if (!NT_STATUS_IS_OK(status)) {
8016 printf("POSIX lock failed %s\n", nt_errstr(status));
8017 goto out;
8020 /* Punch a hole in the locked area. */
8021 status = cli_posix_unlock(cli1, fnum1, 10, 80);
8022 if (!NT_STATUS_IS_OK(status)) {
8023 printf("POSIX unlock failed %s\n", nt_errstr(status));
8024 goto out;
8027 cli_close(cli1, fnum1);
8029 /* Open the symlink for read - this should fail. A POSIX
8030 client should not be doing opens on a symlink. */
8031 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8032 if (NT_STATUS_IS_OK(status)) {
8033 printf("POSIX open of %s succeeded (should have failed)\n", sname);
8034 goto out;
8036 ok = check_both_error(
8037 __LINE__, status, ERRDOS, ERRbadpath,
8038 NT_STATUS_OBJECT_NAME_NOT_FOUND);
8039 if (!ok) {
8040 printf("POSIX open of %s should have failed "
8041 "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8042 "failed with %s instead.\n",
8043 sname, nt_errstr(status));
8044 goto out;
8047 status = cli_readlink(cli1, sname, talloc_tos(), &target, NULL, NULL);
8048 if (!NT_STATUS_IS_OK(status)) {
8049 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8050 goto out;
8053 if (strcmp(target, fname) != 0) {
8054 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8055 sname, fname, target);
8056 goto out;
8059 status = cli_posix_rmdir(cli1, dname);
8060 if (!NT_STATUS_IS_OK(status)) {
8061 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8062 goto out;
8065 /* Check directory opens with a specific permission. */
8066 status = cli_posix_mkdir(cli1, dname, 0700);
8067 if (!NT_STATUS_IS_OK(status)) {
8068 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8069 goto out;
8072 /* Ensure st_mode == 0700 */
8073 status = cli_posix_stat(cli1, dname, &sbuf);
8074 if (!NT_STATUS_IS_OK(status)) {
8075 printf("stat failed (%s)\n", nt_errstr(status));
8076 goto out;
8079 if ((sbuf.st_ex_mode & 07777) != 0700) {
8080 printf("posix_mkdir - bad permissions 0%o != 0700\n",
8081 (unsigned int)(sbuf.st_ex_mode & 07777));
8082 goto out;
8086 * Now create a Windows file, and attempt a POSIX unlink.
8087 * This should fail with a sharing violation but due to:
8089 * [Bug 9571] Unlink after open causes smbd to panic
8091 * ensure we've fixed the lock ordering violation.
8094 status = cli_ntcreate(cli1, fname_windows, 0,
8095 FILE_READ_DATA|FILE_WRITE_DATA, 0,
8096 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8097 FILE_CREATE,
8098 0x0, 0x0, &fnum2, NULL);
8099 if (!NT_STATUS_IS_OK(status)) {
8100 printf("Windows create of %s failed (%s)\n", fname_windows,
8101 nt_errstr(status));
8102 goto out;
8105 /* Now try posix_unlink. */
8106 status = cli_posix_unlink(cli1, fname_windows);
8107 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8108 printf("POSIX unlink of %s should fail "
8109 "with NT_STATUS_SHARING_VIOLATION "
8110 "got %s instead !\n",
8111 fname_windows,
8112 nt_errstr(status));
8113 goto out;
8116 cli_close(cli1, fnum2);
8118 printf("Simple POSIX open test passed\n");
8119 correct = true;
8121 out:
8123 if (fnum1 != (uint16_t)-1) {
8124 cli_close(cli1, fnum1);
8125 fnum1 = (uint16_t)-1;
8128 if (fnum2 != (uint16_t)-1) {
8129 cli_close(cli1, fnum2);
8130 fnum2 = (uint16_t)-1;
8133 cli_setatr(cli1, sname, 0, 0);
8134 cli_posix_unlink(cli1, sname);
8135 cli_setatr(cli1, hname, 0, 0);
8136 cli_posix_unlink(cli1, hname);
8137 cli_setatr(cli1, fname, 0, 0);
8138 cli_posix_unlink(cli1, fname);
8139 cli_setatr(cli1, dname, 0, 0);
8140 cli_posix_rmdir(cli1, dname);
8141 cli_setatr(cli1, fname_windows, 0, 0);
8142 cli_posix_unlink(cli1, fname_windows);
8144 if (!torture_close_connection(cli1)) {
8145 correct = false;
8148 return correct;
8152 Test POSIX and Windows ACLs are rejected on symlinks.
8154 static bool run_acl_symlink_test(int dummy)
8156 static struct cli_state *cli;
8157 const char *fname = "posix_file";
8158 const char *sname = "posix_symlink";
8159 uint16_t fnum = (uint16_t)-1;
8160 bool correct = false;
8161 NTSTATUS status;
8162 char *posix_acl = NULL;
8163 size_t posix_acl_len = 0;
8164 char *posix_acl_sym = NULL;
8165 size_t posix_acl_len_sym = 0;
8166 struct security_descriptor *sd = NULL;
8167 TALLOC_CTX *frame = NULL;
8169 frame = talloc_stackframe();
8171 printf("Starting acl symlink test\n");
8173 if (!torture_open_connection(&cli, 0)) {
8174 TALLOC_FREE(frame);
8175 return false;
8178 smbXcli_conn_set_sockopt(cli->conn, sockops);
8180 status = torture_setup_unix_extensions(cli);
8181 if (!NT_STATUS_IS_OK(status)) {
8182 TALLOC_FREE(frame);
8183 return false;
8186 cli_setatr(cli, fname, 0, 0);
8187 cli_posix_unlink(cli, fname);
8188 cli_setatr(cli, sname, 0, 0);
8189 cli_posix_unlink(cli, sname);
8191 status = cli_ntcreate(cli,
8192 fname,
8194 READ_CONTROL_ACCESS,
8196 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8197 FILE_CREATE,
8198 0x0,
8199 0x0,
8200 &fnum,
8201 NULL);
8203 if (!NT_STATUS_IS_OK(status)) {
8204 printf("cli_ntcreate of %s failed (%s)\n",
8205 fname,
8206 nt_errstr(status));
8207 goto out;
8210 /* Get the Windows ACL on the file. */
8211 status = cli_query_secdesc(cli,
8212 fnum,
8213 frame,
8214 &sd);
8215 if (!NT_STATUS_IS_OK(status)) {
8216 printf("cli_query_secdesc failed (%s)\n",
8217 nt_errstr(status));
8218 goto out;
8221 /* Get the POSIX ACL on the file. */
8222 status = cli_posix_getacl(cli,
8223 fname,
8224 frame,
8225 &posix_acl_len,
8226 &posix_acl);
8228 if (!NT_STATUS_IS_OK(status)) {
8229 printf("cli_posix_getacl failed (%s)\n",
8230 nt_errstr(status));
8231 goto out;
8234 status = cli_close(cli, fnum);
8235 if (!NT_STATUS_IS_OK(status)) {
8236 printf("close failed (%s)\n", nt_errstr(status));
8237 goto out;
8239 fnum = (uint16_t)-1;
8241 /* Now create a symlink. */
8242 status = cli_posix_symlink(cli, fname, sname);
8243 if (!NT_STATUS_IS_OK(status)) {
8244 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8245 sname,
8246 fname,
8247 nt_errstr(status));
8248 goto out;
8251 /* Open a handle on the symlink for SD set/get should fail. */
8252 status = cli_ntcreate(cli,
8253 sname,
8255 READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8257 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8258 FILE_OPEN,
8259 0x0,
8260 0x0,
8261 &fnum,
8262 NULL);
8264 if (NT_STATUS_IS_OK(status)) {
8265 printf("Symlink open for getsd/setsd of %s "
8266 "succeeded (should fail)\n",
8267 sname);
8268 goto out;
8271 /* Try a stat-open on the symlink, should also fail. */
8272 status = cli_ntcreate(cli,
8273 sname,
8275 FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8277 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8278 FILE_OPEN,
8279 0x0,
8280 0x0,
8281 &fnum,
8282 NULL);
8284 if (NT_STATUS_IS_OK(status)) {
8285 printf("Stat-open of symlink succeeded (should fail)\n");
8286 goto out;
8289 /* Get the POSIX ACL on the symlink pathname. Should fail. */
8290 status = cli_posix_getacl(cli,
8291 sname,
8292 frame,
8293 &posix_acl_len_sym,
8294 &posix_acl_sym);
8296 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8297 printf("cli_posix_getacl on a symlink gave %s. "
8298 "Should be NT_STATUS_ACCESS_DENIED.\n",
8299 nt_errstr(status));
8300 goto out;
8303 /* Set the POSIX ACL on the symlink pathname. Should fail. */
8304 status = cli_posix_setacl(cli,
8305 sname,
8306 posix_acl,
8307 posix_acl_len);
8309 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8310 printf("cli_posix_setacl on a symlink gave %s. "
8311 "Should be NT_STATUS_ACCESS_DENIED.\n",
8312 nt_errstr(status));
8313 goto out;
8316 printf("ACL symlink test passed\n");
8317 correct = true;
8319 out:
8321 if (fnum != (uint16_t)-1) {
8322 cli_close(cli, fnum);
8323 fnum = (uint16_t)-1;
8326 cli_setatr(cli, sname, 0, 0);
8327 cli_posix_unlink(cli, sname);
8328 cli_setatr(cli, fname, 0, 0);
8329 cli_posix_unlink(cli, fname);
8331 if (!torture_close_connection(cli)) {
8332 correct = false;
8335 TALLOC_FREE(frame);
8336 return correct;
8340 Test POSIX can delete a file containing streams.
8342 static bool run_posix_stream_delete(int dummy)
8344 struct cli_state *cli1 = NULL;
8345 struct cli_state *cli2 = NULL;
8346 const char *fname = "streamfile";
8347 const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8348 uint16_t fnum1 = (uint16_t)-1;
8349 bool correct = false;
8350 NTSTATUS status;
8351 TALLOC_CTX *frame = NULL;
8353 frame = talloc_stackframe();
8355 printf("Starting POSIX stream delete test\n");
8357 if (!torture_open_connection(&cli1, 0) ||
8358 !torture_open_connection(&cli2, 1)) {
8359 TALLOC_FREE(frame);
8360 return false;
8363 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8364 smbXcli_conn_set_sockopt(cli2->conn, sockops);
8366 status = torture_setup_unix_extensions(cli2);
8367 if (!NT_STATUS_IS_OK(status)) {
8368 goto out;
8371 cli_setatr(cli1, fname, 0, 0);
8372 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8374 /* Create the file. */
8375 status = cli_ntcreate(cli1,
8376 fname,
8378 READ_CONTROL_ACCESS,
8380 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8381 FILE_CREATE,
8382 0x0,
8383 0x0,
8384 &fnum1,
8385 NULL);
8387 if (!NT_STATUS_IS_OK(status)) {
8388 printf("cli_ntcreate of %s failed (%s)\n",
8389 fname,
8390 nt_errstr(status));
8391 goto out;
8394 status = cli_close(cli1, fnum1);
8395 if (!NT_STATUS_IS_OK(status)) {
8396 printf("cli_close of %s failed (%s)\n",
8397 fname,
8398 nt_errstr(status));
8399 goto out;
8401 fnum1 = (uint16_t)-1;
8403 /* Now create the stream. */
8404 status = cli_ntcreate(cli1,
8405 stream_fname,
8407 FILE_WRITE_DATA,
8409 FILE_SHARE_READ|FILE_SHARE_WRITE,
8410 FILE_CREATE,
8411 0x0,
8412 0x0,
8413 &fnum1,
8414 NULL);
8416 if (!NT_STATUS_IS_OK(status)) {
8417 printf("cli_ntcreate of %s failed (%s)\n",
8418 stream_fname,
8419 nt_errstr(status));
8420 goto out;
8423 /* Leave the stream handle open... */
8425 /* POSIX unlink should fail. */
8426 status = cli_posix_unlink(cli2, fname);
8427 if (NT_STATUS_IS_OK(status)) {
8428 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8429 fname);
8430 goto out;
8433 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8434 printf("cli_posix_unlink of %s failed with (%s) "
8435 "should have been NT_STATUS_SHARING_VIOLATION\n",
8436 fname,
8437 nt_errstr(status));
8438 goto out;
8441 /* Close the stream handle. */
8442 status = cli_close(cli1, fnum1);
8443 if (!NT_STATUS_IS_OK(status)) {
8444 printf("cli_close of %s failed (%s)\n",
8445 stream_fname,
8446 nt_errstr(status));
8447 goto out;
8449 fnum1 = (uint16_t)-1;
8451 /* POSIX unlink after stream handle closed should succeed. */
8452 status = cli_posix_unlink(cli2, fname);
8453 if (!NT_STATUS_IS_OK(status)) {
8454 printf("cli_posix_unlink of %s failed (%s)\n",
8455 fname,
8456 nt_errstr(status));
8457 goto out;
8460 printf("POSIX stream delete test passed\n");
8461 correct = true;
8463 out:
8465 if (fnum1 != (uint16_t)-1) {
8466 cli_close(cli1, fnum1);
8467 fnum1 = (uint16_t)-1;
8470 cli_setatr(cli1, fname, 0, 0);
8471 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8473 if (!torture_close_connection(cli1)) {
8474 correct = false;
8476 if (!torture_close_connection(cli2)) {
8477 correct = false;
8480 TALLOC_FREE(frame);
8481 return correct;
8485 Test setting EA's are rejected on symlinks.
8487 static bool run_ea_symlink_test(int dummy)
8489 static struct cli_state *cli;
8490 const char *fname = "posix_file_ea";
8491 const char *sname = "posix_symlink_ea";
8492 const char *ea_name = "testea_name";
8493 const char *ea_value = "testea_value";
8494 uint16_t fnum = (uint16_t)-1;
8495 bool correct = false;
8496 NTSTATUS status;
8497 size_t i, num_eas;
8498 struct ea_struct *eas = NULL;
8499 TALLOC_CTX *frame = NULL;
8501 frame = talloc_stackframe();
8503 printf("Starting EA symlink test\n");
8505 if (!torture_open_connection(&cli, 0)) {
8506 TALLOC_FREE(frame);
8507 return false;
8510 smbXcli_conn_set_sockopt(cli->conn, sockops);
8512 status = torture_setup_unix_extensions(cli);
8513 if (!NT_STATUS_IS_OK(status)) {
8514 TALLOC_FREE(frame);
8515 return false;
8518 cli_setatr(cli, fname, 0, 0);
8519 cli_posix_unlink(cli, fname);
8520 cli_setatr(cli, sname, 0, 0);
8521 cli_posix_unlink(cli, sname);
8523 status = cli_ntcreate(cli,
8524 fname,
8526 READ_CONTROL_ACCESS,
8528 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8529 FILE_CREATE,
8530 0x0,
8531 0x0,
8532 &fnum,
8533 NULL);
8535 if (!NT_STATUS_IS_OK(status)) {
8536 printf("cli_ntcreate of %s failed (%s)\n",
8537 fname,
8538 nt_errstr(status));
8539 goto out;
8542 status = cli_close(cli, fnum);
8543 if (!NT_STATUS_IS_OK(status)) {
8544 printf("close failed (%s)\n",
8545 nt_errstr(status));
8546 goto out;
8548 fnum = (uint16_t)-1;
8550 /* Set an EA on the path. */
8551 status = cli_set_ea_path(cli,
8552 fname,
8553 ea_name,
8554 ea_value,
8555 strlen(ea_value)+1);
8557 if (!NT_STATUS_IS_OK(status)) {
8558 printf("cli_set_ea_path failed (%s)\n",
8559 nt_errstr(status));
8560 goto out;
8563 /* Now create a symlink. */
8564 status = cli_posix_symlink(cli, fname, sname);
8565 if (!NT_STATUS_IS_OK(status)) {
8566 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8567 sname,
8568 fname,
8569 nt_errstr(status));
8570 goto out;
8573 /* Get the EA list on the path. Should return value set. */
8574 status = cli_get_ea_list_path(cli,
8575 fname,
8576 frame,
8577 &num_eas,
8578 &eas);
8580 if (!NT_STATUS_IS_OK(status)) {
8581 printf("cli_get_ea_list_path failed (%s)\n",
8582 nt_errstr(status));
8583 goto out;
8586 /* Ensure the EA we set is there. */
8587 for (i=0; i<num_eas; i++) {
8588 if (strcmp(eas[i].name, ea_name) == 0 &&
8589 eas[i].value.length == strlen(ea_value)+1 &&
8590 memcmp(eas[i].value.data,
8591 ea_value,
8592 eas[i].value.length) == 0) {
8593 break;
8597 if (i == num_eas) {
8598 printf("Didn't find EA on pathname %s\n",
8599 fname);
8600 goto out;
8603 num_eas = 0;
8604 TALLOC_FREE(eas);
8606 /* Get the EA list on the symlink. Should return empty list. */
8607 status = cli_get_ea_list_path(cli,
8608 sname,
8609 frame,
8610 &num_eas,
8611 &eas);
8613 if (!NT_STATUS_IS_OK(status)) {
8614 printf("cli_get_ea_list_path failed (%s)\n",
8615 nt_errstr(status));
8616 goto out;
8619 if (num_eas != 0) {
8620 printf("cli_get_ea_list_path failed (%s)\n",
8621 nt_errstr(status));
8622 goto out;
8625 /* Set an EA on the symlink. Should fail. */
8626 status = cli_set_ea_path(cli,
8627 sname,
8628 ea_name,
8629 ea_value,
8630 strlen(ea_value)+1);
8632 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8633 printf("cli_set_ea_path on a symlink gave %s. "
8634 "Should be NT_STATUS_ACCESS_DENIED.\n",
8635 nt_errstr(status));
8636 goto out;
8639 printf("EA symlink test passed\n");
8640 correct = true;
8642 out:
8644 if (fnum != (uint16_t)-1) {
8645 cli_close(cli, fnum);
8646 fnum = (uint16_t)-1;
8649 cli_setatr(cli, sname, 0, 0);
8650 cli_posix_unlink(cli, sname);
8651 cli_setatr(cli, fname, 0, 0);
8652 cli_posix_unlink(cli, fname);
8654 if (!torture_close_connection(cli)) {
8655 correct = false;
8658 TALLOC_FREE(frame);
8659 return correct;
8663 Test POSIX locks are OFD-locks.
8665 static bool run_posix_ofd_lock_test(int dummy)
8667 static struct cli_state *cli;
8668 const char *fname = "posix_file";
8669 uint16_t fnum1 = (uint16_t)-1;
8670 uint16_t fnum2 = (uint16_t)-1;
8671 bool correct = false;
8672 NTSTATUS status;
8673 TALLOC_CTX *frame = NULL;
8675 frame = talloc_stackframe();
8677 printf("Starting POSIX ofd-lock test\n");
8679 if (!torture_open_connection(&cli, 0)) {
8680 TALLOC_FREE(frame);
8681 return false;
8684 smbXcli_conn_set_sockopt(cli->conn, sockops);
8686 status = torture_setup_unix_extensions(cli);
8687 if (!NT_STATUS_IS_OK(status)) {
8688 TALLOC_FREE(frame);
8689 return false;
8692 cli_setatr(cli, fname, 0, 0);
8693 cli_posix_unlink(cli, fname);
8695 /* Open the file twice. */
8696 status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8697 0600, &fnum1);
8698 if (!NT_STATUS_IS_OK(status)) {
8699 printf("First POSIX open of %s failed\n", fname);
8700 goto out;
8703 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8704 if (!NT_STATUS_IS_OK(status)) {
8705 printf("First POSIX open of %s failed\n", fname);
8706 goto out;
8709 /* Set a 0-50 lock on fnum1. */
8710 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8711 if (!NT_STATUS_IS_OK(status)) {
8712 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8713 goto out;
8716 /* Set a 60-100 lock on fnum2. */
8717 status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8718 if (!NT_STATUS_IS_OK(status)) {
8719 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8720 goto out;
8723 /* close fnum1 - 0-50 lock should go away. */
8724 status = cli_close(cli, fnum1);
8725 if (!NT_STATUS_IS_OK(status)) {
8726 printf("close failed (%s)\n",
8727 nt_errstr(status));
8728 goto out;
8730 fnum1 = (uint16_t)-1;
8732 /* Change the lock context. */
8733 cli_setpid(cli, cli_getpid(cli) + 1);
8735 /* Re-open fnum1. */
8736 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8737 if (!NT_STATUS_IS_OK(status)) {
8738 printf("Third POSIX open of %s failed\n", fname);
8739 goto out;
8742 /* 60-100 lock should still be there. */
8743 status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8744 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8745 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8746 goto out;
8749 /* 0-50 lock should be gone. */
8750 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8751 if (!NT_STATUS_IS_OK(status)) {
8752 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8753 goto out;
8756 printf("POSIX OFD lock test passed\n");
8757 correct = true;
8759 out:
8761 if (fnum1 != (uint16_t)-1) {
8762 cli_close(cli, fnum1);
8763 fnum1 = (uint16_t)-1;
8765 if (fnum2 != (uint16_t)-1) {
8766 cli_close(cli, fnum2);
8767 fnum2 = (uint16_t)-1;
8770 cli_setatr(cli, fname, 0, 0);
8771 cli_posix_unlink(cli, fname);
8773 if (!torture_close_connection(cli)) {
8774 correct = false;
8777 TALLOC_FREE(frame);
8778 return correct;
8781 struct posix_blocking_state {
8782 struct tevent_context *ev;
8783 struct cli_state *cli1;
8784 uint16_t fnum1;
8785 struct cli_state *cli2;
8786 uint16_t fnum2;
8787 bool gotblocked;
8788 bool gotecho;
8791 static void posix_blocking_locked(struct tevent_req *subreq);
8792 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8793 static void posix_blocking_gotecho(struct tevent_req *subreq);
8794 static void posix_blocking_unlocked(struct tevent_req *subreq);
8796 static struct tevent_req *posix_blocking_send(
8797 TALLOC_CTX *mem_ctx,
8798 struct tevent_context *ev,
8799 struct cli_state *cli1,
8800 uint16_t fnum1,
8801 struct cli_state *cli2,
8802 uint16_t fnum2)
8804 struct tevent_req *req = NULL, *subreq = NULL;
8805 struct posix_blocking_state *state = NULL;
8807 req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8808 if (req == NULL) {
8809 return NULL;
8811 state->ev = ev;
8812 state->cli1 = cli1;
8813 state->fnum1 = fnum1;
8814 state->cli2 = cli2;
8815 state->fnum2 = fnum2;
8817 subreq = cli_posix_lock_send(
8818 state,
8819 state->ev,
8820 state->cli1,
8821 state->fnum1,
8824 false,
8825 WRITE_LOCK);
8826 if (tevent_req_nomem(subreq, req)) {
8827 return tevent_req_post(req, ev);
8829 tevent_req_set_callback(subreq, posix_blocking_locked, req);
8830 return req;
8833 static void posix_blocking_locked(struct tevent_req *subreq)
8835 struct tevent_req *req = tevent_req_callback_data(
8836 subreq, struct tevent_req);
8837 struct posix_blocking_state *state = tevent_req_data(
8838 req, struct posix_blocking_state);
8839 NTSTATUS status;
8841 status = cli_posix_lock_recv(subreq);
8842 TALLOC_FREE(subreq);
8843 if (tevent_req_nterror(req, status)) {
8844 return;
8847 subreq = cli_posix_lock_send(
8848 state,
8849 state->ev,
8850 state->cli2,
8851 state->fnum2,
8854 true,
8855 WRITE_LOCK);
8856 if (tevent_req_nomem(subreq, req)) {
8857 return;
8859 tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8861 /* Make sure the blocking request is delivered */
8862 subreq = cli_echo_send(
8863 state,
8864 state->ev,
8865 state->cli2,
8867 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8868 if (tevent_req_nomem(subreq, req)) {
8869 return;
8871 tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8874 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8876 struct tevent_req *req = tevent_req_callback_data(
8877 subreq, struct tevent_req);
8878 struct posix_blocking_state *state = tevent_req_data(
8879 req, struct posix_blocking_state);
8880 NTSTATUS status;
8882 status = cli_posix_lock_recv(subreq);
8883 TALLOC_FREE(subreq);
8884 if (tevent_req_nterror(req, status)) {
8885 return;
8887 if (!state->gotecho) {
8888 printf("blocked req got through before echo\n");
8889 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8890 return;
8892 tevent_req_done(req);
8895 static void posix_blocking_gotecho(struct tevent_req *subreq)
8897 struct tevent_req *req = tevent_req_callback_data(
8898 subreq, struct tevent_req);
8899 struct posix_blocking_state *state = tevent_req_data(
8900 req, struct posix_blocking_state);
8901 NTSTATUS status;
8903 status = cli_echo_recv(subreq);
8904 TALLOC_FREE(subreq);
8905 if (tevent_req_nterror(req, status)) {
8906 return;
8908 if (state->gotblocked) {
8909 printf("blocked req got through before echo\n");
8910 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8911 return;
8913 state->gotecho = true;
8915 subreq = cli_posix_lock_send(
8916 state,
8917 state->ev,
8918 state->cli1,
8919 state->fnum1,
8922 false,
8923 UNLOCK_LOCK);
8924 if (tevent_req_nomem(subreq, req)) {
8925 return;
8927 tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
8930 static void posix_blocking_unlocked(struct tevent_req *subreq)
8932 struct tevent_req *req = tevent_req_callback_data(
8933 subreq, struct tevent_req);
8934 NTSTATUS status;
8936 status = cli_posix_lock_recv(subreq);
8937 TALLOC_FREE(subreq);
8938 if (tevent_req_nterror(req, status)) {
8939 return;
8941 /* tevent_req_done in posix_blocking_gotlocked */
8944 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
8946 return tevent_req_simple_recv_ntstatus(req);
8949 static bool run_posix_blocking_lock(int dummy)
8951 struct tevent_context *ev = NULL;
8952 struct cli_state *cli1 = NULL, *cli2 = NULL;
8953 const char *fname = "posix_blocking";
8954 uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
8955 struct tevent_req *req = NULL;
8956 NTSTATUS status;
8957 bool ret = false;
8958 bool ok;
8960 printf("Starting posix blocking lock test\n");
8962 ev = samba_tevent_context_init(NULL);
8963 if (ev == NULL) {
8964 return false;
8967 ok = torture_open_connection(&cli1, 0);
8968 if (!ok) {
8969 goto fail;
8971 ok = torture_open_connection(&cli2, 0);
8972 if (!ok) {
8973 goto fail;
8976 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8978 status = torture_setup_unix_extensions(cli1);
8979 if (!NT_STATUS_IS_OK(status)) {
8980 return false;
8983 status = torture_setup_unix_extensions(cli2);
8984 if (!NT_STATUS_IS_OK(status)) {
8985 return false;
8988 cli_setatr(cli1, fname, 0, 0);
8989 cli_posix_unlink(cli1, fname);
8991 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8992 0600, &fnum1);
8993 if (!NT_STATUS_IS_OK(status)) {
8994 printf("First POSIX open of %s failed: %s\n",
8995 fname,
8996 nt_errstr(status));
8997 goto fail;
9000 status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
9001 if (!NT_STATUS_IS_OK(status)) {
9002 printf("Second POSIX open of %s failed: %s\n",
9003 fname,
9004 nt_errstr(status));
9005 goto fail;
9008 req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9009 if (req == NULL) {
9010 printf("cli_posix_blocking failed\n");
9011 goto fail;
9014 ok = tevent_req_poll_ntstatus(req, ev, &status);
9015 if (!ok) {
9016 printf("tevent_req_poll_ntstatus failed: %s\n",
9017 nt_errstr(status));
9018 goto fail;
9020 status = posix_blocking_recv(req);
9021 TALLOC_FREE(req);
9022 if (!NT_STATUS_IS_OK(status)) {
9023 printf("posix_blocking_recv returned %s\n",
9024 nt_errstr(status));
9025 goto fail;
9028 ret = true;
9029 fail:
9031 if (fnum1 != UINT16_MAX) {
9032 cli_close(cli1, fnum1);
9033 fnum1 = UINT16_MAX;
9035 if (fnum2 != UINT16_MAX) {
9036 cli_close(cli2, fnum2);
9037 fnum2 = UINT16_MAX;
9040 if (cli1 != NULL) {
9041 cli_setatr(cli1, fname, 0, 0);
9042 cli_posix_unlink(cli1, fname);
9045 ok = true;
9047 if (cli1 != NULL) {
9048 ok &= torture_close_connection(cli1);
9049 cli1 = NULL;
9051 if (cli2 != NULL) {
9052 ok &= torture_close_connection(cli2);
9053 cli2 = NULL;
9056 if (!ok) {
9057 ret = false;
9059 TALLOC_FREE(ev);
9060 return ret;
9064 Test POSIX mkdir is case-sensitive.
9066 static bool run_posix_mkdir_test(int dummy)
9068 static struct cli_state *cli;
9069 const char *fname_foo = "POSIX_foo";
9070 const char *fname_foo_Foo = "POSIX_foo/Foo";
9071 const char *fname_foo_foo = "POSIX_foo/foo";
9072 const char *fname_Foo = "POSIX_Foo";
9073 const char *fname_Foo_Foo = "POSIX_Foo/Foo";
9074 const char *fname_Foo_foo = "POSIX_Foo/foo";
9075 bool correct = false;
9076 NTSTATUS status;
9077 TALLOC_CTX *frame = NULL;
9078 uint16_t fnum = (uint16_t)-1;
9080 frame = talloc_stackframe();
9082 printf("Starting POSIX mkdir test\n");
9084 if (!torture_open_connection(&cli, 0)) {
9085 TALLOC_FREE(frame);
9086 return false;
9089 smbXcli_conn_set_sockopt(cli->conn, sockops);
9091 status = torture_setup_unix_extensions(cli);
9092 if (!NT_STATUS_IS_OK(status)) {
9093 TALLOC_FREE(frame);
9094 return false;
9097 cli_posix_rmdir(cli, fname_foo_foo);
9098 cli_posix_rmdir(cli, fname_foo_Foo);
9099 cli_posix_rmdir(cli, fname_foo);
9101 cli_posix_rmdir(cli, fname_Foo_foo);
9102 cli_posix_rmdir(cli, fname_Foo_Foo);
9103 cli_posix_rmdir(cli, fname_Foo);
9106 * Create a file POSIX_foo then try
9107 * and use it in a directory path by
9108 * doing mkdir POSIX_foo/bar.
9109 * The mkdir should fail with
9110 * NT_STATUS_OBJECT_PATH_NOT_FOUND
9113 status = cli_posix_open(cli,
9114 fname_foo,
9115 O_RDWR|O_CREAT,
9116 0666,
9117 &fnum);
9118 if (!NT_STATUS_IS_OK(status)) {
9119 printf("cli_posix_open of %s failed error %s\n",
9120 fname_foo,
9121 nt_errstr(status));
9122 goto out;
9125 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9126 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9127 printf("cli_posix_mkdir of %s should fail with "
9128 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9129 "%s instead\n",
9130 fname_foo_foo,
9131 nt_errstr(status));
9132 goto out;
9135 status = cli_close(cli, fnum);
9136 if (!NT_STATUS_IS_OK(status)) {
9137 printf("cli_close failed %s\n", nt_errstr(status));
9138 goto out;
9140 fnum = (uint16_t)-1;
9142 status = cli_posix_unlink(cli, fname_foo);
9143 if (!NT_STATUS_IS_OK(status)) {
9144 printf("cli_posix_unlink of %s failed error %s\n",
9145 fname_foo,
9146 nt_errstr(status));
9147 goto out;
9151 * Now we've deleted everything, posix_mkdir, posix_rmdir,
9152 * posix_open, posix_unlink, on
9153 * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9154 * not silently create POSIX_foo/foo.
9157 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9158 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9159 printf("cli_posix_mkdir of %s should fail with "
9160 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9161 "%s instead\n",
9162 fname_foo_foo,
9163 nt_errstr(status));
9164 goto out;
9167 status = cli_posix_rmdir(cli, fname_foo_foo);
9168 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9169 printf("cli_posix_rmdir of %s should fail with "
9170 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9171 "%s instead\n",
9172 fname_foo_foo,
9173 nt_errstr(status));
9174 goto out;
9177 status = cli_posix_open(cli,
9178 fname_foo_foo,
9179 O_RDWR|O_CREAT,
9180 0666,
9181 &fnum);
9182 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9183 printf("cli_posix_open of %s should fail with "
9184 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9185 "%s instead\n",
9186 fname_foo_foo,
9187 nt_errstr(status));
9188 goto out;
9191 status = cli_posix_unlink(cli, fname_foo_foo);
9192 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9193 printf("cli_posix_unlink of %s should fail with "
9194 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9195 "%s instead\n",
9196 fname_foo_foo,
9197 nt_errstr(status));
9198 goto out;
9201 status = cli_posix_mkdir(cli, fname_foo, 0777);
9202 if (!NT_STATUS_IS_OK(status)) {
9203 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9204 goto out;
9207 status = cli_posix_mkdir(cli, fname_Foo, 0777);
9208 if (!NT_STATUS_IS_OK(status)) {
9209 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9210 goto out;
9213 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9214 if (!NT_STATUS_IS_OK(status)) {
9215 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9216 goto out;
9219 status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9220 if (!NT_STATUS_IS_OK(status)) {
9221 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9222 goto out;
9225 status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9226 if (!NT_STATUS_IS_OK(status)) {
9227 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9228 goto out;
9231 status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9232 if (!NT_STATUS_IS_OK(status)) {
9233 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9234 goto out;
9237 printf("POSIX mkdir test passed\n");
9238 correct = true;
9240 out:
9242 if (fnum != (uint16_t)-1) {
9243 cli_close(cli, fnum);
9244 fnum = (uint16_t)-1;
9247 cli_posix_rmdir(cli, fname_foo_foo);
9248 cli_posix_rmdir(cli, fname_foo_Foo);
9249 cli_posix_rmdir(cli, fname_foo);
9251 cli_posix_rmdir(cli, fname_Foo_foo);
9252 cli_posix_rmdir(cli, fname_Foo_Foo);
9253 cli_posix_rmdir(cli, fname_Foo);
9255 if (!torture_close_connection(cli)) {
9256 correct = false;
9259 TALLOC_FREE(frame);
9260 return correct;
9263 struct posix_acl_oplock_state {
9264 struct tevent_context *ev;
9265 struct cli_state *cli;
9266 bool *got_break;
9267 bool *acl_ret;
9268 NTSTATUS status;
9271 static void posix_acl_oplock_got_break(struct tevent_req *req)
9273 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9274 req, struct posix_acl_oplock_state);
9275 uint16_t fnum;
9276 uint8_t level;
9277 NTSTATUS status;
9279 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9280 TALLOC_FREE(req);
9281 if (!NT_STATUS_IS_OK(status)) {
9282 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9283 nt_errstr(status));
9284 return;
9286 *state->got_break = true;
9288 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9289 NO_OPLOCK);
9290 if (req == NULL) {
9291 printf("cli_oplock_ack_send failed\n");
9292 return;
9296 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9298 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9299 req, struct posix_acl_oplock_state);
9300 size_t ret_size = 0;
9301 char *ret_data = NULL;
9303 state->status = cli_posix_getacl_recv(req,
9304 state,
9305 &ret_size,
9306 &ret_data);
9308 if (!NT_STATUS_IS_OK(state->status)) {
9309 printf("cli_posix_getacl_recv returned %s\n",
9310 nt_errstr(state->status));
9312 *state->acl_ret = true;
9315 static bool run_posix_acl_oplock_test(int dummy)
9317 struct tevent_context *ev;
9318 struct cli_state *cli1, *cli2;
9319 struct tevent_req *oplock_req, *getacl_req;
9320 const char *fname = "posix_acl_oplock";
9321 uint16_t fnum;
9322 int saved_use_oplocks = use_oplocks;
9323 NTSTATUS status;
9324 bool correct = true;
9325 bool got_break = false;
9326 bool acl_ret = false;
9328 struct posix_acl_oplock_state *state;
9330 printf("starting posix_acl_oplock test\n");
9332 if (!torture_open_connection(&cli1, 0)) {
9333 use_level_II_oplocks = false;
9334 use_oplocks = saved_use_oplocks;
9335 return false;
9338 if (!torture_open_connection(&cli2, 1)) {
9339 use_level_II_oplocks = false;
9340 use_oplocks = saved_use_oplocks;
9341 return false;
9344 /* Setup posix on cli2 only. */
9345 status = torture_setup_unix_extensions(cli2);
9346 if (!NT_STATUS_IS_OK(status)) {
9347 return false;
9350 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9351 smbXcli_conn_set_sockopt(cli2->conn, sockops);
9353 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9355 /* Create the file on the Windows connection. */
9356 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9357 &fnum);
9358 if (!NT_STATUS_IS_OK(status)) {
9359 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9360 return false;
9363 status = cli_close(cli1, fnum);
9364 if (!NT_STATUS_IS_OK(status)) {
9365 printf("close1 failed (%s)\n", nt_errstr(status));
9366 return false;
9369 cli1->use_oplocks = true;
9371 /* Open with oplock. */
9372 status = cli_ntcreate(cli1,
9373 fname,
9375 FILE_READ_DATA,
9376 FILE_ATTRIBUTE_NORMAL,
9377 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9378 FILE_OPEN,
9381 &fnum,
9382 NULL);
9384 if (!NT_STATUS_IS_OK(status)) {
9385 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9386 return false;
9389 ev = samba_tevent_context_init(talloc_tos());
9390 if (ev == NULL) {
9391 printf("tevent_context_init failed\n");
9392 return false;
9395 state = talloc_zero(ev, struct posix_acl_oplock_state);
9396 if (state == NULL) {
9397 printf("talloc failed\n");
9398 return false;
9400 state->ev = ev;
9401 state->cli = cli1;
9402 state->got_break = &got_break;
9403 state->acl_ret = &acl_ret;
9405 oplock_req = cli_smb_oplock_break_waiter_send(
9406 talloc_tos(), ev, cli1);
9407 if (oplock_req == NULL) {
9408 printf("cli_smb_oplock_break_waiter_send failed\n");
9409 return false;
9411 tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9413 /* Get ACL on POSIX connection - should break oplock. */
9414 getacl_req = cli_posix_getacl_send(talloc_tos(),
9416 cli2,
9417 fname);
9418 if (getacl_req == NULL) {
9419 printf("cli_posix_getacl_send failed\n");
9420 return false;
9422 tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9424 while (!got_break || !acl_ret) {
9425 int ret;
9426 ret = tevent_loop_once(ev);
9427 if (ret == -1) {
9428 printf("tevent_loop_once failed: %s\n",
9429 strerror(errno));
9430 return false;
9434 if (!NT_STATUS_IS_OK(state->status)) {
9435 printf("getacl failed (%s)\n", nt_errstr(state->status));
9436 correct = false;
9439 status = cli_close(cli1, fnum);
9440 if (!NT_STATUS_IS_OK(status)) {
9441 printf("close2 failed (%s)\n", nt_errstr(status));
9442 correct = false;
9445 status = cli_unlink(cli1,
9446 fname,
9447 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9448 if (!NT_STATUS_IS_OK(status)) {
9449 printf("unlink failed (%s)\n", nt_errstr(status));
9450 correct = false;
9453 if (!torture_close_connection(cli1)) {
9454 correct = false;
9456 if (!torture_close_connection(cli2)) {
9457 correct = false;
9460 if (!got_break) {
9461 correct = false;
9464 printf("finished posix acl oplock test\n");
9466 return correct;
9469 static bool run_posix_acl_shareroot_test(int dummy)
9471 struct cli_state *cli;
9472 NTSTATUS status;
9473 bool correct = false;
9474 char *posix_acl = NULL;
9475 size_t posix_acl_len = 0;
9476 uint16_t num_file_acls = 0;
9477 uint16_t num_dir_acls = 0;
9478 uint16_t i;
9479 uint32_t expected_size = 0;
9480 bool got_user = false;
9481 bool got_group = false;
9482 bool got_other = false;
9483 TALLOC_CTX *frame = NULL;
9485 frame = talloc_stackframe();
9487 printf("starting posix_acl_shareroot test\n");
9489 if (!torture_open_connection(&cli, 0)) {
9490 TALLOC_FREE(frame);
9491 return false;
9494 smbXcli_conn_set_sockopt(cli->conn, sockops);
9496 status = torture_setup_unix_extensions(cli);
9497 if (!NT_STATUS_IS_OK(status)) {
9498 printf("Failed to setup unix extensions\n");
9499 goto out;
9502 /* Get the POSIX ACL on the root of the share. */
9503 status = cli_posix_getacl(cli,
9504 ".",
9505 frame,
9506 &posix_acl_len,
9507 &posix_acl);
9509 if (!NT_STATUS_IS_OK(status)) {
9510 printf("cli_posix_getacl of '.' failed (%s)\n",
9511 nt_errstr(status));
9512 goto out;
9515 if (posix_acl_len < 6 ||
9516 SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9517 printf("getfacl ., unknown POSIX acl version %u.\n",
9518 (unsigned int)CVAL(posix_acl,0) );
9519 goto out;
9522 num_file_acls = SVAL(posix_acl,2);
9523 num_dir_acls = SVAL(posix_acl,4);
9524 expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9525 SMB_POSIX_ACL_ENTRY_SIZE*
9526 (num_file_acls+num_dir_acls);
9528 if (posix_acl_len != expected_size) {
9529 printf("incorrect POSIX acl buffer size "
9530 "(should be %u, was %u).\n",
9531 (unsigned int)expected_size,
9532 (unsigned int)posix_acl_len);
9533 goto out;
9537 * We don't need to know what the ACL's are
9538 * we just need to know we have at least 3
9539 * file entries (u,g,o).
9542 for (i = 0; i < num_file_acls; i++) {
9543 unsigned char tagtype =
9544 CVAL(posix_acl,
9545 SMB_POSIX_ACL_HEADER_SIZE+
9546 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9548 switch(tagtype) {
9549 case SMB_POSIX_ACL_USER_OBJ:
9550 got_user = true;
9551 break;
9552 case SMB_POSIX_ACL_GROUP_OBJ:
9553 got_group = true;
9554 break;
9555 case SMB_POSIX_ACL_OTHER:
9556 got_other = true;
9557 break;
9558 default:
9559 break;
9563 if (!got_user) {
9564 printf("Missing user entry\n");
9565 goto out;
9568 if (!got_group) {
9569 printf("Missing group entry\n");
9570 goto out;
9573 if (!got_other) {
9574 printf("Missing other entry\n");
9575 goto out;
9578 correct = true;
9580 out:
9582 if (!torture_close_connection(cli)) {
9583 correct = false;
9586 printf("finished posix acl shareroot test\n");
9587 TALLOC_FREE(frame);
9589 return correct;
9592 static uint32_t open_attrs_table[] = {
9593 FILE_ATTRIBUTE_NORMAL,
9594 FILE_ATTRIBUTE_ARCHIVE,
9595 FILE_ATTRIBUTE_READONLY,
9596 FILE_ATTRIBUTE_HIDDEN,
9597 FILE_ATTRIBUTE_SYSTEM,
9599 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9600 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9601 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9602 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9603 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9604 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9606 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9607 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9608 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9609 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9612 struct trunc_open_results {
9613 unsigned int num;
9614 uint32_t init_attr;
9615 uint32_t trunc_attr;
9616 uint32_t result_attr;
9619 static struct trunc_open_results attr_results[] = {
9620 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9621 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9622 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9623 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9624 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9625 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9626 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9627 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9628 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9629 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9630 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9631 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9632 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9633 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9634 { 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 },
9635 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9636 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9637 { 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 },
9638 { 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 },
9639 { 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 },
9640 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9641 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9642 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9643 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9644 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9645 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9648 static bool run_openattrtest(int dummy)
9650 static struct cli_state *cli1;
9651 const char *fname = "\\openattr.file";
9652 uint16_t fnum1;
9653 bool correct = True;
9654 uint32_t attr;
9655 unsigned int i, j, k, l;
9656 NTSTATUS status;
9658 printf("starting open attr test\n");
9660 if (!torture_open_connection(&cli1, 0)) {
9661 return False;
9664 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9666 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9667 cli_setatr(cli1, fname, 0, 0);
9668 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9670 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9671 open_attrs_table[i], FILE_SHARE_NONE,
9672 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9673 if (!NT_STATUS_IS_OK(status)) {
9674 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9675 return False;
9678 status = cli_close(cli1, fnum1);
9679 if (!NT_STATUS_IS_OK(status)) {
9680 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9681 return False;
9684 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9685 status = cli_ntcreate(cli1, fname, 0,
9686 FILE_READ_DATA|FILE_WRITE_DATA,
9687 open_attrs_table[j],
9688 FILE_SHARE_NONE, FILE_OVERWRITE,
9689 0, 0, &fnum1, NULL);
9690 if (!NT_STATUS_IS_OK(status)) {
9691 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9692 if (attr_results[l].num == k) {
9693 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9694 k, open_attrs_table[i],
9695 open_attrs_table[j],
9696 fname, NT_STATUS_V(status), nt_errstr(status));
9697 correct = False;
9701 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9702 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9703 k, open_attrs_table[i], open_attrs_table[j],
9704 nt_errstr(status));
9705 correct = False;
9707 #if 0
9708 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9709 #endif
9710 k++;
9711 continue;
9714 status = cli_close(cli1, fnum1);
9715 if (!NT_STATUS_IS_OK(status)) {
9716 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9717 return False;
9720 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9721 if (!NT_STATUS_IS_OK(status)) {
9722 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9723 return False;
9726 #if 0
9727 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9728 k, open_attrs_table[i], open_attrs_table[j], attr );
9729 #endif
9731 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9732 if (attr_results[l].num == k) {
9733 if (attr != attr_results[l].result_attr ||
9734 open_attrs_table[i] != attr_results[l].init_attr ||
9735 open_attrs_table[j] != attr_results[l].trunc_attr) {
9736 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9737 open_attrs_table[i],
9738 open_attrs_table[j],
9739 (unsigned int)attr,
9740 attr_results[l].result_attr);
9741 correct = False;
9743 break;
9746 k++;
9750 cli_setatr(cli1, fname, 0, 0);
9751 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9753 printf("open attr test %s.\n", correct ? "passed" : "failed");
9755 if (!torture_close_connection(cli1)) {
9756 correct = False;
9758 return correct;
9761 static NTSTATUS list_fn(struct file_info *finfo,
9762 const char *name, void *state)
9764 int *matched = (int *)state;
9765 if (matched != NULL) {
9766 *matched += 1;
9768 return NT_STATUS_OK;
9772 test directory listing speed
9774 static bool run_dirtest(int dummy)
9776 int i;
9777 static struct cli_state *cli;
9778 uint16_t fnum;
9779 struct timeval core_start;
9780 bool correct = True;
9781 int matched;
9783 printf("starting directory test\n");
9785 if (!torture_open_connection(&cli, 0)) {
9786 return False;
9789 smbXcli_conn_set_sockopt(cli->conn, sockops);
9791 srandom(0);
9792 for (i=0;i<torture_numops;i++) {
9793 fstring fname;
9794 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9795 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9796 fprintf(stderr,"Failed to open %s\n", fname);
9797 return False;
9799 cli_close(cli, fnum);
9802 core_start = timeval_current();
9804 matched = 0;
9805 cli_list(cli, "a*.*", 0, list_fn, &matched);
9806 printf("Matched %d\n", matched);
9808 matched = 0;
9809 cli_list(cli, "b*.*", 0, list_fn, &matched);
9810 printf("Matched %d\n", matched);
9812 matched = 0;
9813 cli_list(cli, "xyzabc", 0, list_fn, &matched);
9814 printf("Matched %d\n", matched);
9816 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9818 srandom(0);
9819 for (i=0;i<torture_numops;i++) {
9820 fstring fname;
9821 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9822 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9825 if (!torture_close_connection(cli)) {
9826 correct = False;
9829 printf("finished dirtest\n");
9831 return correct;
9834 static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9835 void *state)
9837 struct cli_state *pcli = (struct cli_state *)state;
9838 fstring fname;
9839 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9841 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9842 return NT_STATUS_OK;
9844 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9845 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9846 printf("del_fn: failed to rmdir %s\n,", fname );
9847 } else {
9848 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9849 printf("del_fn: failed to unlink %s\n,", fname );
9851 return NT_STATUS_OK;
9856 sees what IOCTLs are supported
9858 bool torture_ioctl_test(int dummy)
9860 static struct cli_state *cli;
9861 uint16_t device, function;
9862 uint16_t fnum;
9863 const char *fname = "\\ioctl.dat";
9864 DATA_BLOB blob;
9865 NTSTATUS status;
9867 if (!torture_open_connection(&cli, 0)) {
9868 return False;
9871 printf("starting ioctl test\n");
9873 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9875 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9876 if (!NT_STATUS_IS_OK(status)) {
9877 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9878 return False;
9881 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9882 printf("ioctl device info: %s\n", nt_errstr(status));
9884 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9885 printf("ioctl job info: %s\n", nt_errstr(status));
9887 for (device=0;device<0x100;device++) {
9888 printf("ioctl test with device = 0x%x\n", device);
9889 for (function=0;function<0x100;function++) {
9890 uint32_t code = (device<<16) | function;
9892 status = cli_raw_ioctl(cli, fnum, code, &blob);
9894 if (NT_STATUS_IS_OK(status)) {
9895 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
9896 (int)blob.length);
9897 data_blob_free(&blob);
9902 if (!torture_close_connection(cli)) {
9903 return False;
9906 return True;
9911 tries variants of chkpath
9913 bool torture_chkpath_test(int dummy)
9915 static struct cli_state *cli;
9916 uint16_t fnum;
9917 bool ret;
9918 NTSTATUS status;
9920 if (!torture_open_connection(&cli, 0)) {
9921 return False;
9924 printf("starting chkpath test\n");
9926 /* cleanup from an old run */
9927 torture_deltree(cli, "\\chkpath.dir");
9929 status = cli_mkdir(cli, "\\chkpath.dir");
9930 if (!NT_STATUS_IS_OK(status)) {
9931 printf("mkdir1 failed : %s\n", nt_errstr(status));
9932 return False;
9935 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
9936 if (!NT_STATUS_IS_OK(status)) {
9937 printf("mkdir2 failed : %s\n", nt_errstr(status));
9938 return False;
9941 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
9942 DENY_NONE, &fnum);
9943 if (!NT_STATUS_IS_OK(status)) {
9944 printf("open1 failed (%s)\n", nt_errstr(status));
9945 return False;
9947 cli_close(cli, fnum);
9949 status = cli_chkpath(cli, "\\chkpath.dir");
9950 if (!NT_STATUS_IS_OK(status)) {
9951 printf("chkpath1 failed: %s\n", nt_errstr(status));
9952 ret = False;
9955 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
9956 if (!NT_STATUS_IS_OK(status)) {
9957 printf("chkpath2 failed: %s\n", nt_errstr(status));
9958 ret = False;
9961 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
9962 if (!NT_STATUS_IS_OK(status)) {
9963 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9964 NT_STATUS_NOT_A_DIRECTORY);
9965 } else {
9966 printf("* chkpath on a file should fail\n");
9967 ret = False;
9970 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
9971 if (!NT_STATUS_IS_OK(status)) {
9972 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
9973 NT_STATUS_OBJECT_NAME_NOT_FOUND);
9974 } else {
9975 printf("* chkpath on a non existent file should fail\n");
9976 ret = False;
9979 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
9980 if (!NT_STATUS_IS_OK(status)) {
9981 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9982 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9983 } else {
9984 printf("* chkpath on a non existent component should fail\n");
9985 ret = False;
9988 torture_deltree(cli, "\\chkpath.dir");
9990 if (!torture_close_connection(cli)) {
9991 return False;
9994 return ret;
9997 static bool run_eatest(int dummy)
9999 static struct cli_state *cli;
10000 const char *fname = "\\eatest.txt";
10001 bool correct = True;
10002 uint16_t fnum;
10003 size_t i, num_eas;
10004 struct ea_struct *ea_list = NULL;
10005 TALLOC_CTX *mem_ctx = talloc_init("eatest");
10006 NTSTATUS status;
10008 printf("starting eatest\n");
10010 if (!torture_open_connection(&cli, 0)) {
10011 talloc_destroy(mem_ctx);
10012 return False;
10015 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10017 status = cli_ntcreate(cli, fname, 0,
10018 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10019 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10020 0x4044, 0, &fnum, NULL);
10021 if (!NT_STATUS_IS_OK(status)) {
10022 printf("open failed - %s\n", nt_errstr(status));
10023 talloc_destroy(mem_ctx);
10024 return False;
10027 for (i = 0; i < 10; i++) {
10028 fstring ea_name, ea_val;
10030 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10031 memset(ea_val, (char)i+1, i+1);
10032 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10033 if (!NT_STATUS_IS_OK(status)) {
10034 printf("ea_set of name %s failed - %s\n", ea_name,
10035 nt_errstr(status));
10036 talloc_destroy(mem_ctx);
10037 return False;
10041 cli_close(cli, fnum);
10042 for (i = 0; i < 10; i++) {
10043 fstring ea_name, ea_val;
10045 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10046 memset(ea_val, (char)i+1, i+1);
10047 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10048 if (!NT_STATUS_IS_OK(status)) {
10049 printf("ea_set of name %s failed - %s\n", ea_name,
10050 nt_errstr(status));
10051 talloc_destroy(mem_ctx);
10052 return False;
10056 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10057 if (!NT_STATUS_IS_OK(status)) {
10058 printf("ea_get list failed - %s\n", nt_errstr(status));
10059 correct = False;
10062 printf("num_eas = %d\n", (int)num_eas);
10064 if (num_eas != 20) {
10065 printf("Should be 20 EA's stored... failing.\n");
10066 correct = False;
10069 for (i = 0; i < num_eas; i++) {
10070 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10071 dump_data(0, ea_list[i].value.data,
10072 ea_list[i].value.length);
10075 /* Setting EA's to zero length deletes them. Test this */
10076 printf("Now deleting all EA's - case independent....\n");
10078 #if 1
10079 cli_set_ea_path(cli, fname, "", "", 0);
10080 #else
10081 for (i = 0; i < 20; i++) {
10082 fstring ea_name;
10083 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10084 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10085 if (!NT_STATUS_IS_OK(status)) {
10086 printf("ea_set of name %s failed - %s\n", ea_name,
10087 nt_errstr(status));
10088 talloc_destroy(mem_ctx);
10089 return False;
10092 #endif
10094 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10095 if (!NT_STATUS_IS_OK(status)) {
10096 printf("ea_get list failed - %s\n", nt_errstr(status));
10097 correct = False;
10100 printf("num_eas = %d\n", (int)num_eas);
10101 for (i = 0; i < num_eas; i++) {
10102 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10103 dump_data(0, ea_list[i].value.data,
10104 ea_list[i].value.length);
10107 if (num_eas != 0) {
10108 printf("deleting EA's failed.\n");
10109 correct = False;
10112 /* Try and delete a non existent EA. */
10113 status = cli_set_ea_path(cli, fname, "foo", "", 0);
10114 if (!NT_STATUS_IS_OK(status)) {
10115 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10116 nt_errstr(status));
10117 correct = False;
10120 talloc_destroy(mem_ctx);
10121 if (!torture_close_connection(cli)) {
10122 correct = False;
10125 return correct;
10128 static bool run_dirtest1(int dummy)
10130 int i;
10131 static struct cli_state *cli;
10132 uint16_t fnum;
10133 int num_seen;
10134 bool correct = True;
10136 printf("starting directory test\n");
10138 if (!torture_open_connection(&cli, 0)) {
10139 return False;
10142 smbXcli_conn_set_sockopt(cli->conn, sockops);
10144 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10145 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10146 cli_rmdir(cli, "\\LISTDIR");
10147 cli_mkdir(cli, "\\LISTDIR");
10149 /* Create 1000 files and 1000 directories. */
10150 for (i=0;i<1000;i++) {
10151 fstring fname;
10152 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10153 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10154 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10155 0, 0, &fnum, NULL))) {
10156 fprintf(stderr,"Failed to open %s\n", fname);
10157 return False;
10159 cli_close(cli, fnum);
10161 for (i=0;i<1000;i++) {
10162 fstring fname;
10163 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10164 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10165 fprintf(stderr,"Failed to open %s\n", fname);
10166 return False;
10170 /* Now ensure that doing an old list sees both files and directories. */
10171 num_seen = 0;
10172 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10173 printf("num_seen = %d\n", num_seen );
10174 /* We should see 100 files + 1000 directories + . and .. */
10175 if (num_seen != 2002)
10176 correct = False;
10178 /* Ensure if we have the "must have" bits we only see the
10179 * relevant entries.
10181 num_seen = 0;
10182 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10183 printf("num_seen = %d\n", num_seen );
10184 if (num_seen != 1002)
10185 correct = False;
10187 num_seen = 0;
10188 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10189 printf("num_seen = %d\n", num_seen );
10190 if (num_seen != 1000)
10191 correct = False;
10193 /* Delete everything. */
10194 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10195 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10196 cli_rmdir(cli, "\\LISTDIR");
10198 #if 0
10199 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10200 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10201 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10202 #endif
10204 if (!torture_close_connection(cli)) {
10205 correct = False;
10208 printf("finished dirtest1\n");
10210 return correct;
10213 static bool run_error_map_extract(int dummy) {
10215 static struct cli_state *c_dos;
10216 static struct cli_state *c_nt;
10217 NTSTATUS status;
10219 uint32_t error;
10221 uint32_t errnum;
10222 uint8_t errclass;
10224 NTSTATUS nt_status;
10226 fstring user;
10228 /* NT-Error connection */
10230 disable_spnego = true;
10231 if (!(c_nt = open_nbt_connection())) {
10232 disable_spnego = false;
10233 return False;
10235 disable_spnego = false;
10237 status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
10238 PROTOCOL_NT1);
10240 if (!NT_STATUS_IS_OK(status)) {
10241 printf("%s rejected the NT-error negprot (%s)\n", host,
10242 nt_errstr(status));
10243 cli_shutdown(c_nt);
10244 return False;
10247 status = cli_session_setup_anon(c_nt);
10248 if (!NT_STATUS_IS_OK(status)) {
10249 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10250 return False;
10253 /* DOS-Error connection */
10255 disable_spnego = true;
10256 force_dos_errors = true;
10257 if (!(c_dos = open_nbt_connection())) {
10258 disable_spnego = false;
10259 force_dos_errors = false;
10260 return False;
10262 disable_spnego = false;
10263 force_dos_errors = false;
10265 status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
10266 PROTOCOL_NT1);
10267 if (!NT_STATUS_IS_OK(status)) {
10268 printf("%s rejected the DOS-error negprot (%s)\n", host,
10269 nt_errstr(status));
10270 cli_shutdown(c_dos);
10271 return False;
10274 status = cli_session_setup_anon(c_dos);
10275 if (!NT_STATUS_IS_OK(status)) {
10276 printf("%s rejected the DOS-error initial session setup (%s)\n",
10277 host, nt_errstr(status));
10278 return False;
10281 c_nt->map_dos_errors = false;
10282 c_dos->map_dos_errors = false;
10284 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10285 struct cli_credentials *user_creds = NULL;
10287 fstr_sprintf(user, "%X", error);
10289 user_creds = cli_session_creds_init(talloc_tos(),
10290 user,
10291 workgroup,
10292 NULL, /* realm */
10293 password,
10294 false, /* use_kerberos */
10295 false, /* fallback_after_kerberos */
10296 false, /* use_ccache */
10297 false); /* password_is_nt_hash */
10298 if (user_creds == NULL) {
10299 printf("cli_session_creds_init(%s) failed\n", user);
10300 return false;
10303 status = cli_session_setup_creds(c_nt, user_creds);
10304 if (NT_STATUS_IS_OK(status)) {
10305 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10308 /* Case #1: 32-bit NT errors */
10309 if (!NT_STATUS_IS_DOS(status)) {
10310 nt_status = status;
10311 } else {
10312 printf("/** Dos error on NT connection! (%s) */\n",
10313 nt_errstr(status));
10314 nt_status = NT_STATUS(0xc0000000);
10317 status = cli_session_setup_creds(c_dos, user_creds);
10318 if (NT_STATUS_IS_OK(status)) {
10319 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10322 /* Case #1: 32-bit NT errors */
10323 if (NT_STATUS_IS_DOS(status)) {
10324 printf("/** NT error on DOS connection! (%s) */\n",
10325 nt_errstr(status));
10326 errnum = errclass = 0;
10327 } else {
10328 errclass = NT_STATUS_DOS_CLASS(status);
10329 errnum = NT_STATUS_DOS_CODE(status);
10332 if (NT_STATUS_V(nt_status) != error) {
10333 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10334 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
10335 get_nt_error_c_code(talloc_tos(), nt_status));
10338 printf("\t{%s,\t%s,\t%s},\n",
10339 smb_dos_err_class(errclass),
10340 smb_dos_err_name(errclass, errnum),
10341 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10343 TALLOC_FREE(user_creds);
10345 return True;
10348 static bool run_sesssetup_bench(int dummy)
10350 static struct cli_state *c;
10351 const char *fname = "\\file.dat";
10352 uint16_t fnum;
10353 NTSTATUS status;
10354 int i;
10356 if (!torture_open_connection(&c, 0)) {
10357 return false;
10360 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10361 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10362 FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10363 if (!NT_STATUS_IS_OK(status)) {
10364 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10365 return false;
10368 for (i=0; i<torture_numops; i++) {
10369 status = cli_session_setup_creds(c, torture_creds);
10370 if (!NT_STATUS_IS_OK(status)) {
10371 d_printf("(%s) cli_session_setup_creds failed: %s\n",
10372 __location__, nt_errstr(status));
10373 return false;
10376 d_printf("\r%d ", (int)cli_state_get_uid(c));
10378 status = cli_ulogoff(c);
10379 if (!NT_STATUS_IS_OK(status)) {
10380 d_printf("(%s) cli_ulogoff failed: %s\n",
10381 __location__, nt_errstr(status));
10382 return false;
10386 return true;
10389 static bool subst_test(const char *str, const char *user, const char *domain,
10390 uid_t uid, gid_t gid, const char *expected)
10392 char *subst;
10393 bool result = true;
10395 subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10397 if (strcmp(subst, expected) != 0) {
10398 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10399 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10400 expected);
10401 result = false;
10404 TALLOC_FREE(subst);
10405 return result;
10408 static void chain1_open_completion(struct tevent_req *req)
10410 uint16_t fnum;
10411 NTSTATUS status;
10412 status = cli_openx_recv(req, &fnum);
10413 TALLOC_FREE(req);
10415 d_printf("cli_openx_recv returned %s: %d\n",
10416 nt_errstr(status),
10417 NT_STATUS_IS_OK(status) ? fnum : -1);
10420 static void chain1_write_completion(struct tevent_req *req)
10422 size_t written;
10423 NTSTATUS status;
10424 status = cli_write_andx_recv(req, &written);
10425 TALLOC_FREE(req);
10427 d_printf("cli_write_andx_recv returned %s: %d\n",
10428 nt_errstr(status),
10429 NT_STATUS_IS_OK(status) ? (int)written : -1);
10432 static void chain1_close_completion(struct tevent_req *req)
10434 NTSTATUS status;
10435 bool *done = (bool *)tevent_req_callback_data_void(req);
10437 status = cli_close_recv(req);
10438 *done = true;
10440 TALLOC_FREE(req);
10442 d_printf("cli_close returned %s\n", nt_errstr(status));
10445 static bool run_chain1(int dummy)
10447 struct cli_state *cli1;
10448 struct tevent_context *evt = samba_tevent_context_init(NULL);
10449 struct tevent_req *reqs[3], *smbreqs[3];
10450 bool done = false;
10451 const char *str = "foobar";
10452 const char *fname = "\\test_chain";
10453 NTSTATUS status;
10455 printf("starting chain1 test\n");
10456 if (!torture_open_connection(&cli1, 0)) {
10457 return False;
10460 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10462 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10464 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10465 O_CREAT|O_RDWR, 0, &smbreqs[0]);
10466 if (reqs[0] == NULL) return false;
10467 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10470 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10471 (const uint8_t *)str, 0, strlen(str)+1,
10472 smbreqs, 1, &smbreqs[1]);
10473 if (reqs[1] == NULL) return false;
10474 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10476 reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10477 if (reqs[2] == NULL) return false;
10478 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10480 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10481 if (!NT_STATUS_IS_OK(status)) {
10482 return false;
10485 while (!done) {
10486 tevent_loop_once(evt);
10489 torture_close_connection(cli1);
10490 return True;
10493 static void chain2_sesssetup_completion(struct tevent_req *req)
10495 NTSTATUS status;
10496 status = cli_session_setup_guest_recv(req);
10497 d_printf("sesssetup returned %s\n", nt_errstr(status));
10500 static void chain2_tcon_completion(struct tevent_req *req)
10502 bool *done = (bool *)tevent_req_callback_data_void(req);
10503 NTSTATUS status;
10504 status = cli_tcon_andx_recv(req);
10505 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10506 *done = true;
10509 static bool run_chain2(int dummy)
10511 struct cli_state *cli1;
10512 struct tevent_context *evt = samba_tevent_context_init(NULL);
10513 struct tevent_req *reqs[2], *smbreqs[2];
10514 bool done = false;
10515 NTSTATUS status;
10516 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10518 printf("starting chain2 test\n");
10519 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10520 port_to_use, SMB_SIGNING_DEFAULT, flags);
10521 if (!NT_STATUS_IS_OK(status)) {
10522 return False;
10525 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10527 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10528 &smbreqs[0]);
10529 if (reqs[0] == NULL) return false;
10530 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10532 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10533 "?????", NULL, 0, &smbreqs[1]);
10534 if (reqs[1] == NULL) return false;
10535 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10537 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10538 if (!NT_STATUS_IS_OK(status)) {
10539 return false;
10542 while (!done) {
10543 tevent_loop_once(evt);
10546 torture_close_connection(cli1);
10547 return True;
10551 struct torture_createdel_state {
10552 struct tevent_context *ev;
10553 struct cli_state *cli;
10556 static void torture_createdel_created(struct tevent_req *subreq);
10557 static void torture_createdel_closed(struct tevent_req *subreq);
10559 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10560 struct tevent_context *ev,
10561 struct cli_state *cli,
10562 const char *name)
10564 struct tevent_req *req, *subreq;
10565 struct torture_createdel_state *state;
10567 req = tevent_req_create(mem_ctx, &state,
10568 struct torture_createdel_state);
10569 if (req == NULL) {
10570 return NULL;
10572 state->ev = ev;
10573 state->cli = cli;
10575 subreq = cli_ntcreate_send(
10576 state, ev, cli, name, 0,
10577 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10578 FILE_ATTRIBUTE_NORMAL,
10579 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10580 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10581 SMB2_IMPERSONATION_IMPERSONATION, 0);
10583 if (tevent_req_nomem(subreq, req)) {
10584 return tevent_req_post(req, ev);
10586 tevent_req_set_callback(subreq, torture_createdel_created, req);
10587 return req;
10590 static void torture_createdel_created(struct tevent_req *subreq)
10592 struct tevent_req *req = tevent_req_callback_data(
10593 subreq, struct tevent_req);
10594 struct torture_createdel_state *state = tevent_req_data(
10595 req, struct torture_createdel_state);
10596 NTSTATUS status;
10597 uint16_t fnum;
10599 status = cli_ntcreate_recv(subreq, &fnum, NULL);
10600 TALLOC_FREE(subreq);
10601 if (tevent_req_nterror(req, status)) {
10602 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10603 nt_errstr(status)));
10604 return;
10607 subreq = cli_close_send(state, state->ev, state->cli, fnum);
10608 if (tevent_req_nomem(subreq, req)) {
10609 return;
10611 tevent_req_set_callback(subreq, torture_createdel_closed, req);
10614 static void torture_createdel_closed(struct tevent_req *subreq)
10616 struct tevent_req *req = tevent_req_callback_data(
10617 subreq, struct tevent_req);
10618 NTSTATUS status;
10620 status = cli_close_recv(subreq);
10621 if (tevent_req_nterror(req, status)) {
10622 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10623 return;
10625 tevent_req_done(req);
10628 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10630 return tevent_req_simple_recv_ntstatus(req);
10633 struct torture_createdels_state {
10634 struct tevent_context *ev;
10635 struct cli_state *cli;
10636 const char *base_name;
10637 int sent;
10638 int received;
10639 int num_files;
10640 struct tevent_req **reqs;
10643 static void torture_createdels_done(struct tevent_req *subreq);
10645 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10646 struct tevent_context *ev,
10647 struct cli_state *cli,
10648 const char *base_name,
10649 int num_parallel,
10650 int num_files)
10652 struct tevent_req *req;
10653 struct torture_createdels_state *state;
10654 int i;
10656 req = tevent_req_create(mem_ctx, &state,
10657 struct torture_createdels_state);
10658 if (req == NULL) {
10659 return NULL;
10661 state->ev = ev;
10662 state->cli = cli;
10663 state->base_name = talloc_strdup(state, base_name);
10664 if (tevent_req_nomem(state->base_name, req)) {
10665 return tevent_req_post(req, ev);
10667 state->num_files = MAX(num_parallel, num_files);
10668 state->sent = 0;
10669 state->received = 0;
10671 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10672 if (tevent_req_nomem(state->reqs, req)) {
10673 return tevent_req_post(req, ev);
10676 for (i=0; i<num_parallel; i++) {
10677 char *name;
10679 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10680 state->sent);
10681 if (tevent_req_nomem(name, req)) {
10682 return tevent_req_post(req, ev);
10684 state->reqs[i] = torture_createdel_send(
10685 state->reqs, state->ev, state->cli, name);
10686 if (tevent_req_nomem(state->reqs[i], req)) {
10687 return tevent_req_post(req, ev);
10689 name = talloc_move(state->reqs[i], &name);
10690 tevent_req_set_callback(state->reqs[i],
10691 torture_createdels_done, req);
10692 state->sent += 1;
10694 return req;
10697 static void torture_createdels_done(struct tevent_req *subreq)
10699 struct tevent_req *req = tevent_req_callback_data(
10700 subreq, struct tevent_req);
10701 struct torture_createdels_state *state = tevent_req_data(
10702 req, struct torture_createdels_state);
10703 size_t i, num_parallel = talloc_array_length(state->reqs);
10704 NTSTATUS status;
10705 char *name;
10707 status = torture_createdel_recv(subreq);
10708 if (!NT_STATUS_IS_OK(status)){
10709 DEBUG(10, ("torture_createdel_recv returned %s\n",
10710 nt_errstr(status)));
10711 TALLOC_FREE(subreq);
10712 tevent_req_nterror(req, status);
10713 return;
10716 for (i=0; i<num_parallel; i++) {
10717 if (subreq == state->reqs[i]) {
10718 break;
10721 if (i == num_parallel) {
10722 DEBUG(10, ("received something we did not send\n"));
10723 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10724 return;
10726 TALLOC_FREE(state->reqs[i]);
10728 if (state->sent >= state->num_files) {
10729 tevent_req_done(req);
10730 return;
10733 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10734 state->sent);
10735 if (tevent_req_nomem(name, req)) {
10736 return;
10738 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10739 state->cli, name);
10740 if (tevent_req_nomem(state->reqs[i], req)) {
10741 return;
10743 name = talloc_move(state->reqs[i], &name);
10744 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10745 state->sent += 1;
10748 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10750 return tevent_req_simple_recv_ntstatus(req);
10753 struct swallow_notify_state {
10754 struct tevent_context *ev;
10755 struct cli_state *cli;
10756 uint16_t fnum;
10757 uint32_t completion_filter;
10758 bool recursive;
10759 bool (*fn)(uint32_t action, const char *name, void *priv);
10760 void *priv;
10763 static void swallow_notify_done(struct tevent_req *subreq);
10765 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10766 struct tevent_context *ev,
10767 struct cli_state *cli,
10768 uint16_t fnum,
10769 uint32_t completion_filter,
10770 bool recursive,
10771 bool (*fn)(uint32_t action,
10772 const char *name,
10773 void *priv),
10774 void *priv)
10776 struct tevent_req *req, *subreq;
10777 struct swallow_notify_state *state;
10779 req = tevent_req_create(mem_ctx, &state,
10780 struct swallow_notify_state);
10781 if (req == NULL) {
10782 return NULL;
10784 state->ev = ev;
10785 state->cli = cli;
10786 state->fnum = fnum;
10787 state->completion_filter = completion_filter;
10788 state->recursive = recursive;
10789 state->fn = fn;
10790 state->priv = priv;
10792 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10793 0xffff, state->completion_filter,
10794 state->recursive);
10795 if (tevent_req_nomem(subreq, req)) {
10796 return tevent_req_post(req, ev);
10798 tevent_req_set_callback(subreq, swallow_notify_done, req);
10799 return req;
10802 static void swallow_notify_done(struct tevent_req *subreq)
10804 struct tevent_req *req = tevent_req_callback_data(
10805 subreq, struct tevent_req);
10806 struct swallow_notify_state *state = tevent_req_data(
10807 req, struct swallow_notify_state);
10808 NTSTATUS status;
10809 uint32_t i, num_changes;
10810 struct notify_change *changes;
10812 status = cli_notify_recv(subreq, state, &num_changes, &changes);
10813 TALLOC_FREE(subreq);
10814 if (!NT_STATUS_IS_OK(status)) {
10815 DEBUG(10, ("cli_notify_recv returned %s\n",
10816 nt_errstr(status)));
10817 tevent_req_nterror(req, status);
10818 return;
10821 for (i=0; i<num_changes; i++) {
10822 state->fn(changes[i].action, changes[i].name, state->priv);
10824 TALLOC_FREE(changes);
10826 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10827 0xffff, state->completion_filter,
10828 state->recursive);
10829 if (tevent_req_nomem(subreq, req)) {
10830 return;
10832 tevent_req_set_callback(subreq, swallow_notify_done, req);
10835 static bool print_notifies(uint32_t action, const char *name, void *priv)
10837 if (DEBUGLEVEL > 5) {
10838 d_printf("%d %s\n", (int)action, name);
10840 return true;
10843 static void notify_bench_done(struct tevent_req *req)
10845 int *num_finished = (int *)tevent_req_callback_data_void(req);
10846 *num_finished += 1;
10849 static bool run_notify_bench(int dummy)
10851 const char *dname = "\\notify-bench";
10852 struct tevent_context *ev;
10853 NTSTATUS status;
10854 uint16_t dnum;
10855 struct tevent_req *req1;
10856 struct tevent_req *req2 = NULL;
10857 int i, num_unc_names;
10858 int num_finished = 0;
10860 printf("starting notify-bench test\n");
10862 if (use_multishare_conn) {
10863 char **unc_list;
10864 unc_list = file_lines_load(multishare_conn_fname,
10865 &num_unc_names, 0, NULL);
10866 if (!unc_list || num_unc_names <= 0) {
10867 d_printf("Failed to load unc names list from '%s'\n",
10868 multishare_conn_fname);
10869 return false;
10871 TALLOC_FREE(unc_list);
10872 } else {
10873 num_unc_names = 1;
10876 ev = samba_tevent_context_init(talloc_tos());
10877 if (ev == NULL) {
10878 d_printf("tevent_context_init failed\n");
10879 return false;
10882 for (i=0; i<num_unc_names; i++) {
10883 struct cli_state *cli;
10884 char *base_fname;
10886 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
10887 dname, i);
10888 if (base_fname == NULL) {
10889 return false;
10892 if (!torture_open_connection(&cli, i)) {
10893 return false;
10896 status = cli_ntcreate(cli, dname, 0,
10897 MAXIMUM_ALLOWED_ACCESS,
10898 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
10899 FILE_SHARE_DELETE,
10900 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
10901 &dnum, NULL);
10903 if (!NT_STATUS_IS_OK(status)) {
10904 d_printf("Could not create %s: %s\n", dname,
10905 nt_errstr(status));
10906 return false;
10909 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
10910 FILE_NOTIFY_CHANGE_FILE_NAME |
10911 FILE_NOTIFY_CHANGE_DIR_NAME |
10912 FILE_NOTIFY_CHANGE_ATTRIBUTES |
10913 FILE_NOTIFY_CHANGE_LAST_WRITE,
10914 false, print_notifies, NULL);
10915 if (req1 == NULL) {
10916 d_printf("Could not create notify request\n");
10917 return false;
10920 req2 = torture_createdels_send(talloc_tos(), ev, cli,
10921 base_fname, 10, torture_numops);
10922 if (req2 == NULL) {
10923 d_printf("Could not create createdels request\n");
10924 return false;
10926 TALLOC_FREE(base_fname);
10928 tevent_req_set_callback(req2, notify_bench_done,
10929 &num_finished);
10932 while (num_finished < num_unc_names) {
10933 int ret;
10934 ret = tevent_loop_once(ev);
10935 if (ret != 0) {
10936 d_printf("tevent_loop_once failed\n");
10937 return false;
10941 if (!tevent_req_poll(req2, ev)) {
10942 d_printf("tevent_req_poll failed\n");
10945 status = torture_createdels_recv(req2);
10946 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
10948 return true;
10951 static bool run_mangle1(int dummy)
10953 struct cli_state *cli;
10954 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
10955 uint16_t fnum;
10956 fstring alt_name;
10957 NTSTATUS status;
10958 time_t change_time, access_time, write_time;
10959 off_t size;
10960 uint32_t attr;
10962 printf("starting mangle1 test\n");
10963 if (!torture_open_connection(&cli, 0)) {
10964 return False;
10967 smbXcli_conn_set_sockopt(cli->conn, sockops);
10969 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10970 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10971 0, 0, &fnum, NULL);
10972 if (!NT_STATUS_IS_OK(status)) {
10973 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10974 return false;
10976 cli_close(cli, fnum);
10978 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
10979 if (!NT_STATUS_IS_OK(status)) {
10980 d_printf("cli_qpathinfo_alt_name failed: %s\n",
10981 nt_errstr(status));
10982 return false;
10984 d_printf("alt_name: %s\n", alt_name);
10986 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
10987 if (!NT_STATUS_IS_OK(status)) {
10988 d_printf("cli_openx(%s) failed: %s\n", alt_name,
10989 nt_errstr(status));
10990 return false;
10992 cli_close(cli, fnum);
10994 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
10995 &write_time, &size, &attr);
10996 if (!NT_STATUS_IS_OK(status)) {
10997 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
10998 nt_errstr(status));
10999 return false;
11002 return true;
11005 static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
11006 const char *mask,
11007 void *state)
11009 if (f->short_name == NULL) {
11010 return NT_STATUS_OK;
11013 if (strlen(f->short_name) == 0) {
11014 return NT_STATUS_OK;
11017 printf("unexpected shortname: %s\n", f->short_name);
11019 return NT_STATUS_OBJECT_NAME_INVALID;
11022 static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11023 const char *mask,
11024 void *state)
11026 char *name = state;
11028 printf("name: %s\n", f->name);
11029 fstrcpy(name, f->name);
11030 return NT_STATUS_OK;
11033 static bool run_mangle_illegal(int dummy)
11035 struct cli_state *cli = NULL;
11036 struct cli_state *cli_posix = NULL;
11037 const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11038 const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11039 char *mangled_path = NULL;
11040 uint16_t fnum;
11041 fstring name;
11042 fstring alt_name;
11043 NTSTATUS status;
11045 printf("starting mangle-illegal test\n");
11047 if (!torture_open_connection(&cli, 0)) {
11048 return False;
11051 smbXcli_conn_set_sockopt(cli->conn, sockops);
11053 if (!torture_open_connection(&cli_posix, 0)) {
11054 return false;
11057 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11059 status = torture_setup_unix_extensions(cli_posix);
11060 if (!NT_STATUS_IS_OK(status)) {
11061 return false;
11064 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11065 status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11066 if (!NT_STATUS_IS_OK(status)) {
11067 printf("mkdir1 failed : %s\n", nt_errstr(status));
11068 return False;
11072 * Create a file with illegal NTFS characters and test that we
11073 * get a usable mangled name
11076 cli_setatr(cli_posix, illegal_fname, 0, 0);
11077 cli_posix_unlink(cli_posix, illegal_fname);
11079 status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11080 0600, &fnum);
11081 if (!NT_STATUS_IS_OK(status)) {
11082 printf("POSIX create of %s failed (%s)\n",
11083 illegal_fname, nt_errstr(status));
11084 return false;
11087 status = cli_close(cli_posix, fnum);
11088 if (!NT_STATUS_IS_OK(status)) {
11089 printf("close failed (%s)\n", nt_errstr(status));
11090 return false;
11093 status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11094 if (!NT_STATUS_IS_OK(status)) {
11095 d_printf("cli_list failed: %s\n", nt_errstr(status));
11096 return false;
11099 mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11100 if (mangled_path == NULL) {
11101 return false;
11104 status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11105 if (!NT_STATUS_IS_OK(status)) {
11106 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11107 TALLOC_FREE(mangled_path);
11108 return false;
11110 TALLOC_FREE(mangled_path);
11111 cli_close(cli, fnum);
11113 cli_setatr(cli_posix, illegal_fname, 0, 0);
11114 cli_posix_unlink(cli_posix, illegal_fname);
11117 * Create a file with a long name and check that we got *no* short name.
11120 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11121 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11122 0, 0, &fnum, NULL);
11123 if (!NT_STATUS_IS_OK(status)) {
11124 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11125 return false;
11127 cli_close(cli, fnum);
11129 status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11130 if (!NT_STATUS_IS_OK(status)) {
11131 d_printf("cli_list failed\n");
11132 return false;
11135 cli_unlink(cli, fname, 0);
11136 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11138 if (!torture_close_connection(cli_posix)) {
11139 return false;
11142 if (!torture_close_connection(cli)) {
11143 return false;
11146 return true;
11149 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11151 size_t *to_pull = (size_t *)priv;
11152 size_t thistime = *to_pull;
11154 thistime = MIN(thistime, n);
11155 if (thistime == 0) {
11156 return 0;
11159 memset(buf, 0, thistime);
11160 *to_pull -= thistime;
11161 return thistime;
11164 static bool run_windows_write(int dummy)
11166 struct cli_state *cli1;
11167 uint16_t fnum;
11168 int i;
11169 bool ret = false;
11170 const char *fname = "\\writetest.txt";
11171 struct timeval start_time;
11172 double seconds;
11173 double kbytes;
11174 NTSTATUS status;
11176 printf("starting windows_write test\n");
11177 if (!torture_open_connection(&cli1, 0)) {
11178 return False;
11181 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11182 if (!NT_STATUS_IS_OK(status)) {
11183 printf("open failed (%s)\n", nt_errstr(status));
11184 return False;
11187 smbXcli_conn_set_sockopt(cli1->conn, sockops);
11189 start_time = timeval_current();
11191 for (i=0; i<torture_numops; i++) {
11192 uint8_t c = 0;
11193 off_t start = i * torture_blocksize;
11194 size_t to_pull = torture_blocksize - 1;
11196 status = cli_writeall(cli1, fnum, 0, &c,
11197 start + torture_blocksize - 1, 1, NULL);
11198 if (!NT_STATUS_IS_OK(status)) {
11199 printf("cli_write failed: %s\n", nt_errstr(status));
11200 goto fail;
11203 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11204 null_source, &to_pull);
11205 if (!NT_STATUS_IS_OK(status)) {
11206 printf("cli_push returned: %s\n", nt_errstr(status));
11207 goto fail;
11211 seconds = timeval_elapsed(&start_time);
11212 kbytes = (double)torture_blocksize * torture_numops;
11213 kbytes /= 1024;
11215 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11216 (double)seconds, (int)(kbytes/seconds));
11218 ret = true;
11219 fail:
11220 cli_close(cli1, fnum);
11221 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11222 torture_close_connection(cli1);
11223 return ret;
11226 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11228 size_t max_pdu = 0x1FFFF;
11230 if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11231 max_pdu = 0xFFFFFF;
11234 if (smb1cli_conn_signing_is_active(cli->conn)) {
11235 max_pdu = 0x1FFFF;
11238 if (smb1cli_conn_encryption_on(cli->conn)) {
11239 max_pdu = CLI_BUFFER_SIZE;
11242 if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11243 len_requested &= 0xFFFF;
11246 return MIN(len_requested,
11247 max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11250 static bool check_read_call(struct cli_state *cli,
11251 uint16_t fnum,
11252 uint8_t *buf,
11253 size_t len_requested)
11255 NTSTATUS status;
11256 struct tevent_req *subreq = NULL;
11257 ssize_t len_read = 0;
11258 size_t len_expected = 0;
11259 struct tevent_context *ev = NULL;
11261 ev = samba_tevent_context_init(talloc_tos());
11262 if (ev == NULL) {
11263 return false;
11266 subreq = cli_read_andx_send(talloc_tos(),
11268 cli,
11269 fnum,
11271 len_requested);
11273 if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11274 return false;
11277 status = cli_read_andx_recv(subreq, &len_read, &buf);
11278 if (!NT_STATUS_IS_OK(status)) {
11279 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11280 return false;
11283 TALLOC_FREE(subreq);
11284 TALLOC_FREE(ev);
11286 len_expected = calc_expected_return(cli, len_requested);
11288 if (len_expected > 0x10000 && len_read == 0x10000) {
11289 /* Windows servers only return a max of 0x10000,
11290 doesn't matter if you set CAP_LARGE_READX in
11291 the client sessionsetupX call or not. */
11292 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11293 (unsigned int)len_requested);
11294 } else if (len_read != len_expected) {
11295 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11296 (unsigned int)len_requested,
11297 (unsigned int)len_read,
11298 (unsigned int)len_expected);
11299 return false;
11300 } else {
11301 d_printf("Correct read reply.\n");
11304 return true;
11307 /* Test large readX variants. */
11308 static bool large_readx_tests(struct cli_state *cli,
11309 uint16_t fnum,
11310 uint8_t *buf)
11312 /* A read of 0xFFFF0001 should *always* return 1 byte. */
11313 if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11314 return false;
11316 /* A read of 0x10000 should return 0x10000 bytes. */
11317 if (check_read_call(cli, fnum, buf, 0x10000) == false) {
11318 return false;
11320 /* A read of 0x10000 should return 0x10001 bytes. */
11321 if (check_read_call(cli, fnum, buf, 0x10001) == false) {
11322 return false;
11324 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11325 the requested number of bytes. */
11326 if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11327 return false;
11329 /* A read of 1MB should return 1MB bytes (on Samba). */
11330 if (check_read_call(cli, fnum, buf, 0x100000) == false) {
11331 return false;
11334 if (check_read_call(cli, fnum, buf, 0x20001) == false) {
11335 return false;
11337 if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11338 return false;
11340 if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11341 return false;
11343 return true;
11346 static bool run_large_readx(int dummy)
11348 uint8_t *buf = NULL;
11349 struct cli_state *cli1 = NULL;
11350 struct cli_state *cli2 = NULL;
11351 bool correct = false;
11352 const char *fname = "\\large_readx.dat";
11353 NTSTATUS status;
11354 uint16_t fnum1 = UINT16_MAX;
11355 uint32_t normal_caps = 0;
11356 size_t file_size = 20*1024*1024;
11357 TALLOC_CTX *frame = talloc_stackframe();
11358 size_t i;
11359 struct {
11360 const char *name;
11361 enum smb_signing_setting signing_setting;
11362 enum protocol_types protocol;
11363 } runs[] = {
11365 .name = "NT1",
11366 .signing_setting = SMB_SIGNING_IF_REQUIRED,
11367 .protocol = PROTOCOL_NT1,
11369 .name = "NT1 - SIGNING_REQUIRED",
11370 .signing_setting = SMB_SIGNING_REQUIRED,
11371 .protocol = PROTOCOL_NT1,
11375 printf("starting large_readx test\n");
11377 if (!torture_open_connection(&cli1, 0)) {
11378 goto out;
11381 normal_caps = smb1cli_conn_capabilities(cli1->conn);
11383 if (!(normal_caps & CAP_LARGE_READX)) {
11384 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11385 (unsigned int)normal_caps);
11386 goto out;
11389 /* Create a file of size 4MB. */
11390 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11391 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11392 0, 0, &fnum1, NULL);
11394 if (!NT_STATUS_IS_OK(status)) {
11395 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11396 goto out;
11399 /* Write file_size bytes. */
11400 buf = talloc_zero_array(frame, uint8_t, file_size);
11401 if (buf == NULL) {
11402 goto out;
11405 status = cli_writeall(cli1,
11406 fnum1,
11408 buf,
11410 file_size,
11411 NULL);
11412 if (!NT_STATUS_IS_OK(status)) {
11413 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11414 goto out;
11417 status = cli_close(cli1, fnum1);
11418 if (!NT_STATUS_IS_OK(status)) {
11419 d_printf("cli_close failed: %s\n", nt_errstr(status));
11420 goto out;
11423 fnum1 = UINT16_MAX;
11425 for (i=0; i < ARRAY_SIZE(runs); i++) {
11426 enum smb_signing_setting saved_signing_setting = signing_state;
11427 uint16_t fnum2 = -1;
11429 if (do_encrypt &&
11430 (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11432 d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11433 continue;
11436 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11438 signing_state = runs[i].signing_setting;
11439 cli2 = open_nbt_connection();
11440 signing_state = saved_signing_setting;
11441 if (cli2 == NULL) {
11442 goto out;
11445 status = smbXcli_negprot(cli2->conn,
11446 cli2->timeout,
11447 runs[i].protocol,
11448 runs[i].protocol);
11449 if (!NT_STATUS_IS_OK(status)) {
11450 goto out;
11453 status = cli_session_setup_creds(cli2, torture_creds);
11454 if (!NT_STATUS_IS_OK(status)) {
11455 goto out;
11458 status = cli_tree_connect(cli2,
11459 share,
11460 "?????",
11461 password);
11462 if (!NT_STATUS_IS_OK(status)) {
11463 goto out;
11466 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11468 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11470 if (!(normal_caps & CAP_LARGE_READX)) {
11471 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11472 (unsigned int)normal_caps);
11473 goto out;
11476 if (do_encrypt) {
11477 if (force_cli_encryption(cli2, share) == false) {
11478 goto out;
11480 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11481 uint16_t major, minor;
11482 uint32_t caplow, caphigh;
11484 status = cli_unix_extensions_version(cli2,
11485 &major, &minor,
11486 &caplow, &caphigh);
11487 if (!NT_STATUS_IS_OK(status)) {
11488 goto out;
11492 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11493 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11494 0, 0, &fnum2, NULL);
11495 if (!NT_STATUS_IS_OK(status)) {
11496 d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11497 goto out;
11500 /* All reads must return less than file_size bytes. */
11501 if (!large_readx_tests(cli2, fnum2, buf)) {
11502 goto out;
11505 status = cli_close(cli2, fnum2);
11506 if (!NT_STATUS_IS_OK(status)) {
11507 d_printf("cli_close failed: %s\n", nt_errstr(status));
11508 goto out;
11510 fnum2 = -1;
11512 if (!torture_close_connection(cli2)) {
11513 goto out;
11515 cli2 = NULL;
11518 correct = true;
11519 printf("Success on large_readx test\n");
11521 out:
11523 if (cli2) {
11524 if (!torture_close_connection(cli2)) {
11525 correct = false;
11529 if (cli1) {
11530 if (fnum1 != UINT16_MAX) {
11531 status = cli_close(cli1, fnum1);
11532 if (!NT_STATUS_IS_OK(status)) {
11533 d_printf("cli_close failed: %s\n", nt_errstr(status));
11535 fnum1 = UINT16_MAX;
11538 status = cli_unlink(cli1, fname,
11539 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11540 if (!NT_STATUS_IS_OK(status)) {
11541 printf("unlink failed (%s)\n", nt_errstr(status));
11544 if (!torture_close_connection(cli1)) {
11545 correct = false;
11549 TALLOC_FREE(frame);
11551 printf("finished large_readx test\n");
11552 return correct;
11555 static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11556 const char *mask,
11557 void *private_data)
11559 uint32_t *p_attr = (uint32_t *)private_data;
11561 if (strequal(finfo->name, test_filename)) {
11562 *p_attr = finfo->attr;
11565 return NT_STATUS_OK;
11568 static bool run_msdfs_attribute(int dummy)
11570 static struct cli_state *cli;
11571 bool correct = false;
11572 uint32_t attr = 0;
11573 NTSTATUS status;
11575 printf("Starting MSDFS-ATTRIBUTE test\n");
11577 if (test_filename == NULL || test_filename[0] == '\0') {
11578 printf("MSDFS-ATTRIBUTE test "
11579 "needs -f filename-of-msdfs-link\n");
11580 return false;
11584 * NB. We use torture_open_connection_flags() not
11585 * torture_open_connection() as the latter forces
11586 * SMB1.
11588 if (!torture_open_connection_flags(&cli, 0, 0)) {
11589 return false;
11592 smbXcli_conn_set_sockopt(cli->conn, sockops);
11594 status = cli_list(cli,
11595 "*",
11596 FILE_ATTRIBUTE_DIRECTORY,
11597 msdfs_attribute_list_fn,
11598 &attr);
11600 if (!NT_STATUS_IS_OK(status)) {
11601 printf("cli_list failed with %s\n",
11602 nt_errstr(status));
11603 goto out;
11605 if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11606 printf("file %s should have "
11607 "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11608 test_filename,
11609 (unsigned int)attr);
11610 goto out;
11613 if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11614 printf("file %s should have "
11615 "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11616 test_filename,
11617 (unsigned int)attr);
11618 goto out;
11621 correct = true;
11623 out:
11625 torture_close_connection(cli);
11626 return correct;
11629 static bool run_cli_echo(int dummy)
11631 struct cli_state *cli;
11632 NTSTATUS status;
11634 printf("starting cli_echo test\n");
11635 if (!torture_open_connection(&cli, 0)) {
11636 return false;
11638 smbXcli_conn_set_sockopt(cli->conn, sockops);
11640 status = cli_echo(cli, 5, data_blob_const("hello", 5));
11642 d_printf("cli_echo returned %s\n", nt_errstr(status));
11644 torture_close_connection(cli);
11645 return NT_STATUS_IS_OK(status);
11648 static int splice_status(off_t written, void *priv)
11650 return true;
11653 static bool run_cli_splice(int dummy)
11655 uint8_t *buf = NULL;
11656 struct cli_state *cli1 = NULL;
11657 bool correct = false;
11658 const char *fname_src = "\\splice_src.dat";
11659 const char *fname_dst = "\\splice_dst.dat";
11660 NTSTATUS status;
11661 uint16_t fnum1 = UINT16_MAX;
11662 uint16_t fnum2 = UINT16_MAX;
11663 size_t file_size = 2*1024*1024;
11664 size_t splice_size = 1*1024*1024 + 713;
11665 uint8_t digest1[16], digest2[16];
11666 off_t written = 0;
11667 size_t nread = 0;
11668 TALLOC_CTX *frame = talloc_stackframe();
11670 printf("starting cli_splice test\n");
11672 if (!torture_open_connection(&cli1, 0)) {
11673 goto out;
11676 cli_unlink(cli1, fname_src,
11677 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11678 cli_unlink(cli1, fname_dst,
11679 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11681 /* Create a file */
11682 status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11683 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11684 0, 0, &fnum1, NULL);
11686 if (!NT_STATUS_IS_OK(status)) {
11687 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11688 goto out;
11691 /* Write file_size bytes - must be bigger than splice_size. */
11692 buf = talloc_zero_array(frame, uint8_t, file_size);
11693 if (buf == NULL) {
11694 d_printf("talloc_fail\n");
11695 goto out;
11698 /* Fill it with random numbers. */
11699 generate_random_buffer(buf, file_size);
11701 /* MD5 the first 1MB + 713 bytes. */
11702 gnutls_hash_fast(GNUTLS_DIG_MD5,
11703 buf,
11704 splice_size,
11705 digest1);
11707 status = cli_writeall(cli1,
11708 fnum1,
11710 buf,
11712 file_size,
11713 NULL);
11714 if (!NT_STATUS_IS_OK(status)) {
11715 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11716 goto out;
11719 status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11720 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11721 0, 0, &fnum2, NULL);
11723 if (!NT_STATUS_IS_OK(status)) {
11724 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11725 goto out;
11728 /* Now splice 1MB + 713 bytes. */
11729 status = cli_splice(cli1,
11730 cli1,
11731 fnum1,
11732 fnum2,
11733 splice_size,
11736 &written,
11737 splice_status,
11738 NULL);
11740 if (!NT_STATUS_IS_OK(status)) {
11741 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11742 goto out;
11745 /* Clear the old buffer. */
11746 memset(buf, '\0', file_size);
11748 /* Read the new file. */
11749 status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11750 if (!NT_STATUS_IS_OK(status)) {
11751 d_printf("cli_read failed: %s\n", nt_errstr(status));
11752 goto out;
11754 if (nread != splice_size) {
11755 d_printf("bad read of 0x%x, should be 0x%x\n",
11756 (unsigned int)nread,
11757 (unsigned int)splice_size);
11758 goto out;
11761 /* MD5 the first 1MB + 713 bytes. */
11762 gnutls_hash_fast(GNUTLS_DIG_MD5,
11763 buf,
11764 splice_size,
11765 digest2);
11767 /* Must be the same. */
11768 if (memcmp(digest1, digest2, 16) != 0) {
11769 d_printf("bad MD5 compare\n");
11770 goto out;
11773 correct = true;
11774 printf("Success on cli_splice test\n");
11776 out:
11778 if (cli1) {
11779 if (fnum1 != UINT16_MAX) {
11780 cli_close(cli1, fnum1);
11782 if (fnum2 != UINT16_MAX) {
11783 cli_close(cli1, fnum2);
11786 cli_unlink(cli1, fname_src,
11787 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11788 cli_unlink(cli1, fname_dst,
11789 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11791 if (!torture_close_connection(cli1)) {
11792 correct = false;
11796 TALLOC_FREE(frame);
11797 return correct;
11800 static bool run_uid_regression_test(int dummy)
11802 static struct cli_state *cli;
11803 int16_t old_vuid;
11804 int32_t old_cnum;
11805 bool correct = True;
11806 struct smbXcli_tcon *tcon_copy = NULL;
11807 NTSTATUS status;
11809 printf("starting uid regression test\n");
11811 if (!torture_open_connection(&cli, 0)) {
11812 return False;
11815 smbXcli_conn_set_sockopt(cli->conn, sockops);
11817 /* Ok - now save then logoff our current user. */
11818 old_vuid = cli_state_get_uid(cli);
11820 status = cli_ulogoff(cli);
11821 if (!NT_STATUS_IS_OK(status)) {
11822 d_printf("(%s) cli_ulogoff failed: %s\n",
11823 __location__, nt_errstr(status));
11824 correct = false;
11825 goto out;
11828 cli_state_set_uid(cli, old_vuid);
11830 /* Try an operation. */
11831 status = cli_mkdir(cli, "\\uid_reg_test");
11832 if (NT_STATUS_IS_OK(status)) {
11833 d_printf("(%s) cli_mkdir succeeded\n",
11834 __location__);
11835 correct = false;
11836 goto out;
11837 } else {
11838 /* Should be bad uid. */
11839 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11840 NT_STATUS_USER_SESSION_DELETED)) {
11841 correct = false;
11842 goto out;
11846 old_cnum = cli_state_get_tid(cli);
11848 * This is an SMB1-only test.
11849 * Copy the tcon, not "save/restore".
11851 * In SMB1 the cli_tdis() below frees
11852 * cli->smb1.tcon so we need a copy
11853 * of the struct to put back for the
11854 * second tdis call with invalid vuid.
11856 * This is a test-only hack. Real client code
11857 * uses cli_state_save_tcon_share()/cli_state_restore_tcon_share().
11859 tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
11860 if (tcon_copy == NULL) {
11861 correct = false;
11862 goto out;
11865 /* Now try a SMBtdis with the invalid vuid set to zero. */
11866 cli_state_set_uid(cli, 0);
11868 /* This should succeed. */
11869 status = cli_tdis(cli);
11871 if (NT_STATUS_IS_OK(status)) {
11872 d_printf("First tdis with invalid vuid should succeed.\n");
11873 } else {
11874 d_printf("First tdis failed (%s)\n", nt_errstr(status));
11875 correct = false;
11876 cli->smb1.tcon = tcon_copy;
11877 goto out;
11880 cli->smb1.tcon = tcon_copy;
11881 cli_state_set_uid(cli, old_vuid);
11882 cli_state_set_tid(cli, old_cnum);
11884 /* This should fail. */
11885 status = cli_tdis(cli);
11886 if (NT_STATUS_IS_OK(status)) {
11887 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
11888 correct = false;
11889 goto out;
11890 } else {
11891 /* Should be bad tid. */
11892 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
11893 NT_STATUS_NETWORK_NAME_DELETED)) {
11894 correct = false;
11895 goto out;
11899 cli_rmdir(cli, "\\uid_reg_test");
11901 out:
11903 cli_shutdown(cli);
11904 return correct;
11908 static const char *illegal_chars = "*\\/?<>|\":";
11909 static char force_shortname_chars[] = " +,.[];=\177";
11911 static NTSTATUS shortname_del_fn(struct file_info *finfo,
11912 const char *mask, void *state)
11914 struct cli_state *pcli = (struct cli_state *)state;
11915 fstring fname;
11916 NTSTATUS status = NT_STATUS_OK;
11918 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
11920 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
11921 return NT_STATUS_OK;
11923 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
11924 status = cli_rmdir(pcli, fname);
11925 if (!NT_STATUS_IS_OK(status)) {
11926 printf("del_fn: failed to rmdir %s\n,", fname );
11928 } else {
11929 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11930 if (!NT_STATUS_IS_OK(status)) {
11931 printf("del_fn: failed to unlink %s\n,", fname );
11934 return status;
11937 struct sn_state {
11938 int matched;
11939 int i;
11940 bool val;
11943 static NTSTATUS shortname_list_fn(struct file_info *finfo,
11944 const char *name, void *state)
11946 struct sn_state *s = (struct sn_state *)state;
11947 int i = s->i;
11949 #if 0
11950 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
11951 i, finfo->name, finfo->short_name);
11952 #endif
11954 if (strchr(force_shortname_chars, i)) {
11955 if (!finfo->short_name) {
11956 /* Shortname not created when it should be. */
11957 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
11958 __location__, finfo->name, i);
11959 s->val = true;
11961 } else if (finfo->short_name){
11962 /* Shortname created when it should not be. */
11963 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
11964 __location__, finfo->short_name, finfo->name);
11965 s->val = true;
11967 s->matched += 1;
11968 return NT_STATUS_OK;
11971 static bool run_shortname_test(int dummy)
11973 static struct cli_state *cli;
11974 bool correct = True;
11975 int i;
11976 struct sn_state s;
11977 char fname[40];
11978 NTSTATUS status;
11980 printf("starting shortname test\n");
11982 if (!torture_open_connection(&cli, 0)) {
11983 return False;
11986 smbXcli_conn_set_sockopt(cli->conn, sockops);
11988 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11989 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11990 cli_rmdir(cli, "\\shortname");
11992 status = cli_mkdir(cli, "\\shortname");
11993 if (!NT_STATUS_IS_OK(status)) {
11994 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
11995 __location__, nt_errstr(status));
11996 correct = false;
11997 goto out;
12000 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
12001 correct = false;
12002 goto out;
12004 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
12005 correct = false;
12006 goto out;
12009 s.val = false;
12011 for (i = 32; i < 128; i++) {
12012 uint16_t fnum = (uint16_t)-1;
12014 s.i = i;
12016 if (strchr(illegal_chars, i)) {
12017 continue;
12019 fname[15] = i;
12021 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12022 FILE_SHARE_READ|FILE_SHARE_WRITE,
12023 FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12024 if (!NT_STATUS_IS_OK(status)) {
12025 d_printf("(%s) cli_nt_create of %s failed: %s\n",
12026 __location__, fname, nt_errstr(status));
12027 correct = false;
12028 goto out;
12030 cli_close(cli, fnum);
12032 s.matched = 0;
12033 status = cli_list(cli, "\\shortname\\test*.*", 0,
12034 shortname_list_fn, &s);
12035 if (s.matched != 1) {
12036 d_printf("(%s) failed to list %s: %s\n",
12037 __location__, fname, nt_errstr(status));
12038 correct = false;
12039 goto out;
12042 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12043 if (!NT_STATUS_IS_OK(status)) {
12044 d_printf("(%s) failed to delete %s: %s\n",
12045 __location__, fname, nt_errstr(status));
12046 correct = false;
12047 goto out;
12050 if (s.val) {
12051 correct = false;
12052 goto out;
12056 out:
12058 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12059 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12060 cli_rmdir(cli, "\\shortname");
12061 torture_close_connection(cli);
12062 return correct;
12065 TLDAPRC callback_code;
12067 static void pagedsearch_cb(struct tevent_req *req)
12069 TLDAPRC rc;
12070 struct tldap_message *msg;
12071 char *dn;
12073 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12074 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12075 d_printf("tldap_search_paged_recv failed: %s\n",
12076 tldap_rc2string(rc));
12077 callback_code = rc;
12078 return;
12080 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12081 TALLOC_FREE(msg);
12082 return;
12084 if (!tldap_entry_dn(msg, &dn)) {
12085 d_printf("tldap_entry_dn failed\n");
12086 return;
12088 d_printf("%s\n", dn);
12089 TALLOC_FREE(msg);
12092 enum tldap_extended_val {
12093 EXTENDED_ZERO = 0,
12094 EXTENDED_ONE = 1,
12095 EXTENDED_NONE = 2,
12099 * Construct an extended dn control with either no value, 0 or 1
12101 * No value and 0 are equivalent (non-hyphenated GUID)
12102 * 1 has the hyphenated GUID
12104 static struct tldap_control *
12105 tldap_build_extended_control(enum tldap_extended_val val)
12107 struct tldap_control empty_control;
12108 struct asn1_data *data;
12110 ZERO_STRUCT(empty_control);
12112 if (val != EXTENDED_NONE) {
12113 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12115 if (!data) {
12116 return NULL;
12119 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12120 return NULL;
12123 if (!asn1_write_Integer(data, (int)val)) {
12124 return NULL;
12127 if (!asn1_pop_tag(data)) {
12128 return NULL;
12131 if (!asn1_blob(data, &empty_control.value)) {
12132 return NULL;
12136 empty_control.oid = "1.2.840.113556.1.4.529";
12137 empty_control.critical = true;
12139 return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12143 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12144 enum tldap_extended_val control_val)
12146 struct tldap_control *control = tldap_build_extended_control(control_val);
12147 char *dn = NULL;
12148 struct tldap_message **msg;
12149 TLDAPRC rc;
12151 rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12152 "(objectClass=*)", NULL, 0, 0,
12153 control, 1, NULL,
12154 0, 0, 0, 0, talloc_tos(), &msg);
12155 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12156 d_printf("tldap_search for domain DN failed: %s\n",
12157 tldap_errstr(talloc_tos(), ld, rc));
12158 return false;
12161 if (!tldap_entry_dn(msg[0], &dn)) {
12162 d_printf("tldap_search domain DN fetch failed: %s\n",
12163 tldap_errstr(talloc_tos(), ld, rc));
12164 return false;
12167 d_printf("%s\n", dn);
12169 uint32_t time_low;
12170 uint32_t time_mid, time_hi_and_version;
12171 uint32_t clock_seq[2];
12172 uint32_t node[6];
12173 char next;
12175 switch (control_val) {
12176 case EXTENDED_NONE:
12177 case EXTENDED_ZERO:
12179 * When reading GUIDs with hyphens, scanf will treat
12180 * hyphen as a hex character (and counts as part of the
12181 * width). This creates leftover GUID string which we
12182 * check will for with 'next' and closing '>'.
12184 if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12185 &time_low, &time_mid,
12186 &time_hi_and_version, &clock_seq[0],
12187 &clock_seq[1], &node[0], &node[1],
12188 &node[2], &node[3], &node[4],
12189 &node[5], &next)) {
12190 /* This GUID is good */
12191 } else {
12192 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12193 return false;
12196 break;
12197 case EXTENDED_ONE:
12198 if (12 == sscanf(dn,
12199 "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12200 &time_low, &time_mid,
12201 &time_hi_and_version, &clock_seq[0],
12202 &clock_seq[1], &node[0], &node[1],
12203 &node[2], &node[3], &node[4],
12204 &node[5], &next)) {
12205 /* This GUID is good */
12206 } else {
12207 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12208 return false;
12211 break;
12212 default:
12213 return false;
12217 return true;
12220 static bool run_tldap(int dummy)
12222 struct tldap_context *ld;
12223 int fd;
12224 TLDAPRC rc;
12225 NTSTATUS status;
12226 struct sockaddr_storage addr;
12227 struct tevent_context *ev;
12228 struct tevent_req *req;
12229 char *basedn;
12230 const char *filter;
12232 if (!resolve_name(host, &addr, 0, false)) {
12233 d_printf("could not find host %s\n", host);
12234 return false;
12236 status = open_socket_out(&addr, 389, 9999, &fd);
12237 if (!NT_STATUS_IS_OK(status)) {
12238 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12239 return false;
12242 ld = tldap_context_create(talloc_tos(), fd);
12243 if (ld == NULL) {
12244 close(fd);
12245 d_printf("tldap_context_create failed\n");
12246 return false;
12249 rc = tldap_fetch_rootdse(ld);
12250 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12251 d_printf("tldap_fetch_rootdse failed: %s\n",
12252 tldap_errstr(talloc_tos(), ld, rc));
12253 return false;
12256 basedn = tldap_talloc_single_attribute(
12257 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12258 if (basedn == NULL) {
12259 d_printf("no defaultNamingContext\n");
12260 return false;
12262 d_printf("defaultNamingContext: %s\n", basedn);
12264 ev = samba_tevent_context_init(talloc_tos());
12265 if (ev == NULL) {
12266 d_printf("tevent_context_init failed\n");
12267 return false;
12270 rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12271 loadparm_init_s3(talloc_tos(),
12272 loadparm_s3_helpers()),
12273 GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12275 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12276 d_printf("tldap_gensec_bind failed\n");
12277 return false;
12280 callback_code = TLDAP_SUCCESS;
12282 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12283 TLDAP_SCOPE_SUB, "(objectclass=*)",
12284 NULL, 0, 0,
12285 NULL, 0, NULL, 0, 0, 0, 0, 5);
12286 if (req == NULL) {
12287 d_printf("tldap_search_paged_send failed\n");
12288 return false;
12290 tevent_req_set_callback(req, pagedsearch_cb, NULL);
12292 tevent_req_poll(req, ev);
12294 TALLOC_FREE(req);
12296 rc = callback_code;
12298 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12299 d_printf("tldap_search with paging failed: %s\n",
12300 tldap_errstr(talloc_tos(), ld, rc));
12301 return false;
12304 /* test search filters against rootDSE */
12305 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12306 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12308 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12309 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12310 talloc_tos(), NULL);
12311 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12312 d_printf("tldap_search with complex filter failed: %s\n",
12313 tldap_errstr(talloc_tos(), ld, rc));
12314 return false;
12318 * Tests to check for regression of:
12320 * https://bugzilla.samba.org/show_bug.cgi?id=14029
12322 * TLDAP used here to pick apart the original string DN (with GUID)
12324 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12325 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12326 tldap_errstr(talloc_tos(), ld, rc));
12327 return false;
12329 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12330 d_printf("tldap_search with extended dn (0) failed: %s\n",
12331 tldap_errstr(talloc_tos(), ld, rc));
12332 return false;
12334 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12335 d_printf("tldap_search with extended dn (1) failed: %s\n",
12336 tldap_errstr(talloc_tos(), ld, rc));
12337 return false;
12340 TALLOC_FREE(ld);
12341 return true;
12344 /* Torture test to ensure no regression of :
12345 https://bugzilla.samba.org/show_bug.cgi?id=7084
12348 static bool run_dir_createtime(int dummy)
12350 struct cli_state *cli;
12351 const char *dname = "\\testdir_createtime";
12352 const char *fname = "\\testdir_createtime\\testfile";
12353 NTSTATUS status;
12354 struct timespec create_time;
12355 struct timespec create_time1;
12356 uint16_t fnum;
12357 bool ret = false;
12358 uint64_t ino;
12360 if (!torture_open_connection(&cli, 0)) {
12361 return false;
12364 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12365 /* Ensure ino is zero, SMB2 gets a real one. */
12366 ino = 0;
12367 } else {
12368 /* Ensure ino is -1, SMB1 never gets a real one. */
12369 ino = (uint64_t)-1;
12372 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12373 cli_rmdir(cli, dname);
12375 status = cli_mkdir(cli, dname);
12376 if (!NT_STATUS_IS_OK(status)) {
12377 printf("mkdir failed: %s\n", nt_errstr(status));
12378 goto out;
12381 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
12382 NULL, NULL, &ino);
12383 if (!NT_STATUS_IS_OK(status)) {
12384 printf("cli_qpathinfo2 returned %s\n",
12385 nt_errstr(status));
12386 goto out;
12389 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12390 /* SMB2 should always return an inode. */
12391 if (ino == 0) {
12392 printf("SMB2 bad inode (0)\n");
12393 goto out;
12395 } else {
12396 /* SMB1 must always return zero here. */
12397 if (ino != 0) {
12398 printf("SMB1 bad inode (!0)\n");
12399 goto out;
12403 /* Sleep 3 seconds, then create a file. */
12404 sleep(3);
12406 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12407 DENY_NONE, &fnum);
12408 if (!NT_STATUS_IS_OK(status)) {
12409 printf("cli_openx failed: %s\n", nt_errstr(status));
12410 goto out;
12413 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
12414 NULL, NULL, NULL);
12415 if (!NT_STATUS_IS_OK(status)) {
12416 printf("cli_qpathinfo2 (2) returned %s\n",
12417 nt_errstr(status));
12418 goto out;
12421 if (timespec_compare(&create_time1, &create_time)) {
12422 printf("run_dir_createtime: create time was updated (error)\n");
12423 } else {
12424 printf("run_dir_createtime: create time was not updated (correct)\n");
12425 ret = true;
12428 out:
12430 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12431 cli_rmdir(cli, dname);
12432 if (!torture_close_connection(cli)) {
12433 ret = false;
12435 return ret;
12439 static bool run_streamerror(int dummy)
12441 struct cli_state *cli;
12442 const char *dname = "\\testdir_streamerror";
12443 const char *streamname =
12444 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12445 NTSTATUS status;
12446 time_t change_time, access_time, write_time;
12447 off_t size;
12448 uint16_t fnum;
12449 uint32_t attr;
12450 bool ret = true;
12452 if (!torture_open_connection(&cli, 0)) {
12453 return false;
12456 torture_deltree(cli, dname);
12458 status = cli_mkdir(cli, dname);
12459 if (!NT_STATUS_IS_OK(status)) {
12460 printf("mkdir failed: %s\n", nt_errstr(status));
12461 return false;
12464 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12465 &write_time, &size, &attr);
12466 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12467 printf("pathinfo returned %s, expected "
12468 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12469 nt_errstr(status));
12470 ret = false;
12473 status = cli_ntcreate(cli, streamname, 0x16,
12474 FILE_READ_DATA|FILE_READ_EA|
12475 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12476 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12477 FILE_OPEN, 0, 0, &fnum, NULL);
12479 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12480 printf("ntcreate returned %s, expected "
12481 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12482 nt_errstr(status));
12483 ret = false;
12487 cli_rmdir(cli, dname);
12488 return ret;
12491 struct pidtest_state {
12492 bool success;
12493 uint16_t vwv[1];
12494 DATA_BLOB data;
12497 static void pid_echo_done(struct tevent_req *subreq);
12499 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12500 struct tevent_context *ev,
12501 struct cli_state *cli)
12503 struct tevent_req *req, *subreq;
12504 struct pidtest_state *state;
12506 req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12507 if (req == NULL) {
12508 return NULL;
12511 SSVAL(state->vwv, 0, 1);
12512 state->data = data_blob_const("hello", 5);
12514 subreq = smb1cli_req_send(state,
12516 cli->conn,
12517 SMBecho,
12518 0, 0, /* *_flags */
12519 0, 0, /* *_flags2 */
12520 cli->timeout,
12521 0xDEADBEEF, /* pid */
12522 NULL, /* tcon */
12523 NULL, /* session */
12524 ARRAY_SIZE(state->vwv), state->vwv,
12525 state->data.length, state->data.data);
12527 if (tevent_req_nomem(subreq, req)) {
12528 return tevent_req_post(req, ev);
12530 tevent_req_set_callback(subreq, pid_echo_done, req);
12531 return req;
12534 static void pid_echo_done(struct tevent_req *subreq)
12536 struct tevent_req *req = tevent_req_callback_data(
12537 subreq, struct tevent_req);
12538 struct pidtest_state *state = tevent_req_data(
12539 req, struct pidtest_state);
12540 NTSTATUS status;
12541 uint32_t num_bytes;
12542 uint8_t *bytes = NULL;
12543 struct iovec *recv_iov = NULL;
12544 uint8_t *phdr = NULL;
12545 uint16_t pidlow = 0;
12546 uint16_t pidhigh = 0;
12547 struct smb1cli_req_expected_response expected[] = {
12549 .status = NT_STATUS_OK,
12550 .wct = 1,
12554 status = smb1cli_req_recv(subreq, state,
12555 &recv_iov,
12556 &phdr,
12557 NULL, /* pwct */
12558 NULL, /* pvwv */
12559 NULL, /* pvwv_offset */
12560 &num_bytes,
12561 &bytes,
12562 NULL, /* pbytes_offset */
12563 NULL, /* pinbuf */
12564 expected, ARRAY_SIZE(expected));
12566 TALLOC_FREE(subreq);
12568 if (!NT_STATUS_IS_OK(status)) {
12569 tevent_req_nterror(req, status);
12570 return;
12573 if (num_bytes != state->data.length) {
12574 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12575 return;
12578 if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12579 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12580 return;
12583 /* Check pid low/high == DEADBEEF */
12584 pidlow = SVAL(phdr, HDR_PID);
12585 if (pidlow != 0xBEEF){
12586 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12587 (unsigned int)pidlow);
12588 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12589 return;
12591 pidhigh = SVAL(phdr, HDR_PIDHIGH);
12592 if (pidhigh != 0xDEAD){
12593 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12594 (unsigned int)pidhigh);
12595 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12596 return;
12599 tevent_req_done(req);
12602 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12604 return tevent_req_simple_recv_ntstatus(req);
12607 static bool run_pidhigh(int dummy)
12609 bool success = false;
12610 struct cli_state *cli = NULL;
12611 NTSTATUS status;
12612 struct tevent_context *ev = NULL;
12613 struct tevent_req *req = NULL;
12614 TALLOC_CTX *frame = talloc_stackframe();
12616 printf("starting pid high test\n");
12617 if (!torture_open_connection(&cli, 0)) {
12618 return false;
12620 smbXcli_conn_set_sockopt(cli->conn, sockops);
12622 ev = samba_tevent_context_init(frame);
12623 if (ev == NULL) {
12624 goto fail;
12627 req = pid_echo_send(frame, ev, cli);
12628 if (req == NULL) {
12629 goto fail;
12632 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12633 goto fail;
12636 status = pid_echo_recv(req);
12637 if (NT_STATUS_IS_OK(status)) {
12638 printf("pid high test ok\n");
12639 success = true;
12642 fail:
12644 TALLOC_FREE(frame);
12645 torture_close_connection(cli);
12646 return success;
12650 Test Windows open on a bad POSIX symlink.
12652 static bool run_symlink_open_test(int dummy)
12654 static struct cli_state *cli;
12655 const char *fname = "non_existant_file";
12656 const char *sname = "dangling_symlink";
12657 uint16_t fnum = (uint16_t)-1;
12658 bool correct = false;
12659 NTSTATUS status;
12660 TALLOC_CTX *frame = NULL;
12662 frame = talloc_stackframe();
12664 printf("Starting Windows bad symlink open test\n");
12666 if (!torture_open_connection(&cli, 0)) {
12667 TALLOC_FREE(frame);
12668 return false;
12671 smbXcli_conn_set_sockopt(cli->conn, sockops);
12673 status = torture_setup_unix_extensions(cli);
12674 if (!NT_STATUS_IS_OK(status)) {
12675 TALLOC_FREE(frame);
12676 return false;
12679 /* Ensure nothing exists. */
12680 cli_setatr(cli, fname, 0, 0);
12681 cli_posix_unlink(cli, fname);
12682 cli_setatr(cli, sname, 0, 0);
12683 cli_posix_unlink(cli, sname);
12685 /* Create a symlink pointing nowhere. */
12686 status = cli_posix_symlink(cli, fname, sname);
12687 if (!NT_STATUS_IS_OK(status)) {
12688 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12689 sname,
12690 fname,
12691 nt_errstr(status));
12692 goto out;
12695 /* Now ensure that a Windows open doesn't hang. */
12696 status = cli_ntcreate(cli,
12697 sname,
12699 FILE_READ_DATA|FILE_WRITE_DATA,
12701 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12702 FILE_OPEN_IF,
12703 0x0,
12704 0x0,
12705 &fnum,
12706 NULL);
12709 * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12710 * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12711 * we use O_NOFOLLOW on the server or not.
12713 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12714 NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12716 correct = true;
12717 } else {
12718 printf("cli_ntcreate of %s returned %s - should return"
12719 " either (%s) or (%s)\n",
12720 sname,
12721 nt_errstr(status),
12722 nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12723 nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12724 goto out;
12727 correct = true;
12729 out:
12731 if (fnum != (uint16_t)-1) {
12732 cli_close(cli, fnum);
12733 fnum = (uint16_t)-1;
12736 cli_setatr(cli, sname, 0, 0);
12737 cli_posix_unlink(cli, sname);
12738 cli_setatr(cli, fname, 0, 0);
12739 cli_posix_unlink(cli, fname);
12741 if (!torture_close_connection(cli)) {
12742 correct = false;
12745 TALLOC_FREE(frame);
12746 return correct;
12749 static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12750 const char *name,
12751 void *state)
12753 char **mangled_name_return = (char **)state;
12754 bool is_mangled = strchr(finfo->name, '~');
12756 if (is_mangled) {
12757 *mangled_name_return = talloc_strdup(NULL, finfo->name);
12758 if (*mangled_name_return == NULL) {
12759 return NT_STATUS_NO_MEMORY;
12762 return NT_STATUS_OK;
12765 static bool run_smb1_wild_mangle_unlink_test(int dummy)
12767 static struct cli_state *cli_posix = NULL;
12768 static struct cli_state *cli = NULL;
12769 uint16_t fnum = (uint16_t)-1;
12770 bool correct = false;
12771 const char *dname = "smb1_wild_mangle_unlink";
12772 const char *aname = "smb1_wild_mangle_unlink/a";
12773 const char *star_name = "smb1_wild_mangle_unlink/*";
12774 char *windows_unlink_name = NULL;
12775 char *mangled_name = NULL;
12776 NTSTATUS status;
12778 printf("Starting SMB1 wild mangle unlink test\n");
12780 /* Open a Windows connection. */
12781 if (!torture_open_connection(&cli, 0)) {
12782 return false;
12785 smbXcli_conn_set_sockopt(cli->conn, sockops);
12787 /* Open a POSIX connection. */
12788 if (!torture_open_connection(&cli_posix, 0)) {
12789 goto out;
12792 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12794 status = torture_setup_unix_extensions(cli_posix);
12795 if (!NT_STATUS_IS_OK(status)) {
12796 printf("server doesn't support POSIX\n");
12797 goto out;
12800 /* Start fresh. */
12801 torture_deltree(cli, dname);
12804 * Create two files - 'a' and '*'.
12805 * We need POSIX extensions for this as '*'
12806 * is not a valid Windows name.
12809 status = cli_mkdir(cli, dname);
12810 if (!NT_STATUS_IS_OK(status)) {
12811 printf("cli_mkdir of %s returned %s\n",
12812 dname,
12813 nt_errstr(status));
12814 goto out;
12817 status = cli_posix_open(cli_posix,
12818 aname,
12819 O_RDWR|O_CREAT|O_EXCL,
12820 0660,
12821 &fnum);
12822 if (!NT_STATUS_IS_OK(status)) {
12823 printf("cli_posix_open (create) of %s returned %s\n",
12824 aname,
12825 nt_errstr(status));
12826 goto out;
12828 status = cli_close(cli_posix, fnum);
12829 if (!NT_STATUS_IS_OK(status)) {
12830 goto out;
12832 status = cli_posix_open(cli_posix,
12833 star_name,
12834 O_RDWR|O_CREAT|O_EXCL,
12835 0660,
12836 &fnum);
12837 if (!NT_STATUS_IS_OK(status)) {
12838 printf("cli_posix_open (create) of %s returned %s\n",
12839 star_name,
12840 nt_errstr(status));
12841 goto out;
12843 status = cli_close(cli_posix, fnum);
12844 if (!NT_STATUS_IS_OK(status)) {
12845 goto out;
12848 status = cli_list(cli,
12849 star_name,
12851 smb1_wild_mangle_list_fn,
12852 &mangled_name);
12853 if (!NT_STATUS_IS_OK(status)) {
12854 printf("cli_list of %s returned %s\n",
12855 star_name,
12856 nt_errstr(status));
12857 goto out;
12860 if (mangled_name == NULL) {
12861 goto out;
12864 printf("mangled_name = %s\n",
12865 mangled_name);
12868 * Try a Windows unlink with the mangled name.
12869 * This should *NOT* unlink the 'a' name.
12872 windows_unlink_name = talloc_asprintf(cli_posix,
12873 "%s\\%s",
12874 dname,
12875 mangled_name);
12877 status = cli_unlink(cli, windows_unlink_name, 0);
12878 if (!NT_STATUS_IS_OK(status)) {
12879 printf("cli_unlink of %s returned %s\n",
12880 windows_unlink_name,
12881 nt_errstr(status));
12882 goto out;
12885 /* Does 'a' still exist ? */
12886 status = cli_posix_open(cli_posix,
12887 aname,
12888 O_RDONLY,
12890 &fnum);
12891 if (!NT_STATUS_IS_OK(status)) {
12892 printf("cli_posix_open O_RNONLY of %s returned %s\n",
12893 aname,
12894 nt_errstr(status));
12895 goto out;
12898 status = cli_close(cli_posix, fnum);
12899 if (!NT_STATUS_IS_OK(status)) {
12900 goto out;
12903 correct = true;
12905 out:
12907 TALLOC_FREE(windows_unlink_name);
12908 TALLOC_FREE(mangled_name);
12910 if (cli != NULL) {
12911 torture_deltree(cli, dname);
12912 torture_close_connection(cli);
12915 if (cli_posix != NULL) {
12916 torture_close_connection(cli_posix);
12919 return correct;
12922 static bool run_smb1_wild_mangle_rename_test(int dummy)
12924 static struct cli_state *cli_posix = NULL;
12925 static struct cli_state *cli = NULL;
12926 uint16_t fnum = (uint16_t)-1;
12927 bool correct = false;
12928 const char *dname = "smb1_wild_mangle_rename";
12929 const char *fooname = "smb1_wild_mangle_rename/foo";
12930 const char *foostar_name = "smb1_wild_mangle_rename/fo*";
12931 const char *wild_name = "smb1_wild_mangle_rename/*";
12932 char *windows_rename_src = NULL;
12933 const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
12934 char *mangled_name = NULL;
12935 NTSTATUS status;
12937 printf("Starting SMB1 wild mangle rename test\n");
12939 if (!torture_open_connection(&cli_posix, 0)) {
12940 return false;
12943 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12945 status = torture_setup_unix_extensions(cli_posix);
12946 if (!NT_STATUS_IS_OK(status)) {
12947 printf("server doesn't support POSIX\n");
12948 return false;
12951 /* Open a Windows connection. */
12952 if (!torture_open_connection(&cli, 0)) {
12953 goto out;
12956 smbXcli_conn_set_sockopt(cli->conn, sockops);
12958 /* Ensure we start from fresh. */
12959 torture_deltree(cli, dname);
12962 * Create two files - 'foo' and 'fo*'.
12963 * We need POSIX extensions for this as 'fo*'
12964 * is not a valid Windows name.
12967 status = cli_posix_mkdir(cli_posix, dname, 0770);
12968 if (!NT_STATUS_IS_OK(status)) {
12969 printf("cli_posix_mkdir of %s returned %s\n",
12970 dname,
12971 nt_errstr(status));
12972 goto out;
12975 status = cli_posix_open(cli_posix,
12976 fooname,
12977 O_RDWR|O_CREAT|O_EXCL,
12978 0660,
12979 &fnum);
12980 if (!NT_STATUS_IS_OK(status)) {
12981 printf("cli_posix_open (create) of %s returned %s\n",
12982 fooname,
12983 nt_errstr(status));
12984 goto out;
12986 status = cli_close(cli_posix, fnum);
12987 if (!NT_STATUS_IS_OK(status)) {
12988 goto out;
12990 status = cli_posix_open(cli_posix,
12991 foostar_name,
12992 O_RDWR|O_CREAT|O_EXCL,
12993 0660,
12994 &fnum);
12995 if (!NT_STATUS_IS_OK(status)) {
12996 printf("cli_posix_open (create) of %s returned %s\n",
12997 foostar_name,
12998 nt_errstr(status));
12999 goto out;
13001 status = cli_close(cli_posix, fnum);
13002 if (!NT_STATUS_IS_OK(status)) {
13003 goto out;
13007 * Get the mangled name. We can re-use the
13008 * previous smb1_wild_mangle_list_fn for this.
13011 status = cli_list(cli,
13012 wild_name,
13014 smb1_wild_mangle_list_fn,
13015 &mangled_name);
13016 if (!NT_STATUS_IS_OK(status)) {
13017 printf("cli_list of %s returned %s\n",
13018 wild_name,
13019 nt_errstr(status));
13020 goto out;
13023 if (mangled_name == NULL) {
13024 goto out;
13027 printf("mangled_name = %s\n",
13028 mangled_name);
13031 * Try a Windows rename with the mangled name.
13032 * This should *NOT* rename the 'foo' name.
13035 windows_rename_src = talloc_asprintf(cli_posix,
13036 "%s\\%s",
13037 dname,
13038 mangled_name);
13040 status = cli_rename(cli,
13041 windows_rename_src,
13042 windows_rename_dst,
13043 false);
13044 if (!NT_STATUS_IS_OK(status)) {
13045 printf("cli_rename of %s -> %s returned %s\n",
13046 windows_rename_src,
13047 windows_rename_dst,
13048 nt_errstr(status));
13049 goto out;
13052 /* Does 'foo' still exist ? */
13053 status = cli_posix_open(cli_posix,
13054 fooname,
13055 O_RDONLY,
13057 &fnum);
13058 if (!NT_STATUS_IS_OK(status)) {
13059 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13060 fooname,
13061 nt_errstr(status));
13062 goto out;
13065 status = cli_close(cli_posix, fnum);
13066 if (!NT_STATUS_IS_OK(status)) {
13067 goto out;
13070 correct = true;
13072 out:
13074 TALLOC_FREE(mangled_name);
13075 TALLOC_FREE(windows_rename_src);
13077 if (cli != NULL) {
13078 torture_deltree(cli, dname);
13079 torture_close_connection(cli);
13082 torture_close_connection(cli_posix);
13084 return correct;
13088 * Only testing minimal time strings, as the others
13089 * need (locale-dependent) guessing at what strftime does and
13090 * even may differ in builds.
13092 static bool timesubst_test(void)
13094 TALLOC_CTX *ctx = NULL;
13095 /* Sa 23. Dez 04:33:20 CET 2017 */
13096 const struct timeval tv = { 1514000000, 123 };
13097 const char* expect_minimal = "20171223_033320";
13098 const char* expect_minus = "20171223_033320_000123";
13099 char *s;
13100 char *env_tz, *orig_tz = NULL;
13101 bool result = true;
13103 ctx = talloc_new(NULL);
13105 env_tz = getenv("TZ");
13106 if(env_tz) {
13107 orig_tz = talloc_strdup(ctx, env_tz);
13109 setenv("TZ", "UTC", 1);
13111 s = minimal_timeval_string(ctx, &tv, false);
13113 if(!s || strcmp(s, expect_minimal)) {
13114 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13115 "[%s]\n", s ? s : "<nil>", expect_minimal);
13116 result = false;
13118 TALLOC_FREE(s);
13119 s = minimal_timeval_string(ctx, &tv, true);
13120 if(!s || strcmp(s, expect_minus)) {
13121 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13122 "[%s]\n", s ? s : "<nil>", expect_minus);
13123 result = false;
13125 TALLOC_FREE(s);
13127 if(orig_tz) {
13128 setenv("TZ", orig_tz, 1);
13131 TALLOC_FREE(ctx);
13132 return result;
13135 static bool run_local_substitute(int dummy)
13137 bool ok = true;
13139 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13140 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13141 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13142 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13143 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13144 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13145 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13146 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13147 ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13148 /* Substitution depends on current time, so better test the underlying
13149 formatting function. At least covers %t. */
13150 ok &= timesubst_test();
13152 /* Different captialization rules in sub_basic... */
13154 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13155 "blaDOM") == 0);
13157 return ok;
13160 static bool run_local_base64(int dummy)
13162 int i;
13163 bool ret = true;
13165 for (i=1; i<2000; i++) {
13166 DATA_BLOB blob1, blob2;
13167 char *b64;
13169 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13170 blob1.length = i;
13171 generate_random_buffer(blob1.data, blob1.length);
13173 b64 = base64_encode_data_blob(talloc_tos(), blob1);
13174 if (b64 == NULL) {
13175 d_fprintf(stderr, "base64_encode_data_blob failed "
13176 "for %d bytes\n", i);
13177 ret = false;
13179 blob2 = base64_decode_data_blob(b64);
13180 TALLOC_FREE(b64);
13182 if (data_blob_cmp(&blob1, &blob2)) {
13183 d_fprintf(stderr, "data_blob_cmp failed for %d "
13184 "bytes\n", i);
13185 ret = false;
13187 TALLOC_FREE(blob1.data);
13188 data_blob_free(&blob2);
13190 return ret;
13193 static void parse_fn(const struct gencache_timeout *t,
13194 DATA_BLOB blob,
13195 void *private_data)
13197 return;
13200 static bool run_local_gencache(int dummy)
13202 char *val;
13203 time_t tm;
13204 DATA_BLOB blob;
13205 char v;
13206 struct memcache *mem;
13207 int i;
13209 mem = memcache_init(NULL, 0);
13210 if (mem == NULL) {
13211 d_printf("%s: memcache_init failed\n", __location__);
13212 return false;
13214 memcache_set_global(mem);
13216 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13217 d_printf("%s: gencache_set() failed\n", __location__);
13218 return False;
13221 if (!gencache_get("foo", NULL, NULL, NULL)) {
13222 d_printf("%s: gencache_get() failed\n", __location__);
13223 return False;
13226 for (i=0; i<1000000; i++) {
13227 gencache_parse("foo", parse_fn, NULL);
13230 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13231 d_printf("%s: gencache_get() failed\n", __location__);
13232 return False;
13234 TALLOC_FREE(val);
13236 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13237 d_printf("%s: gencache_get() failed\n", __location__);
13238 return False;
13241 if (strcmp(val, "bar") != 0) {
13242 d_printf("%s: gencache_get() returned %s, expected %s\n",
13243 __location__, val, "bar");
13244 TALLOC_FREE(val);
13245 return False;
13248 TALLOC_FREE(val);
13250 if (!gencache_del("foo")) {
13251 d_printf("%s: gencache_del() failed\n", __location__);
13252 return False;
13254 if (gencache_del("foo")) {
13255 d_printf("%s: second gencache_del() succeeded\n",
13256 __location__);
13257 return False;
13260 if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13261 d_printf("%s: gencache_get() on deleted entry "
13262 "succeeded\n", __location__);
13263 return False;
13266 blob = data_blob_string_const_null("bar");
13267 tm = time(NULL) + 60;
13269 if (!gencache_set_data_blob("foo", blob, tm)) {
13270 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13271 return False;
13274 if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13275 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13276 return False;
13279 if (strcmp((const char *)blob.data, "bar") != 0) {
13280 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13281 __location__, (const char *)blob.data, "bar");
13282 data_blob_free(&blob);
13283 return False;
13286 data_blob_free(&blob);
13288 if (!gencache_del("foo")) {
13289 d_printf("%s: gencache_del() failed\n", __location__);
13290 return False;
13292 if (gencache_del("foo")) {
13293 d_printf("%s: second gencache_del() succeeded\n",
13294 __location__);
13295 return False;
13298 if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13299 d_printf("%s: gencache_get_data_blob() on deleted entry "
13300 "succeeded\n", __location__);
13301 return False;
13304 v = 1;
13305 blob.data = (uint8_t *)&v;
13306 blob.length = sizeof(v);
13308 if (!gencache_set_data_blob("blob", blob, tm)) {
13309 d_printf("%s: gencache_set_data_blob() failed\n",
13310 __location__);
13311 return false;
13313 if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13314 d_printf("%s: gencache_get succeeded\n", __location__);
13315 return false;
13318 return True;
13321 static bool rbt_testflags(struct db_context *db, const char *key,
13322 const char *value)
13324 bool ret = false;
13325 NTSTATUS status;
13326 struct db_record *rec;
13328 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13329 if (rec == NULL) {
13330 d_fprintf(stderr, "fetch_locked failed\n");
13331 goto done;
13334 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13335 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13336 d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13337 nt_errstr(status));
13338 goto done;
13341 status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13342 TDB_INSERT);
13343 if (!NT_STATUS_IS_OK(status)) {
13344 d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13345 nt_errstr(status));
13346 goto done;
13349 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13350 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13351 d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13352 nt_errstr(status));
13353 goto done;
13356 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13357 if (!NT_STATUS_IS_OK(status)) {
13358 d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13359 nt_errstr(status));
13360 goto done;
13363 ret = true;
13364 done:
13365 TALLOC_FREE(rec);
13366 return ret;
13369 static bool rbt_testval(struct db_context *db, const char *key,
13370 const char *value)
13372 struct db_record *rec;
13373 TDB_DATA data = string_tdb_data(value);
13374 bool ret = false;
13375 NTSTATUS status;
13376 TDB_DATA dbvalue;
13378 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13379 if (rec == NULL) {
13380 d_fprintf(stderr, "fetch_locked failed\n");
13381 goto done;
13383 status = dbwrap_record_store(rec, data, 0);
13384 if (!NT_STATUS_IS_OK(status)) {
13385 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13386 goto done;
13388 TALLOC_FREE(rec);
13390 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13391 if (rec == NULL) {
13392 d_fprintf(stderr, "second fetch_locked failed\n");
13393 goto done;
13396 dbvalue = dbwrap_record_get_value(rec);
13397 if ((dbvalue.dsize != data.dsize)
13398 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13399 d_fprintf(stderr, "Got wrong data back\n");
13400 goto done;
13403 ret = true;
13404 done:
13405 TALLOC_FREE(rec);
13406 return ret;
13409 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13411 int *count2 = (int *)private_data;
13412 (*count2)++;
13413 return 0;
13416 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13418 int *count2 = (int *)private_data;
13419 (*count2)++;
13420 dbwrap_record_delete(rec);
13421 return 0;
13424 static bool run_local_rbtree(int dummy)
13426 struct db_context *db;
13427 bool ret = false;
13428 int i;
13429 NTSTATUS status;
13430 int count = 0;
13431 int count2 = 0;
13433 db = db_open_rbt(NULL);
13435 if (db == NULL) {
13436 d_fprintf(stderr, "db_open_rbt failed\n");
13437 return false;
13440 if (!rbt_testflags(db, "firstkey", "firstval")) {
13441 goto done;
13444 for (i = 0; i < 999; i++) {
13445 char key[sizeof("key-9223372036854775807")];
13446 char value[sizeof("value-9223372036854775807")];
13448 snprintf(key, sizeof(key), "key%ld", random());
13449 snprintf(value, sizeof(value) ,"value%ld", random());
13451 if (!rbt_testval(db, key, value)) {
13452 goto done;
13455 snprintf(value, sizeof(value) ,"value%ld", random());
13457 if (!rbt_testval(db, key, value)) {
13458 goto done;
13462 ret = true;
13463 count = 0; count2 = 0;
13464 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13465 &count2, &count);
13466 printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13467 if ((count != count2) || (count != 1000)) {
13468 ret = false;
13470 count = 0; count2 = 0;
13471 status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13472 &count2, &count);
13473 printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13474 if ((count != count2) || (count != 1000)) {
13475 ret = false;
13477 count = 0; count2 = 0;
13478 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13479 &count2, &count);
13480 printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13481 if ((count != count2) || (count != 0)) {
13482 ret = false;
13485 done:
13486 TALLOC_FREE(db);
13487 return ret;
13492 local test for character set functions
13494 This is a very simple test for the functionality in convert_string_error()
13496 static bool run_local_convert_string(int dummy)
13498 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13499 const char *test_strings[2] = { "March", "M\303\244rz" };
13500 char dst[7];
13501 int i;
13503 for (i=0; i<2; i++) {
13504 const char *str = test_strings[i];
13505 int len = strlen(str);
13506 size_t converted_size;
13507 bool ret;
13509 memset(dst, 'X', sizeof(dst));
13511 /* first try with real source length */
13512 ret = convert_string_error(CH_UNIX, CH_UTF8,
13513 str, len,
13514 dst, sizeof(dst),
13515 &converted_size);
13516 if (ret != true) {
13517 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13518 goto failed;
13521 if (converted_size != len) {
13522 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13523 str, len, (int)converted_size);
13524 goto failed;
13527 if (strncmp(str, dst, converted_size) != 0) {
13528 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13529 goto failed;
13532 if (strlen(str) != converted_size) {
13533 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13534 (int)strlen(str), (int)converted_size);
13535 goto failed;
13538 if (dst[converted_size] != 'X') {
13539 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13540 goto failed;
13543 /* now with srclen==-1, this causes the nul to be
13544 * converted too */
13545 ret = convert_string_error(CH_UNIX, CH_UTF8,
13546 str, -1,
13547 dst, sizeof(dst),
13548 &converted_size);
13549 if (ret != true) {
13550 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13551 goto failed;
13554 if (converted_size != len+1) {
13555 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13556 str, len, (int)converted_size);
13557 goto failed;
13560 if (strncmp(str, dst, converted_size) != 0) {
13561 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13562 goto failed;
13565 if (len+1 != converted_size) {
13566 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13567 len+1, (int)converted_size);
13568 goto failed;
13571 if (dst[converted_size] != 'X') {
13572 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13573 goto failed;
13579 TALLOC_FREE(tmp_ctx);
13580 return true;
13581 failed:
13582 TALLOC_FREE(tmp_ctx);
13583 return false;
13586 static bool run_local_string_to_sid(int dummy) {
13587 struct dom_sid sid;
13589 if (string_to_sid(&sid, "S--1-5-32-545")) {
13590 printf("allowing S--1-5-32-545\n");
13591 return false;
13593 if (string_to_sid(&sid, "S-1-5-32-+545")) {
13594 printf("allowing S-1-5-32-+545\n");
13595 return false;
13597 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")) {
13598 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13599 return false;
13601 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13602 printf("allowing S-1-5-32-545-abc\n");
13603 return false;
13605 if (string_to_sid(&sid, "S-300-5-32-545")) {
13606 printf("allowing S-300-5-32-545\n");
13607 return false;
13609 if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13610 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13611 return false;
13613 if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13614 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13615 return false;
13617 if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13618 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13619 return false;
13621 if (!string_to_sid(&sid, "S-1-5-32-545")) {
13622 printf("could not parse S-1-5-32-545\n");
13623 return false;
13625 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13626 struct dom_sid_buf buf;
13627 printf("mis-parsed S-1-5-32-545 as %s\n",
13628 dom_sid_str_buf(&sid, &buf));
13629 return false;
13631 return true;
13634 static bool sid_to_string_test(const char *expected) {
13635 char *str;
13636 bool res = true;
13637 struct dom_sid sid;
13639 if (!string_to_sid(&sid, expected)) {
13640 printf("could not parse %s\n", expected);
13641 return false;
13644 str = dom_sid_string(NULL, &sid);
13645 if (strcmp(str, expected)) {
13646 printf("Comparison failed (%s != %s)\n", str, expected);
13647 res = false;
13649 TALLOC_FREE(str);
13650 return res;
13653 static bool run_local_sid_to_string(int dummy) {
13654 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13655 return false;
13656 if (!sid_to_string_test("S-1-545"))
13657 return false;
13658 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13659 return false;
13660 return true;
13663 static bool run_local_binary_to_sid(int dummy) {
13664 ssize_t ret;
13665 struct dom_sid *sid = talloc(NULL, struct dom_sid);
13666 static const uint8_t good_binary_sid[] = {
13667 0x1, /* revision number */
13668 15, /* num auths */
13669 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13670 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13671 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13672 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13673 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13674 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13675 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13676 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13677 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13678 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13679 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13680 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13681 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13682 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13683 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13684 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13687 static const uint8_t long_binary_sid[] = {
13688 0x1, /* revision number */
13689 15, /* num auths */
13690 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13691 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13692 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13693 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13694 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13695 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13696 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13697 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13698 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13699 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13700 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13701 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13702 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13703 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13704 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13705 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13706 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13707 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13708 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13711 static const uint8_t long_binary_sid2[] = {
13712 0x1, /* revision number */
13713 32, /* num auths */
13714 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13715 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13716 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13717 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13718 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13719 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13720 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13721 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13722 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13723 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13724 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13725 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13726 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13727 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13728 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13729 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13730 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13731 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13732 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13733 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13734 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13735 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13736 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13737 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13738 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13739 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13740 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13741 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13742 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13743 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13744 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13745 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13746 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13749 ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13750 if (ret == -1) {
13751 return false;
13753 ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13754 if (ret != -1) {
13755 return false;
13757 ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13758 if (ret != -1) {
13759 return false;
13761 return true;
13764 /* Split a path name into filename and stream name components. Canonicalise
13765 * such that an implicit $DATA token is always explicit.
13767 * The "specification" of this function can be found in the
13768 * run_local_stream_name() function in torture.c, I've tried those
13769 * combinations against a W2k3 server.
13772 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13773 char **pbase, char **pstream)
13775 char *base = NULL;
13776 char *stream = NULL;
13777 char *sname; /* stream name */
13778 const char *stype; /* stream type */
13780 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13782 sname = strchr_m(fname, ':');
13784 if (sname == NULL) {
13785 if (pbase != NULL) {
13786 base = talloc_strdup(mem_ctx, fname);
13787 NT_STATUS_HAVE_NO_MEMORY(base);
13789 goto done;
13792 if (pbase != NULL) {
13793 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13794 NT_STATUS_HAVE_NO_MEMORY(base);
13797 sname += 1;
13799 stype = strchr_m(sname, ':');
13801 if (stype == NULL) {
13802 sname = talloc_strdup(mem_ctx, sname);
13803 stype = "$DATA";
13805 else {
13806 if (strcasecmp_m(stype, ":$DATA") != 0) {
13808 * If there is an explicit stream type, so far we only
13809 * allow $DATA. Is there anything else allowed? -- vl
13811 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13812 TALLOC_FREE(base);
13813 return NT_STATUS_OBJECT_NAME_INVALID;
13815 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13816 stype += 1;
13819 if (sname == NULL) {
13820 TALLOC_FREE(base);
13821 return NT_STATUS_NO_MEMORY;
13824 if (sname[0] == '\0') {
13826 * no stream name, so no stream
13828 goto done;
13831 if (pstream != NULL) {
13832 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13833 if (stream == NULL) {
13834 TALLOC_FREE(sname);
13835 TALLOC_FREE(base);
13836 return NT_STATUS_NO_MEMORY;
13839 * upper-case the type field
13841 (void)strupper_m(strchr_m(stream, ':')+1);
13844 done:
13845 if (pbase != NULL) {
13846 *pbase = base;
13848 if (pstream != NULL) {
13849 *pstream = stream;
13851 return NT_STATUS_OK;
13854 static bool test_stream_name(const char *fname, const char *expected_base,
13855 const char *expected_stream,
13856 NTSTATUS expected_status)
13858 NTSTATUS status;
13859 char *base = NULL;
13860 char *stream = NULL;
13862 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13863 if (!NT_STATUS_EQUAL(status, expected_status)) {
13864 goto error;
13867 if (!NT_STATUS_IS_OK(status)) {
13868 return true;
13871 if (base == NULL) goto error;
13873 if (strcmp(expected_base, base) != 0) goto error;
13875 if ((expected_stream != NULL) && (stream == NULL)) goto error;
13876 if ((expected_stream == NULL) && (stream != NULL)) goto error;
13878 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
13879 goto error;
13881 TALLOC_FREE(base);
13882 TALLOC_FREE(stream);
13883 return true;
13885 error:
13886 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
13887 fname, expected_base ? expected_base : "<NULL>",
13888 expected_stream ? expected_stream : "<NULL>",
13889 nt_errstr(expected_status));
13890 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
13891 base ? base : "<NULL>", stream ? stream : "<NULL>",
13892 nt_errstr(status));
13893 TALLOC_FREE(base);
13894 TALLOC_FREE(stream);
13895 return false;
13898 static bool run_local_stream_name(int dummy)
13900 bool ret = true;
13902 ret &= test_stream_name(
13903 "bla", "bla", NULL, NT_STATUS_OK);
13904 ret &= test_stream_name(
13905 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
13906 ret &= test_stream_name(
13907 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13908 ret &= test_stream_name(
13909 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
13910 ret &= test_stream_name(
13911 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13912 ret &= test_stream_name(
13913 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
13914 ret &= test_stream_name(
13915 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
13916 ret &= test_stream_name(
13917 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
13919 return ret;
13922 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
13924 if (a.length != b.length) {
13925 printf("a.length=%d != b.length=%d\n",
13926 (int)a.length, (int)b.length);
13927 return false;
13929 if (memcmp(a.data, b.data, a.length) != 0) {
13930 printf("a.data and b.data differ\n");
13931 return false;
13933 return true;
13936 static bool run_local_memcache(int dummy)
13938 struct memcache *cache;
13939 DATA_BLOB k1, k2, k3, k4, k5;
13940 DATA_BLOB d1, d3;
13941 DATA_BLOB v1, v3;
13943 TALLOC_CTX *mem_ctx;
13944 char *ptr1 = NULL;
13945 char *ptr2 = NULL;
13946 char *ptr3 = NULL;
13948 char *str1, *str2;
13949 size_t size1, size2;
13950 bool ret = false;
13952 mem_ctx = talloc_init("foo");
13953 if (mem_ctx == NULL) {
13954 return false;
13957 /* STAT_CACHE TESTS */
13959 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13961 if (cache == NULL) {
13962 printf("memcache_init failed\n");
13963 return false;
13966 d1 = data_blob_const("d1", 2);
13967 d3 = data_blob_const("d3", 2);
13969 k1 = data_blob_const("d1", 2);
13970 k2 = data_blob_const("d2", 2);
13971 k3 = data_blob_const("d3", 2);
13972 k4 = data_blob_const("d4", 2);
13973 k5 = data_blob_const("d5", 2);
13975 memcache_add(cache, STAT_CACHE, k1, d1);
13977 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
13978 printf("could not find k1\n");
13979 return false;
13981 if (!data_blob_equal(d1, v1)) {
13982 return false;
13985 memcache_add(cache, STAT_CACHE, k1, d3);
13987 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
13988 printf("could not find replaced k1\n");
13989 return false;
13991 if (!data_blob_equal(d3, v3)) {
13992 return false;
13995 TALLOC_FREE(cache);
13997 /* GETWD_CACHE TESTS */
13998 str1 = talloc_strdup(mem_ctx, "string1");
13999 if (str1 == NULL) {
14000 return false;
14002 ptr2 = str1; /* Keep an alias for comparison. */
14004 str2 = talloc_strdup(mem_ctx, "string2");
14005 if (str2 == NULL) {
14006 return false;
14009 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14010 if (cache == NULL) {
14011 printf("memcache_init failed\n");
14012 return false;
14015 memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14016 /* str1 == NULL now. */
14017 ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14018 if (ptr1 == NULL) {
14019 printf("could not find k2\n");
14020 return false;
14022 if (ptr1 != ptr2) {
14023 printf("fetch of k2 got wrong string\n");
14024 return false;
14027 /* Add a blob to ensure k2 gets purged. */
14028 d3 = data_blob_talloc_zero(mem_ctx, 180);
14029 memcache_add(cache, STAT_CACHE, k3, d3);
14031 ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14032 if (ptr2 != NULL) {
14033 printf("Did find k2, should have been purged\n");
14034 return false;
14038 * Test that talloc size also is accounted in memcache and
14039 * causes purge of other object.
14042 str1 = talloc_zero_size(mem_ctx, 100);
14043 str2 = talloc_zero_size(mem_ctx, 100);
14045 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14046 memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14048 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14049 if (ptr3 != NULL) {
14050 printf("Did find k4, should have been purged\n");
14051 return false;
14055 * Test that adding a duplicate non-talloced
14056 * key/value on top of a talloced key/value takes account
14057 * of the talloc_freed value size.
14059 TALLOC_FREE(cache);
14060 TALLOC_FREE(mem_ctx);
14062 mem_ctx = talloc_init("key_replace");
14063 if (mem_ctx == NULL) {
14064 return false;
14067 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14068 if (cache == NULL) {
14069 return false;
14073 * Add a 100 byte talloced string. This will
14074 * store a (4 or 8 byte) pointer and record the
14075 * total talloced size.
14077 str1 = talloc_zero_size(mem_ctx, 100);
14078 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14080 * Now overwrite with a small talloced
14081 * value. This should fit in the existing size
14082 * and the total talloced size should be removed
14083 * from the cache size.
14085 str1 = talloc_zero_size(mem_ctx, 2);
14086 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14088 * Now store a 20 byte string. If the
14089 * total talloced size wasn't accounted for
14090 * and removed in the overwrite, then this
14091 * will evict k4.
14093 str2 = talloc_zero_size(mem_ctx, 20);
14094 memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14096 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14097 if (ptr3 == NULL) {
14098 printf("Did not find k4, should not have been purged\n");
14099 return false;
14102 TALLOC_FREE(cache);
14103 TALLOC_FREE(mem_ctx);
14105 mem_ctx = talloc_init("foo");
14106 if (mem_ctx == NULL) {
14107 return false;
14110 cache = memcache_init(NULL, 0);
14111 if (cache == NULL) {
14112 return false;
14115 str1 = talloc_strdup(mem_ctx, "string1");
14116 if (str1 == NULL) {
14117 return false;
14119 str2 = talloc_strdup(mem_ctx, "string2");
14120 if (str2 == NULL) {
14121 return false;
14123 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14124 data_blob_string_const("torture"), &str1);
14125 size1 = talloc_total_size(cache);
14127 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14128 data_blob_string_const("torture"), &str2);
14129 size2 = talloc_total_size(cache);
14131 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14133 if (size2 > size1) {
14134 printf("memcache leaks memory!\n");
14135 goto fail;
14138 ret = true;
14139 fail:
14140 TALLOC_FREE(cache);
14141 return ret;
14144 static void wbclient_done(struct tevent_req *req)
14146 wbcErr wbc_err;
14147 struct winbindd_response *wb_resp;
14148 int *i = (int *)tevent_req_callback_data_void(req);
14150 wbc_err = wb_trans_recv(req, req, &wb_resp);
14151 TALLOC_FREE(req);
14152 *i += 1;
14153 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14156 static bool run_wbclient_multi_ping(int dummy)
14158 struct tevent_context *ev;
14159 struct wb_context **wb_ctx;
14160 struct winbindd_request wb_req;
14161 bool result = false;
14162 int i, j;
14164 BlockSignals(True, SIGPIPE);
14166 ev = tevent_context_init(talloc_tos());
14167 if (ev == NULL) {
14168 goto fail;
14171 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14172 if (wb_ctx == NULL) {
14173 goto fail;
14176 ZERO_STRUCT(wb_req);
14177 wb_req.cmd = WINBINDD_PING;
14179 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14181 for (i=0; i<torture_nprocs; i++) {
14182 wb_ctx[i] = wb_context_init(ev, NULL);
14183 if (wb_ctx[i] == NULL) {
14184 goto fail;
14186 for (j=0; j<torture_numops; j++) {
14187 struct tevent_req *req;
14188 req = wb_trans_send(ev, ev, wb_ctx[i],
14189 (j % 2) == 0, &wb_req);
14190 if (req == NULL) {
14191 goto fail;
14193 tevent_req_set_callback(req, wbclient_done, &i);
14197 i = 0;
14199 while (i < torture_nprocs * torture_numops) {
14200 tevent_loop_once(ev);
14203 result = true;
14204 fail:
14205 TALLOC_FREE(ev);
14206 return result;
14209 static bool dbtrans_inc(struct db_context *db)
14211 struct db_record *rec;
14212 uint32_t val;
14213 bool ret = false;
14214 NTSTATUS status;
14215 TDB_DATA value;
14217 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14218 if (rec == NULL) {
14219 printf(__location__ "fetch_lock failed\n");
14220 return false;
14223 value = dbwrap_record_get_value(rec);
14225 if (value.dsize != sizeof(uint32_t)) {
14226 printf(__location__ "value.dsize = %d\n",
14227 (int)value.dsize);
14228 goto fail;
14231 memcpy(&val, value.dptr, sizeof(val));
14232 val += 1;
14234 status = dbwrap_record_store(
14235 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14236 if (!NT_STATUS_IS_OK(status)) {
14237 printf(__location__ "store failed: %s\n",
14238 nt_errstr(status));
14239 goto fail;
14242 ret = true;
14243 fail:
14244 TALLOC_FREE(rec);
14245 return ret;
14248 static bool run_local_dbtrans(int dummy)
14250 struct db_context *db;
14251 struct db_record *rec;
14252 NTSTATUS status;
14253 uint32_t initial;
14254 int res;
14255 TDB_DATA value;
14257 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14258 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14259 DBWRAP_FLAG_NONE);
14260 if (db == NULL) {
14261 printf("Could not open transtest.db\n");
14262 return false;
14265 res = dbwrap_transaction_start(db);
14266 if (res != 0) {
14267 printf(__location__ "transaction_start failed\n");
14268 return false;
14271 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14272 if (rec == NULL) {
14273 printf(__location__ "fetch_lock failed\n");
14274 return false;
14277 value = dbwrap_record_get_value(rec);
14279 if (value.dptr == NULL) {
14280 initial = 0;
14281 status = dbwrap_record_store(
14282 rec, make_tdb_data((uint8_t *)&initial,
14283 sizeof(initial)),
14285 if (!NT_STATUS_IS_OK(status)) {
14286 printf(__location__ "store returned %s\n",
14287 nt_errstr(status));
14288 return false;
14292 TALLOC_FREE(rec);
14294 res = dbwrap_transaction_commit(db);
14295 if (res != 0) {
14296 printf(__location__ "transaction_commit failed\n");
14297 return false;
14300 while (true) {
14301 uint32_t val, val2;
14302 int i;
14304 res = dbwrap_transaction_start(db);
14305 if (res != 0) {
14306 printf(__location__ "transaction_start failed\n");
14307 break;
14310 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14311 if (!NT_STATUS_IS_OK(status)) {
14312 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14313 nt_errstr(status));
14314 break;
14317 for (i=0; i<10; i++) {
14318 if (!dbtrans_inc(db)) {
14319 return false;
14323 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14324 if (!NT_STATUS_IS_OK(status)) {
14325 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14326 nt_errstr(status));
14327 break;
14330 if (val2 != val + 10) {
14331 printf(__location__ "val=%d, val2=%d\n",
14332 (int)val, (int)val2);
14333 break;
14336 printf("val2=%d\r", val2);
14338 res = dbwrap_transaction_commit(db);
14339 if (res != 0) {
14340 printf(__location__ "transaction_commit failed\n");
14341 break;
14345 TALLOC_FREE(db);
14346 return true;
14350 * Just a dummy test to be run under a debugger. There's no real way
14351 * to inspect the tevent_poll specific function from outside of
14352 * tevent_poll.c.
14355 static bool run_local_tevent_poll(int dummy)
14357 struct tevent_context *ev;
14358 struct tevent_fd *fd1, *fd2;
14359 bool result = false;
14361 ev = tevent_context_init_byname(NULL, "poll");
14362 if (ev == NULL) {
14363 d_fprintf(stderr, "tevent_context_init_byname failed\n");
14364 goto fail;
14367 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14368 if (fd1 == NULL) {
14369 d_fprintf(stderr, "tevent_add_fd failed\n");
14370 goto fail;
14372 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14373 if (fd2 == NULL) {
14374 d_fprintf(stderr, "tevent_add_fd failed\n");
14375 goto fail;
14377 TALLOC_FREE(fd2);
14379 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14380 if (fd2 == NULL) {
14381 d_fprintf(stderr, "tevent_add_fd failed\n");
14382 goto fail;
14385 result = true;
14386 fail:
14387 TALLOC_FREE(ev);
14388 return result;
14391 static bool run_local_hex_encode_buf(int dummy)
14393 char buf[17];
14394 uint8_t src[8];
14395 size_t i;
14397 for (i=0; i<sizeof(src); i++) {
14398 src[i] = i;
14400 hex_encode_buf(buf, src, sizeof(src));
14401 if (strcmp(buf, "0001020304050607") != 0) {
14402 return false;
14404 hex_encode_buf(buf, NULL, 0);
14405 if (buf[0] != '\0') {
14406 return false;
14408 return true;
14411 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14412 "0.0.0.0",
14413 "::0",
14414 "1.2.3.1",
14415 "0.0.0.0",
14416 "0.0.0.0",
14417 "1.2.3.2",
14418 "1.2.3.3",
14419 "1.2.3.4",
14420 "1.2.3.5",
14421 "::0",
14422 "1.2.3.6",
14423 "1.2.3.7",
14424 "::0",
14425 "::0",
14426 "::0",
14427 "1.2.3.8",
14428 "1.2.3.9",
14429 "1.2.3.10",
14430 "1.2.3.11",
14431 "1.2.3.12",
14432 "1.2.3.13",
14433 "1001:1111:1111:1000:0:1111:1111:1111",
14434 "1.2.3.1",
14435 "1.2.3.2",
14436 "1.2.3.3",
14437 "1.2.3.12",
14438 "::0",
14439 "::0"
14442 static const char *remove_duplicate_addrs2_test_strings_result[] = {
14443 "1.2.3.1",
14444 "1.2.3.2",
14445 "1.2.3.3",
14446 "1.2.3.4",
14447 "1.2.3.5",
14448 "1.2.3.6",
14449 "1.2.3.7",
14450 "1.2.3.8",
14451 "1.2.3.9",
14452 "1.2.3.10",
14453 "1.2.3.11",
14454 "1.2.3.12",
14455 "1.2.3.13",
14456 "1001:1111:1111:1000:0:1111:1111:1111"
14459 static bool run_local_remove_duplicate_addrs2(int dummy)
14461 struct samba_sockaddr test_vector[28];
14462 size_t count, i;
14464 /* Construct the sockaddr_storage test vector. */
14465 for (i = 0; i < 28; i++) {
14466 struct addrinfo hints;
14467 struct addrinfo *res = NULL;
14468 int ret;
14470 memset(&hints, '\0', sizeof(hints));
14471 hints.ai_flags = AI_NUMERICHOST;
14472 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14473 NULL,
14474 &hints,
14475 &res);
14476 if (ret) {
14477 fprintf(stderr, "getaddrinfo failed on [%s]\n",
14478 remove_duplicate_addrs2_test_strings_vector[i]);
14479 return false;
14481 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14482 memcpy(&test_vector[i].u.ss,
14483 res->ai_addr,
14484 res->ai_addrlen);
14485 freeaddrinfo(res);
14488 count = remove_duplicate_addrs2(test_vector, i);
14490 if (count != 14) {
14491 fprintf(stderr, "count wrong (%zu) should be 14\n",
14492 count);
14493 return false;
14496 for (i = 0; i < count; i++) {
14497 char addr[INET6_ADDRSTRLEN];
14499 print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14501 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14502 fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14504 addr,
14505 remove_duplicate_addrs2_test_strings_result[i]);
14506 return false;
14510 printf("run_local_remove_duplicate_addrs2: success\n");
14511 return true;
14514 static bool run_local_tdb_opener(int dummy)
14516 TDB_CONTEXT *t;
14517 unsigned v = 0;
14519 while (1) {
14520 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14521 O_RDWR|O_CREAT, 0755);
14522 if (t == NULL) {
14523 perror("tdb_open failed");
14524 return false;
14526 tdb_close(t);
14528 v += 1;
14529 printf("\r%u", v);
14531 return true;
14534 static bool run_local_tdb_writer(int dummy)
14536 TDB_CONTEXT *t;
14537 unsigned v = 0;
14538 TDB_DATA val;
14540 t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14541 if (t == 0) {
14542 perror("tdb_open failed");
14543 return 1;
14546 val.dptr = (uint8_t *)&v;
14547 val.dsize = sizeof(v);
14549 while (1) {
14550 TDB_DATA data;
14551 int ret;
14553 ret = tdb_store(t, val, val, 0);
14554 if (ret != 0) {
14555 printf("%s\n", tdb_errorstr(t));
14557 v += 1;
14558 printf("\r%u", v);
14560 data = tdb_fetch(t, val);
14561 if (data.dptr != NULL) {
14562 SAFE_FREE(data.dptr);
14565 return true;
14568 static bool run_local_canonicalize_path(int dummy)
14570 const char *src[] = {
14571 "/foo/..",
14572 "/..",
14573 "/foo/bar/../baz",
14574 "/foo/././",
14575 "/../foo",
14576 ".././././",
14577 ".././././../../../boo",
14578 "./..",
14579 "/",
14580 "/../../",
14581 "/foo/../",
14582 "/./././",
14583 "/./././.",
14584 "/.../././.",
14585 "/./././.foo",
14586 "/./././.foo.",
14587 "/./././foo.",
14588 "/foo/bar/..",
14589 "/foo/bar/../baz/",
14590 "////////////////",
14591 "/////////./././././.",
14592 "/./.././../.boo/../baz",
14593 "/a/component/path",
14594 "/a/component/path/",
14595 "/a/component/path/..",
14596 "/a/component/../path/",
14597 "///a/./././///component/../////path/",
14598 NULL
14600 const char *dst[] = {
14601 "/",
14602 "/",
14603 "/foo/baz",
14604 "/foo",
14605 "/foo",
14606 "/",
14607 "/boo",
14608 "/",
14609 "/",
14610 "/",
14611 "/",
14612 "/",
14613 "/",
14614 "/...",
14615 "/.foo",
14616 "/.foo.",
14617 "/foo.",
14618 "/foo",
14619 "/foo/baz",
14620 "/",
14621 "/",
14622 "/baz",
14623 "/a/component/path",
14624 "/a/component/path",
14625 "/a/component",
14626 "/a/path",
14627 "/a/path",
14628 NULL
14630 unsigned int i;
14632 for (i = 0; src[i] != NULL; i++) {
14633 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14634 if (d == NULL) {
14635 perror("talloc fail\n");
14636 return false;
14638 if (strcmp(d, dst[i]) != 0) {
14639 d_fprintf(stderr,
14640 "canonicalize mismatch %s -> %s != %s",
14641 src[i], d, dst[i]);
14642 return false;
14644 talloc_free(d);
14646 return true;
14648 struct session_setup_nt1_truncated_state {
14649 uint16_t vwv[13];
14650 uint8_t bytes[20];
14653 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq);
14655 static struct tevent_req *smb1_session_setup_nt1_truncated_send(
14656 TALLOC_CTX *mem_ctx,
14657 struct tevent_context *ev,
14658 struct smbXcli_conn *conn)
14660 uint16_t *vwv = NULL;
14661 uint8_t *bytes = NULL;
14662 const char *pass = "12345678";
14663 const char *uname = "z";
14664 struct session_setup_nt1_truncated_state *state = NULL;
14665 struct tevent_req *req = NULL;
14666 struct tevent_req *subreq = NULL;
14668 req = tevent_req_create(mem_ctx,
14669 &state,
14670 struct session_setup_nt1_truncated_state);
14671 if (req == NULL) {
14672 return NULL;
14674 vwv = &state->vwv[0];
14675 bytes = &state->bytes[0];
14677 SCVAL(vwv+0, 0, 0xff);
14678 SCVAL(vwv+0, 1, 0);
14679 SSVAL(vwv+1, 0, 0);
14680 SSVAL(vwv+2, 0, 8192);
14681 SSVAL(vwv+3, 0, 2);
14682 SSVAL(vwv+4, 0, 1);
14683 SIVAL(vwv+5, 0, 0);
14684 SSVAL(vwv+7, 0, strlen(pass)); /* OEMPasswordLen */
14685 SSVAL(vwv+8, 0, 0); /* UnicodePasswordLen */
14686 SSVAL(vwv+9, 0, 0); /* reserved */
14687 SSVAL(vwv+10, 0, 0); /* reserved */
14688 SIVAL(vwv+11, 0, CAP_STATUS32);
14690 memcpy(bytes, pass, strlen(pass));
14691 bytes += strlen(pass);
14692 memcpy(bytes, uname, strlen(uname)+1);
14694 subreq = smb1cli_req_send(state, ev, conn,
14695 SMBsesssetupX,
14696 0, /* additional_flags */
14697 0, /* clear_flags */
14698 0, /* additional_flags2 */
14699 0, /* clear_flags2 */
14700 10000, /* timeout_msec */
14701 getpid(),
14702 NULL, /* tcon */
14703 NULL, /* session */
14704 13, /* wct */
14705 state->vwv,
14706 strlen(pass), /* Truncate length at password. */
14707 state->bytes);
14708 if (tevent_req_nomem(subreq, req)) {
14709 return tevent_req_post(req, ev);
14711 tevent_req_set_callback(subreq,
14712 smb1_session_setup_nt1_truncated_done,
14713 req);
14714 return req;
14717 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq)
14719 struct tevent_req *req =
14720 tevent_req_callback_data(subreq,
14721 struct tevent_req);
14722 struct session_setup_nt1_truncated_state *state =
14723 tevent_req_data(req,
14724 struct session_setup_nt1_truncated_state);
14725 NTSTATUS status;
14726 struct smb1cli_req_expected_response expected[] = {
14728 .status = NT_STATUS_OK,
14729 .wct = 3,
14733 status = smb1cli_req_recv(subreq, state,
14734 NULL,
14735 NULL,
14736 NULL,
14737 NULL,
14738 NULL, /* pvwv_offset */
14739 NULL,
14740 NULL,
14741 NULL, /* pbytes_offset */
14742 NULL,
14743 expected, ARRAY_SIZE(expected));
14744 TALLOC_FREE(subreq);
14745 if (tevent_req_nterror(req, status)) {
14746 return;
14748 tevent_req_done(req);
14751 static NTSTATUS smb1_session_setup_nt1_truncated_recv(struct tevent_req *req)
14753 return tevent_req_simple_recv_ntstatus(req);
14756 static bool run_smb1_truncated_sesssetup(int dummy)
14758 struct tevent_context *ev;
14759 struct tevent_req *req;
14760 struct smbXcli_conn *conn;
14761 struct sockaddr_storage ss;
14762 NTSTATUS status;
14763 int fd;
14764 bool ok;
14766 printf("Starting send truncated SMB1 sesssetup.\n");
14768 ok = resolve_name(host, &ss, 0x20, true);
14769 if (!ok) {
14770 d_fprintf(stderr, "Could not resolve name %s\n", host);
14771 return false;
14774 status = open_socket_out(&ss, 445, 10000, &fd);
14775 if (!NT_STATUS_IS_OK(status)) {
14776 d_fprintf(stderr, "open_socket_out failed: %s\n",
14777 nt_errstr(status));
14778 return false;
14781 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14782 NULL, 0, NULL);
14783 if (conn == NULL) {
14784 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14785 return false;
14788 status = smbXcli_negprot(conn, 0, PROTOCOL_NT1, PROTOCOL_NT1);
14789 if (!NT_STATUS_IS_OK(status)) {
14790 d_fprintf(stderr, "smbXcli_negprot failed!\n");
14791 return false;
14794 ev = samba_tevent_context_init(talloc_tos());
14795 if (ev == NULL) {
14796 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14797 return false;
14800 req = smb1_session_setup_nt1_truncated_send(ev, ev, conn);
14801 if (req == NULL) {
14802 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_send failed\n");
14803 return false;
14806 ok = tevent_req_poll_ntstatus(req, ev, &status);
14807 if (!ok) {
14808 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
14809 nt_errstr(status));
14810 return false;
14813 status = smb1_session_setup_nt1_truncated_recv(req);
14814 if (!NT_STATUS_IS_OK(status)) {
14815 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_recv returned "
14816 "%s, expected NT_STATUS_OK\n",
14817 nt_errstr(status));
14818 return false;
14821 TALLOC_FREE(conn);
14822 return true;
14825 struct smb1_negotiate_exit_state {
14826 int dummy;
14829 static void smb1_negotiate_exit_done(struct tevent_req *subreq);
14831 static struct tevent_req *smb1_negotiate_exit_send(
14832 TALLOC_CTX *mem_ctx,
14833 struct tevent_context *ev,
14834 struct smbXcli_conn *conn)
14836 struct smb1_negotiate_exit_state *state = NULL;
14837 struct tevent_req *req = NULL;
14838 struct tevent_req *subreq = NULL;
14840 req = tevent_req_create(mem_ctx,
14841 &state,
14842 struct smb1_negotiate_exit_state);
14843 if (req == NULL) {
14844 return NULL;
14846 subreq = smb1cli_req_send(state, ev, conn,
14847 SMBexit,
14848 0, /* additional_flags */
14849 0, /* clear_flags */
14850 0, /* additional_flags2 */
14851 0, /* clear_flags2 */
14852 10000, /* timeout_msec */
14853 getpid(),
14854 NULL, /* tcon */
14855 NULL, /* session */
14856 0, /* wct */
14857 NULL,
14859 NULL);
14860 if (tevent_req_nomem(subreq, req)) {
14861 return tevent_req_post(req, ev);
14863 tevent_req_set_callback(subreq,
14864 smb1_negotiate_exit_done,
14865 req);
14866 return req;
14869 static void smb1_negotiate_exit_done(struct tevent_req *subreq)
14871 struct tevent_req *req =
14872 tevent_req_callback_data(subreq,
14873 struct tevent_req);
14874 struct smb1_negotiate_exit_state *state =
14875 tevent_req_data(req,
14876 struct smb1_negotiate_exit_state);
14877 NTSTATUS status;
14878 struct smb1cli_req_expected_response expected[] = {
14880 .status = NT_STATUS_OK,
14881 .wct = 0,
14885 status = smb1cli_req_recv(subreq, state,
14886 NULL,
14887 NULL,
14888 NULL,
14889 NULL,
14890 NULL, /* pvwv_offset */
14891 NULL,
14892 NULL,
14893 NULL, /* pbytes_offset */
14894 NULL,
14895 expected, ARRAY_SIZE(expected));
14896 TALLOC_FREE(subreq);
14897 if (tevent_req_nterror(req, status)) {
14898 return;
14900 tevent_req_done(req);
14903 static NTSTATUS smb1_negotiate_exit_recv(struct tevent_req *req)
14905 return tevent_req_simple_recv_ntstatus(req);
14908 static bool do_smb1_exit(TALLOC_CTX *mem_ctx,
14909 struct tevent_context *ev,
14910 struct smbXcli_conn *conn)
14912 struct tevent_req *req;
14913 bool ok;
14914 NTSTATUS status;
14915 NTSTATUS expected_status = NT_STATUS_DOS(ERRSRV, ERRinvnid);;
14917 req = smb1_negotiate_exit_send(ev, ev, conn);
14918 if (req == NULL) {
14919 d_fprintf(stderr, "smb1_negotiate_exit_send failed\n");
14920 return false;
14923 ok = tevent_req_poll_ntstatus(req, ev, &status);
14924 if (!ok) {
14925 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
14926 nt_errstr(status));
14927 return false;
14930 status = smb1_negotiate_exit_recv(req);
14931 if (!NT_STATUS_EQUAL(status, expected_status)) {
14932 d_fprintf(stderr, "smb1_negotiate_exit_recv returned "
14933 "%s, expected ERRSRV, ERRinvnid\n",
14934 nt_errstr(status));
14935 return false;
14937 return true;
14940 static bool run_smb1_negotiate_exit(int dummy)
14942 struct tevent_context *ev;
14943 struct smbXcli_conn *conn;
14944 struct sockaddr_storage ss;
14945 NTSTATUS status;
14946 int fd;
14947 bool ok;
14949 printf("Starting send SMB1 negotiate+exit.\n");
14951 ok = resolve_name(host, &ss, 0x20, true);
14952 if (!ok) {
14953 d_fprintf(stderr, "Could not resolve name %s\n", host);
14954 return false;
14957 status = open_socket_out(&ss, 445, 10000, &fd);
14958 if (!NT_STATUS_IS_OK(status)) {
14959 d_fprintf(stderr, "open_socket_out failed: %s\n",
14960 nt_errstr(status));
14961 return false;
14964 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14965 NULL, 0, NULL);
14966 if (conn == NULL) {
14967 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14968 return false;
14971 status = smbXcli_negprot(conn, 0, PROTOCOL_NT1, PROTOCOL_NT1);
14972 if (!NT_STATUS_IS_OK(status)) {
14973 d_fprintf(stderr, "smbXcli_negprot failed!\n");
14974 return false;
14977 ev = samba_tevent_context_init(talloc_tos());
14978 if (ev == NULL) {
14979 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14980 return false;
14984 * Call do_smb1_exit twice to catch a server crash, the
14985 * server sends the first return code then crashes.
14987 ok = do_smb1_exit(ev, ev, conn);
14988 if (!ok) {
14989 d_fprintf(stderr, "do_smb1_exit (1) failed\n");
14990 return false;
14992 ok = do_smb1_exit(ev, ev, conn);
14993 if (!ok) {
14994 d_fprintf(stderr, "do_smb1_exit (2) failed\n");
14995 return false;
14998 TALLOC_FREE(conn);
14999 return true;
15002 static bool run_ign_bad_negprot(int dummy)
15004 struct tevent_context *ev;
15005 struct tevent_req *req;
15006 struct smbXcli_conn *conn;
15007 struct sockaddr_storage ss;
15008 NTSTATUS status;
15009 int fd;
15010 bool ok;
15012 printf("starting ignore bad negprot\n");
15014 ok = resolve_name(host, &ss, 0x20, true);
15015 if (!ok) {
15016 d_fprintf(stderr, "Could not resolve name %s\n", host);
15017 return false;
15020 status = open_socket_out(&ss, 445, 10000, &fd);
15021 if (!NT_STATUS_IS_OK(status)) {
15022 d_fprintf(stderr, "open_socket_out failed: %s\n",
15023 nt_errstr(status));
15024 return false;
15027 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15028 NULL, 0, NULL);
15029 if (conn == NULL) {
15030 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15031 return false;
15034 status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
15035 if (NT_STATUS_IS_OK(status)) {
15036 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
15037 return false;
15040 ev = samba_tevent_context_init(talloc_tos());
15041 if (ev == NULL) {
15042 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15043 return false;
15046 req = smb1cli_session_setup_nt1_send(
15047 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
15048 data_blob_null, data_blob_null, 0x40,
15049 "Windows 2000 2195", "Windows 2000 5.0");
15050 if (req == NULL) {
15051 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
15052 return false;
15055 ok = tevent_req_poll_ntstatus(req, ev, &status);
15056 if (!ok) {
15057 d_fprintf(stderr, "tevent_req_poll failed\n");
15058 return false;
15061 status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
15062 NULL, NULL);
15063 if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
15064 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
15065 "%s, expected NT_STATUS_CONNECTION_RESET\n",
15066 nt_errstr(status));
15067 return false;
15070 TALLOC_FREE(conn);
15072 printf("starting ignore bad negprot\n");
15074 return true;
15078 static double create_procs(bool (*fn)(int), bool *result)
15080 int i, status;
15081 volatile pid_t *child_status;
15082 volatile bool *child_status_out;
15083 int synccount;
15084 int tries = 8;
15085 struct timeval start;
15087 synccount = 0;
15089 child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
15090 if (!child_status) {
15091 printf("Failed to setup shared memory\n");
15092 return -1;
15095 child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
15096 if (!child_status_out) {
15097 printf("Failed to setup result status shared memory\n");
15098 return -1;
15101 for (i = 0; i < torture_nprocs; i++) {
15102 child_status[i] = 0;
15103 child_status_out[i] = True;
15106 start = timeval_current();
15108 for (i=0;i<torture_nprocs;i++) {
15109 procnum = i;
15110 if (fork() == 0) {
15111 pid_t mypid = getpid();
15112 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
15114 slprintf(myname,sizeof(myname),"CLIENT%d", i);
15116 while (1) {
15117 if (torture_open_connection(&current_cli, i)) break;
15118 if (tries-- == 0) {
15119 printf("pid %d failed to start\n", (int)getpid());
15120 _exit(1);
15122 smb_msleep(10);
15125 child_status[i] = getpid();
15127 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
15129 child_status_out[i] = fn(i);
15130 _exit(0);
15134 do {
15135 synccount = 0;
15136 for (i=0;i<torture_nprocs;i++) {
15137 if (child_status[i]) synccount++;
15139 if (synccount == torture_nprocs) break;
15140 smb_msleep(10);
15141 } while (timeval_elapsed(&start) < 30);
15143 if (synccount != torture_nprocs) {
15144 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
15145 *result = False;
15146 return timeval_elapsed(&start);
15149 /* start the client load */
15150 start = timeval_current();
15152 for (i=0;i<torture_nprocs;i++) {
15153 child_status[i] = 0;
15156 printf("%d clients started\n", torture_nprocs);
15158 for (i=0;i<torture_nprocs;i++) {
15159 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
15162 printf("\n");
15164 for (i=0;i<torture_nprocs;i++) {
15165 if (!child_status_out[i]) {
15166 *result = False;
15169 return timeval_elapsed(&start);
15172 #define FLAG_MULTIPROC 1
15174 static struct {
15175 const char *name;
15176 bool (*fn)(int);
15177 unsigned flags;
15178 } torture_ops[] = {
15180 .name = "FDPASS",
15181 .fn = run_fdpasstest,
15184 .name = "LOCK1",
15185 .fn = run_locktest1,
15188 .name = "LOCK2",
15189 .fn = run_locktest2,
15192 .name = "LOCK3",
15193 .fn = run_locktest3,
15196 .name = "LOCK4",
15197 .fn = run_locktest4,
15200 .name = "LOCK5",
15201 .fn = run_locktest5,
15204 .name = "LOCK6",
15205 .fn = run_locktest6,
15208 .name = "LOCK7",
15209 .fn = run_locktest7,
15212 .name = "LOCK8",
15213 .fn = run_locktest8,
15216 .name = "LOCK9A",
15217 .fn = run_locktest9a,
15220 .name = "LOCK9B",
15221 .fn = run_locktest9b,
15224 .name = "LOCK10",
15225 .fn = run_locktest10,
15228 .name = "LOCK11",
15229 .fn = run_locktest11,
15232 .name = "LOCK12",
15233 .fn = run_locktest12,
15236 .name = "LOCK13",
15237 .fn = run_locktest13,
15240 .name = "UNLINK",
15241 .fn = run_unlinktest,
15244 .name = "BROWSE",
15245 .fn = run_browsetest,
15248 .name = "ATTR",
15249 .fn = run_attrtest,
15252 .name = "TRANS2",
15253 .fn = run_trans2test,
15256 .name = "MAXFID",
15257 .fn = run_maxfidtest,
15258 .flags = FLAG_MULTIPROC,
15261 .name = "TORTURE",
15262 .fn = run_torture,
15263 .flags = FLAG_MULTIPROC,
15266 .name = "RANDOMIPC",
15267 .fn = run_randomipc,
15270 .name = "NEGNOWAIT",
15271 .fn = run_negprot_nowait,
15274 .name = "NBENCH",
15275 .fn = run_nbench,
15278 .name = "NBENCH2",
15279 .fn = run_nbench2,
15282 .name = "OPLOCK1",
15283 .fn = run_oplock1,
15286 .name = "OPLOCK2",
15287 .fn = run_oplock2,
15290 .name = "OPLOCK4",
15291 .fn = run_oplock4,
15293 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
15295 .name = "OPLOCK5",
15296 .fn = run_oplock5,
15298 #endif
15300 .name = "DIR",
15301 .fn = run_dirtest,
15304 .name = "DIR1",
15305 .fn = run_dirtest1,
15308 .name = "DIR-CREATETIME",
15309 .fn = run_dir_createtime,
15312 .name = "DENY1",
15313 .fn = torture_denytest1,
15316 .name = "DENY2",
15317 .fn = torture_denytest2,
15320 .name = "TCON",
15321 .fn = run_tcon_test,
15324 .name = "TCONDEV",
15325 .fn = run_tcon_devtype_test,
15328 .name = "RW1",
15329 .fn = run_readwritetest,
15332 .name = "RW2",
15333 .fn = run_readwritemulti,
15334 .flags = FLAG_MULTIPROC
15337 .name = "RW3",
15338 .fn = run_readwritelarge,
15341 .name = "RW-SIGNING",
15342 .fn = run_readwritelarge_signtest,
15345 .name = "OPEN",
15346 .fn = run_opentest,
15349 .name = "POSIX",
15350 .fn = run_simple_posix_open_test,
15353 .name = "POSIX-APPEND",
15354 .fn = run_posix_append,
15357 .name = "POSIX-SYMLINK-ACL",
15358 .fn = run_acl_symlink_test,
15361 .name = "POSIX-SYMLINK-EA",
15362 .fn = run_ea_symlink_test,
15365 .name = "POSIX-STREAM-DELETE",
15366 .fn = run_posix_stream_delete,
15369 .name = "POSIX-OFD-LOCK",
15370 .fn = run_posix_ofd_lock_test,
15373 .name = "POSIX-BLOCKING-LOCK",
15374 .fn = run_posix_blocking_lock,
15377 .name = "POSIX-MKDIR",
15378 .fn = run_posix_mkdir_test,
15381 .name = "POSIX-ACL-OPLOCK",
15382 .fn = run_posix_acl_oplock_test,
15385 .name = "POSIX-ACL-SHAREROOT",
15386 .fn = run_posix_acl_shareroot_test,
15389 .name = "POSIX-LS-WILDCARD",
15390 .fn = run_posix_ls_wildcard_test,
15393 .name = "POSIX-LS-SINGLE",
15394 .fn = run_posix_ls_single_test,
15397 .name = "POSIX-READLINK",
15398 .fn = run_posix_readlink_test,
15401 .name = "POSIX-STAT",
15402 .fn = run_posix_stat_test,
15405 .name = "POSIX-SYMLINK-PARENT",
15406 .fn = run_posix_symlink_parent_test,
15409 .name = "POSIX-SYMLINK-CHMOD",
15410 .fn = run_posix_symlink_chmod_test,
15413 .name = "POSIX-SYMLINK-RENAME",
15414 .fn = run_posix_symlink_rename_test,
15417 .name = "POSIX-DIR-DEFAULT-ACL",
15418 .fn = run_posix_dir_default_acl_test,
15421 .name = "POSIX-SYMLINK-GETPATHINFO",
15422 .fn = run_posix_symlink_getpathinfo_test,
15425 .name = "POSIX-SYMLINK-SETPATHINFO",
15426 .fn = run_posix_symlink_setpathinfo_test,
15429 .name = "WINDOWS-BAD-SYMLINK",
15430 .fn = run_symlink_open_test,
15433 .name = "SMB1-WILD-MANGLE-UNLINK",
15434 .fn = run_smb1_wild_mangle_unlink_test,
15437 .name = "SMB1-WILD-MANGLE-RENAME",
15438 .fn = run_smb1_wild_mangle_rename_test,
15441 .name = "CASE-INSENSITIVE-CREATE",
15442 .fn = run_case_insensitive_create,
15445 .name = "ASYNC-ECHO",
15446 .fn = run_async_echo,
15449 .name = "UID-REGRESSION-TEST",
15450 .fn = run_uid_regression_test,
15453 .name = "SHORTNAME-TEST",
15454 .fn = run_shortname_test,
15457 .name = "ADDRCHANGE",
15458 .fn = run_addrchange,
15460 #if 1
15462 .name = "OPENATTR",
15463 .fn = run_openattrtest,
15465 #endif
15467 .name = "XCOPY",
15468 .fn = run_xcopy,
15471 .name = "RENAME",
15472 .fn = run_rename,
15475 .name = "RENAME-ACCESS",
15476 .fn = run_rename_access,
15479 .name = "OWNER-RIGHTS",
15480 .fn = run_owner_rights,
15483 .name = "DELETE",
15484 .fn = run_deletetest,
15487 .name = "DELETE-STREAM",
15488 .fn = run_delete_stream,
15491 .name = "DELETE-PRINT",
15492 .fn = run_delete_print_test,
15495 .name = "DELETE-LN",
15496 .fn = run_deletetest_ln,
15499 .name = "PROPERTIES",
15500 .fn = run_properties,
15503 .name = "MANGLE",
15504 .fn = torture_mangle,
15507 .name = "MANGLE1",
15508 .fn = run_mangle1,
15511 .name = "MANGLE-ILLEGAL",
15512 .fn = run_mangle_illegal,
15515 .name = "W2K",
15516 .fn = run_w2ktest,
15519 .name = "TRANS2SCAN",
15520 .fn = torture_trans2_scan,
15523 .name = "NTTRANSSCAN",
15524 .fn = torture_nttrans_scan,
15527 .name = "UTABLE",
15528 .fn = torture_utable,
15531 .name = "CASETABLE",
15532 .fn = torture_casetable,
15535 .name = "ERRMAPEXTRACT",
15536 .fn = run_error_map_extract,
15539 .name = "PIPE_NUMBER",
15540 .fn = run_pipe_number,
15543 .name = "TCON2",
15544 .fn = run_tcon2_test,
15547 .name = "IOCTL",
15548 .fn = torture_ioctl_test,
15551 .name = "CHKPATH",
15552 .fn = torture_chkpath_test,
15555 .name = "FDSESS",
15556 .fn = run_fdsesstest,
15559 .name = "EATEST",
15560 .fn = run_eatest,
15563 .name = "SESSSETUP_BENCH",
15564 .fn = run_sesssetup_bench,
15567 .name = "CHAIN1",
15568 .fn = run_chain1,
15571 .name = "CHAIN2",
15572 .fn = run_chain2,
15575 .name = "CHAIN3",
15576 .fn = run_chain3,
15579 .name = "WINDOWS-WRITE",
15580 .fn = run_windows_write,
15583 .name = "LARGE_READX",
15584 .fn = run_large_readx,
15587 .name = "MSDFS-ATTRIBUTE",
15588 .fn = run_msdfs_attribute,
15591 .name = "NTTRANS-CREATE",
15592 .fn = run_nttrans_create,
15595 .name = "NTTRANS-FSCTL",
15596 .fn = run_nttrans_fsctl,
15599 .name = "CLI_ECHO",
15600 .fn = run_cli_echo,
15603 .name = "CLI_SPLICE",
15604 .fn = run_cli_splice,
15607 .name = "TLDAP",
15608 .fn = run_tldap,
15611 .name = "STREAMERROR",
15612 .fn = run_streamerror,
15615 .name = "NOTIFY-BENCH",
15616 .fn = run_notify_bench,
15619 .name = "NOTIFY-BENCH2",
15620 .fn = run_notify_bench2,
15623 .name = "NOTIFY-BENCH3",
15624 .fn = run_notify_bench3,
15627 .name = "BAD-NBT-SESSION",
15628 .fn = run_bad_nbt_session,
15631 .name = "IGN-BAD-NEGPROT",
15632 .fn = run_ign_bad_negprot,
15635 .name = "SMB-ANY-CONNECT",
15636 .fn = run_smb_any_connect,
15639 .name = "NOTIFY-ONLINE",
15640 .fn = run_notify_online,
15643 .name = "SMB2-BASIC",
15644 .fn = run_smb2_basic,
15647 .name = "SMB2-NEGPROT",
15648 .fn = run_smb2_negprot,
15651 .name = "SMB2-ANONYMOUS",
15652 .fn = run_smb2_anonymous,
15655 .name = "SMB2-SESSION-RECONNECT",
15656 .fn = run_smb2_session_reconnect,
15659 .name = "SMB2-TCON-DEPENDENCE",
15660 .fn = run_smb2_tcon_dependence,
15663 .name = "SMB2-MULTI-CHANNEL",
15664 .fn = run_smb2_multi_channel,
15667 .name = "SMB2-SESSION-REAUTH",
15668 .fn = run_smb2_session_reauth,
15671 .name = "SMB2-FTRUNCATE",
15672 .fn = run_smb2_ftruncate,
15675 .name = "SMB2-DIR-FSYNC",
15676 .fn = run_smb2_dir_fsync,
15679 .name = "SMB2-PATH-SLASH",
15680 .fn = run_smb2_path_slash,
15683 .name = "SMB1-SYSTEM-SECURITY",
15684 .fn = run_smb1_system_security,
15687 .name = "SMB2-SACL",
15688 .fn = run_smb2_sacl,
15691 .name = "SMB2-QUOTA1",
15692 .fn = run_smb2_quota1,
15695 .name = "SMB2-STREAM-ACL",
15696 .fn = run_smb2_stream_acl,
15699 .name = "SMB2-LIST-DIR-ASYNC",
15700 .fn = run_list_dir_async_test,
15703 .name = "SMB2-DEL-ON-CLOSE-NONEMPTY",
15704 .fn = run_delete_on_close_non_empty,
15707 .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15708 .fn = run_delete_on_close_nonwrite_delete_yes_test,
15711 .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15712 .fn = run_delete_on_close_nonwrite_delete_no_test,
15715 .name = "SMB2-DFS-PATHS",
15716 .fn = run_smb2_dfs_paths,
15719 .name = "SMB2-NON-DFS-SHARE",
15720 .fn = run_smb2_non_dfs_share,
15723 .name = "SMB2-DFS-SHARE-NON-DFS-PATH",
15724 .fn = run_smb2_dfs_share_non_dfs_path,
15727 .name = "SMB2-DFS-FILENAME-LEADING-BACKSLASH",
15728 .fn = run_smb2_dfs_filename_leading_backslash,
15731 .name = "SMB1-TRUNCATED-SESSSETUP",
15732 .fn = run_smb1_truncated_sesssetup,
15735 .name = "SMB1-NEGOTIATE-EXIT",
15736 .fn = run_smb1_negotiate_exit,
15739 .name = "SMB1-DFS-PATHS",
15740 .fn = run_smb1_dfs_paths,
15743 .name = "SMB1-DFS-SEARCH-PATHS",
15744 .fn = run_smb1_dfs_search_paths,
15747 .name = "SMB1-DFS-OPERATIONS",
15748 .fn = run_smb1_dfs_operations,
15751 .name = "SMB1-DFS-BADPATH",
15752 .fn = run_smb1_dfs_check_badpath,
15755 .name = "CLEANUP1",
15756 .fn = run_cleanup1,
15759 .name = "CLEANUP2",
15760 .fn = run_cleanup2,
15763 .name = "CLEANUP4",
15764 .fn = run_cleanup4,
15767 .name = "OPLOCK-CANCEL",
15768 .fn = run_oplock_cancel,
15771 .name = "PIDHIGH",
15772 .fn = run_pidhigh,
15775 .name = "LOCAL-SUBSTITUTE",
15776 .fn = run_local_substitute,
15779 .name = "LOCAL-GENCACHE",
15780 .fn = run_local_gencache,
15783 .name = "LOCAL-DBWRAP-WATCH1",
15784 .fn = run_dbwrap_watch1,
15787 .name = "LOCAL-DBWRAP-WATCH2",
15788 .fn = run_dbwrap_watch2,
15791 .name = "LOCAL-DBWRAP-WATCH3",
15792 .fn = run_dbwrap_watch3,
15795 .name = "LOCAL-DBWRAP-WATCH4",
15796 .fn = run_dbwrap_watch4,
15799 .name = "LOCAL-DBWRAP-DO-LOCKED1",
15800 .fn = run_dbwrap_do_locked1,
15803 .name = "LOCAL-MESSAGING-READ1",
15804 .fn = run_messaging_read1,
15807 .name = "LOCAL-MESSAGING-READ2",
15808 .fn = run_messaging_read2,
15811 .name = "LOCAL-MESSAGING-READ3",
15812 .fn = run_messaging_read3,
15815 .name = "LOCAL-MESSAGING-READ4",
15816 .fn = run_messaging_read4,
15819 .name = "LOCAL-MESSAGING-FDPASS1",
15820 .fn = run_messaging_fdpass1,
15823 .name = "LOCAL-MESSAGING-FDPASS2",
15824 .fn = run_messaging_fdpass2,
15827 .name = "LOCAL-MESSAGING-FDPASS2a",
15828 .fn = run_messaging_fdpass2a,
15831 .name = "LOCAL-MESSAGING-FDPASS2b",
15832 .fn = run_messaging_fdpass2b,
15835 .name = "LOCAL-MESSAGING-SEND-ALL",
15836 .fn = run_messaging_send_all,
15839 .name = "LOCAL-BASE64",
15840 .fn = run_local_base64,
15843 .name = "LOCAL-RBTREE",
15844 .fn = run_local_rbtree,
15847 .name = "LOCAL-MEMCACHE",
15848 .fn = run_local_memcache,
15851 .name = "LOCAL-STREAM-NAME",
15852 .fn = run_local_stream_name,
15855 .name = "LOCAL-STR-MATCH-MSWILD",
15856 .fn = run_str_match_mswild,
15859 .name = "LOCAL-STR-MATCH-REGEX-SUB1",
15860 .fn = run_str_match_regex_sub1,
15863 .name = "WBCLIENT-MULTI-PING",
15864 .fn = run_wbclient_multi_ping,
15867 .name = "LOCAL-string_to_sid",
15868 .fn = run_local_string_to_sid,
15871 .name = "LOCAL-sid_to_string",
15872 .fn = run_local_sid_to_string,
15875 .name = "LOCAL-binary_to_sid",
15876 .fn = run_local_binary_to_sid,
15879 .name = "LOCAL-DBTRANS",
15880 .fn = run_local_dbtrans,
15883 .name = "LOCAL-TEVENT-POLL",
15884 .fn = run_local_tevent_poll,
15887 .name = "LOCAL-CONVERT-STRING",
15888 .fn = run_local_convert_string,
15891 .name = "LOCAL-CONV-AUTH-INFO",
15892 .fn = run_local_conv_auth_info,
15895 .name = "LOCAL-hex_encode_buf",
15896 .fn = run_local_hex_encode_buf,
15899 .name = "LOCAL-IDMAP-TDB-COMMON",
15900 .fn = run_idmap_tdb_common_test,
15903 .name = "LOCAL-remove_duplicate_addrs2",
15904 .fn = run_local_remove_duplicate_addrs2,
15907 .name = "local-tdb-opener",
15908 .fn = run_local_tdb_opener,
15911 .name = "local-tdb-writer",
15912 .fn = run_local_tdb_writer,
15915 .name = "LOCAL-DBWRAP-CTDB1",
15916 .fn = run_local_dbwrap_ctdb1,
15919 .name = "LOCAL-BENCH-PTHREADPOOL",
15920 .fn = run_bench_pthreadpool,
15923 .name = "LOCAL-PTHREADPOOL-TEVENT",
15924 .fn = run_pthreadpool_tevent,
15927 .name = "LOCAL-G-LOCK1",
15928 .fn = run_g_lock1,
15931 .name = "LOCAL-G-LOCK2",
15932 .fn = run_g_lock2,
15935 .name = "LOCAL-G-LOCK3",
15936 .fn = run_g_lock3,
15939 .name = "LOCAL-G-LOCK4",
15940 .fn = run_g_lock4,
15943 .name = "LOCAL-G-LOCK4A",
15944 .fn = run_g_lock4a,
15947 .name = "LOCAL-G-LOCK5",
15948 .fn = run_g_lock5,
15951 .name = "LOCAL-G-LOCK6",
15952 .fn = run_g_lock6,
15955 .name = "LOCAL-G-LOCK7",
15956 .fn = run_g_lock7,
15959 .name = "LOCAL-G-LOCK8",
15960 .fn = run_g_lock8,
15963 .name = "LOCAL-G-LOCK-PING-PONG",
15964 .fn = run_g_lock_ping_pong,
15967 .name = "LOCAL-CANONICALIZE-PATH",
15968 .fn = run_local_canonicalize_path,
15971 .name = "LOCAL-NAMEMAP-CACHE1",
15972 .fn = run_local_namemap_cache1,
15975 .name = "LOCAL-IDMAP-CACHE1",
15976 .fn = run_local_idmap_cache1,
15979 .name = "qpathinfo-bufsize",
15980 .fn = run_qpathinfo_bufsize,
15983 .name = "hide-new-files-timeout",
15984 .fn = run_hidenewfiles,
15987 .name = "hide-new-files-timeout-showdirs",
15988 .fn = run_hidenewfiles_showdirs,
15990 #ifdef CLUSTER_SUPPORT
15992 .name = "ctdbd-conn1",
15993 .fn = run_ctdbd_conn1,
15995 #endif
15997 .name = "readdir-timestamp",
15998 .fn = run_readdir_timestamp,
16001 .name = "rpc-scale",
16002 .fn = run_rpc_scale,
16005 .name = "LOCAL-TDB-VALIDATE",
16006 .fn = run_tdb_validate,
16009 .name = NULL,
16013 /****************************************************************************
16014 run a specified test or "ALL"
16015 ****************************************************************************/
16016 static bool run_test(const char *name)
16018 bool ret = True;
16019 bool result = True;
16020 bool found = False;
16021 int i;
16022 double t;
16023 if (strequal(name,"ALL")) {
16024 for (i=0;torture_ops[i].name;i++) {
16025 run_test(torture_ops[i].name);
16027 found = True;
16030 for (i=0;torture_ops[i].name;i++) {
16031 fstr_sprintf(randomfname, "\\XX%x",
16032 (unsigned)random());
16034 if (strequal(name, torture_ops[i].name)) {
16035 found = True;
16036 printf("Running %s\n", name);
16037 if (torture_ops[i].flags & FLAG_MULTIPROC) {
16038 t = create_procs(torture_ops[i].fn, &result);
16039 if (!result) {
16040 ret = False;
16041 printf("TEST %s FAILED!\n", name);
16043 } else {
16044 struct timeval start;
16045 start = timeval_current();
16046 if (!torture_ops[i].fn(0)) {
16047 ret = False;
16048 printf("TEST %s FAILED!\n", name);
16050 t = timeval_elapsed(&start);
16052 printf("%s took %g secs\n\n", name, t);
16056 if (!found) {
16057 printf("Did not find a test named %s\n", name);
16058 ret = False;
16061 return ret;
16065 static void usage(void)
16067 int i;
16069 printf("WARNING samba4 test suite is much more complete nowadays.\n");
16070 printf("Please use samba4 torture.\n\n");
16072 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
16074 printf("\t-d debuglevel\n");
16075 printf("\t-U user%%pass\n");
16076 printf("\t-k use kerberos\n");
16077 printf("\t-N numprocs\n");
16078 printf("\t-n my_netbios_name\n");
16079 printf("\t-W workgroup\n");
16080 printf("\t-o num_operations\n");
16081 printf("\t-O socket_options\n");
16082 printf("\t-m maximum protocol\n");
16083 printf("\t-L use oplocks\n");
16084 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
16085 printf("\t-A showall\n");
16086 printf("\t-p port\n");
16087 printf("\t-s seed\n");
16088 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
16089 printf("\t-f filename filename to test\n");
16090 printf("\t-e encrypt\n");
16091 printf("\n\n");
16093 printf("tests are:");
16094 for (i=0;torture_ops[i].name;i++) {
16095 printf(" %s", torture_ops[i].name);
16097 printf("\n");
16099 printf("default test is ALL\n");
16101 exit(1);
16104 /****************************************************************************
16105 main program
16106 ****************************************************************************/
16107 int main(int argc,char *argv[])
16109 int opt, i;
16110 char *p;
16111 int gotuser = 0;
16112 int gotpass = 0;
16113 bool correct = True;
16114 TALLOC_CTX *frame = talloc_stackframe();
16115 int seed = time(NULL);
16117 #ifdef HAVE_SETBUFFER
16118 setbuffer(stdout, NULL, 0);
16119 #endif
16121 setup_logging("smbtorture", DEBUG_STDOUT);
16123 smb_init_locale();
16124 fault_setup();
16126 if (is_default_dyn_CONFIGFILE()) {
16127 if(getenv("SMB_CONF_PATH")) {
16128 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
16131 lp_load_global(get_dyn_CONFIGFILE());
16132 load_interfaces();
16134 if (argc < 2) {
16135 usage();
16138 for(p = argv[1]; *p; p++)
16139 if(*p == '\\')
16140 *p = '/';
16142 if (strncmp(argv[1], "//", 2)) {
16143 usage();
16146 fstrcpy(host, &argv[1][2]);
16147 p = strchr_m(&host[2],'/');
16148 if (!p) {
16149 usage();
16151 *p = 0;
16152 fstrcpy(share, p+1);
16154 fstrcpy(myname, get_myname(talloc_tos()));
16155 if (!*myname) {
16156 fprintf(stderr, "Failed to get my hostname.\n");
16157 return 1;
16160 if (*username == 0 && getenv("LOGNAME")) {
16161 fstrcpy(username,getenv("LOGNAME"));
16164 argc--;
16165 argv++;
16167 fstrcpy(workgroup, lp_workgroup());
16169 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
16170 != EOF) {
16171 switch (opt) {
16172 case 'p':
16173 port_to_use = atoi(optarg);
16174 break;
16175 case 's':
16176 seed = atoi(optarg);
16177 break;
16178 case 'W':
16179 fstrcpy(workgroup,optarg);
16180 break;
16181 case 'm':
16182 lp_set_cmdline("client max protocol", optarg);
16183 break;
16184 case 'N':
16185 torture_nprocs = atoi(optarg);
16186 break;
16187 case 'o':
16188 torture_numops = atoi(optarg);
16189 break;
16190 case 'd':
16191 lp_set_cmdline("log level", optarg);
16192 break;
16193 case 'O':
16194 sockops = optarg;
16195 break;
16196 case 'L':
16197 use_oplocks = True;
16198 break;
16199 case 'l':
16200 local_path = optarg;
16201 break;
16202 case 'A':
16203 torture_showall = True;
16204 break;
16205 case 'n':
16206 fstrcpy(myname, optarg);
16207 break;
16208 case 'c':
16209 client_txt = optarg;
16210 break;
16211 case 'e':
16212 do_encrypt = true;
16213 break;
16214 case 'k':
16215 #ifdef HAVE_KRB5
16216 use_kerberos = True;
16217 #else
16218 d_printf("No kerberos support compiled in\n");
16219 exit(1);
16220 #endif
16221 break;
16222 case 'U':
16223 gotuser = 1;
16224 fstrcpy(username,optarg);
16225 p = strchr_m(username,'%');
16226 if (p) {
16227 *p = 0;
16228 fstrcpy(password, p+1);
16229 gotpass = 1;
16231 break;
16232 case 'b':
16233 fstrcpy(multishare_conn_fname, optarg);
16234 use_multishare_conn = True;
16235 break;
16236 case 'B':
16237 torture_blocksize = atoi(optarg);
16238 break;
16239 case 'f':
16240 test_filename = SMB_STRDUP(optarg);
16241 break;
16242 default:
16243 printf("Unknown option %c (%d)\n", (char)opt, opt);
16244 usage();
16248 d_printf("using seed %d\n", seed);
16250 srandom(seed);
16252 if(use_kerberos && !gotuser) gotpass = True;
16254 while (!gotpass) {
16255 char pwd[256] = {0};
16256 int rc;
16258 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
16259 if (rc == 0) {
16260 fstrcpy(password, pwd);
16261 gotpass = 1;
16265 printf("host=%s share=%s user=%s myname=%s\n",
16266 host, share, username, myname);
16268 torture_creds = cli_session_creds_init(frame,
16269 username,
16270 workgroup,
16271 NULL, /* realm */
16272 password,
16273 use_kerberos,
16274 false, /* fallback_after_kerberos */
16275 false, /* use_ccache */
16276 false); /* password_is_nt_hash */
16277 if (torture_creds == NULL) {
16278 d_printf("cli_session_creds_init() failed.\n");
16279 exit(1);
16282 if (argc == optind) {
16283 correct = run_test("ALL");
16284 } else {
16285 for (i=optind;i<argc;i++) {
16286 if (!run_test(argv[i])) {
16287 correct = False;
16292 TALLOC_FREE(frame);
16294 if (correct) {
16295 return(0);
16296 } else {
16297 return(1);