ctdb-tool: Remove old ctdb tool
[Samba.git] / source3 / torture / torture.c
blobf9766bbf1b2f2537cb2e20fc010ca960b7774ba1
1 /*
2 Unix SMB/CIFS implementation.
3 SMB torture tester
4 Copyright (C) Andrew Tridgell 1997-1998
5 Copyright (C) Jeremy Allison 2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "system/shmem.h"
23 #include "wbc_async.h"
24 #include "torture/proto.h"
25 #include "libcli/security/security.h"
26 #include "tldap.h"
27 #include "tldap_util.h"
28 #include "../librpc/gen_ndr/svcctl.h"
29 #include "../lib/util/memcache.h"
30 #include "nsswitch/winbind_client.h"
31 #include "dbwrap/dbwrap.h"
32 #include "dbwrap/dbwrap_open.h"
33 #include "dbwrap/dbwrap_rbt.h"
34 #include "talloc_dict.h"
35 #include "async_smb.h"
36 #include "libsmb/libsmb.h"
37 #include "libsmb/clirap.h"
38 #include "trans2.h"
39 #include "libsmb/nmblib.h"
40 #include "../lib/util/tevent_ntstatus.h"
41 #include "util_tdb.h"
42 #include "../libcli/smb/read_smb.h"
43 #include "../libcli/smb/smbXcli_base.h"
44 #include "lib/util/sys_rw_data.h"
45 #include "lib/util/base64.h"
47 extern char *optarg;
48 extern int optind;
50 fstring host, workgroup, share, password, username, myname;
51 static const char *sockops="TCP_NODELAY";
52 int torture_nprocs=1;
53 static int port_to_use=0;
54 int torture_numops=100;
55 int torture_blocksize=1024*1024;
56 static int procnum; /* records process count number when forking */
57 static struct cli_state *current_cli;
58 static fstring randomfname;
59 static bool use_oplocks;
60 static bool use_level_II_oplocks;
61 static const char *client_txt = "client_oplocks.txt";
62 static bool disable_spnego;
63 static bool use_kerberos;
64 static bool force_dos_errors;
65 static fstring multishare_conn_fname;
66 static bool use_multishare_conn = False;
67 static bool do_encrypt;
68 static const char *local_path = NULL;
69 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
70 char *test_filename;
72 bool torture_showall = False;
74 static double create_procs(bool (*fn)(int), bool *result);
76 /********************************************************************
77 Ensure a connection is encrypted.
78 ********************************************************************/
80 static bool force_cli_encryption(struct cli_state *c,
81 const char *sharename)
83 uint16_t major, minor;
84 uint32_t caplow, caphigh;
85 NTSTATUS status;
87 if (!SERVER_HAS_UNIX_CIFS(c)) {
88 d_printf("Encryption required and "
89 "server that doesn't support "
90 "UNIX extensions - failing connect\n");
91 return false;
94 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
95 &caphigh);
96 if (!NT_STATUS_IS_OK(status)) {
97 d_printf("Encryption required and "
98 "can't get UNIX CIFS extensions "
99 "version from server: %s\n", nt_errstr(status));
100 return false;
103 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
104 d_printf("Encryption required and "
105 "share %s doesn't support "
106 "encryption.\n", sharename);
107 return false;
110 if (c->use_kerberos) {
111 status = cli_gss_smb_encryption_start(c);
112 } else {
113 status = cli_raw_ntlm_smb_encryption_start(c,
114 username,
115 password,
116 workgroup);
119 if (!NT_STATUS_IS_OK(status)) {
120 d_printf("Encryption required and "
121 "setup failed with error %s.\n",
122 nt_errstr(status));
123 return false;
126 return true;
130 static struct cli_state *open_nbt_connection(void)
132 struct cli_state *c;
133 NTSTATUS status;
134 int flags = 0;
136 if (disable_spnego) {
137 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
140 if (use_oplocks) {
141 flags |= CLI_FULL_CONNECTION_OPLOCKS;
144 if (use_level_II_oplocks) {
145 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
148 if (use_kerberos) {
149 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
152 if (force_dos_errors) {
153 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
156 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
157 signing_state, flags, &c);
158 if (!NT_STATUS_IS_OK(status)) {
159 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
160 return NULL;
163 cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
165 return c;
168 /****************************************************************************
169 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
170 ****************************************************************************/
172 static bool cli_bad_session_request(int fd,
173 struct nmb_name *calling, struct nmb_name *called)
175 TALLOC_CTX *frame;
176 uint8_t len_buf[4];
177 struct iovec iov[3];
178 ssize_t len;
179 uint8_t *inbuf;
180 int err;
181 bool ret = false;
182 uint8_t message_type;
183 uint8_t error;
184 struct tevent_context *ev;
185 struct tevent_req *req;
187 frame = talloc_stackframe();
189 iov[0].iov_base = len_buf;
190 iov[0].iov_len = sizeof(len_buf);
192 /* put in the destination name */
194 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
195 called->name_type);
196 if (iov[1].iov_base == NULL) {
197 goto fail;
199 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
200 talloc_get_size(iov[1].iov_base));
202 /* and my name */
204 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
205 calling->name_type);
206 if (iov[2].iov_base == NULL) {
207 goto fail;
209 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
210 talloc_get_size(iov[2].iov_base));
212 /* Deliberately corrupt the name len (first byte) */
213 *((uint8_t *)iov[2].iov_base) = 100;
215 /* send a session request (RFC 1002) */
216 /* setup the packet length
217 * Remove four bytes from the length count, since the length
218 * field in the NBT Session Service header counts the number
219 * of bytes which follow. The cli_send_smb() function knows
220 * about this and accounts for those four bytes.
221 * CRH.
224 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
225 SCVAL(len_buf,0,0x81);
227 len = write_data_iov(fd, iov, 3);
228 if (len == -1) {
229 goto fail;
232 ev = samba_tevent_context_init(frame);
233 if (ev == NULL) {
234 goto fail;
236 req = read_smb_send(frame, ev, fd);
237 if (req == NULL) {
238 goto fail;
240 if (!tevent_req_poll(req, ev)) {
241 goto fail;
243 len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
244 if (len == -1) {
245 errno = err;
246 goto fail;
248 TALLOC_FREE(ev);
250 message_type = CVAL(inbuf, 0);
251 if (message_type != 0x83) {
252 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
253 message_type);
254 goto fail;
257 if (smb_len(inbuf) != 1) {
258 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
259 (int)smb_len(inbuf));
260 goto fail;
263 error = CVAL(inbuf, 4);
264 if (error != 0x82) {
265 d_fprintf(stderr, "Expected error 0x82, got %d\n",
266 (int)error);
267 goto fail;
270 ret = true;
271 fail:
272 TALLOC_FREE(frame);
273 return ret;
276 /* Insert a NULL at the first separator of the given path and return a pointer
277 * to the remainder of the string.
279 static char *
280 terminate_path_at_separator(char * path)
282 char * p;
284 if (!path) {
285 return NULL;
288 if ((p = strchr_m(path, '/'))) {
289 *p = '\0';
290 return p + 1;
293 if ((p = strchr_m(path, '\\'))) {
294 *p = '\0';
295 return p + 1;
298 /* No separator. */
299 return NULL;
303 parse a //server/share type UNC name
305 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
306 char **hostname, char **sharename)
308 char *p;
310 *hostname = *sharename = NULL;
312 if (strncmp(unc_name, "\\\\", 2) &&
313 strncmp(unc_name, "//", 2)) {
314 return False;
317 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
318 p = terminate_path_at_separator(*hostname);
320 if (p && *p) {
321 *sharename = talloc_strdup(mem_ctx, p);
322 terminate_path_at_separator(*sharename);
325 if (*hostname && *sharename) {
326 return True;
329 TALLOC_FREE(*hostname);
330 TALLOC_FREE(*sharename);
331 return False;
334 static bool torture_open_connection_share(struct cli_state **c,
335 const char *hostname,
336 const char *sharename)
338 int flags = 0;
339 NTSTATUS status;
341 if (use_kerberos)
342 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
343 if (use_oplocks)
344 flags |= CLI_FULL_CONNECTION_OPLOCKS;
345 if (use_level_II_oplocks)
346 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
348 status = cli_full_connection(c, myname,
349 hostname, NULL, port_to_use,
350 sharename, "?????",
351 username, workgroup,
352 password, flags, signing_state);
353 if (!NT_STATUS_IS_OK(status)) {
354 printf("failed to open share connection: //%s/%s port:%d - %s\n",
355 hostname, sharename, port_to_use, nt_errstr(status));
356 return False;
359 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
361 if (do_encrypt) {
362 return force_cli_encryption(*c,
363 sharename);
365 return True;
368 bool torture_open_connection(struct cli_state **c, int conn_index)
370 char **unc_list = NULL;
371 int num_unc_names = 0;
372 bool result;
374 if (use_multishare_conn==True) {
375 char *h, *s;
376 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
377 if (!unc_list || num_unc_names <= 0) {
378 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
379 exit(1);
382 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
383 NULL, &h, &s)) {
384 printf("Failed to parse UNC name %s\n",
385 unc_list[conn_index % num_unc_names]);
386 TALLOC_FREE(unc_list);
387 exit(1);
390 result = torture_open_connection_share(c, h, s);
392 /* h, s were copied earlier */
393 TALLOC_FREE(unc_list);
394 return result;
397 return torture_open_connection_share(c, host, share);
400 bool torture_init_connection(struct cli_state **pcli)
402 struct cli_state *cli;
404 cli = open_nbt_connection();
405 if (cli == NULL) {
406 return false;
409 *pcli = cli;
410 return true;
413 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
415 uint16_t old_vuid = cli_state_get_uid(cli);
416 size_t passlen = strlen(password);
417 NTSTATUS status;
418 bool ret;
420 cli_state_set_uid(cli, 0);
421 status = cli_session_setup(cli, username,
422 password, passlen,
423 password, passlen,
424 workgroup);
425 ret = NT_STATUS_IS_OK(status);
426 *new_vuid = cli_state_get_uid(cli);
427 cli_state_set_uid(cli, old_vuid);
428 return ret;
432 bool torture_close_connection(struct cli_state *c)
434 bool ret = True;
435 NTSTATUS status;
437 status = cli_tdis(c);
438 if (!NT_STATUS_IS_OK(status)) {
439 printf("tdis failed (%s)\n", nt_errstr(status));
440 ret = False;
443 cli_shutdown(c);
445 return ret;
449 /* check if the server produced the expected dos or nt error code */
450 static bool check_both_error(int line, NTSTATUS status,
451 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
453 if (NT_STATUS_IS_DOS(status)) {
454 uint8_t cclass;
455 uint32_t num;
457 /* Check DOS error */
458 cclass = NT_STATUS_DOS_CLASS(status);
459 num = NT_STATUS_DOS_CODE(status);
461 if (eclass != cclass || ecode != num) {
462 printf("unexpected error code class=%d code=%d\n",
463 (int)cclass, (int)num);
464 printf(" expected %d/%d %s (line=%d)\n",
465 (int)eclass, (int)ecode, nt_errstr(nterr), line);
466 return false;
468 } else {
469 /* Check NT error */
470 if (!NT_STATUS_EQUAL(nterr, status)) {
471 printf("unexpected error code %s\n",
472 nt_errstr(status));
473 printf(" expected %s (line=%d)\n",
474 nt_errstr(nterr), line);
475 return false;
479 return true;
483 /* check if the server produced the expected error code */
484 static bool check_error(int line, NTSTATUS status,
485 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
487 if (NT_STATUS_IS_DOS(status)) {
488 uint8_t cclass;
489 uint32_t num;
491 /* Check DOS error */
493 cclass = NT_STATUS_DOS_CLASS(status);
494 num = NT_STATUS_DOS_CODE(status);
496 if (eclass != cclass || ecode != num) {
497 printf("unexpected error code class=%d code=%d\n",
498 (int)cclass, (int)num);
499 printf(" expected %d/%d %s (line=%d)\n",
500 (int)eclass, (int)ecode, nt_errstr(nterr),
501 line);
502 return False;
505 } else {
506 /* Check NT error */
508 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
509 printf("unexpected error code %s\n",
510 nt_errstr(status));
511 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
512 line);
513 return False;
517 return True;
521 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
523 NTSTATUS status;
525 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
527 while (!NT_STATUS_IS_OK(status)) {
528 if (!check_both_error(__LINE__, status, ERRDOS,
529 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
530 return false;
533 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
536 return true;
540 static bool rw_torture(struct cli_state *c)
542 const char *lockfname = "\\torture.lck";
543 fstring fname;
544 uint16_t fnum;
545 uint16_t fnum2;
546 pid_t pid2, pid = getpid();
547 int i, j;
548 char buf[1024];
549 bool correct = True;
550 size_t nread = 0;
551 NTSTATUS status;
553 memset(buf, '\0', sizeof(buf));
555 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
556 DENY_NONE, &fnum2);
557 if (!NT_STATUS_IS_OK(status)) {
558 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
560 if (!NT_STATUS_IS_OK(status)) {
561 printf("open of %s failed (%s)\n",
562 lockfname, nt_errstr(status));
563 return False;
566 for (i=0;i<torture_numops;i++) {
567 unsigned n = (unsigned)sys_random()%10;
569 if (i % 10 == 0) {
570 printf("%d\r", i); fflush(stdout);
572 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
574 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
575 return False;
578 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
579 DENY_ALL, &fnum);
580 if (!NT_STATUS_IS_OK(status)) {
581 printf("open failed (%s)\n", nt_errstr(status));
582 correct = False;
583 break;
586 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
587 sizeof(pid), NULL);
588 if (!NT_STATUS_IS_OK(status)) {
589 printf("write failed (%s)\n", nt_errstr(status));
590 correct = False;
593 for (j=0;j<50;j++) {
594 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
595 sizeof(pid)+(j*sizeof(buf)),
596 sizeof(buf), NULL);
597 if (!NT_STATUS_IS_OK(status)) {
598 printf("write failed (%s)\n",
599 nt_errstr(status));
600 correct = False;
604 pid2 = 0;
606 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
607 &nread);
608 if (!NT_STATUS_IS_OK(status)) {
609 printf("read failed (%s)\n", nt_errstr(status));
610 correct = false;
611 } else if (nread != sizeof(pid)) {
612 printf("read/write compare failed: "
613 "recv %ld req %ld\n", (unsigned long)nread,
614 (unsigned long)sizeof(pid));
615 correct = false;
618 if (pid2 != pid) {
619 printf("data corruption!\n");
620 correct = False;
623 status = cli_close(c, fnum);
624 if (!NT_STATUS_IS_OK(status)) {
625 printf("close failed (%s)\n", nt_errstr(status));
626 correct = False;
629 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
630 if (!NT_STATUS_IS_OK(status)) {
631 printf("unlink failed (%s)\n", nt_errstr(status));
632 correct = False;
635 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
636 if (!NT_STATUS_IS_OK(status)) {
637 printf("unlock failed (%s)\n", nt_errstr(status));
638 correct = False;
642 cli_close(c, fnum2);
643 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
645 printf("%d\n", i);
647 return correct;
650 static bool run_torture(int dummy)
652 struct cli_state *cli;
653 bool ret;
655 cli = current_cli;
657 smbXcli_conn_set_sockopt(cli->conn, sockops);
659 ret = rw_torture(cli);
661 if (!torture_close_connection(cli)) {
662 ret = False;
665 return ret;
668 static bool rw_torture3(struct cli_state *c, char *lockfname)
670 uint16_t fnum = (uint16_t)-1;
671 unsigned int i = 0;
672 char buf[131072];
673 char buf_rd[131072];
674 unsigned count;
675 unsigned countprev = 0;
676 size_t sent = 0;
677 bool correct = True;
678 NTSTATUS status = NT_STATUS_OK;
680 srandom(1);
681 for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
683 SIVAL(buf, i, sys_random());
686 if (procnum == 0)
688 status = cli_unlink(
689 c, lockfname,
690 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
691 if (!NT_STATUS_IS_OK(status)) {
692 printf("unlink failed (%s) (normal, this file should "
693 "not exist)\n", nt_errstr(status));
696 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
697 DENY_NONE, &fnum);
698 if (!NT_STATUS_IS_OK(status)) {
699 printf("first open read/write of %s failed (%s)\n",
700 lockfname, nt_errstr(status));
701 return False;
704 else
706 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
708 status = cli_openx(c, lockfname, O_RDONLY,
709 DENY_NONE, &fnum);
710 if (NT_STATUS_IS_OK(status)) {
711 break;
713 smb_msleep(10);
715 if (!NT_STATUS_IS_OK(status)) {
716 printf("second open read-only of %s failed (%s)\n",
717 lockfname, nt_errstr(status));
718 return False;
722 i = 0;
723 for (count = 0; count < sizeof(buf); count += sent)
725 if (count >= countprev) {
726 printf("%d %8d\r", i, count);
727 fflush(stdout);
728 i++;
729 countprev += (sizeof(buf) / 20);
732 if (procnum == 0)
734 sent = ((unsigned)sys_random()%(20))+ 1;
735 if (sent > sizeof(buf) - count)
737 sent = sizeof(buf) - count;
740 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
741 count, sent, NULL);
742 if (!NT_STATUS_IS_OK(status)) {
743 printf("write failed (%s)\n",
744 nt_errstr(status));
745 correct = False;
748 else
750 status = cli_read(c, fnum, buf_rd+count, count,
751 sizeof(buf)-count, &sent);
752 if(!NT_STATUS_IS_OK(status)) {
753 printf("read failed offset:%d size:%ld (%s)\n",
754 count, (unsigned long)sizeof(buf)-count,
755 nt_errstr(status));
756 correct = False;
757 sent = 0;
758 } else if (sent > 0) {
759 if (memcmp(buf_rd+count, buf+count, sent) != 0)
761 printf("read/write compare failed\n");
762 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
763 correct = False;
764 break;
771 status = cli_close(c, fnum);
772 if (!NT_STATUS_IS_OK(status)) {
773 printf("close failed (%s)\n", nt_errstr(status));
774 correct = False;
777 return correct;
780 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
782 const char *lockfname = "\\torture2.lck";
783 uint16_t fnum1;
784 uint16_t fnum2;
785 int i;
786 char buf[131072];
787 char buf_rd[131072];
788 bool correct = True;
789 size_t bytes_read;
790 NTSTATUS status;
792 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
793 if (!NT_STATUS_IS_OK(status)) {
794 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
797 status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
798 DENY_NONE, &fnum1);
799 if (!NT_STATUS_IS_OK(status)) {
800 printf("first open read/write of %s failed (%s)\n",
801 lockfname, nt_errstr(status));
802 return False;
805 status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
806 if (!NT_STATUS_IS_OK(status)) {
807 printf("second open read-only of %s failed (%s)\n",
808 lockfname, nt_errstr(status));
809 cli_close(c1, fnum1);
810 return False;
813 for (i = 0; i < torture_numops; i++)
815 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
816 if (i % 10 == 0) {
817 printf("%d\r", i); fflush(stdout);
820 generate_random_buffer((unsigned char *)buf, buf_size);
822 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
823 buf_size, NULL);
824 if (!NT_STATUS_IS_OK(status)) {
825 printf("write failed (%s)\n", nt_errstr(status));
826 correct = False;
827 break;
830 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
831 if(!NT_STATUS_IS_OK(status)) {
832 printf("read failed (%s)\n", nt_errstr(status));
833 correct = false;
834 break;
835 } else if (bytes_read != buf_size) {
836 printf("read failed\n");
837 printf("read %ld, expected %ld\n",
838 (unsigned long)bytes_read,
839 (unsigned long)buf_size);
840 correct = False;
841 break;
844 if (memcmp(buf_rd, buf, buf_size) != 0)
846 printf("read/write compare failed\n");
847 correct = False;
848 break;
852 status = cli_close(c2, fnum2);
853 if (!NT_STATUS_IS_OK(status)) {
854 printf("close failed (%s)\n", nt_errstr(status));
855 correct = False;
858 status = cli_close(c1, fnum1);
859 if (!NT_STATUS_IS_OK(status)) {
860 printf("close failed (%s)\n", nt_errstr(status));
861 correct = False;
864 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
865 if (!NT_STATUS_IS_OK(status)) {
866 printf("unlink failed (%s)\n", nt_errstr(status));
867 correct = False;
870 return correct;
873 static bool run_readwritetest(int dummy)
875 struct cli_state *cli1, *cli2;
876 bool test1, test2 = False;
878 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
879 return False;
881 smbXcli_conn_set_sockopt(cli1->conn, sockops);
882 smbXcli_conn_set_sockopt(cli2->conn, sockops);
884 printf("starting readwritetest\n");
886 test1 = rw_torture2(cli1, cli2);
887 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
889 if (test1) {
890 test2 = rw_torture2(cli1, cli1);
891 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
894 if (!torture_close_connection(cli1)) {
895 test1 = False;
898 if (!torture_close_connection(cli2)) {
899 test2 = False;
902 return (test1 && test2);
905 static bool run_readwritemulti(int dummy)
907 struct cli_state *cli;
908 bool test;
910 cli = current_cli;
912 smbXcli_conn_set_sockopt(cli->conn, sockops);
914 printf("run_readwritemulti: fname %s\n", randomfname);
915 test = rw_torture3(cli, randomfname);
917 if (!torture_close_connection(cli)) {
918 test = False;
921 return test;
924 static bool run_readwritelarge_internal(void)
926 static struct cli_state *cli1;
927 uint16_t fnum1;
928 const char *lockfname = "\\large.dat";
929 off_t fsize;
930 char buf[126*1024];
931 bool correct = True;
932 NTSTATUS status;
934 if (!torture_open_connection(&cli1, 0)) {
935 return False;
937 smbXcli_conn_set_sockopt(cli1->conn, sockops);
938 memset(buf,'\0',sizeof(buf));
940 printf("starting readwritelarge_internal\n");
942 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
944 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
945 DENY_NONE, &fnum1);
946 if (!NT_STATUS_IS_OK(status)) {
947 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
948 return False;
951 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
953 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
954 NULL, NULL, NULL);
955 if (!NT_STATUS_IS_OK(status)) {
956 printf("qfileinfo failed (%s)\n", nt_errstr(status));
957 correct = False;
960 if (fsize == sizeof(buf))
961 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
962 (unsigned long)fsize);
963 else {
964 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
965 (unsigned long)fsize);
966 correct = False;
969 status = cli_close(cli1, fnum1);
970 if (!NT_STATUS_IS_OK(status)) {
971 printf("close failed (%s)\n", nt_errstr(status));
972 correct = False;
975 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
976 if (!NT_STATUS_IS_OK(status)) {
977 printf("unlink failed (%s)\n", nt_errstr(status));
978 correct = False;
981 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
982 DENY_NONE, &fnum1);
983 if (!NT_STATUS_IS_OK(status)) {
984 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
985 return False;
988 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
990 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
991 NULL, NULL, NULL);
992 if (!NT_STATUS_IS_OK(status)) {
993 printf("qfileinfo failed (%s)\n", nt_errstr(status));
994 correct = False;
997 if (fsize == sizeof(buf))
998 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
999 (unsigned long)fsize);
1000 else {
1001 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1002 (unsigned long)fsize);
1003 correct = False;
1006 #if 0
1007 /* ToDo - set allocation. JRA */
1008 if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1009 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1010 return False;
1012 if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1013 NULL, NULL)) {
1014 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1015 correct = False;
1017 if (fsize != 0)
1018 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1019 #endif
1021 status = cli_close(cli1, fnum1);
1022 if (!NT_STATUS_IS_OK(status)) {
1023 printf("close failed (%s)\n", nt_errstr(status));
1024 correct = False;
1027 if (!torture_close_connection(cli1)) {
1028 correct = False;
1030 return correct;
1033 static bool run_readwritelarge(int dummy)
1035 return run_readwritelarge_internal();
1038 static bool run_readwritelarge_signtest(int dummy)
1040 bool ret;
1041 signing_state = SMB_SIGNING_REQUIRED;
1042 ret = run_readwritelarge_internal();
1043 signing_state = SMB_SIGNING_DEFAULT;
1044 return ret;
1047 int line_count = 0;
1048 int nbio_id;
1050 #define ival(s) strtol(s, NULL, 0)
1052 /* run a test that simulates an approximate netbench client load */
1053 static bool run_netbench(int client)
1055 struct cli_state *cli;
1056 int i;
1057 char line[1024];
1058 char cname[20];
1059 FILE *f;
1060 const char *params[20];
1061 bool correct = True;
1063 cli = current_cli;
1065 nbio_id = client;
1067 smbXcli_conn_set_sockopt(cli->conn, sockops);
1069 nb_setup(cli);
1071 slprintf(cname,sizeof(cname)-1, "client%d", client);
1073 f = fopen(client_txt, "r");
1075 if (!f) {
1076 perror(client_txt);
1077 return False;
1080 while (fgets(line, sizeof(line)-1, f)) {
1081 char *saveptr;
1082 line_count++;
1084 line[strlen(line)-1] = 0;
1086 /* printf("[%d] %s\n", line_count, line); */
1088 all_string_sub(line,"client1", cname, sizeof(line));
1090 /* parse the command parameters */
1091 params[0] = strtok_r(line, " ", &saveptr);
1092 i = 0;
1093 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1095 params[i] = "";
1097 if (i < 2) continue;
1099 if (!strncmp(params[0],"SMB", 3)) {
1100 printf("ERROR: You are using a dbench 1 load file\n");
1101 exit(1);
1104 if (!strcmp(params[0],"NTCreateX")) {
1105 nb_createx(params[1], ival(params[2]), ival(params[3]),
1106 ival(params[4]));
1107 } else if (!strcmp(params[0],"Close")) {
1108 nb_close(ival(params[1]));
1109 } else if (!strcmp(params[0],"Rename")) {
1110 nb_rename(params[1], params[2]);
1111 } else if (!strcmp(params[0],"Unlink")) {
1112 nb_unlink(params[1]);
1113 } else if (!strcmp(params[0],"Deltree")) {
1114 nb_deltree(params[1]);
1115 } else if (!strcmp(params[0],"Rmdir")) {
1116 nb_rmdir(params[1]);
1117 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1118 nb_qpathinfo(params[1]);
1119 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1120 nb_qfileinfo(ival(params[1]));
1121 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1122 nb_qfsinfo(ival(params[1]));
1123 } else if (!strcmp(params[0],"FIND_FIRST")) {
1124 nb_findfirst(params[1]);
1125 } else if (!strcmp(params[0],"WriteX")) {
1126 nb_writex(ival(params[1]),
1127 ival(params[2]), ival(params[3]), ival(params[4]));
1128 } else if (!strcmp(params[0],"ReadX")) {
1129 nb_readx(ival(params[1]),
1130 ival(params[2]), ival(params[3]), ival(params[4]));
1131 } else if (!strcmp(params[0],"Flush")) {
1132 nb_flush(ival(params[1]));
1133 } else {
1134 printf("Unknown operation %s\n", params[0]);
1135 exit(1);
1138 fclose(f);
1140 nb_cleanup();
1142 if (!torture_close_connection(cli)) {
1143 correct = False;
1146 return correct;
1150 /* run a test that simulates an approximate netbench client load */
1151 static bool run_nbench(int dummy)
1153 double t;
1154 bool correct = True;
1156 nbio_shmem(torture_nprocs);
1158 nbio_id = -1;
1160 signal(SIGALRM, nb_alarm);
1161 alarm(1);
1162 t = create_procs(run_netbench, &correct);
1163 alarm(0);
1165 printf("\nThroughput %g MB/sec\n",
1166 1.0e-6 * nbio_total() / t);
1167 return correct;
1172 This test checks for two things:
1174 1) correct support for retaining locks over a close (ie. the server
1175 must not use posix semantics)
1176 2) support for lock timeouts
1178 static bool run_locktest1(int dummy)
1180 struct cli_state *cli1, *cli2;
1181 const char *fname = "\\lockt1.lck";
1182 uint16_t fnum1, fnum2, fnum3;
1183 time_t t1, t2;
1184 unsigned lock_timeout;
1185 NTSTATUS status;
1187 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1188 return False;
1190 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1191 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1193 printf("starting locktest1\n");
1195 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1197 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1198 &fnum1);
1199 if (!NT_STATUS_IS_OK(status)) {
1200 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1201 return False;
1204 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1205 if (!NT_STATUS_IS_OK(status)) {
1206 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1207 return False;
1210 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1211 if (!NT_STATUS_IS_OK(status)) {
1212 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1213 return False;
1216 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1217 if (!NT_STATUS_IS_OK(status)) {
1218 printf("lock1 failed (%s)\n", nt_errstr(status));
1219 return false;
1222 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1223 if (NT_STATUS_IS_OK(status)) {
1224 printf("lock2 succeeded! This is a locking bug\n");
1225 return false;
1226 } else {
1227 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1228 NT_STATUS_LOCK_NOT_GRANTED)) {
1229 return false;
1233 lock_timeout = (1 + (random() % 20));
1234 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1235 t1 = time(NULL);
1236 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1237 if (NT_STATUS_IS_OK(status)) {
1238 printf("lock3 succeeded! This is a locking bug\n");
1239 return false;
1240 } else {
1241 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1242 NT_STATUS_FILE_LOCK_CONFLICT)) {
1243 return false;
1246 t2 = time(NULL);
1248 if (ABS(t2 - t1) < lock_timeout-1) {
1249 printf("error: This server appears not to support timed lock requests\n");
1252 printf("server slept for %u seconds for a %u second timeout\n",
1253 (unsigned int)(t2-t1), lock_timeout);
1255 status = cli_close(cli1, fnum2);
1256 if (!NT_STATUS_IS_OK(status)) {
1257 printf("close1 failed (%s)\n", nt_errstr(status));
1258 return False;
1261 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1262 if (NT_STATUS_IS_OK(status)) {
1263 printf("lock4 succeeded! This is a locking bug\n");
1264 return false;
1265 } else {
1266 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1267 NT_STATUS_FILE_LOCK_CONFLICT)) {
1268 return false;
1272 status = cli_close(cli1, fnum1);
1273 if (!NT_STATUS_IS_OK(status)) {
1274 printf("close2 failed (%s)\n", nt_errstr(status));
1275 return False;
1278 status = cli_close(cli2, fnum3);
1279 if (!NT_STATUS_IS_OK(status)) {
1280 printf("close3 failed (%s)\n", nt_errstr(status));
1281 return False;
1284 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1285 if (!NT_STATUS_IS_OK(status)) {
1286 printf("unlink failed (%s)\n", nt_errstr(status));
1287 return False;
1291 if (!torture_close_connection(cli1)) {
1292 return False;
1295 if (!torture_close_connection(cli2)) {
1296 return False;
1299 printf("Passed locktest1\n");
1300 return True;
1304 this checks to see if a secondary tconx can use open files from an
1305 earlier tconx
1307 static bool run_tcon_test(int dummy)
1309 static struct cli_state *cli;
1310 const char *fname = "\\tcontest.tmp";
1311 uint16_t fnum1;
1312 uint16_t cnum1, cnum2, cnum3;
1313 uint16_t vuid1, vuid2;
1314 char buf[4];
1315 bool ret = True;
1316 NTSTATUS status;
1318 memset(buf, '\0', sizeof(buf));
1320 if (!torture_open_connection(&cli, 0)) {
1321 return False;
1323 smbXcli_conn_set_sockopt(cli->conn, sockops);
1325 printf("starting tcontest\n");
1327 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1329 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1330 if (!NT_STATUS_IS_OK(status)) {
1331 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1332 return False;
1335 cnum1 = cli_state_get_tid(cli);
1336 vuid1 = cli_state_get_uid(cli);
1338 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1339 if (!NT_STATUS_IS_OK(status)) {
1340 printf("initial write failed (%s)", nt_errstr(status));
1341 return False;
1344 status = cli_tree_connect(cli, share, "?????",
1345 password, strlen(password)+1);
1346 if (!NT_STATUS_IS_OK(status)) {
1347 printf("%s refused 2nd tree connect (%s)\n", host,
1348 nt_errstr(status));
1349 cli_shutdown(cli);
1350 return False;
1353 cnum2 = cli_state_get_tid(cli);
1354 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1355 vuid2 = cli_state_get_uid(cli) + 1;
1357 /* try a write with the wrong tid */
1358 cli_state_set_tid(cli, cnum2);
1360 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1361 if (NT_STATUS_IS_OK(status)) {
1362 printf("* server allows write with wrong TID\n");
1363 ret = False;
1364 } else {
1365 printf("server fails write with wrong TID : %s\n",
1366 nt_errstr(status));
1370 /* try a write with an invalid tid */
1371 cli_state_set_tid(cli, cnum3);
1373 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1374 if (NT_STATUS_IS_OK(status)) {
1375 printf("* server allows write with invalid TID\n");
1376 ret = False;
1377 } else {
1378 printf("server fails write with invalid TID : %s\n",
1379 nt_errstr(status));
1382 /* try a write with an invalid vuid */
1383 cli_state_set_uid(cli, vuid2);
1384 cli_state_set_tid(cli, cnum1);
1386 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1387 if (NT_STATUS_IS_OK(status)) {
1388 printf("* server allows write with invalid VUID\n");
1389 ret = False;
1390 } else {
1391 printf("server fails write with invalid VUID : %s\n",
1392 nt_errstr(status));
1395 cli_state_set_tid(cli, cnum1);
1396 cli_state_set_uid(cli, vuid1);
1398 status = cli_close(cli, fnum1);
1399 if (!NT_STATUS_IS_OK(status)) {
1400 printf("close failed (%s)\n", nt_errstr(status));
1401 return False;
1404 cli_state_set_tid(cli, cnum2);
1406 status = cli_tdis(cli);
1407 if (!NT_STATUS_IS_OK(status)) {
1408 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1409 return False;
1412 cli_state_set_tid(cli, cnum1);
1414 if (!torture_close_connection(cli)) {
1415 return False;
1418 return ret;
1423 checks for old style tcon support
1425 static bool run_tcon2_test(int dummy)
1427 static struct cli_state *cli;
1428 uint16_t cnum, max_xmit;
1429 char *service;
1430 NTSTATUS status;
1432 if (!torture_open_connection(&cli, 0)) {
1433 return False;
1435 smbXcli_conn_set_sockopt(cli->conn, sockops);
1437 printf("starting tcon2 test\n");
1439 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1440 return false;
1443 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1445 SAFE_FREE(service);
1447 if (!NT_STATUS_IS_OK(status)) {
1448 printf("tcon2 failed : %s\n", nt_errstr(status));
1449 } else {
1450 printf("tcon OK : max_xmit=%d cnum=%d\n",
1451 (int)max_xmit, (int)cnum);
1454 if (!torture_close_connection(cli)) {
1455 return False;
1458 printf("Passed tcon2 test\n");
1459 return True;
1462 static bool tcon_devtest(struct cli_state *cli,
1463 const char *myshare, const char *devtype,
1464 const char *return_devtype,
1465 NTSTATUS expected_error)
1467 NTSTATUS status;
1468 bool ret;
1470 status = cli_tree_connect(cli, myshare, devtype,
1471 password, strlen(password)+1);
1473 if (NT_STATUS_IS_OK(expected_error)) {
1474 if (NT_STATUS_IS_OK(status)) {
1475 if (strcmp(cli->dev, return_devtype) == 0) {
1476 ret = True;
1477 } else {
1478 printf("tconX to share %s with type %s "
1479 "succeeded but returned the wrong "
1480 "device type (got [%s] but should have got [%s])\n",
1481 myshare, devtype, cli->dev, return_devtype);
1482 ret = False;
1484 } else {
1485 printf("tconX to share %s with type %s "
1486 "should have succeeded but failed\n",
1487 myshare, devtype);
1488 ret = False;
1490 cli_tdis(cli);
1491 } else {
1492 if (NT_STATUS_IS_OK(status)) {
1493 printf("tconx to share %s with type %s "
1494 "should have failed but succeeded\n",
1495 myshare, devtype);
1496 ret = False;
1497 } else {
1498 if (NT_STATUS_EQUAL(status, expected_error)) {
1499 ret = True;
1500 } else {
1501 printf("Returned unexpected error\n");
1502 ret = False;
1506 return ret;
1510 checks for correct tconX support
1512 static bool run_tcon_devtype_test(int dummy)
1514 static struct cli_state *cli1 = NULL;
1515 int flags = 0;
1516 NTSTATUS status;
1517 bool ret = True;
1519 status = cli_full_connection(&cli1, myname,
1520 host, NULL, port_to_use,
1521 NULL, NULL,
1522 username, workgroup,
1523 password, flags, signing_state);
1525 if (!NT_STATUS_IS_OK(status)) {
1526 printf("could not open connection\n");
1527 return False;
1530 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1531 ret = False;
1533 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1534 ret = False;
1536 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1537 ret = False;
1539 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1540 ret = False;
1542 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1543 ret = False;
1545 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1546 ret = False;
1548 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1549 ret = False;
1551 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1552 ret = False;
1554 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1555 ret = False;
1557 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1558 ret = False;
1560 cli_shutdown(cli1);
1562 if (ret)
1563 printf("Passed tcondevtest\n");
1565 return ret;
1570 This test checks that
1572 1) the server supports multiple locking contexts on the one SMB
1573 connection, distinguished by PID.
1575 2) the server correctly fails overlapping locks made by the same PID (this
1576 goes against POSIX behaviour, which is why it is tricky to implement)
1578 3) the server denies unlock requests by an incorrect client PID
1580 static bool run_locktest2(int dummy)
1582 static struct cli_state *cli;
1583 const char *fname = "\\lockt2.lck";
1584 uint16_t fnum1, fnum2, fnum3;
1585 bool correct = True;
1586 NTSTATUS status;
1588 if (!torture_open_connection(&cli, 0)) {
1589 return False;
1592 smbXcli_conn_set_sockopt(cli->conn, sockops);
1594 printf("starting locktest2\n");
1596 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1598 cli_setpid(cli, 1);
1600 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1601 if (!NT_STATUS_IS_OK(status)) {
1602 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1603 return False;
1606 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1607 if (!NT_STATUS_IS_OK(status)) {
1608 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1609 return False;
1612 cli_setpid(cli, 2);
1614 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1615 if (!NT_STATUS_IS_OK(status)) {
1616 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1617 return False;
1620 cli_setpid(cli, 1);
1622 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1623 if (!NT_STATUS_IS_OK(status)) {
1624 printf("lock1 failed (%s)\n", nt_errstr(status));
1625 return false;
1628 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1629 if (NT_STATUS_IS_OK(status)) {
1630 printf("WRITE lock1 succeeded! This is a locking bug\n");
1631 correct = false;
1632 } else {
1633 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1634 NT_STATUS_LOCK_NOT_GRANTED)) {
1635 return false;
1639 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1640 if (NT_STATUS_IS_OK(status)) {
1641 printf("WRITE lock2 succeeded! This is a locking bug\n");
1642 correct = false;
1643 } else {
1644 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1645 NT_STATUS_LOCK_NOT_GRANTED)) {
1646 return false;
1650 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1651 if (NT_STATUS_IS_OK(status)) {
1652 printf("READ lock2 succeeded! This is a locking bug\n");
1653 correct = false;
1654 } else {
1655 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1656 NT_STATUS_FILE_LOCK_CONFLICT)) {
1657 return false;
1661 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1662 if (!NT_STATUS_IS_OK(status)) {
1663 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1665 cli_setpid(cli, 2);
1666 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1667 printf("unlock at 100 succeeded! This is a locking bug\n");
1668 correct = False;
1671 status = cli_unlock(cli, fnum1, 0, 4);
1672 if (NT_STATUS_IS_OK(status)) {
1673 printf("unlock1 succeeded! This is a locking bug\n");
1674 correct = false;
1675 } else {
1676 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1677 NT_STATUS_RANGE_NOT_LOCKED)) {
1678 return false;
1682 status = cli_unlock(cli, fnum1, 0, 8);
1683 if (NT_STATUS_IS_OK(status)) {
1684 printf("unlock2 succeeded! This is a locking bug\n");
1685 correct = false;
1686 } else {
1687 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1688 NT_STATUS_RANGE_NOT_LOCKED)) {
1689 return false;
1693 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1694 if (NT_STATUS_IS_OK(status)) {
1695 printf("lock3 succeeded! This is a locking bug\n");
1696 correct = false;
1697 } else {
1698 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1699 NT_STATUS_LOCK_NOT_GRANTED)) {
1700 return false;
1704 cli_setpid(cli, 1);
1706 status = cli_close(cli, fnum1);
1707 if (!NT_STATUS_IS_OK(status)) {
1708 printf("close1 failed (%s)\n", nt_errstr(status));
1709 return False;
1712 status = cli_close(cli, fnum2);
1713 if (!NT_STATUS_IS_OK(status)) {
1714 printf("close2 failed (%s)\n", nt_errstr(status));
1715 return False;
1718 status = cli_close(cli, fnum3);
1719 if (!NT_STATUS_IS_OK(status)) {
1720 printf("close3 failed (%s)\n", nt_errstr(status));
1721 return False;
1724 if (!torture_close_connection(cli)) {
1725 correct = False;
1728 printf("locktest2 finished\n");
1730 return correct;
1735 This test checks that
1737 1) the server supports the full offset range in lock requests
1739 static bool run_locktest3(int dummy)
1741 static struct cli_state *cli1, *cli2;
1742 const char *fname = "\\lockt3.lck";
1743 uint16_t fnum1, fnum2;
1744 int i;
1745 uint32_t offset;
1746 bool correct = True;
1747 NTSTATUS status;
1749 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1751 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1752 return False;
1754 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1755 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1757 printf("starting locktest3\n");
1759 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1761 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1762 &fnum1);
1763 if (!NT_STATUS_IS_OK(status)) {
1764 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1765 return False;
1768 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1769 if (!NT_STATUS_IS_OK(status)) {
1770 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1771 return False;
1774 for (offset=i=0;i<torture_numops;i++) {
1775 NEXT_OFFSET;
1777 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1778 if (!NT_STATUS_IS_OK(status)) {
1779 printf("lock1 %d failed (%s)\n",
1781 nt_errstr(status));
1782 return False;
1785 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1786 if (!NT_STATUS_IS_OK(status)) {
1787 printf("lock2 %d failed (%s)\n",
1789 nt_errstr(status));
1790 return False;
1794 for (offset=i=0;i<torture_numops;i++) {
1795 NEXT_OFFSET;
1797 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1798 if (NT_STATUS_IS_OK(status)) {
1799 printf("error: lock1 %d succeeded!\n", i);
1800 return False;
1803 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1804 if (NT_STATUS_IS_OK(status)) {
1805 printf("error: lock2 %d succeeded!\n", i);
1806 return False;
1809 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1810 if (NT_STATUS_IS_OK(status)) {
1811 printf("error: lock3 %d succeeded!\n", i);
1812 return False;
1815 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1816 if (NT_STATUS_IS_OK(status)) {
1817 printf("error: lock4 %d succeeded!\n", i);
1818 return False;
1822 for (offset=i=0;i<torture_numops;i++) {
1823 NEXT_OFFSET;
1825 status = cli_unlock(cli1, fnum1, offset-1, 1);
1826 if (!NT_STATUS_IS_OK(status)) {
1827 printf("unlock1 %d failed (%s)\n",
1829 nt_errstr(status));
1830 return False;
1833 status = cli_unlock(cli2, fnum2, offset-2, 1);
1834 if (!NT_STATUS_IS_OK(status)) {
1835 printf("unlock2 %d failed (%s)\n",
1837 nt_errstr(status));
1838 return False;
1842 status = cli_close(cli1, fnum1);
1843 if (!NT_STATUS_IS_OK(status)) {
1844 printf("close1 failed (%s)\n", nt_errstr(status));
1845 return False;
1848 status = cli_close(cli2, fnum2);
1849 if (!NT_STATUS_IS_OK(status)) {
1850 printf("close2 failed (%s)\n", nt_errstr(status));
1851 return False;
1854 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1855 if (!NT_STATUS_IS_OK(status)) {
1856 printf("unlink failed (%s)\n", nt_errstr(status));
1857 return False;
1860 if (!torture_close_connection(cli1)) {
1861 correct = False;
1864 if (!torture_close_connection(cli2)) {
1865 correct = False;
1868 printf("finished locktest3\n");
1870 return correct;
1873 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1874 char *buf, off_t offset, size_t size,
1875 size_t *nread, size_t expect)
1877 NTSTATUS status;
1878 size_t l_nread;
1880 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1882 if(!NT_STATUS_IS_OK(status)) {
1883 return false;
1884 } else if (l_nread != expect) {
1885 return false;
1888 if (nread) {
1889 *nread = l_nread;
1892 return true;
1895 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1896 printf("** "); correct = False; \
1900 looks at overlapping locks
1902 static bool run_locktest4(int dummy)
1904 static struct cli_state *cli1, *cli2;
1905 const char *fname = "\\lockt4.lck";
1906 uint16_t fnum1, fnum2, f;
1907 bool ret;
1908 char buf[1000];
1909 bool correct = True;
1910 NTSTATUS status;
1912 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1913 return False;
1916 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1917 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1919 printf("starting locktest4\n");
1921 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1923 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1924 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1926 memset(buf, 0, sizeof(buf));
1928 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1929 NULL);
1930 if (!NT_STATUS_IS_OK(status)) {
1931 printf("Failed to create file: %s\n", nt_errstr(status));
1932 correct = False;
1933 goto fail;
1936 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1937 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1938 EXPECTED(ret, False);
1939 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1941 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1942 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1943 EXPECTED(ret, True);
1944 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1946 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1947 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1948 EXPECTED(ret, False);
1949 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1951 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1952 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1953 EXPECTED(ret, True);
1954 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1956 ret = (cli_setpid(cli1, 1),
1957 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1958 (cli_setpid(cli1, 2),
1959 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1960 EXPECTED(ret, False);
1961 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1963 ret = (cli_setpid(cli1, 1),
1964 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1965 (cli_setpid(cli1, 2),
1966 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1967 EXPECTED(ret, True);
1968 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1970 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1971 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1972 EXPECTED(ret, True);
1973 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1975 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1976 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1977 EXPECTED(ret, False);
1978 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1980 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1981 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1982 EXPECTED(ret, False);
1983 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1985 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1986 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
1987 EXPECTED(ret, True);
1988 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1990 ret = (cli_setpid(cli1, 1),
1991 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
1992 (cli_setpid(cli1, 2),
1993 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
1994 EXPECTED(ret, False);
1995 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1997 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
1998 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
1999 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2000 EXPECTED(ret, False);
2001 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2004 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2005 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2006 EXPECTED(ret, False);
2007 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2009 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2010 ret = NT_STATUS_IS_OK(status);
2011 if (ret) {
2012 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2013 NULL);
2014 ret = NT_STATUS_IS_OK(status);
2016 EXPECTED(ret, False);
2017 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2020 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2021 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2022 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2023 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2024 EXPECTED(ret, True);
2025 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2028 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2029 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2030 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2031 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2032 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2033 150, 4, NULL))) &&
2034 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2035 EXPECTED(ret, True);
2036 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2038 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2039 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2040 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2041 160, 4, NULL)) &&
2042 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2043 EXPECTED(ret, True);
2044 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2046 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2047 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2048 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2049 170, 4, NULL)) &&
2050 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2051 EXPECTED(ret, True);
2052 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2054 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2055 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2056 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2057 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2058 190, 4, NULL)) &&
2059 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2060 EXPECTED(ret, True);
2061 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2063 cli_close(cli1, fnum1);
2064 cli_close(cli2, fnum2);
2065 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2066 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2067 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2068 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2069 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2070 NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2071 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2072 cli_close(cli1, f);
2073 cli_close(cli1, fnum1);
2074 EXPECTED(ret, True);
2075 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2077 fail:
2078 cli_close(cli1, fnum1);
2079 cli_close(cli2, fnum2);
2080 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2081 torture_close_connection(cli1);
2082 torture_close_connection(cli2);
2084 printf("finished locktest4\n");
2085 return correct;
2089 looks at lock upgrade/downgrade.
2091 static bool run_locktest5(int dummy)
2093 static struct cli_state *cli1, *cli2;
2094 const char *fname = "\\lockt5.lck";
2095 uint16_t fnum1, fnum2, fnum3;
2096 bool ret;
2097 char buf[1000];
2098 bool correct = True;
2099 NTSTATUS status;
2101 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2102 return False;
2105 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2106 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2108 printf("starting locktest5\n");
2110 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2112 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2113 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2114 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2116 memset(buf, 0, sizeof(buf));
2118 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2119 NULL);
2120 if (!NT_STATUS_IS_OK(status)) {
2121 printf("Failed to create file: %s\n", nt_errstr(status));
2122 correct = False;
2123 goto fail;
2126 /* Check for NT bug... */
2127 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2128 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2129 cli_close(cli1, fnum1);
2130 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2131 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2132 ret = NT_STATUS_IS_OK(status);
2133 EXPECTED(ret, True);
2134 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2135 cli_close(cli1, fnum1);
2136 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2137 cli_unlock(cli1, fnum3, 0, 1);
2139 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2140 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2141 EXPECTED(ret, True);
2142 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2144 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2145 ret = NT_STATUS_IS_OK(status);
2146 EXPECTED(ret, False);
2148 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2150 /* Unlock the process 2 lock. */
2151 cli_unlock(cli2, fnum2, 0, 4);
2153 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2154 ret = NT_STATUS_IS_OK(status);
2155 EXPECTED(ret, False);
2157 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2159 /* Unlock the process 1 fnum3 lock. */
2160 cli_unlock(cli1, fnum3, 0, 4);
2162 /* Stack 2 more locks here. */
2163 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2164 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2166 EXPECTED(ret, True);
2167 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2169 /* Unlock the first process lock, then check this was the WRITE lock that was
2170 removed. */
2172 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2173 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2175 EXPECTED(ret, True);
2176 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2178 /* Unlock the process 2 lock. */
2179 cli_unlock(cli2, fnum2, 0, 4);
2181 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2183 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2184 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2185 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2187 EXPECTED(ret, True);
2188 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2190 /* Ensure the next unlock fails. */
2191 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2192 EXPECTED(ret, False);
2193 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2195 /* Ensure connection 2 can get a write lock. */
2196 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2197 ret = NT_STATUS_IS_OK(status);
2198 EXPECTED(ret, True);
2200 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2203 fail:
2204 cli_close(cli1, fnum1);
2205 cli_close(cli2, fnum2);
2206 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2207 if (!torture_close_connection(cli1)) {
2208 correct = False;
2210 if (!torture_close_connection(cli2)) {
2211 correct = False;
2214 printf("finished locktest5\n");
2216 return correct;
2220 tries the unusual lockingX locktype bits
2222 static bool run_locktest6(int dummy)
2224 static struct cli_state *cli;
2225 const char *fname[1] = { "\\lock6.txt" };
2226 int i;
2227 uint16_t fnum;
2228 NTSTATUS status;
2230 if (!torture_open_connection(&cli, 0)) {
2231 return False;
2234 smbXcli_conn_set_sockopt(cli->conn, sockops);
2236 printf("starting locktest6\n");
2238 for (i=0;i<1;i++) {
2239 printf("Testing %s\n", fname[i]);
2241 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2243 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2244 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2245 cli_close(cli, fnum);
2246 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2248 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2249 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2250 cli_close(cli, fnum);
2251 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2253 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2256 torture_close_connection(cli);
2258 printf("finished locktest6\n");
2259 return True;
2262 static bool run_locktest7(int dummy)
2264 struct cli_state *cli1;
2265 const char *fname = "\\lockt7.lck";
2266 uint16_t fnum1;
2267 char buf[200];
2268 bool correct = False;
2269 size_t nread;
2270 NTSTATUS status;
2272 if (!torture_open_connection(&cli1, 0)) {
2273 return False;
2276 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2278 printf("starting locktest7\n");
2280 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2282 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2284 memset(buf, 0, sizeof(buf));
2286 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2287 NULL);
2288 if (!NT_STATUS_IS_OK(status)) {
2289 printf("Failed to create file: %s\n", nt_errstr(status));
2290 goto fail;
2293 cli_setpid(cli1, 1);
2295 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2296 if (!NT_STATUS_IS_OK(status)) {
2297 printf("Unable to apply read lock on range 130:4, "
2298 "error was %s\n", nt_errstr(status));
2299 goto fail;
2300 } else {
2301 printf("pid1 successfully locked range 130:4 for READ\n");
2304 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2305 if (!NT_STATUS_IS_OK(status)) {
2306 printf("pid1 unable to read the range 130:4, error was %s\n",
2307 nt_errstr(status));
2308 goto fail;
2309 } else if (nread != 4) {
2310 printf("pid1 unable to read the range 130:4, "
2311 "recv %ld req %d\n", (unsigned long)nread, 4);
2312 goto fail;
2313 } else {
2314 printf("pid1 successfully read the range 130:4\n");
2317 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2318 if (!NT_STATUS_IS_OK(status)) {
2319 printf("pid1 unable to write to the range 130:4, error was "
2320 "%s\n", nt_errstr(status));
2321 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2322 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2323 goto fail;
2325 } else {
2326 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2327 goto fail;
2330 cli_setpid(cli1, 2);
2332 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2333 if (!NT_STATUS_IS_OK(status)) {
2334 printf("pid2 unable to read the range 130:4, error was %s\n",
2335 nt_errstr(status));
2336 goto fail;
2337 } else if (nread != 4) {
2338 printf("pid2 unable to read the range 130:4, "
2339 "recv %ld req %d\n", (unsigned long)nread, 4);
2340 goto fail;
2341 } else {
2342 printf("pid2 successfully read the range 130:4\n");
2345 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2346 if (!NT_STATUS_IS_OK(status)) {
2347 printf("pid2 unable to write to the range 130:4, error was "
2348 "%s\n", nt_errstr(status));
2349 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2350 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2351 goto fail;
2353 } else {
2354 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2355 goto fail;
2358 cli_setpid(cli1, 1);
2359 cli_unlock(cli1, fnum1, 130, 4);
2361 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2362 if (!NT_STATUS_IS_OK(status)) {
2363 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2364 goto fail;
2365 } else {
2366 printf("pid1 successfully locked range 130:4 for WRITE\n");
2369 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2370 if (!NT_STATUS_IS_OK(status)) {
2371 printf("pid1 unable to read the range 130:4, error was %s\n",
2372 nt_errstr(status));
2373 goto fail;
2374 } else if (nread != 4) {
2375 printf("pid1 unable to read the range 130:4, "
2376 "recv %ld req %d\n", (unsigned long)nread, 4);
2377 goto fail;
2378 } else {
2379 printf("pid1 successfully read the range 130:4\n");
2382 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2383 if (!NT_STATUS_IS_OK(status)) {
2384 printf("pid1 unable to write to the range 130:4, error was "
2385 "%s\n", nt_errstr(status));
2386 goto fail;
2387 } else {
2388 printf("pid1 successfully wrote to the range 130:4\n");
2391 cli_setpid(cli1, 2);
2393 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2394 if (!NT_STATUS_IS_OK(status)) {
2395 printf("pid2 unable to read the range 130:4, error was "
2396 "%s\n", nt_errstr(status));
2397 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2398 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2399 goto fail;
2401 } else {
2402 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2403 (unsigned long)nread);
2404 goto fail;
2407 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2408 if (!NT_STATUS_IS_OK(status)) {
2409 printf("pid2 unable to write to the range 130:4, error was "
2410 "%s\n", nt_errstr(status));
2411 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2412 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2413 goto fail;
2415 } else {
2416 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2417 goto fail;
2420 cli_unlock(cli1, fnum1, 130, 0);
2421 correct = True;
2423 fail:
2424 cli_close(cli1, fnum1);
2425 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2426 torture_close_connection(cli1);
2428 printf("finished locktest7\n");
2429 return correct;
2433 * This demonstrates a problem with our use of GPFS share modes: A file
2434 * descriptor sitting in the pending close queue holding a GPFS share mode
2435 * blocks opening a file another time. Happens with Word 2007 temp files.
2436 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2437 * open is denied with NT_STATUS_SHARING_VIOLATION.
2440 static bool run_locktest8(int dummy)
2442 struct cli_state *cli1;
2443 const char *fname = "\\lockt8.lck";
2444 uint16_t fnum1, fnum2;
2445 char buf[200];
2446 bool correct = False;
2447 NTSTATUS status;
2449 if (!torture_open_connection(&cli1, 0)) {
2450 return False;
2453 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2455 printf("starting locktest8\n");
2457 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2459 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2460 &fnum1);
2461 if (!NT_STATUS_IS_OK(status)) {
2462 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2463 return false;
2466 memset(buf, 0, sizeof(buf));
2468 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2469 if (!NT_STATUS_IS_OK(status)) {
2470 d_fprintf(stderr, "cli_openx second time returned %s\n",
2471 nt_errstr(status));
2472 goto fail;
2475 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2476 if (!NT_STATUS_IS_OK(status)) {
2477 printf("Unable to apply read lock on range 1:1, error was "
2478 "%s\n", nt_errstr(status));
2479 goto fail;
2482 status = cli_close(cli1, fnum1);
2483 if (!NT_STATUS_IS_OK(status)) {
2484 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2485 goto fail;
2488 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2489 if (!NT_STATUS_IS_OK(status)) {
2490 d_fprintf(stderr, "cli_openx third time returned %s\n",
2491 nt_errstr(status));
2492 goto fail;
2495 correct = true;
2497 fail:
2498 cli_close(cli1, fnum1);
2499 cli_close(cli1, fnum2);
2500 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2501 torture_close_connection(cli1);
2503 printf("finished locktest8\n");
2504 return correct;
2508 * This test is designed to be run in conjunction with
2509 * external NFS or POSIX locks taken in the filesystem.
2510 * It checks that the smbd server will block until the
2511 * lock is released and then acquire it. JRA.
2514 static bool got_alarm;
2515 static struct cli_state *alarm_cli;
2517 static void alarm_handler(int dummy)
2519 got_alarm = True;
2522 static void alarm_handler_parent(int dummy)
2524 smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_OK);
2527 static void do_local_lock(int read_fd, int write_fd)
2529 int fd;
2530 char c = '\0';
2531 struct flock lock;
2532 const char *local_pathname = NULL;
2533 int ret;
2535 local_pathname = talloc_asprintf(talloc_tos(),
2536 "%s/lockt9.lck", local_path);
2537 if (!local_pathname) {
2538 printf("child: alloc fail\n");
2539 exit(1);
2542 unlink(local_pathname);
2543 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2544 if (fd == -1) {
2545 printf("child: open of %s failed %s.\n",
2546 local_pathname, strerror(errno));
2547 exit(1);
2550 /* Now take a fcntl lock. */
2551 lock.l_type = F_WRLCK;
2552 lock.l_whence = SEEK_SET;
2553 lock.l_start = 0;
2554 lock.l_len = 4;
2555 lock.l_pid = getpid();
2557 ret = fcntl(fd,F_SETLK,&lock);
2558 if (ret == -1) {
2559 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2560 local_pathname, strerror(errno));
2561 exit(1);
2562 } else {
2563 printf("child: got lock 0:4 on file %s.\n",
2564 local_pathname );
2565 fflush(stdout);
2568 CatchSignal(SIGALRM, alarm_handler);
2569 alarm(5);
2570 /* Signal the parent. */
2571 if (write(write_fd, &c, 1) != 1) {
2572 printf("child: start signal fail %s.\n",
2573 strerror(errno));
2574 exit(1);
2576 alarm(0);
2578 alarm(10);
2579 /* Wait for the parent to be ready. */
2580 if (read(read_fd, &c, 1) != 1) {
2581 printf("child: reply signal fail %s.\n",
2582 strerror(errno));
2583 exit(1);
2585 alarm(0);
2587 sleep(5);
2588 close(fd);
2589 printf("child: released lock 0:4 on file %s.\n",
2590 local_pathname );
2591 fflush(stdout);
2592 exit(0);
2595 static bool run_locktest9(int dummy)
2597 struct cli_state *cli1;
2598 const char *fname = "\\lockt9.lck";
2599 uint16_t fnum;
2600 bool correct = False;
2601 int pipe_in[2], pipe_out[2];
2602 pid_t child_pid;
2603 char c = '\0';
2604 int ret;
2605 struct timeval start;
2606 double seconds;
2607 NTSTATUS status;
2609 printf("starting locktest9\n");
2611 if (local_path == NULL) {
2612 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2613 return false;
2616 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2617 return false;
2620 child_pid = fork();
2621 if (child_pid == -1) {
2622 return false;
2625 if (child_pid == 0) {
2626 /* Child. */
2627 do_local_lock(pipe_out[0], pipe_in[1]);
2628 exit(0);
2631 close(pipe_out[0]);
2632 close(pipe_in[1]);
2633 pipe_out[0] = -1;
2634 pipe_in[1] = -1;
2636 /* Parent. */
2637 ret = read(pipe_in[0], &c, 1);
2638 if (ret != 1) {
2639 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2640 strerror(errno));
2641 return false;
2644 if (!torture_open_connection(&cli1, 0)) {
2645 return false;
2648 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2650 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE,
2651 &fnum);
2652 if (!NT_STATUS_IS_OK(status)) {
2653 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2654 return false;
2657 /* Ensure the child has the lock. */
2658 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2659 if (NT_STATUS_IS_OK(status)) {
2660 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2661 goto fail;
2662 } else {
2663 d_printf("Child has the lock.\n");
2666 /* Tell the child to wait 5 seconds then exit. */
2667 ret = write(pipe_out[1], &c, 1);
2668 if (ret != 1) {
2669 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2670 strerror(errno));
2671 goto fail;
2674 /* Wait 20 seconds for the lock. */
2675 alarm_cli = cli1;
2676 CatchSignal(SIGALRM, alarm_handler_parent);
2677 alarm(20);
2679 start = timeval_current();
2681 status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2682 if (!NT_STATUS_IS_OK(status)) {
2683 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2684 "%s\n", nt_errstr(status));
2685 goto fail_nofd;
2687 alarm(0);
2689 seconds = timeval_elapsed(&start);
2691 printf("Parent got the lock after %.2f seconds.\n",
2692 seconds);
2694 status = cli_close(cli1, fnum);
2695 if (!NT_STATUS_IS_OK(status)) {
2696 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2697 goto fail;
2700 correct = true;
2702 fail:
2703 cli_close(cli1, fnum);
2704 torture_close_connection(cli1);
2706 fail_nofd:
2708 printf("finished locktest9\n");
2709 return correct;
2713 test whether fnums and tids open on one VC are available on another (a major
2714 security hole)
2716 static bool run_fdpasstest(int dummy)
2718 struct cli_state *cli1, *cli2;
2719 const char *fname = "\\fdpass.tst";
2720 uint16_t fnum1;
2721 char buf[1024];
2722 NTSTATUS status;
2724 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2725 return False;
2727 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2728 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2730 printf("starting fdpasstest\n");
2732 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2734 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2735 &fnum1);
2736 if (!NT_STATUS_IS_OK(status)) {
2737 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2738 return False;
2741 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2742 13, NULL);
2743 if (!NT_STATUS_IS_OK(status)) {
2744 printf("write failed (%s)\n", nt_errstr(status));
2745 return False;
2748 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
2749 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2750 cli_setpid(cli2, cli_getpid(cli1));
2752 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
2753 printf("read succeeded! nasty security hole [%s]\n", buf);
2754 return false;
2757 cli_close(cli1, fnum1);
2758 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2760 torture_close_connection(cli1);
2761 torture_close_connection(cli2);
2763 printf("finished fdpasstest\n");
2764 return True;
2767 static bool run_fdsesstest(int dummy)
2769 struct cli_state *cli;
2770 uint16_t new_vuid;
2771 uint16_t saved_vuid;
2772 uint16_t new_cnum;
2773 uint16_t saved_cnum;
2774 const char *fname = "\\fdsess.tst";
2775 const char *fname1 = "\\fdsess1.tst";
2776 uint16_t fnum1;
2777 uint16_t fnum2;
2778 char buf[1024];
2779 bool ret = True;
2780 NTSTATUS status;
2782 if (!torture_open_connection(&cli, 0))
2783 return False;
2784 smbXcli_conn_set_sockopt(cli->conn, sockops);
2786 if (!torture_cli_session_setup2(cli, &new_vuid))
2787 return False;
2789 saved_cnum = cli_state_get_tid(cli);
2790 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", "", 1)))
2791 return False;
2792 new_cnum = cli_state_get_tid(cli);
2793 cli_state_set_tid(cli, saved_cnum);
2795 printf("starting fdsesstest\n");
2797 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2798 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2800 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2801 if (!NT_STATUS_IS_OK(status)) {
2802 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2803 return False;
2806 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2807 NULL);
2808 if (!NT_STATUS_IS_OK(status)) {
2809 printf("write failed (%s)\n", nt_errstr(status));
2810 return False;
2813 saved_vuid = cli_state_get_uid(cli);
2814 cli_state_set_uid(cli, new_vuid);
2816 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2817 printf("read succeeded with different vuid! "
2818 "nasty security hole [%s]\n", buf);
2819 ret = false;
2821 /* Try to open a file with different vuid, samba cnum. */
2822 if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2823 printf("create with different vuid, same cnum succeeded.\n");
2824 cli_close(cli, fnum2);
2825 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2826 } else {
2827 printf("create with different vuid, same cnum failed.\n");
2828 printf("This will cause problems with service clients.\n");
2829 ret = False;
2832 cli_state_set_uid(cli, saved_vuid);
2834 /* Try with same vuid, different cnum. */
2835 cli_state_set_tid(cli, new_cnum);
2837 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2838 printf("read succeeded with different cnum![%s]\n", buf);
2839 ret = false;
2842 cli_state_set_tid(cli, saved_cnum);
2843 cli_close(cli, fnum1);
2844 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2846 torture_close_connection(cli);
2848 printf("finished fdsesstest\n");
2849 return ret;
2853 This test checks that
2855 1) the server does not allow an unlink on a file that is open
2857 static bool run_unlinktest(int dummy)
2859 struct cli_state *cli;
2860 const char *fname = "\\unlink.tst";
2861 uint16_t fnum;
2862 bool correct = True;
2863 NTSTATUS status;
2865 if (!torture_open_connection(&cli, 0)) {
2866 return False;
2869 smbXcli_conn_set_sockopt(cli->conn, sockops);
2871 printf("starting unlink test\n");
2873 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2875 cli_setpid(cli, 1);
2877 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2878 if (!NT_STATUS_IS_OK(status)) {
2879 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2880 return False;
2883 status = cli_unlink(cli, fname,
2884 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2885 if (NT_STATUS_IS_OK(status)) {
2886 printf("error: server allowed unlink on an open file\n");
2887 correct = False;
2888 } else {
2889 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
2890 NT_STATUS_SHARING_VIOLATION);
2893 cli_close(cli, fnum);
2894 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2896 if (!torture_close_connection(cli)) {
2897 correct = False;
2900 printf("unlink test finished\n");
2902 return correct;
2907 test how many open files this server supports on the one socket
2909 static bool run_maxfidtest(int dummy)
2911 struct cli_state *cli;
2912 fstring fname;
2913 uint16_t fnums[0x11000];
2914 int i;
2915 int retries=4;
2916 bool correct = True;
2917 NTSTATUS status;
2919 cli = current_cli;
2921 if (retries <= 0) {
2922 printf("failed to connect\n");
2923 return False;
2926 smbXcli_conn_set_sockopt(cli->conn, sockops);
2928 for (i=0; i<0x11000; i++) {
2929 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2930 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2931 &fnums[i]);
2932 if (!NT_STATUS_IS_OK(status)) {
2933 printf("open of %s failed (%s)\n",
2934 fname, nt_errstr(status));
2935 printf("maximum fnum is %d\n", i);
2936 break;
2938 printf("%6d\r", i);
2940 printf("%6d\n", i);
2941 i--;
2943 printf("cleaning up\n");
2944 for (;i>=0;i--) {
2945 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2946 cli_close(cli, fnums[i]);
2948 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2949 if (!NT_STATUS_IS_OK(status)) {
2950 printf("unlink of %s failed (%s)\n",
2951 fname, nt_errstr(status));
2952 correct = False;
2954 printf("%6d\r", i);
2956 printf("%6d\n", 0);
2958 printf("maxfid test finished\n");
2959 if (!torture_close_connection(cli)) {
2960 correct = False;
2962 return correct;
2965 /* generate a random buffer */
2966 static void rand_buf(char *buf, int len)
2968 while (len--) {
2969 *buf = (char)sys_random();
2970 buf++;
2974 /* send smb negprot commands, not reading the response */
2975 static bool run_negprot_nowait(int dummy)
2977 struct tevent_context *ev;
2978 int i;
2979 struct cli_state *cli;
2980 bool correct = True;
2982 printf("starting negprot nowait test\n");
2984 ev = samba_tevent_context_init(talloc_tos());
2985 if (ev == NULL) {
2986 return false;
2989 if (!(cli = open_nbt_connection())) {
2990 TALLOC_FREE(ev);
2991 return False;
2994 for (i=0;i<50000;i++) {
2995 struct tevent_req *req;
2997 req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
2998 PROTOCOL_CORE, PROTOCOL_NT1);
2999 if (req == NULL) {
3000 TALLOC_FREE(ev);
3001 return false;
3003 if (!tevent_req_poll(req, ev)) {
3004 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3005 strerror(errno));
3006 TALLOC_FREE(ev);
3007 return false;
3009 TALLOC_FREE(req);
3012 if (torture_close_connection(cli)) {
3013 correct = False;
3016 printf("finished negprot nowait test\n");
3018 return correct;
3021 /* send smb negprot commands, not reading the response */
3022 static bool run_bad_nbt_session(int dummy)
3024 struct nmb_name called, calling;
3025 struct sockaddr_storage ss;
3026 NTSTATUS status;
3027 int fd;
3028 bool ret;
3030 printf("starting bad nbt session test\n");
3032 make_nmb_name(&calling, myname, 0x0);
3033 make_nmb_name(&called , host, 0x20);
3035 if (!resolve_name(host, &ss, 0x20, true)) {
3036 d_fprintf(stderr, "Could not resolve name %s\n", host);
3037 return false;
3040 status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3041 if (!NT_STATUS_IS_OK(status)) {
3042 d_fprintf(stderr, "open_socket_out failed: %s\n",
3043 nt_errstr(status));
3044 return false;
3047 ret = cli_bad_session_request(fd, &calling, &called);
3048 close(fd);
3049 if (!ret) {
3050 d_fprintf(stderr, "open_socket_out failed: %s\n",
3051 nt_errstr(status));
3052 return false;
3055 printf("finished bad nbt session test\n");
3056 return true;
3059 /* send random IPC commands */
3060 static bool run_randomipc(int dummy)
3062 char *rparam = NULL;
3063 char *rdata = NULL;
3064 unsigned int rdrcnt,rprcnt;
3065 char param[1024];
3066 int api, param_len, i;
3067 struct cli_state *cli;
3068 bool correct = True;
3069 int count = 50000;
3071 printf("starting random ipc test\n");
3073 if (!torture_open_connection(&cli, 0)) {
3074 return False;
3077 for (i=0;i<count;i++) {
3078 api = sys_random() % 500;
3079 param_len = (sys_random() % 64);
3081 rand_buf(param, param_len);
3083 SSVAL(param,0,api);
3085 cli_api(cli,
3086 param, param_len, 8,
3087 NULL, 0, CLI_BUFFER_SIZE,
3088 &rparam, &rprcnt,
3089 &rdata, &rdrcnt);
3090 if (i % 100 == 0) {
3091 printf("%d/%d\r", i,count);
3094 printf("%d/%d\n", i, count);
3096 if (!torture_close_connection(cli)) {
3097 correct = False;
3100 SAFE_FREE(rparam);
3101 SAFE_FREE(rdata);
3103 printf("finished random ipc test\n");
3105 return correct;
3110 static void browse_callback(const char *sname, uint32_t stype,
3111 const char *comment, void *state)
3113 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3119 This test checks the browse list code
3122 static bool run_browsetest(int dummy)
3124 static struct cli_state *cli;
3125 bool correct = True;
3127 printf("starting browse test\n");
3129 if (!torture_open_connection(&cli, 0)) {
3130 return False;
3133 printf("domain list:\n");
3134 cli_NetServerEnum(cli, cli->server_domain,
3135 SV_TYPE_DOMAIN_ENUM,
3136 browse_callback, NULL);
3138 printf("machine list:\n");
3139 cli_NetServerEnum(cli, cli->server_domain,
3140 SV_TYPE_ALL,
3141 browse_callback, NULL);
3143 if (!torture_close_connection(cli)) {
3144 correct = False;
3147 printf("browse test finished\n");
3149 return correct;
3155 This checks how the getatr calls works
3157 static bool run_attrtest(int dummy)
3159 struct cli_state *cli;
3160 uint16_t fnum;
3161 time_t t, t2;
3162 const char *fname = "\\attrib123456789.tst";
3163 bool correct = True;
3164 NTSTATUS status;
3166 printf("starting attrib test\n");
3168 if (!torture_open_connection(&cli, 0)) {
3169 return False;
3172 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3173 cli_openx(cli, fname,
3174 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3175 cli_close(cli, fnum);
3177 status = cli_getatr(cli, fname, NULL, NULL, &t);
3178 if (!NT_STATUS_IS_OK(status)) {
3179 printf("getatr failed (%s)\n", nt_errstr(status));
3180 correct = False;
3183 if (abs(t - time(NULL)) > 60*60*24*10) {
3184 printf("ERROR: SMBgetatr bug. time is %s",
3185 ctime(&t));
3186 t = time(NULL);
3187 correct = True;
3190 t2 = t-60*60*24; /* 1 day ago */
3192 status = cli_setatr(cli, fname, 0, t2);
3193 if (!NT_STATUS_IS_OK(status)) {
3194 printf("setatr failed (%s)\n", nt_errstr(status));
3195 correct = True;
3198 status = cli_getatr(cli, fname, NULL, NULL, &t);
3199 if (!NT_STATUS_IS_OK(status)) {
3200 printf("getatr failed (%s)\n", nt_errstr(status));
3201 correct = True;
3204 if (t != t2) {
3205 printf("ERROR: getatr/setatr bug. times are\n%s",
3206 ctime(&t));
3207 printf("%s", ctime(&t2));
3208 correct = True;
3211 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3213 if (!torture_close_connection(cli)) {
3214 correct = False;
3217 printf("attrib test finished\n");
3219 return correct;
3224 This checks a couple of trans2 calls
3226 static bool run_trans2test(int dummy)
3228 struct cli_state *cli;
3229 uint16_t fnum;
3230 off_t size;
3231 time_t c_time, a_time, m_time;
3232 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3233 const char *fname = "\\trans2.tst";
3234 const char *dname = "\\trans2";
3235 const char *fname2 = "\\trans2\\trans2.tst";
3236 char *pname;
3237 bool correct = True;
3238 NTSTATUS status;
3239 uint32_t fs_attr;
3241 printf("starting trans2 test\n");
3243 if (!torture_open_connection(&cli, 0)) {
3244 return False;
3247 status = cli_get_fs_attr_info(cli, &fs_attr);
3248 if (!NT_STATUS_IS_OK(status)) {
3249 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3250 nt_errstr(status));
3251 correct = false;
3254 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3255 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3256 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3257 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3258 if (!NT_STATUS_IS_OK(status)) {
3259 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3260 correct = False;
3263 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3264 if (!NT_STATUS_IS_OK(status)) {
3265 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3266 correct = False;
3268 else if (strcmp(pname, fname)) {
3269 printf("qfilename gave different name? [%s] [%s]\n",
3270 fname, pname);
3271 correct = False;
3274 cli_close(cli, fnum);
3276 sleep(2);
3278 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3279 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3280 &fnum);
3281 if (!NT_STATUS_IS_OK(status)) {
3282 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3283 return False;
3285 cli_close(cli, fnum);
3287 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3288 NULL);
3289 if (!NT_STATUS_IS_OK(status)) {
3290 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3291 correct = False;
3292 } else {
3293 time_t t = time(NULL);
3295 if (c_time != m_time) {
3296 printf("create time=%s", ctime(&c_time));
3297 printf("modify time=%s", ctime(&m_time));
3298 printf("This system appears to have sticky create times\n");
3300 if ((abs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
3301 printf("access time=%s", ctime(&a_time));
3302 printf("This system appears to set a midnight access time\n");
3303 correct = False;
3306 if (abs(m_time - t) > 60*60*24*7) {
3307 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3308 correct = False;
3313 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3314 cli_openx(cli, fname,
3315 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3316 cli_close(cli, fnum);
3317 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3318 &m_time_ts, &size, NULL, NULL);
3319 if (!NT_STATUS_IS_OK(status)) {
3320 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3321 correct = False;
3322 } else {
3323 if (w_time_ts.tv_sec < 60*60*24*2) {
3324 printf("write time=%s", ctime(&w_time_ts.tv_sec));
3325 printf("This system appears to set a initial 0 write time\n");
3326 correct = False;
3330 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3333 /* check if the server updates the directory modification time
3334 when creating a new file */
3335 status = cli_mkdir(cli, dname);
3336 if (!NT_STATUS_IS_OK(status)) {
3337 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3338 correct = False;
3340 sleep(3);
3341 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3342 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3343 if (!NT_STATUS_IS_OK(status)) {
3344 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3345 correct = False;
3348 cli_openx(cli, fname2,
3349 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3350 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3351 cli_close(cli, fnum);
3352 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3353 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3354 if (!NT_STATUS_IS_OK(status)) {
3355 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3356 correct = False;
3357 } else {
3358 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3359 == 0) {
3360 printf("This system does not update directory modification times\n");
3361 correct = False;
3364 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3365 cli_rmdir(cli, dname);
3367 if (!torture_close_connection(cli)) {
3368 correct = False;
3371 printf("trans2 test finished\n");
3373 return correct;
3377 This checks new W2K calls.
3380 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3382 uint8_t *buf = NULL;
3383 uint32_t len;
3384 NTSTATUS status;
3386 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3387 CLI_BUFFER_SIZE, NULL, &buf, &len);
3388 if (!NT_STATUS_IS_OK(status)) {
3389 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3390 nt_errstr(status));
3391 } else {
3392 printf("qfileinfo: level %d, len = %u\n", level, len);
3393 dump_data(0, (uint8_t *)buf, len);
3394 printf("\n");
3396 TALLOC_FREE(buf);
3397 return status;
3400 static bool run_w2ktest(int dummy)
3402 struct cli_state *cli;
3403 uint16_t fnum;
3404 const char *fname = "\\w2ktest\\w2k.tst";
3405 int level;
3406 bool correct = True;
3408 printf("starting w2k test\n");
3410 if (!torture_open_connection(&cli, 0)) {
3411 return False;
3414 cli_openx(cli, fname,
3415 O_RDWR | O_CREAT , DENY_NONE, &fnum);
3417 for (level = 1004; level < 1040; level++) {
3418 new_trans(cli, fnum, level);
3421 cli_close(cli, fnum);
3423 if (!torture_close_connection(cli)) {
3424 correct = False;
3427 printf("w2k test finished\n");
3429 return correct;
3434 this is a harness for some oplock tests
3436 static bool run_oplock1(int dummy)
3438 struct cli_state *cli1;
3439 const char *fname = "\\lockt1.lck";
3440 uint16_t fnum1;
3441 bool correct = True;
3442 NTSTATUS status;
3444 printf("starting oplock test 1\n");
3446 if (!torture_open_connection(&cli1, 0)) {
3447 return False;
3450 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3452 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3454 cli1->use_oplocks = True;
3456 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3457 &fnum1);
3458 if (!NT_STATUS_IS_OK(status)) {
3459 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3460 return False;
3463 cli1->use_oplocks = False;
3465 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3466 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3468 status = cli_close(cli1, fnum1);
3469 if (!NT_STATUS_IS_OK(status)) {
3470 printf("close2 failed (%s)\n", nt_errstr(status));
3471 return False;
3474 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3475 if (!NT_STATUS_IS_OK(status)) {
3476 printf("unlink failed (%s)\n", nt_errstr(status));
3477 return False;
3480 if (!torture_close_connection(cli1)) {
3481 correct = False;
3484 printf("finished oplock test 1\n");
3486 return correct;
3489 static bool run_oplock2(int dummy)
3491 struct cli_state *cli1, *cli2;
3492 const char *fname = "\\lockt2.lck";
3493 uint16_t fnum1, fnum2;
3494 int saved_use_oplocks = use_oplocks;
3495 char buf[4];
3496 bool correct = True;
3497 volatile bool *shared_correct;
3498 size_t nread;
3499 NTSTATUS status;
3501 shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
3502 *shared_correct = True;
3504 use_level_II_oplocks = True;
3505 use_oplocks = True;
3507 printf("starting oplock test 2\n");
3509 if (!torture_open_connection(&cli1, 0)) {
3510 use_level_II_oplocks = False;
3511 use_oplocks = saved_use_oplocks;
3512 return False;
3515 if (!torture_open_connection(&cli2, 1)) {
3516 use_level_II_oplocks = False;
3517 use_oplocks = saved_use_oplocks;
3518 return False;
3521 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3523 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3524 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3526 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3527 &fnum1);
3528 if (!NT_STATUS_IS_OK(status)) {
3529 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3530 return False;
3533 /* Don't need the globals any more. */
3534 use_level_II_oplocks = False;
3535 use_oplocks = saved_use_oplocks;
3537 if (fork() == 0) {
3538 /* Child code */
3539 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3540 if (!NT_STATUS_IS_OK(status)) {
3541 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3542 *shared_correct = False;
3543 exit(0);
3546 sleep(2);
3548 status = cli_close(cli2, fnum2);
3549 if (!NT_STATUS_IS_OK(status)) {
3550 printf("close2 failed (%s)\n", nt_errstr(status));
3551 *shared_correct = False;
3554 exit(0);
3557 sleep(2);
3559 /* Ensure cli1 processes the break. Empty file should always return 0
3560 * bytes. */
3561 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
3562 if (!NT_STATUS_IS_OK(status)) {
3563 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
3564 correct = false;
3565 } else if (nread != 0) {
3566 printf("read on empty fnum1 failed. recv %ld expected %d\n",
3567 (unsigned long)nread, 0);
3568 correct = false;
3571 /* Should now be at level II. */
3572 /* Test if sending a write locks causes a break to none. */
3573 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3574 if (!NT_STATUS_IS_OK(status)) {
3575 printf("lock failed (%s)\n", nt_errstr(status));
3576 correct = False;
3579 cli_unlock(cli1, fnum1, 0, 4);
3581 sleep(2);
3583 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3584 if (!NT_STATUS_IS_OK(status)) {
3585 printf("lock failed (%s)\n", nt_errstr(status));
3586 correct = False;
3589 cli_unlock(cli1, fnum1, 0, 4);
3591 sleep(2);
3593 cli_read(cli1, fnum1, buf, 0, 4, NULL);
3595 status = cli_close(cli1, fnum1);
3596 if (!NT_STATUS_IS_OK(status)) {
3597 printf("close1 failed (%s)\n", nt_errstr(status));
3598 correct = False;
3601 sleep(4);
3603 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3604 if (!NT_STATUS_IS_OK(status)) {
3605 printf("unlink failed (%s)\n", nt_errstr(status));
3606 correct = False;
3609 if (!torture_close_connection(cli1)) {
3610 correct = False;
3613 if (!*shared_correct) {
3614 correct = False;
3617 printf("finished oplock test 2\n");
3619 return correct;
3622 struct oplock4_state {
3623 struct tevent_context *ev;
3624 struct cli_state *cli;
3625 bool *got_break;
3626 uint16_t *fnum2;
3629 static void oplock4_got_break(struct tevent_req *req);
3630 static void oplock4_got_open(struct tevent_req *req);
3632 static bool run_oplock4(int dummy)
3634 struct tevent_context *ev;
3635 struct cli_state *cli1, *cli2;
3636 struct tevent_req *oplock_req, *open_req;
3637 const char *fname = "\\lockt4.lck";
3638 const char *fname_ln = "\\lockt4_ln.lck";
3639 uint16_t fnum1, fnum2;
3640 int saved_use_oplocks = use_oplocks;
3641 NTSTATUS status;
3642 bool correct = true;
3644 bool got_break;
3646 struct oplock4_state *state;
3648 printf("starting oplock test 4\n");
3650 if (!torture_open_connection(&cli1, 0)) {
3651 use_level_II_oplocks = false;
3652 use_oplocks = saved_use_oplocks;
3653 return false;
3656 if (!torture_open_connection(&cli2, 1)) {
3657 use_level_II_oplocks = false;
3658 use_oplocks = saved_use_oplocks;
3659 return false;
3662 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3663 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3665 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3666 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3668 /* Create the file. */
3669 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3670 &fnum1);
3671 if (!NT_STATUS_IS_OK(status)) {
3672 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3673 return false;
3676 status = cli_close(cli1, fnum1);
3677 if (!NT_STATUS_IS_OK(status)) {
3678 printf("close1 failed (%s)\n", nt_errstr(status));
3679 return false;
3682 /* Now create a hardlink. */
3683 status = cli_nt_hardlink(cli1, fname, fname_ln);
3684 if (!NT_STATUS_IS_OK(status)) {
3685 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3686 return false;
3689 /* Prove that opening hardlinks cause deny modes to conflict. */
3690 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3691 if (!NT_STATUS_IS_OK(status)) {
3692 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3693 return false;
3696 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3697 if (NT_STATUS_IS_OK(status)) {
3698 printf("open of %s succeeded - should fail with sharing violation.\n",
3699 fname_ln);
3700 return false;
3703 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3704 printf("open of %s should fail with sharing violation. Got %s\n",
3705 fname_ln, nt_errstr(status));
3706 return false;
3709 status = cli_close(cli1, fnum1);
3710 if (!NT_STATUS_IS_OK(status)) {
3711 printf("close1 failed (%s)\n", nt_errstr(status));
3712 return false;
3715 cli1->use_oplocks = true;
3716 cli2->use_oplocks = true;
3718 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3719 if (!NT_STATUS_IS_OK(status)) {
3720 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3721 return false;
3724 ev = samba_tevent_context_init(talloc_tos());
3725 if (ev == NULL) {
3726 printf("tevent_context_init failed\n");
3727 return false;
3730 state = talloc(ev, struct oplock4_state);
3731 if (state == NULL) {
3732 printf("talloc failed\n");
3733 return false;
3735 state->ev = ev;
3736 state->cli = cli1;
3737 state->got_break = &got_break;
3738 state->fnum2 = &fnum2;
3740 oplock_req = cli_smb_oplock_break_waiter_send(
3741 talloc_tos(), ev, cli1);
3742 if (oplock_req == NULL) {
3743 printf("cli_smb_oplock_break_waiter_send failed\n");
3744 return false;
3746 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3748 open_req = cli_openx_send(
3749 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3750 if (open_req == NULL) {
3751 printf("cli_openx_send failed\n");
3752 return false;
3754 tevent_req_set_callback(open_req, oplock4_got_open, state);
3756 got_break = false;
3757 fnum2 = 0xffff;
3759 while (!got_break || fnum2 == 0xffff) {
3760 int ret;
3761 ret = tevent_loop_once(ev);
3762 if (ret == -1) {
3763 printf("tevent_loop_once failed: %s\n",
3764 strerror(errno));
3765 return false;
3769 status = cli_close(cli2, fnum2);
3770 if (!NT_STATUS_IS_OK(status)) {
3771 printf("close2 failed (%s)\n", nt_errstr(status));
3772 correct = false;
3775 status = cli_close(cli1, fnum1);
3776 if (!NT_STATUS_IS_OK(status)) {
3777 printf("close1 failed (%s)\n", nt_errstr(status));
3778 correct = false;
3781 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3782 if (!NT_STATUS_IS_OK(status)) {
3783 printf("unlink failed (%s)\n", nt_errstr(status));
3784 correct = false;
3787 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3788 if (!NT_STATUS_IS_OK(status)) {
3789 printf("unlink failed (%s)\n", nt_errstr(status));
3790 correct = false;
3793 if (!torture_close_connection(cli1)) {
3794 correct = false;
3797 if (!got_break) {
3798 correct = false;
3801 printf("finished oplock test 4\n");
3803 return correct;
3806 static void oplock4_got_break(struct tevent_req *req)
3808 struct oplock4_state *state = tevent_req_callback_data(
3809 req, struct oplock4_state);
3810 uint16_t fnum;
3811 uint8_t level;
3812 NTSTATUS status;
3814 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3815 TALLOC_FREE(req);
3816 if (!NT_STATUS_IS_OK(status)) {
3817 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3818 nt_errstr(status));
3819 return;
3821 *state->got_break = true;
3823 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3824 NO_OPLOCK);
3825 if (req == NULL) {
3826 printf("cli_oplock_ack_send failed\n");
3827 return;
3831 static void oplock4_got_open(struct tevent_req *req)
3833 struct oplock4_state *state = tevent_req_callback_data(
3834 req, struct oplock4_state);
3835 NTSTATUS status;
3837 status = cli_openx_recv(req, state->fnum2);
3838 if (!NT_STATUS_IS_OK(status)) {
3839 printf("cli_openx_recv returned %s\n", nt_errstr(status));
3840 *state->fnum2 = 0xffff;
3845 Test delete on close semantics.
3847 static bool run_deletetest(int dummy)
3849 struct cli_state *cli1 = NULL;
3850 struct cli_state *cli2 = NULL;
3851 const char *fname = "\\delete.file";
3852 uint16_t fnum1 = (uint16_t)-1;
3853 uint16_t fnum2 = (uint16_t)-1;
3854 bool correct = false;
3855 NTSTATUS status;
3857 printf("starting delete test\n");
3859 if (!torture_open_connection(&cli1, 0)) {
3860 return False;
3863 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3865 /* Test 1 - this should delete the file on close. */
3867 cli_setatr(cli1, fname, 0, 0);
3868 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3870 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3871 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3872 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
3873 if (!NT_STATUS_IS_OK(status)) {
3874 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3875 goto fail;
3878 status = cli_close(cli1, fnum1);
3879 if (!NT_STATUS_IS_OK(status)) {
3880 printf("[1] close failed (%s)\n", nt_errstr(status));
3881 goto fail;
3884 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3885 if (NT_STATUS_IS_OK(status)) {
3886 printf("[1] open of %s succeeded (should fail)\n", fname);
3887 goto fail;
3890 printf("first delete on close test succeeded.\n");
3892 /* Test 2 - this should delete the file on close. */
3894 cli_setatr(cli1, fname, 0, 0);
3895 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3897 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3898 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3899 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
3900 if (!NT_STATUS_IS_OK(status)) {
3901 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3902 goto fail;
3905 status = cli_nt_delete_on_close(cli1, fnum1, true);
3906 if (!NT_STATUS_IS_OK(status)) {
3907 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3908 goto fail;
3911 status = cli_close(cli1, fnum1);
3912 if (!NT_STATUS_IS_OK(status)) {
3913 printf("[2] close failed (%s)\n", nt_errstr(status));
3914 goto fail;
3917 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
3918 if (NT_STATUS_IS_OK(status)) {
3919 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3920 status = cli_close(cli1, fnum1);
3921 if (!NT_STATUS_IS_OK(status)) {
3922 printf("[2] close failed (%s)\n", nt_errstr(status));
3924 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3925 goto fail;
3928 printf("second delete on close test succeeded.\n");
3930 /* Test 3 - ... */
3931 cli_setatr(cli1, fname, 0, 0);
3932 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3934 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3935 FILE_ATTRIBUTE_NORMAL,
3936 FILE_SHARE_READ|FILE_SHARE_WRITE,
3937 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
3938 if (!NT_STATUS_IS_OK(status)) {
3939 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
3940 goto fail;
3943 /* This should fail with a sharing violation - open for delete is only compatible
3944 with SHARE_DELETE. */
3946 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3947 FILE_ATTRIBUTE_NORMAL,
3948 FILE_SHARE_READ|FILE_SHARE_WRITE,
3949 FILE_OPEN, 0, 0, &fnum2, NULL);
3950 if (NT_STATUS_IS_OK(status)) {
3951 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
3952 goto fail;
3955 /* This should succeed. */
3956 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3957 FILE_ATTRIBUTE_NORMAL,
3958 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3959 FILE_OPEN, 0, 0, &fnum2, NULL);
3960 if (!NT_STATUS_IS_OK(status)) {
3961 printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
3962 goto fail;
3965 status = cli_nt_delete_on_close(cli1, fnum1, true);
3966 if (!NT_STATUS_IS_OK(status)) {
3967 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
3968 goto fail;
3971 status = cli_close(cli1, fnum1);
3972 if (!NT_STATUS_IS_OK(status)) {
3973 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
3974 goto fail;
3977 status = cli_close(cli1, fnum2);
3978 if (!NT_STATUS_IS_OK(status)) {
3979 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
3980 goto fail;
3983 /* This should fail - file should no longer be there. */
3985 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
3986 if (NT_STATUS_IS_OK(status)) {
3987 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
3988 status = cli_close(cli1, fnum1);
3989 if (!NT_STATUS_IS_OK(status)) {
3990 printf("[3] close failed (%s)\n", nt_errstr(status));
3992 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3993 goto fail;
3996 printf("third delete on close test succeeded.\n");
3998 /* Test 4 ... */
3999 cli_setatr(cli1, fname, 0, 0);
4000 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4002 status = cli_ntcreate(cli1, fname, 0,
4003 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4004 FILE_ATTRIBUTE_NORMAL,
4005 FILE_SHARE_READ|FILE_SHARE_WRITE,
4006 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4007 if (!NT_STATUS_IS_OK(status)) {
4008 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4009 goto fail;
4012 /* This should succeed. */
4013 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4014 FILE_ATTRIBUTE_NORMAL,
4015 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4016 FILE_OPEN, 0, 0, &fnum2, NULL);
4017 if (!NT_STATUS_IS_OK(status)) {
4018 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4019 goto fail;
4022 status = cli_close(cli1, fnum2);
4023 if (!NT_STATUS_IS_OK(status)) {
4024 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4025 goto fail;
4028 status = cli_nt_delete_on_close(cli1, fnum1, true);
4029 if (!NT_STATUS_IS_OK(status)) {
4030 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4031 goto fail;
4034 /* This should fail - no more opens once delete on close set. */
4035 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4036 FILE_ATTRIBUTE_NORMAL,
4037 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4038 FILE_OPEN, 0, 0, &fnum2, NULL);
4039 if (NT_STATUS_IS_OK(status)) {
4040 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
4041 goto fail;
4044 status = cli_close(cli1, fnum1);
4045 if (!NT_STATUS_IS_OK(status)) {
4046 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4047 goto fail;
4050 printf("fourth delete on close test succeeded.\n");
4052 /* Test 5 ... */
4053 cli_setatr(cli1, fname, 0, 0);
4054 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4056 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4057 if (!NT_STATUS_IS_OK(status)) {
4058 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4059 goto fail;
4062 /* This should fail - only allowed on NT opens with DELETE access. */
4064 status = cli_nt_delete_on_close(cli1, fnum1, true);
4065 if (NT_STATUS_IS_OK(status)) {
4066 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4067 goto fail;
4070 status = cli_close(cli1, fnum1);
4071 if (!NT_STATUS_IS_OK(status)) {
4072 printf("[5] close failed (%s)\n", nt_errstr(status));
4073 goto fail;
4076 printf("fifth delete on close test succeeded.\n");
4078 /* Test 6 ... */
4079 cli_setatr(cli1, fname, 0, 0);
4080 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4082 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4083 FILE_ATTRIBUTE_NORMAL,
4084 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4085 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4086 if (!NT_STATUS_IS_OK(status)) {
4087 printf("[6] open of %s failed (%s)\n", fname,
4088 nt_errstr(status));
4089 goto fail;
4092 /* This should fail - only allowed on NT opens with DELETE access. */
4094 status = cli_nt_delete_on_close(cli1, fnum1, true);
4095 if (NT_STATUS_IS_OK(status)) {
4096 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4097 goto fail;
4100 status = cli_close(cli1, fnum1);
4101 if (!NT_STATUS_IS_OK(status)) {
4102 printf("[6] close failed (%s)\n", nt_errstr(status));
4103 goto fail;
4106 printf("sixth delete on close test succeeded.\n");
4108 /* Test 7 ... */
4109 cli_setatr(cli1, fname, 0, 0);
4110 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4112 status = cli_ntcreate(cli1, fname, 0,
4113 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4114 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4115 0, 0, &fnum1, NULL);
4116 if (!NT_STATUS_IS_OK(status)) {
4117 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4118 goto fail;
4121 status = cli_nt_delete_on_close(cli1, fnum1, true);
4122 if (!NT_STATUS_IS_OK(status)) {
4123 printf("[7] setting delete_on_close on file failed !\n");
4124 goto fail;
4127 status = cli_nt_delete_on_close(cli1, fnum1, false);
4128 if (!NT_STATUS_IS_OK(status)) {
4129 printf("[7] unsetting delete_on_close on file failed !\n");
4130 goto fail;
4133 status = cli_close(cli1, fnum1);
4134 if (!NT_STATUS_IS_OK(status)) {
4135 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
4136 goto fail;
4139 /* This next open should succeed - we reset the flag. */
4140 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4141 if (!NT_STATUS_IS_OK(status)) {
4142 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4143 goto fail;
4146 status = cli_close(cli1, fnum1);
4147 if (!NT_STATUS_IS_OK(status)) {
4148 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4149 goto fail;
4152 printf("seventh delete on close test succeeded.\n");
4154 /* Test 8 ... */
4155 cli_setatr(cli1, fname, 0, 0);
4156 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4158 if (!torture_open_connection(&cli2, 1)) {
4159 printf("[8] failed to open second connection.\n");
4160 goto fail;
4163 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4165 status = cli_ntcreate(cli1, fname, 0,
4166 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4167 FILE_ATTRIBUTE_NORMAL,
4168 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4169 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4170 if (!NT_STATUS_IS_OK(status)) {
4171 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4172 goto fail;
4175 status = cli_ntcreate(cli2, fname, 0,
4176 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4177 FILE_ATTRIBUTE_NORMAL,
4178 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4179 FILE_OPEN, 0, 0, &fnum2, NULL);
4180 if (!NT_STATUS_IS_OK(status)) {
4181 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4182 goto fail;
4185 status = cli_nt_delete_on_close(cli1, fnum1, true);
4186 if (!NT_STATUS_IS_OK(status)) {
4187 printf("[8] setting delete_on_close on file failed !\n");
4188 goto fail;
4191 status = cli_close(cli1, fnum1);
4192 if (!NT_STATUS_IS_OK(status)) {
4193 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4194 goto fail;
4197 status = cli_close(cli2, fnum2);
4198 if (!NT_STATUS_IS_OK(status)) {
4199 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4200 goto fail;
4203 /* This should fail.. */
4204 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4205 if (NT_STATUS_IS_OK(status)) {
4206 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4207 goto fail;
4210 printf("eighth delete on close test succeeded.\n");
4212 /* Test 9 ... */
4214 /* This should fail - we need to set DELETE_ACCESS. */
4215 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4216 FILE_ATTRIBUTE_NORMAL,
4217 FILE_SHARE_NONE,
4218 FILE_OVERWRITE_IF,
4219 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4220 if (NT_STATUS_IS_OK(status)) {
4221 printf("[9] open of %s succeeded should have failed!\n", fname);
4222 goto fail;
4225 printf("ninth delete on close test succeeded.\n");
4227 /* Test 10 ... */
4229 status = cli_ntcreate(cli1, fname, 0,
4230 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4231 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4232 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4233 0, &fnum1, NULL);
4234 if (!NT_STATUS_IS_OK(status)) {
4235 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4236 goto fail;
4239 /* This should delete the file. */
4240 status = cli_close(cli1, fnum1);
4241 if (!NT_STATUS_IS_OK(status)) {
4242 printf("[10] close failed (%s)\n", nt_errstr(status));
4243 goto fail;
4246 /* This should fail.. */
4247 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4248 if (NT_STATUS_IS_OK(status)) {
4249 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4250 goto fail;
4253 printf("tenth delete on close test succeeded.\n");
4255 /* Test 11 ... */
4257 cli_setatr(cli1, fname, 0, 0);
4258 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4260 /* Can we open a read-only file with delete access? */
4262 /* Create a readonly file. */
4263 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4264 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4265 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4266 if (!NT_STATUS_IS_OK(status)) {
4267 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4268 goto fail;
4271 status = cli_close(cli1, fnum1);
4272 if (!NT_STATUS_IS_OK(status)) {
4273 printf("[11] close failed (%s)\n", nt_errstr(status));
4274 goto fail;
4277 /* Now try open for delete access. */
4278 status = cli_ntcreate(cli1, fname, 0,
4279 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4281 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4282 FILE_OPEN, 0, 0, &fnum1, NULL);
4283 if (!NT_STATUS_IS_OK(status)) {
4284 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
4285 goto fail;
4288 cli_close(cli1, fnum1);
4290 printf("eleventh delete on close test succeeded.\n");
4293 * Test 12
4294 * like test 4 but with initial delete on close
4297 cli_setatr(cli1, fname, 0, 0);
4298 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4300 status = cli_ntcreate(cli1, fname, 0,
4301 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4302 FILE_ATTRIBUTE_NORMAL,
4303 FILE_SHARE_READ|FILE_SHARE_WRITE,
4304 FILE_OVERWRITE_IF,
4305 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4306 if (!NT_STATUS_IS_OK(status)) {
4307 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4308 goto fail;
4311 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4312 FILE_ATTRIBUTE_NORMAL,
4313 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4314 FILE_OPEN, 0, 0, &fnum2, NULL);
4315 if (!NT_STATUS_IS_OK(status)) {
4316 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
4317 goto fail;
4320 status = cli_close(cli1, fnum2);
4321 if (!NT_STATUS_IS_OK(status)) {
4322 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
4323 goto fail;
4326 status = cli_nt_delete_on_close(cli1, fnum1, true);
4327 if (!NT_STATUS_IS_OK(status)) {
4328 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
4329 goto fail;
4332 /* This should fail - no more opens once delete on close set. */
4333 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4334 FILE_ATTRIBUTE_NORMAL,
4335 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4336 FILE_OPEN, 0, 0, &fnum2, NULL);
4337 if (NT_STATUS_IS_OK(status)) {
4338 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
4339 goto fail;
4342 status = cli_nt_delete_on_close(cli1, fnum1, false);
4343 if (!NT_STATUS_IS_OK(status)) {
4344 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
4345 goto fail;
4348 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4349 FILE_ATTRIBUTE_NORMAL,
4350 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4351 FILE_OPEN, 0, 0, &fnum2, NULL);
4352 if (!NT_STATUS_IS_OK(status)) {
4353 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
4354 goto fail;
4357 status = cli_close(cli1, fnum2);
4358 if (!NT_STATUS_IS_OK(status)) {
4359 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
4360 goto fail;
4363 status = cli_close(cli1, fnum1);
4364 if (!NT_STATUS_IS_OK(status)) {
4365 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
4366 goto fail;
4370 * setting delete on close on the handle does
4371 * not unset the initial delete on close...
4373 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4374 FILE_ATTRIBUTE_NORMAL,
4375 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4376 FILE_OPEN, 0, 0, &fnum2, NULL);
4377 if (NT_STATUS_IS_OK(status)) {
4378 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
4379 goto fail;
4380 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4381 printf("ntcreate returned %s, expected "
4382 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
4383 nt_errstr(status));
4384 goto fail;
4387 printf("twelfth delete on close test succeeded.\n");
4390 printf("finished delete test\n");
4392 correct = true;
4394 fail:
4395 /* FIXME: This will crash if we aborted before cli2 got
4396 * intialized, because these functions don't handle
4397 * uninitialized connections. */
4399 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4400 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4401 cli_setatr(cli1, fname, 0, 0);
4402 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4404 if (cli1 && !torture_close_connection(cli1)) {
4405 correct = False;
4407 if (cli2 && !torture_close_connection(cli2)) {
4408 correct = False;
4410 return correct;
4415 Test wildcard delete.
4417 static bool run_wild_deletetest(int dummy)
4419 struct cli_state *cli = NULL;
4420 const char *dname = "\\WTEST";
4421 const char *fname = "\\WTEST\\A";
4422 const char *wunlink_name = "\\WTEST\\*";
4423 uint16_t fnum1 = (uint16_t)-1;
4424 bool correct = false;
4425 NTSTATUS status;
4427 printf("starting wildcard delete test\n");
4429 if (!torture_open_connection(&cli, 0)) {
4430 return false;
4433 smbXcli_conn_set_sockopt(cli->conn, sockops);
4435 cli_unlink(cli, fname, 0);
4436 cli_rmdir(cli, dname);
4437 status = cli_mkdir(cli, dname);
4438 if (!NT_STATUS_IS_OK(status)) {
4439 printf("mkdir of %s failed %s!\n", dname, nt_errstr(status));
4440 goto fail;
4442 status = cli_openx(cli, fname, O_CREAT|O_RDONLY, DENY_NONE, &fnum1);
4443 if (!NT_STATUS_IS_OK(status)) {
4444 printf("open of %s failed %s!\n", fname, nt_errstr(status));
4445 goto fail;
4447 status = cli_close(cli, fnum1);
4448 fnum1 = -1;
4451 * Note the unlink attribute-type of zero. This should
4452 * map into FILE_ATTRIBUTE_NORMAL at the server even
4453 * on a wildcard delete.
4456 status = cli_unlink(cli, wunlink_name, 0);
4457 if (!NT_STATUS_IS_OK(status)) {
4458 printf("unlink of %s failed %s!\n",
4459 wunlink_name, nt_errstr(status));
4460 goto fail;
4463 printf("finished wildcard delete test\n");
4465 correct = true;
4467 fail:
4469 if (fnum1 != (uint16_t)-1) cli_close(cli, fnum1);
4470 cli_unlink(cli, fname, 0);
4471 cli_rmdir(cli, dname);
4473 if (cli && !torture_close_connection(cli)) {
4474 correct = false;
4476 return correct;
4479 static bool run_deletetest_ln(int dummy)
4481 struct cli_state *cli;
4482 const char *fname = "\\delete1";
4483 const char *fname_ln = "\\delete1_ln";
4484 uint16_t fnum;
4485 uint16_t fnum1;
4486 NTSTATUS status;
4487 bool correct = true;
4488 time_t t;
4490 printf("starting deletetest-ln\n");
4492 if (!torture_open_connection(&cli, 0)) {
4493 return false;
4496 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4497 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4499 smbXcli_conn_set_sockopt(cli->conn, sockops);
4501 /* Create the file. */
4502 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4503 if (!NT_STATUS_IS_OK(status)) {
4504 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4505 return false;
4508 status = cli_close(cli, fnum);
4509 if (!NT_STATUS_IS_OK(status)) {
4510 printf("close1 failed (%s)\n", nt_errstr(status));
4511 return false;
4514 /* Now create a hardlink. */
4515 status = cli_nt_hardlink(cli, fname, fname_ln);
4516 if (!NT_STATUS_IS_OK(status)) {
4517 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4518 return false;
4521 /* Open the original file. */
4522 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4523 FILE_ATTRIBUTE_NORMAL,
4524 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4525 FILE_OPEN_IF, 0, 0, &fnum, NULL);
4526 if (!NT_STATUS_IS_OK(status)) {
4527 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4528 return false;
4531 /* Unlink the hard link path. */
4532 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4533 FILE_ATTRIBUTE_NORMAL,
4534 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4535 FILE_OPEN_IF, 0, 0, &fnum1, NULL);
4536 if (!NT_STATUS_IS_OK(status)) {
4537 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4538 return false;
4540 status = cli_nt_delete_on_close(cli, fnum1, true);
4541 if (!NT_STATUS_IS_OK(status)) {
4542 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4543 __location__, fname_ln, nt_errstr(status));
4544 return false;
4547 status = cli_close(cli, fnum1);
4548 if (!NT_STATUS_IS_OK(status)) {
4549 printf("close %s failed (%s)\n",
4550 fname_ln, nt_errstr(status));
4551 return false;
4554 status = cli_close(cli, fnum);
4555 if (!NT_STATUS_IS_OK(status)) {
4556 printf("close %s failed (%s)\n",
4557 fname, nt_errstr(status));
4558 return false;
4561 /* Ensure the original file is still there. */
4562 status = cli_getatr(cli, fname, NULL, NULL, &t);
4563 if (!NT_STATUS_IS_OK(status)) {
4564 printf("%s getatr on file %s failed (%s)\n",
4565 __location__,
4566 fname,
4567 nt_errstr(status));
4568 correct = False;
4571 /* Ensure the link path is gone. */
4572 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4573 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4574 printf("%s, getatr for file %s returned wrong error code %s "
4575 "- should have been deleted\n",
4576 __location__,
4577 fname_ln, nt_errstr(status));
4578 correct = False;
4581 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4582 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4584 if (!torture_close_connection(cli)) {
4585 correct = false;
4588 printf("finished deletetest-ln\n");
4590 return correct;
4594 print out server properties
4596 static bool run_properties(int dummy)
4598 struct cli_state *cli;
4599 bool correct = True;
4601 printf("starting properties test\n");
4603 ZERO_STRUCT(cli);
4605 if (!torture_open_connection(&cli, 0)) {
4606 return False;
4609 smbXcli_conn_set_sockopt(cli->conn, sockops);
4611 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
4613 if (!torture_close_connection(cli)) {
4614 correct = False;
4617 return correct;
4622 /* FIRST_DESIRED_ACCESS 0xf019f */
4623 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4624 FILE_READ_EA| /* 0xf */ \
4625 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
4626 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
4627 DELETE_ACCESS|READ_CONTROL_ACCESS|\
4628 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
4629 /* SECOND_DESIRED_ACCESS 0xe0080 */
4630 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4631 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4632 WRITE_OWNER_ACCESS /* 0xe0000 */
4634 #if 0
4635 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4636 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4637 FILE_READ_DATA|\
4638 WRITE_OWNER_ACCESS /* */
4639 #endif
4642 Test ntcreate calls made by xcopy
4644 static bool run_xcopy(int dummy)
4646 static struct cli_state *cli1;
4647 const char *fname = "\\test.txt";
4648 bool correct = True;
4649 uint16_t fnum1, fnum2;
4650 NTSTATUS status;
4652 printf("starting xcopy test\n");
4654 if (!torture_open_connection(&cli1, 0)) {
4655 return False;
4658 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4659 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4660 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
4661 if (!NT_STATUS_IS_OK(status)) {
4662 printf("First open failed - %s\n", nt_errstr(status));
4663 return False;
4666 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4667 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4668 FILE_OPEN, 0x200000, 0, &fnum2, NULL);
4669 if (!NT_STATUS_IS_OK(status)) {
4670 printf("second open failed - %s\n", nt_errstr(status));
4671 return False;
4674 if (!torture_close_connection(cli1)) {
4675 correct = False;
4678 return correct;
4682 Test rename on files open with share delete and no share delete.
4684 static bool run_rename(int dummy)
4686 static struct cli_state *cli1;
4687 const char *fname = "\\test.txt";
4688 const char *fname1 = "\\test1.txt";
4689 bool correct = True;
4690 uint16_t fnum1;
4691 uint16_t attr;
4692 NTSTATUS status;
4694 printf("starting rename test\n");
4696 if (!torture_open_connection(&cli1, 0)) {
4697 return False;
4700 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4701 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4703 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4704 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4705 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4706 if (!NT_STATUS_IS_OK(status)) {
4707 printf("First open failed - %s\n", nt_errstr(status));
4708 return False;
4711 status = cli_rename(cli1, fname, fname1);
4712 if (!NT_STATUS_IS_OK(status)) {
4713 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4714 } else {
4715 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4716 correct = False;
4719 status = cli_close(cli1, fnum1);
4720 if (!NT_STATUS_IS_OK(status)) {
4721 printf("close - 1 failed (%s)\n", nt_errstr(status));
4722 return False;
4725 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4726 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4727 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4728 #if 0
4729 FILE_SHARE_DELETE|FILE_SHARE_NONE,
4730 #else
4731 FILE_SHARE_DELETE|FILE_SHARE_READ,
4732 #endif
4733 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4734 if (!NT_STATUS_IS_OK(status)) {
4735 printf("Second open failed - %s\n", nt_errstr(status));
4736 return False;
4739 status = cli_rename(cli1, fname, fname1);
4740 if (!NT_STATUS_IS_OK(status)) {
4741 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4742 correct = False;
4743 } else {
4744 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4747 status = cli_close(cli1, fnum1);
4748 if (!NT_STATUS_IS_OK(status)) {
4749 printf("close - 2 failed (%s)\n", nt_errstr(status));
4750 return False;
4753 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4754 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4756 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4757 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4758 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4759 if (!NT_STATUS_IS_OK(status)) {
4760 printf("Third open failed - %s\n", nt_errstr(status));
4761 return False;
4765 #if 0
4767 uint16_t fnum2;
4769 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4770 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
4771 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4772 return False;
4774 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4775 printf("[8] setting delete_on_close on file failed !\n");
4776 return False;
4779 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4780 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4781 return False;
4784 #endif
4786 status = cli_rename(cli1, fname, fname1);
4787 if (!NT_STATUS_IS_OK(status)) {
4788 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4789 correct = False;
4790 } else {
4791 printf("Third rename succeeded (SHARE_NONE)\n");
4794 status = cli_close(cli1, fnum1);
4795 if (!NT_STATUS_IS_OK(status)) {
4796 printf("close - 3 failed (%s)\n", nt_errstr(status));
4797 return False;
4800 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4801 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4803 /*----*/
4805 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4806 FILE_ATTRIBUTE_NORMAL,
4807 FILE_SHARE_READ | FILE_SHARE_WRITE,
4808 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4809 if (!NT_STATUS_IS_OK(status)) {
4810 printf("Fourth open failed - %s\n", nt_errstr(status));
4811 return False;
4814 status = cli_rename(cli1, fname, fname1);
4815 if (!NT_STATUS_IS_OK(status)) {
4816 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4817 } else {
4818 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4819 correct = False;
4822 status = cli_close(cli1, fnum1);
4823 if (!NT_STATUS_IS_OK(status)) {
4824 printf("close - 4 failed (%s)\n", nt_errstr(status));
4825 return False;
4828 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4829 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4831 /*--*/
4833 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4834 FILE_ATTRIBUTE_NORMAL,
4835 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4836 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4837 if (!NT_STATUS_IS_OK(status)) {
4838 printf("Fifth open failed - %s\n", nt_errstr(status));
4839 return False;
4842 status = cli_rename(cli1, fname, fname1);
4843 if (!NT_STATUS_IS_OK(status)) {
4844 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4845 correct = False;
4846 } else {
4847 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4851 * Now check if the first name still exists ...
4854 /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4855 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4856 FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
4857 printf("Opening original file after rename of open file fails: %s\n",
4858 cli_errstr(cli1));
4860 else {
4861 printf("Opening original file after rename of open file works ...\n");
4862 (void)cli_close(cli1, fnum2);
4863 } */
4865 /*--*/
4866 status = cli_close(cli1, fnum1);
4867 if (!NT_STATUS_IS_OK(status)) {
4868 printf("close - 5 failed (%s)\n", nt_errstr(status));
4869 return False;
4872 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4873 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4874 if (!NT_STATUS_IS_OK(status)) {
4875 printf("getatr on file %s failed - %s ! \n",
4876 fname1, nt_errstr(status));
4877 correct = False;
4878 } else {
4879 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4880 printf("Renamed file %s has wrong attr 0x%x "
4881 "(should be 0x%x)\n",
4882 fname1,
4883 attr,
4884 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4885 correct = False;
4886 } else {
4887 printf("Renamed file %s has archive bit set\n", fname1);
4891 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4892 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4894 if (!torture_close_connection(cli1)) {
4895 correct = False;
4898 return correct;
4901 static bool run_pipe_number(int dummy)
4903 struct cli_state *cli1;
4904 const char *pipe_name = "\\SPOOLSS";
4905 uint16_t fnum;
4906 int num_pipes = 0;
4907 NTSTATUS status;
4909 printf("starting pipenumber test\n");
4910 if (!torture_open_connection(&cli1, 0)) {
4911 return False;
4914 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4915 while(1) {
4916 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
4917 FILE_ATTRIBUTE_NORMAL,
4918 FILE_SHARE_READ|FILE_SHARE_WRITE,
4919 FILE_OPEN_IF, 0, 0, &fnum, NULL);
4920 if (!NT_STATUS_IS_OK(status)) {
4921 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
4922 break;
4924 num_pipes++;
4925 printf("\r%6d", num_pipes);
4928 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4929 torture_close_connection(cli1);
4930 return True;
4934 Test open mode returns on read-only files.
4936 static bool run_opentest(int dummy)
4938 static struct cli_state *cli1;
4939 static struct cli_state *cli2;
4940 const char *fname = "\\readonly.file";
4941 uint16_t fnum1, fnum2;
4942 char buf[20];
4943 off_t fsize;
4944 bool correct = True;
4945 char *tmp_path;
4946 NTSTATUS status;
4948 printf("starting open test\n");
4950 if (!torture_open_connection(&cli1, 0)) {
4951 return False;
4954 cli_setatr(cli1, fname, 0, 0);
4955 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4957 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4959 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4960 if (!NT_STATUS_IS_OK(status)) {
4961 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4962 return False;
4965 status = cli_close(cli1, fnum1);
4966 if (!NT_STATUS_IS_OK(status)) {
4967 printf("close2 failed (%s)\n", nt_errstr(status));
4968 return False;
4971 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
4972 if (!NT_STATUS_IS_OK(status)) {
4973 printf("cli_setatr failed (%s)\n", nt_errstr(status));
4974 return False;
4977 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4978 if (!NT_STATUS_IS_OK(status)) {
4979 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4980 return False;
4983 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4984 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4986 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
4987 NT_STATUS_ACCESS_DENIED)) {
4988 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4991 printf("finished open test 1\n");
4993 cli_close(cli1, fnum1);
4995 /* Now try not readonly and ensure ERRbadshare is returned. */
4997 cli_setatr(cli1, fname, 0, 0);
4999 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
5000 if (!NT_STATUS_IS_OK(status)) {
5001 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5002 return False;
5005 /* This will fail - but the error should be ERRshare. */
5006 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
5008 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
5009 NT_STATUS_SHARING_VIOLATION)) {
5010 printf("correct error code ERRDOS/ERRbadshare returned\n");
5013 status = cli_close(cli1, fnum1);
5014 if (!NT_STATUS_IS_OK(status)) {
5015 printf("close2 failed (%s)\n", nt_errstr(status));
5016 return False;
5019 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5021 printf("finished open test 2\n");
5023 /* Test truncate open disposition on file opened for read. */
5024 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
5025 if (!NT_STATUS_IS_OK(status)) {
5026 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
5027 return False;
5030 /* write 20 bytes. */
5032 memset(buf, '\0', 20);
5034 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
5035 if (!NT_STATUS_IS_OK(status)) {
5036 printf("write failed (%s)\n", nt_errstr(status));
5037 correct = False;
5040 status = cli_close(cli1, fnum1);
5041 if (!NT_STATUS_IS_OK(status)) {
5042 printf("(3) close1 failed (%s)\n", nt_errstr(status));
5043 return False;
5046 /* Ensure size == 20. */
5047 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5048 if (!NT_STATUS_IS_OK(status)) {
5049 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5050 return False;
5053 if (fsize != 20) {
5054 printf("(3) file size != 20\n");
5055 return False;
5058 /* Now test if we can truncate a file opened for readonly. */
5059 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
5060 if (!NT_STATUS_IS_OK(status)) {
5061 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
5062 return False;
5065 status = cli_close(cli1, fnum1);
5066 if (!NT_STATUS_IS_OK(status)) {
5067 printf("close2 failed (%s)\n", nt_errstr(status));
5068 return False;
5071 /* Ensure size == 0. */
5072 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5073 if (!NT_STATUS_IS_OK(status)) {
5074 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5075 return False;
5078 if (fsize != 0) {
5079 printf("(3) file size != 0\n");
5080 return False;
5082 printf("finished open test 3\n");
5084 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5086 printf("Do ctemp tests\n");
5087 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
5088 if (!NT_STATUS_IS_OK(status)) {
5089 printf("ctemp failed (%s)\n", nt_errstr(status));
5090 return False;
5093 printf("ctemp gave path %s\n", tmp_path);
5094 status = cli_close(cli1, fnum1);
5095 if (!NT_STATUS_IS_OK(status)) {
5096 printf("close of temp failed (%s)\n", nt_errstr(status));
5099 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5100 if (!NT_STATUS_IS_OK(status)) {
5101 printf("unlink of temp failed (%s)\n", nt_errstr(status));
5104 /* Test the non-io opens... */
5106 if (!torture_open_connection(&cli2, 1)) {
5107 return False;
5110 cli_setatr(cli2, fname, 0, 0);
5111 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5113 smbXcli_conn_set_sockopt(cli2->conn, sockops);
5115 printf("TEST #1 testing 2 non-io opens (no delete)\n");
5116 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5117 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5118 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5119 if (!NT_STATUS_IS_OK(status)) {
5120 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5121 return False;
5124 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5125 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5126 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5127 if (!NT_STATUS_IS_OK(status)) {
5128 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5129 return False;
5132 status = cli_close(cli1, fnum1);
5133 if (!NT_STATUS_IS_OK(status)) {
5134 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5135 return False;
5138 status = cli_close(cli2, fnum2);
5139 if (!NT_STATUS_IS_OK(status)) {
5140 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5141 return False;
5144 printf("non-io open test #1 passed.\n");
5146 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5148 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5150 status = cli_ntcreate(cli1, fname, 0,
5151 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5152 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5153 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5154 if (!NT_STATUS_IS_OK(status)) {
5155 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5156 return False;
5159 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5160 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5161 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5162 if (!NT_STATUS_IS_OK(status)) {
5163 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5164 return False;
5167 status = cli_close(cli1, fnum1);
5168 if (!NT_STATUS_IS_OK(status)) {
5169 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5170 return False;
5173 status = cli_close(cli2, fnum2);
5174 if (!NT_STATUS_IS_OK(status)) {
5175 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5176 return False;
5179 printf("non-io open test #2 passed.\n");
5181 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5183 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5185 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5186 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5187 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5188 if (!NT_STATUS_IS_OK(status)) {
5189 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5190 return False;
5193 status = cli_ntcreate(cli2, fname, 0,
5194 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5195 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5196 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5197 if (!NT_STATUS_IS_OK(status)) {
5198 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5199 return False;
5202 status = cli_close(cli1, fnum1);
5203 if (!NT_STATUS_IS_OK(status)) {
5204 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5205 return False;
5208 status = cli_close(cli2, fnum2);
5209 if (!NT_STATUS_IS_OK(status)) {
5210 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5211 return False;
5214 printf("non-io open test #3 passed.\n");
5216 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5218 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5220 status = cli_ntcreate(cli1, fname, 0,
5221 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5222 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5223 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5224 if (!NT_STATUS_IS_OK(status)) {
5225 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5226 return False;
5229 status = cli_ntcreate(cli2, fname, 0,
5230 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5231 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5232 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5233 if (NT_STATUS_IS_OK(status)) {
5234 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5235 return False;
5238 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5240 status = cli_close(cli1, fnum1);
5241 if (!NT_STATUS_IS_OK(status)) {
5242 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5243 return False;
5246 printf("non-io open test #4 passed.\n");
5248 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5250 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5252 status = cli_ntcreate(cli1, fname, 0,
5253 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5254 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5255 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5256 if (!NT_STATUS_IS_OK(status)) {
5257 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5258 return False;
5261 status = cli_ntcreate(cli2, fname, 0,
5262 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5263 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5264 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5265 if (!NT_STATUS_IS_OK(status)) {
5266 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5267 return False;
5270 status = cli_close(cli1, fnum1);
5271 if (!NT_STATUS_IS_OK(status)) {
5272 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5273 return False;
5276 status = cli_close(cli2, fnum2);
5277 if (!NT_STATUS_IS_OK(status)) {
5278 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5279 return False;
5282 printf("non-io open test #5 passed.\n");
5284 printf("TEST #6 testing 1 non-io open, one io open\n");
5286 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5288 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5289 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5290 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5291 if (!NT_STATUS_IS_OK(status)) {
5292 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5293 return False;
5296 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5297 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5298 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5299 if (!NT_STATUS_IS_OK(status)) {
5300 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5301 return False;
5304 status = cli_close(cli1, fnum1);
5305 if (!NT_STATUS_IS_OK(status)) {
5306 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5307 return False;
5310 status = cli_close(cli2, fnum2);
5311 if (!NT_STATUS_IS_OK(status)) {
5312 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5313 return False;
5316 printf("non-io open test #6 passed.\n");
5318 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5320 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5322 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5323 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5324 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5325 if (!NT_STATUS_IS_OK(status)) {
5326 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5327 return False;
5330 status = cli_ntcreate(cli2, fname, 0,
5331 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5332 FILE_ATTRIBUTE_NORMAL,
5333 FILE_SHARE_READ|FILE_SHARE_DELETE,
5334 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5335 if (NT_STATUS_IS_OK(status)) {
5336 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5337 return False;
5340 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5342 status = cli_close(cli1, fnum1);
5343 if (!NT_STATUS_IS_OK(status)) {
5344 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5345 return False;
5348 printf("non-io open test #7 passed.\n");
5350 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5352 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5353 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5354 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5355 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5356 if (!NT_STATUS_IS_OK(status)) {
5357 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5358 correct = false;
5359 goto out;
5362 /* Write to ensure we have to update the file time. */
5363 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5364 NULL);
5365 if (!NT_STATUS_IS_OK(status)) {
5366 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5367 correct = false;
5368 goto out;
5371 status = cli_close(cli1, fnum1);
5372 if (!NT_STATUS_IS_OK(status)) {
5373 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5374 correct = false;
5377 out:
5379 if (!torture_close_connection(cli1)) {
5380 correct = False;
5382 if (!torture_close_connection(cli2)) {
5383 correct = False;
5386 return correct;
5389 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5391 uint16_t major, minor;
5392 uint32_t caplow, caphigh;
5393 NTSTATUS status;
5395 if (!SERVER_HAS_UNIX_CIFS(cli)) {
5396 printf("Server doesn't support UNIX CIFS extensions.\n");
5397 return NT_STATUS_NOT_SUPPORTED;
5400 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5401 &caphigh);
5402 if (!NT_STATUS_IS_OK(status)) {
5403 printf("Server didn't return UNIX CIFS extensions: %s\n",
5404 nt_errstr(status));
5405 return status;
5408 status = cli_set_unix_extensions_capabilities(cli, major, minor,
5409 caplow, caphigh);
5410 if (!NT_STATUS_IS_OK(status)) {
5411 printf("Server doesn't support setting UNIX CIFS extensions: "
5412 "%s.\n", nt_errstr(status));
5413 return status;
5416 return NT_STATUS_OK;
5420 Test POSIX open /mkdir calls.
5422 static bool run_simple_posix_open_test(int dummy)
5424 static struct cli_state *cli1;
5425 const char *fname = "posix:file";
5426 const char *hname = "posix:hlink";
5427 const char *sname = "posix:symlink";
5428 const char *dname = "posix:dir";
5429 char buf[10];
5430 char namebuf[11];
5431 uint16_t fnum1 = (uint16_t)-1;
5432 SMB_STRUCT_STAT sbuf;
5433 bool correct = false;
5434 NTSTATUS status;
5435 size_t nread;
5436 const char *fname_windows = "windows_file";
5437 uint16_t fnum2 = (uint16_t)-1;
5439 printf("Starting simple POSIX open test\n");
5441 if (!torture_open_connection(&cli1, 0)) {
5442 return false;
5445 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5447 status = torture_setup_unix_extensions(cli1);
5448 if (!NT_STATUS_IS_OK(status)) {
5449 return false;
5452 cli_setatr(cli1, fname, 0, 0);
5453 cli_posix_unlink(cli1, fname);
5454 cli_setatr(cli1, dname, 0, 0);
5455 cli_posix_rmdir(cli1, dname);
5456 cli_setatr(cli1, hname, 0, 0);
5457 cli_posix_unlink(cli1, hname);
5458 cli_setatr(cli1, sname, 0, 0);
5459 cli_posix_unlink(cli1, sname);
5460 cli_setatr(cli1, fname_windows, 0, 0);
5461 cli_posix_unlink(cli1, fname_windows);
5463 /* Create a directory. */
5464 status = cli_posix_mkdir(cli1, dname, 0777);
5465 if (!NT_STATUS_IS_OK(status)) {
5466 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5467 goto out;
5470 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5471 0600, &fnum1);
5472 if (!NT_STATUS_IS_OK(status)) {
5473 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5474 goto out;
5477 /* Test ftruncate - set file size. */
5478 status = cli_ftruncate(cli1, fnum1, 1000);
5479 if (!NT_STATUS_IS_OK(status)) {
5480 printf("ftruncate failed (%s)\n", nt_errstr(status));
5481 goto out;
5484 /* Ensure st_size == 1000 */
5485 status = cli_posix_stat(cli1, fname, &sbuf);
5486 if (!NT_STATUS_IS_OK(status)) {
5487 printf("stat failed (%s)\n", nt_errstr(status));
5488 goto out;
5491 if (sbuf.st_ex_size != 1000) {
5492 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5493 goto out;
5496 /* Ensure st_mode == 0600 */
5497 if ((sbuf.st_ex_mode & 07777) != 0600) {
5498 printf("posix_open - bad permissions 0%o != 0600\n",
5499 (unsigned int)(sbuf.st_ex_mode & 07777));
5500 goto out;
5503 /* Test ftruncate - set file size back to zero. */
5504 status = cli_ftruncate(cli1, fnum1, 0);
5505 if (!NT_STATUS_IS_OK(status)) {
5506 printf("ftruncate failed (%s)\n", nt_errstr(status));
5507 goto out;
5510 status = cli_close(cli1, fnum1);
5511 if (!NT_STATUS_IS_OK(status)) {
5512 printf("close failed (%s)\n", nt_errstr(status));
5513 goto out;
5516 /* Now open the file again for read only. */
5517 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5518 if (!NT_STATUS_IS_OK(status)) {
5519 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5520 goto out;
5523 /* Now unlink while open. */
5524 status = cli_posix_unlink(cli1, fname);
5525 if (!NT_STATUS_IS_OK(status)) {
5526 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5527 goto out;
5530 status = cli_close(cli1, fnum1);
5531 if (!NT_STATUS_IS_OK(status)) {
5532 printf("close(2) failed (%s)\n", nt_errstr(status));
5533 goto out;
5536 /* Ensure the file has gone. */
5537 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5538 if (NT_STATUS_IS_OK(status)) {
5539 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5540 goto out;
5543 /* Create again to test open with O_TRUNC. */
5544 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
5545 if (!NT_STATUS_IS_OK(status)) {
5546 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5547 goto out;
5550 /* Test ftruncate - set file size. */
5551 status = cli_ftruncate(cli1, fnum1, 1000);
5552 if (!NT_STATUS_IS_OK(status)) {
5553 printf("ftruncate failed (%s)\n", nt_errstr(status));
5554 goto out;
5557 /* Ensure st_size == 1000 */
5558 status = cli_posix_stat(cli1, fname, &sbuf);
5559 if (!NT_STATUS_IS_OK(status)) {
5560 printf("stat failed (%s)\n", nt_errstr(status));
5561 goto out;
5564 if (sbuf.st_ex_size != 1000) {
5565 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5566 goto out;
5569 status = cli_close(cli1, fnum1);
5570 if (!NT_STATUS_IS_OK(status)) {
5571 printf("close(2) failed (%s)\n", nt_errstr(status));
5572 goto out;
5575 /* Re-open with O_TRUNC. */
5576 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
5577 if (!NT_STATUS_IS_OK(status)) {
5578 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5579 goto out;
5582 /* Ensure st_size == 0 */
5583 status = cli_posix_stat(cli1, fname, &sbuf);
5584 if (!NT_STATUS_IS_OK(status)) {
5585 printf("stat failed (%s)\n", nt_errstr(status));
5586 goto out;
5589 if (sbuf.st_ex_size != 0) {
5590 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5591 goto out;
5594 status = cli_close(cli1, fnum1);
5595 if (!NT_STATUS_IS_OK(status)) {
5596 printf("close failed (%s)\n", nt_errstr(status));
5597 goto out;
5600 status = cli_posix_unlink(cli1, fname);
5601 if (!NT_STATUS_IS_OK(status)) {
5602 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5603 goto out;
5606 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
5607 if (!NT_STATUS_IS_OK(status)) {
5608 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5609 dname, nt_errstr(status));
5610 goto out;
5613 cli_close(cli1, fnum1);
5615 /* What happens when we try and POSIX open a directory for write ? */
5616 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
5617 if (NT_STATUS_IS_OK(status)) {
5618 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5619 goto out;
5620 } else {
5621 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
5622 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5623 goto out;
5627 /* Create the file. */
5628 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5629 0600, &fnum1);
5630 if (!NT_STATUS_IS_OK(status)) {
5631 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5632 goto out;
5635 /* Write some data into it. */
5636 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5637 NULL);
5638 if (!NT_STATUS_IS_OK(status)) {
5639 printf("cli_write failed: %s\n", nt_errstr(status));
5640 goto out;
5643 cli_close(cli1, fnum1);
5645 /* Now create a hardlink. */
5646 status = cli_posix_hardlink(cli1, fname, hname);
5647 if (!NT_STATUS_IS_OK(status)) {
5648 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5649 goto out;
5652 /* Now create a symlink. */
5653 status = cli_posix_symlink(cli1, fname, sname);
5654 if (!NT_STATUS_IS_OK(status)) {
5655 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5656 goto out;
5659 /* Open the hardlink for read. */
5660 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5661 if (!NT_STATUS_IS_OK(status)) {
5662 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5663 goto out;
5666 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
5667 if (!NT_STATUS_IS_OK(status)) {
5668 printf("POSIX read of %s failed (%s)\n", hname,
5669 nt_errstr(status));
5670 goto out;
5671 } else if (nread != 10) {
5672 printf("POSIX read of %s failed. Received %ld, expected %d\n",
5673 hname, (unsigned long)nread, 10);
5674 goto out;
5677 if (memcmp(buf, "TEST DATA\n", 10)) {
5678 printf("invalid data read from hardlink\n");
5679 goto out;
5682 /* Do a POSIX lock/unlock. */
5683 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5684 if (!NT_STATUS_IS_OK(status)) {
5685 printf("POSIX lock failed %s\n", nt_errstr(status));
5686 goto out;
5689 /* Punch a hole in the locked area. */
5690 status = cli_posix_unlock(cli1, fnum1, 10, 80);
5691 if (!NT_STATUS_IS_OK(status)) {
5692 printf("POSIX unlock failed %s\n", nt_errstr(status));
5693 goto out;
5696 cli_close(cli1, fnum1);
5698 /* Open the symlink for read - this should fail. A POSIX
5699 client should not be doing opens on a symlink. */
5700 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5701 if (NT_STATUS_IS_OK(status)) {
5702 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5703 goto out;
5704 } else {
5705 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
5706 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5707 printf("POSIX open of %s should have failed "
5708 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5709 "failed with %s instead.\n",
5710 sname, nt_errstr(status));
5711 goto out;
5715 status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5716 if (!NT_STATUS_IS_OK(status)) {
5717 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5718 goto out;
5721 if (strcmp(namebuf, fname) != 0) {
5722 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5723 sname, fname, namebuf);
5724 goto out;
5727 status = cli_posix_rmdir(cli1, dname);
5728 if (!NT_STATUS_IS_OK(status)) {
5729 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5730 goto out;
5733 /* Check directory opens with a specific permission. */
5734 status = cli_posix_mkdir(cli1, dname, 0700);
5735 if (!NT_STATUS_IS_OK(status)) {
5736 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5737 goto out;
5740 /* Ensure st_mode == 0700 */
5741 status = cli_posix_stat(cli1, dname, &sbuf);
5742 if (!NT_STATUS_IS_OK(status)) {
5743 printf("stat failed (%s)\n", nt_errstr(status));
5744 goto out;
5747 if ((sbuf.st_ex_mode & 07777) != 0700) {
5748 printf("posix_mkdir - bad permissions 0%o != 0700\n",
5749 (unsigned int)(sbuf.st_ex_mode & 07777));
5750 goto out;
5754 * Now create a Windows file, and attempt a POSIX unlink.
5755 * This should fail with a sharing violation but due to:
5757 * [Bug 9571] Unlink after open causes smbd to panic
5759 * ensure we've fixed the lock ordering violation.
5762 status = cli_ntcreate(cli1, fname_windows, 0,
5763 FILE_READ_DATA|FILE_WRITE_DATA, 0,
5764 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5765 FILE_CREATE,
5766 0x0, 0x0, &fnum2, NULL);
5767 if (!NT_STATUS_IS_OK(status)) {
5768 printf("Windows create of %s failed (%s)\n", fname_windows,
5769 nt_errstr(status));
5770 goto out;
5773 /* Now try posix_unlink. */
5774 status = cli_posix_unlink(cli1, fname_windows);
5775 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5776 printf("POSIX unlink of %s should fail "
5777 "with NT_STATUS_SHARING_VIOLATION "
5778 "got %s instead !\n",
5779 fname_windows,
5780 nt_errstr(status));
5781 goto out;
5784 cli_close(cli1, fnum2);
5786 printf("Simple POSIX open test passed\n");
5787 correct = true;
5789 out:
5791 if (fnum1 != (uint16_t)-1) {
5792 cli_close(cli1, fnum1);
5793 fnum1 = (uint16_t)-1;
5796 if (fnum2 != (uint16_t)-1) {
5797 cli_close(cli1, fnum2);
5798 fnum2 = (uint16_t)-1;
5801 cli_setatr(cli1, sname, 0, 0);
5802 cli_posix_unlink(cli1, sname);
5803 cli_setatr(cli1, hname, 0, 0);
5804 cli_posix_unlink(cli1, hname);
5805 cli_setatr(cli1, fname, 0, 0);
5806 cli_posix_unlink(cli1, fname);
5807 cli_setatr(cli1, dname, 0, 0);
5808 cli_posix_rmdir(cli1, dname);
5809 cli_setatr(cli1, fname_windows, 0, 0);
5810 cli_posix_unlink(cli1, fname_windows);
5812 if (!torture_close_connection(cli1)) {
5813 correct = false;
5816 return correct;
5820 Test POSIX and Windows ACLs are rejected on symlinks.
5822 static bool run_acl_symlink_test(int dummy)
5824 static struct cli_state *cli;
5825 const char *fname = "posix_file";
5826 const char *sname = "posix_symlink";
5827 uint16_t fnum = (uint16_t)-1;
5828 bool correct = false;
5829 NTSTATUS status;
5830 char *posix_acl = NULL;
5831 size_t posix_acl_len = 0;
5832 char *posix_acl_sym = NULL;
5833 size_t posix_acl_len_sym = 0;
5834 struct security_descriptor *sd = NULL;
5835 struct security_descriptor *sd_sym = NULL;
5836 TALLOC_CTX *frame = NULL;
5838 frame = talloc_stackframe();
5840 printf("Starting acl symlink test\n");
5842 if (!torture_open_connection(&cli, 0)) {
5843 TALLOC_FREE(frame);
5844 return false;
5847 smbXcli_conn_set_sockopt(cli->conn, sockops);
5849 status = torture_setup_unix_extensions(cli);
5850 if (!NT_STATUS_IS_OK(status)) {
5851 TALLOC_FREE(frame);
5852 return false;
5855 cli_setatr(cli, fname, 0, 0);
5856 cli_posix_unlink(cli, fname);
5857 cli_setatr(cli, sname, 0, 0);
5858 cli_posix_unlink(cli, sname);
5860 status = cli_ntcreate(cli,
5861 fname,
5863 READ_CONTROL_ACCESS,
5865 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5866 FILE_CREATE,
5867 0x0,
5868 0x0,
5869 &fnum,
5870 NULL);
5872 if (!NT_STATUS_IS_OK(status)) {
5873 printf("cli_ntcreate of %s failed (%s)\n",
5874 fname,
5875 nt_errstr(status));
5876 goto out;
5879 /* Get the Windows ACL on the file. */
5880 status = cli_query_secdesc(cli,
5881 fnum,
5882 frame,
5883 &sd);
5884 if (!NT_STATUS_IS_OK(status)) {
5885 printf("cli_query_secdesc failed (%s)\n",
5886 nt_errstr(status));
5887 goto out;
5890 /* Get the POSIX ACL on the file. */
5891 status = cli_posix_getacl(cli,
5892 fname,
5893 frame,
5894 &posix_acl_len,
5895 &posix_acl);
5897 if (!NT_STATUS_IS_OK(status)) {
5898 printf("cli_posix_getacl failed (%s)\n",
5899 nt_errstr(status));
5900 goto out;
5903 status = cli_close(cli, fnum);
5904 if (!NT_STATUS_IS_OK(status)) {
5905 printf("close failed (%s)\n", nt_errstr(status));
5906 goto out;
5908 fnum = (uint16_t)-1;
5910 /* Now create a symlink. */
5911 status = cli_posix_symlink(cli, fname, sname);
5912 if (!NT_STATUS_IS_OK(status)) {
5913 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
5914 sname,
5915 fname,
5916 nt_errstr(status));
5917 goto out;
5920 /* Open a handle on the symlink. */
5921 status = cli_ntcreate(cli,
5922 sname,
5924 READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
5926 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5927 FILE_OPEN,
5928 0x0,
5929 0x0,
5930 &fnum,
5931 NULL);
5933 if (!NT_STATUS_IS_OK(status)) {
5934 printf("cli_posix_open of %s failed (%s)\n",
5935 sname,
5936 nt_errstr(status));
5937 goto out;
5940 /* Get the Windows ACL on the symlink handle. Should fail */
5941 status = cli_query_secdesc(cli,
5942 fnum,
5943 frame,
5944 &sd_sym);
5946 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5947 printf("cli_query_secdesc on a symlink gave %s. "
5948 "Should be NT_STATUS_ACCESS_DENIED.\n",
5949 nt_errstr(status));
5950 goto out;
5953 /* Get the POSIX ACL on the symlink pathname. Should fail. */
5954 status = cli_posix_getacl(cli,
5955 sname,
5956 frame,
5957 &posix_acl_len_sym,
5958 &posix_acl_sym);
5960 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5961 printf("cli_posix_getacl on a symlink gave %s. "
5962 "Should be NT_STATUS_ACCESS_DENIED.\n",
5963 nt_errstr(status));
5964 goto out;
5967 /* Set the Windows ACL on the symlink handle. Should fail */
5968 status = cli_set_security_descriptor(cli,
5969 fnum,
5970 SECINFO_DACL,
5971 sd);
5973 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5974 printf("cli_query_secdesc on a symlink gave %s. "
5975 "Should be NT_STATUS_ACCESS_DENIED.\n",
5976 nt_errstr(status));
5977 goto out;
5980 /* Set the POSIX ACL on the symlink pathname. Should fail. */
5981 status = cli_posix_setacl(cli,
5982 sname,
5983 posix_acl,
5984 posix_acl_len);
5986 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5987 printf("cli_posix_getacl on a symlink gave %s. "
5988 "Should be NT_STATUS_ACCESS_DENIED.\n",
5989 nt_errstr(status));
5990 goto out;
5993 printf("ACL symlink test passed\n");
5994 correct = true;
5996 out:
5998 if (fnum != (uint16_t)-1) {
5999 cli_close(cli, fnum);
6000 fnum = (uint16_t)-1;
6003 cli_setatr(cli, sname, 0, 0);
6004 cli_posix_unlink(cli, sname);
6005 cli_setatr(cli, fname, 0, 0);
6006 cli_posix_unlink(cli, fname);
6008 if (!torture_close_connection(cli)) {
6009 correct = false;
6012 TALLOC_FREE(frame);
6013 return correct;
6017 Test POSIX can delete a file containing streams.
6019 static bool run_posix_stream_delete(int dummy)
6021 struct cli_state *cli1 = NULL;
6022 struct cli_state *cli2 = NULL;
6023 const char *fname = "streamfile";
6024 const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
6025 uint16_t fnum1 = (uint16_t)-1;
6026 bool correct = false;
6027 NTSTATUS status;
6028 TALLOC_CTX *frame = NULL;
6030 frame = talloc_stackframe();
6032 printf("Starting POSIX stream delete test\n");
6034 if (!torture_open_connection(&cli1, 0) ||
6035 !torture_open_connection(&cli2, 1)) {
6036 TALLOC_FREE(frame);
6037 return false;
6040 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6041 smbXcli_conn_set_sockopt(cli2->conn, sockops);
6043 status = torture_setup_unix_extensions(cli2);
6044 if (!NT_STATUS_IS_OK(status)) {
6045 goto out;
6048 cli_setatr(cli1, fname, 0, 0);
6049 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6051 /* Create the file. */
6052 status = cli_ntcreate(cli1,
6053 fname,
6055 READ_CONTROL_ACCESS,
6057 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6058 FILE_CREATE,
6059 0x0,
6060 0x0,
6061 &fnum1,
6062 NULL);
6064 if (!NT_STATUS_IS_OK(status)) {
6065 printf("cli_ntcreate of %s failed (%s)\n",
6066 fname,
6067 nt_errstr(status));
6068 goto out;
6071 status = cli_close(cli1, fnum1);
6072 if (!NT_STATUS_IS_OK(status)) {
6073 printf("cli_close of %s failed (%s)\n",
6074 fname,
6075 nt_errstr(status));
6076 goto out;
6078 fnum1 = (uint16_t)-1;
6080 /* Now create the stream. */
6081 status = cli_ntcreate(cli1,
6082 stream_fname,
6084 FILE_WRITE_DATA,
6086 FILE_SHARE_READ|FILE_SHARE_WRITE,
6087 FILE_CREATE,
6088 0x0,
6089 0x0,
6090 &fnum1,
6091 NULL);
6093 if (!NT_STATUS_IS_OK(status)) {
6094 printf("cli_ntcreate of %s failed (%s)\n",
6095 stream_fname,
6096 nt_errstr(status));
6097 goto out;
6100 /* Leave the stream handle open... */
6102 /* POSIX unlink should fail. */
6103 status = cli_posix_unlink(cli2, fname);
6104 if (NT_STATUS_IS_OK(status)) {
6105 printf("cli_posix_unlink of %s succeeded, should have failed\n",
6106 fname);
6107 goto out;
6110 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6111 printf("cli_posix_unlink of %s failed with (%s) "
6112 "should have been NT_STATUS_SHARING_VIOLATION\n",
6113 fname,
6114 nt_errstr(status));
6115 goto out;
6118 /* Close the stream handle. */
6119 status = cli_close(cli1, fnum1);
6120 if (!NT_STATUS_IS_OK(status)) {
6121 printf("cli_close of %s failed (%s)\n",
6122 stream_fname,
6123 nt_errstr(status));
6124 goto out;
6126 fnum1 = (uint16_t)-1;
6128 /* POSIX unlink after stream handle closed should succeed. */
6129 status = cli_posix_unlink(cli2, fname);
6130 if (!NT_STATUS_IS_OK(status)) {
6131 printf("cli_posix_unlink of %s failed (%s)\n",
6132 fname,
6133 nt_errstr(status));
6134 goto out;
6137 printf("POSIX stream delete test passed\n");
6138 correct = true;
6140 out:
6142 if (fnum1 != (uint16_t)-1) {
6143 cli_close(cli1, fnum1);
6144 fnum1 = (uint16_t)-1;
6147 cli_setatr(cli1, fname, 0, 0);
6148 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6150 if (!torture_close_connection(cli1)) {
6151 correct = false;
6153 if (!torture_close_connection(cli2)) {
6154 correct = false;
6157 TALLOC_FREE(frame);
6158 return correct;
6162 Test setting EA's are rejected on symlinks.
6164 static bool run_ea_symlink_test(int dummy)
6166 static struct cli_state *cli;
6167 const char *fname = "posix_file_ea";
6168 const char *sname = "posix_symlink_ea";
6169 const char *ea_name = "testea_name";
6170 const char *ea_value = "testea_value";
6171 uint16_t fnum = (uint16_t)-1;
6172 bool correct = false;
6173 NTSTATUS status;
6174 size_t i, num_eas;
6175 struct ea_struct *eas = NULL;
6176 TALLOC_CTX *frame = NULL;
6178 frame = talloc_stackframe();
6180 printf("Starting EA symlink test\n");
6182 if (!torture_open_connection(&cli, 0)) {
6183 TALLOC_FREE(frame);
6184 return false;
6187 smbXcli_conn_set_sockopt(cli->conn, sockops);
6189 status = torture_setup_unix_extensions(cli);
6190 if (!NT_STATUS_IS_OK(status)) {
6191 TALLOC_FREE(frame);
6192 return false;
6195 cli_setatr(cli, fname, 0, 0);
6196 cli_posix_unlink(cli, fname);
6197 cli_setatr(cli, sname, 0, 0);
6198 cli_posix_unlink(cli, sname);
6200 status = cli_ntcreate(cli,
6201 fname,
6203 READ_CONTROL_ACCESS,
6205 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6206 FILE_CREATE,
6207 0x0,
6208 0x0,
6209 &fnum,
6210 NULL);
6212 if (!NT_STATUS_IS_OK(status)) {
6213 printf("cli_ntcreate of %s failed (%s)\n",
6214 fname,
6215 nt_errstr(status));
6216 goto out;
6219 status = cli_close(cli, fnum);
6220 if (!NT_STATUS_IS_OK(status)) {
6221 printf("close failed (%s)\n",
6222 nt_errstr(status));
6223 goto out;
6225 fnum = (uint16_t)-1;
6227 /* Set an EA on the path. */
6228 status = cli_set_ea_path(cli,
6229 fname,
6230 ea_name,
6231 ea_value,
6232 strlen(ea_value)+1);
6234 if (!NT_STATUS_IS_OK(status)) {
6235 printf("cli_set_ea_path failed (%s)\n",
6236 nt_errstr(status));
6237 goto out;
6240 /* Now create a symlink. */
6241 status = cli_posix_symlink(cli, fname, sname);
6242 if (!NT_STATUS_IS_OK(status)) {
6243 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
6244 sname,
6245 fname,
6246 nt_errstr(status));
6247 goto out;
6250 /* Get the EA list on the path. Should return value set. */
6251 status = cli_get_ea_list_path(cli,
6252 fname,
6253 frame,
6254 &num_eas,
6255 &eas);
6257 if (!NT_STATUS_IS_OK(status)) {
6258 printf("cli_get_ea_list_path failed (%s)\n",
6259 nt_errstr(status));
6260 goto out;
6263 /* Ensure the EA we set is there. */
6264 for (i=0; i<num_eas; i++) {
6265 if (strcmp(eas[i].name, ea_name) == 0 &&
6266 eas[i].value.length == strlen(ea_value)+1 &&
6267 memcmp(eas[i].value.data,
6268 ea_value,
6269 eas[i].value.length) == 0) {
6270 break;
6274 if (i == num_eas) {
6275 printf("Didn't find EA on pathname %s\n",
6276 fname);
6277 goto out;
6280 num_eas = 0;
6281 TALLOC_FREE(eas);
6283 /* Get the EA list on the symlink. Should return empty list. */
6284 status = cli_get_ea_list_path(cli,
6285 sname,
6286 frame,
6287 &num_eas,
6288 &eas);
6290 if (!NT_STATUS_IS_OK(status)) {
6291 printf("cli_get_ea_list_path failed (%s)\n",
6292 nt_errstr(status));
6293 goto out;
6296 if (num_eas != 0) {
6297 printf("cli_get_ea_list_path failed (%s)\n",
6298 nt_errstr(status));
6299 goto out;
6302 /* Set an EA on the symlink. Should fail. */
6303 status = cli_set_ea_path(cli,
6304 sname,
6305 ea_name,
6306 ea_value,
6307 strlen(ea_value)+1);
6309 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6310 printf("cli_set_ea_path on a symlink gave %s. "
6311 "Should be NT_STATUS_ACCESS_DENIED.\n",
6312 nt_errstr(status));
6313 goto out;
6316 printf("EA symlink test passed\n");
6317 correct = true;
6319 out:
6321 if (fnum != (uint16_t)-1) {
6322 cli_close(cli, fnum);
6323 fnum = (uint16_t)-1;
6326 cli_setatr(cli, sname, 0, 0);
6327 cli_posix_unlink(cli, sname);
6328 cli_setatr(cli, fname, 0, 0);
6329 cli_posix_unlink(cli, fname);
6331 if (!torture_close_connection(cli)) {
6332 correct = false;
6335 TALLOC_FREE(frame);
6336 return correct;
6340 Test POSIX locks are OFD-locks.
6342 static bool run_posix_ofd_lock_test(int dummy)
6344 static struct cli_state *cli;
6345 const char *fname = "posix_file";
6346 uint16_t fnum1 = (uint16_t)-1;
6347 uint16_t fnum2 = (uint16_t)-1;
6348 bool correct = false;
6349 NTSTATUS status;
6350 TALLOC_CTX *frame = NULL;
6352 frame = talloc_stackframe();
6354 printf("Starting POSIX ofd-lock test\n");
6356 if (!torture_open_connection(&cli, 0)) {
6357 TALLOC_FREE(frame);
6358 return false;
6361 smbXcli_conn_set_sockopt(cli->conn, sockops);
6363 status = torture_setup_unix_extensions(cli);
6364 if (!NT_STATUS_IS_OK(status)) {
6365 TALLOC_FREE(frame);
6366 return false;
6369 cli_setatr(cli, fname, 0, 0);
6370 cli_posix_unlink(cli, fname);
6372 /* Open the file twice. */
6373 status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
6374 0600, &fnum1);
6375 if (!NT_STATUS_IS_OK(status)) {
6376 printf("First POSIX open of %s failed\n", fname);
6377 goto out;
6380 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
6381 if (!NT_STATUS_IS_OK(status)) {
6382 printf("First POSIX open of %s failed\n", fname);
6383 goto out;
6386 /* Set a 0-50 lock on fnum1. */
6387 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
6388 if (!NT_STATUS_IS_OK(status)) {
6389 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
6390 goto out;
6393 /* Set a 60-100 lock on fnum2. */
6394 status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
6395 if (!NT_STATUS_IS_OK(status)) {
6396 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
6397 goto out;
6400 /* close fnum1 - 0-50 lock should go away. */
6401 status = cli_close(cli, fnum1);
6402 if (!NT_STATUS_IS_OK(status)) {
6403 printf("close failed (%s)\n",
6404 nt_errstr(status));
6405 goto out;
6407 fnum1 = (uint16_t)-1;
6409 /* Change the lock context. */
6410 cli_setpid(cli, cli_getpid(cli) + 1);
6412 /* Re-open fnum1. */
6413 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
6414 if (!NT_STATUS_IS_OK(status)) {
6415 printf("Third POSIX open of %s failed\n", fname);
6416 goto out;
6419 /* 60-100 lock should still be there. */
6420 status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
6421 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
6422 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
6423 goto out;
6426 /* 0-50 lock should be gone. */
6427 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
6428 if (!NT_STATUS_IS_OK(status)) {
6429 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
6430 goto out;
6433 printf("POSIX OFD lock test passed\n");
6434 correct = true;
6436 out:
6438 if (fnum1 != (uint16_t)-1) {
6439 cli_close(cli, fnum1);
6440 fnum1 = (uint16_t)-1;
6442 if (fnum2 != (uint16_t)-1) {
6443 cli_close(cli, fnum2);
6444 fnum2 = (uint16_t)-1;
6447 cli_setatr(cli, fname, 0, 0);
6448 cli_posix_unlink(cli, fname);
6450 if (!torture_close_connection(cli)) {
6451 correct = false;
6454 TALLOC_FREE(frame);
6455 return correct;
6458 static uint32_t open_attrs_table[] = {
6459 FILE_ATTRIBUTE_NORMAL,
6460 FILE_ATTRIBUTE_ARCHIVE,
6461 FILE_ATTRIBUTE_READONLY,
6462 FILE_ATTRIBUTE_HIDDEN,
6463 FILE_ATTRIBUTE_SYSTEM,
6465 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
6466 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
6467 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
6468 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
6469 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
6470 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
6472 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
6473 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
6474 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
6475 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
6478 struct trunc_open_results {
6479 unsigned int num;
6480 uint32_t init_attr;
6481 uint32_t trunc_attr;
6482 uint32_t result_attr;
6485 static struct trunc_open_results attr_results[] = {
6486 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
6487 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
6488 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
6489 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
6490 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
6491 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
6492 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
6493 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
6494 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
6495 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
6496 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
6497 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
6498 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
6499 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
6500 { 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 },
6501 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
6502 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
6503 { 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 },
6504 { 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 },
6505 { 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 },
6506 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
6507 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
6508 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
6509 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
6510 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
6511 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
6514 static bool run_openattrtest(int dummy)
6516 static struct cli_state *cli1;
6517 const char *fname = "\\openattr.file";
6518 uint16_t fnum1;
6519 bool correct = True;
6520 uint16_t attr;
6521 unsigned int i, j, k, l;
6522 NTSTATUS status;
6524 printf("starting open attr test\n");
6526 if (!torture_open_connection(&cli1, 0)) {
6527 return False;
6530 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6532 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
6533 cli_setatr(cli1, fname, 0, 0);
6534 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6536 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
6537 open_attrs_table[i], FILE_SHARE_NONE,
6538 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6539 if (!NT_STATUS_IS_OK(status)) {
6540 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
6541 return False;
6544 status = cli_close(cli1, fnum1);
6545 if (!NT_STATUS_IS_OK(status)) {
6546 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
6547 return False;
6550 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
6551 status = cli_ntcreate(cli1, fname, 0,
6552 FILE_READ_DATA|FILE_WRITE_DATA,
6553 open_attrs_table[j],
6554 FILE_SHARE_NONE, FILE_OVERWRITE,
6555 0, 0, &fnum1, NULL);
6556 if (!NT_STATUS_IS_OK(status)) {
6557 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
6558 if (attr_results[l].num == k) {
6559 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
6560 k, open_attrs_table[i],
6561 open_attrs_table[j],
6562 fname, NT_STATUS_V(status), nt_errstr(status));
6563 correct = False;
6567 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6568 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
6569 k, open_attrs_table[i], open_attrs_table[j],
6570 nt_errstr(status));
6571 correct = False;
6573 #if 0
6574 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
6575 #endif
6576 k++;
6577 continue;
6580 status = cli_close(cli1, fnum1);
6581 if (!NT_STATUS_IS_OK(status)) {
6582 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
6583 return False;
6586 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
6587 if (!NT_STATUS_IS_OK(status)) {
6588 printf("getatr(2) failed (%s)\n", nt_errstr(status));
6589 return False;
6592 #if 0
6593 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
6594 k, open_attrs_table[i], open_attrs_table[j], attr );
6595 #endif
6597 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
6598 if (attr_results[l].num == k) {
6599 if (attr != attr_results[l].result_attr ||
6600 open_attrs_table[i] != attr_results[l].init_attr ||
6601 open_attrs_table[j] != attr_results[l].trunc_attr) {
6602 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
6603 open_attrs_table[i],
6604 open_attrs_table[j],
6605 (unsigned int)attr,
6606 attr_results[l].result_attr);
6607 correct = False;
6609 break;
6612 k++;
6616 cli_setatr(cli1, fname, 0, 0);
6617 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6619 printf("open attr test %s.\n", correct ? "passed" : "failed");
6621 if (!torture_close_connection(cli1)) {
6622 correct = False;
6624 return correct;
6627 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
6628 const char *name, void *state)
6630 int *matched = (int *)state;
6631 if (matched != NULL) {
6632 *matched += 1;
6634 return NT_STATUS_OK;
6638 test directory listing speed
6640 static bool run_dirtest(int dummy)
6642 int i;
6643 static struct cli_state *cli;
6644 uint16_t fnum;
6645 struct timeval core_start;
6646 bool correct = True;
6647 int matched;
6649 printf("starting directory test\n");
6651 if (!torture_open_connection(&cli, 0)) {
6652 return False;
6655 smbXcli_conn_set_sockopt(cli->conn, sockops);
6657 srandom(0);
6658 for (i=0;i<torture_numops;i++) {
6659 fstring fname;
6660 slprintf(fname, sizeof(fname), "\\%x", (int)random());
6661 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
6662 fprintf(stderr,"Failed to open %s\n", fname);
6663 return False;
6665 cli_close(cli, fnum);
6668 core_start = timeval_current();
6670 matched = 0;
6671 cli_list(cli, "a*.*", 0, list_fn, &matched);
6672 printf("Matched %d\n", matched);
6674 matched = 0;
6675 cli_list(cli, "b*.*", 0, list_fn, &matched);
6676 printf("Matched %d\n", matched);
6678 matched = 0;
6679 cli_list(cli, "xyzabc", 0, list_fn, &matched);
6680 printf("Matched %d\n", matched);
6682 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
6684 srandom(0);
6685 for (i=0;i<torture_numops;i++) {
6686 fstring fname;
6687 slprintf(fname, sizeof(fname), "\\%x", (int)random());
6688 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6691 if (!torture_close_connection(cli)) {
6692 correct = False;
6695 printf("finished dirtest\n");
6697 return correct;
6700 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
6701 void *state)
6703 struct cli_state *pcli = (struct cli_state *)state;
6704 fstring fname;
6705 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
6707 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
6708 return NT_STATUS_OK;
6710 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
6711 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
6712 printf("del_fn: failed to rmdir %s\n,", fname );
6713 } else {
6714 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
6715 printf("del_fn: failed to unlink %s\n,", fname );
6717 return NT_STATUS_OK;
6722 sees what IOCTLs are supported
6724 bool torture_ioctl_test(int dummy)
6726 static struct cli_state *cli;
6727 uint16_t device, function;
6728 uint16_t fnum;
6729 const char *fname = "\\ioctl.dat";
6730 DATA_BLOB blob;
6731 NTSTATUS status;
6733 if (!torture_open_connection(&cli, 0)) {
6734 return False;
6737 printf("starting ioctl test\n");
6739 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6741 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6742 if (!NT_STATUS_IS_OK(status)) {
6743 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6744 return False;
6747 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
6748 printf("ioctl device info: %s\n", nt_errstr(status));
6750 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
6751 printf("ioctl job info: %s\n", nt_errstr(status));
6753 for (device=0;device<0x100;device++) {
6754 printf("ioctl test with device = 0x%x\n", device);
6755 for (function=0;function<0x100;function++) {
6756 uint32_t code = (device<<16) | function;
6758 status = cli_raw_ioctl(cli, fnum, code, &blob);
6760 if (NT_STATUS_IS_OK(status)) {
6761 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
6762 (int)blob.length);
6763 data_blob_free(&blob);
6768 if (!torture_close_connection(cli)) {
6769 return False;
6772 return True;
6777 tries varients of chkpath
6779 bool torture_chkpath_test(int dummy)
6781 static struct cli_state *cli;
6782 uint16_t fnum;
6783 bool ret;
6784 NTSTATUS status;
6786 if (!torture_open_connection(&cli, 0)) {
6787 return False;
6790 printf("starting chkpath test\n");
6792 /* cleanup from an old run */
6793 cli_rmdir(cli, "\\chkpath.dir\\dir2");
6794 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6795 cli_rmdir(cli, "\\chkpath.dir");
6797 status = cli_mkdir(cli, "\\chkpath.dir");
6798 if (!NT_STATUS_IS_OK(status)) {
6799 printf("mkdir1 failed : %s\n", nt_errstr(status));
6800 return False;
6803 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
6804 if (!NT_STATUS_IS_OK(status)) {
6805 printf("mkdir2 failed : %s\n", nt_errstr(status));
6806 return False;
6809 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
6810 DENY_NONE, &fnum);
6811 if (!NT_STATUS_IS_OK(status)) {
6812 printf("open1 failed (%s)\n", nt_errstr(status));
6813 return False;
6815 cli_close(cli, fnum);
6817 status = cli_chkpath(cli, "\\chkpath.dir");
6818 if (!NT_STATUS_IS_OK(status)) {
6819 printf("chkpath1 failed: %s\n", nt_errstr(status));
6820 ret = False;
6823 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
6824 if (!NT_STATUS_IS_OK(status)) {
6825 printf("chkpath2 failed: %s\n", nt_errstr(status));
6826 ret = False;
6829 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
6830 if (!NT_STATUS_IS_OK(status)) {
6831 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6832 NT_STATUS_NOT_A_DIRECTORY);
6833 } else {
6834 printf("* chkpath on a file should fail\n");
6835 ret = False;
6838 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
6839 if (!NT_STATUS_IS_OK(status)) {
6840 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
6841 NT_STATUS_OBJECT_NAME_NOT_FOUND);
6842 } else {
6843 printf("* chkpath on a non existent file should fail\n");
6844 ret = False;
6847 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
6848 if (!NT_STATUS_IS_OK(status)) {
6849 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6850 NT_STATUS_OBJECT_PATH_NOT_FOUND);
6851 } else {
6852 printf("* chkpath on a non existent component should fail\n");
6853 ret = False;
6856 cli_rmdir(cli, "\\chkpath.dir\\dir2");
6857 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6858 cli_rmdir(cli, "\\chkpath.dir");
6860 if (!torture_close_connection(cli)) {
6861 return False;
6864 return ret;
6867 static bool run_eatest(int dummy)
6869 static struct cli_state *cli;
6870 const char *fname = "\\eatest.txt";
6871 bool correct = True;
6872 uint16_t fnum;
6873 int i;
6874 size_t num_eas;
6875 struct ea_struct *ea_list = NULL;
6876 TALLOC_CTX *mem_ctx = talloc_init("eatest");
6877 NTSTATUS status;
6879 printf("starting eatest\n");
6881 if (!torture_open_connection(&cli, 0)) {
6882 talloc_destroy(mem_ctx);
6883 return False;
6886 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6888 status = cli_ntcreate(cli, fname, 0,
6889 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6890 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
6891 0x4044, 0, &fnum, NULL);
6892 if (!NT_STATUS_IS_OK(status)) {
6893 printf("open failed - %s\n", nt_errstr(status));
6894 talloc_destroy(mem_ctx);
6895 return False;
6898 for (i = 0; i < 10; i++) {
6899 fstring ea_name, ea_val;
6901 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
6902 memset(ea_val, (char)i+1, i+1);
6903 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
6904 if (!NT_STATUS_IS_OK(status)) {
6905 printf("ea_set of name %s failed - %s\n", ea_name,
6906 nt_errstr(status));
6907 talloc_destroy(mem_ctx);
6908 return False;
6912 cli_close(cli, fnum);
6913 for (i = 0; i < 10; i++) {
6914 fstring ea_name, ea_val;
6916 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
6917 memset(ea_val, (char)i+1, i+1);
6918 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
6919 if (!NT_STATUS_IS_OK(status)) {
6920 printf("ea_set of name %s failed - %s\n", ea_name,
6921 nt_errstr(status));
6922 talloc_destroy(mem_ctx);
6923 return False;
6927 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6928 if (!NT_STATUS_IS_OK(status)) {
6929 printf("ea_get list failed - %s\n", nt_errstr(status));
6930 correct = False;
6933 printf("num_eas = %d\n", (int)num_eas);
6935 if (num_eas != 20) {
6936 printf("Should be 20 EA's stored... failing.\n");
6937 correct = False;
6940 for (i = 0; i < num_eas; i++) {
6941 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6942 dump_data(0, ea_list[i].value.data,
6943 ea_list[i].value.length);
6946 /* Setting EA's to zero length deletes them. Test this */
6947 printf("Now deleting all EA's - case indepenent....\n");
6949 #if 1
6950 cli_set_ea_path(cli, fname, "", "", 0);
6951 #else
6952 for (i = 0; i < 20; i++) {
6953 fstring ea_name;
6954 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
6955 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
6956 if (!NT_STATUS_IS_OK(status)) {
6957 printf("ea_set of name %s failed - %s\n", ea_name,
6958 nt_errstr(status));
6959 talloc_destroy(mem_ctx);
6960 return False;
6963 #endif
6965 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6966 if (!NT_STATUS_IS_OK(status)) {
6967 printf("ea_get list failed - %s\n", nt_errstr(status));
6968 correct = False;
6971 printf("num_eas = %d\n", (int)num_eas);
6972 for (i = 0; i < num_eas; i++) {
6973 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6974 dump_data(0, ea_list[i].value.data,
6975 ea_list[i].value.length);
6978 if (num_eas != 0) {
6979 printf("deleting EA's failed.\n");
6980 correct = False;
6983 /* Try and delete a non existent EA. */
6984 status = cli_set_ea_path(cli, fname, "foo", "", 0);
6985 if (!NT_STATUS_IS_OK(status)) {
6986 printf("deleting non-existent EA 'foo' should succeed. %s\n",
6987 nt_errstr(status));
6988 correct = False;
6991 talloc_destroy(mem_ctx);
6992 if (!torture_close_connection(cli)) {
6993 correct = False;
6996 return correct;
6999 static bool run_dirtest1(int dummy)
7001 int i;
7002 static struct cli_state *cli;
7003 uint16_t fnum;
7004 int num_seen;
7005 bool correct = True;
7007 printf("starting directory test\n");
7009 if (!torture_open_connection(&cli, 0)) {
7010 return False;
7013 smbXcli_conn_set_sockopt(cli->conn, sockops);
7015 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
7016 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
7017 cli_rmdir(cli, "\\LISTDIR");
7018 cli_mkdir(cli, "\\LISTDIR");
7020 /* Create 1000 files and 1000 directories. */
7021 for (i=0;i<1000;i++) {
7022 fstring fname;
7023 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
7024 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
7025 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
7026 0, 0, &fnum, NULL))) {
7027 fprintf(stderr,"Failed to open %s\n", fname);
7028 return False;
7030 cli_close(cli, fnum);
7032 for (i=0;i<1000;i++) {
7033 fstring fname;
7034 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
7035 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
7036 fprintf(stderr,"Failed to open %s\n", fname);
7037 return False;
7041 /* Now ensure that doing an old list sees both files and directories. */
7042 num_seen = 0;
7043 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7044 printf("num_seen = %d\n", num_seen );
7045 /* We should see 100 files + 1000 directories + . and .. */
7046 if (num_seen != 2002)
7047 correct = False;
7049 /* Ensure if we have the "must have" bits we only see the
7050 * relevent entries.
7052 num_seen = 0;
7053 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7054 printf("num_seen = %d\n", num_seen );
7055 if (num_seen != 1002)
7056 correct = False;
7058 num_seen = 0;
7059 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7060 printf("num_seen = %d\n", num_seen );
7061 if (num_seen != 1000)
7062 correct = False;
7064 /* Delete everything. */
7065 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
7066 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
7067 cli_rmdir(cli, "\\LISTDIR");
7069 #if 0
7070 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
7071 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
7072 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
7073 #endif
7075 if (!torture_close_connection(cli)) {
7076 correct = False;
7079 printf("finished dirtest1\n");
7081 return correct;
7084 static bool run_error_map_extract(int dummy) {
7086 static struct cli_state *c_dos;
7087 static struct cli_state *c_nt;
7088 NTSTATUS status;
7090 uint32_t error;
7092 uint32_t errnum;
7093 uint8_t errclass;
7095 NTSTATUS nt_status;
7097 fstring user;
7099 /* NT-Error connection */
7101 disable_spnego = true;
7102 if (!(c_nt = open_nbt_connection())) {
7103 disable_spnego = false;
7104 return False;
7106 disable_spnego = false;
7108 status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
7109 PROTOCOL_NT1);
7111 if (!NT_STATUS_IS_OK(status)) {
7112 printf("%s rejected the NT-error negprot (%s)\n", host,
7113 nt_errstr(status));
7114 cli_shutdown(c_nt);
7115 return False;
7118 status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
7119 if (!NT_STATUS_IS_OK(status)) {
7120 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
7121 return False;
7124 /* DOS-Error connection */
7126 disable_spnego = true;
7127 force_dos_errors = true;
7128 if (!(c_dos = open_nbt_connection())) {
7129 disable_spnego = false;
7130 force_dos_errors = false;
7131 return False;
7133 disable_spnego = false;
7134 force_dos_errors = false;
7136 status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
7137 PROTOCOL_NT1);
7138 if (!NT_STATUS_IS_OK(status)) {
7139 printf("%s rejected the DOS-error negprot (%s)\n", host,
7140 nt_errstr(status));
7141 cli_shutdown(c_dos);
7142 return False;
7145 status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
7146 if (!NT_STATUS_IS_OK(status)) {
7147 printf("%s rejected the DOS-error initial session setup (%s)\n",
7148 host, nt_errstr(status));
7149 return False;
7152 c_nt->map_dos_errors = false;
7153 c_dos->map_dos_errors = false;
7155 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
7156 fstr_sprintf(user, "%X", error);
7158 status = cli_session_setup(c_nt, user,
7159 password, strlen(password),
7160 password, strlen(password),
7161 workgroup);
7162 if (NT_STATUS_IS_OK(status)) {
7163 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
7166 /* Case #1: 32-bit NT errors */
7167 if (!NT_STATUS_IS_DOS(status)) {
7168 nt_status = status;
7169 } else {
7170 printf("/** Dos error on NT connection! (%s) */\n",
7171 nt_errstr(status));
7172 nt_status = NT_STATUS(0xc0000000);
7175 status = cli_session_setup(c_dos, user,
7176 password, strlen(password),
7177 password, strlen(password),
7178 workgroup);
7179 if (NT_STATUS_IS_OK(status)) {
7180 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
7183 /* Case #1: 32-bit NT errors */
7184 if (NT_STATUS_IS_DOS(status)) {
7185 printf("/** NT error on DOS connection! (%s) */\n",
7186 nt_errstr(status));
7187 errnum = errclass = 0;
7188 } else {
7189 errclass = NT_STATUS_DOS_CLASS(status);
7190 errnum = NT_STATUS_DOS_CODE(status);
7193 if (NT_STATUS_V(nt_status) != error) {
7194 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
7195 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
7196 get_nt_error_c_code(talloc_tos(), nt_status));
7199 printf("\t{%s,\t%s,\t%s},\n",
7200 smb_dos_err_class(errclass),
7201 smb_dos_err_name(errclass, errnum),
7202 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
7204 return True;
7207 static bool run_sesssetup_bench(int dummy)
7209 static struct cli_state *c;
7210 const char *fname = "\\file.dat";
7211 uint16_t fnum;
7212 NTSTATUS status;
7213 int i;
7215 if (!torture_open_connection(&c, 0)) {
7216 return false;
7219 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7220 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7221 FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
7222 if (!NT_STATUS_IS_OK(status)) {
7223 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7224 return false;
7227 for (i=0; i<torture_numops; i++) {
7228 status = cli_session_setup(
7229 c, username,
7230 password, strlen(password),
7231 password, strlen(password),
7232 workgroup);
7233 if (!NT_STATUS_IS_OK(status)) {
7234 d_printf("(%s) cli_session_setup failed: %s\n",
7235 __location__, nt_errstr(status));
7236 return false;
7239 d_printf("\r%d ", (int)cli_state_get_uid(c));
7241 status = cli_ulogoff(c);
7242 if (!NT_STATUS_IS_OK(status)) {
7243 d_printf("(%s) cli_ulogoff failed: %s\n",
7244 __location__, nt_errstr(status));
7245 return false;
7249 return true;
7252 static bool subst_test(const char *str, const char *user, const char *domain,
7253 uid_t uid, gid_t gid, const char *expected)
7255 char *subst;
7256 bool result = true;
7258 subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
7260 if (strcmp(subst, expected) != 0) {
7261 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
7262 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
7263 expected);
7264 result = false;
7267 TALLOC_FREE(subst);
7268 return result;
7271 static void chain1_open_completion(struct tevent_req *req)
7273 uint16_t fnum;
7274 NTSTATUS status;
7275 status = cli_openx_recv(req, &fnum);
7276 TALLOC_FREE(req);
7278 d_printf("cli_openx_recv returned %s: %d\n",
7279 nt_errstr(status),
7280 NT_STATUS_IS_OK(status) ? fnum : -1);
7283 static void chain1_write_completion(struct tevent_req *req)
7285 size_t written;
7286 NTSTATUS status;
7287 status = cli_write_andx_recv(req, &written);
7288 TALLOC_FREE(req);
7290 d_printf("cli_write_andx_recv returned %s: %d\n",
7291 nt_errstr(status),
7292 NT_STATUS_IS_OK(status) ? (int)written : -1);
7295 static void chain1_close_completion(struct tevent_req *req)
7297 NTSTATUS status;
7298 bool *done = (bool *)tevent_req_callback_data_void(req);
7300 status = cli_close_recv(req);
7301 *done = true;
7303 TALLOC_FREE(req);
7305 d_printf("cli_close returned %s\n", nt_errstr(status));
7308 static bool run_chain1(int dummy)
7310 struct cli_state *cli1;
7311 struct tevent_context *evt = samba_tevent_context_init(NULL);
7312 struct tevent_req *reqs[3], *smbreqs[3];
7313 bool done = false;
7314 const char *str = "foobar";
7315 NTSTATUS status;
7317 printf("starting chain1 test\n");
7318 if (!torture_open_connection(&cli1, 0)) {
7319 return False;
7322 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7324 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, "\\test",
7325 O_CREAT|O_RDWR, 0, &smbreqs[0]);
7326 if (reqs[0] == NULL) return false;
7327 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
7330 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
7331 (const uint8_t *)str, 0, strlen(str)+1,
7332 smbreqs, 1, &smbreqs[1]);
7333 if (reqs[1] == NULL) return false;
7334 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
7336 reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
7337 if (reqs[2] == NULL) return false;
7338 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
7340 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
7341 if (!NT_STATUS_IS_OK(status)) {
7342 return false;
7345 while (!done) {
7346 tevent_loop_once(evt);
7349 torture_close_connection(cli1);
7350 return True;
7353 static void chain2_sesssetup_completion(struct tevent_req *req)
7355 NTSTATUS status;
7356 status = cli_session_setup_guest_recv(req);
7357 d_printf("sesssetup returned %s\n", nt_errstr(status));
7360 static void chain2_tcon_completion(struct tevent_req *req)
7362 bool *done = (bool *)tevent_req_callback_data_void(req);
7363 NTSTATUS status;
7364 status = cli_tcon_andx_recv(req);
7365 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
7366 *done = true;
7369 static bool run_chain2(int dummy)
7371 struct cli_state *cli1;
7372 struct tevent_context *evt = samba_tevent_context_init(NULL);
7373 struct tevent_req *reqs[2], *smbreqs[2];
7374 bool done = false;
7375 NTSTATUS status;
7377 printf("starting chain2 test\n");
7378 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
7379 port_to_use, SMB_SIGNING_DEFAULT, 0);
7380 if (!NT_STATUS_IS_OK(status)) {
7381 return False;
7384 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7386 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
7387 &smbreqs[0]);
7388 if (reqs[0] == NULL) return false;
7389 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
7391 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
7392 "?????", NULL, 0, &smbreqs[1]);
7393 if (reqs[1] == NULL) return false;
7394 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
7396 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
7397 if (!NT_STATUS_IS_OK(status)) {
7398 return false;
7401 while (!done) {
7402 tevent_loop_once(evt);
7405 torture_close_connection(cli1);
7406 return True;
7410 struct torture_createdel_state {
7411 struct tevent_context *ev;
7412 struct cli_state *cli;
7415 static void torture_createdel_created(struct tevent_req *subreq);
7416 static void torture_createdel_closed(struct tevent_req *subreq);
7418 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
7419 struct tevent_context *ev,
7420 struct cli_state *cli,
7421 const char *name)
7423 struct tevent_req *req, *subreq;
7424 struct torture_createdel_state *state;
7426 req = tevent_req_create(mem_ctx, &state,
7427 struct torture_createdel_state);
7428 if (req == NULL) {
7429 return NULL;
7431 state->ev = ev;
7432 state->cli = cli;
7434 subreq = cli_ntcreate_send(
7435 state, ev, cli, name, 0,
7436 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
7437 FILE_ATTRIBUTE_NORMAL,
7438 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7439 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
7441 if (tevent_req_nomem(subreq, req)) {
7442 return tevent_req_post(req, ev);
7444 tevent_req_set_callback(subreq, torture_createdel_created, req);
7445 return req;
7448 static void torture_createdel_created(struct tevent_req *subreq)
7450 struct tevent_req *req = tevent_req_callback_data(
7451 subreq, struct tevent_req);
7452 struct torture_createdel_state *state = tevent_req_data(
7453 req, struct torture_createdel_state);
7454 NTSTATUS status;
7455 uint16_t fnum;
7457 status = cli_ntcreate_recv(subreq, &fnum, NULL);
7458 TALLOC_FREE(subreq);
7459 if (tevent_req_nterror(req, status)) {
7460 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
7461 nt_errstr(status)));
7462 return;
7465 subreq = cli_close_send(state, state->ev, state->cli, fnum);
7466 if (tevent_req_nomem(subreq, req)) {
7467 return;
7469 tevent_req_set_callback(subreq, torture_createdel_closed, req);
7472 static void torture_createdel_closed(struct tevent_req *subreq)
7474 struct tevent_req *req = tevent_req_callback_data(
7475 subreq, struct tevent_req);
7476 NTSTATUS status;
7478 status = cli_close_recv(subreq);
7479 if (tevent_req_nterror(req, status)) {
7480 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
7481 return;
7483 tevent_req_done(req);
7486 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
7488 return tevent_req_simple_recv_ntstatus(req);
7491 struct torture_createdels_state {
7492 struct tevent_context *ev;
7493 struct cli_state *cli;
7494 const char *base_name;
7495 int sent;
7496 int received;
7497 int num_files;
7498 struct tevent_req **reqs;
7501 static void torture_createdels_done(struct tevent_req *subreq);
7503 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
7504 struct tevent_context *ev,
7505 struct cli_state *cli,
7506 const char *base_name,
7507 int num_parallel,
7508 int num_files)
7510 struct tevent_req *req;
7511 struct torture_createdels_state *state;
7512 int i;
7514 req = tevent_req_create(mem_ctx, &state,
7515 struct torture_createdels_state);
7516 if (req == NULL) {
7517 return NULL;
7519 state->ev = ev;
7520 state->cli = cli;
7521 state->base_name = talloc_strdup(state, base_name);
7522 if (tevent_req_nomem(state->base_name, req)) {
7523 return tevent_req_post(req, ev);
7525 state->num_files = MAX(num_parallel, num_files);
7526 state->sent = 0;
7527 state->received = 0;
7529 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
7530 if (tevent_req_nomem(state->reqs, req)) {
7531 return tevent_req_post(req, ev);
7534 for (i=0; i<num_parallel; i++) {
7535 char *name;
7537 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
7538 state->sent);
7539 if (tevent_req_nomem(name, req)) {
7540 return tevent_req_post(req, ev);
7542 state->reqs[i] = torture_createdel_send(
7543 state->reqs, state->ev, state->cli, name);
7544 if (tevent_req_nomem(state->reqs[i], req)) {
7545 return tevent_req_post(req, ev);
7547 name = talloc_move(state->reqs[i], &name);
7548 tevent_req_set_callback(state->reqs[i],
7549 torture_createdels_done, req);
7550 state->sent += 1;
7552 return req;
7555 static void torture_createdels_done(struct tevent_req *subreq)
7557 struct tevent_req *req = tevent_req_callback_data(
7558 subreq, struct tevent_req);
7559 struct torture_createdels_state *state = tevent_req_data(
7560 req, struct torture_createdels_state);
7561 size_t num_parallel = talloc_array_length(state->reqs);
7562 NTSTATUS status;
7563 char *name;
7564 int i;
7566 status = torture_createdel_recv(subreq);
7567 if (!NT_STATUS_IS_OK(status)){
7568 DEBUG(10, ("torture_createdel_recv returned %s\n",
7569 nt_errstr(status)));
7570 TALLOC_FREE(subreq);
7571 tevent_req_nterror(req, status);
7572 return;
7575 for (i=0; i<num_parallel; i++) {
7576 if (subreq == state->reqs[i]) {
7577 break;
7580 if (i == num_parallel) {
7581 DEBUG(10, ("received something we did not send\n"));
7582 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
7583 return;
7585 TALLOC_FREE(state->reqs[i]);
7587 if (state->sent >= state->num_files) {
7588 tevent_req_done(req);
7589 return;
7592 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
7593 state->sent);
7594 if (tevent_req_nomem(name, req)) {
7595 return;
7597 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
7598 state->cli, name);
7599 if (tevent_req_nomem(state->reqs[i], req)) {
7600 return;
7602 name = talloc_move(state->reqs[i], &name);
7603 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
7604 state->sent += 1;
7607 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
7609 return tevent_req_simple_recv_ntstatus(req);
7612 struct swallow_notify_state {
7613 struct tevent_context *ev;
7614 struct cli_state *cli;
7615 uint16_t fnum;
7616 uint32_t completion_filter;
7617 bool recursive;
7618 bool (*fn)(uint32_t action, const char *name, void *priv);
7619 void *priv;
7622 static void swallow_notify_done(struct tevent_req *subreq);
7624 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
7625 struct tevent_context *ev,
7626 struct cli_state *cli,
7627 uint16_t fnum,
7628 uint32_t completion_filter,
7629 bool recursive,
7630 bool (*fn)(uint32_t action,
7631 const char *name,
7632 void *priv),
7633 void *priv)
7635 struct tevent_req *req, *subreq;
7636 struct swallow_notify_state *state;
7638 req = tevent_req_create(mem_ctx, &state,
7639 struct swallow_notify_state);
7640 if (req == NULL) {
7641 return NULL;
7643 state->ev = ev;
7644 state->cli = cli;
7645 state->fnum = fnum;
7646 state->completion_filter = completion_filter;
7647 state->recursive = recursive;
7648 state->fn = fn;
7649 state->priv = priv;
7651 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
7652 0xffff, state->completion_filter,
7653 state->recursive);
7654 if (tevent_req_nomem(subreq, req)) {
7655 return tevent_req_post(req, ev);
7657 tevent_req_set_callback(subreq, swallow_notify_done, req);
7658 return req;
7661 static void swallow_notify_done(struct tevent_req *subreq)
7663 struct tevent_req *req = tevent_req_callback_data(
7664 subreq, struct tevent_req);
7665 struct swallow_notify_state *state = tevent_req_data(
7666 req, struct swallow_notify_state);
7667 NTSTATUS status;
7668 uint32_t i, num_changes;
7669 struct notify_change *changes;
7671 status = cli_notify_recv(subreq, state, &num_changes, &changes);
7672 TALLOC_FREE(subreq);
7673 if (!NT_STATUS_IS_OK(status)) {
7674 DEBUG(10, ("cli_notify_recv returned %s\n",
7675 nt_errstr(status)));
7676 tevent_req_nterror(req, status);
7677 return;
7680 for (i=0; i<num_changes; i++) {
7681 state->fn(changes[i].action, changes[i].name, state->priv);
7683 TALLOC_FREE(changes);
7685 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
7686 0xffff, state->completion_filter,
7687 state->recursive);
7688 if (tevent_req_nomem(subreq, req)) {
7689 return;
7691 tevent_req_set_callback(subreq, swallow_notify_done, req);
7694 static bool print_notifies(uint32_t action, const char *name, void *priv)
7696 if (DEBUGLEVEL > 5) {
7697 d_printf("%d %s\n", (int)action, name);
7699 return true;
7702 static void notify_bench_done(struct tevent_req *req)
7704 int *num_finished = (int *)tevent_req_callback_data_void(req);
7705 *num_finished += 1;
7708 static bool run_notify_bench(int dummy)
7710 const char *dname = "\\notify-bench";
7711 struct tevent_context *ev;
7712 NTSTATUS status;
7713 uint16_t dnum;
7714 struct tevent_req *req1;
7715 struct tevent_req *req2 = NULL;
7716 int i, num_unc_names;
7717 int num_finished = 0;
7719 printf("starting notify-bench test\n");
7721 if (use_multishare_conn) {
7722 char **unc_list;
7723 unc_list = file_lines_load(multishare_conn_fname,
7724 &num_unc_names, 0, NULL);
7725 if (!unc_list || num_unc_names <= 0) {
7726 d_printf("Failed to load unc names list from '%s'\n",
7727 multishare_conn_fname);
7728 return false;
7730 TALLOC_FREE(unc_list);
7731 } else {
7732 num_unc_names = 1;
7735 ev = samba_tevent_context_init(talloc_tos());
7736 if (ev == NULL) {
7737 d_printf("tevent_context_init failed\n");
7738 return false;
7741 for (i=0; i<num_unc_names; i++) {
7742 struct cli_state *cli;
7743 char *base_fname;
7745 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
7746 dname, i);
7747 if (base_fname == NULL) {
7748 return false;
7751 if (!torture_open_connection(&cli, i)) {
7752 return false;
7755 status = cli_ntcreate(cli, dname, 0,
7756 MAXIMUM_ALLOWED_ACCESS,
7757 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
7758 FILE_SHARE_DELETE,
7759 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
7760 &dnum, NULL);
7762 if (!NT_STATUS_IS_OK(status)) {
7763 d_printf("Could not create %s: %s\n", dname,
7764 nt_errstr(status));
7765 return false;
7768 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
7769 FILE_NOTIFY_CHANGE_FILE_NAME |
7770 FILE_NOTIFY_CHANGE_DIR_NAME |
7771 FILE_NOTIFY_CHANGE_ATTRIBUTES |
7772 FILE_NOTIFY_CHANGE_LAST_WRITE,
7773 false, print_notifies, NULL);
7774 if (req1 == NULL) {
7775 d_printf("Could not create notify request\n");
7776 return false;
7779 req2 = torture_createdels_send(talloc_tos(), ev, cli,
7780 base_fname, 10, torture_numops);
7781 if (req2 == NULL) {
7782 d_printf("Could not create createdels request\n");
7783 return false;
7785 TALLOC_FREE(base_fname);
7787 tevent_req_set_callback(req2, notify_bench_done,
7788 &num_finished);
7791 while (num_finished < num_unc_names) {
7792 int ret;
7793 ret = tevent_loop_once(ev);
7794 if (ret != 0) {
7795 d_printf("tevent_loop_once failed\n");
7796 return false;
7800 if (!tevent_req_poll(req2, ev)) {
7801 d_printf("tevent_req_poll failed\n");
7804 status = torture_createdels_recv(req2);
7805 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
7807 return true;
7810 static bool run_mangle1(int dummy)
7812 struct cli_state *cli;
7813 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
7814 uint16_t fnum;
7815 fstring alt_name;
7816 NTSTATUS status;
7817 time_t change_time, access_time, write_time;
7818 off_t size;
7819 uint16_t mode;
7821 printf("starting mangle1 test\n");
7822 if (!torture_open_connection(&cli, 0)) {
7823 return False;
7826 smbXcli_conn_set_sockopt(cli->conn, sockops);
7828 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7829 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7830 0, 0, &fnum, NULL);
7831 if (!NT_STATUS_IS_OK(status)) {
7832 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7833 return false;
7835 cli_close(cli, fnum);
7837 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
7838 if (!NT_STATUS_IS_OK(status)) {
7839 d_printf("cli_qpathinfo_alt_name failed: %s\n",
7840 nt_errstr(status));
7841 return false;
7843 d_printf("alt_name: %s\n", alt_name);
7845 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
7846 if (!NT_STATUS_IS_OK(status)) {
7847 d_printf("cli_openx(%s) failed: %s\n", alt_name,
7848 nt_errstr(status));
7849 return false;
7851 cli_close(cli, fnum);
7853 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
7854 &write_time, &size, &mode);
7855 if (!NT_STATUS_IS_OK(status)) {
7856 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
7857 nt_errstr(status));
7858 return false;
7861 return true;
7864 static size_t null_source(uint8_t *buf, size_t n, void *priv)
7866 size_t *to_pull = (size_t *)priv;
7867 size_t thistime = *to_pull;
7869 thistime = MIN(thistime, n);
7870 if (thistime == 0) {
7871 return 0;
7874 memset(buf, 0, thistime);
7875 *to_pull -= thistime;
7876 return thistime;
7879 static bool run_windows_write(int dummy)
7881 struct cli_state *cli1;
7882 uint16_t fnum;
7883 int i;
7884 bool ret = false;
7885 const char *fname = "\\writetest.txt";
7886 struct timeval start_time;
7887 double seconds;
7888 double kbytes;
7889 NTSTATUS status;
7891 printf("starting windows_write test\n");
7892 if (!torture_open_connection(&cli1, 0)) {
7893 return False;
7896 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7897 if (!NT_STATUS_IS_OK(status)) {
7898 printf("open failed (%s)\n", nt_errstr(status));
7899 return False;
7902 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7904 start_time = timeval_current();
7906 for (i=0; i<torture_numops; i++) {
7907 uint8_t c = 0;
7908 off_t start = i * torture_blocksize;
7909 size_t to_pull = torture_blocksize - 1;
7911 status = cli_writeall(cli1, fnum, 0, &c,
7912 start + torture_blocksize - 1, 1, NULL);
7913 if (!NT_STATUS_IS_OK(status)) {
7914 printf("cli_write failed: %s\n", nt_errstr(status));
7915 goto fail;
7918 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
7919 null_source, &to_pull);
7920 if (!NT_STATUS_IS_OK(status)) {
7921 printf("cli_push returned: %s\n", nt_errstr(status));
7922 goto fail;
7926 seconds = timeval_elapsed(&start_time);
7927 kbytes = (double)torture_blocksize * torture_numops;
7928 kbytes /= 1024;
7930 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
7931 (double)seconds, (int)(kbytes/seconds));
7933 ret = true;
7934 fail:
7935 cli_close(cli1, fnum);
7936 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7937 torture_close_connection(cli1);
7938 return ret;
7941 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
7943 size_t max_pdu = 0x1FFFF;
7945 if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
7946 max_pdu = 0xFFFFFF;
7949 if (smb1cli_conn_signing_is_active(cli->conn)) {
7950 max_pdu = 0x1FFFF;
7953 if (smb1cli_conn_encryption_on(cli->conn)) {
7954 max_pdu = CLI_BUFFER_SIZE;
7957 if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
7958 len_requested &= 0xFFFF;
7961 return MIN(len_requested,
7962 max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
7965 static bool check_read_call(struct cli_state *cli,
7966 uint16_t fnum,
7967 uint8_t *buf,
7968 size_t len_requested)
7970 NTSTATUS status;
7971 struct tevent_req *subreq = NULL;
7972 ssize_t len_read = 0;
7973 size_t len_expected = 0;
7974 struct tevent_context *ev = NULL;
7976 ev = samba_tevent_context_init(talloc_tos());
7977 if (ev == NULL) {
7978 return false;
7981 subreq = cli_read_andx_send(talloc_tos(),
7983 cli,
7984 fnum,
7986 len_requested);
7988 if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
7989 return false;
7992 status = cli_read_andx_recv(subreq, &len_read, &buf);
7993 if (!NT_STATUS_IS_OK(status)) {
7994 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
7995 return false;
7998 TALLOC_FREE(subreq);
7999 TALLOC_FREE(ev);
8001 len_expected = calc_expected_return(cli, len_requested);
8003 if (len_expected > 0x10000 && len_read == 0x10000) {
8004 /* Windows servers only return a max of 0x10000,
8005 doesn't matter if you set CAP_LARGE_READX in
8006 the client sessionsetupX call or not. */
8007 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
8008 (unsigned int)len_requested);
8009 } else if (len_read != len_expected) {
8010 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
8011 (unsigned int)len_requested,
8012 (unsigned int)len_read,
8013 (unsigned int)len_expected);
8014 return false;
8015 } else {
8016 d_printf("Correct read reply.\n");
8019 return true;
8022 /* Test large readX variants. */
8023 static bool large_readx_tests(struct cli_state *cli,
8024 uint16_t fnum,
8025 uint8_t *buf)
8027 /* A read of 0xFFFF0001 should *always* return 1 byte. */
8028 if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
8029 return false;
8031 /* A read of 0x10000 should return 0x10000 bytes. */
8032 if (check_read_call(cli, fnum, buf, 0x10000) == false) {
8033 return false;
8035 /* A read of 0x10000 should return 0x10001 bytes. */
8036 if (check_read_call(cli, fnum, buf, 0x10001) == false) {
8037 return false;
8039 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
8040 the requested number of bytes. */
8041 if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
8042 return false;
8044 /* A read of 1MB should return 1MB bytes (on Samba). */
8045 if (check_read_call(cli, fnum, buf, 0x100000) == false) {
8046 return false;
8049 if (check_read_call(cli, fnum, buf, 0x20001) == false) {
8050 return false;
8052 if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
8053 return false;
8055 if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
8056 return false;
8058 return true;
8061 static bool run_large_readx(int dummy)
8063 uint8_t *buf = NULL;
8064 struct cli_state *cli1 = NULL;
8065 struct cli_state *cli2 = NULL;
8066 bool correct = false;
8067 const char *fname = "\\large_readx.dat";
8068 NTSTATUS status;
8069 uint16_t fnum1 = UINT16_MAX;
8070 uint32_t normal_caps = 0;
8071 size_t file_size = 20*1024*1024;
8072 TALLOC_CTX *frame = talloc_stackframe();
8073 size_t i;
8074 struct {
8075 const char *name;
8076 enum smb_signing_setting signing_setting;
8077 enum protocol_types protocol;
8078 } runs[] = {
8080 .name = "NT1",
8081 .signing_setting = SMB_SIGNING_IF_REQUIRED,
8082 .protocol = PROTOCOL_NT1,
8084 .name = "NT1 - SIGNING_REQUIRED",
8085 .signing_setting = SMB_SIGNING_REQUIRED,
8086 .protocol = PROTOCOL_NT1,
8090 printf("starting large_readx test\n");
8092 if (!torture_open_connection(&cli1, 0)) {
8093 goto out;
8096 normal_caps = smb1cli_conn_capabilities(cli1->conn);
8098 if (!(normal_caps & CAP_LARGE_READX)) {
8099 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
8100 (unsigned int)normal_caps);
8101 goto out;
8104 /* Create a file of size 4MB. */
8105 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
8106 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8107 0, 0, &fnum1, NULL);
8109 if (!NT_STATUS_IS_OK(status)) {
8110 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8111 goto out;
8114 /* Write file_size bytes. */
8115 buf = talloc_zero_array(frame, uint8_t, file_size);
8116 if (buf == NULL) {
8117 goto out;
8120 status = cli_writeall(cli1,
8121 fnum1,
8123 buf,
8125 file_size,
8126 NULL);
8127 if (!NT_STATUS_IS_OK(status)) {
8128 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
8129 goto out;
8132 status = cli_close(cli1, fnum1);
8133 if (!NT_STATUS_IS_OK(status)) {
8134 d_printf("cli_close failed: %s\n", nt_errstr(status));
8135 goto out;
8138 fnum1 = UINT16_MAX;
8140 for (i=0; i < ARRAY_SIZE(runs); i++) {
8141 enum smb_signing_setting saved_signing_setting = signing_state;
8142 uint16_t fnum2 = -1;
8144 if (do_encrypt &&
8145 (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
8147 d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
8148 continue;
8151 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
8153 signing_state = runs[i].signing_setting;
8154 cli2 = open_nbt_connection();
8155 signing_state = saved_signing_setting;
8156 if (cli2 == NULL) {
8157 goto out;
8160 status = smbXcli_negprot(cli2->conn,
8161 cli2->timeout,
8162 runs[i].protocol,
8163 runs[i].protocol);
8164 if (!NT_STATUS_IS_OK(status)) {
8165 goto out;
8168 status = cli_session_setup(cli2,
8169 username,
8170 password,
8171 strlen(password)+1,
8172 password,
8173 strlen(password)+1,
8174 workgroup);
8175 if (!NT_STATUS_IS_OK(status)) {
8176 goto out;
8179 status = cli_tree_connect(cli2,
8180 share,
8181 "?????",
8182 password,
8183 strlen(password)+1);
8184 if (!NT_STATUS_IS_OK(status)) {
8185 goto out;
8188 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
8190 normal_caps = smb1cli_conn_capabilities(cli2->conn);
8192 if (!(normal_caps & CAP_LARGE_READX)) {
8193 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
8194 (unsigned int)normal_caps);
8195 goto out;
8198 if (do_encrypt) {
8199 if (force_cli_encryption(cli2, share) == false) {
8200 goto out;
8202 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
8203 uint16_t major, minor;
8204 uint32_t caplow, caphigh;
8206 status = cli_unix_extensions_version(cli2,
8207 &major, &minor,
8208 &caplow, &caphigh);
8209 if (!NT_STATUS_IS_OK(status)) {
8210 goto out;
8214 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
8215 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
8216 0, 0, &fnum2, NULL);
8217 if (!NT_STATUS_IS_OK(status)) {
8218 d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
8219 goto out;
8222 /* All reads must return less than file_size bytes. */
8223 if (!large_readx_tests(cli2, fnum2, buf)) {
8224 goto out;
8227 status = cli_close(cli2, fnum2);
8228 if (!NT_STATUS_IS_OK(status)) {
8229 d_printf("cli_close failed: %s\n", nt_errstr(status));
8230 goto out;
8232 fnum2 = -1;
8234 if (!torture_close_connection(cli2)) {
8235 goto out;
8237 cli2 = NULL;
8240 correct = true;
8241 printf("Success on large_readx test\n");
8243 out:
8245 if (cli2) {
8246 if (!torture_close_connection(cli2)) {
8247 correct = false;
8251 if (cli1) {
8252 if (fnum1 != UINT16_MAX) {
8253 status = cli_close(cli1, fnum1);
8254 if (!NT_STATUS_IS_OK(status)) {
8255 d_printf("cli_close failed: %s\n", nt_errstr(status));
8257 fnum1 = UINT16_MAX;
8260 status = cli_unlink(cli1, fname,
8261 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8262 if (!NT_STATUS_IS_OK(status)) {
8263 printf("unlink failed (%s)\n", nt_errstr(status));
8266 if (!torture_close_connection(cli1)) {
8267 correct = false;
8271 TALLOC_FREE(frame);
8273 printf("finished large_readx test\n");
8274 return correct;
8277 static bool run_cli_echo(int dummy)
8279 struct cli_state *cli;
8280 NTSTATUS status;
8282 printf("starting cli_echo test\n");
8283 if (!torture_open_connection(&cli, 0)) {
8284 return false;
8286 smbXcli_conn_set_sockopt(cli->conn, sockops);
8288 status = cli_echo(cli, 5, data_blob_const("hello", 5));
8290 d_printf("cli_echo returned %s\n", nt_errstr(status));
8292 torture_close_connection(cli);
8293 return NT_STATUS_IS_OK(status);
8296 static bool run_uid_regression_test(int dummy)
8298 static struct cli_state *cli;
8299 int16_t old_vuid;
8300 int16_t old_cnum;
8301 bool correct = True;
8302 NTSTATUS status;
8304 printf("starting uid regression test\n");
8306 if (!torture_open_connection(&cli, 0)) {
8307 return False;
8310 smbXcli_conn_set_sockopt(cli->conn, sockops);
8312 /* Ok - now save then logoff our current user. */
8313 old_vuid = cli_state_get_uid(cli);
8315 status = cli_ulogoff(cli);
8316 if (!NT_STATUS_IS_OK(status)) {
8317 d_printf("(%s) cli_ulogoff failed: %s\n",
8318 __location__, nt_errstr(status));
8319 correct = false;
8320 goto out;
8323 cli_state_set_uid(cli, old_vuid);
8325 /* Try an operation. */
8326 status = cli_mkdir(cli, "\\uid_reg_test");
8327 if (NT_STATUS_IS_OK(status)) {
8328 d_printf("(%s) cli_mkdir succeeded\n",
8329 __location__);
8330 correct = false;
8331 goto out;
8332 } else {
8333 /* Should be bad uid. */
8334 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
8335 NT_STATUS_USER_SESSION_DELETED)) {
8336 correct = false;
8337 goto out;
8341 old_cnum = cli_state_get_tid(cli);
8343 /* Now try a SMBtdis with the invald vuid set to zero. */
8344 cli_state_set_uid(cli, 0);
8346 /* This should succeed. */
8347 status = cli_tdis(cli);
8349 if (NT_STATUS_IS_OK(status)) {
8350 d_printf("First tdis with invalid vuid should succeed.\n");
8351 } else {
8352 d_printf("First tdis failed (%s)\n", nt_errstr(status));
8353 correct = false;
8354 goto out;
8357 cli_state_set_uid(cli, old_vuid);
8358 cli_state_set_tid(cli, old_cnum);
8360 /* This should fail. */
8361 status = cli_tdis(cli);
8362 if (NT_STATUS_IS_OK(status)) {
8363 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
8364 correct = false;
8365 goto out;
8366 } else {
8367 /* Should be bad tid. */
8368 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
8369 NT_STATUS_NETWORK_NAME_DELETED)) {
8370 correct = false;
8371 goto out;
8375 cli_rmdir(cli, "\\uid_reg_test");
8377 out:
8379 cli_shutdown(cli);
8380 return correct;
8384 static const char *illegal_chars = "*\\/?<>|\":";
8385 static char force_shortname_chars[] = " +,.[];=\177";
8387 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
8388 const char *mask, void *state)
8390 struct cli_state *pcli = (struct cli_state *)state;
8391 fstring fname;
8392 NTSTATUS status = NT_STATUS_OK;
8394 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
8396 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
8397 return NT_STATUS_OK;
8399 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
8400 status = cli_rmdir(pcli, fname);
8401 if (!NT_STATUS_IS_OK(status)) {
8402 printf("del_fn: failed to rmdir %s\n,", fname );
8404 } else {
8405 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8406 if (!NT_STATUS_IS_OK(status)) {
8407 printf("del_fn: failed to unlink %s\n,", fname );
8410 return status;
8413 struct sn_state {
8414 int matched;
8415 int i;
8416 bool val;
8419 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
8420 const char *name, void *state)
8422 struct sn_state *s = (struct sn_state *)state;
8423 int i = s->i;
8425 #if 0
8426 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
8427 i, finfo->name, finfo->short_name);
8428 #endif
8430 if (strchr(force_shortname_chars, i)) {
8431 if (!finfo->short_name) {
8432 /* Shortname not created when it should be. */
8433 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
8434 __location__, finfo->name, i);
8435 s->val = true;
8437 } else if (finfo->short_name){
8438 /* Shortname created when it should not be. */
8439 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
8440 __location__, finfo->short_name, finfo->name);
8441 s->val = true;
8443 s->matched += 1;
8444 return NT_STATUS_OK;
8447 static bool run_shortname_test(int dummy)
8449 static struct cli_state *cli;
8450 bool correct = True;
8451 int i;
8452 struct sn_state s;
8453 char fname[40];
8454 NTSTATUS status;
8456 printf("starting shortname test\n");
8458 if (!torture_open_connection(&cli, 0)) {
8459 return False;
8462 smbXcli_conn_set_sockopt(cli->conn, sockops);
8464 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
8465 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
8466 cli_rmdir(cli, "\\shortname");
8468 status = cli_mkdir(cli, "\\shortname");
8469 if (!NT_STATUS_IS_OK(status)) {
8470 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
8471 __location__, nt_errstr(status));
8472 correct = false;
8473 goto out;
8476 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
8477 correct = false;
8478 goto out;
8480 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
8481 correct = false;
8482 goto out;
8485 s.val = false;
8487 for (i = 32; i < 128; i++) {
8488 uint16_t fnum = (uint16_t)-1;
8490 s.i = i;
8492 if (strchr(illegal_chars, i)) {
8493 continue;
8495 fname[15] = i;
8497 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
8498 FILE_SHARE_READ|FILE_SHARE_WRITE,
8499 FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
8500 if (!NT_STATUS_IS_OK(status)) {
8501 d_printf("(%s) cli_nt_create of %s failed: %s\n",
8502 __location__, fname, nt_errstr(status));
8503 correct = false;
8504 goto out;
8506 cli_close(cli, fnum);
8508 s.matched = 0;
8509 status = cli_list(cli, "\\shortname\\test*.*", 0,
8510 shortname_list_fn, &s);
8511 if (s.matched != 1) {
8512 d_printf("(%s) failed to list %s: %s\n",
8513 __location__, fname, nt_errstr(status));
8514 correct = false;
8515 goto out;
8518 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8519 if (!NT_STATUS_IS_OK(status)) {
8520 d_printf("(%s) failed to delete %s: %s\n",
8521 __location__, fname, nt_errstr(status));
8522 correct = false;
8523 goto out;
8526 if (s.val) {
8527 correct = false;
8528 goto out;
8532 out:
8534 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
8535 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
8536 cli_rmdir(cli, "\\shortname");
8537 torture_close_connection(cli);
8538 return correct;
8541 static void pagedsearch_cb(struct tevent_req *req)
8543 TLDAPRC rc;
8544 struct tldap_message *msg;
8545 char *dn;
8547 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
8548 if (!TLDAP_RC_IS_SUCCESS(rc)) {
8549 d_printf("tldap_search_paged_recv failed: %s\n",
8550 tldap_rc2string(rc));
8551 return;
8553 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
8554 TALLOC_FREE(msg);
8555 return;
8557 if (!tldap_entry_dn(msg, &dn)) {
8558 d_printf("tldap_entry_dn failed\n");
8559 return;
8561 d_printf("%s\n", dn);
8562 TALLOC_FREE(msg);
8565 static bool run_tldap(int dummy)
8567 struct tldap_context *ld;
8568 int fd;
8569 TLDAPRC rc;
8570 NTSTATUS status;
8571 struct sockaddr_storage addr;
8572 struct tevent_context *ev;
8573 struct tevent_req *req;
8574 char *basedn;
8575 const char *filter;
8577 if (!resolve_name(host, &addr, 0, false)) {
8578 d_printf("could not find host %s\n", host);
8579 return false;
8581 status = open_socket_out(&addr, 389, 9999, &fd);
8582 if (!NT_STATUS_IS_OK(status)) {
8583 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
8584 return false;
8587 ld = tldap_context_create(talloc_tos(), fd);
8588 if (ld == NULL) {
8589 close(fd);
8590 d_printf("tldap_context_create failed\n");
8591 return false;
8594 rc = tldap_fetch_rootdse(ld);
8595 if (!TLDAP_RC_IS_SUCCESS(rc)) {
8596 d_printf("tldap_fetch_rootdse failed: %s\n",
8597 tldap_errstr(talloc_tos(), ld, rc));
8598 return false;
8601 basedn = tldap_talloc_single_attribute(
8602 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
8603 if (basedn == NULL) {
8604 d_printf("no defaultNamingContext\n");
8605 return false;
8607 d_printf("defaultNamingContext: %s\n", basedn);
8609 ev = samba_tevent_context_init(talloc_tos());
8610 if (ev == NULL) {
8611 d_printf("tevent_context_init failed\n");
8612 return false;
8615 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
8616 TLDAP_SCOPE_SUB, "(objectclass=*)",
8617 NULL, 0, 0,
8618 NULL, 0, NULL, 0, 0, 0, 0, 5);
8619 if (req == NULL) {
8620 d_printf("tldap_search_paged_send failed\n");
8621 return false;
8623 tevent_req_set_callback(req, pagedsearch_cb, NULL);
8625 tevent_req_poll(req, ev);
8627 TALLOC_FREE(req);
8629 /* test search filters against rootDSE */
8630 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
8631 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
8633 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
8634 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
8635 talloc_tos(), NULL);
8636 if (!TLDAP_RC_IS_SUCCESS(rc)) {
8637 d_printf("tldap_search with complex filter failed: %s\n",
8638 tldap_errstr(talloc_tos(), ld, rc));
8639 return false;
8642 TALLOC_FREE(ld);
8643 return true;
8646 /* Torture test to ensure no regression of :
8647 https://bugzilla.samba.org/show_bug.cgi?id=7084
8650 static bool run_dir_createtime(int dummy)
8652 struct cli_state *cli;
8653 const char *dname = "\\testdir";
8654 const char *fname = "\\testdir\\testfile";
8655 NTSTATUS status;
8656 struct timespec create_time;
8657 struct timespec create_time1;
8658 uint16_t fnum;
8659 bool ret = false;
8661 if (!torture_open_connection(&cli, 0)) {
8662 return false;
8665 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8666 cli_rmdir(cli, dname);
8668 status = cli_mkdir(cli, dname);
8669 if (!NT_STATUS_IS_OK(status)) {
8670 printf("mkdir failed: %s\n", nt_errstr(status));
8671 goto out;
8674 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
8675 NULL, NULL, NULL);
8676 if (!NT_STATUS_IS_OK(status)) {
8677 printf("cli_qpathinfo2 returned %s\n",
8678 nt_errstr(status));
8679 goto out;
8682 /* Sleep 3 seconds, then create a file. */
8683 sleep(3);
8685 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
8686 DENY_NONE, &fnum);
8687 if (!NT_STATUS_IS_OK(status)) {
8688 printf("cli_openx failed: %s\n", nt_errstr(status));
8689 goto out;
8692 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
8693 NULL, NULL, NULL);
8694 if (!NT_STATUS_IS_OK(status)) {
8695 printf("cli_qpathinfo2 (2) returned %s\n",
8696 nt_errstr(status));
8697 goto out;
8700 if (timespec_compare(&create_time1, &create_time)) {
8701 printf("run_dir_createtime: create time was updated (error)\n");
8702 } else {
8703 printf("run_dir_createtime: create time was not updated (correct)\n");
8704 ret = true;
8707 out:
8709 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8710 cli_rmdir(cli, dname);
8711 if (!torture_close_connection(cli)) {
8712 ret = false;
8714 return ret;
8718 static bool run_streamerror(int dummy)
8720 struct cli_state *cli;
8721 const char *dname = "\\testdir";
8722 const char *streamname =
8723 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
8724 NTSTATUS status;
8725 time_t change_time, access_time, write_time;
8726 off_t size;
8727 uint16_t mode, fnum;
8728 bool ret = true;
8730 if (!torture_open_connection(&cli, 0)) {
8731 return false;
8734 cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8735 cli_rmdir(cli, dname);
8737 status = cli_mkdir(cli, dname);
8738 if (!NT_STATUS_IS_OK(status)) {
8739 printf("mkdir failed: %s\n", nt_errstr(status));
8740 return false;
8743 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
8744 &write_time, &size, &mode);
8745 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
8746 printf("pathinfo returned %s, expected "
8747 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
8748 nt_errstr(status));
8749 ret = false;
8752 status = cli_ntcreate(cli, streamname, 0x16,
8753 FILE_READ_DATA|FILE_READ_EA|
8754 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
8755 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
8756 FILE_OPEN, 0, 0, &fnum, NULL);
8758 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
8759 printf("ntcreate returned %s, expected "
8760 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
8761 nt_errstr(status));
8762 ret = false;
8766 cli_rmdir(cli, dname);
8767 return ret;
8770 struct pidtest_state {
8771 bool success;
8772 uint16_t vwv[1];
8773 DATA_BLOB data;
8776 static void pid_echo_done(struct tevent_req *subreq);
8778 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
8779 struct tevent_context *ev,
8780 struct cli_state *cli)
8782 struct tevent_req *req, *subreq;
8783 struct pidtest_state *state;
8785 req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
8786 if (req == NULL) {
8787 return NULL;
8790 SSVAL(state->vwv, 0, 1);
8791 state->data = data_blob_const("hello", 5);
8793 subreq = smb1cli_req_send(state,
8795 cli->conn,
8796 SMBecho,
8797 0, 0, /* *_flags */
8798 0, 0, /* *_flags2 */
8799 cli->timeout,
8800 0xDEADBEEF, /* pid */
8801 NULL, /* tcon */
8802 NULL, /* session */
8803 ARRAY_SIZE(state->vwv), state->vwv,
8804 state->data.length, state->data.data);
8806 if (tevent_req_nomem(subreq, req)) {
8807 return tevent_req_post(req, ev);
8809 tevent_req_set_callback(subreq, pid_echo_done, req);
8810 return req;
8813 static void pid_echo_done(struct tevent_req *subreq)
8815 struct tevent_req *req = tevent_req_callback_data(
8816 subreq, struct tevent_req);
8817 struct pidtest_state *state = tevent_req_data(
8818 req, struct pidtest_state);
8819 NTSTATUS status;
8820 uint32_t num_bytes;
8821 uint8_t *bytes = NULL;
8822 struct iovec *recv_iov = NULL;
8823 uint8_t *phdr = NULL;
8824 uint16_t pidlow = 0;
8825 uint16_t pidhigh = 0;
8826 struct smb1cli_req_expected_response expected[] = {
8828 .status = NT_STATUS_OK,
8829 .wct = 1,
8833 status = smb1cli_req_recv(subreq, state,
8834 &recv_iov,
8835 &phdr,
8836 NULL, /* pwct */
8837 NULL, /* pvwv */
8838 NULL, /* pvwv_offset */
8839 &num_bytes,
8840 &bytes,
8841 NULL, /* pbytes_offset */
8842 NULL, /* pinbuf */
8843 expected, ARRAY_SIZE(expected));
8845 TALLOC_FREE(subreq);
8847 if (!NT_STATUS_IS_OK(status)) {
8848 tevent_req_nterror(req, status);
8849 return;
8852 if (num_bytes != state->data.length) {
8853 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
8854 return;
8857 if (memcmp(bytes, state->data.data, num_bytes) != 0) {
8858 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
8859 return;
8862 /* Check pid low/high == DEADBEEF */
8863 pidlow = SVAL(phdr, HDR_PID);
8864 if (pidlow != 0xBEEF){
8865 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
8866 (unsigned int)pidlow);
8867 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
8868 return;
8870 pidhigh = SVAL(phdr, HDR_PIDHIGH);
8871 if (pidhigh != 0xDEAD){
8872 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
8873 (unsigned int)pidhigh);
8874 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
8875 return;
8878 tevent_req_done(req);
8881 static NTSTATUS pid_echo_recv(struct tevent_req *req)
8883 return tevent_req_simple_recv_ntstatus(req);
8886 static bool run_pidhigh(int dummy)
8888 bool success = false;
8889 struct cli_state *cli = NULL;
8890 NTSTATUS status;
8891 struct tevent_context *ev = NULL;
8892 struct tevent_req *req = NULL;
8893 TALLOC_CTX *frame = talloc_stackframe();
8895 printf("starting pid high test\n");
8896 if (!torture_open_connection(&cli, 0)) {
8897 return false;
8899 smbXcli_conn_set_sockopt(cli->conn, sockops);
8901 ev = samba_tevent_context_init(frame);
8902 if (ev == NULL) {
8903 goto fail;
8906 req = pid_echo_send(frame, ev, cli);
8907 if (req == NULL) {
8908 goto fail;
8911 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
8912 goto fail;
8915 status = pid_echo_recv(req);
8916 if (NT_STATUS_IS_OK(status)) {
8917 printf("pid high test ok\n");
8918 success = true;
8921 fail:
8923 TALLOC_FREE(frame);
8924 torture_close_connection(cli);
8925 return success;
8928 static bool run_local_substitute(int dummy)
8930 bool ok = true;
8932 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
8933 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
8934 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
8935 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
8936 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
8937 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
8938 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
8939 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
8941 /* Different captialization rules in sub_basic... */
8943 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
8944 "blaDOM") == 0);
8946 return ok;
8949 static bool run_local_base64(int dummy)
8951 int i;
8952 bool ret = true;
8954 for (i=1; i<2000; i++) {
8955 DATA_BLOB blob1, blob2;
8956 char *b64;
8958 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
8959 blob1.length = i;
8960 generate_random_buffer(blob1.data, blob1.length);
8962 b64 = base64_encode_data_blob(talloc_tos(), blob1);
8963 if (b64 == NULL) {
8964 d_fprintf(stderr, "base64_encode_data_blob failed "
8965 "for %d bytes\n", i);
8966 ret = false;
8968 blob2 = base64_decode_data_blob(b64);
8969 TALLOC_FREE(b64);
8971 if (data_blob_cmp(&blob1, &blob2)) {
8972 d_fprintf(stderr, "data_blob_cmp failed for %d "
8973 "bytes\n", i);
8974 ret = false;
8976 TALLOC_FREE(blob1.data);
8977 data_blob_free(&blob2);
8979 return ret;
8982 static void parse_fn(time_t timeout, DATA_BLOB blob, void *private_data)
8984 return;
8987 static bool run_local_gencache(int dummy)
8989 char *val;
8990 time_t tm;
8991 DATA_BLOB blob;
8992 char v;
8993 struct memcache *mem;
8994 int i;
8996 mem = memcache_init(NULL, 0);
8997 if (mem == NULL) {
8998 d_printf("%s: memcache_init failed\n", __location__);
8999 return false;
9001 memcache_set_global(mem);
9003 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
9004 d_printf("%s: gencache_set() failed\n", __location__);
9005 return False;
9008 if (!gencache_get("foo", NULL, NULL, NULL)) {
9009 d_printf("%s: gencache_get() failed\n", __location__);
9010 return False;
9013 for (i=0; i<1000000; i++) {
9014 gencache_parse("foo", parse_fn, NULL);
9017 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
9018 d_printf("%s: gencache_get() failed\n", __location__);
9019 return False;
9021 TALLOC_FREE(val);
9023 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
9024 d_printf("%s: gencache_get() failed\n", __location__);
9025 return False;
9028 if (strcmp(val, "bar") != 0) {
9029 d_printf("%s: gencache_get() returned %s, expected %s\n",
9030 __location__, val, "bar");
9031 TALLOC_FREE(val);
9032 return False;
9035 TALLOC_FREE(val);
9037 if (!gencache_del("foo")) {
9038 d_printf("%s: gencache_del() failed\n", __location__);
9039 return False;
9041 if (gencache_del("foo")) {
9042 d_printf("%s: second gencache_del() succeeded\n",
9043 __location__);
9044 return False;
9047 if (gencache_get("foo", talloc_tos(), &val, &tm)) {
9048 d_printf("%s: gencache_get() on deleted entry "
9049 "succeeded\n", __location__);
9050 return False;
9053 blob = data_blob_string_const_null("bar");
9054 tm = time(NULL) + 60;
9056 if (!gencache_set_data_blob("foo", &blob, tm)) {
9057 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
9058 return False;
9061 if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
9062 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
9063 return False;
9066 if (strcmp((const char *)blob.data, "bar") != 0) {
9067 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
9068 __location__, (const char *)blob.data, "bar");
9069 data_blob_free(&blob);
9070 return False;
9073 data_blob_free(&blob);
9075 if (!gencache_del("foo")) {
9076 d_printf("%s: gencache_del() failed\n", __location__);
9077 return False;
9079 if (gencache_del("foo")) {
9080 d_printf("%s: second gencache_del() succeeded\n",
9081 __location__);
9082 return False;
9085 if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
9086 d_printf("%s: gencache_get_data_blob() on deleted entry "
9087 "succeeded\n", __location__);
9088 return False;
9091 v = 1;
9092 blob.data = (uint8_t *)&v;
9093 blob.length = sizeof(v);
9095 if (!gencache_set_data_blob("blob", &blob, tm)) {
9096 d_printf("%s: gencache_set_data_blob() failed\n",
9097 __location__);
9098 return false;
9100 if (gencache_get("blob", talloc_tos(), &val, &tm)) {
9101 d_printf("%s: gencache_get succeeded\n", __location__);
9102 return false;
9105 return True;
9108 static bool rbt_testval(struct db_context *db, const char *key,
9109 const char *value)
9111 struct db_record *rec;
9112 TDB_DATA data = string_tdb_data(value);
9113 bool ret = false;
9114 NTSTATUS status;
9115 TDB_DATA dbvalue;
9117 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
9118 if (rec == NULL) {
9119 d_fprintf(stderr, "fetch_locked failed\n");
9120 goto done;
9122 status = dbwrap_record_store(rec, data, 0);
9123 if (!NT_STATUS_IS_OK(status)) {
9124 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
9125 goto done;
9127 TALLOC_FREE(rec);
9129 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
9130 if (rec == NULL) {
9131 d_fprintf(stderr, "second fetch_locked failed\n");
9132 goto done;
9135 dbvalue = dbwrap_record_get_value(rec);
9136 if ((dbvalue.dsize != data.dsize)
9137 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
9138 d_fprintf(stderr, "Got wrong data back\n");
9139 goto done;
9142 ret = true;
9143 done:
9144 TALLOC_FREE(rec);
9145 return ret;
9148 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
9150 int *count2 = (int *)private_data;
9151 (*count2)++;
9152 return 0;
9155 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
9157 int *count2 = (int *)private_data;
9158 (*count2)++;
9159 dbwrap_record_delete(rec);
9160 return 0;
9163 static bool run_local_rbtree(int dummy)
9165 struct db_context *db;
9166 bool ret = false;
9167 int i;
9168 NTSTATUS status;
9169 int count = 0;
9170 int count2 = 0;
9172 db = db_open_rbt(NULL);
9174 if (db == NULL) {
9175 d_fprintf(stderr, "db_open_rbt failed\n");
9176 return false;
9179 for (i=0; i<1000; i++) {
9180 char *key, *value;
9182 if (asprintf(&key, "key%ld", random()) == -1) {
9183 goto done;
9185 if (asprintf(&value, "value%ld", random()) == -1) {
9186 SAFE_FREE(key);
9187 goto done;
9190 if (!rbt_testval(db, key, value)) {
9191 SAFE_FREE(key);
9192 SAFE_FREE(value);
9193 goto done;
9196 SAFE_FREE(value);
9197 if (asprintf(&value, "value%ld", random()) == -1) {
9198 SAFE_FREE(key);
9199 goto done;
9202 if (!rbt_testval(db, key, value)) {
9203 SAFE_FREE(key);
9204 SAFE_FREE(value);
9205 goto done;
9208 SAFE_FREE(key);
9209 SAFE_FREE(value);
9212 ret = true;
9213 count = 0; count2 = 0;
9214 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
9215 &count2, &count);
9216 printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
9217 if ((count != count2) || (count != 1000)) {
9218 ret = false;
9220 count = 0; count2 = 0;
9221 status = dbwrap_traverse(db, local_rbtree_traverse_delete,
9222 &count2, &count);
9223 printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
9224 if ((count != count2) || (count != 1000)) {
9225 ret = false;
9227 count = 0; count2 = 0;
9228 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
9229 &count2, &count);
9230 printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
9231 if ((count != count2) || (count != 0)) {
9232 ret = false;
9235 done:
9236 TALLOC_FREE(db);
9237 return ret;
9242 local test for character set functions
9244 This is a very simple test for the functionality in convert_string_error()
9246 static bool run_local_convert_string(int dummy)
9248 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
9249 const char *test_strings[2] = { "March", "M\303\244rz" };
9250 char dst[7];
9251 int i;
9253 for (i=0; i<2; i++) {
9254 const char *str = test_strings[i];
9255 int len = strlen(str);
9256 size_t converted_size;
9257 bool ret;
9259 memset(dst, 'X', sizeof(dst));
9261 /* first try with real source length */
9262 ret = convert_string_error(CH_UNIX, CH_UTF8,
9263 str, len,
9264 dst, sizeof(dst),
9265 &converted_size);
9266 if (ret != true) {
9267 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
9268 goto failed;
9271 if (converted_size != len) {
9272 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
9273 str, len, (int)converted_size);
9274 goto failed;
9277 if (strncmp(str, dst, converted_size) != 0) {
9278 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
9279 goto failed;
9282 if (strlen(str) != converted_size) {
9283 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
9284 (int)strlen(str), (int)converted_size);
9285 goto failed;
9288 if (dst[converted_size] != 'X') {
9289 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
9290 goto failed;
9293 /* now with srclen==-1, this causes the nul to be
9294 * converted too */
9295 ret = convert_string_error(CH_UNIX, CH_UTF8,
9296 str, -1,
9297 dst, sizeof(dst),
9298 &converted_size);
9299 if (ret != true) {
9300 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
9301 goto failed;
9304 if (converted_size != len+1) {
9305 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
9306 str, len, (int)converted_size);
9307 goto failed;
9310 if (strncmp(str, dst, converted_size) != 0) {
9311 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
9312 goto failed;
9315 if (len+1 != converted_size) {
9316 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
9317 len+1, (int)converted_size);
9318 goto failed;
9321 if (dst[converted_size] != 'X') {
9322 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
9323 goto failed;
9329 TALLOC_FREE(tmp_ctx);
9330 return true;
9331 failed:
9332 TALLOC_FREE(tmp_ctx);
9333 return false;
9337 struct talloc_dict_test {
9338 int content;
9341 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
9343 int *count = (int *)priv;
9344 *count += 1;
9345 return 0;
9348 static bool run_local_talloc_dict(int dummy)
9350 struct talloc_dict *dict;
9351 struct talloc_dict_test *t;
9352 int key, count, res;
9353 bool ok;
9355 dict = talloc_dict_init(talloc_tos());
9356 if (dict == NULL) {
9357 return false;
9360 t = talloc(talloc_tos(), struct talloc_dict_test);
9361 if (t == NULL) {
9362 return false;
9365 key = 1;
9366 t->content = 1;
9367 ok = talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), &t);
9368 if (!ok) {
9369 return false;
9372 count = 0;
9373 res = talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count);
9374 if (res == -1) {
9375 return false;
9378 if (count != 1) {
9379 return false;
9382 if (count != res) {
9383 return false;
9386 TALLOC_FREE(dict);
9388 return true;
9391 static bool run_local_string_to_sid(int dummy) {
9392 struct dom_sid sid;
9394 if (string_to_sid(&sid, "S--1-5-32-545")) {
9395 printf("allowing S--1-5-32-545\n");
9396 return false;
9398 if (string_to_sid(&sid, "S-1-5-32-+545")) {
9399 printf("allowing S-1-5-32-+545\n");
9400 return false;
9402 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")) {
9403 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
9404 return false;
9406 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
9407 printf("allowing S-1-5-32-545-abc\n");
9408 return false;
9410 if (string_to_sid(&sid, "S-300-5-32-545")) {
9411 printf("allowing S-300-5-32-545\n");
9412 return false;
9414 if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
9415 printf("allowing S-1-0xfffffffffffffe-32-545\n");
9416 return false;
9418 if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
9419 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
9420 return false;
9422 if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
9423 printf("could not parse S-1-0xfffffffffffe-32-545\n");
9424 return false;
9426 if (!string_to_sid(&sid, "S-1-5-32-545")) {
9427 printf("could not parse S-1-5-32-545\n");
9428 return false;
9430 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
9431 printf("mis-parsed S-1-5-32-545 as %s\n",
9432 sid_string_tos(&sid));
9433 return false;
9435 return true;
9438 static bool sid_to_string_test(const char *expected) {
9439 char *str;
9440 bool res = true;
9441 struct dom_sid sid;
9443 if (!string_to_sid(&sid, expected)) {
9444 printf("could not parse %s\n", expected);
9445 return false;
9448 str = dom_sid_string(NULL, &sid);
9449 if (strcmp(str, expected)) {
9450 printf("Comparison failed (%s != %s)\n", str, expected);
9451 res = false;
9453 TALLOC_FREE(str);
9454 return res;
9457 static bool run_local_sid_to_string(int dummy) {
9458 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
9459 return false;
9460 if (!sid_to_string_test("S-1-545"))
9461 return false;
9462 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
9463 return false;
9464 return true;
9467 static bool run_local_binary_to_sid(int dummy) {
9468 struct dom_sid *sid = talloc(NULL, struct dom_sid);
9469 static const uint8_t good_binary_sid[] = {
9470 0x1, /* revision number */
9471 15, /* num auths */
9472 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
9473 0x1, 0x1, 0x1, 0x1, /* auth[0] */
9474 0x1, 0x1, 0x1, 0x1, /* auth[1] */
9475 0x1, 0x1, 0x1, 0x1, /* auth[2] */
9476 0x1, 0x1, 0x1, 0x1, /* auth[3] */
9477 0x1, 0x1, 0x1, 0x1, /* auth[4] */
9478 0x1, 0x1, 0x1, 0x1, /* auth[5] */
9479 0x1, 0x1, 0x1, 0x1, /* auth[6] */
9480 0x1, 0x1, 0x1, 0x1, /* auth[7] */
9481 0x1, 0x1, 0x1, 0x1, /* auth[8] */
9482 0x1, 0x1, 0x1, 0x1, /* auth[9] */
9483 0x1, 0x1, 0x1, 0x1, /* auth[10] */
9484 0x1, 0x1, 0x1, 0x1, /* auth[11] */
9485 0x1, 0x1, 0x1, 0x1, /* auth[12] */
9486 0x1, 0x1, 0x1, 0x1, /* auth[13] */
9487 0x1, 0x1, 0x1, 0x1, /* auth[14] */
9490 static const uint8_t long_binary_sid[] = {
9491 0x1, /* revision number */
9492 15, /* num auths */
9493 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
9494 0x1, 0x1, 0x1, 0x1, /* auth[0] */
9495 0x1, 0x1, 0x1, 0x1, /* auth[1] */
9496 0x1, 0x1, 0x1, 0x1, /* auth[2] */
9497 0x1, 0x1, 0x1, 0x1, /* auth[3] */
9498 0x1, 0x1, 0x1, 0x1, /* auth[4] */
9499 0x1, 0x1, 0x1, 0x1, /* auth[5] */
9500 0x1, 0x1, 0x1, 0x1, /* auth[6] */
9501 0x1, 0x1, 0x1, 0x1, /* auth[7] */
9502 0x1, 0x1, 0x1, 0x1, /* auth[8] */
9503 0x1, 0x1, 0x1, 0x1, /* auth[9] */
9504 0x1, 0x1, 0x1, 0x1, /* auth[10] */
9505 0x1, 0x1, 0x1, 0x1, /* auth[11] */
9506 0x1, 0x1, 0x1, 0x1, /* auth[12] */
9507 0x1, 0x1, 0x1, 0x1, /* auth[13] */
9508 0x1, 0x1, 0x1, 0x1, /* auth[14] */
9509 0x1, 0x1, 0x1, 0x1, /* auth[15] */
9510 0x1, 0x1, 0x1, 0x1, /* auth[16] */
9511 0x1, 0x1, 0x1, 0x1, /* auth[17] */
9514 static const uint8_t long_binary_sid2[] = {
9515 0x1, /* revision number */
9516 32, /* num auths */
9517 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
9518 0x1, 0x1, 0x1, 0x1, /* auth[0] */
9519 0x1, 0x1, 0x1, 0x1, /* auth[1] */
9520 0x1, 0x1, 0x1, 0x1, /* auth[2] */
9521 0x1, 0x1, 0x1, 0x1, /* auth[3] */
9522 0x1, 0x1, 0x1, 0x1, /* auth[4] */
9523 0x1, 0x1, 0x1, 0x1, /* auth[5] */
9524 0x1, 0x1, 0x1, 0x1, /* auth[6] */
9525 0x1, 0x1, 0x1, 0x1, /* auth[7] */
9526 0x1, 0x1, 0x1, 0x1, /* auth[8] */
9527 0x1, 0x1, 0x1, 0x1, /* auth[9] */
9528 0x1, 0x1, 0x1, 0x1, /* auth[10] */
9529 0x1, 0x1, 0x1, 0x1, /* auth[11] */
9530 0x1, 0x1, 0x1, 0x1, /* auth[12] */
9531 0x1, 0x1, 0x1, 0x1, /* auth[13] */
9532 0x1, 0x1, 0x1, 0x1, /* auth[14] */
9533 0x1, 0x1, 0x1, 0x1, /* auth[15] */
9534 0x1, 0x1, 0x1, 0x1, /* auth[16] */
9535 0x1, 0x1, 0x1, 0x1, /* auth[17] */
9536 0x1, 0x1, 0x1, 0x1, /* auth[18] */
9537 0x1, 0x1, 0x1, 0x1, /* auth[19] */
9538 0x1, 0x1, 0x1, 0x1, /* auth[20] */
9539 0x1, 0x1, 0x1, 0x1, /* auth[21] */
9540 0x1, 0x1, 0x1, 0x1, /* auth[22] */
9541 0x1, 0x1, 0x1, 0x1, /* auth[23] */
9542 0x1, 0x1, 0x1, 0x1, /* auth[24] */
9543 0x1, 0x1, 0x1, 0x1, /* auth[25] */
9544 0x1, 0x1, 0x1, 0x1, /* auth[26] */
9545 0x1, 0x1, 0x1, 0x1, /* auth[27] */
9546 0x1, 0x1, 0x1, 0x1, /* auth[28] */
9547 0x1, 0x1, 0x1, 0x1, /* auth[29] */
9548 0x1, 0x1, 0x1, 0x1, /* auth[30] */
9549 0x1, 0x1, 0x1, 0x1, /* auth[31] */
9552 if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
9553 return false;
9555 if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
9556 return false;
9558 if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
9559 return false;
9561 return true;
9564 /* Split a path name into filename and stream name components. Canonicalise
9565 * such that an implicit $DATA token is always explicit.
9567 * The "specification" of this function can be found in the
9568 * run_local_stream_name() function in torture.c, I've tried those
9569 * combinations against a W2k3 server.
9572 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
9573 char **pbase, char **pstream)
9575 char *base = NULL;
9576 char *stream = NULL;
9577 char *sname; /* stream name */
9578 const char *stype; /* stream type */
9580 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
9582 sname = strchr_m(fname, ':');
9584 if (sname == NULL) {
9585 if (pbase != NULL) {
9586 base = talloc_strdup(mem_ctx, fname);
9587 NT_STATUS_HAVE_NO_MEMORY(base);
9589 goto done;
9592 if (pbase != NULL) {
9593 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
9594 NT_STATUS_HAVE_NO_MEMORY(base);
9597 sname += 1;
9599 stype = strchr_m(sname, ':');
9601 if (stype == NULL) {
9602 sname = talloc_strdup(mem_ctx, sname);
9603 stype = "$DATA";
9605 else {
9606 if (strcasecmp_m(stype, ":$DATA") != 0) {
9608 * If there is an explicit stream type, so far we only
9609 * allow $DATA. Is there anything else allowed? -- vl
9611 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
9612 TALLOC_FREE(base);
9613 return NT_STATUS_OBJECT_NAME_INVALID;
9615 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
9616 stype += 1;
9619 if (sname == NULL) {
9620 TALLOC_FREE(base);
9621 return NT_STATUS_NO_MEMORY;
9624 if (sname[0] == '\0') {
9626 * no stream name, so no stream
9628 goto done;
9631 if (pstream != NULL) {
9632 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
9633 if (stream == NULL) {
9634 TALLOC_FREE(sname);
9635 TALLOC_FREE(base);
9636 return NT_STATUS_NO_MEMORY;
9639 * upper-case the type field
9641 (void)strupper_m(strchr_m(stream, ':')+1);
9644 done:
9645 if (pbase != NULL) {
9646 *pbase = base;
9648 if (pstream != NULL) {
9649 *pstream = stream;
9651 return NT_STATUS_OK;
9654 static bool test_stream_name(const char *fname, const char *expected_base,
9655 const char *expected_stream,
9656 NTSTATUS expected_status)
9658 NTSTATUS status;
9659 char *base = NULL;
9660 char *stream = NULL;
9662 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
9663 if (!NT_STATUS_EQUAL(status, expected_status)) {
9664 goto error;
9667 if (!NT_STATUS_IS_OK(status)) {
9668 return true;
9671 if (base == NULL) goto error;
9673 if (strcmp(expected_base, base) != 0) goto error;
9675 if ((expected_stream != NULL) && (stream == NULL)) goto error;
9676 if ((expected_stream == NULL) && (stream != NULL)) goto error;
9678 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
9679 goto error;
9681 TALLOC_FREE(base);
9682 TALLOC_FREE(stream);
9683 return true;
9685 error:
9686 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
9687 fname, expected_base ? expected_base : "<NULL>",
9688 expected_stream ? expected_stream : "<NULL>",
9689 nt_errstr(expected_status));
9690 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
9691 base ? base : "<NULL>", stream ? stream : "<NULL>",
9692 nt_errstr(status));
9693 TALLOC_FREE(base);
9694 TALLOC_FREE(stream);
9695 return false;
9698 static bool run_local_stream_name(int dummy)
9700 bool ret = true;
9702 ret &= test_stream_name(
9703 "bla", "bla", NULL, NT_STATUS_OK);
9704 ret &= test_stream_name(
9705 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
9706 ret &= test_stream_name(
9707 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
9708 ret &= test_stream_name(
9709 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
9710 ret &= test_stream_name(
9711 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
9712 ret &= test_stream_name(
9713 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
9714 ret &= test_stream_name(
9715 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
9716 ret &= test_stream_name(
9717 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
9719 return ret;
9722 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
9724 if (a.length != b.length) {
9725 printf("a.length=%d != b.length=%d\n",
9726 (int)a.length, (int)b.length);
9727 return false;
9729 if (memcmp(a.data, b.data, a.length) != 0) {
9730 printf("a.data and b.data differ\n");
9731 return false;
9733 return true;
9736 static bool run_local_memcache(int dummy)
9738 struct memcache *cache;
9739 DATA_BLOB k1, k2;
9740 DATA_BLOB d1, d2, d3;
9741 DATA_BLOB v1, v2, v3;
9743 TALLOC_CTX *mem_ctx;
9744 char *str1, *str2;
9745 size_t size1, size2;
9746 bool ret = false;
9748 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
9750 if (cache == NULL) {
9751 printf("memcache_init failed\n");
9752 return false;
9755 d1 = data_blob_const("d1", 2);
9756 d2 = data_blob_const("d2", 2);
9757 d3 = data_blob_const("d3", 2);
9759 k1 = data_blob_const("d1", 2);
9760 k2 = data_blob_const("d2", 2);
9762 memcache_add(cache, STAT_CACHE, k1, d1);
9763 memcache_add(cache, GETWD_CACHE, k2, d2);
9765 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
9766 printf("could not find k1\n");
9767 return false;
9769 if (!data_blob_equal(d1, v1)) {
9770 return false;
9773 if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
9774 printf("could not find k2\n");
9775 return false;
9777 if (!data_blob_equal(d2, v2)) {
9778 return false;
9781 memcache_add(cache, STAT_CACHE, k1, d3);
9783 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
9784 printf("could not find replaced k1\n");
9785 return false;
9787 if (!data_blob_equal(d3, v3)) {
9788 return false;
9791 memcache_add(cache, GETWD_CACHE, k1, d1);
9793 if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
9794 printf("Did find k2, should have been purged\n");
9795 return false;
9798 TALLOC_FREE(cache);
9800 cache = memcache_init(NULL, 0);
9802 mem_ctx = talloc_init("foo");
9804 str1 = talloc_strdup(mem_ctx, "string1");
9805 str2 = talloc_strdup(mem_ctx, "string2");
9807 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
9808 data_blob_string_const("torture"), &str1);
9809 size1 = talloc_total_size(cache);
9811 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
9812 data_blob_string_const("torture"), &str2);
9813 size2 = talloc_total_size(cache);
9815 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
9817 if (size2 > size1) {
9818 printf("memcache leaks memory!\n");
9819 goto fail;
9822 ret = true;
9823 fail:
9824 TALLOC_FREE(cache);
9825 return ret;
9828 static void wbclient_done(struct tevent_req *req)
9830 wbcErr wbc_err;
9831 struct winbindd_response *wb_resp;
9832 int *i = (int *)tevent_req_callback_data_void(req);
9834 wbc_err = wb_trans_recv(req, req, &wb_resp);
9835 TALLOC_FREE(req);
9836 *i += 1;
9837 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
9840 static bool run_wbclient_multi_ping(int dummy)
9842 struct tevent_context *ev;
9843 struct wb_context **wb_ctx;
9844 struct winbindd_request wb_req;
9845 bool result = false;
9846 int i, j;
9848 BlockSignals(True, SIGPIPE);
9850 ev = tevent_context_init(talloc_tos());
9851 if (ev == NULL) {
9852 goto fail;
9855 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
9856 if (wb_ctx == NULL) {
9857 goto fail;
9860 ZERO_STRUCT(wb_req);
9861 wb_req.cmd = WINBINDD_PING;
9863 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
9865 for (i=0; i<torture_nprocs; i++) {
9866 wb_ctx[i] = wb_context_init(ev, NULL);
9867 if (wb_ctx[i] == NULL) {
9868 goto fail;
9870 for (j=0; j<torture_numops; j++) {
9871 struct tevent_req *req;
9872 req = wb_trans_send(ev, ev, wb_ctx[i],
9873 (j % 2) == 0, &wb_req);
9874 if (req == NULL) {
9875 goto fail;
9877 tevent_req_set_callback(req, wbclient_done, &i);
9881 i = 0;
9883 while (i < torture_nprocs * torture_numops) {
9884 tevent_loop_once(ev);
9887 result = true;
9888 fail:
9889 TALLOC_FREE(ev);
9890 return result;
9893 static void getaddrinfo_finished(struct tevent_req *req)
9895 char *name = (char *)tevent_req_callback_data_void(req);
9896 struct addrinfo *ainfo;
9897 int res;
9899 res = getaddrinfo_recv(req, &ainfo);
9900 if (res != 0) {
9901 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
9902 return;
9904 d_printf("gai(%s) succeeded\n", name);
9905 freeaddrinfo(ainfo);
9908 static bool run_getaddrinfo_send(int dummy)
9910 TALLOC_CTX *frame = talloc_stackframe();
9911 struct fncall_context *ctx;
9912 struct tevent_context *ev;
9913 bool result = false;
9914 const char *names[4] = { "www.samba.org", "notfound.samba.org",
9915 "www.slashdot.org", "heise.de" };
9916 struct tevent_req *reqs[4];
9917 int i;
9919 ev = samba_tevent_context_init(frame);
9920 if (ev == NULL) {
9921 goto fail;
9924 ctx = fncall_context_init(frame, 4);
9926 for (i=0; i<ARRAY_SIZE(names); i++) {
9927 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
9928 NULL);
9929 if (reqs[i] == NULL) {
9930 goto fail;
9932 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
9933 discard_const_p(void, names[i]));
9936 for (i=0; i<ARRAY_SIZE(reqs); i++) {
9937 tevent_loop_once(ev);
9940 result = true;
9941 fail:
9942 TALLOC_FREE(frame);
9943 return result;
9946 static bool dbtrans_inc(struct db_context *db)
9948 struct db_record *rec;
9949 uint32_t val;
9950 bool ret = false;
9951 NTSTATUS status;
9952 TDB_DATA value;
9954 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
9955 if (rec == NULL) {
9956 printf(__location__ "fetch_lock failed\n");
9957 return false;
9960 value = dbwrap_record_get_value(rec);
9962 if (value.dsize != sizeof(uint32_t)) {
9963 printf(__location__ "value.dsize = %d\n",
9964 (int)value.dsize);
9965 goto fail;
9968 memcpy(&val, value.dptr, sizeof(val));
9969 val += 1;
9971 status = dbwrap_record_store(
9972 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
9973 if (!NT_STATUS_IS_OK(status)) {
9974 printf(__location__ "store failed: %s\n",
9975 nt_errstr(status));
9976 goto fail;
9979 ret = true;
9980 fail:
9981 TALLOC_FREE(rec);
9982 return ret;
9985 static bool run_local_dbtrans(int dummy)
9987 struct db_context *db;
9988 struct db_record *rec;
9989 NTSTATUS status;
9990 uint32_t initial;
9991 int res;
9992 TDB_DATA value;
9994 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
9995 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
9996 DBWRAP_FLAG_NONE);
9997 if (db == NULL) {
9998 printf("Could not open transtest.db\n");
9999 return false;
10002 res = dbwrap_transaction_start(db);
10003 if (res != 0) {
10004 printf(__location__ "transaction_start failed\n");
10005 return false;
10008 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
10009 if (rec == NULL) {
10010 printf(__location__ "fetch_lock failed\n");
10011 return false;
10014 value = dbwrap_record_get_value(rec);
10016 if (value.dptr == NULL) {
10017 initial = 0;
10018 status = dbwrap_record_store(
10019 rec, make_tdb_data((uint8_t *)&initial,
10020 sizeof(initial)),
10022 if (!NT_STATUS_IS_OK(status)) {
10023 printf(__location__ "store returned %s\n",
10024 nt_errstr(status));
10025 return false;
10029 TALLOC_FREE(rec);
10031 res = dbwrap_transaction_commit(db);
10032 if (res != 0) {
10033 printf(__location__ "transaction_commit failed\n");
10034 return false;
10037 while (true) {
10038 uint32_t val, val2;
10039 int i;
10041 res = dbwrap_transaction_start(db);
10042 if (res != 0) {
10043 printf(__location__ "transaction_start failed\n");
10044 break;
10047 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
10048 if (!NT_STATUS_IS_OK(status)) {
10049 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
10050 nt_errstr(status));
10051 break;
10054 for (i=0; i<10; i++) {
10055 if (!dbtrans_inc(db)) {
10056 return false;
10060 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
10061 if (!NT_STATUS_IS_OK(status)) {
10062 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
10063 nt_errstr(status));
10064 break;
10067 if (val2 != val + 10) {
10068 printf(__location__ "val=%d, val2=%d\n",
10069 (int)val, (int)val2);
10070 break;
10073 printf("val2=%d\r", val2);
10075 res = dbwrap_transaction_commit(db);
10076 if (res != 0) {
10077 printf(__location__ "transaction_commit failed\n");
10078 break;
10082 TALLOC_FREE(db);
10083 return true;
10087 * Just a dummy test to be run under a debugger. There's no real way
10088 * to inspect the tevent_select specific function from outside of
10089 * tevent_select.c.
10092 static bool run_local_tevent_select(int dummy)
10094 struct tevent_context *ev;
10095 struct tevent_fd *fd1, *fd2;
10096 bool result = false;
10098 ev = tevent_context_init_byname(NULL, "select");
10099 if (ev == NULL) {
10100 d_fprintf(stderr, "tevent_context_init_byname failed\n");
10101 goto fail;
10104 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
10105 if (fd1 == NULL) {
10106 d_fprintf(stderr, "tevent_add_fd failed\n");
10107 goto fail;
10109 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
10110 if (fd2 == NULL) {
10111 d_fprintf(stderr, "tevent_add_fd failed\n");
10112 goto fail;
10114 TALLOC_FREE(fd2);
10116 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
10117 if (fd2 == NULL) {
10118 d_fprintf(stderr, "tevent_add_fd failed\n");
10119 goto fail;
10122 result = true;
10123 fail:
10124 TALLOC_FREE(ev);
10125 return result;
10128 static bool run_local_hex_encode_buf(int dummy)
10130 char buf[17];
10131 uint8_t src[8];
10132 int i;
10134 for (i=0; i<sizeof(src); i++) {
10135 src[i] = i;
10137 hex_encode_buf(buf, src, sizeof(src));
10138 if (strcmp(buf, "0001020304050607") != 0) {
10139 return false;
10141 hex_encode_buf(buf, NULL, 0);
10142 if (buf[0] != '\0') {
10143 return false;
10145 return true;
10148 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
10149 "0.0.0.0",
10150 "::0",
10151 "1.2.3.1",
10152 "0.0.0.0",
10153 "0.0.0.0",
10154 "1.2.3.2",
10155 "1.2.3.3",
10156 "1.2.3.4",
10157 "1.2.3.5",
10158 "::0",
10159 "1.2.3.6",
10160 "1.2.3.7",
10161 "::0",
10162 "::0",
10163 "::0",
10164 "1.2.3.8",
10165 "1.2.3.9",
10166 "1.2.3.10",
10167 "1.2.3.11",
10168 "1.2.3.12",
10169 "1.2.3.13",
10170 "1001:1111:1111:1000:0:1111:1111:1111",
10171 "1.2.3.1",
10172 "1.2.3.2",
10173 "1.2.3.3",
10174 "1.2.3.12",
10175 "::0",
10176 "::0"
10179 static const char *remove_duplicate_addrs2_test_strings_result[] = {
10180 "1.2.3.1",
10181 "1.2.3.2",
10182 "1.2.3.3",
10183 "1.2.3.4",
10184 "1.2.3.5",
10185 "1.2.3.6",
10186 "1.2.3.7",
10187 "1.2.3.8",
10188 "1.2.3.9",
10189 "1.2.3.10",
10190 "1.2.3.11",
10191 "1.2.3.12",
10192 "1.2.3.13",
10193 "1001:1111:1111:1000:0:1111:1111:1111"
10196 static bool run_local_remove_duplicate_addrs2(int dummy)
10198 struct ip_service test_vector[28];
10199 int count, i;
10201 /* Construct the sockaddr_storage test vector. */
10202 for (i = 0; i < 28; i++) {
10203 struct addrinfo hints;
10204 struct addrinfo *res = NULL;
10205 int ret;
10207 memset(&hints, '\0', sizeof(hints));
10208 hints.ai_flags = AI_NUMERICHOST;
10209 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
10210 NULL,
10211 &hints,
10212 &res);
10213 if (ret) {
10214 fprintf(stderr, "getaddrinfo failed on [%s]\n",
10215 remove_duplicate_addrs2_test_strings_vector[i]);
10216 return false;
10218 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
10219 memcpy(&test_vector[i].ss,
10220 res->ai_addr,
10221 res->ai_addrlen);
10222 freeaddrinfo(res);
10225 count = remove_duplicate_addrs2(test_vector, i);
10227 if (count != 14) {
10228 fprintf(stderr, "count wrong (%d) should be 14\n",
10229 count);
10230 return false;
10233 for (i = 0; i < count; i++) {
10234 char addr[INET6_ADDRSTRLEN];
10236 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
10238 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
10239 fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
10241 addr,
10242 remove_duplicate_addrs2_test_strings_result[i]);
10243 return false;
10247 printf("run_local_remove_duplicate_addrs2: success\n");
10248 return true;
10251 static bool run_local_tdb_opener(int dummy)
10253 TDB_CONTEXT *t;
10254 unsigned v = 0;
10256 while (1) {
10257 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
10258 O_RDWR|O_CREAT, 0755);
10259 if (t == NULL) {
10260 perror("tdb_open failed");
10261 return false;
10263 tdb_close(t);
10265 v += 1;
10266 printf("\r%u", v);
10268 return true;
10271 static bool run_local_tdb_writer(int dummy)
10273 TDB_CONTEXT *t;
10274 unsigned v = 0;
10275 TDB_DATA val;
10277 t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
10278 if (t == 0) {
10279 perror("tdb_open failed");
10280 return 1;
10283 val.dptr = (uint8_t *)&v;
10284 val.dsize = sizeof(v);
10286 while (1) {
10287 TDB_DATA data;
10288 int ret;
10290 ret = tdb_store(t, val, val, 0);
10291 if (ret != 0) {
10292 printf("%s\n", tdb_errorstr(t));
10294 v += 1;
10295 printf("\r%u", v);
10297 data = tdb_fetch(t, val);
10298 if (data.dptr != NULL) {
10299 SAFE_FREE(data.dptr);
10302 return true;
10305 static double create_procs(bool (*fn)(int), bool *result)
10307 int i, status;
10308 volatile pid_t *child_status;
10309 volatile bool *child_status_out;
10310 int synccount;
10311 int tries = 8;
10312 struct timeval start;
10314 synccount = 0;
10316 child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
10317 if (!child_status) {
10318 printf("Failed to setup shared memory\n");
10319 return -1;
10322 child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
10323 if (!child_status_out) {
10324 printf("Failed to setup result status shared memory\n");
10325 return -1;
10328 for (i = 0; i < torture_nprocs; i++) {
10329 child_status[i] = 0;
10330 child_status_out[i] = True;
10333 start = timeval_current();
10335 for (i=0;i<torture_nprocs;i++) {
10336 procnum = i;
10337 if (fork() == 0) {
10338 pid_t mypid = getpid();
10339 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
10341 slprintf(myname,sizeof(myname),"CLIENT%d", i);
10343 while (1) {
10344 if (torture_open_connection(&current_cli, i)) break;
10345 if (tries-- == 0) {
10346 printf("pid %d failed to start\n", (int)getpid());
10347 _exit(1);
10349 smb_msleep(10);
10352 child_status[i] = getpid();
10354 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
10356 child_status_out[i] = fn(i);
10357 _exit(0);
10361 do {
10362 synccount = 0;
10363 for (i=0;i<torture_nprocs;i++) {
10364 if (child_status[i]) synccount++;
10366 if (synccount == torture_nprocs) break;
10367 smb_msleep(10);
10368 } while (timeval_elapsed(&start) < 30);
10370 if (synccount != torture_nprocs) {
10371 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
10372 *result = False;
10373 return timeval_elapsed(&start);
10376 /* start the client load */
10377 start = timeval_current();
10379 for (i=0;i<torture_nprocs;i++) {
10380 child_status[i] = 0;
10383 printf("%d clients started\n", torture_nprocs);
10385 for (i=0;i<torture_nprocs;i++) {
10386 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
10389 printf("\n");
10391 for (i=0;i<torture_nprocs;i++) {
10392 if (!child_status_out[i]) {
10393 *result = False;
10396 return timeval_elapsed(&start);
10399 #define FLAG_MULTIPROC 1
10401 static struct {
10402 const char *name;
10403 bool (*fn)(int);
10404 unsigned flags;
10405 } torture_ops[] = {
10406 {"FDPASS", run_fdpasstest, 0},
10407 {"LOCK1", run_locktest1, 0},
10408 {"LOCK2", run_locktest2, 0},
10409 {"LOCK3", run_locktest3, 0},
10410 {"LOCK4", run_locktest4, 0},
10411 {"LOCK5", run_locktest5, 0},
10412 {"LOCK6", run_locktest6, 0},
10413 {"LOCK7", run_locktest7, 0},
10414 {"LOCK8", run_locktest8, 0},
10415 {"LOCK9", run_locktest9, 0},
10416 {"UNLINK", run_unlinktest, 0},
10417 {"BROWSE", run_browsetest, 0},
10418 {"ATTR", run_attrtest, 0},
10419 {"TRANS2", run_trans2test, 0},
10420 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
10421 {"TORTURE",run_torture, FLAG_MULTIPROC},
10422 {"RANDOMIPC", run_randomipc, 0},
10423 {"NEGNOWAIT", run_negprot_nowait, 0},
10424 {"NBENCH", run_nbench, 0},
10425 {"NBENCH2", run_nbench2, 0},
10426 {"OPLOCK1", run_oplock1, 0},
10427 {"OPLOCK2", run_oplock2, 0},
10428 {"OPLOCK4", run_oplock4, 0},
10429 {"DIR", run_dirtest, 0},
10430 {"DIR1", run_dirtest1, 0},
10431 {"DIR-CREATETIME", run_dir_createtime, 0},
10432 {"DENY1", torture_denytest1, 0},
10433 {"DENY2", torture_denytest2, 0},
10434 {"TCON", run_tcon_test, 0},
10435 {"TCONDEV", run_tcon_devtype_test, 0},
10436 {"RW1", run_readwritetest, 0},
10437 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
10438 {"RW3", run_readwritelarge, 0},
10439 {"RW-SIGNING", run_readwritelarge_signtest, 0},
10440 {"OPEN", run_opentest, 0},
10441 {"POSIX", run_simple_posix_open_test, 0},
10442 {"POSIX-APPEND", run_posix_append, 0},
10443 {"POSIX-SYMLINK-ACL", run_acl_symlink_test, 0},
10444 {"POSIX-SYMLINK-EA", run_ea_symlink_test, 0},
10445 {"POSIX-STREAM-DELETE", run_posix_stream_delete, 0},
10446 {"POSIX-OFD-LOCK", run_posix_ofd_lock_test, 0},
10447 {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
10448 {"ASYNC-ECHO", run_async_echo, 0},
10449 { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
10450 { "SHORTNAME-TEST", run_shortname_test, 0},
10451 { "ADDRCHANGE", run_addrchange, 0},
10452 #if 1
10453 {"OPENATTR", run_openattrtest, 0},
10454 #endif
10455 {"XCOPY", run_xcopy, 0},
10456 {"RENAME", run_rename, 0},
10457 {"DELETE", run_deletetest, 0},
10458 {"WILDDELETE", run_wild_deletetest, 0},
10459 {"DELETE-LN", run_deletetest_ln, 0},
10460 {"PROPERTIES", run_properties, 0},
10461 {"MANGLE", torture_mangle, 0},
10462 {"MANGLE1", run_mangle1, 0},
10463 {"W2K", run_w2ktest, 0},
10464 {"TRANS2SCAN", torture_trans2_scan, 0},
10465 {"NTTRANSSCAN", torture_nttrans_scan, 0},
10466 {"UTABLE", torture_utable, 0},
10467 {"CASETABLE", torture_casetable, 0},
10468 {"ERRMAPEXTRACT", run_error_map_extract, 0},
10469 {"PIPE_NUMBER", run_pipe_number, 0},
10470 {"TCON2", run_tcon2_test, 0},
10471 {"IOCTL", torture_ioctl_test, 0},
10472 {"CHKPATH", torture_chkpath_test, 0},
10473 {"FDSESS", run_fdsesstest, 0},
10474 { "EATEST", run_eatest, 0},
10475 { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
10476 { "CHAIN1", run_chain1, 0},
10477 { "CHAIN2", run_chain2, 0},
10478 { "CHAIN3", run_chain3, 0},
10479 { "WINDOWS-WRITE", run_windows_write, 0},
10480 { "LARGE_READX", run_large_readx, 0},
10481 { "NTTRANS-CREATE", run_nttrans_create, 0},
10482 { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
10483 { "CLI_ECHO", run_cli_echo, 0},
10484 { "GETADDRINFO", run_getaddrinfo_send, 0},
10485 { "TLDAP", run_tldap },
10486 { "STREAMERROR", run_streamerror },
10487 { "NOTIFY-BENCH", run_notify_bench },
10488 { "NOTIFY-BENCH2", run_notify_bench2 },
10489 { "NOTIFY-BENCH3", run_notify_bench3 },
10490 { "BAD-NBT-SESSION", run_bad_nbt_session },
10491 { "SMB-ANY-CONNECT", run_smb_any_connect },
10492 { "NOTIFY-ONLINE", run_notify_online },
10493 { "SMB2-BASIC", run_smb2_basic },
10494 { "SMB2-NEGPROT", run_smb2_negprot },
10495 { "SMB2-SESSION-RECONNECT", run_smb2_session_reconnect },
10496 { "SMB2-TCON-DEPENDENCE", run_smb2_tcon_dependence },
10497 { "SMB2-MULTI-CHANNEL", run_smb2_multi_channel },
10498 { "SMB2-SESSION-REAUTH", run_smb2_session_reauth },
10499 { "CLEANUP1", run_cleanup1 },
10500 { "CLEANUP2", run_cleanup2 },
10501 { "CLEANUP3", run_cleanup3 },
10502 { "CLEANUP4", run_cleanup4 },
10503 { "OPLOCK-CANCEL", run_oplock_cancel },
10504 { "PIDHIGH", run_pidhigh },
10505 { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
10506 { "LOCAL-GENCACHE", run_local_gencache, 0},
10507 { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
10508 { "LOCAL-DBWRAP-WATCH1", run_dbwrap_watch1, 0 },
10509 { "LOCAL-MESSAGING-READ1", run_messaging_read1, 0 },
10510 { "LOCAL-MESSAGING-READ2", run_messaging_read2, 0 },
10511 { "LOCAL-MESSAGING-READ3", run_messaging_read3, 0 },
10512 { "LOCAL-MESSAGING-READ4", run_messaging_read4, 0 },
10513 { "LOCAL-MESSAGING-FDPASS1", run_messaging_fdpass1, 0 },
10514 { "LOCAL-MESSAGING-FDPASS2", run_messaging_fdpass2, 0 },
10515 { "LOCAL-MESSAGING-FDPASS2a", run_messaging_fdpass2a, 0 },
10516 { "LOCAL-MESSAGING-FDPASS2b", run_messaging_fdpass2b, 0 },
10517 { "LOCAL-BASE64", run_local_base64, 0},
10518 { "LOCAL-RBTREE", run_local_rbtree, 0},
10519 { "LOCAL-MEMCACHE", run_local_memcache, 0},
10520 { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
10521 { "WBCLIENT-MULTI-PING", run_wbclient_multi_ping, 0},
10522 { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
10523 { "LOCAL-sid_to_string", run_local_sid_to_string, 0},
10524 { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
10525 { "LOCAL-DBTRANS", run_local_dbtrans, 0},
10526 { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
10527 { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
10528 { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
10529 { "LOCAL-sprintf_append", run_local_sprintf_append, 0},
10530 { "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0},
10531 { "LOCAL-IDMAP-TDB-COMMON", run_idmap_tdb_common_test, 0},
10532 { "LOCAL-remove_duplicate_addrs2", run_local_remove_duplicate_addrs2, 0},
10533 { "local-tdb-opener", run_local_tdb_opener, 0 },
10534 { "local-tdb-writer", run_local_tdb_writer, 0 },
10535 { "LOCAL-DBWRAP-CTDB", run_local_dbwrap_ctdb, 0 },
10536 { "LOCAL-BENCH-PTHREADPOOL", run_bench_pthreadpool, 0 },
10537 { "qpathinfo-bufsize", run_qpathinfo_bufsize, 0 },
10538 {NULL, NULL, 0}};
10541 * dummy function to satisfy linker dependency
10543 struct tevent_context *winbind_event_context(void);
10544 struct tevent_context *winbind_event_context(void)
10546 return NULL;
10549 /****************************************************************************
10550 run a specified test or "ALL"
10551 ****************************************************************************/
10552 static bool run_test(const char *name)
10554 bool ret = True;
10555 bool result = True;
10556 bool found = False;
10557 int i;
10558 double t;
10559 if (strequal(name,"ALL")) {
10560 for (i=0;torture_ops[i].name;i++) {
10561 run_test(torture_ops[i].name);
10563 found = True;
10566 for (i=0;torture_ops[i].name;i++) {
10567 fstr_sprintf(randomfname, "\\XX%x",
10568 (unsigned)random());
10570 if (strequal(name, torture_ops[i].name)) {
10571 found = True;
10572 printf("Running %s\n", name);
10573 if (torture_ops[i].flags & FLAG_MULTIPROC) {
10574 t = create_procs(torture_ops[i].fn, &result);
10575 if (!result) {
10576 ret = False;
10577 printf("TEST %s FAILED!\n", name);
10579 } else {
10580 struct timeval start;
10581 start = timeval_current();
10582 if (!torture_ops[i].fn(0)) {
10583 ret = False;
10584 printf("TEST %s FAILED!\n", name);
10586 t = timeval_elapsed(&start);
10588 printf("%s took %g secs\n\n", name, t);
10592 if (!found) {
10593 printf("Did not find a test named %s\n", name);
10594 ret = False;
10597 return ret;
10601 static void usage(void)
10603 int i;
10605 printf("WARNING samba4 test suite is much more complete nowadays.\n");
10606 printf("Please use samba4 torture.\n\n");
10608 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
10610 printf("\t-d debuglevel\n");
10611 printf("\t-U user%%pass\n");
10612 printf("\t-k use kerberos\n");
10613 printf("\t-N numprocs\n");
10614 printf("\t-n my_netbios_name\n");
10615 printf("\t-W workgroup\n");
10616 printf("\t-o num_operations\n");
10617 printf("\t-O socket_options\n");
10618 printf("\t-m maximum protocol\n");
10619 printf("\t-L use oplocks\n");
10620 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
10621 printf("\t-A showall\n");
10622 printf("\t-p port\n");
10623 printf("\t-s seed\n");
10624 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
10625 printf("\t-f filename filename to test\n");
10626 printf("\t-e encrypt\n");
10627 printf("\n\n");
10629 printf("tests are:");
10630 for (i=0;torture_ops[i].name;i++) {
10631 printf(" %s", torture_ops[i].name);
10633 printf("\n");
10635 printf("default test is ALL\n");
10637 exit(1);
10640 /****************************************************************************
10641 main program
10642 ****************************************************************************/
10643 int main(int argc,char *argv[])
10645 int opt, i;
10646 char *p;
10647 int gotuser = 0;
10648 int gotpass = 0;
10649 bool correct = True;
10650 TALLOC_CTX *frame = talloc_stackframe();
10651 int seed = time(NULL);
10653 #ifdef HAVE_SETBUFFER
10654 setbuffer(stdout, NULL, 0);
10655 #endif
10657 setup_logging("smbtorture", DEBUG_STDOUT);
10659 smb_init_locale();
10660 fault_setup();
10662 if (is_default_dyn_CONFIGFILE()) {
10663 if(getenv("SMB_CONF_PATH")) {
10664 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
10667 lp_load_global(get_dyn_CONFIGFILE());
10668 load_interfaces();
10670 if (argc < 2) {
10671 usage();
10674 for(p = argv[1]; *p; p++)
10675 if(*p == '\\')
10676 *p = '/';
10678 if (strncmp(argv[1], "//", 2)) {
10679 usage();
10682 fstrcpy(host, &argv[1][2]);
10683 p = strchr_m(&host[2],'/');
10684 if (!p) {
10685 usage();
10687 *p = 0;
10688 fstrcpy(share, p+1);
10690 fstrcpy(myname, get_myname(talloc_tos()));
10691 if (!*myname) {
10692 fprintf(stderr, "Failed to get my hostname.\n");
10693 return 1;
10696 if (*username == 0 && getenv("LOGNAME")) {
10697 fstrcpy(username,getenv("LOGNAME"));
10700 argc--;
10701 argv++;
10703 fstrcpy(workgroup, lp_workgroup());
10705 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
10706 != EOF) {
10707 switch (opt) {
10708 case 'p':
10709 port_to_use = atoi(optarg);
10710 break;
10711 case 's':
10712 seed = atoi(optarg);
10713 break;
10714 case 'W':
10715 fstrcpy(workgroup,optarg);
10716 break;
10717 case 'm':
10718 lp_set_cmdline("client max protocol", optarg);
10719 break;
10720 case 'N':
10721 torture_nprocs = atoi(optarg);
10722 break;
10723 case 'o':
10724 torture_numops = atoi(optarg);
10725 break;
10726 case 'd':
10727 lp_set_cmdline("log level", optarg);
10728 break;
10729 case 'O':
10730 sockops = optarg;
10731 break;
10732 case 'L':
10733 use_oplocks = True;
10734 break;
10735 case 'l':
10736 local_path = optarg;
10737 break;
10738 case 'A':
10739 torture_showall = True;
10740 break;
10741 case 'n':
10742 fstrcpy(myname, optarg);
10743 break;
10744 case 'c':
10745 client_txt = optarg;
10746 break;
10747 case 'e':
10748 do_encrypt = true;
10749 break;
10750 case 'k':
10751 #ifdef HAVE_KRB5
10752 use_kerberos = True;
10753 #else
10754 d_printf("No kerberos support compiled in\n");
10755 exit(1);
10756 #endif
10757 break;
10758 case 'U':
10759 gotuser = 1;
10760 fstrcpy(username,optarg);
10761 p = strchr_m(username,'%');
10762 if (p) {
10763 *p = 0;
10764 fstrcpy(password, p+1);
10765 gotpass = 1;
10767 break;
10768 case 'b':
10769 fstrcpy(multishare_conn_fname, optarg);
10770 use_multishare_conn = True;
10771 break;
10772 case 'B':
10773 torture_blocksize = atoi(optarg);
10774 break;
10775 case 'f':
10776 test_filename = SMB_STRDUP(optarg);
10777 break;
10778 default:
10779 printf("Unknown option %c (%d)\n", (char)opt, opt);
10780 usage();
10784 d_printf("using seed %d\n", seed);
10786 srandom(seed);
10788 if(use_kerberos && !gotuser) gotpass = True;
10790 while (!gotpass) {
10791 char pwd[256] = {0};
10792 int rc;
10794 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
10795 if (rc == 0) {
10796 fstrcpy(password, pwd);
10797 gotpass = 1;
10801 printf("host=%s share=%s user=%s myname=%s\n",
10802 host, share, username, myname);
10804 if (argc == optind) {
10805 correct = run_test("ALL");
10806 } else {
10807 for (i=optind;i<argc;i++) {
10808 if (!run_test(argv[i])) {
10809 correct = False;
10814 TALLOC_FREE(frame);
10816 if (correct) {
10817 return(0);
10818 } else {
10819 return(1);