Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : SMB torture tester
4 : Copyright (C) Andrew Tridgell 1997-1998
5 : Copyright (C) Jeremy Allison 2009
6 :
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.
11 :
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.
16 :
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/>.
19 : */
20 :
21 : #include "includes.h"
22 : #include "system/shmem.h"
23 : #include "libsmb/namequery.h"
24 : #include "wbc_async.h"
25 : #include "torture/proto.h"
26 : #include "libcli/security/security.h"
27 : #include "tldap.h"
28 : #include "tldap_util.h"
29 : #include "tldap_gensec_bind.h"
30 : #include "../librpc/gen_ndr/svcctl.h"
31 : #include "../lib/util/memcache.h"
32 : #include "nsswitch/winbind_client.h"
33 : #include "dbwrap/dbwrap.h"
34 : #include "dbwrap/dbwrap_open.h"
35 : #include "dbwrap/dbwrap_rbt.h"
36 : #include "async_smb.h"
37 : #include "libsmb/libsmb.h"
38 : #include "libsmb/clirap.h"
39 : #include "trans2.h"
40 : #include "libsmb/nmblib.h"
41 : #include "../lib/util/tevent_ntstatus.h"
42 : #include "util_tdb.h"
43 : #include "../libcli/smb/read_smb.h"
44 : #include "../libcli/smb/smbXcli_base.h"
45 : #include "lib/util/sys_rw_data.h"
46 : #include "lib/util/base64.h"
47 : #include "lib/util/time.h"
48 : #include "lib/gencache.h"
49 : #include "lib/util/sys_rw.h"
50 : #include "lib/util/asn1.h"
51 : #include "lib/param/param.h"
52 : #include "auth/gensec/gensec.h"
53 : #include "lib/util/string_wrappers.h"
54 : #include "source3/lib/substitute.h"
55 :
56 : #include <gnutls/gnutls.h>
57 : #include <gnutls/crypto.h>
58 :
59 : extern char *optarg;
60 : extern int optind;
61 :
62 : fstring host, workgroup, share, password, username, myname;
63 : struct cli_credentials *torture_creds;
64 : static const char *sockops="TCP_NODELAY";
65 : int torture_nprocs=1;
66 : static int port_to_use=0;
67 : int torture_numops=100;
68 : int torture_blocksize=1024*1024;
69 : static int procnum; /* records process count number when forking */
70 : static struct cli_state *current_cli;
71 : static fstring randomfname;
72 : static bool use_oplocks;
73 : static bool use_level_II_oplocks;
74 : static const char *client_txt = "client_oplocks.txt";
75 : static bool disable_spnego;
76 : static bool use_kerberos;
77 : static bool force_dos_errors;
78 : static fstring multishare_conn_fname;
79 : static bool use_multishare_conn = False;
80 : static bool do_encrypt;
81 : static const char *local_path = NULL;
82 : static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
83 : char *test_filename;
84 :
85 : bool torture_showall = False;
86 :
87 : static double create_procs(bool (*fn)(int), bool *result);
88 :
89 : /********************************************************************
90 : Ensure a connection is encrypted.
91 : ********************************************************************/
92 :
93 0 : static bool force_cli_encryption(struct cli_state *c,
94 : const char *sharename)
95 : {
96 : uint16_t major, minor;
97 : uint32_t caplow, caphigh;
98 : NTSTATUS status;
99 :
100 0 : if (!SERVER_HAS_UNIX_CIFS(c)) {
101 0 : d_printf("Encryption required and "
102 : "server that doesn't support "
103 : "UNIX extensions - failing connect\n");
104 0 : return false;
105 : }
106 :
107 0 : status = cli_unix_extensions_version(c, &major, &minor, &caplow,
108 : &caphigh);
109 0 : if (!NT_STATUS_IS_OK(status)) {
110 0 : d_printf("Encryption required and "
111 : "can't get UNIX CIFS extensions "
112 : "version from server: %s\n", nt_errstr(status));
113 0 : return false;
114 : }
115 :
116 0 : if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
117 0 : d_printf("Encryption required and "
118 : "share %s doesn't support "
119 : "encryption.\n", sharename);
120 0 : return false;
121 : }
122 :
123 0 : status = cli_smb1_setup_encryption(c, torture_creds);
124 0 : if (!NT_STATUS_IS_OK(status)) {
125 0 : d_printf("Encryption required and "
126 : "setup failed with error %s.\n",
127 : nt_errstr(status));
128 0 : return false;
129 : }
130 :
131 0 : return true;
132 : }
133 :
134 :
135 8 : static struct cli_state *open_nbt_connection(void)
136 : {
137 : struct cli_state *c;
138 : NTSTATUS status;
139 8 : int flags = 0;
140 :
141 8 : if (disable_spnego) {
142 0 : flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
143 : }
144 :
145 8 : if (use_oplocks) {
146 0 : flags |= CLI_FULL_CONNECTION_OPLOCKS;
147 : }
148 :
149 8 : if (use_level_II_oplocks) {
150 0 : flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
151 : }
152 :
153 8 : if (force_dos_errors) {
154 0 : flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
155 : }
156 :
157 8 : status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
158 : signing_state, flags, &c);
159 8 : if (!NT_STATUS_IS_OK(status)) {
160 0 : printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
161 0 : return NULL;
162 : }
163 :
164 8 : cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
165 :
166 8 : return c;
167 : }
168 :
169 : /****************************************************************************
170 : Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
171 : ****************************************************************************/
172 :
173 0 : static bool cli_bad_session_request(int fd,
174 : struct nmb_name *calling, struct nmb_name *called)
175 : {
176 : TALLOC_CTX *frame;
177 : uint8_t len_buf[4];
178 : struct iovec iov[3];
179 : ssize_t len;
180 : uint8_t *inbuf;
181 : int err;
182 0 : bool ret = false;
183 : uint8_t message_type;
184 : uint8_t error;
185 : struct tevent_context *ev;
186 : struct tevent_req *req;
187 :
188 0 : frame = talloc_stackframe();
189 :
190 0 : iov[0].iov_base = len_buf;
191 0 : iov[0].iov_len = sizeof(len_buf);
192 :
193 : /* put in the destination name */
194 :
195 0 : iov[1].iov_base = name_mangle(talloc_tos(), called->name,
196 0 : called->name_type);
197 0 : if (iov[1].iov_base == NULL) {
198 0 : goto fail;
199 : }
200 0 : iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
201 0 : talloc_get_size(iov[1].iov_base));
202 :
203 : /* and my name */
204 :
205 0 : iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
206 0 : calling->name_type);
207 0 : if (iov[2].iov_base == NULL) {
208 0 : goto fail;
209 : }
210 0 : iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
211 0 : talloc_get_size(iov[2].iov_base));
212 :
213 : /* Deliberately corrupt the name len (first byte) */
214 0 : *((uint8_t *)iov[2].iov_base) = 100;
215 :
216 : /* send a session request (RFC 1002) */
217 : /* setup the packet length
218 : * Remove four bytes from the length count, since the length
219 : * field in the NBT Session Service header counts the number
220 : * of bytes which follow. The cli_send_smb() function knows
221 : * about this and accounts for those four bytes.
222 : * CRH.
223 : */
224 :
225 0 : _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
226 0 : SCVAL(len_buf,0,0x81);
227 :
228 0 : len = write_data_iov(fd, iov, 3);
229 0 : if (len == -1) {
230 0 : goto fail;
231 : }
232 :
233 0 : ev = samba_tevent_context_init(frame);
234 0 : if (ev == NULL) {
235 0 : goto fail;
236 : }
237 0 : req = read_smb_send(frame, ev, fd);
238 0 : if (req == NULL) {
239 0 : goto fail;
240 : }
241 0 : if (!tevent_req_poll(req, ev)) {
242 0 : goto fail;
243 : }
244 0 : len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
245 0 : if (len == -1) {
246 0 : errno = err;
247 0 : goto fail;
248 : }
249 0 : TALLOC_FREE(ev);
250 :
251 0 : message_type = CVAL(inbuf, 0);
252 0 : if (message_type != 0x83) {
253 0 : d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
254 : message_type);
255 0 : goto fail;
256 : }
257 :
258 0 : if (smb_len(inbuf) != 1) {
259 0 : d_fprintf(stderr, "Expected smb_len 1, got %d\n",
260 0 : (int)smb_len(inbuf));
261 0 : goto fail;
262 : }
263 :
264 0 : error = CVAL(inbuf, 4);
265 0 : if (error != 0x82) {
266 0 : d_fprintf(stderr, "Expected error 0x82, got %d\n",
267 : (int)error);
268 0 : goto fail;
269 : }
270 :
271 0 : ret = true;
272 0 : fail:
273 0 : TALLOC_FREE(frame);
274 0 : return ret;
275 : }
276 :
277 : /* Insert a NULL at the first separator of the given path and return a pointer
278 : * to the remainder of the string.
279 : */
280 : static char *
281 0 : terminate_path_at_separator(char * path)
282 : {
283 : char * p;
284 :
285 0 : if (!path) {
286 0 : return NULL;
287 : }
288 :
289 0 : if ((p = strchr_m(path, '/'))) {
290 0 : *p = '\0';
291 0 : return p + 1;
292 : }
293 :
294 0 : if ((p = strchr_m(path, '\\'))) {
295 0 : *p = '\0';
296 0 : return p + 1;
297 : }
298 :
299 : /* No separator. */
300 0 : return NULL;
301 : }
302 :
303 : /*
304 : parse a //server/share type UNC name
305 : */
306 0 : bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
307 : char **hostname, char **sharename)
308 : {
309 : char *p;
310 :
311 0 : *hostname = *sharename = NULL;
312 :
313 0 : if (strncmp(unc_name, "\\\\", 2) &&
314 0 : strncmp(unc_name, "//", 2)) {
315 0 : return False;
316 : }
317 :
318 0 : *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
319 0 : p = terminate_path_at_separator(*hostname);
320 :
321 0 : if (p && *p) {
322 0 : *sharename = talloc_strdup(mem_ctx, p);
323 0 : terminate_path_at_separator(*sharename);
324 : }
325 :
326 0 : if (*hostname && *sharename) {
327 0 : return True;
328 : }
329 :
330 0 : TALLOC_FREE(*hostname);
331 0 : TALLOC_FREE(*sharename);
332 0 : return False;
333 : }
334 :
335 58 : static bool torture_open_connection_share(struct cli_state **c,
336 : const char *hostname,
337 : const char *sharename,
338 : int flags)
339 : {
340 : NTSTATUS status;
341 :
342 58 : status = cli_full_connection_creds(c,
343 : myname,
344 : hostname,
345 : NULL, /* dest_ss */
346 : port_to_use,
347 : sharename,
348 : "?????",
349 : torture_creds,
350 : flags);
351 58 : if (!NT_STATUS_IS_OK(status)) {
352 2 : printf("failed to open share connection: //%s/%s port:%d - %s\n",
353 : hostname, sharename, port_to_use, nt_errstr(status));
354 2 : return False;
355 : }
356 :
357 56 : cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
358 :
359 56 : if (do_encrypt) {
360 0 : return force_cli_encryption(*c,
361 : sharename);
362 : }
363 56 : return True;
364 : }
365 :
366 58 : bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
367 : {
368 58 : char **unc_list = NULL;
369 58 : int num_unc_names = 0;
370 : bool result;
371 :
372 58 : if (use_multishare_conn==True) {
373 : char *h, *s;
374 0 : unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
375 0 : if (!unc_list || num_unc_names <= 0) {
376 0 : printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
377 0 : exit(1);
378 : }
379 :
380 0 : if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
381 : NULL, &h, &s)) {
382 0 : printf("Failed to parse UNC name %s\n",
383 0 : unc_list[conn_index % num_unc_names]);
384 0 : TALLOC_FREE(unc_list);
385 0 : exit(1);
386 : }
387 :
388 0 : result = torture_open_connection_share(c, h, s, flags);
389 :
390 : /* h, s were copied earlier */
391 0 : TALLOC_FREE(unc_list);
392 0 : return result;
393 : }
394 :
395 58 : return torture_open_connection_share(c, host, share, flags);
396 : }
397 :
398 58 : bool torture_open_connection(struct cli_state **c, int conn_index)
399 : {
400 58 : int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
401 :
402 58 : if (use_oplocks) {
403 0 : flags |= CLI_FULL_CONNECTION_OPLOCKS;
404 : }
405 58 : if (use_level_II_oplocks) {
406 0 : flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
407 : }
408 :
409 58 : return torture_open_connection_flags(c, conn_index, flags);
410 : }
411 :
412 6 : bool torture_init_connection(struct cli_state **pcli)
413 : {
414 : struct cli_state *cli;
415 :
416 6 : cli = open_nbt_connection();
417 6 : if (cli == NULL) {
418 0 : return false;
419 : }
420 :
421 6 : *pcli = cli;
422 6 : return true;
423 : }
424 :
425 1 : bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
426 : {
427 1 : uint16_t old_vuid = cli_state_get_uid(cli);
428 : NTSTATUS status;
429 : bool ret;
430 :
431 1 : cli_state_set_uid(cli, 0);
432 1 : status = cli_session_setup_creds(cli, torture_creds);
433 1 : ret = NT_STATUS_IS_OK(status);
434 1 : *new_vuid = cli_state_get_uid(cli);
435 1 : cli_state_set_uid(cli, old_vuid);
436 1 : return ret;
437 : }
438 :
439 :
440 49 : bool torture_close_connection(struct cli_state *c)
441 : {
442 49 : bool ret = True;
443 : NTSTATUS status;
444 :
445 49 : status = cli_tdis(c);
446 49 : if (!NT_STATUS_IS_OK(status)) {
447 1 : printf("tdis failed (%s)\n", nt_errstr(status));
448 1 : ret = False;
449 : }
450 :
451 49 : cli_shutdown(c);
452 :
453 49 : return ret;
454 : }
455 :
456 0 : void torture_conn_set_sockopt(struct cli_state *cli)
457 : {
458 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
459 0 : }
460 :
461 6 : static NTSTATUS torture_delete_fn(struct file_info *finfo,
462 : const char *pattern,
463 : void *state)
464 : {
465 : NTSTATUS status;
466 6 : char *filename = NULL;
467 6 : char *dirname = NULL;
468 6 : char *p = NULL;
469 6 : TALLOC_CTX *frame = talloc_stackframe();
470 6 : struct cli_state *cli = (struct cli_state *)state;
471 :
472 6 : if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
473 4 : TALLOC_FREE(frame);
474 4 : return NT_STATUS_OK;
475 : }
476 :
477 2 : dirname = talloc_strdup(frame, pattern);
478 2 : if (dirname == NULL) {
479 0 : TALLOC_FREE(frame);
480 0 : return NT_STATUS_NO_MEMORY;
481 : }
482 2 : p = strrchr_m(dirname, '\\');
483 2 : if (p != NULL) {
484 : /* Remove the terminating '\' */
485 2 : *p = '\0';
486 : }
487 2 : if (dirname[0] != '\0') {
488 2 : filename = talloc_asprintf(frame,
489 : "%s\\%s",
490 : dirname,
491 : finfo->name);
492 : } else {
493 0 : filename = talloc_asprintf(frame,
494 : "%s",
495 : finfo->name);
496 : }
497 2 : if (filename == NULL) {
498 0 : TALLOC_FREE(frame);
499 0 : return NT_STATUS_NO_MEMORY;
500 : }
501 2 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
502 1 : char *subdirname = talloc_asprintf(frame,
503 : "%s\\*",
504 : filename);
505 1 : if (subdirname == NULL) {
506 0 : TALLOC_FREE(frame);
507 0 : return NT_STATUS_NO_MEMORY;
508 : }
509 1 : status = cli_list(cli,
510 : subdirname,
511 : FILE_ATTRIBUTE_DIRECTORY |
512 : FILE_ATTRIBUTE_HIDDEN |
513 : FILE_ATTRIBUTE_SYSTEM,
514 : torture_delete_fn,
515 : cli);
516 1 : if (!NT_STATUS_IS_OK(status)) {
517 0 : printf("torture_delete_fn: cli_list "
518 : "of %s failed (%s)\n",
519 : subdirname,
520 : nt_errstr(status));
521 0 : TALLOC_FREE(frame);
522 0 : return status;
523 : }
524 1 : status = cli_rmdir(cli, filename);
525 : } else {
526 1 : status = cli_unlink(cli,
527 : filename,
528 : FILE_ATTRIBUTE_SYSTEM |
529 : FILE_ATTRIBUTE_HIDDEN);
530 : }
531 2 : if (!NT_STATUS_IS_OK(status)) {
532 0 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
533 0 : printf("torture_delete_fn: cli_rmdir"
534 : " of %s failed (%s)\n",
535 : filename,
536 : nt_errstr(status));
537 : } else {
538 0 : printf("torture_delete_fn: cli_unlink"
539 : " of %s failed (%s)\n",
540 : filename,
541 : nt_errstr(status));
542 : }
543 : }
544 2 : TALLOC_FREE(frame);
545 2 : return status;
546 : }
547 :
548 2 : void torture_deltree(struct cli_state *cli, const char *dname)
549 : {
550 2 : char *mask = NULL;
551 : NTSTATUS status;
552 :
553 : /* It might be a file */
554 2 : (void)cli_unlink(cli,
555 : dname,
556 : FILE_ATTRIBUTE_SYSTEM |
557 : FILE_ATTRIBUTE_HIDDEN);
558 :
559 2 : mask = talloc_asprintf(cli,
560 : "%s\\*",
561 : dname);
562 2 : if (mask == NULL) {
563 0 : printf("torture_deltree: talloc_asprintf failed\n");
564 0 : return;
565 : }
566 :
567 2 : status = cli_list(cli,
568 : mask,
569 : FILE_ATTRIBUTE_DIRECTORY |
570 : FILE_ATTRIBUTE_HIDDEN|
571 : FILE_ATTRIBUTE_SYSTEM,
572 : torture_delete_fn,
573 : cli);
574 2 : if (!NT_STATUS_IS_OK(status)) {
575 1 : printf("torture_deltree: cli_list of %s failed (%s)\n",
576 : mask,
577 : nt_errstr(status));
578 : }
579 2 : TALLOC_FREE(mask);
580 2 : status = cli_rmdir(cli, dname);
581 2 : if (!NT_STATUS_IS_OK(status)) {
582 1 : printf("torture_deltree: cli_rmdir of %s failed (%s)\n",
583 : dname,
584 : nt_errstr(status));
585 : }
586 : }
587 :
588 : /* check if the server produced the expected dos or nt error code */
589 9 : static bool check_both_error(int line, NTSTATUS status,
590 : uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
591 : {
592 9 : if (NT_STATUS_IS_DOS(status)) {
593 : uint8_t cclass;
594 : uint32_t num;
595 :
596 : /* Check DOS error */
597 0 : cclass = NT_STATUS_DOS_CLASS(status);
598 0 : num = NT_STATUS_DOS_CODE(status);
599 :
600 0 : if (eclass != cclass || ecode != num) {
601 0 : printf("unexpected error code class=%d code=%d\n",
602 : (int)cclass, (int)num);
603 0 : printf(" expected %d/%d %s (line=%d)\n",
604 : (int)eclass, (int)ecode, nt_errstr(nterr), line);
605 0 : return false;
606 : }
607 : } else {
608 : /* Check NT error */
609 9 : if (!NT_STATUS_EQUAL(nterr, status)) {
610 0 : printf("unexpected error code %s\n",
611 : nt_errstr(status));
612 0 : printf(" expected %s (line=%d)\n",
613 : nt_errstr(nterr), line);
614 0 : return false;
615 : }
616 : }
617 :
618 9 : return true;
619 : }
620 :
621 :
622 : /* check if the server produced the expected error code */
623 6 : static bool check_error(int line, NTSTATUS status,
624 : uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
625 : {
626 6 : if (NT_STATUS_IS_DOS(status)) {
627 : uint8_t cclass;
628 : uint32_t num;
629 :
630 : /* Check DOS error */
631 :
632 0 : cclass = NT_STATUS_DOS_CLASS(status);
633 0 : num = NT_STATUS_DOS_CODE(status);
634 :
635 0 : if (eclass != cclass || ecode != num) {
636 0 : printf("unexpected error code class=%d code=%d\n",
637 : (int)cclass, (int)num);
638 0 : printf(" expected %d/%d %s (line=%d)\n",
639 : (int)eclass, (int)ecode, nt_errstr(nterr),
640 : line);
641 0 : return False;
642 : }
643 :
644 : } else {
645 : /* Check NT error */
646 :
647 6 : if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
648 1 : printf("unexpected error code %s\n",
649 : nt_errstr(status));
650 1 : printf(" expected %s (line=%d)\n", nt_errstr(nterr),
651 : line);
652 1 : return False;
653 : }
654 : }
655 :
656 5 : return True;
657 : }
658 :
659 :
660 0 : static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
661 : {
662 : NTSTATUS status;
663 :
664 0 : status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
665 :
666 0 : while (!NT_STATUS_IS_OK(status)) {
667 0 : if (!check_both_error(__LINE__, status, ERRDOS,
668 0 : ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
669 0 : return false;
670 : }
671 :
672 0 : status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
673 : }
674 :
675 0 : return true;
676 : }
677 :
678 :
679 0 : static bool rw_torture(struct cli_state *c)
680 : {
681 0 : const char *lockfname = "\\torture.lck";
682 : fstring fname;
683 : uint16_t fnum;
684 : uint16_t fnum2;
685 0 : pid_t pid2, pid = getpid();
686 : int i, j;
687 : char buf[1024];
688 0 : bool correct = True;
689 0 : size_t nread = 0;
690 : NTSTATUS status;
691 :
692 0 : memset(buf, '\0', sizeof(buf));
693 :
694 0 : status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
695 : DENY_NONE, &fnum2);
696 0 : if (!NT_STATUS_IS_OK(status)) {
697 0 : status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
698 : }
699 0 : if (!NT_STATUS_IS_OK(status)) {
700 0 : printf("open of %s failed (%s)\n",
701 : lockfname, nt_errstr(status));
702 0 : return False;
703 : }
704 :
705 0 : for (i=0;i<torture_numops;i++) {
706 0 : unsigned n = (unsigned)sys_random()%10;
707 :
708 0 : if (i % 10 == 0) {
709 0 : printf("%d\r", i); fflush(stdout);
710 : }
711 0 : slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
712 :
713 0 : if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
714 0 : return False;
715 : }
716 :
717 0 : status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
718 : DENY_ALL, &fnum);
719 0 : if (!NT_STATUS_IS_OK(status)) {
720 0 : printf("open failed (%s)\n", nt_errstr(status));
721 0 : correct = False;
722 0 : break;
723 : }
724 :
725 0 : status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
726 : sizeof(pid), NULL);
727 0 : if (!NT_STATUS_IS_OK(status)) {
728 0 : printf("write failed (%s)\n", nt_errstr(status));
729 0 : correct = False;
730 : }
731 :
732 0 : for (j=0;j<50;j++) {
733 0 : status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
734 0 : sizeof(pid)+(j*sizeof(buf)),
735 : sizeof(buf), NULL);
736 0 : if (!NT_STATUS_IS_OK(status)) {
737 0 : printf("write failed (%s)\n",
738 : nt_errstr(status));
739 0 : correct = False;
740 : }
741 : }
742 :
743 0 : pid2 = 0;
744 :
745 0 : status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
746 : &nread);
747 0 : if (!NT_STATUS_IS_OK(status)) {
748 0 : printf("read failed (%s)\n", nt_errstr(status));
749 0 : correct = false;
750 0 : } else if (nread != sizeof(pid)) {
751 0 : printf("read/write compare failed: "
752 : "recv %ld req %ld\n", (unsigned long)nread,
753 : (unsigned long)sizeof(pid));
754 0 : correct = false;
755 : }
756 :
757 0 : if (pid2 != pid) {
758 0 : printf("data corruption!\n");
759 0 : correct = False;
760 : }
761 :
762 0 : status = cli_close(c, fnum);
763 0 : if (!NT_STATUS_IS_OK(status)) {
764 0 : printf("close failed (%s)\n", nt_errstr(status));
765 0 : correct = False;
766 : }
767 :
768 0 : status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
769 0 : if (!NT_STATUS_IS_OK(status)) {
770 0 : printf("unlink failed (%s)\n", nt_errstr(status));
771 0 : correct = False;
772 : }
773 :
774 0 : status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
775 0 : if (!NT_STATUS_IS_OK(status)) {
776 0 : printf("unlock failed (%s)\n", nt_errstr(status));
777 0 : correct = False;
778 : }
779 : }
780 :
781 0 : cli_close(c, fnum2);
782 0 : cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
783 :
784 0 : printf("%d\n", i);
785 :
786 0 : return correct;
787 : }
788 :
789 0 : static bool run_torture(int dummy)
790 : {
791 : struct cli_state *cli;
792 : bool ret;
793 :
794 0 : cli = current_cli;
795 :
796 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
797 :
798 0 : ret = rw_torture(cli);
799 :
800 0 : if (!torture_close_connection(cli)) {
801 0 : ret = False;
802 : }
803 :
804 0 : return ret;
805 : }
806 :
807 0 : static bool rw_torture3(struct cli_state *c, char *lockfname)
808 : {
809 0 : uint16_t fnum = (uint16_t)-1;
810 0 : unsigned int i = 0;
811 : char buf[131072];
812 : char buf_rd[131072];
813 : unsigned count;
814 0 : unsigned countprev = 0;
815 0 : size_t sent = 0;
816 0 : bool correct = True;
817 0 : NTSTATUS status = NT_STATUS_OK;
818 :
819 0 : srandom(1);
820 0 : for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
821 : {
822 0 : SIVAL(buf, i, sys_random());
823 : }
824 :
825 0 : if (procnum == 0)
826 : {
827 0 : status = cli_unlink(
828 : c, lockfname,
829 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
830 0 : if (!NT_STATUS_IS_OK(status)) {
831 0 : printf("unlink failed (%s) (normal, this file should "
832 : "not exist)\n", nt_errstr(status));
833 : }
834 :
835 0 : status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
836 : DENY_NONE, &fnum);
837 0 : if (!NT_STATUS_IS_OK(status)) {
838 0 : printf("first open read/write of %s failed (%s)\n",
839 : lockfname, nt_errstr(status));
840 0 : return False;
841 : }
842 : }
843 : else
844 : {
845 0 : for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
846 : {
847 0 : status = cli_openx(c, lockfname, O_RDONLY,
848 : DENY_NONE, &fnum);
849 0 : if (NT_STATUS_IS_OK(status)) {
850 0 : break;
851 : }
852 0 : smb_msleep(10);
853 : }
854 0 : if (!NT_STATUS_IS_OK(status)) {
855 0 : printf("second open read-only of %s failed (%s)\n",
856 : lockfname, nt_errstr(status));
857 0 : return False;
858 : }
859 : }
860 :
861 0 : i = 0;
862 0 : for (count = 0; count < sizeof(buf); count += sent)
863 : {
864 0 : if (count >= countprev) {
865 0 : printf("%d %8d\r", i, count);
866 0 : fflush(stdout);
867 0 : i++;
868 0 : countprev += (sizeof(buf) / 20);
869 : }
870 :
871 0 : if (procnum == 0)
872 : {
873 0 : sent = ((unsigned)sys_random()%(20))+ 1;
874 0 : if (sent > sizeof(buf) - count)
875 : {
876 0 : sent = sizeof(buf) - count;
877 : }
878 :
879 0 : status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
880 : count, sent, NULL);
881 0 : if (!NT_STATUS_IS_OK(status)) {
882 0 : printf("write failed (%s)\n",
883 : nt_errstr(status));
884 0 : correct = False;
885 : }
886 : }
887 : else
888 : {
889 0 : status = cli_read(c, fnum, buf_rd+count, count,
890 : sizeof(buf)-count, &sent);
891 0 : if(!NT_STATUS_IS_OK(status)) {
892 0 : printf("read failed offset:%d size:%ld (%s)\n",
893 : count, (unsigned long)sizeof(buf)-count,
894 : nt_errstr(status));
895 0 : correct = False;
896 0 : sent = 0;
897 0 : } else if (sent > 0) {
898 0 : if (memcmp(buf_rd+count, buf+count, sent) != 0)
899 : {
900 0 : printf("read/write compare failed\n");
901 0 : printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
902 0 : correct = False;
903 0 : break;
904 : }
905 : }
906 : }
907 :
908 : }
909 :
910 0 : status = cli_close(c, fnum);
911 0 : if (!NT_STATUS_IS_OK(status)) {
912 0 : printf("close failed (%s)\n", nt_errstr(status));
913 0 : correct = False;
914 : }
915 :
916 0 : return correct;
917 : }
918 :
919 2 : static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
920 : {
921 2 : const char *lockfname = "\\torture2.lck";
922 : uint16_t fnum1;
923 : uint16_t fnum2;
924 : int i;
925 : char buf[131072];
926 : char buf_rd[131072];
927 2 : bool correct = True;
928 : size_t bytes_read;
929 : NTSTATUS status;
930 :
931 2 : status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
932 2 : if (!NT_STATUS_IS_OK(status)) {
933 2 : printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
934 : }
935 :
936 2 : status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
937 : DENY_NONE, &fnum1);
938 2 : if (!NT_STATUS_IS_OK(status)) {
939 0 : printf("first open read/write of %s failed (%s)\n",
940 : lockfname, nt_errstr(status));
941 0 : return False;
942 : }
943 :
944 2 : status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
945 2 : if (!NT_STATUS_IS_OK(status)) {
946 0 : printf("second open read-only of %s failed (%s)\n",
947 : lockfname, nt_errstr(status));
948 0 : cli_close(c1, fnum1);
949 0 : return False;
950 : }
951 :
952 202 : for (i = 0; i < torture_numops; i++)
953 : {
954 200 : size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
955 200 : if (i % 10 == 0) {
956 20 : printf("%d\r", i); fflush(stdout);
957 : }
958 :
959 200 : generate_random_buffer((unsigned char *)buf, buf_size);
960 :
961 200 : status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
962 : buf_size, NULL);
963 200 : if (!NT_STATUS_IS_OK(status)) {
964 0 : printf("write failed (%s)\n", nt_errstr(status));
965 0 : correct = False;
966 0 : break;
967 : }
968 :
969 200 : status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
970 200 : if(!NT_STATUS_IS_OK(status)) {
971 0 : printf("read failed (%s)\n", nt_errstr(status));
972 0 : correct = false;
973 0 : break;
974 200 : } else if (bytes_read != buf_size) {
975 0 : printf("read failed\n");
976 0 : printf("read %ld, expected %ld\n",
977 : (unsigned long)bytes_read,
978 : (unsigned long)buf_size);
979 0 : correct = False;
980 0 : break;
981 : }
982 :
983 200 : if (memcmp(buf_rd, buf, buf_size) != 0)
984 : {
985 0 : printf("read/write compare failed\n");
986 0 : correct = False;
987 0 : break;
988 : }
989 : }
990 :
991 2 : status = cli_close(c2, fnum2);
992 2 : if (!NT_STATUS_IS_OK(status)) {
993 0 : printf("close failed (%s)\n", nt_errstr(status));
994 0 : correct = False;
995 : }
996 :
997 2 : status = cli_close(c1, fnum1);
998 2 : if (!NT_STATUS_IS_OK(status)) {
999 0 : printf("close failed (%s)\n", nt_errstr(status));
1000 0 : correct = False;
1001 : }
1002 :
1003 2 : status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1004 2 : if (!NT_STATUS_IS_OK(status)) {
1005 0 : printf("unlink failed (%s)\n", nt_errstr(status));
1006 0 : correct = False;
1007 : }
1008 :
1009 2 : return correct;
1010 : }
1011 :
1012 1 : static bool run_readwritetest(int dummy)
1013 : {
1014 : struct cli_state *cli1, *cli2;
1015 1 : bool test1, test2 = False;
1016 :
1017 1 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1018 0 : return False;
1019 : }
1020 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
1021 1 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
1022 :
1023 1 : printf("starting readwritetest\n");
1024 :
1025 1 : test1 = rw_torture2(cli1, cli2);
1026 1 : printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
1027 :
1028 1 : if (test1) {
1029 1 : test2 = rw_torture2(cli1, cli1);
1030 1 : printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
1031 : }
1032 :
1033 1 : if (!torture_close_connection(cli1)) {
1034 0 : test1 = False;
1035 : }
1036 :
1037 1 : if (!torture_close_connection(cli2)) {
1038 0 : test2 = False;
1039 : }
1040 :
1041 1 : return (test1 && test2);
1042 : }
1043 :
1044 0 : static bool run_readwritemulti(int dummy)
1045 : {
1046 : struct cli_state *cli;
1047 : bool test;
1048 :
1049 0 : cli = current_cli;
1050 :
1051 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1052 :
1053 0 : printf("run_readwritemulti: fname %s\n", randomfname);
1054 0 : test = rw_torture3(cli, randomfname);
1055 :
1056 0 : if (!torture_close_connection(cli)) {
1057 0 : test = False;
1058 : }
1059 :
1060 0 : return test;
1061 : }
1062 :
1063 2 : static bool run_readwritelarge_internal(void)
1064 : {
1065 : static struct cli_state *cli1;
1066 : uint16_t fnum1;
1067 2 : const char *lockfname = "\\large.dat";
1068 : off_t fsize;
1069 : char buf[126*1024];
1070 2 : bool correct = True;
1071 : NTSTATUS status;
1072 :
1073 2 : if (!torture_open_connection(&cli1, 0)) {
1074 0 : return False;
1075 : }
1076 2 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
1077 2 : memset(buf,'\0',sizeof(buf));
1078 :
1079 2 : printf("starting readwritelarge_internal\n");
1080 :
1081 2 : cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1082 :
1083 2 : status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1084 : DENY_NONE, &fnum1);
1085 2 : if (!NT_STATUS_IS_OK(status)) {
1086 0 : printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1087 0 : return False;
1088 : }
1089 :
1090 2 : cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1091 :
1092 2 : status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1093 : NULL, NULL, NULL);
1094 2 : if (!NT_STATUS_IS_OK(status)) {
1095 0 : printf("qfileinfo failed (%s)\n", nt_errstr(status));
1096 0 : correct = False;
1097 : }
1098 :
1099 2 : if (fsize == sizeof(buf))
1100 2 : printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1101 : (unsigned long)fsize);
1102 : else {
1103 0 : printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1104 : (unsigned long)fsize);
1105 0 : correct = False;
1106 : }
1107 :
1108 2 : status = cli_close(cli1, fnum1);
1109 2 : if (!NT_STATUS_IS_OK(status)) {
1110 0 : printf("close failed (%s)\n", nt_errstr(status));
1111 0 : correct = False;
1112 : }
1113 :
1114 2 : status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1115 2 : if (!NT_STATUS_IS_OK(status)) {
1116 0 : printf("unlink failed (%s)\n", nt_errstr(status));
1117 0 : correct = False;
1118 : }
1119 :
1120 2 : status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1121 : DENY_NONE, &fnum1);
1122 2 : if (!NT_STATUS_IS_OK(status)) {
1123 0 : printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1124 0 : return False;
1125 : }
1126 :
1127 2 : cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1128 :
1129 2 : status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1130 : NULL, NULL, NULL);
1131 2 : if (!NT_STATUS_IS_OK(status)) {
1132 0 : printf("qfileinfo failed (%s)\n", nt_errstr(status));
1133 0 : correct = False;
1134 : }
1135 :
1136 2 : if (fsize == sizeof(buf))
1137 2 : printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1138 : (unsigned long)fsize);
1139 : else {
1140 0 : printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1141 : (unsigned long)fsize);
1142 0 : correct = False;
1143 : }
1144 :
1145 2 : status = cli_close(cli1, fnum1);
1146 2 : if (!NT_STATUS_IS_OK(status)) {
1147 0 : printf("close failed (%s)\n", nt_errstr(status));
1148 0 : correct = False;
1149 : }
1150 :
1151 2 : if (!torture_close_connection(cli1)) {
1152 0 : correct = False;
1153 : }
1154 2 : return correct;
1155 : }
1156 :
1157 1 : static bool run_readwritelarge(int dummy)
1158 : {
1159 1 : return run_readwritelarge_internal();
1160 : }
1161 :
1162 1 : static bool run_readwritelarge_signtest(int dummy)
1163 : {
1164 : bool ret;
1165 1 : signing_state = SMB_SIGNING_REQUIRED;
1166 1 : ret = run_readwritelarge_internal();
1167 1 : signing_state = SMB_SIGNING_DEFAULT;
1168 1 : return ret;
1169 : }
1170 :
1171 : int line_count = 0;
1172 : int nbio_id;
1173 :
1174 : #define ival(s) strtol(s, NULL, 0)
1175 :
1176 : /* run a test that simulates an approximate netbench client load */
1177 0 : static bool run_netbench(int client)
1178 : {
1179 : struct cli_state *cli;
1180 : int i;
1181 : char line[1024];
1182 : char cname[20];
1183 : FILE *f;
1184 : const char *params[20];
1185 0 : bool correct = True;
1186 :
1187 0 : cli = current_cli;
1188 :
1189 0 : nbio_id = client;
1190 :
1191 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1192 :
1193 0 : nb_setup(cli);
1194 :
1195 0 : slprintf(cname,sizeof(cname)-1, "client%d", client);
1196 :
1197 0 : f = fopen(client_txt, "r");
1198 :
1199 0 : if (!f) {
1200 0 : perror(client_txt);
1201 0 : return False;
1202 : }
1203 :
1204 0 : while (fgets(line, sizeof(line)-1, f)) {
1205 : char *saveptr;
1206 0 : line_count++;
1207 :
1208 0 : line[strlen(line)-1] = 0;
1209 :
1210 : /* printf("[%d] %s\n", line_count, line); */
1211 :
1212 0 : all_string_sub(line,"client1", cname, sizeof(line));
1213 :
1214 : /* parse the command parameters */
1215 0 : params[0] = strtok_r(line, " ", &saveptr);
1216 0 : i = 0;
1217 0 : while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1218 :
1219 0 : params[i] = "";
1220 :
1221 0 : if (i < 2) continue;
1222 :
1223 0 : if (!strncmp(params[0],"SMB", 3)) {
1224 0 : printf("ERROR: You are using a dbench 1 load file\n");
1225 0 : exit(1);
1226 : }
1227 :
1228 0 : if (!strcmp(params[0],"NTCreateX")) {
1229 0 : nb_createx(params[1], ival(params[2]), ival(params[3]),
1230 0 : ival(params[4]));
1231 0 : } else if (!strcmp(params[0],"Close")) {
1232 0 : nb_close(ival(params[1]));
1233 0 : } else if (!strcmp(params[0],"Rename")) {
1234 0 : nb_rename(params[1], params[2]);
1235 0 : } else if (!strcmp(params[0],"Unlink")) {
1236 0 : nb_unlink(params[1]);
1237 0 : } else if (!strcmp(params[0],"Deltree")) {
1238 0 : nb_deltree(params[1]);
1239 0 : } else if (!strcmp(params[0],"Rmdir")) {
1240 0 : nb_rmdir(params[1]);
1241 0 : } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1242 0 : nb_qpathinfo(params[1]);
1243 0 : } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1244 0 : nb_qfileinfo(ival(params[1]));
1245 0 : } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1246 0 : nb_qfsinfo(ival(params[1]));
1247 0 : } else if (!strcmp(params[0],"FIND_FIRST")) {
1248 0 : nb_findfirst(params[1]);
1249 0 : } else if (!strcmp(params[0],"WriteX")) {
1250 0 : nb_writex(ival(params[1]),
1251 0 : ival(params[2]), ival(params[3]), ival(params[4]));
1252 0 : } else if (!strcmp(params[0],"ReadX")) {
1253 0 : nb_readx(ival(params[1]),
1254 0 : ival(params[2]), ival(params[3]), ival(params[4]));
1255 0 : } else if (!strcmp(params[0],"Flush")) {
1256 0 : nb_flush(ival(params[1]));
1257 : } else {
1258 0 : printf("Unknown operation %s\n", params[0]);
1259 0 : exit(1);
1260 : }
1261 : }
1262 0 : fclose(f);
1263 :
1264 0 : nb_cleanup();
1265 :
1266 0 : if (!torture_close_connection(cli)) {
1267 0 : correct = False;
1268 : }
1269 :
1270 0 : return correct;
1271 : }
1272 :
1273 :
1274 : /* run a test that simulates an approximate netbench client load */
1275 0 : static bool run_nbench(int dummy)
1276 : {
1277 : double t;
1278 0 : bool correct = True;
1279 :
1280 0 : nbio_shmem(torture_nprocs);
1281 :
1282 0 : nbio_id = -1;
1283 :
1284 0 : signal(SIGALRM, nb_alarm);
1285 0 : alarm(1);
1286 0 : t = create_procs(run_netbench, &correct);
1287 0 : alarm(0);
1288 :
1289 0 : printf("\nThroughput %g MB/sec\n",
1290 0 : 1.0e-6 * nbio_total() / t);
1291 0 : return correct;
1292 : }
1293 :
1294 :
1295 : /*
1296 : This test checks for two things:
1297 :
1298 : 1) correct support for retaining locks over a close (ie. the server
1299 : must not use posix semantics)
1300 : 2) support for lock timeouts
1301 : */
1302 1 : static bool run_locktest1(int dummy)
1303 : {
1304 : struct cli_state *cli1, *cli2;
1305 1 : const char *fname = "\\lockt1.lck";
1306 : uint16_t fnum1, fnum2, fnum3;
1307 : time_t t1, t2;
1308 : unsigned lock_timeout;
1309 : NTSTATUS status;
1310 :
1311 1 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1312 0 : return False;
1313 : }
1314 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
1315 1 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
1316 :
1317 1 : printf("starting locktest1\n");
1318 :
1319 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1320 :
1321 1 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1322 : &fnum1);
1323 1 : if (!NT_STATUS_IS_OK(status)) {
1324 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1325 0 : return False;
1326 : }
1327 :
1328 1 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1329 1 : if (!NT_STATUS_IS_OK(status)) {
1330 0 : printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1331 0 : return False;
1332 : }
1333 :
1334 1 : status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1335 1 : if (!NT_STATUS_IS_OK(status)) {
1336 0 : printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1337 0 : return False;
1338 : }
1339 :
1340 1 : status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1341 1 : if (!NT_STATUS_IS_OK(status)) {
1342 0 : printf("lock1 failed (%s)\n", nt_errstr(status));
1343 0 : return false;
1344 : }
1345 :
1346 1 : status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1347 1 : if (NT_STATUS_IS_OK(status)) {
1348 0 : printf("lock2 succeeded! This is a locking bug\n");
1349 0 : return false;
1350 : } else {
1351 1 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1352 1 : NT_STATUS_LOCK_NOT_GRANTED)) {
1353 0 : return false;
1354 : }
1355 : }
1356 :
1357 1 : lock_timeout = (1 + (random() % 20));
1358 1 : printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1359 1 : t1 = time(NULL);
1360 1 : status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1361 1 : if (NT_STATUS_IS_OK(status)) {
1362 0 : printf("lock3 succeeded! This is a locking bug\n");
1363 0 : return false;
1364 : } else {
1365 1 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1366 1 : NT_STATUS_FILE_LOCK_CONFLICT)) {
1367 0 : return false;
1368 : }
1369 : }
1370 1 : t2 = time(NULL);
1371 :
1372 1 : if (ABS(t2 - t1) < lock_timeout-1) {
1373 0 : printf("error: This server appears not to support timed lock requests\n");
1374 : }
1375 :
1376 1 : printf("server slept for %u seconds for a %u second timeout\n",
1377 : (unsigned int)(t2-t1), lock_timeout);
1378 :
1379 1 : status = cli_close(cli1, fnum2);
1380 1 : if (!NT_STATUS_IS_OK(status)) {
1381 0 : printf("close1 failed (%s)\n", nt_errstr(status));
1382 0 : return False;
1383 : }
1384 :
1385 1 : status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1386 1 : if (NT_STATUS_IS_OK(status)) {
1387 0 : printf("lock4 succeeded! This is a locking bug\n");
1388 0 : return false;
1389 : } else {
1390 1 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1391 1 : NT_STATUS_FILE_LOCK_CONFLICT)) {
1392 0 : return false;
1393 : }
1394 : }
1395 :
1396 1 : status = cli_close(cli1, fnum1);
1397 1 : if (!NT_STATUS_IS_OK(status)) {
1398 0 : printf("close2 failed (%s)\n", nt_errstr(status));
1399 0 : return False;
1400 : }
1401 :
1402 1 : status = cli_close(cli2, fnum3);
1403 1 : if (!NT_STATUS_IS_OK(status)) {
1404 0 : printf("close3 failed (%s)\n", nt_errstr(status));
1405 0 : return False;
1406 : }
1407 :
1408 1 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1409 1 : if (!NT_STATUS_IS_OK(status)) {
1410 0 : printf("unlink failed (%s)\n", nt_errstr(status));
1411 0 : return False;
1412 : }
1413 :
1414 :
1415 1 : if (!torture_close_connection(cli1)) {
1416 0 : return False;
1417 : }
1418 :
1419 1 : if (!torture_close_connection(cli2)) {
1420 0 : return False;
1421 : }
1422 :
1423 1 : printf("Passed locktest1\n");
1424 1 : return True;
1425 : }
1426 :
1427 : /*
1428 : this checks to see if a secondary tconx can use open files from an
1429 : earlier tconx
1430 : */
1431 1 : static bool run_tcon_test(int dummy)
1432 : {
1433 : static struct cli_state *cli;
1434 1 : const char *fname = "\\tcontest.tmp";
1435 : uint16_t fnum1;
1436 : uint32_t cnum1, cnum2, cnum3;
1437 1 : struct smbXcli_tcon *orig_tcon = NULL;
1438 1 : char *orig_share = NULL;
1439 : uint16_t vuid1, vuid2;
1440 : char buf[4];
1441 1 : bool ret = True;
1442 : NTSTATUS status;
1443 :
1444 1 : memset(buf, '\0', sizeof(buf));
1445 :
1446 1 : if (!torture_open_connection(&cli, 0)) {
1447 0 : return False;
1448 : }
1449 1 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1450 :
1451 1 : printf("starting tcontest\n");
1452 :
1453 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1454 :
1455 1 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1456 1 : if (!NT_STATUS_IS_OK(status)) {
1457 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1458 0 : return False;
1459 : }
1460 :
1461 1 : cnum1 = cli_state_get_tid(cli);
1462 1 : vuid1 = cli_state_get_uid(cli);
1463 :
1464 1 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1465 1 : if (!NT_STATUS_IS_OK(status)) {
1466 0 : printf("initial write failed (%s)", nt_errstr(status));
1467 0 : return False;
1468 : }
1469 :
1470 1 : cli_state_save_tcon_share(cli, &orig_tcon, &orig_share);
1471 :
1472 1 : status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1473 1 : if (!NT_STATUS_IS_OK(status)) {
1474 0 : printf("%s refused 2nd tree connect (%s)\n", host,
1475 : nt_errstr(status));
1476 0 : cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1477 0 : cli_shutdown(cli);
1478 0 : return False;
1479 : }
1480 :
1481 1 : cnum2 = cli_state_get_tid(cli);
1482 1 : cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1483 1 : vuid2 = cli_state_get_uid(cli) + 1;
1484 :
1485 : /* try a write with the wrong tid */
1486 1 : cli_state_set_tid(cli, cnum2);
1487 :
1488 1 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1489 1 : if (NT_STATUS_IS_OK(status)) {
1490 0 : printf("* server allows write with wrong TID\n");
1491 0 : ret = False;
1492 : } else {
1493 1 : printf("server fails write with wrong TID : %s\n",
1494 : nt_errstr(status));
1495 : }
1496 :
1497 :
1498 : /* try a write with an invalid tid */
1499 1 : cli_state_set_tid(cli, cnum3);
1500 :
1501 1 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1502 1 : if (NT_STATUS_IS_OK(status)) {
1503 0 : printf("* server allows write with invalid TID\n");
1504 0 : ret = False;
1505 : } else {
1506 1 : printf("server fails write with invalid TID : %s\n",
1507 : nt_errstr(status));
1508 : }
1509 :
1510 : /* try a write with an invalid vuid */
1511 1 : cli_state_set_uid(cli, vuid2);
1512 1 : cli_state_set_tid(cli, cnum1);
1513 :
1514 1 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1515 1 : if (NT_STATUS_IS_OK(status)) {
1516 0 : printf("* server allows write with invalid VUID\n");
1517 0 : ret = False;
1518 : } else {
1519 1 : printf("server fails write with invalid VUID : %s\n",
1520 : nt_errstr(status));
1521 : }
1522 :
1523 1 : cli_state_set_tid(cli, cnum1);
1524 1 : cli_state_set_uid(cli, vuid1);
1525 :
1526 1 : status = cli_close(cli, fnum1);
1527 1 : if (!NT_STATUS_IS_OK(status)) {
1528 0 : printf("close failed (%s)\n", nt_errstr(status));
1529 0 : cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1530 0 : cli_shutdown(cli);
1531 0 : return False;
1532 : }
1533 :
1534 1 : cli_state_set_tid(cli, cnum2);
1535 :
1536 1 : status = cli_tdis(cli);
1537 1 : if (!NT_STATUS_IS_OK(status)) {
1538 0 : printf("secondary tdis failed (%s)\n", nt_errstr(status));
1539 0 : cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1540 0 : cli_shutdown(cli);
1541 0 : return False;
1542 : }
1543 :
1544 1 : cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1545 :
1546 1 : cli_state_set_tid(cli, cnum1);
1547 :
1548 1 : if (!torture_close_connection(cli)) {
1549 0 : return False;
1550 : }
1551 :
1552 1 : return ret;
1553 : }
1554 :
1555 :
1556 : /*
1557 : checks for old style tcon support
1558 : */
1559 1 : static bool run_tcon2_test(int dummy)
1560 : {
1561 : static struct cli_state *cli;
1562 : uint16_t cnum, max_xmit;
1563 : char *service;
1564 : NTSTATUS status;
1565 :
1566 1 : if (!torture_open_connection(&cli, 0)) {
1567 0 : return False;
1568 : }
1569 1 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1570 :
1571 1 : printf("starting tcon2 test\n");
1572 :
1573 1 : if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1574 0 : return false;
1575 : }
1576 :
1577 1 : status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1578 :
1579 1 : SAFE_FREE(service);
1580 :
1581 1 : if (!NT_STATUS_IS_OK(status)) {
1582 1 : printf("tcon2 failed : %s\n", nt_errstr(status));
1583 : } else {
1584 0 : printf("tcon OK : max_xmit=%d cnum=%d\n",
1585 : (int)max_xmit, (int)cnum);
1586 : }
1587 :
1588 1 : if (!torture_close_connection(cli)) {
1589 0 : return False;
1590 : }
1591 :
1592 1 : printf("Passed tcon2 test\n");
1593 1 : return True;
1594 : }
1595 :
1596 10 : static bool tcon_devtest(struct cli_state *cli,
1597 : const char *myshare, const char *devtype,
1598 : const char *return_devtype,
1599 : NTSTATUS expected_error)
1600 : {
1601 : NTSTATUS status;
1602 : bool ret;
1603 :
1604 10 : status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1605 :
1606 10 : if (NT_STATUS_IS_OK(expected_error)) {
1607 4 : if (NT_STATUS_IS_OK(status)) {
1608 8 : if (return_devtype != NULL &&
1609 4 : strequal(cli->dev, return_devtype)) {
1610 4 : ret = True;
1611 : } else {
1612 0 : printf("tconX to share %s with type %s "
1613 : "succeeded but returned the wrong "
1614 : "device type (got [%s] but should have got [%s])\n",
1615 : myshare, devtype, cli->dev, return_devtype);
1616 0 : ret = False;
1617 : }
1618 : } else {
1619 0 : printf("tconX to share %s with type %s "
1620 : "should have succeeded but failed\n",
1621 : myshare, devtype);
1622 0 : ret = False;
1623 : }
1624 4 : cli_tdis(cli);
1625 : } else {
1626 6 : if (NT_STATUS_IS_OK(status)) {
1627 0 : printf("tconx to share %s with type %s "
1628 : "should have failed but succeeded\n",
1629 : myshare, devtype);
1630 0 : ret = False;
1631 : } else {
1632 6 : if (NT_STATUS_EQUAL(status, expected_error)) {
1633 6 : ret = True;
1634 : } else {
1635 0 : printf("Returned unexpected error\n");
1636 0 : ret = False;
1637 : }
1638 : }
1639 : }
1640 10 : return ret;
1641 : }
1642 :
1643 : /*
1644 : checks for correct tconX support
1645 : */
1646 1 : static bool run_tcon_devtype_test(int dummy)
1647 : {
1648 : static struct cli_state *cli1 = NULL;
1649 1 : int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1650 : NTSTATUS status;
1651 1 : bool ret = True;
1652 :
1653 1 : status = cli_full_connection_creds(&cli1,
1654 : myname,
1655 : host,
1656 : NULL, /* dest_ss */
1657 : port_to_use,
1658 : NULL, /* service */
1659 : NULL, /* service_type */
1660 : torture_creds,
1661 : flags);
1662 :
1663 1 : if (!NT_STATUS_IS_OK(status)) {
1664 0 : printf("could not open connection\n");
1665 0 : return False;
1666 : }
1667 :
1668 1 : if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1669 0 : ret = False;
1670 :
1671 1 : if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1672 0 : ret = False;
1673 :
1674 1 : if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1675 0 : ret = False;
1676 :
1677 1 : if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1678 0 : ret = False;
1679 :
1680 1 : if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1681 0 : ret = False;
1682 :
1683 1 : if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1684 0 : ret = False;
1685 :
1686 1 : if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1687 0 : ret = False;
1688 :
1689 1 : if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1690 0 : ret = False;
1691 :
1692 1 : if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1693 0 : ret = False;
1694 :
1695 1 : if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1696 0 : ret = False;
1697 :
1698 1 : cli_shutdown(cli1);
1699 :
1700 1 : if (ret)
1701 1 : printf("Passed tcondevtest\n");
1702 :
1703 1 : return ret;
1704 : }
1705 :
1706 :
1707 : /*
1708 : This test checks that
1709 :
1710 : 1) the server supports multiple locking contexts on the one SMB
1711 : connection, distinguished by PID.
1712 :
1713 : 2) the server correctly fails overlapping locks made by the same PID (this
1714 : goes against POSIX behaviour, which is why it is tricky to implement)
1715 :
1716 : 3) the server denies unlock requests by an incorrect client PID
1717 : */
1718 1 : static bool run_locktest2(int dummy)
1719 : {
1720 : static struct cli_state *cli;
1721 1 : const char *fname = "\\lockt2.lck";
1722 : uint16_t fnum1, fnum2, fnum3;
1723 1 : bool correct = True;
1724 : NTSTATUS status;
1725 :
1726 1 : if (!torture_open_connection(&cli, 0)) {
1727 0 : return False;
1728 : }
1729 :
1730 1 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1731 :
1732 1 : printf("starting locktest2\n");
1733 :
1734 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1735 :
1736 1 : cli_setpid(cli, 1);
1737 :
1738 1 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1739 1 : if (!NT_STATUS_IS_OK(status)) {
1740 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1741 0 : return False;
1742 : }
1743 :
1744 1 : status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1745 1 : if (!NT_STATUS_IS_OK(status)) {
1746 0 : printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1747 0 : return False;
1748 : }
1749 :
1750 1 : cli_setpid(cli, 2);
1751 :
1752 1 : status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1753 1 : if (!NT_STATUS_IS_OK(status)) {
1754 0 : printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1755 0 : return False;
1756 : }
1757 :
1758 1 : cli_setpid(cli, 1);
1759 :
1760 1 : status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1761 1 : if (!NT_STATUS_IS_OK(status)) {
1762 0 : printf("lock1 failed (%s)\n", nt_errstr(status));
1763 0 : return false;
1764 : }
1765 :
1766 1 : status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1767 1 : if (NT_STATUS_IS_OK(status)) {
1768 0 : printf("WRITE lock1 succeeded! This is a locking bug\n");
1769 0 : correct = false;
1770 : } else {
1771 1 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1772 1 : NT_STATUS_LOCK_NOT_GRANTED)) {
1773 0 : return false;
1774 : }
1775 : }
1776 :
1777 1 : status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1778 1 : if (NT_STATUS_IS_OK(status)) {
1779 0 : printf("WRITE lock2 succeeded! This is a locking bug\n");
1780 0 : correct = false;
1781 : } else {
1782 1 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1783 1 : NT_STATUS_LOCK_NOT_GRANTED)) {
1784 0 : return false;
1785 : }
1786 : }
1787 :
1788 1 : status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1789 1 : if (NT_STATUS_IS_OK(status)) {
1790 0 : printf("READ lock2 succeeded! This is a locking bug\n");
1791 0 : correct = false;
1792 : } else {
1793 1 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1794 1 : NT_STATUS_FILE_LOCK_CONFLICT)) {
1795 0 : return false;
1796 : }
1797 : }
1798 :
1799 1 : status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1800 1 : if (!NT_STATUS_IS_OK(status)) {
1801 0 : printf("lock at 100 failed (%s)\n", nt_errstr(status));
1802 : }
1803 1 : cli_setpid(cli, 2);
1804 1 : if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1805 0 : printf("unlock at 100 succeeded! This is a locking bug\n");
1806 0 : correct = False;
1807 : }
1808 :
1809 1 : status = cli_unlock(cli, fnum1, 0, 4);
1810 1 : if (NT_STATUS_IS_OK(status)) {
1811 0 : printf("unlock1 succeeded! This is a locking bug\n");
1812 0 : correct = false;
1813 : } else {
1814 1 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1815 1 : NT_STATUS_RANGE_NOT_LOCKED)) {
1816 0 : return false;
1817 : }
1818 : }
1819 :
1820 1 : status = cli_unlock(cli, fnum1, 0, 8);
1821 1 : if (NT_STATUS_IS_OK(status)) {
1822 0 : printf("unlock2 succeeded! This is a locking bug\n");
1823 0 : correct = false;
1824 : } else {
1825 1 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1826 1 : NT_STATUS_RANGE_NOT_LOCKED)) {
1827 0 : return false;
1828 : }
1829 : }
1830 :
1831 1 : status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1832 1 : if (NT_STATUS_IS_OK(status)) {
1833 0 : printf("lock3 succeeded! This is a locking bug\n");
1834 0 : correct = false;
1835 : } else {
1836 1 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1837 1 : NT_STATUS_LOCK_NOT_GRANTED)) {
1838 0 : return false;
1839 : }
1840 : }
1841 :
1842 1 : cli_setpid(cli, 1);
1843 :
1844 1 : status = cli_close(cli, fnum1);
1845 1 : if (!NT_STATUS_IS_OK(status)) {
1846 0 : printf("close1 failed (%s)\n", nt_errstr(status));
1847 0 : return False;
1848 : }
1849 :
1850 1 : status = cli_close(cli, fnum2);
1851 1 : if (!NT_STATUS_IS_OK(status)) {
1852 0 : printf("close2 failed (%s)\n", nt_errstr(status));
1853 0 : return False;
1854 : }
1855 :
1856 1 : status = cli_close(cli, fnum3);
1857 1 : if (!NT_STATUS_IS_OK(status)) {
1858 0 : printf("close3 failed (%s)\n", nt_errstr(status));
1859 0 : return False;
1860 : }
1861 :
1862 1 : if (!torture_close_connection(cli)) {
1863 0 : correct = False;
1864 : }
1865 :
1866 1 : printf("locktest2 finished\n");
1867 :
1868 1 : return correct;
1869 : }
1870 :
1871 :
1872 : /*
1873 : This test checks that
1874 :
1875 : 1) the server supports the full offset range in lock requests
1876 : */
1877 1 : static bool run_locktest3(int dummy)
1878 : {
1879 : static struct cli_state *cli1, *cli2;
1880 1 : const char *fname = "\\lockt3.lck";
1881 : uint16_t fnum1, fnum2;
1882 : int i;
1883 : uint32_t offset;
1884 1 : bool correct = True;
1885 : NTSTATUS status;
1886 :
1887 : #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1888 :
1889 1 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1890 0 : return False;
1891 : }
1892 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
1893 1 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
1894 :
1895 1 : printf("starting locktest3\n");
1896 :
1897 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1898 :
1899 1 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1900 : &fnum1);
1901 1 : if (!NT_STATUS_IS_OK(status)) {
1902 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1903 0 : return False;
1904 : }
1905 :
1906 1 : status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1907 1 : if (!NT_STATUS_IS_OK(status)) {
1908 0 : printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1909 0 : return False;
1910 : }
1911 :
1912 101 : for (offset=i=0;i<torture_numops;i++) {
1913 100 : NEXT_OFFSET;
1914 :
1915 100 : status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1916 100 : if (!NT_STATUS_IS_OK(status)) {
1917 0 : printf("lock1 %d failed (%s)\n",
1918 : i,
1919 : nt_errstr(status));
1920 0 : return False;
1921 : }
1922 :
1923 100 : status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1924 100 : if (!NT_STATUS_IS_OK(status)) {
1925 0 : printf("lock2 %d failed (%s)\n",
1926 : i,
1927 : nt_errstr(status));
1928 0 : return False;
1929 : }
1930 : }
1931 :
1932 101 : for (offset=i=0;i<torture_numops;i++) {
1933 100 : NEXT_OFFSET;
1934 :
1935 100 : status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1936 100 : if (NT_STATUS_IS_OK(status)) {
1937 0 : printf("error: lock1 %d succeeded!\n", i);
1938 0 : return False;
1939 : }
1940 :
1941 100 : status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1942 100 : if (NT_STATUS_IS_OK(status)) {
1943 0 : printf("error: lock2 %d succeeded!\n", i);
1944 0 : return False;
1945 : }
1946 :
1947 100 : status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1948 100 : if (NT_STATUS_IS_OK(status)) {
1949 0 : printf("error: lock3 %d succeeded!\n", i);
1950 0 : return False;
1951 : }
1952 :
1953 100 : status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1954 100 : if (NT_STATUS_IS_OK(status)) {
1955 0 : printf("error: lock4 %d succeeded!\n", i);
1956 0 : return False;
1957 : }
1958 : }
1959 :
1960 101 : for (offset=i=0;i<torture_numops;i++) {
1961 100 : NEXT_OFFSET;
1962 :
1963 100 : status = cli_unlock(cli1, fnum1, offset-1, 1);
1964 100 : if (!NT_STATUS_IS_OK(status)) {
1965 0 : printf("unlock1 %d failed (%s)\n",
1966 : i,
1967 : nt_errstr(status));
1968 0 : return False;
1969 : }
1970 :
1971 100 : status = cli_unlock(cli2, fnum2, offset-2, 1);
1972 100 : if (!NT_STATUS_IS_OK(status)) {
1973 0 : printf("unlock2 %d failed (%s)\n",
1974 : i,
1975 : nt_errstr(status));
1976 0 : return False;
1977 : }
1978 : }
1979 :
1980 1 : status = cli_close(cli1, fnum1);
1981 1 : if (!NT_STATUS_IS_OK(status)) {
1982 0 : printf("close1 failed (%s)\n", nt_errstr(status));
1983 0 : return False;
1984 : }
1985 :
1986 1 : status = cli_close(cli2, fnum2);
1987 1 : if (!NT_STATUS_IS_OK(status)) {
1988 0 : printf("close2 failed (%s)\n", nt_errstr(status));
1989 0 : return False;
1990 : }
1991 :
1992 1 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1993 1 : if (!NT_STATUS_IS_OK(status)) {
1994 0 : printf("unlink failed (%s)\n", nt_errstr(status));
1995 0 : return False;
1996 : }
1997 :
1998 1 : if (!torture_close_connection(cli1)) {
1999 0 : correct = False;
2000 : }
2001 :
2002 1 : if (!torture_close_connection(cli2)) {
2003 0 : correct = False;
2004 : }
2005 :
2006 1 : printf("finished locktest3\n");
2007 :
2008 1 : return correct;
2009 : }
2010 :
2011 8 : static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
2012 : char *buf, off_t offset, size_t size,
2013 : size_t *nread, size_t expect)
2014 : {
2015 : NTSTATUS status;
2016 : size_t l_nread;
2017 :
2018 8 : status = cli_read(cli, fnum, buf, offset, size, &l_nread);
2019 :
2020 8 : if(!NT_STATUS_IS_OK(status)) {
2021 4 : return false;
2022 4 : } else if (l_nread != expect) {
2023 0 : return false;
2024 : }
2025 :
2026 4 : if (nread) {
2027 0 : *nread = l_nread;
2028 : }
2029 :
2030 4 : return true;
2031 : }
2032 :
2033 : #define EXPECTED(ret, v) if ((ret) != (v)) { \
2034 : printf("** "); correct = False; \
2035 : }
2036 :
2037 : /*
2038 : looks at overlapping locks
2039 : */
2040 1 : static bool run_locktest4(int dummy)
2041 : {
2042 : static struct cli_state *cli1, *cli2;
2043 1 : const char *fname = "\\lockt4.lck";
2044 : uint16_t fnum1, fnum2, f;
2045 : bool ret;
2046 : char buf[1000];
2047 1 : bool correct = True;
2048 : NTSTATUS status;
2049 :
2050 1 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2051 0 : return False;
2052 : }
2053 :
2054 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2055 1 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
2056 :
2057 1 : printf("starting locktest4\n");
2058 :
2059 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2060 :
2061 1 : cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2062 1 : cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2063 :
2064 1 : memset(buf, 0, sizeof(buf));
2065 :
2066 1 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2067 : NULL);
2068 1 : if (!NT_STATUS_IS_OK(status)) {
2069 0 : printf("Failed to create file: %s\n", nt_errstr(status));
2070 0 : correct = False;
2071 0 : goto fail;
2072 : }
2073 :
2074 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2075 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
2076 1 : EXPECTED(ret, False);
2077 1 : printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2078 :
2079 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2080 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2081 1 : EXPECTED(ret, True);
2082 1 : printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2083 :
2084 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2085 1 : NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2086 1 : EXPECTED(ret, False);
2087 1 : printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2088 :
2089 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2090 1 : NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2091 1 : EXPECTED(ret, True);
2092 1 : printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2093 :
2094 1 : ret = (cli_setpid(cli1, 1),
2095 2 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2096 1 : (cli_setpid(cli1, 2),
2097 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2098 1 : EXPECTED(ret, False);
2099 1 : printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2100 :
2101 1 : ret = (cli_setpid(cli1, 1),
2102 2 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2103 1 : (cli_setpid(cli1, 2),
2104 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2105 1 : EXPECTED(ret, True);
2106 1 : printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2107 :
2108 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2109 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2110 1 : EXPECTED(ret, True);
2111 1 : printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2112 :
2113 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2114 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2115 1 : EXPECTED(ret, False);
2116 1 : printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2117 :
2118 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2119 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2120 1 : EXPECTED(ret, False);
2121 1 : printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2122 :
2123 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2124 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2125 1 : EXPECTED(ret, True);
2126 1 : printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2127 :
2128 1 : ret = (cli_setpid(cli1, 1),
2129 2 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2130 1 : (cli_setpid(cli1, 2),
2131 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2132 1 : EXPECTED(ret, False);
2133 1 : printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2134 :
2135 1 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2136 2 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2137 1 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2138 1 : EXPECTED(ret, False);
2139 1 : printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2140 :
2141 :
2142 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2143 1 : test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2144 1 : EXPECTED(ret, False);
2145 1 : printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2146 :
2147 1 : status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2148 1 : ret = NT_STATUS_IS_OK(status);
2149 1 : if (ret) {
2150 1 : status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2151 : NULL);
2152 1 : ret = NT_STATUS_IS_OK(status);
2153 : }
2154 1 : EXPECTED(ret, False);
2155 1 : printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2156 :
2157 :
2158 1 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2159 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2160 3 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2161 1 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2162 1 : EXPECTED(ret, True);
2163 1 : printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2164 :
2165 :
2166 1 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2167 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2168 2 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2169 1 : test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2170 1 : !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2171 2 : 150, 4, NULL))) &&
2172 1 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2173 1 : EXPECTED(ret, True);
2174 1 : printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2175 :
2176 1 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2177 1 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2178 1 : NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2179 2 : 160, 4, NULL)) &&
2180 1 : test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2181 1 : EXPECTED(ret, True);
2182 1 : printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2183 :
2184 1 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2185 1 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2186 1 : NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2187 2 : 170, 4, NULL)) &&
2188 1 : test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2189 1 : EXPECTED(ret, True);
2190 1 : printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2191 :
2192 1 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2193 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2194 1 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2195 1 : !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2196 2 : 190, 4, NULL)) &&
2197 1 : test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2198 1 : EXPECTED(ret, True);
2199 1 : printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2200 :
2201 1 : cli_close(cli1, fnum1);
2202 1 : cli_close(cli2, fnum2);
2203 1 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2204 1 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2205 1 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2206 1 : NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2207 1 : NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2208 3 : NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2209 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2210 1 : cli_close(cli1, f);
2211 1 : cli_close(cli1, fnum1);
2212 1 : EXPECTED(ret, True);
2213 1 : printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2214 :
2215 1 : fail:
2216 1 : cli_close(cli1, fnum1);
2217 1 : cli_close(cli2, fnum2);
2218 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2219 1 : torture_close_connection(cli1);
2220 1 : torture_close_connection(cli2);
2221 :
2222 1 : printf("finished locktest4\n");
2223 1 : return correct;
2224 : }
2225 :
2226 : /*
2227 : looks at lock upgrade/downgrade.
2228 : */
2229 1 : static bool run_locktest5(int dummy)
2230 : {
2231 : static struct cli_state *cli1, *cli2;
2232 1 : const char *fname = "\\lockt5.lck";
2233 : uint16_t fnum1, fnum2, fnum3;
2234 : bool ret;
2235 : char buf[1000];
2236 1 : bool correct = True;
2237 : NTSTATUS status;
2238 :
2239 1 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2240 0 : return False;
2241 : }
2242 :
2243 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2244 1 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
2245 :
2246 1 : printf("starting locktest5\n");
2247 :
2248 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2249 :
2250 1 : cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2251 1 : cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2252 1 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2253 :
2254 1 : memset(buf, 0, sizeof(buf));
2255 :
2256 1 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2257 : NULL);
2258 1 : if (!NT_STATUS_IS_OK(status)) {
2259 0 : printf("Failed to create file: %s\n", nt_errstr(status));
2260 0 : correct = False;
2261 0 : goto fail;
2262 : }
2263 :
2264 : /* Check for NT bug... */
2265 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2266 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2267 1 : cli_close(cli1, fnum1);
2268 1 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2269 1 : status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2270 1 : ret = NT_STATUS_IS_OK(status);
2271 1 : EXPECTED(ret, True);
2272 1 : printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2273 1 : cli_close(cli1, fnum1);
2274 1 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2275 1 : cli_unlock(cli1, fnum3, 0, 1);
2276 :
2277 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2278 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2279 1 : EXPECTED(ret, True);
2280 1 : printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2281 :
2282 1 : status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2283 1 : ret = NT_STATUS_IS_OK(status);
2284 1 : EXPECTED(ret, False);
2285 :
2286 1 : printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2287 :
2288 : /* Unlock the process 2 lock. */
2289 1 : cli_unlock(cli2, fnum2, 0, 4);
2290 :
2291 1 : status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2292 1 : ret = NT_STATUS_IS_OK(status);
2293 1 : EXPECTED(ret, False);
2294 :
2295 1 : printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2296 :
2297 : /* Unlock the process 1 fnum3 lock. */
2298 1 : cli_unlock(cli1, fnum3, 0, 4);
2299 :
2300 : /* Stack 2 more locks here. */
2301 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2302 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2303 :
2304 1 : EXPECTED(ret, True);
2305 1 : printf("the same process %s stack read locks\n", ret?"can":"cannot");
2306 :
2307 : /* Unlock the first process lock, then check this was the WRITE lock that was
2308 : removed. */
2309 :
2310 2 : ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2311 1 : NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2312 :
2313 1 : EXPECTED(ret, True);
2314 1 : printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2315 :
2316 : /* Unlock the process 2 lock. */
2317 1 : cli_unlock(cli2, fnum2, 0, 4);
2318 :
2319 : /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2320 :
2321 1 : ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2322 2 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2323 1 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2324 :
2325 1 : EXPECTED(ret, True);
2326 1 : printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2327 :
2328 : /* Ensure the next unlock fails. */
2329 1 : ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2330 1 : EXPECTED(ret, False);
2331 1 : printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2332 :
2333 : /* Ensure connection 2 can get a write lock. */
2334 1 : status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2335 1 : ret = NT_STATUS_IS_OK(status);
2336 1 : EXPECTED(ret, True);
2337 :
2338 1 : printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2339 :
2340 :
2341 1 : fail:
2342 1 : cli_close(cli1, fnum1);
2343 1 : cli_close(cli2, fnum2);
2344 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2345 1 : if (!torture_close_connection(cli1)) {
2346 0 : correct = False;
2347 : }
2348 1 : if (!torture_close_connection(cli2)) {
2349 0 : correct = False;
2350 : }
2351 :
2352 1 : printf("finished locktest5\n");
2353 :
2354 1 : return correct;
2355 : }
2356 :
2357 : /*
2358 : tries the unusual lockingX locktype bits
2359 : */
2360 1 : static bool run_locktest6(int dummy)
2361 : {
2362 : static struct cli_state *cli;
2363 1 : const char *fname[1] = { "\\lock6.txt" };
2364 : int i;
2365 : uint16_t fnum;
2366 : NTSTATUS status;
2367 :
2368 1 : if (!torture_open_connection(&cli, 0)) {
2369 0 : return False;
2370 : }
2371 :
2372 1 : smbXcli_conn_set_sockopt(cli->conn, sockops);
2373 :
2374 1 : printf("starting locktest6\n");
2375 :
2376 2 : for (i=0;i<1;i++) {
2377 1 : printf("Testing %s\n", fname[i]);
2378 :
2379 1 : cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2380 :
2381 1 : cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2382 1 : status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2383 1 : cli_close(cli, fnum);
2384 1 : printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2385 :
2386 1 : cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2387 1 : status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2388 1 : cli_close(cli, fnum);
2389 1 : printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2390 :
2391 1 : cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2392 : }
2393 :
2394 1 : torture_close_connection(cli);
2395 :
2396 1 : printf("finished locktest6\n");
2397 1 : return True;
2398 : }
2399 :
2400 1 : static bool run_locktest7(int dummy)
2401 : {
2402 : struct cli_state *cli1;
2403 1 : const char *fname = "\\lockt7.lck";
2404 : uint16_t fnum1;
2405 : char buf[200];
2406 1 : bool correct = False;
2407 : size_t nread;
2408 : NTSTATUS status;
2409 :
2410 1 : if (!torture_open_connection(&cli1, 0)) {
2411 0 : return False;
2412 : }
2413 :
2414 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2415 :
2416 1 : printf("starting locktest7\n");
2417 :
2418 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2419 :
2420 1 : cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2421 :
2422 1 : memset(buf, 0, sizeof(buf));
2423 :
2424 1 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2425 : NULL);
2426 1 : if (!NT_STATUS_IS_OK(status)) {
2427 0 : printf("Failed to create file: %s\n", nt_errstr(status));
2428 0 : goto fail;
2429 : }
2430 :
2431 1 : cli_setpid(cli1, 1);
2432 :
2433 1 : status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2434 1 : if (!NT_STATUS_IS_OK(status)) {
2435 0 : printf("Unable to apply read lock on range 130:4, "
2436 : "error was %s\n", nt_errstr(status));
2437 0 : goto fail;
2438 : } else {
2439 1 : printf("pid1 successfully locked range 130:4 for READ\n");
2440 : }
2441 :
2442 1 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2443 1 : if (!NT_STATUS_IS_OK(status)) {
2444 0 : printf("pid1 unable to read the range 130:4, error was %s\n",
2445 : nt_errstr(status));
2446 0 : goto fail;
2447 1 : } else if (nread != 4) {
2448 0 : printf("pid1 unable to read the range 130:4, "
2449 : "recv %ld req %d\n", (unsigned long)nread, 4);
2450 0 : goto fail;
2451 : } else {
2452 1 : printf("pid1 successfully read the range 130:4\n");
2453 : }
2454 :
2455 1 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2456 1 : if (!NT_STATUS_IS_OK(status)) {
2457 1 : printf("pid1 unable to write to the range 130:4, error was "
2458 : "%s\n", nt_errstr(status));
2459 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2460 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2461 0 : goto fail;
2462 : }
2463 : } else {
2464 0 : printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2465 0 : goto fail;
2466 : }
2467 :
2468 1 : cli_setpid(cli1, 2);
2469 :
2470 1 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2471 1 : if (!NT_STATUS_IS_OK(status)) {
2472 0 : printf("pid2 unable to read the range 130:4, error was %s\n",
2473 : nt_errstr(status));
2474 0 : goto fail;
2475 1 : } else if (nread != 4) {
2476 0 : printf("pid2 unable to read the range 130:4, "
2477 : "recv %ld req %d\n", (unsigned long)nread, 4);
2478 0 : goto fail;
2479 : } else {
2480 1 : printf("pid2 successfully read the range 130:4\n");
2481 : }
2482 :
2483 1 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2484 1 : if (!NT_STATUS_IS_OK(status)) {
2485 1 : printf("pid2 unable to write to the range 130:4, error was "
2486 : "%s\n", nt_errstr(status));
2487 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2488 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2489 0 : goto fail;
2490 : }
2491 : } else {
2492 0 : printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2493 0 : goto fail;
2494 : }
2495 :
2496 1 : cli_setpid(cli1, 1);
2497 1 : cli_unlock(cli1, fnum1, 130, 4);
2498 :
2499 1 : status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2500 1 : if (!NT_STATUS_IS_OK(status)) {
2501 0 : printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2502 0 : goto fail;
2503 : } else {
2504 1 : printf("pid1 successfully locked range 130:4 for WRITE\n");
2505 : }
2506 :
2507 1 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2508 1 : if (!NT_STATUS_IS_OK(status)) {
2509 0 : printf("pid1 unable to read the range 130:4, error was %s\n",
2510 : nt_errstr(status));
2511 0 : goto fail;
2512 1 : } else if (nread != 4) {
2513 0 : printf("pid1 unable to read the range 130:4, "
2514 : "recv %ld req %d\n", (unsigned long)nread, 4);
2515 0 : goto fail;
2516 : } else {
2517 1 : printf("pid1 successfully read the range 130:4\n");
2518 : }
2519 :
2520 1 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2521 1 : if (!NT_STATUS_IS_OK(status)) {
2522 0 : printf("pid1 unable to write to the range 130:4, error was "
2523 : "%s\n", nt_errstr(status));
2524 0 : goto fail;
2525 : } else {
2526 1 : printf("pid1 successfully wrote to the range 130:4\n");
2527 : }
2528 :
2529 1 : cli_setpid(cli1, 2);
2530 :
2531 1 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2532 1 : if (!NT_STATUS_IS_OK(status)) {
2533 1 : printf("pid2 unable to read the range 130:4, error was "
2534 : "%s\n", nt_errstr(status));
2535 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2536 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2537 0 : goto fail;
2538 : }
2539 : } else {
2540 0 : printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2541 : (unsigned long)nread);
2542 0 : goto fail;
2543 : }
2544 :
2545 1 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2546 1 : if (!NT_STATUS_IS_OK(status)) {
2547 1 : printf("pid2 unable to write to the range 130:4, error was "
2548 : "%s\n", nt_errstr(status));
2549 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2550 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2551 0 : goto fail;
2552 : }
2553 : } else {
2554 0 : printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2555 0 : goto fail;
2556 : }
2557 :
2558 1 : cli_unlock(cli1, fnum1, 130, 0);
2559 1 : correct = True;
2560 :
2561 1 : fail:
2562 1 : cli_close(cli1, fnum1);
2563 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2564 1 : torture_close_connection(cli1);
2565 :
2566 1 : printf("finished locktest7\n");
2567 1 : return correct;
2568 : }
2569 :
2570 : /*
2571 : * This demonstrates a problem with our use of GPFS share modes: A file
2572 : * descriptor sitting in the pending close queue holding a GPFS share mode
2573 : * blocks opening a file another time. Happens with Word 2007 temp files.
2574 : * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2575 : * open is denied with NT_STATUS_SHARING_VIOLATION.
2576 : */
2577 :
2578 0 : static bool run_locktest8(int dummy)
2579 : {
2580 : struct cli_state *cli1;
2581 0 : const char *fname = "\\lockt8.lck";
2582 : uint16_t fnum1, fnum2;
2583 : char buf[200];
2584 0 : bool correct = False;
2585 : NTSTATUS status;
2586 :
2587 0 : if (!torture_open_connection(&cli1, 0)) {
2588 0 : return False;
2589 : }
2590 :
2591 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2592 :
2593 0 : printf("starting locktest8\n");
2594 :
2595 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2596 :
2597 0 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2598 : &fnum1);
2599 0 : if (!NT_STATUS_IS_OK(status)) {
2600 0 : d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2601 0 : return false;
2602 : }
2603 :
2604 0 : memset(buf, 0, sizeof(buf));
2605 :
2606 0 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2607 0 : if (!NT_STATUS_IS_OK(status)) {
2608 0 : d_fprintf(stderr, "cli_openx second time returned %s\n",
2609 : nt_errstr(status));
2610 0 : goto fail;
2611 : }
2612 :
2613 0 : status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2614 0 : if (!NT_STATUS_IS_OK(status)) {
2615 0 : printf("Unable to apply read lock on range 1:1, error was "
2616 : "%s\n", nt_errstr(status));
2617 0 : goto fail;
2618 : }
2619 :
2620 0 : status = cli_close(cli1, fnum1);
2621 0 : if (!NT_STATUS_IS_OK(status)) {
2622 0 : d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2623 0 : goto fail;
2624 : }
2625 :
2626 0 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2627 0 : if (!NT_STATUS_IS_OK(status)) {
2628 0 : d_fprintf(stderr, "cli_openx third time returned %s\n",
2629 : nt_errstr(status));
2630 0 : goto fail;
2631 : }
2632 :
2633 0 : correct = true;
2634 :
2635 0 : fail:
2636 0 : cli_close(cli1, fnum1);
2637 0 : cli_close(cli1, fnum2);
2638 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2639 0 : torture_close_connection(cli1);
2640 :
2641 0 : printf("finished locktest8\n");
2642 0 : return correct;
2643 : }
2644 :
2645 : /*
2646 : * This test is designed to be run in conjunction with
2647 : * external NFS or POSIX locks taken in the filesystem.
2648 : * It checks that the smbd server will block until the
2649 : * lock is released and then acquire it. JRA.
2650 : */
2651 :
2652 : static bool got_alarm;
2653 : static struct cli_state *alarm_cli;
2654 :
2655 0 : static void alarm_handler(int dummy)
2656 : {
2657 0 : got_alarm = True;
2658 0 : }
2659 :
2660 0 : static void alarm_handler_parent(int dummy)
2661 : {
2662 0 : smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2663 0 : }
2664 :
2665 0 : static void do_local_lock(const char *fname, int read_fd, int write_fd)
2666 : {
2667 : int fd;
2668 0 : char c = '\0';
2669 : struct flock lock;
2670 0 : const char *local_pathname = NULL;
2671 : int ret;
2672 :
2673 0 : local_pathname = talloc_asprintf(talloc_tos(),
2674 : "%s/%s", local_path, fname);
2675 0 : if (!local_pathname) {
2676 0 : printf("child: alloc fail\n");
2677 0 : exit(1);
2678 : }
2679 :
2680 0 : unlink(local_pathname);
2681 0 : fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2682 0 : if (fd == -1) {
2683 0 : printf("child: open of %s failed %s.\n",
2684 0 : local_pathname, strerror(errno));
2685 0 : exit(1);
2686 : }
2687 :
2688 : /* Now take a fcntl lock. */
2689 0 : lock.l_type = F_WRLCK;
2690 0 : lock.l_whence = SEEK_SET;
2691 0 : lock.l_start = 0;
2692 0 : lock.l_len = 4;
2693 0 : lock.l_pid = getpid();
2694 :
2695 0 : ret = fcntl(fd,F_SETLK,&lock);
2696 0 : if (ret == -1) {
2697 0 : printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2698 0 : local_pathname, strerror(errno));
2699 0 : exit(1);
2700 : } else {
2701 0 : printf("child: got lock 0:4 on file %s.\n",
2702 : local_pathname );
2703 0 : fflush(stdout);
2704 : }
2705 :
2706 0 : CatchSignal(SIGALRM, alarm_handler);
2707 0 : alarm(5);
2708 : /* Signal the parent. */
2709 0 : if (write(write_fd, &c, 1) != 1) {
2710 0 : printf("child: start signal fail %s.\n",
2711 0 : strerror(errno));
2712 0 : exit(1);
2713 : }
2714 0 : alarm(0);
2715 :
2716 0 : alarm(10);
2717 : /* Wait for the parent to be ready. */
2718 0 : if (read(read_fd, &c, 1) != 1) {
2719 0 : printf("child: reply signal fail %s.\n",
2720 0 : strerror(errno));
2721 0 : exit(1);
2722 : }
2723 0 : alarm(0);
2724 :
2725 0 : sleep(5);
2726 0 : close(fd);
2727 0 : printf("child: released lock 0:4 on file %s.\n",
2728 : local_pathname );
2729 0 : fflush(stdout);
2730 0 : exit(0);
2731 : }
2732 :
2733 0 : static bool _run_locktest9X(const char *fname, int timeout)
2734 : {
2735 : struct cli_state *cli1;
2736 0 : char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2737 : uint16_t fnum;
2738 0 : bool correct = False;
2739 : int pipe_in[2], pipe_out[2];
2740 : pid_t child_pid;
2741 0 : char c = '\0';
2742 : int ret;
2743 : struct timeval start;
2744 : double seconds;
2745 : NTSTATUS status;
2746 :
2747 0 : printf("starting locktest9X: %s\n", fname);
2748 :
2749 0 : if (local_path == NULL) {
2750 0 : d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2751 0 : return false;
2752 : }
2753 :
2754 0 : if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2755 0 : return false;
2756 : }
2757 :
2758 0 : child_pid = fork();
2759 0 : if (child_pid == -1) {
2760 0 : return false;
2761 : }
2762 :
2763 0 : if (child_pid == 0) {
2764 : /* Child. */
2765 0 : do_local_lock(fname, pipe_out[0], pipe_in[1]);
2766 0 : exit(0);
2767 : }
2768 :
2769 0 : close(pipe_out[0]);
2770 0 : close(pipe_in[1]);
2771 0 : pipe_out[0] = -1;
2772 0 : pipe_in[1] = -1;
2773 :
2774 : /* Parent. */
2775 0 : ret = read(pipe_in[0], &c, 1);
2776 0 : if (ret != 1) {
2777 0 : d_fprintf(stderr, "failed to read start signal from child. %s\n",
2778 0 : strerror(errno));
2779 0 : return false;
2780 : }
2781 :
2782 0 : if (!torture_open_connection(&cli1, 0)) {
2783 0 : return false;
2784 : }
2785 :
2786 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2787 :
2788 0 : status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2789 : &fnum);
2790 0 : if (!NT_STATUS_IS_OK(status)) {
2791 0 : d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2792 0 : return false;
2793 : }
2794 :
2795 : /* Ensure the child has the lock. */
2796 0 : status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2797 0 : if (NT_STATUS_IS_OK(status)) {
2798 0 : d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2799 0 : goto fail;
2800 : } else {
2801 0 : d_printf("Child has the lock.\n");
2802 : }
2803 :
2804 : /* Tell the child to wait 5 seconds then exit. */
2805 0 : ret = write(pipe_out[1], &c, 1);
2806 0 : if (ret != 1) {
2807 0 : d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2808 0 : strerror(errno));
2809 0 : goto fail;
2810 : }
2811 :
2812 : /* Wait 20 seconds for the lock. */
2813 0 : alarm_cli = cli1;
2814 0 : CatchSignal(SIGALRM, alarm_handler_parent);
2815 0 : alarm(20);
2816 :
2817 0 : start = timeval_current();
2818 :
2819 0 : status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2820 0 : if (!NT_STATUS_IS_OK(status)) {
2821 0 : d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2822 : "%s\n", nt_errstr(status));
2823 0 : goto fail_nofd;
2824 : }
2825 0 : alarm(0);
2826 :
2827 0 : seconds = timeval_elapsed(&start);
2828 :
2829 0 : printf("Parent got the lock after %.2f seconds.\n",
2830 : seconds);
2831 :
2832 0 : status = cli_close(cli1, fnum);
2833 0 : if (!NT_STATUS_IS_OK(status)) {
2834 0 : d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2835 0 : goto fail;
2836 : }
2837 :
2838 0 : correct = true;
2839 :
2840 0 : fail:
2841 0 : cli_close(cli1, fnum);
2842 0 : torture_close_connection(cli1);
2843 :
2844 0 : fail_nofd:
2845 :
2846 0 : printf("finished locktest9X: %s\n", fname);
2847 0 : return correct;
2848 : }
2849 :
2850 0 : static bool run_locktest9a(int dummy)
2851 : {
2852 0 : return _run_locktest9X("lock9a.dat", -1);
2853 : }
2854 :
2855 0 : static bool run_locktest9b(int dummy)
2856 : {
2857 0 : return _run_locktest9X("lock9b.dat", 10000);
2858 : }
2859 :
2860 : struct locktest10_state {
2861 : bool ok;
2862 : bool done;
2863 : };
2864 :
2865 : static void locktest10_lockingx_done(struct tevent_req *subreq);
2866 : static void locktest10_read_andx_done(struct tevent_req *subreq);
2867 :
2868 1 : static bool run_locktest10(int dummy)
2869 : {
2870 1 : struct tevent_context *ev = NULL;
2871 1 : struct cli_state *cli1 = NULL;
2872 1 : struct cli_state *cli2 = NULL;
2873 1 : struct smb1_lock_element lck = { 0 };
2874 1 : struct tevent_req *reqs[2] = { NULL };
2875 1 : struct tevent_req *smbreqs[2] = { NULL };
2876 1 : const char fname[] = "\\lockt10.lck";
2877 : uint16_t fnum1, fnum2;
2878 1 : bool ret = false;
2879 : bool ok;
2880 1 : uint8_t data = 1;
2881 1 : struct locktest10_state state = { .ok = true };
2882 : NTSTATUS status;
2883 :
2884 1 : printf("starting locktest10\n");
2885 :
2886 1 : ev = samba_tevent_context_init(NULL);
2887 1 : if (ev == NULL) {
2888 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
2889 0 : goto done;
2890 : }
2891 :
2892 1 : ok = torture_open_connection(&cli1, 0);
2893 1 : if (!ok) {
2894 0 : goto done;
2895 : }
2896 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2897 :
2898 1 : ok = torture_open_connection(&cli2, 1);
2899 1 : if (!ok) {
2900 0 : goto done;
2901 : }
2902 1 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
2903 :
2904 1 : status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2905 1 : if (!NT_STATUS_IS_OK(status)) {
2906 0 : d_fprintf(stderr,
2907 : "cli_openx failed: %s\n",
2908 : nt_errstr(status));
2909 0 : goto done;
2910 : }
2911 :
2912 1 : status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2913 1 : if (!NT_STATUS_IS_OK(status)) {
2914 0 : d_fprintf(stderr,
2915 : "cli_writeall failed: %s\n",
2916 : nt_errstr(status));
2917 0 : goto done;
2918 : }
2919 :
2920 1 : status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2921 1 : if (!NT_STATUS_IS_OK(status)) {
2922 0 : d_fprintf(stderr,
2923 : "cli_openx failed: %s\n",
2924 : nt_errstr(status));
2925 0 : goto done;
2926 : }
2927 :
2928 1 : status = cli_locktype(
2929 : cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2930 1 : if (!NT_STATUS_IS_OK(status)) {
2931 0 : d_fprintf(stderr,
2932 : "cli_locktype failed: %s\n",
2933 : nt_errstr(status));
2934 0 : goto done;
2935 : }
2936 :
2937 1 : lck = (struct smb1_lock_element) {
2938 1 : .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2939 : };
2940 :
2941 1 : reqs[0] = cli_lockingx_create(
2942 : ev, /* mem_ctx */
2943 : ev, /* tevent_context */
2944 : cli1, /* cli */
2945 : fnum1, /* fnum */
2946 : LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
2947 : 0, /* newoplocklevel */
2948 : 1, /* timeout */
2949 : 0, /* num_unlocks */
2950 : NULL, /* unlocks */
2951 : 1, /* num_locks */
2952 : &lck, /* locks */
2953 : &smbreqs[0]); /* psmbreq */
2954 1 : if (reqs[0] == NULL) {
2955 0 : d_fprintf(stderr, "cli_lockingx_create failed\n");
2956 0 : goto done;
2957 : }
2958 1 : tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
2959 :
2960 1 : reqs[1] = cli_read_andx_create(
2961 : ev, /* mem_ctx */
2962 : ev, /* ev */
2963 : cli1, /* cli */
2964 : fnum1, /* fnum */
2965 : 0, /* offset */
2966 : 1, /* size */
2967 : &smbreqs[1]); /* psmbreq */
2968 1 : if (reqs[1] == NULL) {
2969 0 : d_fprintf(stderr, "cli_read_andx_create failed\n");
2970 0 : goto done;
2971 : }
2972 1 : tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
2973 :
2974 1 : status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
2975 1 : if (!NT_STATUS_IS_OK(status)) {
2976 0 : d_fprintf(stderr,
2977 : "smb1cli_req_chain_submit failed: %s\n",
2978 : nt_errstr(status));
2979 0 : goto done;
2980 : }
2981 :
2982 6 : while (!state.done) {
2983 5 : tevent_loop_once(ev);
2984 : }
2985 :
2986 1 : torture_close_connection(cli1);
2987 :
2988 1 : if (state.ok) {
2989 1 : ret = true;
2990 : }
2991 0 : done:
2992 1 : return ret;
2993 : }
2994 :
2995 1 : static void locktest10_lockingx_done(struct tevent_req *subreq)
2996 : {
2997 1 : struct locktest10_state *state = tevent_req_callback_data_void(subreq);
2998 : NTSTATUS status;
2999 :
3000 1 : status = cli_lockingx_recv(subreq);
3001 1 : TALLOC_FREE(subreq);
3002 :
3003 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3004 0 : d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3005 0 : state->ok = false;
3006 : }
3007 1 : }
3008 :
3009 1 : static void locktest10_read_andx_done(struct tevent_req *subreq)
3010 : {
3011 1 : struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3012 1 : ssize_t received = -1;
3013 1 : uint8_t *rcvbuf = NULL;
3014 : NTSTATUS status;
3015 :
3016 1 : status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3017 :
3018 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
3019 0 : d_printf("cli_read_andx returned %s\n", nt_errstr(status));
3020 0 : state->ok = false;
3021 : }
3022 :
3023 1 : state->done = true;
3024 1 : TALLOC_FREE(subreq);
3025 1 : }
3026 :
3027 1 : static bool run_locktest11(int dummy)
3028 : {
3029 : struct cli_state *cli1;
3030 1 : const char *fname = "\\lockt11.lck";
3031 : NTSTATUS status;
3032 : uint16_t fnum;
3033 1 : bool ret = false;
3034 :
3035 1 : if (!torture_open_connection(&cli1, 0)) {
3036 0 : return false;
3037 : }
3038 :
3039 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
3040 :
3041 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3042 :
3043 1 : status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
3044 1 : if (!NT_STATUS_IS_OK(status)) {
3045 0 : d_fprintf(stderr,
3046 : "cli_openx returned %s\n",
3047 : nt_errstr(status));
3048 0 : return false;
3049 : }
3050 :
3051 : /*
3052 : * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3053 : * returns NT_STATUS_OK
3054 : */
3055 :
3056 1 : status = cli_lockingx(
3057 : cli1, /* cli */
3058 : fnum, /* fnum */
3059 : LOCKING_ANDX_CANCEL_LOCK, /* typeoflock */
3060 : 0, /* newoplocklevel */
3061 : 0, /* timeout */
3062 : 0, /* num_unlocks */
3063 : NULL, /* unlocks */
3064 : 0, /* num_locks */
3065 : NULL); /* locks */
3066 :
3067 1 : if (!NT_STATUS_IS_OK(status)) {
3068 1 : d_printf("cli_lockingX returned %s\n", nt_errstr(status));
3069 1 : goto fail;
3070 : }
3071 :
3072 0 : ret = true;
3073 1 : fail:
3074 1 : cli_close(cli1, fnum);
3075 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3076 :
3077 1 : return ret;
3078 : }
3079 :
3080 : struct deferred_close_state {
3081 : struct tevent_context *ev;
3082 : struct cli_state *cli;
3083 : uint16_t fnum;
3084 : };
3085 :
3086 : static void deferred_close_waited(struct tevent_req *subreq);
3087 : static void deferred_close_done(struct tevent_req *subreq);
3088 :
3089 1 : static struct tevent_req *deferred_close_send(
3090 : TALLOC_CTX *mem_ctx,
3091 : struct tevent_context *ev,
3092 : int wait_secs,
3093 : struct cli_state *cli,
3094 : uint16_t fnum)
3095 : {
3096 1 : struct tevent_req *req = NULL, *subreq = NULL;
3097 1 : struct deferred_close_state *state = NULL;
3098 1 : struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
3099 :
3100 1 : req = tevent_req_create(
3101 : mem_ctx, &state, struct deferred_close_state);
3102 1 : if (req == NULL) {
3103 0 : return NULL;
3104 : }
3105 1 : state->ev = ev;
3106 1 : state->cli = cli;
3107 1 : state->fnum = fnum;
3108 :
3109 1 : subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
3110 1 : if (tevent_req_nomem(subreq, req)) {
3111 0 : return tevent_req_post(req, ev);
3112 : }
3113 1 : tevent_req_set_callback(subreq, deferred_close_waited, req);
3114 1 : return req;
3115 : }
3116 :
3117 1 : static void deferred_close_waited(struct tevent_req *subreq)
3118 : {
3119 1 : struct tevent_req *req = tevent_req_callback_data(
3120 : subreq, struct tevent_req);
3121 1 : struct deferred_close_state *state = tevent_req_data(
3122 : req, struct deferred_close_state);
3123 : bool ok;
3124 :
3125 1 : ok = tevent_wakeup_recv(subreq);
3126 1 : TALLOC_FREE(subreq);
3127 1 : if (!ok) {
3128 0 : tevent_req_oom(req);
3129 0 : return;
3130 : }
3131 :
3132 1 : subreq = cli_close_send(state, state->ev, state->cli, state->fnum);
3133 1 : if (tevent_req_nomem(subreq, req)) {
3134 0 : return;
3135 : }
3136 1 : tevent_req_set_callback(subreq, deferred_close_done, req);
3137 : }
3138 :
3139 1 : static void deferred_close_done(struct tevent_req *subreq)
3140 : {
3141 1 : NTSTATUS status = cli_close_recv(subreq);
3142 1 : tevent_req_simple_finish_ntstatus(subreq, status);
3143 1 : }
3144 :
3145 1 : static NTSTATUS deferred_close_recv(struct tevent_req *req)
3146 : {
3147 1 : return tevent_req_simple_recv_ntstatus(req);
3148 : }
3149 :
3150 : struct lockread_state {
3151 : struct smb1_lock_element lck;
3152 : struct tevent_req *reqs[2];
3153 : struct tevent_req *smbreqs[2];
3154 : NTSTATUS lock_status;
3155 : NTSTATUS read_status;
3156 : uint8_t *readbuf;
3157 : };
3158 :
3159 : static void lockread_lockingx_done(struct tevent_req *subreq);
3160 : static void lockread_read_andx_done(struct tevent_req *subreq);
3161 :
3162 1 : static struct tevent_req *lockread_send(
3163 : TALLOC_CTX *mem_ctx,
3164 : struct tevent_context *ev,
3165 : struct cli_state *cli,
3166 : uint16_t fnum)
3167 : {
3168 1 : struct tevent_req *req = NULL;
3169 1 : struct lockread_state *state = NULL;
3170 : NTSTATUS status;
3171 :
3172 1 : req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3173 1 : if (req == NULL) {
3174 0 : return NULL;
3175 : }
3176 :
3177 2 : state->lck = (struct smb1_lock_element) {
3178 1 : .pid = cli_getpid(cli), .offset = 0, .length = 1,
3179 : };
3180 :
3181 2 : state->reqs[0] = cli_lockingx_create(
3182 : ev, /* mem_ctx */
3183 : ev, /* tevent_context */
3184 : cli, /* cli */
3185 : fnum, /* fnum */
3186 : LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3187 : 0, /* newoplocklevel */
3188 : 10000, /* timeout */
3189 : 0, /* num_unlocks */
3190 : NULL, /* unlocks */
3191 : 1, /* num_locks */
3192 1 : &state->lck, /* locks */
3193 1 : &state->smbreqs[0]); /* psmbreq */
3194 1 : if (tevent_req_nomem(state->reqs[0], req)) {
3195 0 : return tevent_req_post(req, ev);
3196 : }
3197 1 : tevent_req_set_callback(
3198 1 : state->reqs[0], lockread_lockingx_done, req);
3199 :
3200 2 : state->reqs[1] = cli_read_andx_create(
3201 : ev, /* mem_ctx */
3202 : ev, /* ev */
3203 : cli, /* cli */
3204 : fnum, /* fnum */
3205 : 0, /* offset */
3206 : 1, /* size */
3207 1 : &state->smbreqs[1]); /* psmbreq */
3208 1 : if (tevent_req_nomem(state->reqs[1], req)) {
3209 0 : return tevent_req_post(req, ev);
3210 : }
3211 1 : tevent_req_set_callback(
3212 1 : state->reqs[1], lockread_read_andx_done, req);
3213 :
3214 1 : status = smb1cli_req_chain_submit(state->smbreqs, 2);
3215 1 : if (tevent_req_nterror(req, status)) {
3216 0 : return tevent_req_post(req, ev);
3217 : }
3218 1 : return req;
3219 : }
3220 :
3221 1 : static void lockread_lockingx_done(struct tevent_req *subreq)
3222 : {
3223 1 : struct tevent_req *req = tevent_req_callback_data(
3224 : subreq, struct tevent_req);
3225 1 : struct lockread_state *state = tevent_req_data(
3226 : req, struct lockread_state);
3227 1 : state->lock_status = cli_lockingx_recv(subreq);
3228 1 : TALLOC_FREE(subreq);
3229 1 : d_fprintf(stderr,
3230 : "lockingx returned %s\n",
3231 : nt_errstr(state->lock_status));
3232 1 : }
3233 :
3234 1 : static void lockread_read_andx_done(struct tevent_req *subreq)
3235 : {
3236 1 : struct tevent_req *req = tevent_req_callback_data(
3237 : subreq, struct tevent_req);
3238 1 : struct lockread_state *state = tevent_req_data(
3239 : req, struct lockread_state);
3240 1 : ssize_t received = -1;
3241 1 : uint8_t *rcvbuf = NULL;
3242 :
3243 1 : state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3244 :
3245 1 : d_fprintf(stderr,
3246 : "read returned %s\n",
3247 : nt_errstr(state->read_status));
3248 :
3249 1 : if (!NT_STATUS_IS_OK(state->read_status)) {
3250 0 : TALLOC_FREE(subreq);
3251 0 : tevent_req_done(req);
3252 0 : return;
3253 : }
3254 :
3255 1 : if (received > 0) {
3256 1 : state->readbuf = talloc_memdup(state, rcvbuf, received);
3257 1 : TALLOC_FREE(subreq);
3258 1 : if (tevent_req_nomem(state->readbuf, req)) {
3259 0 : return;
3260 : }
3261 : }
3262 1 : TALLOC_FREE(subreq);
3263 1 : tevent_req_done(req);
3264 : }
3265 :
3266 1 : static NTSTATUS lockread_recv(
3267 : struct tevent_req *req,
3268 : NTSTATUS *lock_status,
3269 : NTSTATUS *read_status,
3270 : TALLOC_CTX *mem_ctx,
3271 : uint8_t **read_buf)
3272 : {
3273 1 : struct lockread_state *state = tevent_req_data(
3274 : req, struct lockread_state);
3275 : NTSTATUS status;
3276 :
3277 1 : if (tevent_req_is_nterror(req, &status)) {
3278 0 : return status;
3279 : }
3280 :
3281 1 : *lock_status = state->lock_status;
3282 1 : *read_status = state->read_status;
3283 1 : if (state->readbuf != NULL) {
3284 1 : *read_buf = talloc_move(mem_ctx, &state->readbuf);
3285 : } else {
3286 0 : *read_buf = NULL;
3287 : }
3288 :
3289 1 : return NT_STATUS_OK;
3290 : }
3291 :
3292 : struct lock12_state {
3293 : uint8_t dummy;
3294 : };
3295 :
3296 : static void lock12_closed(struct tevent_req *subreq);
3297 : static void lock12_read(struct tevent_req *subreq);
3298 :
3299 1 : static struct tevent_req *lock12_send(
3300 : TALLOC_CTX *mem_ctx,
3301 : struct tevent_context *ev,
3302 : struct cli_state *cli,
3303 : uint16_t fnum1,
3304 : uint16_t fnum2)
3305 : {
3306 1 : struct tevent_req *req = NULL, *subreq = NULL;
3307 1 : struct lock12_state *state = NULL;
3308 :
3309 1 : req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3310 1 : if (req == NULL) {
3311 0 : return NULL;
3312 : }
3313 :
3314 1 : subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3315 1 : if (tevent_req_nomem(subreq, req)) {
3316 0 : return tevent_req_post(req, ev);
3317 : }
3318 1 : tevent_req_set_callback(subreq, lock12_closed, req);
3319 :
3320 1 : subreq = lockread_send(state, ev, cli, fnum2);
3321 1 : if (tevent_req_nomem(subreq, req)) {
3322 0 : return tevent_req_post(req, ev);
3323 : }
3324 1 : tevent_req_set_callback(subreq, lock12_read, req);
3325 :
3326 1 : return req;
3327 : }
3328 :
3329 1 : static void lock12_closed(struct tevent_req *subreq)
3330 : {
3331 1 : struct tevent_req *req = tevent_req_callback_data(
3332 : subreq, struct tevent_req);
3333 : NTSTATUS status;
3334 :
3335 1 : status = deferred_close_recv(subreq);
3336 1 : TALLOC_FREE(subreq);
3337 1 : DBG_DEBUG("close returned %s\n", nt_errstr(status));
3338 1 : if (tevent_req_nterror(req, status)) {
3339 0 : return;
3340 : }
3341 : }
3342 :
3343 1 : static void lock12_read(struct tevent_req *subreq)
3344 : {
3345 1 : struct tevent_req *req = tevent_req_callback_data(
3346 : subreq, struct tevent_req);
3347 1 : struct lock12_state *state = tevent_req_data(
3348 : req, struct lock12_state);
3349 : NTSTATUS status, lock_status, read_status;
3350 1 : uint8_t *buf = NULL;
3351 :
3352 1 : status = lockread_recv(
3353 : subreq, &lock_status, &read_status, state, &buf);
3354 1 : TALLOC_FREE(subreq);
3355 2 : if (tevent_req_nterror(req, status) ||
3356 2 : tevent_req_nterror(req, lock_status) ||
3357 1 : tevent_req_nterror(req, read_status)) {
3358 0 : return;
3359 : }
3360 1 : tevent_req_done(req);
3361 : }
3362 :
3363 1 : static NTSTATUS lock12_recv(struct tevent_req *req)
3364 :
3365 : {
3366 : NTSTATUS status;
3367 :
3368 1 : if (tevent_req_is_nterror(req, &status)) {
3369 0 : return status;
3370 : }
3371 1 : return NT_STATUS_OK;
3372 : }
3373 :
3374 1 : static bool run_locktest12(int dummy)
3375 : {
3376 1 : struct tevent_context *ev = NULL;
3377 1 : struct tevent_req *req = NULL;
3378 1 : struct cli_state *cli = NULL;
3379 1 : const char fname[] = "\\lockt12.lck";
3380 : uint16_t fnum1, fnum2;
3381 1 : bool ret = false;
3382 : bool ok;
3383 1 : uint8_t data = 1;
3384 : NTSTATUS status;
3385 :
3386 1 : printf("starting locktest12\n");
3387 :
3388 1 : ev = samba_tevent_context_init(NULL);
3389 1 : if (ev == NULL) {
3390 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
3391 0 : goto done;
3392 : }
3393 :
3394 1 : ok = torture_open_connection(&cli, 0);
3395 1 : if (!ok) {
3396 0 : goto done;
3397 : }
3398 1 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3399 :
3400 1 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3401 1 : if (!NT_STATUS_IS_OK(status)) {
3402 0 : d_fprintf(stderr,
3403 : "cli_openx failed: %s\n",
3404 : nt_errstr(status));
3405 0 : goto done;
3406 : }
3407 :
3408 1 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3409 1 : if (!NT_STATUS_IS_OK(status)) {
3410 0 : d_fprintf(stderr,
3411 : "cli_openx failed: %s\n",
3412 : nt_errstr(status));
3413 0 : goto done;
3414 : }
3415 :
3416 1 : status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3417 1 : if (!NT_STATUS_IS_OK(status)) {
3418 0 : d_fprintf(stderr,
3419 : "cli_writeall failed: %s\n",
3420 : nt_errstr(status));
3421 0 : goto done;
3422 : }
3423 :
3424 1 : status = cli_locktype(
3425 : cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3426 1 : if (!NT_STATUS_IS_OK(status)) {
3427 0 : d_fprintf(stderr,
3428 : "cli_locktype failed: %s\n",
3429 : nt_errstr(status));
3430 0 : goto done;
3431 : }
3432 :
3433 1 : req = lock12_send(ev, ev, cli, fnum1, fnum2);
3434 1 : if (req == NULL) {
3435 0 : d_fprintf(stderr, "lock12_send failed\n");
3436 0 : goto done;
3437 : }
3438 :
3439 1 : ok = tevent_req_poll_ntstatus(req, ev, &status);
3440 1 : if (!ok) {
3441 0 : d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3442 0 : goto done;
3443 : }
3444 :
3445 1 : if (!NT_STATUS_IS_OK(status)) {
3446 0 : d_fprintf(stderr,
3447 : "tevent_req_poll_ntstatus returned %s\n",
3448 : nt_errstr(status));
3449 0 : goto done;
3450 : }
3451 :
3452 1 : status = lock12_recv(req);
3453 1 : if (!NT_STATUS_IS_OK(status)) {
3454 0 : d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3455 0 : goto done;
3456 : }
3457 :
3458 1 : ret = true;
3459 1 : done:
3460 1 : if (cli != NULL) {
3461 1 : torture_close_connection(cli);
3462 : }
3463 1 : return ret;
3464 : }
3465 :
3466 : struct lock_ntcancel_state {
3467 : struct timeval start;
3468 : struct smb1_lock_element lck;
3469 : struct tevent_req *subreq;
3470 : };
3471 :
3472 : static void lock_ntcancel_waited(struct tevent_req *subreq);
3473 : static void lock_ntcancel_done(struct tevent_req *subreq);
3474 :
3475 1 : static struct tevent_req *lock_ntcancel_send(
3476 : TALLOC_CTX *mem_ctx,
3477 : struct tevent_context *ev,
3478 : struct cli_state *cli,
3479 : uint16_t fnum)
3480 : {
3481 1 : struct tevent_req *req = NULL, *subreq = NULL;
3482 1 : struct lock_ntcancel_state *state = NULL;
3483 :
3484 1 : req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3485 1 : if (req == NULL) {
3486 0 : return NULL;
3487 : }
3488 2 : state->lck = (struct smb1_lock_element) {
3489 1 : .pid = cli_getpid(cli), .offset = 0, .length = 1,
3490 : };
3491 1 : state->start = timeval_current();
3492 :
3493 2 : state->subreq = cli_lockingx_send(
3494 : state, /* mem_ctx */
3495 : ev, /* tevent_context */
3496 : cli, /* cli */
3497 : fnum, /* fnum */
3498 : LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3499 : 0, /* newoplocklevel */
3500 : 10000, /* timeout */
3501 : 0, /* num_unlocks */
3502 : NULL, /* unlocks */
3503 : 1, /* num_locks */
3504 1 : &state->lck); /* locks */
3505 1 : if (tevent_req_nomem(state->subreq, req)) {
3506 0 : return tevent_req_post(req, ev);
3507 : }
3508 1 : tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3509 :
3510 1 : subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3511 1 : if (tevent_req_nomem(subreq, req)) {
3512 0 : return tevent_req_post(req, ev);
3513 : }
3514 1 : tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3515 1 : return req;
3516 : }
3517 :
3518 1 : static void lock_ntcancel_waited(struct tevent_req *subreq)
3519 : {
3520 1 : struct tevent_req *req = tevent_req_callback_data(
3521 : subreq, struct tevent_req);
3522 1 : struct lock_ntcancel_state *state = tevent_req_data(
3523 : req, struct lock_ntcancel_state);
3524 : bool ok;
3525 :
3526 1 : ok = tevent_wakeup_recv(subreq);
3527 1 : TALLOC_FREE(subreq);
3528 1 : if (!ok) {
3529 0 : tevent_req_oom(req);
3530 0 : return;
3531 : }
3532 :
3533 1 : ok = tevent_req_cancel(state->subreq);
3534 1 : if (!ok) {
3535 0 : d_fprintf(stderr, "Could not cancel subreq\n");
3536 0 : tevent_req_oom(req);
3537 0 : return;
3538 : }
3539 : }
3540 :
3541 1 : static void lock_ntcancel_done(struct tevent_req *subreq)
3542 : {
3543 1 : struct tevent_req *req = tevent_req_callback_data(
3544 : subreq, struct tevent_req);
3545 1 : struct lock_ntcancel_state *state = tevent_req_data(
3546 : req, struct lock_ntcancel_state);
3547 : NTSTATUS status;
3548 : double elapsed;
3549 :
3550 1 : status = cli_lockingx_recv(subreq);
3551 1 : TALLOC_FREE(subreq);
3552 :
3553 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3554 0 : d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3555 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3556 0 : return;
3557 : }
3558 :
3559 1 : elapsed = timeval_elapsed(&state->start);
3560 :
3561 1 : if (elapsed > 3) {
3562 0 : d_printf("cli_lockingx was too slow, cancel did not work\n");
3563 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3564 0 : return;
3565 : }
3566 :
3567 1 : tevent_req_done(req);
3568 : }
3569 :
3570 1 : static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3571 : {
3572 1 : return tevent_req_simple_recv_ntstatus(req);
3573 : }
3574 :
3575 1 : static bool run_locktest13(int dummy)
3576 : {
3577 1 : struct tevent_context *ev = NULL;
3578 1 : struct tevent_req *req = NULL;
3579 1 : struct cli_state *cli = NULL;
3580 1 : const char fname[] = "\\lockt13.lck";
3581 : uint16_t fnum1, fnum2;
3582 1 : bool ret = false;
3583 : bool ok;
3584 1 : uint8_t data = 1;
3585 : NTSTATUS status;
3586 :
3587 1 : printf("starting locktest13\n");
3588 :
3589 1 : ev = samba_tevent_context_init(NULL);
3590 1 : if (ev == NULL) {
3591 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
3592 0 : goto done;
3593 : }
3594 :
3595 1 : ok = torture_open_connection(&cli, 0);
3596 1 : if (!ok) {
3597 0 : goto done;
3598 : }
3599 1 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3600 :
3601 1 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3602 1 : if (!NT_STATUS_IS_OK(status)) {
3603 0 : d_fprintf(stderr,
3604 : "cli_openx failed: %s\n",
3605 : nt_errstr(status));
3606 0 : goto done;
3607 : }
3608 :
3609 1 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3610 1 : if (!NT_STATUS_IS_OK(status)) {
3611 0 : d_fprintf(stderr,
3612 : "cli_openx failed: %s\n",
3613 : nt_errstr(status));
3614 0 : goto done;
3615 : }
3616 :
3617 1 : status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3618 1 : if (!NT_STATUS_IS_OK(status)) {
3619 0 : d_fprintf(stderr,
3620 : "cli_writeall failed: %s\n",
3621 : nt_errstr(status));
3622 0 : goto done;
3623 : }
3624 :
3625 1 : status = cli_locktype(
3626 : cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3627 1 : if (!NT_STATUS_IS_OK(status)) {
3628 0 : d_fprintf(stderr,
3629 : "cli_locktype failed: %s\n",
3630 : nt_errstr(status));
3631 0 : goto done;
3632 : }
3633 :
3634 1 : req = lock_ntcancel_send(ev, ev, cli, fnum2);
3635 1 : if (req == NULL) {
3636 0 : d_fprintf(stderr, "lock_ntcancel_send failed\n");
3637 0 : goto done;
3638 : }
3639 :
3640 1 : ok = tevent_req_poll_ntstatus(req, ev, &status);
3641 1 : if (!ok) {
3642 0 : d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3643 0 : goto done;
3644 : }
3645 :
3646 1 : if (!NT_STATUS_IS_OK(status)) {
3647 0 : d_fprintf(stderr,
3648 : "tevent_req_poll_ntstatus returned %s\n",
3649 : nt_errstr(status));
3650 0 : goto done;
3651 : }
3652 :
3653 1 : status = lock_ntcancel_recv(req);
3654 1 : if (!NT_STATUS_IS_OK(status)) {
3655 0 : d_fprintf(stderr,
3656 : "lock_ntcancel returned %s\n",
3657 : nt_errstr(status));
3658 0 : goto done;
3659 : }
3660 :
3661 1 : ret = true;
3662 1 : done:
3663 1 : if (cli != NULL) {
3664 1 : torture_close_connection(cli);
3665 : }
3666 1 : return ret;
3667 : }
3668 :
3669 : /*
3670 : test whether fnums and tids open on one VC are available on another (a major
3671 : security hole)
3672 : */
3673 1 : static bool run_fdpasstest(int dummy)
3674 : {
3675 : struct cli_state *cli1, *cli2;
3676 1 : const char *fname = "\\fdpass.tst";
3677 : uint16_t fnum1;
3678 : char buf[1024];
3679 : NTSTATUS status;
3680 :
3681 1 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3682 0 : return False;
3683 : }
3684 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
3685 1 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
3686 :
3687 1 : printf("starting fdpasstest\n");
3688 :
3689 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3690 :
3691 1 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3692 : &fnum1);
3693 1 : if (!NT_STATUS_IS_OK(status)) {
3694 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3695 0 : return False;
3696 : }
3697 :
3698 1 : status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3699 : 13, NULL);
3700 1 : if (!NT_STATUS_IS_OK(status)) {
3701 0 : printf("write failed (%s)\n", nt_errstr(status));
3702 0 : return False;
3703 : }
3704 :
3705 1 : cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3706 1 : cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3707 1 : cli_setpid(cli2, cli_getpid(cli1));
3708 :
3709 1 : if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3710 0 : printf("read succeeded! nasty security hole [%s]\n", buf);
3711 0 : return false;
3712 : }
3713 :
3714 1 : cli_close(cli1, fnum1);
3715 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3716 :
3717 1 : torture_close_connection(cli1);
3718 1 : torture_close_connection(cli2);
3719 :
3720 1 : printf("finished fdpasstest\n");
3721 1 : return True;
3722 : }
3723 :
3724 1 : static bool run_fdsesstest(int dummy)
3725 : {
3726 : struct cli_state *cli;
3727 : uint16_t new_vuid;
3728 : uint16_t saved_vuid;
3729 : uint32_t new_cnum;
3730 : uint32_t saved_cnum;
3731 1 : const char *fname = "\\fdsess.tst";
3732 1 : const char *fname1 = "\\fdsess1.tst";
3733 : uint16_t fnum1;
3734 : uint16_t fnum2;
3735 : char buf[1024];
3736 1 : bool ret = True;
3737 : NTSTATUS status;
3738 :
3739 1 : if (!torture_open_connection(&cli, 0))
3740 0 : return False;
3741 1 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3742 :
3743 1 : if (!torture_cli_session_setup2(cli, &new_vuid))
3744 0 : return False;
3745 :
3746 1 : saved_cnum = cli_state_get_tid(cli);
3747 1 : if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3748 0 : return False;
3749 1 : new_cnum = cli_state_get_tid(cli);
3750 1 : cli_state_set_tid(cli, saved_cnum);
3751 :
3752 1 : printf("starting fdsesstest\n");
3753 :
3754 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3755 1 : cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3756 :
3757 1 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3758 1 : if (!NT_STATUS_IS_OK(status)) {
3759 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3760 0 : return False;
3761 : }
3762 :
3763 1 : status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3764 : NULL);
3765 1 : if (!NT_STATUS_IS_OK(status)) {
3766 0 : printf("write failed (%s)\n", nt_errstr(status));
3767 0 : return False;
3768 : }
3769 :
3770 1 : saved_vuid = cli_state_get_uid(cli);
3771 1 : cli_state_set_uid(cli, new_vuid);
3772 :
3773 1 : if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3774 0 : printf("read succeeded with different vuid! "
3775 : "nasty security hole [%s]\n", buf);
3776 0 : ret = false;
3777 : }
3778 : /* Try to open a file with different vuid, samba cnum. */
3779 1 : if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3780 1 : printf("create with different vuid, same cnum succeeded.\n");
3781 1 : cli_close(cli, fnum2);
3782 1 : cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3783 : } else {
3784 0 : printf("create with different vuid, same cnum failed.\n");
3785 0 : printf("This will cause problems with service clients.\n");
3786 0 : ret = False;
3787 : }
3788 :
3789 1 : cli_state_set_uid(cli, saved_vuid);
3790 :
3791 : /* Try with same vuid, different cnum. */
3792 1 : cli_state_set_tid(cli, new_cnum);
3793 :
3794 1 : if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3795 0 : printf("read succeeded with different cnum![%s]\n", buf);
3796 0 : ret = false;
3797 : }
3798 :
3799 1 : cli_state_set_tid(cli, saved_cnum);
3800 1 : cli_close(cli, fnum1);
3801 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3802 :
3803 1 : torture_close_connection(cli);
3804 :
3805 1 : printf("finished fdsesstest\n");
3806 1 : return ret;
3807 : }
3808 :
3809 : /*
3810 : This test checks that
3811 :
3812 : 1) the server does not allow an unlink on a file that is open
3813 : */
3814 1 : static bool run_unlinktest(int dummy)
3815 : {
3816 : struct cli_state *cli;
3817 1 : const char *fname = "\\unlink.tst";
3818 : uint16_t fnum;
3819 1 : bool correct = True;
3820 : NTSTATUS status;
3821 :
3822 1 : if (!torture_open_connection(&cli, 0)) {
3823 0 : return False;
3824 : }
3825 :
3826 1 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3827 :
3828 1 : printf("starting unlink test\n");
3829 :
3830 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3831 :
3832 1 : cli_setpid(cli, 1);
3833 :
3834 1 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3835 1 : if (!NT_STATUS_IS_OK(status)) {
3836 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3837 0 : return False;
3838 : }
3839 :
3840 1 : status = cli_unlink(cli, fname,
3841 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3842 1 : if (NT_STATUS_IS_OK(status)) {
3843 0 : printf("error: server allowed unlink on an open file\n");
3844 0 : correct = False;
3845 : } else {
3846 1 : correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3847 1 : NT_STATUS_SHARING_VIOLATION);
3848 : }
3849 :
3850 1 : cli_close(cli, fnum);
3851 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3852 :
3853 1 : if (!torture_close_connection(cli)) {
3854 0 : correct = False;
3855 : }
3856 :
3857 1 : printf("unlink test finished\n");
3858 :
3859 1 : return correct;
3860 : }
3861 :
3862 :
3863 : /*
3864 : test how many open files this server supports on the one socket
3865 : */
3866 0 : static bool run_maxfidtest(int dummy)
3867 : {
3868 : struct cli_state *cli;
3869 : fstring fname;
3870 : uint16_t fnums[0x11000];
3871 : int i;
3872 0 : int retries=4;
3873 0 : bool correct = True;
3874 : NTSTATUS status;
3875 :
3876 0 : cli = current_cli;
3877 :
3878 0 : if (retries <= 0) {
3879 0 : printf("failed to connect\n");
3880 0 : return False;
3881 : }
3882 :
3883 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3884 :
3885 0 : for (i=0; i<0x11000; i++) {
3886 0 : slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3887 0 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3888 : &fnums[i]);
3889 0 : if (!NT_STATUS_IS_OK(status)) {
3890 0 : printf("open of %s failed (%s)\n",
3891 : fname, nt_errstr(status));
3892 0 : printf("maximum fnum is %d\n", i);
3893 0 : break;
3894 : }
3895 0 : printf("%6d\r", i);
3896 : }
3897 0 : printf("%6d\n", i);
3898 0 : i--;
3899 :
3900 0 : printf("cleaning up\n");
3901 0 : for (;i>=0;i--) {
3902 0 : slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3903 0 : cli_close(cli, fnums[i]);
3904 :
3905 0 : status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3906 0 : if (!NT_STATUS_IS_OK(status)) {
3907 0 : printf("unlink of %s failed (%s)\n",
3908 : fname, nt_errstr(status));
3909 0 : correct = False;
3910 : }
3911 0 : printf("%6d\r", i);
3912 : }
3913 0 : printf("%6d\n", 0);
3914 :
3915 0 : printf("maxfid test finished\n");
3916 0 : if (!torture_close_connection(cli)) {
3917 0 : correct = False;
3918 : }
3919 0 : return correct;
3920 : }
3921 :
3922 : /* generate a random buffer */
3923 0 : static void rand_buf(char *buf, int len)
3924 : {
3925 0 : while (len--) {
3926 0 : *buf = (char)sys_random();
3927 0 : buf++;
3928 : }
3929 0 : }
3930 :
3931 : /* send smb negprot commands, not reading the response */
3932 0 : static bool run_negprot_nowait(int dummy)
3933 : {
3934 : struct tevent_context *ev;
3935 : int i;
3936 : struct cli_state *cli;
3937 0 : bool correct = True;
3938 :
3939 0 : printf("starting negprot nowait test\n");
3940 :
3941 0 : ev = samba_tevent_context_init(talloc_tos());
3942 0 : if (ev == NULL) {
3943 0 : return false;
3944 : }
3945 :
3946 0 : if (!(cli = open_nbt_connection())) {
3947 0 : TALLOC_FREE(ev);
3948 0 : return False;
3949 : }
3950 :
3951 0 : for (i=0;i<50000;i++) {
3952 : struct tevent_req *req;
3953 :
3954 0 : req = smbXcli_negprot_send(
3955 : ev,
3956 : ev,
3957 : cli->conn,
3958 0 : cli->timeout,
3959 : PROTOCOL_CORE,
3960 : PROTOCOL_NT1,
3961 : 0,
3962 : NULL);
3963 0 : if (req == NULL) {
3964 0 : TALLOC_FREE(ev);
3965 0 : return false;
3966 : }
3967 0 : if (!tevent_req_poll(req, ev)) {
3968 0 : d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3969 0 : strerror(errno));
3970 0 : TALLOC_FREE(ev);
3971 0 : return false;
3972 : }
3973 0 : TALLOC_FREE(req);
3974 : }
3975 :
3976 0 : if (torture_close_connection(cli)) {
3977 0 : correct = False;
3978 : }
3979 :
3980 0 : printf("finished negprot nowait test\n");
3981 :
3982 0 : return correct;
3983 : }
3984 :
3985 : /* send smb negprot commands, not reading the response */
3986 0 : static bool run_bad_nbt_session(int dummy)
3987 : {
3988 : struct nmb_name called, calling;
3989 : struct sockaddr_storage ss;
3990 : NTSTATUS status;
3991 : int fd;
3992 : bool ret;
3993 :
3994 0 : printf("starting bad nbt session test\n");
3995 :
3996 0 : make_nmb_name(&calling, myname, 0x0);
3997 0 : make_nmb_name(&called , host, 0x20);
3998 :
3999 0 : if (!resolve_name(host, &ss, 0x20, true)) {
4000 0 : d_fprintf(stderr, "Could not resolve name %s\n", host);
4001 0 : return false;
4002 : }
4003 :
4004 0 : status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4005 0 : if (!NT_STATUS_IS_OK(status)) {
4006 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
4007 : nt_errstr(status));
4008 0 : return false;
4009 : }
4010 :
4011 0 : ret = cli_bad_session_request(fd, &calling, &called);
4012 0 : close(fd);
4013 0 : if (!ret) {
4014 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
4015 : nt_errstr(status));
4016 0 : return false;
4017 : }
4018 :
4019 0 : printf("finished bad nbt session test\n");
4020 0 : return true;
4021 : }
4022 :
4023 : /* send random IPC commands */
4024 0 : static bool run_randomipc(int dummy)
4025 : {
4026 0 : char *rparam = NULL;
4027 0 : char *rdata = NULL;
4028 : unsigned int rdrcnt,rprcnt;
4029 : char param[1024];
4030 : int api, param_len, i;
4031 : struct cli_state *cli;
4032 0 : bool correct = True;
4033 0 : int count = 50000;
4034 :
4035 0 : printf("starting random ipc test\n");
4036 :
4037 0 : if (!torture_open_connection(&cli, 0)) {
4038 0 : return False;
4039 : }
4040 :
4041 0 : for (i=0;i<count;i++) {
4042 0 : api = sys_random() % 500;
4043 0 : param_len = (sys_random() % 64);
4044 :
4045 0 : rand_buf(param, param_len);
4046 :
4047 0 : SSVAL(param,0,api);
4048 :
4049 0 : cli_api(cli,
4050 : param, param_len, 8,
4051 : NULL, 0, CLI_BUFFER_SIZE,
4052 : &rparam, &rprcnt,
4053 : &rdata, &rdrcnt);
4054 0 : if (i % 100 == 0) {
4055 0 : printf("%d/%d\r", i,count);
4056 : }
4057 : }
4058 0 : printf("%d/%d\n", i, count);
4059 :
4060 0 : if (!torture_close_connection(cli)) {
4061 0 : correct = False;
4062 : }
4063 :
4064 0 : SAFE_FREE(rparam);
4065 0 : SAFE_FREE(rdata);
4066 :
4067 0 : printf("finished random ipc test\n");
4068 :
4069 0 : return correct;
4070 : }
4071 :
4072 :
4073 :
4074 0 : static void browse_callback(const char *sname, uint32_t stype,
4075 : const char *comment, void *state)
4076 : {
4077 0 : printf("\t%20.20s %08x %s\n", sname, stype, comment);
4078 0 : }
4079 :
4080 :
4081 :
4082 : /*
4083 : This test checks the browse list code
4084 :
4085 : */
4086 1 : static bool run_browsetest(int dummy)
4087 : {
4088 : static struct cli_state *cli;
4089 1 : bool correct = True;
4090 :
4091 1 : printf("starting browse test\n");
4092 :
4093 1 : if (!torture_open_connection(&cli, 0)) {
4094 0 : return False;
4095 : }
4096 :
4097 1 : printf("domain list:\n");
4098 1 : cli_NetServerEnum(cli, cli->server_domain,
4099 : SV_TYPE_DOMAIN_ENUM,
4100 : browse_callback, NULL);
4101 :
4102 1 : printf("machine list:\n");
4103 1 : cli_NetServerEnum(cli, cli->server_domain,
4104 : SV_TYPE_ALL,
4105 : browse_callback, NULL);
4106 :
4107 1 : if (!torture_close_connection(cli)) {
4108 0 : correct = False;
4109 : }
4110 :
4111 1 : printf("browse test finished\n");
4112 :
4113 1 : return correct;
4114 :
4115 : }
4116 :
4117 4 : static bool check_attributes(struct cli_state *cli,
4118 : const char *fname,
4119 : uint32_t expected_attrs)
4120 : {
4121 4 : uint32_t attrs = 0;
4122 4 : NTSTATUS status = cli_getatr(cli,
4123 : fname,
4124 : &attrs,
4125 : NULL,
4126 : NULL);
4127 4 : if (!NT_STATUS_IS_OK(status)) {
4128 0 : printf("cli_getatr failed with %s\n",
4129 : nt_errstr(status));
4130 0 : return false;
4131 : }
4132 4 : if (attrs != expected_attrs) {
4133 0 : printf("Attributes incorrect 0x%x, should be 0x%x\n",
4134 : (unsigned int)attrs,
4135 : (unsigned int)expected_attrs);
4136 0 : return false;
4137 : }
4138 4 : return true;
4139 : }
4140 :
4141 : /*
4142 : This checks how the getatr calls works
4143 : */
4144 1 : static bool run_attrtest(int dummy)
4145 : {
4146 : struct cli_state *cli;
4147 : uint16_t fnum;
4148 : time_t t, t2;
4149 1 : const char *fname = "\\attrib123456789.tst";
4150 1 : bool correct = True;
4151 : NTSTATUS status;
4152 :
4153 1 : printf("starting attrib test\n");
4154 :
4155 1 : if (!torture_open_connection(&cli, 0)) {
4156 0 : return False;
4157 : }
4158 :
4159 : /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4160 1 : status = cli_unlink(cli, fname, 0x20000);
4161 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4162 0 : correct = false;
4163 0 : goto out;
4164 : }
4165 :
4166 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4167 1 : cli_openx(cli, fname,
4168 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4169 1 : cli_close(cli, fnum);
4170 :
4171 1 : status = cli_getatr(cli, fname, NULL, NULL, &t);
4172 1 : if (!NT_STATUS_IS_OK(status)) {
4173 0 : printf("getatr failed (%s)\n", nt_errstr(status));
4174 0 : correct = False;
4175 : }
4176 :
4177 1 : if (labs(t - time(NULL)) > 60*60*24*10) {
4178 0 : printf("ERROR: SMBgetatr bug. time is %s",
4179 : ctime(&t));
4180 0 : t = time(NULL);
4181 0 : correct = True;
4182 : }
4183 :
4184 1 : t2 = t-60*60*24; /* 1 day ago */
4185 :
4186 : /* Ensure we can't set with out-of-range (unknown) attribute. */
4187 1 : status = cli_setatr(cli, fname, 0x20000, t2);
4188 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4189 0 : correct = false;
4190 0 : goto out;
4191 : }
4192 :
4193 1 : status = cli_setatr(cli, fname, 0, t2);
4194 1 : if (!NT_STATUS_IS_OK(status)) {
4195 0 : printf("setatr failed (%s)\n", nt_errstr(status));
4196 0 : correct = True;
4197 : }
4198 :
4199 1 : status = cli_getatr(cli, fname, NULL, NULL, &t);
4200 1 : if (!NT_STATUS_IS_OK(status)) {
4201 0 : printf("getatr failed (%s)\n", nt_errstr(status));
4202 0 : correct = True;
4203 : }
4204 :
4205 1 : if (t != t2) {
4206 0 : printf("ERROR: getatr/setatr bug. times are\n%s",
4207 : ctime(&t));
4208 0 : printf("%s", ctime(&t2));
4209 0 : correct = True;
4210 : }
4211 :
4212 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4213 :
4214 : /* Check cli_setpathinfo_ext() */
4215 : /* Re-create the file. */
4216 1 : status = cli_openx(cli, fname,
4217 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4218 1 : if (!NT_STATUS_IS_OK(status)) {
4219 0 : printf("Failed to recreate %s (%s)\n",
4220 : fname, nt_errstr(status));
4221 0 : correct = false;
4222 : }
4223 1 : cli_close(cli, fnum);
4224 :
4225 1 : status = cli_setpathinfo_ext(
4226 : cli,
4227 : fname,
4228 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4229 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4230 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4231 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4232 : FILE_ATTRIBUTE_SYSTEM |
4233 : FILE_ATTRIBUTE_HIDDEN |
4234 : FILE_ATTRIBUTE_READONLY);
4235 1 : if (!NT_STATUS_IS_OK(status)) {
4236 0 : printf("cli_setpathinfo_ext failed with %s\n",
4237 : nt_errstr(status));
4238 0 : correct = false;
4239 : }
4240 :
4241 : /* Check attributes are correct. */
4242 1 : correct = check_attributes(cli,
4243 : fname,
4244 : FILE_ATTRIBUTE_SYSTEM |
4245 : FILE_ATTRIBUTE_HIDDEN |
4246 : FILE_ATTRIBUTE_READONLY);
4247 1 : if (correct == false) {
4248 0 : goto out;
4249 : }
4250 :
4251 : /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4252 1 : status = cli_setpathinfo_ext(
4253 : cli,
4254 : fname,
4255 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4256 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4257 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4258 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4259 : FILE_ATTRIBUTE_NORMAL);
4260 1 : if (!NT_STATUS_IS_OK(status)) {
4261 0 : printf("cli_setpathinfo_ext failed with %s\n",
4262 : nt_errstr(status));
4263 0 : correct = false;
4264 : }
4265 :
4266 : /* Check attributes are correct. */
4267 1 : correct = check_attributes(cli,
4268 : fname,
4269 : FILE_ATTRIBUTE_SYSTEM |
4270 : FILE_ATTRIBUTE_HIDDEN |
4271 : FILE_ATTRIBUTE_READONLY);
4272 1 : if (correct == false) {
4273 0 : goto out;
4274 : }
4275 :
4276 : /* Setting to (uint16_t)-1 should also be ignored. */
4277 1 : status = cli_setpathinfo_ext(
4278 : cli,
4279 : fname,
4280 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4281 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4282 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4283 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4284 : (uint32_t)-1);
4285 1 : if (!NT_STATUS_IS_OK(status)) {
4286 0 : printf("cli_setpathinfo_ext failed with %s\n",
4287 : nt_errstr(status));
4288 0 : correct = false;
4289 : }
4290 :
4291 : /* Check attributes are correct. */
4292 1 : correct = check_attributes(cli,
4293 : fname,
4294 : FILE_ATTRIBUTE_SYSTEM |
4295 : FILE_ATTRIBUTE_HIDDEN |
4296 : FILE_ATTRIBUTE_READONLY);
4297 1 : if (correct == false) {
4298 0 : goto out;
4299 : }
4300 :
4301 : /* Setting to 0 should clear them all. */
4302 1 : status = cli_setpathinfo_ext(
4303 : cli,
4304 : fname,
4305 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4306 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4307 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4308 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4309 : 0);
4310 1 : if (!NT_STATUS_IS_OK(status)) {
4311 0 : printf("cli_setpathinfo_ext failed with %s\n",
4312 : nt_errstr(status));
4313 0 : correct = false;
4314 : }
4315 :
4316 : /* Check attributes are correct. */
4317 1 : correct = check_attributes(cli,
4318 : fname,
4319 : FILE_ATTRIBUTE_NORMAL);
4320 1 : if (correct == false) {
4321 0 : goto out;
4322 : }
4323 :
4324 1 : out:
4325 :
4326 1 : cli_unlink(cli,
4327 : fname,
4328 : FILE_ATTRIBUTE_SYSTEM |
4329 : FILE_ATTRIBUTE_HIDDEN|
4330 : FILE_ATTRIBUTE_READONLY);
4331 :
4332 1 : if (!torture_close_connection(cli)) {
4333 0 : correct = False;
4334 : }
4335 :
4336 1 : printf("attrib test finished\n");
4337 :
4338 1 : return correct;
4339 : }
4340 :
4341 1 : static NTSTATUS cli_qfilename(
4342 : struct cli_state *cli,
4343 : uint16_t fnum,
4344 : TALLOC_CTX *mem_ctx,
4345 : char **_name)
4346 : {
4347 : uint16_t recv_flags2;
4348 : uint8_t *rdata;
4349 : uint32_t num_rdata;
4350 : NTSTATUS status;
4351 1 : char *name = NULL;
4352 : uint32_t namelen;
4353 :
4354 1 : status = cli_qfileinfo(talloc_tos(), cli, fnum,
4355 : SMB_QUERY_FILE_NAME_INFO,
4356 : 4, CLI_BUFFER_SIZE, &recv_flags2,
4357 : &rdata, &num_rdata);
4358 1 : if (!NT_STATUS_IS_OK(status)) {
4359 0 : return status;
4360 : }
4361 :
4362 1 : namelen = IVAL(rdata, 0);
4363 1 : if (namelen > (num_rdata - 4)) {
4364 0 : TALLOC_FREE(rdata);
4365 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
4366 : }
4367 :
4368 1 : pull_string_talloc(mem_ctx,
4369 : (const char *)rdata,
4370 : recv_flags2,
4371 : &name,
4372 1 : rdata + 4,
4373 : namelen,
4374 : STR_UNICODE);
4375 1 : if (name == NULL) {
4376 0 : status = map_nt_error_from_unix(errno);
4377 0 : TALLOC_FREE(rdata);
4378 0 : return status;
4379 : }
4380 :
4381 1 : *_name = name;
4382 1 : TALLOC_FREE(rdata);
4383 1 : return NT_STATUS_OK;
4384 : }
4385 :
4386 : /*
4387 : This checks a couple of trans2 calls
4388 : */
4389 1 : static bool run_trans2test(int dummy)
4390 : {
4391 : struct cli_state *cli;
4392 : uint16_t fnum;
4393 : off_t size;
4394 : time_t c_time, a_time, m_time;
4395 : struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4396 1 : const char *fname = "\\trans2.tst";
4397 1 : const char *dname = "\\trans2";
4398 1 : const char *fname2 = "\\trans2\\trans2.tst";
4399 1 : char *pname = NULL;
4400 1 : bool correct = True;
4401 : NTSTATUS status;
4402 : uint32_t fs_attr;
4403 : uint64_t ino;
4404 :
4405 1 : printf("starting trans2 test\n");
4406 :
4407 1 : if (!torture_open_connection(&cli, 0)) {
4408 0 : return False;
4409 : }
4410 :
4411 1 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4412 : /* Ensure ino is zero, SMB2 gets a real one. */
4413 0 : ino = 0;
4414 : } else {
4415 : /* Ensure ino is -1, SMB1 never gets a real one. */
4416 1 : ino = (uint64_t)-1;
4417 : }
4418 :
4419 1 : status = cli_get_fs_attr_info(cli, &fs_attr);
4420 1 : if (!NT_STATUS_IS_OK(status)) {
4421 0 : printf("ERROR: cli_get_fs_attr_info returned %s\n",
4422 : nt_errstr(status));
4423 0 : correct = false;
4424 : }
4425 :
4426 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4427 1 : cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4428 1 : status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4429 : &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4430 1 : if (!NT_STATUS_IS_OK(status)) {
4431 0 : printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4432 0 : correct = False;
4433 : }
4434 :
4435 1 : status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4436 1 : if (!NT_STATUS_IS_OK(status)) {
4437 0 : printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4438 0 : correct = False;
4439 : }
4440 1 : else if (strcmp(pname, fname)) {
4441 0 : printf("qfilename gave different name? [%s] [%s]\n",
4442 : fname, pname);
4443 0 : correct = False;
4444 : }
4445 :
4446 1 : cli_close(cli, fnum);
4447 :
4448 1 : sleep(2);
4449 :
4450 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4451 1 : status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4452 : &fnum);
4453 1 : if (!NT_STATUS_IS_OK(status)) {
4454 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4455 0 : return False;
4456 : }
4457 1 : cli_close(cli, fnum);
4458 :
4459 1 : status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4460 : NULL);
4461 1 : if (!NT_STATUS_IS_OK(status)) {
4462 0 : printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4463 0 : correct = False;
4464 : } else {
4465 1 : time_t t = time(NULL);
4466 :
4467 1 : if (c_time != m_time) {
4468 0 : printf("create time=%s", ctime(&c_time));
4469 0 : printf("modify time=%s", ctime(&m_time));
4470 0 : printf("This system appears to have sticky create times\n");
4471 : }
4472 1 : if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4473 0 : printf("access time=%s", ctime(&a_time));
4474 0 : printf("This system appears to set a midnight access time\n");
4475 0 : correct = False;
4476 : }
4477 :
4478 1 : if (labs(m_time - t) > 60*60*24*7) {
4479 0 : printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4480 0 : correct = False;
4481 : }
4482 : }
4483 :
4484 :
4485 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4486 1 : cli_openx(cli, fname,
4487 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4488 1 : cli_close(cli, fnum);
4489 1 : status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
4490 : &m_time_ts, &size, NULL, &ino);
4491 1 : if (!NT_STATUS_IS_OK(status)) {
4492 0 : printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4493 0 : correct = False;
4494 : } else {
4495 1 : if (w_time_ts.tv_sec < 60*60*24*2) {
4496 0 : printf("write time=%s", ctime(&w_time_ts.tv_sec));
4497 0 : printf("This system appears to set a initial 0 write time\n");
4498 0 : correct = False;
4499 : }
4500 1 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4501 : /* SMB2 should always return an inode. */
4502 0 : if (ino == 0) {
4503 0 : printf("SMB2 bad inode (0)\n");
4504 0 : correct = false;
4505 : }
4506 : } else {
4507 : /* SMB1 must always return zero here. */
4508 1 : if (ino != 0) {
4509 0 : printf("SMB1 bad inode (!0)\n");
4510 0 : correct = false;
4511 : }
4512 : }
4513 : }
4514 :
4515 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4516 :
4517 :
4518 : /* check if the server updates the directory modification time
4519 : when creating a new file */
4520 1 : status = cli_mkdir(cli, dname);
4521 1 : if (!NT_STATUS_IS_OK(status)) {
4522 0 : printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4523 0 : correct = False;
4524 : }
4525 1 : sleep(3);
4526 1 : status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4527 : &w_time_ts, &m_time_ts, &size, NULL, NULL);
4528 1 : if (!NT_STATUS_IS_OK(status)) {
4529 0 : printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4530 0 : correct = False;
4531 : }
4532 :
4533 1 : cli_openx(cli, fname2,
4534 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4535 1 : cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4536 1 : cli_close(cli, fnum);
4537 1 : status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4538 : &w_time_ts, &m_time2_ts, &size, NULL, NULL);
4539 1 : if (!NT_STATUS_IS_OK(status)) {
4540 0 : printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4541 0 : correct = False;
4542 : } else {
4543 1 : if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4544 : == 0) {
4545 0 : printf("This system does not update directory modification times\n");
4546 0 : correct = False;
4547 : }
4548 : }
4549 1 : cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4550 1 : cli_rmdir(cli, dname);
4551 :
4552 1 : if (!torture_close_connection(cli)) {
4553 0 : correct = False;
4554 : }
4555 :
4556 1 : printf("trans2 test finished\n");
4557 :
4558 1 : return correct;
4559 : }
4560 :
4561 : /*
4562 : This checks new W2K calls.
4563 : */
4564 :
4565 36 : static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4566 : {
4567 36 : uint8_t *buf = NULL;
4568 : uint32_t len;
4569 : NTSTATUS status;
4570 :
4571 36 : status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4572 : CLI_BUFFER_SIZE, NULL, &buf, &len);
4573 36 : if (!NT_STATUS_IS_OK(status)) {
4574 36 : printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4575 : nt_errstr(status));
4576 : } else {
4577 0 : printf("qfileinfo: level %d, len = %u\n", level, len);
4578 0 : dump_data(0, (uint8_t *)buf, len);
4579 0 : printf("\n");
4580 : }
4581 36 : TALLOC_FREE(buf);
4582 36 : return status;
4583 : }
4584 :
4585 1 : static bool run_w2ktest(int dummy)
4586 : {
4587 : struct cli_state *cli;
4588 : uint16_t fnum;
4589 1 : const char *fname = "\\w2ktest\\w2k.tst";
4590 : int level;
4591 1 : bool correct = True;
4592 :
4593 1 : printf("starting w2k test\n");
4594 :
4595 1 : if (!torture_open_connection(&cli, 0)) {
4596 0 : return False;
4597 : }
4598 :
4599 1 : cli_openx(cli, fname,
4600 : O_RDWR | O_CREAT , DENY_NONE, &fnum);
4601 :
4602 37 : for (level = 1004; level < 1040; level++) {
4603 36 : new_trans(cli, fnum, level);
4604 : }
4605 :
4606 1 : cli_close(cli, fnum);
4607 :
4608 1 : if (!torture_close_connection(cli)) {
4609 0 : correct = False;
4610 : }
4611 :
4612 1 : printf("w2k test finished\n");
4613 :
4614 1 : return correct;
4615 : }
4616 :
4617 :
4618 : /*
4619 : this is a harness for some oplock tests
4620 : */
4621 1 : static bool run_oplock1(int dummy)
4622 : {
4623 : struct cli_state *cli1;
4624 1 : const char *fname = "\\lockt1.lck";
4625 : uint16_t fnum1;
4626 1 : bool correct = True;
4627 : NTSTATUS status;
4628 :
4629 1 : printf("starting oplock test 1\n");
4630 :
4631 1 : if (!torture_open_connection(&cli1, 0)) {
4632 0 : return False;
4633 : }
4634 :
4635 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4636 :
4637 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
4638 :
4639 1 : cli1->use_oplocks = True;
4640 :
4641 1 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4642 : &fnum1);
4643 1 : if (!NT_STATUS_IS_OK(status)) {
4644 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4645 0 : return False;
4646 : }
4647 :
4648 1 : cli1->use_oplocks = False;
4649 :
4650 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4651 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4652 :
4653 1 : status = cli_close(cli1, fnum1);
4654 1 : if (!NT_STATUS_IS_OK(status)) {
4655 0 : printf("close2 failed (%s)\n", nt_errstr(status));
4656 0 : return False;
4657 : }
4658 :
4659 1 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4660 1 : if (!NT_STATUS_IS_OK(status)) {
4661 0 : printf("unlink failed (%s)\n", nt_errstr(status));
4662 0 : return False;
4663 : }
4664 :
4665 1 : if (!torture_close_connection(cli1)) {
4666 0 : correct = False;
4667 : }
4668 :
4669 1 : printf("finished oplock test 1\n");
4670 :
4671 1 : return correct;
4672 : }
4673 :
4674 0 : static bool run_oplock2(int dummy)
4675 : {
4676 : struct cli_state *cli1, *cli2;
4677 0 : const char *fname = "\\lockt2.lck";
4678 : uint16_t fnum1, fnum2;
4679 0 : int saved_use_oplocks = use_oplocks;
4680 : char buf[4];
4681 0 : bool correct = True;
4682 : volatile bool *shared_correct;
4683 : size_t nread;
4684 : NTSTATUS status;
4685 :
4686 0 : shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4687 0 : *shared_correct = True;
4688 :
4689 0 : use_level_II_oplocks = True;
4690 0 : use_oplocks = True;
4691 :
4692 0 : printf("starting oplock test 2\n");
4693 :
4694 0 : if (!torture_open_connection(&cli1, 0)) {
4695 0 : use_level_II_oplocks = False;
4696 0 : use_oplocks = saved_use_oplocks;
4697 0 : return False;
4698 : }
4699 :
4700 0 : if (!torture_open_connection(&cli2, 1)) {
4701 0 : use_level_II_oplocks = False;
4702 0 : use_oplocks = saved_use_oplocks;
4703 0 : return False;
4704 : }
4705 :
4706 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4707 :
4708 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
4709 0 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
4710 :
4711 0 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4712 : &fnum1);
4713 0 : if (!NT_STATUS_IS_OK(status)) {
4714 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4715 0 : return False;
4716 : }
4717 :
4718 : /* Don't need the globals any more. */
4719 0 : use_level_II_oplocks = False;
4720 0 : use_oplocks = saved_use_oplocks;
4721 :
4722 0 : if (fork() == 0) {
4723 : /* Child code */
4724 0 : status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4725 0 : if (!NT_STATUS_IS_OK(status)) {
4726 0 : printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4727 0 : *shared_correct = False;
4728 0 : exit(0);
4729 : }
4730 :
4731 0 : sleep(2);
4732 :
4733 0 : status = cli_close(cli2, fnum2);
4734 0 : if (!NT_STATUS_IS_OK(status)) {
4735 0 : printf("close2 failed (%s)\n", nt_errstr(status));
4736 0 : *shared_correct = False;
4737 : }
4738 :
4739 0 : exit(0);
4740 : }
4741 :
4742 0 : sleep(2);
4743 :
4744 : /* Ensure cli1 processes the break. Empty file should always return 0
4745 : * bytes. */
4746 0 : status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4747 0 : if (!NT_STATUS_IS_OK(status)) {
4748 0 : printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4749 0 : correct = false;
4750 0 : } else if (nread != 0) {
4751 0 : printf("read on empty fnum1 failed. recv %ld expected %d\n",
4752 : (unsigned long)nread, 0);
4753 0 : correct = false;
4754 : }
4755 :
4756 : /* Should now be at level II. */
4757 : /* Test if sending a write locks causes a break to none. */
4758 0 : status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4759 0 : if (!NT_STATUS_IS_OK(status)) {
4760 0 : printf("lock failed (%s)\n", nt_errstr(status));
4761 0 : correct = False;
4762 : }
4763 :
4764 0 : cli_unlock(cli1, fnum1, 0, 4);
4765 :
4766 0 : sleep(2);
4767 :
4768 0 : status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4769 0 : if (!NT_STATUS_IS_OK(status)) {
4770 0 : printf("lock failed (%s)\n", nt_errstr(status));
4771 0 : correct = False;
4772 : }
4773 :
4774 0 : cli_unlock(cli1, fnum1, 0, 4);
4775 :
4776 0 : sleep(2);
4777 :
4778 0 : cli_read(cli1, fnum1, buf, 0, 4, NULL);
4779 :
4780 0 : status = cli_close(cli1, fnum1);
4781 0 : if (!NT_STATUS_IS_OK(status)) {
4782 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4783 0 : correct = False;
4784 : }
4785 :
4786 0 : sleep(4);
4787 :
4788 0 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4789 0 : if (!NT_STATUS_IS_OK(status)) {
4790 0 : printf("unlink failed (%s)\n", nt_errstr(status));
4791 0 : correct = False;
4792 : }
4793 :
4794 0 : if (!torture_close_connection(cli1)) {
4795 0 : correct = False;
4796 : }
4797 :
4798 0 : if (!*shared_correct) {
4799 0 : correct = False;
4800 : }
4801 :
4802 0 : printf("finished oplock test 2\n");
4803 :
4804 0 : return correct;
4805 : }
4806 :
4807 : struct oplock4_state {
4808 : struct tevent_context *ev;
4809 : struct cli_state *cli;
4810 : bool *got_break;
4811 : uint16_t *fnum2;
4812 : };
4813 :
4814 : static void oplock4_got_break(struct tevent_req *req);
4815 : static void oplock4_got_open(struct tevent_req *req);
4816 :
4817 1 : static bool run_oplock4(int dummy)
4818 : {
4819 : struct tevent_context *ev;
4820 : struct cli_state *cli1, *cli2;
4821 : struct tevent_req *oplock_req, *open_req;
4822 1 : const char *fname = "\\lockt4.lck";
4823 1 : const char *fname_ln = "\\lockt4_ln.lck";
4824 : uint16_t fnum1, fnum2;
4825 1 : int saved_use_oplocks = use_oplocks;
4826 : NTSTATUS status;
4827 1 : bool correct = true;
4828 :
4829 : bool got_break;
4830 :
4831 : struct oplock4_state *state;
4832 :
4833 1 : printf("starting oplock test 4\n");
4834 :
4835 1 : if (!torture_open_connection(&cli1, 0)) {
4836 0 : use_level_II_oplocks = false;
4837 0 : use_oplocks = saved_use_oplocks;
4838 0 : return false;
4839 : }
4840 :
4841 1 : if (!torture_open_connection(&cli2, 1)) {
4842 0 : use_level_II_oplocks = false;
4843 0 : use_oplocks = saved_use_oplocks;
4844 0 : return false;
4845 : }
4846 :
4847 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4848 1 : cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4849 :
4850 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
4851 1 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
4852 :
4853 : /* Create the file. */
4854 1 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4855 : &fnum1);
4856 1 : if (!NT_STATUS_IS_OK(status)) {
4857 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4858 0 : return false;
4859 : }
4860 :
4861 1 : status = cli_close(cli1, fnum1);
4862 1 : if (!NT_STATUS_IS_OK(status)) {
4863 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4864 0 : return false;
4865 : }
4866 :
4867 : /* Now create a hardlink. */
4868 1 : status = cli_hardlink(cli1, fname, fname_ln);
4869 1 : if (!NT_STATUS_IS_OK(status)) {
4870 0 : printf("nt hardlink failed (%s)\n", nt_errstr(status));
4871 0 : return false;
4872 : }
4873 :
4874 : /* Prove that opening hardlinks cause deny modes to conflict. */
4875 1 : status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4876 1 : if (!NT_STATUS_IS_OK(status)) {
4877 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4878 0 : return false;
4879 : }
4880 :
4881 1 : status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4882 1 : if (NT_STATUS_IS_OK(status)) {
4883 0 : printf("open of %s succeeded - should fail with sharing violation.\n",
4884 : fname_ln);
4885 0 : return false;
4886 : }
4887 :
4888 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4889 0 : printf("open of %s should fail with sharing violation. Got %s\n",
4890 : fname_ln, nt_errstr(status));
4891 0 : return false;
4892 : }
4893 :
4894 1 : status = cli_close(cli1, fnum1);
4895 1 : if (!NT_STATUS_IS_OK(status)) {
4896 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4897 0 : return false;
4898 : }
4899 :
4900 1 : cli1->use_oplocks = true;
4901 1 : cli2->use_oplocks = true;
4902 :
4903 1 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4904 1 : if (!NT_STATUS_IS_OK(status)) {
4905 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4906 0 : return false;
4907 : }
4908 :
4909 1 : ev = samba_tevent_context_init(talloc_tos());
4910 1 : if (ev == NULL) {
4911 0 : printf("tevent_context_init failed\n");
4912 0 : return false;
4913 : }
4914 :
4915 1 : state = talloc(ev, struct oplock4_state);
4916 1 : if (state == NULL) {
4917 0 : printf("talloc failed\n");
4918 0 : return false;
4919 : }
4920 1 : state->ev = ev;
4921 1 : state->cli = cli1;
4922 1 : state->got_break = &got_break;
4923 1 : state->fnum2 = &fnum2;
4924 :
4925 1 : oplock_req = cli_smb_oplock_break_waiter_send(
4926 : talloc_tos(), ev, cli1);
4927 1 : if (oplock_req == NULL) {
4928 0 : printf("cli_smb_oplock_break_waiter_send failed\n");
4929 0 : return false;
4930 : }
4931 1 : tevent_req_set_callback(oplock_req, oplock4_got_break, state);
4932 :
4933 1 : open_req = cli_openx_send(
4934 : talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
4935 1 : if (open_req == NULL) {
4936 0 : printf("cli_openx_send failed\n");
4937 0 : return false;
4938 : }
4939 1 : tevent_req_set_callback(open_req, oplock4_got_open, state);
4940 :
4941 1 : got_break = false;
4942 1 : fnum2 = 0xffff;
4943 :
4944 8 : while (!got_break || fnum2 == 0xffff) {
4945 : int ret;
4946 7 : ret = tevent_loop_once(ev);
4947 7 : if (ret == -1) {
4948 0 : printf("tevent_loop_once failed: %s\n",
4949 0 : strerror(errno));
4950 0 : return false;
4951 : }
4952 : }
4953 :
4954 1 : status = cli_close(cli2, fnum2);
4955 1 : if (!NT_STATUS_IS_OK(status)) {
4956 0 : printf("close2 failed (%s)\n", nt_errstr(status));
4957 0 : correct = false;
4958 : }
4959 :
4960 1 : status = cli_close(cli1, fnum1);
4961 1 : if (!NT_STATUS_IS_OK(status)) {
4962 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4963 0 : correct = false;
4964 : }
4965 :
4966 1 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4967 1 : if (!NT_STATUS_IS_OK(status)) {
4968 0 : printf("unlink failed (%s)\n", nt_errstr(status));
4969 0 : correct = false;
4970 : }
4971 :
4972 1 : status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4973 1 : if (!NT_STATUS_IS_OK(status)) {
4974 0 : printf("unlink failed (%s)\n", nt_errstr(status));
4975 0 : correct = false;
4976 : }
4977 :
4978 1 : if (!torture_close_connection(cli1)) {
4979 0 : correct = false;
4980 : }
4981 :
4982 1 : if (!got_break) {
4983 0 : correct = false;
4984 : }
4985 :
4986 1 : printf("finished oplock test 4\n");
4987 :
4988 1 : return correct;
4989 : }
4990 :
4991 1 : static void oplock4_got_break(struct tevent_req *req)
4992 : {
4993 1 : struct oplock4_state *state = tevent_req_callback_data(
4994 : req, struct oplock4_state);
4995 : uint16_t fnum;
4996 : uint8_t level;
4997 : NTSTATUS status;
4998 :
4999 1 : status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
5000 1 : TALLOC_FREE(req);
5001 1 : if (!NT_STATUS_IS_OK(status)) {
5002 0 : printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5003 : nt_errstr(status));
5004 0 : return;
5005 : }
5006 1 : *state->got_break = true;
5007 :
5008 1 : req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5009 : NO_OPLOCK);
5010 1 : if (req == NULL) {
5011 0 : printf("cli_oplock_ack_send failed\n");
5012 0 : return;
5013 : }
5014 : }
5015 :
5016 1 : static void oplock4_got_open(struct tevent_req *req)
5017 : {
5018 1 : struct oplock4_state *state = tevent_req_callback_data(
5019 : req, struct oplock4_state);
5020 : NTSTATUS status;
5021 :
5022 1 : status = cli_openx_recv(req, state->fnum2);
5023 1 : if (!NT_STATUS_IS_OK(status)) {
5024 0 : printf("cli_openx_recv returned %s\n", nt_errstr(status));
5025 0 : *state->fnum2 = 0xffff;
5026 : }
5027 1 : }
5028 :
5029 : #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5030 :
5031 : struct oplock5_state {
5032 : int pipe_down_fd;
5033 : };
5034 :
5035 : /*
5036 : * Async open the file that has a kernel oplock, do an echo to get
5037 : * that 100% across, close the file to signal to the child fd that the
5038 : * oplock can be dropped, wait for the open reply.
5039 : */
5040 :
5041 : static void oplock5_opened(struct tevent_req *subreq);
5042 : static void oplock5_pong(struct tevent_req *subreq);
5043 : static void oplock5_timedout(struct tevent_req *subreq);
5044 :
5045 0 : static struct tevent_req *oplock5_send(
5046 : TALLOC_CTX *mem_ctx,
5047 : struct tevent_context *ev,
5048 : struct cli_state *cli,
5049 : const char *fname,
5050 : int pipe_down_fd)
5051 : {
5052 0 : struct tevent_req *req = NULL, *subreq = NULL;
5053 0 : struct oplock5_state *state = NULL;
5054 : static uint8_t data = 0;
5055 :
5056 0 : req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5057 0 : if (req == NULL) {
5058 0 : return NULL;
5059 : }
5060 0 : state->pipe_down_fd = pipe_down_fd;
5061 :
5062 0 : subreq = cli_ntcreate_send(
5063 : state,
5064 : ev,
5065 : cli,
5066 : fname,
5067 : 0, /* CreatFlags */
5068 : SEC_FILE_READ_DATA, /* DesiredAccess */
5069 : FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
5070 : FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5071 : FILE_OPEN, /* CreateDisposition */
5072 : FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5073 : 0, /* Impersonation */
5074 : 0); /* SecurityFlags */
5075 0 : if (tevent_req_nomem(subreq, req)) {
5076 0 : return tevent_req_post(req, ev);
5077 : }
5078 0 : tevent_req_set_callback(subreq, oplock5_opened, req);
5079 :
5080 0 : subreq = cli_echo_send(
5081 : state,
5082 : ev,
5083 : cli,
5084 : 1,
5085 0 : (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5086 0 : if (tevent_req_nomem(subreq, req)) {
5087 0 : return tevent_req_post(req, ev);
5088 : }
5089 0 : tevent_req_set_callback(subreq, oplock5_pong, req);
5090 :
5091 0 : subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5092 0 : if (tevent_req_nomem(subreq, req)) {
5093 0 : return tevent_req_post(req, ev);
5094 : }
5095 0 : tevent_req_set_callback(subreq, oplock5_timedout, req);
5096 :
5097 0 : return req;
5098 : }
5099 :
5100 0 : static void oplock5_opened(struct tevent_req *subreq)
5101 : {
5102 0 : struct tevent_req *req = tevent_req_callback_data(
5103 : subreq, struct tevent_req);
5104 : NTSTATUS status;
5105 : uint16_t fnum;
5106 :
5107 0 : status = cli_ntcreate_recv(subreq, &fnum, NULL);
5108 0 : TALLOC_FREE(subreq);
5109 0 : if (tevent_req_nterror(req, status)) {
5110 0 : return;
5111 : }
5112 0 : tevent_req_done(req);
5113 : }
5114 :
5115 0 : static void oplock5_pong(struct tevent_req *subreq)
5116 : {
5117 0 : struct tevent_req *req = tevent_req_callback_data(
5118 : subreq, struct tevent_req);
5119 0 : struct oplock5_state *state = tevent_req_data(
5120 : req, struct oplock5_state);
5121 : NTSTATUS status;
5122 :
5123 0 : status = cli_echo_recv(subreq);
5124 0 : TALLOC_FREE(subreq);
5125 0 : if (tevent_req_nterror(req, status)) {
5126 0 : return;
5127 : }
5128 :
5129 0 : close(state->pipe_down_fd);
5130 : }
5131 :
5132 0 : static void oplock5_timedout(struct tevent_req *subreq)
5133 : {
5134 0 : struct tevent_req *req = tevent_req_callback_data(
5135 : subreq, struct tevent_req);
5136 : bool ok;
5137 :
5138 0 : ok = tevent_wakeup_recv(subreq);
5139 0 : TALLOC_FREE(subreq);
5140 0 : if (!ok) {
5141 0 : tevent_req_oom(req);
5142 0 : return;
5143 : }
5144 0 : tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5145 : }
5146 :
5147 0 : static NTSTATUS oplock5_recv(struct tevent_req *req)
5148 : {
5149 0 : return tevent_req_simple_recv_ntstatus(req);
5150 : }
5151 :
5152 0 : static bool run_oplock5(int dummy)
5153 : {
5154 0 : struct tevent_context *ev = NULL;
5155 0 : struct tevent_req *req = NULL;
5156 0 : struct cli_state *cli = NULL;
5157 0 : const char *fname = "oplock5.txt";
5158 : int pipe_down[2], pipe_up[2];
5159 : pid_t child_pid;
5160 0 : uint8_t c = '\0';
5161 : NTSTATUS status;
5162 : int ret;
5163 : bool ok;
5164 :
5165 0 : printf("starting oplock5\n");
5166 :
5167 0 : if (local_path == NULL) {
5168 0 : d_fprintf(stderr, "oplock5 must be given a local path via "
5169 : "-l <localpath>\n");
5170 0 : return false;
5171 : }
5172 :
5173 0 : ret = pipe(pipe_down);
5174 0 : if (ret == -1) {
5175 0 : d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5176 0 : return false;
5177 : }
5178 0 : ret = pipe(pipe_up);
5179 0 : if (ret == -1) {
5180 0 : d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5181 0 : return false;
5182 : }
5183 :
5184 0 : child_pid = fork();
5185 0 : if (child_pid == -1) {
5186 0 : d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5187 0 : return false;
5188 : }
5189 :
5190 0 : if (child_pid == 0) {
5191 0 : char *local_file = NULL;
5192 : int fd;
5193 :
5194 0 : close(pipe_down[1]);
5195 0 : close(pipe_up[0]);
5196 :
5197 0 : local_file = talloc_asprintf(
5198 0 : talloc_tos(), "%s/%s", local_path, fname);
5199 0 : if (local_file == 0) {
5200 0 : c = 1;
5201 0 : goto do_write;
5202 : }
5203 0 : fd = open(local_file, O_RDWR|O_CREAT, 0644);
5204 0 : if (fd == -1) {
5205 0 : d_fprintf(stderr,
5206 : "open(%s) in child failed: %s\n",
5207 : local_file,
5208 0 : strerror(errno));
5209 0 : c = 2;
5210 0 : goto do_write;
5211 : }
5212 :
5213 0 : signal(SIGIO, SIG_IGN);
5214 :
5215 0 : ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5216 0 : if (ret == -1) {
5217 0 : d_fprintf(stderr,
5218 : "SETLEASE in child failed: %s\n",
5219 0 : strerror(errno));
5220 0 : c = 3;
5221 0 : goto do_write;
5222 : }
5223 :
5224 0 : do_write:
5225 0 : ret = sys_write(pipe_up[1], &c, sizeof(c));
5226 0 : if (ret == -1) {
5227 0 : d_fprintf(stderr,
5228 : "sys_write failed: %s\n",
5229 0 : strerror(errno));
5230 0 : exit(4);
5231 : }
5232 0 : ret = sys_read(pipe_down[0], &c, sizeof(c));
5233 0 : if (ret == -1) {
5234 0 : d_fprintf(stderr,
5235 : "sys_read failed: %s\n",
5236 0 : strerror(errno));
5237 0 : exit(5);
5238 : }
5239 0 : exit(0);
5240 : }
5241 :
5242 0 : close(pipe_up[1]);
5243 0 : close(pipe_down[0]);
5244 :
5245 0 : ret = sys_read(pipe_up[0], &c, sizeof(c));
5246 0 : if (ret != 1) {
5247 0 : d_fprintf(stderr,
5248 : "sys_read failed: %s\n",
5249 0 : strerror(errno));
5250 0 : return false;
5251 : }
5252 0 : if (c != 0) {
5253 0 : d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5254 0 : return false;
5255 : }
5256 :
5257 0 : ok = torture_open_connection(&cli, 0);
5258 0 : if (!ok) {
5259 0 : d_fprintf(stderr, "torture_open_connection failed\n");
5260 0 : return false;
5261 : }
5262 :
5263 0 : ev = samba_tevent_context_init(talloc_tos());
5264 0 : if (ev == NULL) {
5265 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
5266 0 : return false;
5267 : }
5268 :
5269 0 : req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5270 0 : if (req == NULL) {
5271 0 : d_fprintf(stderr, "oplock5_send failed\n");
5272 0 : return false;
5273 : }
5274 :
5275 0 : ok = tevent_req_poll_ntstatus(req, ev, &status);
5276 0 : if (!ok) {
5277 0 : d_fprintf(stderr,
5278 : "tevent_req_poll_ntstatus failed: %s\n",
5279 : nt_errstr(status));
5280 0 : return false;
5281 : }
5282 :
5283 0 : status = oplock5_recv(req);
5284 0 : TALLOC_FREE(req);
5285 0 : if (!NT_STATUS_IS_OK(status)) {
5286 0 : d_fprintf(stderr,
5287 : "oplock5 failed: %s\n",
5288 : nt_errstr(status));
5289 0 : return false;
5290 : }
5291 :
5292 0 : return true;
5293 : }
5294 :
5295 : #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5296 :
5297 : /*
5298 : Test delete on close semantics.
5299 : */
5300 1 : static bool run_deletetest(int dummy)
5301 : {
5302 1 : struct cli_state *cli1 = NULL;
5303 1 : struct cli_state *cli2 = NULL;
5304 1 : const char *fname = "\\delete.file";
5305 1 : uint16_t fnum1 = (uint16_t)-1;
5306 1 : uint16_t fnum2 = (uint16_t)-1;
5307 1 : bool correct = false;
5308 : NTSTATUS status;
5309 :
5310 1 : printf("starting delete test\n");
5311 :
5312 1 : if (!torture_open_connection(&cli1, 0)) {
5313 0 : return False;
5314 : }
5315 :
5316 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
5317 :
5318 : /* Test 1 - this should delete the file on close. */
5319 :
5320 1 : cli_setatr(cli1, fname, 0, 0);
5321 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5322 :
5323 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5324 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5325 : FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5326 1 : if (!NT_STATUS_IS_OK(status)) {
5327 0 : printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5328 0 : goto fail;
5329 : }
5330 :
5331 1 : status = cli_close(cli1, fnum1);
5332 1 : if (!NT_STATUS_IS_OK(status)) {
5333 0 : printf("[1] close failed (%s)\n", nt_errstr(status));
5334 0 : goto fail;
5335 : }
5336 :
5337 1 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5338 1 : if (NT_STATUS_IS_OK(status)) {
5339 0 : printf("[1] open of %s succeeded (should fail)\n", fname);
5340 0 : goto fail;
5341 : }
5342 :
5343 1 : printf("first delete on close test succeeded.\n");
5344 :
5345 : /* Test 2 - this should delete the file on close. */
5346 :
5347 1 : cli_setatr(cli1, fname, 0, 0);
5348 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5349 :
5350 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5351 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5352 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5353 1 : if (!NT_STATUS_IS_OK(status)) {
5354 0 : printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5355 0 : goto fail;
5356 : }
5357 :
5358 1 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5359 1 : if (!NT_STATUS_IS_OK(status)) {
5360 0 : printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5361 0 : goto fail;
5362 : }
5363 :
5364 1 : status = cli_close(cli1, fnum1);
5365 1 : if (!NT_STATUS_IS_OK(status)) {
5366 0 : printf("[2] close failed (%s)\n", nt_errstr(status));
5367 0 : goto fail;
5368 : }
5369 :
5370 1 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5371 1 : if (NT_STATUS_IS_OK(status)) {
5372 0 : printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5373 0 : status = cli_close(cli1, fnum1);
5374 0 : if (!NT_STATUS_IS_OK(status)) {
5375 0 : printf("[2] close failed (%s)\n", nt_errstr(status));
5376 : }
5377 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5378 0 : goto fail;
5379 : }
5380 :
5381 1 : printf("second delete on close test succeeded.\n");
5382 :
5383 : /* Test 3 - ... */
5384 1 : cli_setatr(cli1, fname, 0, 0);
5385 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5386 :
5387 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5388 : FILE_ATTRIBUTE_NORMAL,
5389 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5390 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5391 1 : if (!NT_STATUS_IS_OK(status)) {
5392 0 : printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5393 0 : goto fail;
5394 : }
5395 :
5396 : /* This should fail with a sharing violation - open for delete is only compatible
5397 : with SHARE_DELETE. */
5398 :
5399 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5400 : FILE_ATTRIBUTE_NORMAL,
5401 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5402 : FILE_OPEN, 0, 0, &fnum2, NULL);
5403 1 : if (NT_STATUS_IS_OK(status)) {
5404 0 : printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
5405 0 : goto fail;
5406 : }
5407 :
5408 : /* This should succeed. */
5409 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5410 : FILE_ATTRIBUTE_NORMAL,
5411 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5412 : FILE_OPEN, 0, 0, &fnum2, NULL);
5413 1 : if (!NT_STATUS_IS_OK(status)) {
5414 0 : printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5415 0 : goto fail;
5416 : }
5417 :
5418 1 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5419 1 : if (!NT_STATUS_IS_OK(status)) {
5420 0 : printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5421 0 : goto fail;
5422 : }
5423 :
5424 1 : status = cli_close(cli1, fnum1);
5425 1 : if (!NT_STATUS_IS_OK(status)) {
5426 0 : printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5427 0 : goto fail;
5428 : }
5429 :
5430 1 : status = cli_close(cli1, fnum2);
5431 1 : if (!NT_STATUS_IS_OK(status)) {
5432 0 : printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5433 0 : goto fail;
5434 : }
5435 :
5436 : /* This should fail - file should no longer be there. */
5437 :
5438 1 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5439 1 : if (NT_STATUS_IS_OK(status)) {
5440 0 : printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5441 0 : status = cli_close(cli1, fnum1);
5442 0 : if (!NT_STATUS_IS_OK(status)) {
5443 0 : printf("[3] close failed (%s)\n", nt_errstr(status));
5444 : }
5445 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5446 0 : goto fail;
5447 : }
5448 :
5449 1 : printf("third delete on close test succeeded.\n");
5450 :
5451 : /* Test 4 ... */
5452 1 : cli_setatr(cli1, fname, 0, 0);
5453 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5454 :
5455 1 : status = cli_ntcreate(cli1, fname, 0,
5456 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5457 : FILE_ATTRIBUTE_NORMAL,
5458 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5459 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5460 1 : if (!NT_STATUS_IS_OK(status)) {
5461 0 : printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5462 0 : goto fail;
5463 : }
5464 :
5465 : /* This should succeed. */
5466 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5467 : FILE_ATTRIBUTE_NORMAL,
5468 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5469 : FILE_OPEN, 0, 0, &fnum2, NULL);
5470 1 : if (!NT_STATUS_IS_OK(status)) {
5471 0 : printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5472 0 : goto fail;
5473 : }
5474 :
5475 1 : status = cli_close(cli1, fnum2);
5476 1 : if (!NT_STATUS_IS_OK(status)) {
5477 0 : printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5478 0 : goto fail;
5479 : }
5480 :
5481 1 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5482 1 : if (!NT_STATUS_IS_OK(status)) {
5483 0 : printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5484 0 : goto fail;
5485 : }
5486 :
5487 : /* This should fail - no more opens once delete on close set. */
5488 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5489 : FILE_ATTRIBUTE_NORMAL,
5490 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5491 : FILE_OPEN, 0, 0, &fnum2, NULL);
5492 1 : if (NT_STATUS_IS_OK(status)) {
5493 0 : printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
5494 0 : goto fail;
5495 : }
5496 :
5497 1 : status = cli_close(cli1, fnum1);
5498 1 : if (!NT_STATUS_IS_OK(status)) {
5499 0 : printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5500 0 : goto fail;
5501 : }
5502 :
5503 1 : printf("fourth delete on close test succeeded.\n");
5504 :
5505 : /* Test 5 ... */
5506 1 : cli_setatr(cli1, fname, 0, 0);
5507 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5508 :
5509 1 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5510 1 : if (!NT_STATUS_IS_OK(status)) {
5511 0 : printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5512 0 : goto fail;
5513 : }
5514 :
5515 : /* This should fail - only allowed on NT opens with DELETE access. */
5516 :
5517 1 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5518 1 : if (NT_STATUS_IS_OK(status)) {
5519 0 : printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5520 0 : goto fail;
5521 : }
5522 :
5523 1 : status = cli_close(cli1, fnum1);
5524 1 : if (!NT_STATUS_IS_OK(status)) {
5525 0 : printf("[5] close failed (%s)\n", nt_errstr(status));
5526 0 : goto fail;
5527 : }
5528 :
5529 1 : printf("fifth delete on close test succeeded.\n");
5530 :
5531 : /* Test 6 ... */
5532 1 : cli_setatr(cli1, fname, 0, 0);
5533 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5534 :
5535 1 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5536 : FILE_ATTRIBUTE_NORMAL,
5537 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5538 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5539 1 : if (!NT_STATUS_IS_OK(status)) {
5540 0 : printf("[6] open of %s failed (%s)\n", fname,
5541 : nt_errstr(status));
5542 0 : goto fail;
5543 : }
5544 :
5545 : /* This should fail - only allowed on NT opens with DELETE access. */
5546 :
5547 1 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5548 1 : if (NT_STATUS_IS_OK(status)) {
5549 0 : printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5550 0 : goto fail;
5551 : }
5552 :
5553 1 : status = cli_close(cli1, fnum1);
5554 1 : if (!NT_STATUS_IS_OK(status)) {
5555 0 : printf("[6] close failed (%s)\n", nt_errstr(status));
5556 0 : goto fail;
5557 : }
5558 :
5559 1 : printf("sixth delete on close test succeeded.\n");
5560 :
5561 : /* Test 7 ... */
5562 1 : cli_setatr(cli1, fname, 0, 0);
5563 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5564 :
5565 1 : status = cli_ntcreate(cli1, fname, 0,
5566 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5567 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5568 : 0, 0, &fnum1, NULL);
5569 1 : if (!NT_STATUS_IS_OK(status)) {
5570 0 : printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5571 0 : goto fail;
5572 : }
5573 :
5574 1 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5575 1 : if (!NT_STATUS_IS_OK(status)) {
5576 0 : printf("[7] setting delete_on_close on file failed !\n");
5577 0 : goto fail;
5578 : }
5579 :
5580 1 : status = cli_nt_delete_on_close(cli1, fnum1, false);
5581 1 : if (!NT_STATUS_IS_OK(status)) {
5582 0 : printf("[7] unsetting delete_on_close on file failed !\n");
5583 0 : goto fail;
5584 : }
5585 :
5586 1 : status = cli_close(cli1, fnum1);
5587 1 : if (!NT_STATUS_IS_OK(status)) {
5588 0 : printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5589 0 : goto fail;
5590 : }
5591 :
5592 : /* This next open should succeed - we reset the flag. */
5593 1 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5594 1 : if (!NT_STATUS_IS_OK(status)) {
5595 0 : printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5596 0 : goto fail;
5597 : }
5598 :
5599 1 : status = cli_close(cli1, fnum1);
5600 1 : if (!NT_STATUS_IS_OK(status)) {
5601 0 : printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5602 0 : goto fail;
5603 : }
5604 :
5605 1 : printf("seventh delete on close test succeeded.\n");
5606 :
5607 : /* Test 8 ... */
5608 1 : cli_setatr(cli1, fname, 0, 0);
5609 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5610 :
5611 1 : if (!torture_open_connection(&cli2, 1)) {
5612 0 : printf("[8] failed to open second connection.\n");
5613 0 : goto fail;
5614 : }
5615 :
5616 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
5617 :
5618 1 : status = cli_ntcreate(cli1, fname, 0,
5619 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5620 : FILE_ATTRIBUTE_NORMAL,
5621 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5622 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5623 1 : if (!NT_STATUS_IS_OK(status)) {
5624 0 : printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5625 0 : goto fail;
5626 : }
5627 :
5628 1 : status = cli_ntcreate(cli2, fname, 0,
5629 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5630 : FILE_ATTRIBUTE_NORMAL,
5631 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5632 : FILE_OPEN, 0, 0, &fnum2, NULL);
5633 1 : if (!NT_STATUS_IS_OK(status)) {
5634 0 : printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5635 0 : goto fail;
5636 : }
5637 :
5638 1 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5639 1 : if (!NT_STATUS_IS_OK(status)) {
5640 0 : printf("[8] setting delete_on_close on file failed !\n");
5641 0 : goto fail;
5642 : }
5643 :
5644 1 : status = cli_close(cli1, fnum1);
5645 1 : if (!NT_STATUS_IS_OK(status)) {
5646 0 : printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5647 0 : goto fail;
5648 : }
5649 :
5650 1 : status = cli_close(cli2, fnum2);
5651 1 : if (!NT_STATUS_IS_OK(status)) {
5652 0 : printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5653 0 : goto fail;
5654 : }
5655 :
5656 : /* This should fail.. */
5657 1 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5658 1 : if (NT_STATUS_IS_OK(status)) {
5659 0 : printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5660 0 : goto fail;
5661 : }
5662 :
5663 1 : printf("eighth delete on close test succeeded.\n");
5664 :
5665 : /* Test 9 ... */
5666 :
5667 : /* This should fail - we need to set DELETE_ACCESS. */
5668 1 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5669 : FILE_ATTRIBUTE_NORMAL,
5670 : FILE_SHARE_NONE,
5671 : FILE_OVERWRITE_IF,
5672 : FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5673 1 : if (NT_STATUS_IS_OK(status)) {
5674 0 : printf("[9] open of %s succeeded should have failed!\n", fname);
5675 0 : goto fail;
5676 : }
5677 :
5678 1 : printf("ninth delete on close test succeeded.\n");
5679 :
5680 : /* Test 10 ... */
5681 :
5682 1 : status = cli_ntcreate(cli1, fname, 0,
5683 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5684 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5685 : FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5686 : 0, &fnum1, NULL);
5687 1 : if (!NT_STATUS_IS_OK(status)) {
5688 0 : printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5689 0 : goto fail;
5690 : }
5691 :
5692 : /* This should delete the file. */
5693 1 : status = cli_close(cli1, fnum1);
5694 1 : if (!NT_STATUS_IS_OK(status)) {
5695 0 : printf("[10] close failed (%s)\n", nt_errstr(status));
5696 0 : goto fail;
5697 : }
5698 :
5699 : /* This should fail.. */
5700 1 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5701 1 : if (NT_STATUS_IS_OK(status)) {
5702 0 : printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5703 0 : goto fail;
5704 : }
5705 :
5706 1 : printf("tenth delete on close test succeeded.\n");
5707 :
5708 : /* Test 11 ... */
5709 :
5710 1 : cli_setatr(cli1, fname, 0, 0);
5711 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5712 :
5713 : /* Can we open a read-only file with delete access? */
5714 :
5715 : /* Create a readonly file. */
5716 1 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5717 : FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5718 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5719 1 : if (!NT_STATUS_IS_OK(status)) {
5720 0 : printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5721 0 : goto fail;
5722 : }
5723 :
5724 1 : status = cli_close(cli1, fnum1);
5725 1 : if (!NT_STATUS_IS_OK(status)) {
5726 0 : printf("[11] close failed (%s)\n", nt_errstr(status));
5727 0 : goto fail;
5728 : }
5729 :
5730 : /* Now try open for delete access. */
5731 1 : status = cli_ntcreate(cli1, fname, 0,
5732 : FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5733 : 0,
5734 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5735 : FILE_OPEN, 0, 0, &fnum1, NULL);
5736 1 : if (!NT_STATUS_IS_OK(status)) {
5737 0 : printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5738 0 : goto fail;
5739 : }
5740 :
5741 1 : cli_close(cli1, fnum1);
5742 :
5743 1 : printf("eleventh delete on close test succeeded.\n");
5744 :
5745 : /*
5746 : * Test 12
5747 : * like test 4 but with initial delete on close
5748 : */
5749 :
5750 1 : cli_setatr(cli1, fname, 0, 0);
5751 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5752 :
5753 1 : status = cli_ntcreate(cli1, fname, 0,
5754 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5755 : FILE_ATTRIBUTE_NORMAL,
5756 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5757 : FILE_OVERWRITE_IF,
5758 : FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5759 1 : if (!NT_STATUS_IS_OK(status)) {
5760 0 : printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5761 0 : goto fail;
5762 : }
5763 :
5764 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5765 : FILE_ATTRIBUTE_NORMAL,
5766 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5767 : FILE_OPEN, 0, 0, &fnum2, NULL);
5768 1 : if (!NT_STATUS_IS_OK(status)) {
5769 0 : printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5770 0 : goto fail;
5771 : }
5772 :
5773 1 : status = cli_close(cli1, fnum2);
5774 1 : if (!NT_STATUS_IS_OK(status)) {
5775 0 : printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5776 0 : goto fail;
5777 : }
5778 :
5779 1 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5780 1 : if (!NT_STATUS_IS_OK(status)) {
5781 0 : printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5782 0 : goto fail;
5783 : }
5784 :
5785 : /* This should fail - no more opens once delete on close set. */
5786 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5787 : FILE_ATTRIBUTE_NORMAL,
5788 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5789 : FILE_OPEN, 0, 0, &fnum2, NULL);
5790 1 : if (NT_STATUS_IS_OK(status)) {
5791 0 : printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5792 0 : goto fail;
5793 : }
5794 :
5795 1 : status = cli_nt_delete_on_close(cli1, fnum1, false);
5796 1 : if (!NT_STATUS_IS_OK(status)) {
5797 0 : printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5798 0 : goto fail;
5799 : }
5800 :
5801 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5802 : FILE_ATTRIBUTE_NORMAL,
5803 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5804 : FILE_OPEN, 0, 0, &fnum2, NULL);
5805 1 : if (!NT_STATUS_IS_OK(status)) {
5806 0 : printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5807 0 : goto fail;
5808 : }
5809 :
5810 1 : status = cli_close(cli1, fnum2);
5811 1 : if (!NT_STATUS_IS_OK(status)) {
5812 0 : printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5813 0 : goto fail;
5814 : }
5815 :
5816 1 : status = cli_close(cli1, fnum1);
5817 1 : if (!NT_STATUS_IS_OK(status)) {
5818 0 : printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5819 0 : goto fail;
5820 : }
5821 :
5822 : /*
5823 : * setting delete on close on the handle does
5824 : * not unset the initial delete on close...
5825 : */
5826 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5827 : FILE_ATTRIBUTE_NORMAL,
5828 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5829 : FILE_OPEN, 0, 0, &fnum2, NULL);
5830 1 : if (NT_STATUS_IS_OK(status)) {
5831 0 : printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5832 0 : goto fail;
5833 1 : } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5834 0 : printf("ntcreate returned %s, expected "
5835 : "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5836 : nt_errstr(status));
5837 0 : goto fail;
5838 : }
5839 :
5840 1 : printf("twelfth delete on close test succeeded.\n");
5841 :
5842 :
5843 1 : printf("finished delete test\n");
5844 :
5845 1 : correct = true;
5846 :
5847 1 : fail:
5848 : /* FIXME: This will crash if we aborted before cli2 got
5849 : * intialized, because these functions don't handle
5850 : * uninitialized connections. */
5851 :
5852 1 : if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5853 1 : if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5854 1 : cli_setatr(cli1, fname, 0, 0);
5855 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5856 :
5857 1 : if (cli1 && !torture_close_connection(cli1)) {
5858 0 : correct = False;
5859 : }
5860 1 : if (cli2 && !torture_close_connection(cli2)) {
5861 0 : correct = False;
5862 : }
5863 1 : return correct;
5864 : }
5865 :
5866 : struct delete_stream_state {
5867 : bool closed;
5868 : };
5869 :
5870 : static void delete_stream_unlinked(struct tevent_req *subreq);
5871 : static void delete_stream_closed(struct tevent_req *subreq);
5872 :
5873 1 : static struct tevent_req *delete_stream_send(
5874 : TALLOC_CTX *mem_ctx,
5875 : struct tevent_context *ev,
5876 : struct cli_state *cli,
5877 : const char *base_fname,
5878 : uint16_t stream_fnum)
5879 : {
5880 1 : struct tevent_req *req = NULL, *subreq = NULL;
5881 1 : struct delete_stream_state *state = NULL;
5882 :
5883 1 : req = tevent_req_create(
5884 : mem_ctx, &state, struct delete_stream_state);
5885 1 : if (req == NULL) {
5886 0 : return NULL;
5887 : }
5888 :
5889 1 : subreq = cli_unlink_send(
5890 : state,
5891 : ev,
5892 : cli,
5893 : base_fname,
5894 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5895 1 : if (tevent_req_nomem(subreq, req)) {
5896 0 : return tevent_req_post(req, ev);
5897 : }
5898 1 : tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5899 :
5900 1 : subreq = cli_close_send(state, ev, cli, stream_fnum);
5901 1 : if (tevent_req_nomem(subreq, req)) {
5902 0 : return tevent_req_post(req, ev);
5903 : }
5904 1 : tevent_req_set_callback(subreq, delete_stream_closed, req);
5905 :
5906 1 : return req;
5907 : }
5908 :
5909 1 : static void delete_stream_unlinked(struct tevent_req *subreq)
5910 : {
5911 1 : struct tevent_req *req = tevent_req_callback_data(
5912 : subreq, struct tevent_req);
5913 1 : struct delete_stream_state *state = tevent_req_data(
5914 : req, struct delete_stream_state);
5915 : NTSTATUS status;
5916 :
5917 1 : status = cli_unlink_recv(subreq);
5918 1 : TALLOC_FREE(subreq);
5919 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5920 0 : printf("cli_unlink returned %s\n",
5921 : nt_errstr(status));
5922 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5923 0 : return;
5924 : }
5925 1 : if (!state->closed) {
5926 : /* close reply should have come in first */
5927 0 : printf("Not closed\n");
5928 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5929 0 : return;
5930 : }
5931 1 : tevent_req_done(req);
5932 : }
5933 :
5934 1 : static void delete_stream_closed(struct tevent_req *subreq)
5935 : {
5936 1 : struct tevent_req *req = tevent_req_callback_data(
5937 : subreq, struct tevent_req);
5938 1 : struct delete_stream_state *state = tevent_req_data(
5939 : req, struct delete_stream_state);
5940 : NTSTATUS status;
5941 :
5942 1 : status = cli_close_recv(subreq);
5943 1 : TALLOC_FREE(subreq);
5944 1 : if (tevent_req_nterror(req, status)) {
5945 0 : return;
5946 : }
5947 : /* also waiting for the unlink to come back */
5948 1 : state->closed = true;
5949 : }
5950 :
5951 1 : static NTSTATUS delete_stream_recv(struct tevent_req *req)
5952 : {
5953 1 : return tevent_req_simple_recv_ntstatus(req);
5954 : }
5955 :
5956 1 : static bool run_delete_stream(int dummy)
5957 : {
5958 1 : struct tevent_context *ev = NULL;
5959 1 : struct tevent_req *req = NULL;
5960 1 : struct cli_state *cli = NULL;
5961 1 : const char fname[] = "delete_stream";
5962 1 : const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
5963 : uint16_t fnum1, fnum2;
5964 : NTSTATUS status;
5965 : bool ok;
5966 :
5967 1 : printf("Starting stream delete test\n");
5968 :
5969 1 : ok = torture_open_connection(&cli, 0);
5970 1 : if (!ok) {
5971 0 : return false;
5972 : }
5973 :
5974 1 : cli_setatr(cli, fname, 0, 0);
5975 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5976 :
5977 : /* Create the file. */
5978 1 : status = cli_ntcreate(
5979 : cli,
5980 : fname,
5981 : 0,
5982 : READ_CONTROL_ACCESS,
5983 : 0,
5984 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5985 : FILE_CREATE,
5986 : 0x0,
5987 : 0x0,
5988 : &fnum1,
5989 : NULL);
5990 1 : if (!NT_STATUS_IS_OK(status)) {
5991 0 : d_fprintf(stderr,
5992 : "cli_ntcreate of %s failed (%s)\n",
5993 : fname,
5994 : nt_errstr(status));
5995 0 : return false;
5996 : }
5997 1 : status = cli_close(cli, fnum1);
5998 1 : if (!NT_STATUS_IS_OK(status)) {
5999 0 : d_fprintf(stderr,
6000 : "cli_close of %s failed (%s)\n",
6001 : fname,
6002 : nt_errstr(status));
6003 0 : return false;
6004 : }
6005 :
6006 : /* Now create the stream. */
6007 1 : status = cli_ntcreate(
6008 : cli,
6009 : fname_stream,
6010 : 0,
6011 : FILE_WRITE_DATA,
6012 : 0,
6013 : FILE_SHARE_READ|FILE_SHARE_WRITE,
6014 : FILE_CREATE,
6015 : 0x0,
6016 : 0x0,
6017 : &fnum1,
6018 : NULL);
6019 :
6020 1 : if (!NT_STATUS_IS_OK(status)) {
6021 0 : d_fprintf(stderr,
6022 : "cli_ntcreate of %s failed (%s)\n",
6023 : fname_stream,
6024 : nt_errstr(status));
6025 0 : return false;
6026 : }
6027 :
6028 : /* open it a second time */
6029 :
6030 1 : status = cli_ntcreate(
6031 : cli,
6032 : fname_stream,
6033 : 0,
6034 : FILE_WRITE_DATA,
6035 : 0,
6036 : FILE_SHARE_READ|FILE_SHARE_WRITE,
6037 : FILE_OPEN,
6038 : 0x0,
6039 : 0x0,
6040 : &fnum2,
6041 : NULL);
6042 :
6043 1 : if (!NT_STATUS_IS_OK(status)) {
6044 0 : d_fprintf(stderr,
6045 : "2nd cli_ntcreate of %s failed (%s)\n",
6046 : fname_stream,
6047 : nt_errstr(status));
6048 0 : return false;
6049 : }
6050 :
6051 1 : ev = samba_tevent_context_init(talloc_tos());
6052 1 : if (ev == NULL) {
6053 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
6054 0 : return false;
6055 : }
6056 :
6057 1 : req = delete_stream_send(ev, ev, cli, fname, fnum1);
6058 1 : if (req == NULL) {
6059 0 : d_fprintf(stderr, "delete_stream_send failed\n");
6060 0 : return false;
6061 : }
6062 :
6063 1 : ok = tevent_req_poll_ntstatus(req, ev, &status);
6064 1 : if (!ok) {
6065 0 : d_fprintf(stderr,
6066 : "tevent_req_poll_ntstatus failed: %s\n",
6067 : nt_errstr(status));
6068 0 : return false;
6069 : }
6070 :
6071 1 : status = delete_stream_recv(req);
6072 1 : TALLOC_FREE(req);
6073 1 : if (!NT_STATUS_IS_OK(status)) {
6074 0 : d_fprintf(stderr,
6075 : "delete_stream failed: %s\n",
6076 : nt_errstr(status));
6077 0 : return false;
6078 : }
6079 :
6080 1 : status = cli_close(cli, fnum2);
6081 1 : if (!NT_STATUS_IS_OK(status)) {
6082 0 : d_fprintf(stderr,
6083 : "close failed: %s\n",
6084 : nt_errstr(status));
6085 0 : return false;
6086 : }
6087 :
6088 1 : status = cli_unlink(
6089 : cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6090 1 : if (!NT_STATUS_IS_OK(status)) {
6091 0 : d_fprintf(stderr,
6092 : "unlink failed: %s\n",
6093 : nt_errstr(status));
6094 0 : return false;
6095 : }
6096 :
6097 1 : return true;
6098 : }
6099 :
6100 : /*
6101 : Exercise delete on close semantics - use on the PRINT1 share in torture
6102 : testing.
6103 : */
6104 0 : static bool run_delete_print_test(int dummy)
6105 : {
6106 0 : struct cli_state *cli1 = NULL;
6107 0 : const char *fname = "print_delete.file";
6108 0 : uint16_t fnum1 = (uint16_t)-1;
6109 0 : bool correct = false;
6110 0 : const char *buf = "print file data\n";
6111 : NTSTATUS status;
6112 :
6113 0 : printf("starting print delete test\n");
6114 :
6115 0 : if (!torture_open_connection(&cli1, 0)) {
6116 0 : return false;
6117 : }
6118 :
6119 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
6120 :
6121 0 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6122 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6123 : 0, 0, &fnum1, NULL);
6124 0 : if (!NT_STATUS_IS_OK(status)) {
6125 0 : printf("open of %s failed (%s)\n",
6126 : fname,
6127 : nt_errstr(status));
6128 0 : goto fail;
6129 : }
6130 :
6131 0 : status = cli_writeall(cli1,
6132 : fnum1,
6133 : 0,
6134 : (const uint8_t *)buf,
6135 : 0, /* offset */
6136 : strlen(buf), /* size */
6137 : NULL);
6138 0 : if (!NT_STATUS_IS_OK(status)) {
6139 0 : printf("writing print file data failed (%s)\n",
6140 : nt_errstr(status));
6141 0 : goto fail;
6142 : }
6143 :
6144 0 : status = cli_nt_delete_on_close(cli1, fnum1, true);
6145 0 : if (!NT_STATUS_IS_OK(status)) {
6146 0 : printf("setting delete_on_close failed (%s)\n",
6147 : nt_errstr(status));
6148 0 : goto fail;
6149 : }
6150 :
6151 0 : status = cli_close(cli1, fnum1);
6152 0 : if (!NT_STATUS_IS_OK(status)) {
6153 0 : printf("close failed (%s)\n", nt_errstr(status));
6154 0 : goto fail;
6155 : }
6156 :
6157 0 : printf("finished print delete test\n");
6158 :
6159 0 : correct = true;
6160 :
6161 0 : fail:
6162 :
6163 0 : if (fnum1 != (uint16_t)-1) {
6164 0 : cli_close(cli1, fnum1);
6165 : }
6166 :
6167 0 : if (cli1 && !torture_close_connection(cli1)) {
6168 0 : correct = false;
6169 : }
6170 0 : return correct;
6171 : }
6172 :
6173 0 : static bool run_deletetest_ln(int dummy)
6174 : {
6175 : struct cli_state *cli;
6176 0 : const char *fname = "\\delete1";
6177 0 : const char *fname_ln = "\\delete1_ln";
6178 : uint16_t fnum;
6179 : uint16_t fnum1;
6180 : NTSTATUS status;
6181 0 : bool correct = true;
6182 : time_t t;
6183 :
6184 0 : printf("starting deletetest-ln\n");
6185 :
6186 0 : if (!torture_open_connection(&cli, 0)) {
6187 0 : return false;
6188 : }
6189 :
6190 0 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6191 0 : cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6192 :
6193 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6194 :
6195 : /* Create the file. */
6196 0 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6197 0 : if (!NT_STATUS_IS_OK(status)) {
6198 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6199 0 : return false;
6200 : }
6201 :
6202 0 : status = cli_close(cli, fnum);
6203 0 : if (!NT_STATUS_IS_OK(status)) {
6204 0 : printf("close1 failed (%s)\n", nt_errstr(status));
6205 0 : return false;
6206 : }
6207 :
6208 : /* Now create a hardlink. */
6209 0 : status = cli_hardlink(cli, fname, fname_ln);
6210 0 : if (!NT_STATUS_IS_OK(status)) {
6211 0 : printf("nt hardlink failed (%s)\n", nt_errstr(status));
6212 0 : return false;
6213 : }
6214 :
6215 : /* Open the original file. */
6216 0 : status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6217 : FILE_ATTRIBUTE_NORMAL,
6218 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6219 : FILE_OPEN_IF, 0, 0, &fnum, NULL);
6220 0 : if (!NT_STATUS_IS_OK(status)) {
6221 0 : printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6222 0 : return false;
6223 : }
6224 :
6225 : /* Unlink the hard link path. */
6226 0 : status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6227 : FILE_ATTRIBUTE_NORMAL,
6228 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6229 : FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6230 0 : if (!NT_STATUS_IS_OK(status)) {
6231 0 : printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6232 0 : return false;
6233 : }
6234 0 : status = cli_nt_delete_on_close(cli, fnum1, true);
6235 0 : if (!NT_STATUS_IS_OK(status)) {
6236 0 : d_printf("(%s) failed to set delete_on_close %s: %s\n",
6237 : __location__, fname_ln, nt_errstr(status));
6238 0 : return false;
6239 : }
6240 :
6241 0 : status = cli_close(cli, fnum1);
6242 0 : if (!NT_STATUS_IS_OK(status)) {
6243 0 : printf("close %s failed (%s)\n",
6244 : fname_ln, nt_errstr(status));
6245 0 : return false;
6246 : }
6247 :
6248 0 : status = cli_close(cli, fnum);
6249 0 : if (!NT_STATUS_IS_OK(status)) {
6250 0 : printf("close %s failed (%s)\n",
6251 : fname, nt_errstr(status));
6252 0 : return false;
6253 : }
6254 :
6255 : /* Ensure the original file is still there. */
6256 0 : status = cli_getatr(cli, fname, NULL, NULL, &t);
6257 0 : if (!NT_STATUS_IS_OK(status)) {
6258 0 : printf("%s getatr on file %s failed (%s)\n",
6259 : __location__,
6260 : fname,
6261 : nt_errstr(status));
6262 0 : correct = False;
6263 : }
6264 :
6265 : /* Ensure the link path is gone. */
6266 0 : status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6267 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6268 0 : printf("%s, getatr for file %s returned wrong error code %s "
6269 : "- should have been deleted\n",
6270 : __location__,
6271 : fname_ln, nt_errstr(status));
6272 0 : correct = False;
6273 : }
6274 :
6275 0 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6276 0 : cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6277 :
6278 0 : if (!torture_close_connection(cli)) {
6279 0 : correct = false;
6280 : }
6281 :
6282 0 : printf("finished deletetest-ln\n");
6283 :
6284 0 : return correct;
6285 : }
6286 :
6287 : /*
6288 : print out server properties
6289 : */
6290 1 : static bool run_properties(int dummy)
6291 : {
6292 : struct cli_state *cli;
6293 1 : bool correct = True;
6294 :
6295 1 : printf("starting properties test\n");
6296 :
6297 1 : ZERO_STRUCT(cli);
6298 :
6299 1 : if (!torture_open_connection(&cli, 0)) {
6300 0 : return False;
6301 : }
6302 :
6303 1 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6304 :
6305 1 : d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6306 :
6307 1 : if (!torture_close_connection(cli)) {
6308 0 : correct = False;
6309 : }
6310 :
6311 1 : return correct;
6312 : }
6313 :
6314 :
6315 :
6316 : /* FIRST_DESIRED_ACCESS 0xf019f */
6317 : #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6318 : FILE_READ_EA| /* 0xf */ \
6319 : FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
6320 : FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
6321 : DELETE_ACCESS|READ_CONTROL_ACCESS|\
6322 : WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
6323 : /* SECOND_DESIRED_ACCESS 0xe0080 */
6324 : #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6325 : READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6326 : WRITE_OWNER_ACCESS /* 0xe0000 */
6327 :
6328 : #if 0
6329 : #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6330 : READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6331 : FILE_READ_DATA|\
6332 : WRITE_OWNER_ACCESS /* */
6333 : #endif
6334 :
6335 : /*
6336 : Test ntcreate calls made by xcopy
6337 : */
6338 1 : static bool run_xcopy(int dummy)
6339 : {
6340 : static struct cli_state *cli1;
6341 1 : const char *fname = "\\test.txt";
6342 1 : bool correct = True;
6343 : uint16_t fnum1, fnum2;
6344 : NTSTATUS status;
6345 :
6346 1 : printf("starting xcopy test\n");
6347 :
6348 1 : if (!torture_open_connection(&cli1, 0)) {
6349 0 : return False;
6350 : }
6351 :
6352 1 : status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6353 : FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6354 : FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6355 1 : if (!NT_STATUS_IS_OK(status)) {
6356 0 : printf("First open failed - %s\n", nt_errstr(status));
6357 0 : return False;
6358 : }
6359 :
6360 1 : status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6361 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6362 : FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6363 1 : if (!NT_STATUS_IS_OK(status)) {
6364 0 : printf("second open failed - %s\n", nt_errstr(status));
6365 0 : return False;
6366 : }
6367 :
6368 1 : if (!torture_close_connection(cli1)) {
6369 0 : correct = False;
6370 : }
6371 :
6372 1 : return correct;
6373 : }
6374 :
6375 : /*
6376 : Test rename on files open with share delete and no share delete.
6377 : */
6378 1 : static bool run_rename(int dummy)
6379 : {
6380 : static struct cli_state *cli1;
6381 1 : const char *fname = "\\test.txt";
6382 1 : const char *fname1 = "\\test1.txt";
6383 1 : bool correct = True;
6384 : uint16_t fnum1;
6385 : uint32_t attr;
6386 : NTSTATUS status;
6387 :
6388 1 : printf("starting rename test\n");
6389 :
6390 1 : if (!torture_open_connection(&cli1, 0)) {
6391 0 : return False;
6392 : }
6393 :
6394 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6395 1 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6396 :
6397 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6398 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6399 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6400 1 : if (!NT_STATUS_IS_OK(status)) {
6401 0 : printf("First open failed - %s\n", nt_errstr(status));
6402 0 : return False;
6403 : }
6404 :
6405 1 : status = cli_rename(cli1, fname, fname1, false);
6406 1 : if (!NT_STATUS_IS_OK(status)) {
6407 1 : printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6408 : } else {
6409 0 : printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6410 0 : correct = False;
6411 : }
6412 :
6413 1 : status = cli_close(cli1, fnum1);
6414 1 : if (!NT_STATUS_IS_OK(status)) {
6415 0 : printf("close - 1 failed (%s)\n", nt_errstr(status));
6416 0 : return False;
6417 : }
6418 :
6419 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6420 1 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6421 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6422 : #if 0
6423 : FILE_SHARE_DELETE|FILE_SHARE_NONE,
6424 : #else
6425 : FILE_SHARE_DELETE|FILE_SHARE_READ,
6426 : #endif
6427 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6428 1 : if (!NT_STATUS_IS_OK(status)) {
6429 0 : printf("Second open failed - %s\n", nt_errstr(status));
6430 0 : return False;
6431 : }
6432 :
6433 1 : status = cli_rename(cli1, fname, fname1, false);
6434 1 : if (!NT_STATUS_IS_OK(status)) {
6435 0 : printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6436 0 : correct = False;
6437 : } else {
6438 1 : printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6439 : }
6440 :
6441 1 : status = cli_close(cli1, fnum1);
6442 1 : if (!NT_STATUS_IS_OK(status)) {
6443 0 : printf("close - 2 failed (%s)\n", nt_errstr(status));
6444 0 : return False;
6445 : }
6446 :
6447 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6448 1 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6449 :
6450 1 : status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6451 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6452 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6453 1 : if (!NT_STATUS_IS_OK(status)) {
6454 0 : printf("Third open failed - %s\n", nt_errstr(status));
6455 0 : return False;
6456 : }
6457 :
6458 :
6459 1 : status = cli_rename(cli1, fname, fname1, false);
6460 1 : if (!NT_STATUS_IS_OK(status)) {
6461 0 : printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6462 0 : correct = False;
6463 : } else {
6464 1 : printf("Third rename succeeded (SHARE_NONE)\n");
6465 : }
6466 :
6467 1 : status = cli_close(cli1, fnum1);
6468 1 : if (!NT_STATUS_IS_OK(status)) {
6469 0 : printf("close - 3 failed (%s)\n", nt_errstr(status));
6470 0 : return False;
6471 : }
6472 :
6473 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6474 1 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6475 :
6476 : /*----*/
6477 :
6478 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6479 : FILE_ATTRIBUTE_NORMAL,
6480 : FILE_SHARE_READ | FILE_SHARE_WRITE,
6481 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6482 1 : if (!NT_STATUS_IS_OK(status)) {
6483 0 : printf("Fourth open failed - %s\n", nt_errstr(status));
6484 0 : return False;
6485 : }
6486 :
6487 1 : status = cli_rename(cli1, fname, fname1, false);
6488 1 : if (!NT_STATUS_IS_OK(status)) {
6489 1 : printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6490 : } else {
6491 0 : printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6492 0 : correct = False;
6493 : }
6494 :
6495 1 : status = cli_close(cli1, fnum1);
6496 1 : if (!NT_STATUS_IS_OK(status)) {
6497 0 : printf("close - 4 failed (%s)\n", nt_errstr(status));
6498 0 : return False;
6499 : }
6500 :
6501 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6502 1 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6503 :
6504 : /*--*/
6505 :
6506 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6507 : FILE_ATTRIBUTE_NORMAL,
6508 : FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6509 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6510 1 : if (!NT_STATUS_IS_OK(status)) {
6511 0 : printf("Fifth open failed - %s\n", nt_errstr(status));
6512 0 : return False;
6513 : }
6514 :
6515 1 : status = cli_rename(cli1, fname, fname1, false);
6516 1 : if (!NT_STATUS_IS_OK(status)) {
6517 0 : printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6518 0 : correct = False;
6519 : } else {
6520 1 : printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6521 : }
6522 :
6523 : /*--*/
6524 1 : status = cli_close(cli1, fnum1);
6525 1 : if (!NT_STATUS_IS_OK(status)) {
6526 0 : printf("close - 5 failed (%s)\n", nt_errstr(status));
6527 0 : return False;
6528 : }
6529 :
6530 : /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6531 1 : status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6532 1 : if (!NT_STATUS_IS_OK(status)) {
6533 0 : printf("getatr on file %s failed - %s ! \n",
6534 : fname1, nt_errstr(status));
6535 0 : correct = False;
6536 : } else {
6537 1 : if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6538 0 : printf("Renamed file %s has wrong attr 0x%x "
6539 : "(should be 0x%x)\n",
6540 : fname1,
6541 : attr,
6542 : (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6543 0 : correct = False;
6544 : } else {
6545 1 : printf("Renamed file %s has archive bit set\n", fname1);
6546 : }
6547 : }
6548 :
6549 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6550 1 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6551 :
6552 1 : if (!torture_close_connection(cli1)) {
6553 0 : correct = False;
6554 : }
6555 :
6556 1 : return correct;
6557 : }
6558 :
6559 : /*
6560 : Test rename into a directory with an ACL denying it.
6561 : */
6562 0 : static bool run_rename_access(int dummy)
6563 : {
6564 : static struct cli_state *cli = NULL;
6565 : static struct cli_state *posix_cli = NULL;
6566 0 : const char *src = "test.txt";
6567 0 : const char *dname = "dir";
6568 0 : const char *dst = "dir\\test.txt";
6569 0 : const char *dsrc = "test.dir";
6570 0 : const char *ddst = "dir\\test.dir";
6571 0 : uint16_t fnum = (uint16_t)-1;
6572 0 : struct security_descriptor *sd = NULL;
6573 0 : struct security_descriptor *newsd = NULL;
6574 : NTSTATUS status;
6575 0 : TALLOC_CTX *frame = NULL;
6576 :
6577 0 : frame = talloc_stackframe();
6578 0 : printf("starting rename access test\n");
6579 :
6580 : /* Windows connection. */
6581 0 : if (!torture_open_connection(&cli, 0)) {
6582 0 : goto fail;
6583 : }
6584 :
6585 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6586 :
6587 : /* Posix connection. */
6588 0 : if (!torture_open_connection(&posix_cli, 0)) {
6589 0 : goto fail;
6590 : }
6591 :
6592 0 : smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6593 :
6594 0 : status = torture_setup_unix_extensions(posix_cli);
6595 0 : if (!NT_STATUS_IS_OK(status)) {
6596 0 : goto fail;
6597 : }
6598 :
6599 : /* Start with a clean slate. */
6600 0 : cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6601 0 : cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6602 0 : cli_rmdir(cli, dsrc);
6603 0 : cli_rmdir(cli, ddst);
6604 0 : cli_rmdir(cli, dname);
6605 :
6606 : /*
6607 : * Setup the destination directory with a DENY ACE to
6608 : * prevent new files within it.
6609 : */
6610 0 : status = cli_ntcreate(cli,
6611 : dname,
6612 : 0,
6613 : FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6614 : WRITE_DAC_ACCESS|FILE_READ_DATA|
6615 : WRITE_OWNER_ACCESS,
6616 : FILE_ATTRIBUTE_DIRECTORY,
6617 : FILE_SHARE_READ|FILE_SHARE_WRITE,
6618 : FILE_CREATE,
6619 : FILE_DIRECTORY_FILE,
6620 : 0,
6621 : &fnum,
6622 : NULL);
6623 0 : if (!NT_STATUS_IS_OK(status)) {
6624 0 : printf("Create of %s - %s\n", dname, nt_errstr(status));
6625 0 : goto fail;
6626 : }
6627 :
6628 0 : status = cli_query_secdesc(cli,
6629 : fnum,
6630 : frame,
6631 : &sd);
6632 0 : if (!NT_STATUS_IS_OK(status)) {
6633 0 : printf("cli_query_secdesc failed for %s (%s)\n",
6634 : dname, nt_errstr(status));
6635 0 : goto fail;
6636 : }
6637 :
6638 0 : newsd = security_descriptor_dacl_create(frame,
6639 : 0,
6640 : NULL,
6641 : NULL,
6642 : SID_WORLD,
6643 : SEC_ACE_TYPE_ACCESS_DENIED,
6644 : SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6645 : 0,
6646 : NULL);
6647 0 : if (newsd == NULL) {
6648 0 : goto fail;
6649 : }
6650 0 : sd->dacl = security_acl_concatenate(frame,
6651 0 : newsd->dacl,
6652 0 : sd->dacl);
6653 0 : if (sd->dacl == NULL) {
6654 0 : goto fail;
6655 : }
6656 0 : status = cli_set_secdesc(cli, fnum, sd);
6657 0 : if (!NT_STATUS_IS_OK(status)) {
6658 0 : printf("cli_set_secdesc failed for %s (%s)\n",
6659 : dname, nt_errstr(status));
6660 0 : goto fail;
6661 : }
6662 0 : status = cli_close(cli, fnum);
6663 0 : if (!NT_STATUS_IS_OK(status)) {
6664 0 : printf("close failed for %s (%s)\n",
6665 : dname, nt_errstr(status));
6666 0 : goto fail;
6667 : }
6668 : /* Now go around the back and chmod to 777 via POSIX. */
6669 0 : status = cli_posix_chmod(posix_cli, dname, 0777);
6670 0 : if (!NT_STATUS_IS_OK(status)) {
6671 0 : printf("cli_posix_chmod failed for %s (%s)\n",
6672 : dname, nt_errstr(status));
6673 0 : goto fail;
6674 : }
6675 :
6676 : /* Check we can't create a file within dname via Windows. */
6677 0 : status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6678 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6679 0 : cli_close(posix_cli, fnum);
6680 0 : printf("Create of %s should be ACCESS denied, was %s\n",
6681 : dst, nt_errstr(status));
6682 0 : goto fail;
6683 : }
6684 :
6685 : /* Make the sample file/directory. */
6686 0 : status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6687 0 : if (!NT_STATUS_IS_OK(status)) {
6688 0 : printf("open of %s failed (%s)\n", src, nt_errstr(status));
6689 0 : goto fail;
6690 : }
6691 0 : status = cli_close(cli, fnum);
6692 0 : if (!NT_STATUS_IS_OK(status)) {
6693 0 : printf("cli_close failed (%s)\n", nt_errstr(status));
6694 0 : goto fail;
6695 : }
6696 :
6697 0 : status = cli_mkdir(cli, dsrc);
6698 0 : if (!NT_STATUS_IS_OK(status)) {
6699 0 : printf("cli_mkdir of %s failed (%s)\n",
6700 : dsrc, nt_errstr(status));
6701 0 : goto fail;
6702 : }
6703 :
6704 : /*
6705 : * OK - renames of the new file and directory into the
6706 : * dst directory should fail.
6707 : */
6708 :
6709 0 : status = cli_rename(cli, src, dst, false);
6710 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6711 0 : printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6712 : src, dst, nt_errstr(status));
6713 0 : goto fail;
6714 : }
6715 0 : status = cli_rename(cli, dsrc, ddst, false);
6716 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6717 0 : printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6718 : src, dst, nt_errstr(status));
6719 0 : goto fail;
6720 : }
6721 :
6722 0 : TALLOC_FREE(frame);
6723 0 : return true;
6724 :
6725 0 : fail:
6726 :
6727 0 : if (posix_cli) {
6728 0 : torture_close_connection(posix_cli);
6729 : }
6730 :
6731 0 : if (cli) {
6732 0 : if (fnum != (uint16_t)-1) {
6733 0 : cli_close(cli, fnum);
6734 : }
6735 0 : cli_unlink(cli, src,
6736 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6737 0 : cli_unlink(cli, dst,
6738 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6739 0 : cli_rmdir(cli, dsrc);
6740 0 : cli_rmdir(cli, ddst);
6741 0 : cli_rmdir(cli, dname);
6742 :
6743 0 : torture_close_connection(cli);
6744 : }
6745 :
6746 0 : TALLOC_FREE(frame);
6747 0 : return false;
6748 : }
6749 :
6750 : /*
6751 : Test owner rights ACE.
6752 : */
6753 0 : static bool run_owner_rights(int dummy)
6754 : {
6755 : static struct cli_state *cli = NULL;
6756 0 : const char *fname = "owner_rights.txt";
6757 0 : uint16_t fnum = (uint16_t)-1;
6758 0 : struct security_descriptor *sd = NULL;
6759 0 : struct security_descriptor *newsd = NULL;
6760 : NTSTATUS status;
6761 0 : TALLOC_CTX *frame = NULL;
6762 :
6763 0 : frame = talloc_stackframe();
6764 0 : printf("starting owner rights test\n");
6765 :
6766 : /* Windows connection. */
6767 0 : if (!torture_open_connection(&cli, 0)) {
6768 0 : goto fail;
6769 : }
6770 :
6771 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6772 :
6773 : /* Start with a clean slate. */
6774 0 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6775 :
6776 : /* Create the test file. */
6777 : /* Now try and open for read and write-dac. */
6778 0 : status = cli_ntcreate(cli,
6779 : fname,
6780 : 0,
6781 : GENERIC_ALL_ACCESS,
6782 : FILE_ATTRIBUTE_NORMAL,
6783 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6784 : FILE_SHARE_DELETE,
6785 : FILE_CREATE,
6786 : 0,
6787 : 0,
6788 : &fnum,
6789 : NULL);
6790 0 : if (!NT_STATUS_IS_OK(status)) {
6791 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
6792 0 : goto fail;
6793 : }
6794 :
6795 : /* Get the original SD. */
6796 0 : status = cli_query_secdesc(cli,
6797 : fnum,
6798 : frame,
6799 : &sd);
6800 0 : if (!NT_STATUS_IS_OK(status)) {
6801 0 : printf("cli_query_secdesc failed for %s (%s)\n",
6802 : fname, nt_errstr(status));
6803 0 : goto fail;
6804 : }
6805 :
6806 : /*
6807 : * Add an "owner-rights" ACE denying WRITE_DATA,
6808 : * and an "owner-rights" ACE allowing READ_DATA.
6809 : */
6810 :
6811 0 : newsd = security_descriptor_dacl_create(frame,
6812 : 0,
6813 : NULL,
6814 : NULL,
6815 : SID_OWNER_RIGHTS,
6816 : SEC_ACE_TYPE_ACCESS_DENIED,
6817 : FILE_WRITE_DATA,
6818 : 0,
6819 : SID_OWNER_RIGHTS,
6820 : SEC_ACE_TYPE_ACCESS_ALLOWED,
6821 : FILE_READ_DATA,
6822 : 0,
6823 : NULL);
6824 0 : if (newsd == NULL) {
6825 0 : goto fail;
6826 : }
6827 0 : sd->dacl = security_acl_concatenate(frame,
6828 0 : newsd->dacl,
6829 0 : sd->dacl);
6830 0 : if (sd->dacl == NULL) {
6831 0 : goto fail;
6832 : }
6833 0 : status = cli_set_secdesc(cli, fnum, sd);
6834 0 : if (!NT_STATUS_IS_OK(status)) {
6835 0 : printf("cli_set_secdesc failed for %s (%s)\n",
6836 : fname, nt_errstr(status));
6837 0 : goto fail;
6838 : }
6839 0 : status = cli_close(cli, fnum);
6840 0 : if (!NT_STATUS_IS_OK(status)) {
6841 0 : printf("close failed for %s (%s)\n",
6842 : fname, nt_errstr(status));
6843 0 : goto fail;
6844 : }
6845 0 : fnum = (uint16_t)-1;
6846 :
6847 : /* Try and open for FILE_WRITE_DATA */
6848 0 : status = cli_ntcreate(cli,
6849 : fname,
6850 : 0,
6851 : FILE_WRITE_DATA,
6852 : FILE_ATTRIBUTE_NORMAL,
6853 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6854 : FILE_SHARE_DELETE,
6855 : FILE_OPEN,
6856 : 0,
6857 : 0,
6858 : &fnum,
6859 : NULL);
6860 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6861 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
6862 0 : goto fail;
6863 : }
6864 :
6865 : /* Now try and open for FILE_READ_DATA */
6866 0 : status = cli_ntcreate(cli,
6867 : fname,
6868 : 0,
6869 : FILE_READ_DATA,
6870 : FILE_ATTRIBUTE_NORMAL,
6871 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6872 : FILE_SHARE_DELETE,
6873 : FILE_OPEN,
6874 : 0,
6875 : 0,
6876 : &fnum,
6877 : NULL);
6878 0 : if (!NT_STATUS_IS_OK(status)) {
6879 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
6880 0 : goto fail;
6881 : }
6882 :
6883 0 : status = cli_close(cli, fnum);
6884 0 : if (!NT_STATUS_IS_OK(status)) {
6885 0 : printf("close failed for %s (%s)\n",
6886 : fname, nt_errstr(status));
6887 0 : goto fail;
6888 : }
6889 :
6890 : /* Restore clean slate. */
6891 0 : TALLOC_FREE(sd);
6892 0 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6893 :
6894 : /* Create the test file. */
6895 0 : status = cli_ntcreate(cli,
6896 : fname,
6897 : 0,
6898 : GENERIC_ALL_ACCESS,
6899 : FILE_ATTRIBUTE_NORMAL,
6900 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6901 : FILE_SHARE_DELETE,
6902 : FILE_CREATE,
6903 : 0,
6904 : 0,
6905 : &fnum,
6906 : NULL);
6907 0 : if (!NT_STATUS_IS_OK(status)) {
6908 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
6909 0 : goto fail;
6910 : }
6911 :
6912 : /* Get the original SD. */
6913 0 : status = cli_query_secdesc(cli,
6914 : fnum,
6915 : frame,
6916 : &sd);
6917 0 : if (!NT_STATUS_IS_OK(status)) {
6918 0 : printf("cli_query_secdesc failed for %s (%s)\n",
6919 : fname, nt_errstr(status));
6920 0 : goto fail;
6921 : }
6922 :
6923 : /*
6924 : * Add an "owner-rights ACE denying WRITE_DATA,
6925 : * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6926 : */
6927 :
6928 0 : newsd = security_descriptor_dacl_create(frame,
6929 : 0,
6930 : NULL,
6931 : NULL,
6932 : SID_OWNER_RIGHTS,
6933 : SEC_ACE_TYPE_ACCESS_DENIED,
6934 : FILE_WRITE_DATA,
6935 : 0,
6936 : SID_OWNER_RIGHTS,
6937 : SEC_ACE_TYPE_ACCESS_ALLOWED,
6938 : FILE_READ_DATA|FILE_WRITE_DATA,
6939 : 0,
6940 : NULL);
6941 0 : if (newsd == NULL) {
6942 0 : goto fail;
6943 : }
6944 0 : sd->dacl = security_acl_concatenate(frame,
6945 0 : newsd->dacl,
6946 0 : sd->dacl);
6947 0 : if (sd->dacl == NULL) {
6948 0 : goto fail;
6949 : }
6950 0 : status = cli_set_secdesc(cli, fnum, sd);
6951 0 : if (!NT_STATUS_IS_OK(status)) {
6952 0 : printf("cli_set_secdesc failed for %s (%s)\n",
6953 : fname, nt_errstr(status));
6954 0 : goto fail;
6955 : }
6956 0 : status = cli_close(cli, fnum);
6957 0 : if (!NT_STATUS_IS_OK(status)) {
6958 0 : printf("close failed for %s (%s)\n",
6959 : fname, nt_errstr(status));
6960 0 : goto fail;
6961 : }
6962 0 : fnum = (uint16_t)-1;
6963 :
6964 : /* Try and open for FILE_WRITE_DATA */
6965 0 : status = cli_ntcreate(cli,
6966 : fname,
6967 : 0,
6968 : FILE_WRITE_DATA,
6969 : FILE_ATTRIBUTE_NORMAL,
6970 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6971 : FILE_SHARE_DELETE,
6972 : FILE_OPEN,
6973 : 0,
6974 : 0,
6975 : &fnum,
6976 : NULL);
6977 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6978 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
6979 0 : goto fail;
6980 : }
6981 :
6982 : /* Now try and open for FILE_READ_DATA */
6983 0 : status = cli_ntcreate(cli,
6984 : fname,
6985 : 0,
6986 : FILE_READ_DATA,
6987 : FILE_ATTRIBUTE_NORMAL,
6988 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6989 : FILE_SHARE_DELETE,
6990 : FILE_OPEN,
6991 : 0,
6992 : 0,
6993 : &fnum,
6994 : NULL);
6995 0 : if (!NT_STATUS_IS_OK(status)) {
6996 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
6997 0 : goto fail;
6998 : }
6999 :
7000 0 : status = cli_close(cli, fnum);
7001 0 : if (!NT_STATUS_IS_OK(status)) {
7002 0 : printf("close failed for %s (%s)\n",
7003 : fname, nt_errstr(status));
7004 0 : goto fail;
7005 : }
7006 :
7007 : /* Restore clean slate. */
7008 0 : TALLOC_FREE(sd);
7009 0 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7010 :
7011 :
7012 : /* Create the test file. */
7013 0 : status = cli_ntcreate(cli,
7014 : fname,
7015 : 0,
7016 : GENERIC_ALL_ACCESS,
7017 : FILE_ATTRIBUTE_NORMAL,
7018 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7019 : FILE_SHARE_DELETE,
7020 : FILE_CREATE,
7021 : 0,
7022 : 0,
7023 : &fnum,
7024 : NULL);
7025 0 : if (!NT_STATUS_IS_OK(status)) {
7026 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
7027 0 : goto fail;
7028 : }
7029 :
7030 : /* Get the original SD. */
7031 0 : status = cli_query_secdesc(cli,
7032 : fnum,
7033 : frame,
7034 : &sd);
7035 0 : if (!NT_STATUS_IS_OK(status)) {
7036 0 : printf("cli_query_secdesc failed for %s (%s)\n",
7037 : fname, nt_errstr(status));
7038 0 : goto fail;
7039 : }
7040 :
7041 : /*
7042 : * Add an "authenticated users" ACE allowing READ_DATA,
7043 : * add an "owner-rights" denying READ_DATA,
7044 : * and an "authenticated users" ACE allowing WRITE_DATA.
7045 : */
7046 :
7047 0 : newsd = security_descriptor_dacl_create(frame,
7048 : 0,
7049 : NULL,
7050 : NULL,
7051 : SID_NT_AUTHENTICATED_USERS,
7052 : SEC_ACE_TYPE_ACCESS_ALLOWED,
7053 : FILE_READ_DATA,
7054 : 0,
7055 : SID_OWNER_RIGHTS,
7056 : SEC_ACE_TYPE_ACCESS_DENIED,
7057 : FILE_READ_DATA,
7058 : 0,
7059 : SID_NT_AUTHENTICATED_USERS,
7060 : SEC_ACE_TYPE_ACCESS_ALLOWED,
7061 : FILE_WRITE_DATA,
7062 : 0,
7063 : NULL);
7064 0 : if (newsd == NULL) {
7065 0 : printf("newsd == NULL\n");
7066 0 : goto fail;
7067 : }
7068 0 : sd->dacl = security_acl_concatenate(frame,
7069 0 : newsd->dacl,
7070 0 : sd->dacl);
7071 0 : if (sd->dacl == NULL) {
7072 0 : printf("sd->dacl == NULL\n");
7073 0 : goto fail;
7074 : }
7075 0 : status = cli_set_secdesc(cli, fnum, sd);
7076 0 : if (!NT_STATUS_IS_OK(status)) {
7077 0 : printf("cli_set_secdesc failed for %s (%s)\n",
7078 : fname, nt_errstr(status));
7079 0 : goto fail;
7080 : }
7081 0 : status = cli_close(cli, fnum);
7082 0 : if (!NT_STATUS_IS_OK(status)) {
7083 0 : printf("close failed for %s (%s)\n",
7084 : fname, nt_errstr(status));
7085 0 : goto fail;
7086 : }
7087 0 : fnum = (uint16_t)-1;
7088 :
7089 : /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7090 0 : status = cli_ntcreate(cli,
7091 : fname,
7092 : 0,
7093 : FILE_READ_DATA|FILE_WRITE_DATA,
7094 : FILE_ATTRIBUTE_NORMAL,
7095 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7096 : FILE_SHARE_DELETE,
7097 : FILE_OPEN,
7098 : 0,
7099 : 0,
7100 : &fnum,
7101 : NULL);
7102 0 : if (!NT_STATUS_IS_OK(status)) {
7103 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
7104 0 : goto fail;
7105 : }
7106 :
7107 0 : status = cli_close(cli, fnum);
7108 0 : if (!NT_STATUS_IS_OK(status)) {
7109 0 : printf("close failed for %s (%s)\n",
7110 : fname, nt_errstr(status));
7111 0 : goto fail;
7112 : }
7113 :
7114 0 : cli_unlink(cli, fname,
7115 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7116 :
7117 0 : TALLOC_FREE(frame);
7118 0 : return true;
7119 :
7120 0 : fail:
7121 :
7122 0 : if (cli) {
7123 0 : if (fnum != (uint16_t)-1) {
7124 0 : cli_close(cli, fnum);
7125 : }
7126 0 : cli_unlink(cli, fname,
7127 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7128 0 : torture_close_connection(cli);
7129 : }
7130 :
7131 0 : TALLOC_FREE(frame);
7132 0 : return false;
7133 : }
7134 :
7135 : /*
7136 : * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7137 : * Note this test only works with a user with SeSecurityPrivilege set.
7138 : *
7139 : * NB. This is also tested in samba3.base.createx_access
7140 : * but this makes it very explicit what we're looking for.
7141 : */
7142 0 : static bool run_smb1_system_security(int dummy)
7143 : {
7144 : static struct cli_state *cli = NULL;
7145 0 : const char *fname = "system_security.txt";
7146 0 : uint16_t fnum = (uint16_t)-1;
7147 : NTSTATUS status;
7148 0 : TALLOC_CTX *frame = NULL;
7149 :
7150 0 : frame = talloc_stackframe();
7151 0 : printf("starting smb1 system security test\n");
7152 :
7153 : /* SMB1 connection - torture_open_connection() forces this. */
7154 0 : if (!torture_open_connection(&cli, 0)) {
7155 0 : goto fail;
7156 : }
7157 :
7158 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
7159 :
7160 : /* Start with a clean slate. */
7161 0 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7162 :
7163 : /* Create the test file. */
7164 0 : status = cli_ntcreate(cli,
7165 : fname,
7166 : 0,
7167 : GENERIC_ALL_ACCESS,
7168 : FILE_ATTRIBUTE_NORMAL,
7169 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7170 : FILE_SHARE_DELETE,
7171 : FILE_CREATE,
7172 : 0,
7173 : 0,
7174 : &fnum,
7175 : NULL);
7176 0 : if (!NT_STATUS_IS_OK(status)) {
7177 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
7178 0 : goto fail;
7179 : }
7180 :
7181 0 : status = cli_close(cli, fnum);
7182 :
7183 : /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7184 : /*
7185 : * On SMB1 this succeeds - SMB2 it fails,
7186 : * see the SMB2-SACL test.
7187 : */
7188 0 : status = cli_ntcreate(cli,
7189 : fname,
7190 : 0,
7191 : SEC_FLAG_SYSTEM_SECURITY,
7192 : FILE_ATTRIBUTE_NORMAL,
7193 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7194 : FILE_SHARE_DELETE,
7195 : FILE_OPEN,
7196 : 0,
7197 : 0,
7198 : &fnum,
7199 : NULL);
7200 0 : if (!NT_STATUS_IS_OK(status)) {
7201 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
7202 0 : goto fail;
7203 : }
7204 :
7205 0 : status = cli_close(cli, fnum);
7206 :
7207 0 : cli_unlink(cli, fname,
7208 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7209 :
7210 0 : torture_close_connection(cli);
7211 0 : TALLOC_FREE(frame);
7212 0 : return true;
7213 :
7214 0 : fail:
7215 :
7216 0 : if (cli) {
7217 0 : if (fnum != (uint16_t)-1) {
7218 0 : cli_close(cli, fnum);
7219 : }
7220 0 : cli_unlink(cli, fname,
7221 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7222 0 : torture_close_connection(cli);
7223 : }
7224 :
7225 0 : TALLOC_FREE(frame);
7226 0 : return false;
7227 : }
7228 :
7229 0 : static bool run_pipe_number(int dummy)
7230 : {
7231 : struct cli_state *cli1;
7232 0 : const char *pipe_name = "\\SPOOLSS";
7233 : uint16_t fnum;
7234 0 : int num_pipes = 0;
7235 : NTSTATUS status;
7236 :
7237 0 : printf("starting pipenumber test\n");
7238 0 : if (!torture_open_connection(&cli1, 0)) {
7239 0 : return False;
7240 : }
7241 :
7242 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
7243 : while(1) {
7244 0 : status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7245 : FILE_ATTRIBUTE_NORMAL,
7246 : FILE_SHARE_READ|FILE_SHARE_WRITE,
7247 : FILE_OPEN_IF, 0, 0, &fnum, NULL);
7248 0 : if (!NT_STATUS_IS_OK(status)) {
7249 0 : printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7250 0 : break;
7251 : }
7252 0 : num_pipes++;
7253 0 : printf("\r%6d", num_pipes);
7254 : }
7255 :
7256 0 : printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7257 0 : torture_close_connection(cli1);
7258 0 : return True;
7259 : }
7260 :
7261 : /*
7262 : Test open mode returns on read-only files.
7263 : */
7264 1 : static bool run_opentest(int dummy)
7265 : {
7266 : static struct cli_state *cli1;
7267 : static struct cli_state *cli2;
7268 1 : const char *fname = "\\readonly.file";
7269 : uint16_t fnum1, fnum2;
7270 : char buf[20];
7271 : off_t fsize;
7272 1 : bool correct = True;
7273 : char *tmp_path;
7274 : NTSTATUS status;
7275 :
7276 1 : printf("starting open test\n");
7277 :
7278 1 : if (!torture_open_connection(&cli1, 0)) {
7279 0 : return False;
7280 : }
7281 :
7282 1 : cli_setatr(cli1, fname, 0, 0);
7283 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7284 :
7285 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
7286 :
7287 1 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7288 1 : if (!NT_STATUS_IS_OK(status)) {
7289 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7290 0 : return False;
7291 : }
7292 :
7293 1 : status = cli_close(cli1, fnum1);
7294 1 : if (!NT_STATUS_IS_OK(status)) {
7295 0 : printf("close2 failed (%s)\n", nt_errstr(status));
7296 0 : return False;
7297 : }
7298 :
7299 1 : status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7300 1 : if (!NT_STATUS_IS_OK(status)) {
7301 0 : printf("cli_setatr failed (%s)\n", nt_errstr(status));
7302 0 : return False;
7303 : }
7304 :
7305 1 : status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7306 1 : if (!NT_STATUS_IS_OK(status)) {
7307 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7308 0 : return False;
7309 : }
7310 :
7311 : /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7312 1 : status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7313 :
7314 1 : if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7315 1 : NT_STATUS_ACCESS_DENIED)) {
7316 0 : printf("correct error code ERRDOS/ERRnoaccess returned\n");
7317 : }
7318 :
7319 1 : printf("finished open test 1\n");
7320 :
7321 1 : cli_close(cli1, fnum1);
7322 :
7323 : /* Now try not readonly and ensure ERRbadshare is returned. */
7324 :
7325 1 : cli_setatr(cli1, fname, 0, 0);
7326 :
7327 1 : status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7328 1 : if (!NT_STATUS_IS_OK(status)) {
7329 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7330 0 : return False;
7331 : }
7332 :
7333 : /* This will fail - but the error should be ERRshare. */
7334 1 : status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7335 :
7336 1 : if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7337 1 : NT_STATUS_SHARING_VIOLATION)) {
7338 1 : printf("correct error code ERRDOS/ERRbadshare returned\n");
7339 : }
7340 :
7341 1 : status = cli_close(cli1, fnum1);
7342 1 : if (!NT_STATUS_IS_OK(status)) {
7343 0 : printf("close2 failed (%s)\n", nt_errstr(status));
7344 0 : return False;
7345 : }
7346 :
7347 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7348 :
7349 1 : printf("finished open test 2\n");
7350 :
7351 : /* Test truncate open disposition on file opened for read. */
7352 1 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7353 1 : if (!NT_STATUS_IS_OK(status)) {
7354 0 : printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7355 0 : return False;
7356 : }
7357 :
7358 : /* write 20 bytes. */
7359 :
7360 1 : memset(buf, '\0', 20);
7361 :
7362 1 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7363 1 : if (!NT_STATUS_IS_OK(status)) {
7364 0 : printf("write failed (%s)\n", nt_errstr(status));
7365 0 : correct = False;
7366 : }
7367 :
7368 1 : status = cli_close(cli1, fnum1);
7369 1 : if (!NT_STATUS_IS_OK(status)) {
7370 0 : printf("(3) close1 failed (%s)\n", nt_errstr(status));
7371 0 : return False;
7372 : }
7373 :
7374 : /* Ensure size == 20. */
7375 1 : status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7376 1 : if (!NT_STATUS_IS_OK(status)) {
7377 0 : printf("(3) getatr failed (%s)\n", nt_errstr(status));
7378 0 : return False;
7379 : }
7380 :
7381 1 : if (fsize != 20) {
7382 0 : printf("(3) file size != 20\n");
7383 0 : return False;
7384 : }
7385 :
7386 : /* Now test if we can truncate a file opened for readonly. */
7387 1 : status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7388 1 : if (!NT_STATUS_IS_OK(status)) {
7389 0 : printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7390 0 : return False;
7391 : }
7392 :
7393 1 : status = cli_close(cli1, fnum1);
7394 1 : if (!NT_STATUS_IS_OK(status)) {
7395 0 : printf("close2 failed (%s)\n", nt_errstr(status));
7396 0 : return False;
7397 : }
7398 :
7399 : /* Ensure size == 0. */
7400 1 : status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7401 1 : if (!NT_STATUS_IS_OK(status)) {
7402 0 : printf("(3) getatr failed (%s)\n", nt_errstr(status));
7403 0 : return False;
7404 : }
7405 :
7406 1 : if (fsize != 0) {
7407 0 : printf("(3) file size != 0\n");
7408 0 : return False;
7409 : }
7410 1 : printf("finished open test 3\n");
7411 :
7412 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7413 :
7414 1 : printf("Do ctemp tests\n");
7415 1 : status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7416 1 : if (!NT_STATUS_IS_OK(status)) {
7417 0 : printf("ctemp failed (%s)\n", nt_errstr(status));
7418 0 : return False;
7419 : }
7420 :
7421 1 : printf("ctemp gave path %s\n", tmp_path);
7422 1 : status = cli_close(cli1, fnum1);
7423 1 : if (!NT_STATUS_IS_OK(status)) {
7424 0 : printf("close of temp failed (%s)\n", nt_errstr(status));
7425 : }
7426 :
7427 1 : status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7428 1 : if (!NT_STATUS_IS_OK(status)) {
7429 0 : printf("unlink of temp failed (%s)\n", nt_errstr(status));
7430 : }
7431 :
7432 : /* Test the non-io opens... */
7433 :
7434 1 : if (!torture_open_connection(&cli2, 1)) {
7435 0 : return False;
7436 : }
7437 :
7438 1 : cli_setatr(cli2, fname, 0, 0);
7439 1 : cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7440 :
7441 1 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
7442 :
7443 1 : printf("TEST #1 testing 2 non-io opens (no delete)\n");
7444 1 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7445 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7446 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7447 1 : if (!NT_STATUS_IS_OK(status)) {
7448 0 : printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7449 0 : return False;
7450 : }
7451 :
7452 1 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7453 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7454 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7455 1 : if (!NT_STATUS_IS_OK(status)) {
7456 0 : printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7457 0 : return False;
7458 : }
7459 :
7460 1 : status = cli_close(cli1, fnum1);
7461 1 : if (!NT_STATUS_IS_OK(status)) {
7462 0 : printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7463 0 : return False;
7464 : }
7465 :
7466 1 : status = cli_close(cli2, fnum2);
7467 1 : if (!NT_STATUS_IS_OK(status)) {
7468 0 : printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7469 0 : return False;
7470 : }
7471 :
7472 1 : printf("non-io open test #1 passed.\n");
7473 :
7474 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7475 :
7476 1 : printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7477 :
7478 1 : status = cli_ntcreate(cli1, fname, 0,
7479 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7480 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7481 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7482 1 : if (!NT_STATUS_IS_OK(status)) {
7483 0 : printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7484 0 : return False;
7485 : }
7486 :
7487 1 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7488 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7489 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7490 1 : if (!NT_STATUS_IS_OK(status)) {
7491 0 : printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7492 0 : return False;
7493 : }
7494 :
7495 1 : status = cli_close(cli1, fnum1);
7496 1 : if (!NT_STATUS_IS_OK(status)) {
7497 0 : printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7498 0 : return False;
7499 : }
7500 :
7501 1 : status = cli_close(cli2, fnum2);
7502 1 : if (!NT_STATUS_IS_OK(status)) {
7503 0 : printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7504 0 : return False;
7505 : }
7506 :
7507 1 : printf("non-io open test #2 passed.\n");
7508 :
7509 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7510 :
7511 1 : printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7512 :
7513 1 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7514 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7515 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7516 1 : if (!NT_STATUS_IS_OK(status)) {
7517 0 : printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7518 0 : return False;
7519 : }
7520 :
7521 1 : status = cli_ntcreate(cli2, fname, 0,
7522 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7523 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7524 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7525 1 : if (!NT_STATUS_IS_OK(status)) {
7526 0 : printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7527 0 : return False;
7528 : }
7529 :
7530 1 : status = cli_close(cli1, fnum1);
7531 1 : if (!NT_STATUS_IS_OK(status)) {
7532 0 : printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7533 0 : return False;
7534 : }
7535 :
7536 1 : status = cli_close(cli2, fnum2);
7537 1 : if (!NT_STATUS_IS_OK(status)) {
7538 0 : printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7539 0 : return False;
7540 : }
7541 :
7542 1 : printf("non-io open test #3 passed.\n");
7543 :
7544 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7545 :
7546 1 : printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7547 :
7548 1 : status = cli_ntcreate(cli1, fname, 0,
7549 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7550 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7551 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7552 1 : if (!NT_STATUS_IS_OK(status)) {
7553 0 : printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7554 0 : return False;
7555 : }
7556 :
7557 1 : status = cli_ntcreate(cli2, fname, 0,
7558 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7559 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7560 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7561 1 : if (NT_STATUS_IS_OK(status)) {
7562 0 : printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7563 0 : return False;
7564 : }
7565 :
7566 1 : printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7567 :
7568 1 : status = cli_close(cli1, fnum1);
7569 1 : if (!NT_STATUS_IS_OK(status)) {
7570 0 : printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7571 0 : return False;
7572 : }
7573 :
7574 1 : printf("non-io open test #4 passed.\n");
7575 :
7576 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7577 :
7578 1 : printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7579 :
7580 1 : status = cli_ntcreate(cli1, fname, 0,
7581 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7582 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7583 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7584 1 : if (!NT_STATUS_IS_OK(status)) {
7585 0 : printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7586 0 : return False;
7587 : }
7588 :
7589 1 : status = cli_ntcreate(cli2, fname, 0,
7590 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7591 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7592 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7593 1 : if (!NT_STATUS_IS_OK(status)) {
7594 0 : printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7595 0 : return False;
7596 : }
7597 :
7598 1 : status = cli_close(cli1, fnum1);
7599 1 : if (!NT_STATUS_IS_OK(status)) {
7600 0 : printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7601 0 : return False;
7602 : }
7603 :
7604 1 : status = cli_close(cli2, fnum2);
7605 1 : if (!NT_STATUS_IS_OK(status)) {
7606 0 : printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7607 0 : return False;
7608 : }
7609 :
7610 1 : printf("non-io open test #5 passed.\n");
7611 :
7612 1 : printf("TEST #6 testing 1 non-io open, one io open\n");
7613 :
7614 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7615 :
7616 1 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7617 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7618 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7619 1 : if (!NT_STATUS_IS_OK(status)) {
7620 0 : printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7621 0 : return False;
7622 : }
7623 :
7624 1 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7625 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7626 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7627 1 : if (!NT_STATUS_IS_OK(status)) {
7628 0 : printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7629 0 : return False;
7630 : }
7631 :
7632 1 : status = cli_close(cli1, fnum1);
7633 1 : if (!NT_STATUS_IS_OK(status)) {
7634 0 : printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7635 0 : return False;
7636 : }
7637 :
7638 1 : status = cli_close(cli2, fnum2);
7639 1 : if (!NT_STATUS_IS_OK(status)) {
7640 0 : printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7641 0 : return False;
7642 : }
7643 :
7644 1 : printf("non-io open test #6 passed.\n");
7645 :
7646 1 : printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7647 :
7648 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7649 :
7650 1 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7651 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7652 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7653 1 : if (!NT_STATUS_IS_OK(status)) {
7654 0 : printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7655 0 : return False;
7656 : }
7657 :
7658 1 : status = cli_ntcreate(cli2, fname, 0,
7659 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7660 : FILE_ATTRIBUTE_NORMAL,
7661 : FILE_SHARE_READ|FILE_SHARE_DELETE,
7662 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7663 1 : if (NT_STATUS_IS_OK(status)) {
7664 0 : printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7665 0 : return False;
7666 : }
7667 :
7668 1 : printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7669 :
7670 1 : status = cli_close(cli1, fnum1);
7671 1 : if (!NT_STATUS_IS_OK(status)) {
7672 0 : printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7673 0 : return False;
7674 : }
7675 :
7676 1 : printf("non-io open test #7 passed.\n");
7677 :
7678 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7679 :
7680 1 : printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7681 1 : status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7682 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7683 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7684 1 : if (!NT_STATUS_IS_OK(status)) {
7685 0 : printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7686 0 : correct = false;
7687 0 : goto out;
7688 : }
7689 :
7690 : /* Write to ensure we have to update the file time. */
7691 1 : status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7692 : NULL);
7693 1 : if (!NT_STATUS_IS_OK(status)) {
7694 0 : printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7695 0 : correct = false;
7696 0 : goto out;
7697 : }
7698 :
7699 1 : status = cli_close(cli1, fnum1);
7700 1 : if (!NT_STATUS_IS_OK(status)) {
7701 0 : printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7702 0 : correct = false;
7703 : }
7704 :
7705 1 : out:
7706 :
7707 1 : if (!torture_close_connection(cli1)) {
7708 0 : correct = False;
7709 : }
7710 1 : if (!torture_close_connection(cli2)) {
7711 0 : correct = False;
7712 : }
7713 :
7714 1 : return correct;
7715 : }
7716 :
7717 0 : NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7718 : {
7719 : uint16_t major, minor;
7720 : uint32_t caplow, caphigh;
7721 : NTSTATUS status;
7722 :
7723 0 : if (!SERVER_HAS_UNIX_CIFS(cli)) {
7724 0 : printf("Server doesn't support UNIX CIFS extensions.\n");
7725 0 : return NT_STATUS_NOT_SUPPORTED;
7726 : }
7727 :
7728 0 : status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7729 : &caphigh);
7730 0 : if (!NT_STATUS_IS_OK(status)) {
7731 0 : printf("Server didn't return UNIX CIFS extensions: %s\n",
7732 : nt_errstr(status));
7733 0 : return status;
7734 : }
7735 :
7736 0 : status = cli_set_unix_extensions_capabilities(cli, major, minor,
7737 : caplow, caphigh);
7738 0 : if (!NT_STATUS_IS_OK(status)) {
7739 0 : printf("Server doesn't support setting UNIX CIFS extensions: "
7740 : "%s.\n", nt_errstr(status));
7741 0 : return status;
7742 : }
7743 :
7744 0 : return NT_STATUS_OK;
7745 : }
7746 :
7747 : /*
7748 : Test POSIX open /mkdir calls.
7749 : */
7750 0 : static bool run_simple_posix_open_test(int dummy)
7751 : {
7752 : static struct cli_state *cli1;
7753 0 : const char *fname = "posix:file";
7754 0 : const char *hname = "posix:hlink";
7755 0 : const char *sname = "posix:symlink";
7756 0 : const char *dname = "posix:dir";
7757 : char buf[10];
7758 0 : char *target = NULL;
7759 0 : uint16_t fnum1 = (uint16_t)-1;
7760 : SMB_STRUCT_STAT sbuf;
7761 0 : bool correct = false;
7762 : NTSTATUS status;
7763 : size_t nread;
7764 0 : const char *fname_windows = "windows_file";
7765 0 : uint16_t fnum2 = (uint16_t)-1;
7766 : bool ok;
7767 :
7768 0 : printf("Starting simple POSIX open test\n");
7769 :
7770 0 : if (!torture_open_connection(&cli1, 0)) {
7771 0 : return false;
7772 : }
7773 :
7774 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
7775 :
7776 0 : status = torture_setup_unix_extensions(cli1);
7777 0 : if (!NT_STATUS_IS_OK(status)) {
7778 0 : return false;
7779 : }
7780 :
7781 0 : cli_setatr(cli1, fname, 0, 0);
7782 0 : cli_posix_unlink(cli1, fname);
7783 0 : cli_setatr(cli1, dname, 0, 0);
7784 0 : cli_posix_rmdir(cli1, dname);
7785 0 : cli_setatr(cli1, hname, 0, 0);
7786 0 : cli_posix_unlink(cli1, hname);
7787 0 : cli_setatr(cli1, sname, 0, 0);
7788 0 : cli_posix_unlink(cli1, sname);
7789 0 : cli_setatr(cli1, fname_windows, 0, 0);
7790 0 : cli_posix_unlink(cli1, fname_windows);
7791 :
7792 : /* Create a directory. */
7793 0 : status = cli_posix_mkdir(cli1, dname, 0777);
7794 0 : if (!NT_STATUS_IS_OK(status)) {
7795 0 : printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7796 0 : goto out;
7797 : }
7798 :
7799 0 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7800 : 0600, &fnum1);
7801 0 : if (!NT_STATUS_IS_OK(status)) {
7802 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7803 0 : goto out;
7804 : }
7805 :
7806 : /* Test ftruncate - set file size. */
7807 0 : status = cli_ftruncate(cli1, fnum1, 1000);
7808 0 : if (!NT_STATUS_IS_OK(status)) {
7809 0 : printf("ftruncate failed (%s)\n", nt_errstr(status));
7810 0 : goto out;
7811 : }
7812 :
7813 : /* Ensure st_size == 1000 */
7814 0 : status = cli_posix_stat(cli1, fname, &sbuf);
7815 0 : if (!NT_STATUS_IS_OK(status)) {
7816 0 : printf("stat failed (%s)\n", nt_errstr(status));
7817 0 : goto out;
7818 : }
7819 :
7820 0 : if (sbuf.st_ex_size != 1000) {
7821 0 : printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7822 0 : goto out;
7823 : }
7824 :
7825 : /* Ensure st_mode == 0600 */
7826 0 : if ((sbuf.st_ex_mode & 07777) != 0600) {
7827 0 : printf("posix_open - bad permissions 0%o != 0600\n",
7828 0 : (unsigned int)(sbuf.st_ex_mode & 07777));
7829 0 : goto out;
7830 : }
7831 :
7832 : /* Test ftruncate - set file size back to zero. */
7833 0 : status = cli_ftruncate(cli1, fnum1, 0);
7834 0 : if (!NT_STATUS_IS_OK(status)) {
7835 0 : printf("ftruncate failed (%s)\n", nt_errstr(status));
7836 0 : goto out;
7837 : }
7838 :
7839 0 : status = cli_close(cli1, fnum1);
7840 0 : if (!NT_STATUS_IS_OK(status)) {
7841 0 : printf("close failed (%s)\n", nt_errstr(status));
7842 0 : goto out;
7843 : }
7844 :
7845 : /* Now open the file again for read only. */
7846 0 : status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7847 0 : if (!NT_STATUS_IS_OK(status)) {
7848 0 : printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7849 0 : goto out;
7850 : }
7851 :
7852 : /* Now unlink while open. */
7853 0 : status = cli_posix_unlink(cli1, fname);
7854 0 : if (!NT_STATUS_IS_OK(status)) {
7855 0 : printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7856 0 : goto out;
7857 : }
7858 :
7859 0 : status = cli_close(cli1, fnum1);
7860 0 : if (!NT_STATUS_IS_OK(status)) {
7861 0 : printf("close(2) failed (%s)\n", nt_errstr(status));
7862 0 : goto out;
7863 : }
7864 :
7865 : /* Ensure the file has gone. */
7866 0 : status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7867 0 : if (NT_STATUS_IS_OK(status)) {
7868 0 : printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7869 0 : goto out;
7870 : }
7871 :
7872 : /* Create again to test open with O_TRUNC. */
7873 0 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7874 0 : if (!NT_STATUS_IS_OK(status)) {
7875 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7876 0 : goto out;
7877 : }
7878 :
7879 : /* Test ftruncate - set file size. */
7880 0 : status = cli_ftruncate(cli1, fnum1, 1000);
7881 0 : if (!NT_STATUS_IS_OK(status)) {
7882 0 : printf("ftruncate failed (%s)\n", nt_errstr(status));
7883 0 : goto out;
7884 : }
7885 :
7886 : /* Ensure st_size == 1000 */
7887 0 : status = cli_posix_stat(cli1, fname, &sbuf);
7888 0 : if (!NT_STATUS_IS_OK(status)) {
7889 0 : printf("stat failed (%s)\n", nt_errstr(status));
7890 0 : goto out;
7891 : }
7892 :
7893 0 : if (sbuf.st_ex_size != 1000) {
7894 0 : printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7895 0 : goto out;
7896 : }
7897 :
7898 0 : status = cli_close(cli1, fnum1);
7899 0 : if (!NT_STATUS_IS_OK(status)) {
7900 0 : printf("close(2) failed (%s)\n", nt_errstr(status));
7901 0 : goto out;
7902 : }
7903 :
7904 : /* Re-open with O_TRUNC. */
7905 0 : status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7906 0 : if (!NT_STATUS_IS_OK(status)) {
7907 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7908 0 : goto out;
7909 : }
7910 :
7911 : /* Ensure st_size == 0 */
7912 0 : status = cli_posix_stat(cli1, fname, &sbuf);
7913 0 : if (!NT_STATUS_IS_OK(status)) {
7914 0 : printf("stat failed (%s)\n", nt_errstr(status));
7915 0 : goto out;
7916 : }
7917 :
7918 0 : if (sbuf.st_ex_size != 0) {
7919 0 : printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7920 0 : goto out;
7921 : }
7922 :
7923 0 : status = cli_close(cli1, fnum1);
7924 0 : if (!NT_STATUS_IS_OK(status)) {
7925 0 : printf("close failed (%s)\n", nt_errstr(status));
7926 0 : goto out;
7927 : }
7928 :
7929 0 : status = cli_posix_unlink(cli1, fname);
7930 0 : if (!NT_STATUS_IS_OK(status)) {
7931 0 : printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7932 0 : goto out;
7933 : }
7934 :
7935 0 : status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
7936 0 : if (!NT_STATUS_IS_OK(status)) {
7937 0 : printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
7938 : dname, nt_errstr(status));
7939 0 : goto out;
7940 : }
7941 :
7942 0 : cli_close(cli1, fnum1);
7943 :
7944 : /* What happens when we try and POSIX open a directory for write ? */
7945 0 : status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
7946 0 : if (NT_STATUS_IS_OK(status)) {
7947 0 : printf("POSIX open of directory %s succeeded, "
7948 : "should have failed.\n",
7949 : dname);
7950 0 : goto out;
7951 : } else {
7952 0 : if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
7953 0 : NT_STATUS_FILE_IS_A_DIRECTORY)) {
7954 0 : goto out;
7955 : }
7956 : }
7957 :
7958 : /* Create the file. */
7959 0 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7960 : 0600, &fnum1);
7961 0 : if (!NT_STATUS_IS_OK(status)) {
7962 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7963 0 : goto out;
7964 : }
7965 :
7966 : /* Write some data into it. */
7967 0 : status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7968 : NULL);
7969 0 : if (!NT_STATUS_IS_OK(status)) {
7970 0 : printf("cli_write failed: %s\n", nt_errstr(status));
7971 0 : goto out;
7972 : }
7973 :
7974 0 : cli_close(cli1, fnum1);
7975 :
7976 : /* Now create a hardlink. */
7977 0 : status = cli_posix_hardlink(cli1, fname, hname);
7978 0 : if (!NT_STATUS_IS_OK(status)) {
7979 0 : printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
7980 0 : goto out;
7981 : }
7982 :
7983 : /* Now create a symlink. */
7984 0 : status = cli_posix_symlink(cli1, fname, sname);
7985 0 : if (!NT_STATUS_IS_OK(status)) {
7986 0 : printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
7987 0 : goto out;
7988 : }
7989 :
7990 : /* Open the hardlink for read. */
7991 0 : status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
7992 0 : if (!NT_STATUS_IS_OK(status)) {
7993 0 : printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
7994 0 : goto out;
7995 : }
7996 :
7997 0 : status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
7998 0 : if (!NT_STATUS_IS_OK(status)) {
7999 0 : printf("POSIX read of %s failed (%s)\n", hname,
8000 : nt_errstr(status));
8001 0 : goto out;
8002 0 : } else if (nread != 10) {
8003 0 : printf("POSIX read of %s failed. Received %ld, expected %d\n",
8004 : hname, (unsigned long)nread, 10);
8005 0 : goto out;
8006 : }
8007 :
8008 0 : if (memcmp(buf, "TEST DATA\n", 10)) {
8009 0 : printf("invalid data read from hardlink\n");
8010 0 : goto out;
8011 : }
8012 :
8013 : /* Do a POSIX lock/unlock. */
8014 0 : status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8015 0 : if (!NT_STATUS_IS_OK(status)) {
8016 0 : printf("POSIX lock failed %s\n", nt_errstr(status));
8017 0 : goto out;
8018 : }
8019 :
8020 : /* Punch a hole in the locked area. */
8021 0 : status = cli_posix_unlock(cli1, fnum1, 10, 80);
8022 0 : if (!NT_STATUS_IS_OK(status)) {
8023 0 : printf("POSIX unlock failed %s\n", nt_errstr(status));
8024 0 : goto out;
8025 : }
8026 :
8027 0 : cli_close(cli1, fnum1);
8028 :
8029 : /* Open the symlink for read - this should fail. A POSIX
8030 : client should not be doing opens on a symlink. */
8031 0 : status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8032 0 : if (NT_STATUS_IS_OK(status)) {
8033 0 : printf("POSIX open of %s succeeded (should have failed)\n", sname);
8034 0 : goto out;
8035 : }
8036 0 : ok = check_both_error(
8037 : __LINE__, status, ERRDOS, ERRbadpath,
8038 0 : NT_STATUS_OBJECT_NAME_NOT_FOUND);
8039 0 : if (!ok) {
8040 0 : printf("POSIX open of %s should have failed "
8041 : "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8042 : "failed with %s instead.\n",
8043 : sname, nt_errstr(status));
8044 0 : goto out;
8045 : }
8046 :
8047 0 : status = cli_readlink(cli1, sname, talloc_tos(), &target, NULL, NULL);
8048 0 : if (!NT_STATUS_IS_OK(status)) {
8049 0 : printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8050 0 : goto out;
8051 : }
8052 :
8053 0 : if (strcmp(target, fname) != 0) {
8054 0 : printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8055 : sname, fname, target);
8056 0 : goto out;
8057 : }
8058 :
8059 0 : status = cli_posix_rmdir(cli1, dname);
8060 0 : if (!NT_STATUS_IS_OK(status)) {
8061 0 : printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8062 0 : goto out;
8063 : }
8064 :
8065 : /* Check directory opens with a specific permission. */
8066 0 : status = cli_posix_mkdir(cli1, dname, 0700);
8067 0 : if (!NT_STATUS_IS_OK(status)) {
8068 0 : printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8069 0 : goto out;
8070 : }
8071 :
8072 : /* Ensure st_mode == 0700 */
8073 0 : status = cli_posix_stat(cli1, dname, &sbuf);
8074 0 : if (!NT_STATUS_IS_OK(status)) {
8075 0 : printf("stat failed (%s)\n", nt_errstr(status));
8076 0 : goto out;
8077 : }
8078 :
8079 0 : if ((sbuf.st_ex_mode & 07777) != 0700) {
8080 0 : printf("posix_mkdir - bad permissions 0%o != 0700\n",
8081 0 : (unsigned int)(sbuf.st_ex_mode & 07777));
8082 0 : goto out;
8083 : }
8084 :
8085 : /*
8086 : * Now create a Windows file, and attempt a POSIX unlink.
8087 : * This should fail with a sharing violation but due to:
8088 : *
8089 : * [Bug 9571] Unlink after open causes smbd to panic
8090 : *
8091 : * ensure we've fixed the lock ordering violation.
8092 : */
8093 :
8094 0 : status = cli_ntcreate(cli1, fname_windows, 0,
8095 : FILE_READ_DATA|FILE_WRITE_DATA, 0,
8096 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8097 : FILE_CREATE,
8098 : 0x0, 0x0, &fnum2, NULL);
8099 0 : if (!NT_STATUS_IS_OK(status)) {
8100 0 : printf("Windows create of %s failed (%s)\n", fname_windows,
8101 : nt_errstr(status));
8102 0 : goto out;
8103 : }
8104 :
8105 : /* Now try posix_unlink. */
8106 0 : status = cli_posix_unlink(cli1, fname_windows);
8107 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8108 0 : printf("POSIX unlink of %s should fail "
8109 : "with NT_STATUS_SHARING_VIOLATION "
8110 : "got %s instead !\n",
8111 : fname_windows,
8112 : nt_errstr(status));
8113 0 : goto out;
8114 : }
8115 :
8116 0 : cli_close(cli1, fnum2);
8117 :
8118 0 : printf("Simple POSIX open test passed\n");
8119 0 : correct = true;
8120 :
8121 0 : out:
8122 :
8123 0 : if (fnum1 != (uint16_t)-1) {
8124 0 : cli_close(cli1, fnum1);
8125 0 : fnum1 = (uint16_t)-1;
8126 : }
8127 :
8128 0 : if (fnum2 != (uint16_t)-1) {
8129 0 : cli_close(cli1, fnum2);
8130 0 : fnum2 = (uint16_t)-1;
8131 : }
8132 :
8133 0 : cli_setatr(cli1, sname, 0, 0);
8134 0 : cli_posix_unlink(cli1, sname);
8135 0 : cli_setatr(cli1, hname, 0, 0);
8136 0 : cli_posix_unlink(cli1, hname);
8137 0 : cli_setatr(cli1, fname, 0, 0);
8138 0 : cli_posix_unlink(cli1, fname);
8139 0 : cli_setatr(cli1, dname, 0, 0);
8140 0 : cli_posix_rmdir(cli1, dname);
8141 0 : cli_setatr(cli1, fname_windows, 0, 0);
8142 0 : cli_posix_unlink(cli1, fname_windows);
8143 :
8144 0 : if (!torture_close_connection(cli1)) {
8145 0 : correct = false;
8146 : }
8147 :
8148 0 : return correct;
8149 : }
8150 :
8151 : /*
8152 : Test POSIX and Windows ACLs are rejected on symlinks.
8153 : */
8154 0 : static bool run_acl_symlink_test(int dummy)
8155 : {
8156 : static struct cli_state *cli;
8157 0 : const char *fname = "posix_file";
8158 0 : const char *sname = "posix_symlink";
8159 0 : uint16_t fnum = (uint16_t)-1;
8160 0 : bool correct = false;
8161 : NTSTATUS status;
8162 0 : char *posix_acl = NULL;
8163 0 : size_t posix_acl_len = 0;
8164 0 : char *posix_acl_sym = NULL;
8165 0 : size_t posix_acl_len_sym = 0;
8166 0 : struct security_descriptor *sd = NULL;
8167 0 : TALLOC_CTX *frame = NULL;
8168 :
8169 0 : frame = talloc_stackframe();
8170 :
8171 0 : printf("Starting acl symlink test\n");
8172 :
8173 0 : if (!torture_open_connection(&cli, 0)) {
8174 0 : TALLOC_FREE(frame);
8175 0 : return false;
8176 : }
8177 :
8178 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
8179 :
8180 0 : status = torture_setup_unix_extensions(cli);
8181 0 : if (!NT_STATUS_IS_OK(status)) {
8182 0 : TALLOC_FREE(frame);
8183 0 : return false;
8184 : }
8185 :
8186 0 : cli_setatr(cli, fname, 0, 0);
8187 0 : cli_posix_unlink(cli, fname);
8188 0 : cli_setatr(cli, sname, 0, 0);
8189 0 : cli_posix_unlink(cli, sname);
8190 :
8191 0 : status = cli_ntcreate(cli,
8192 : fname,
8193 : 0,
8194 : READ_CONTROL_ACCESS,
8195 : 0,
8196 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8197 : FILE_CREATE,
8198 : 0x0,
8199 : 0x0,
8200 : &fnum,
8201 : NULL);
8202 :
8203 0 : if (!NT_STATUS_IS_OK(status)) {
8204 0 : printf("cli_ntcreate of %s failed (%s)\n",
8205 : fname,
8206 : nt_errstr(status));
8207 0 : goto out;
8208 : }
8209 :
8210 : /* Get the Windows ACL on the file. */
8211 0 : status = cli_query_secdesc(cli,
8212 : fnum,
8213 : frame,
8214 : &sd);
8215 0 : if (!NT_STATUS_IS_OK(status)) {
8216 0 : printf("cli_query_secdesc failed (%s)\n",
8217 : nt_errstr(status));
8218 0 : goto out;
8219 : }
8220 :
8221 : /* Get the POSIX ACL on the file. */
8222 0 : status = cli_posix_getacl(cli,
8223 : fname,
8224 : frame,
8225 : &posix_acl_len,
8226 : &posix_acl);
8227 :
8228 0 : if (!NT_STATUS_IS_OK(status)) {
8229 0 : printf("cli_posix_getacl failed (%s)\n",
8230 : nt_errstr(status));
8231 0 : goto out;
8232 : }
8233 :
8234 0 : status = cli_close(cli, fnum);
8235 0 : if (!NT_STATUS_IS_OK(status)) {
8236 0 : printf("close failed (%s)\n", nt_errstr(status));
8237 0 : goto out;
8238 : }
8239 0 : fnum = (uint16_t)-1;
8240 :
8241 : /* Now create a symlink. */
8242 0 : status = cli_posix_symlink(cli, fname, sname);
8243 0 : if (!NT_STATUS_IS_OK(status)) {
8244 0 : printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8245 : sname,
8246 : fname,
8247 : nt_errstr(status));
8248 0 : goto out;
8249 : }
8250 :
8251 : /* Open a handle on the symlink for SD set/get should fail. */
8252 0 : status = cli_ntcreate(cli,
8253 : sname,
8254 : 0,
8255 : READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8256 : 0,
8257 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8258 : FILE_OPEN,
8259 : 0x0,
8260 : 0x0,
8261 : &fnum,
8262 : NULL);
8263 :
8264 0 : if (NT_STATUS_IS_OK(status)) {
8265 0 : printf("Symlink open for getsd/setsd of %s "
8266 : "succeeded (should fail)\n",
8267 : sname);
8268 0 : goto out;
8269 : }
8270 :
8271 : /* Try a stat-open on the symlink, should also fail. */
8272 0 : status = cli_ntcreate(cli,
8273 : sname,
8274 : 0,
8275 : FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8276 : 0,
8277 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8278 : FILE_OPEN,
8279 : 0x0,
8280 : 0x0,
8281 : &fnum,
8282 : NULL);
8283 :
8284 0 : if (NT_STATUS_IS_OK(status)) {
8285 0 : printf("Stat-open of symlink succeeded (should fail)\n");
8286 0 : goto out;
8287 : }
8288 :
8289 : /* Get the POSIX ACL on the symlink pathname. Should fail. */
8290 0 : status = cli_posix_getacl(cli,
8291 : sname,
8292 : frame,
8293 : &posix_acl_len_sym,
8294 : &posix_acl_sym);
8295 :
8296 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8297 0 : printf("cli_posix_getacl on a symlink gave %s. "
8298 : "Should be NT_STATUS_ACCESS_DENIED.\n",
8299 : nt_errstr(status));
8300 0 : goto out;
8301 : }
8302 :
8303 : /* Set the POSIX ACL on the symlink pathname. Should fail. */
8304 0 : status = cli_posix_setacl(cli,
8305 : sname,
8306 : posix_acl,
8307 : posix_acl_len);
8308 :
8309 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8310 0 : printf("cli_posix_setacl on a symlink gave %s. "
8311 : "Should be NT_STATUS_ACCESS_DENIED.\n",
8312 : nt_errstr(status));
8313 0 : goto out;
8314 : }
8315 :
8316 0 : printf("ACL symlink test passed\n");
8317 0 : correct = true;
8318 :
8319 0 : out:
8320 :
8321 0 : if (fnum != (uint16_t)-1) {
8322 0 : cli_close(cli, fnum);
8323 0 : fnum = (uint16_t)-1;
8324 : }
8325 :
8326 0 : cli_setatr(cli, sname, 0, 0);
8327 0 : cli_posix_unlink(cli, sname);
8328 0 : cli_setatr(cli, fname, 0, 0);
8329 0 : cli_posix_unlink(cli, fname);
8330 :
8331 0 : if (!torture_close_connection(cli)) {
8332 0 : correct = false;
8333 : }
8334 :
8335 0 : TALLOC_FREE(frame);
8336 0 : return correct;
8337 : }
8338 :
8339 : /*
8340 : Test POSIX can delete a file containing streams.
8341 : */
8342 0 : static bool run_posix_stream_delete(int dummy)
8343 : {
8344 0 : struct cli_state *cli1 = NULL;
8345 0 : struct cli_state *cli2 = NULL;
8346 0 : const char *fname = "streamfile";
8347 0 : const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8348 0 : uint16_t fnum1 = (uint16_t)-1;
8349 0 : bool correct = false;
8350 : NTSTATUS status;
8351 0 : TALLOC_CTX *frame = NULL;
8352 :
8353 0 : frame = talloc_stackframe();
8354 :
8355 0 : printf("Starting POSIX stream delete test\n");
8356 :
8357 0 : if (!torture_open_connection(&cli1, 0) ||
8358 0 : !torture_open_connection(&cli2, 1)) {
8359 0 : TALLOC_FREE(frame);
8360 0 : return false;
8361 : }
8362 :
8363 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
8364 0 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
8365 :
8366 0 : status = torture_setup_unix_extensions(cli2);
8367 0 : if (!NT_STATUS_IS_OK(status)) {
8368 0 : goto out;
8369 : }
8370 :
8371 0 : cli_setatr(cli1, fname, 0, 0);
8372 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8373 :
8374 : /* Create the file. */
8375 0 : status = cli_ntcreate(cli1,
8376 : fname,
8377 : 0,
8378 : READ_CONTROL_ACCESS,
8379 : 0,
8380 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8381 : FILE_CREATE,
8382 : 0x0,
8383 : 0x0,
8384 : &fnum1,
8385 : NULL);
8386 :
8387 0 : if (!NT_STATUS_IS_OK(status)) {
8388 0 : printf("cli_ntcreate of %s failed (%s)\n",
8389 : fname,
8390 : nt_errstr(status));
8391 0 : goto out;
8392 : }
8393 :
8394 0 : status = cli_close(cli1, fnum1);
8395 0 : if (!NT_STATUS_IS_OK(status)) {
8396 0 : printf("cli_close of %s failed (%s)\n",
8397 : fname,
8398 : nt_errstr(status));
8399 0 : goto out;
8400 : }
8401 0 : fnum1 = (uint16_t)-1;
8402 :
8403 : /* Now create the stream. */
8404 0 : status = cli_ntcreate(cli1,
8405 : stream_fname,
8406 : 0,
8407 : FILE_WRITE_DATA,
8408 : 0,
8409 : FILE_SHARE_READ|FILE_SHARE_WRITE,
8410 : FILE_CREATE,
8411 : 0x0,
8412 : 0x0,
8413 : &fnum1,
8414 : NULL);
8415 :
8416 0 : if (!NT_STATUS_IS_OK(status)) {
8417 0 : printf("cli_ntcreate of %s failed (%s)\n",
8418 : stream_fname,
8419 : nt_errstr(status));
8420 0 : goto out;
8421 : }
8422 :
8423 : /* Leave the stream handle open... */
8424 :
8425 : /* POSIX unlink should fail. */
8426 0 : status = cli_posix_unlink(cli2, fname);
8427 0 : if (NT_STATUS_IS_OK(status)) {
8428 0 : printf("cli_posix_unlink of %s succeeded, should have failed\n",
8429 : fname);
8430 0 : goto out;
8431 : }
8432 :
8433 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8434 0 : printf("cli_posix_unlink of %s failed with (%s) "
8435 : "should have been NT_STATUS_SHARING_VIOLATION\n",
8436 : fname,
8437 : nt_errstr(status));
8438 0 : goto out;
8439 : }
8440 :
8441 : /* Close the stream handle. */
8442 0 : status = cli_close(cli1, fnum1);
8443 0 : if (!NT_STATUS_IS_OK(status)) {
8444 0 : printf("cli_close of %s failed (%s)\n",
8445 : stream_fname,
8446 : nt_errstr(status));
8447 0 : goto out;
8448 : }
8449 0 : fnum1 = (uint16_t)-1;
8450 :
8451 : /* POSIX unlink after stream handle closed should succeed. */
8452 0 : status = cli_posix_unlink(cli2, fname);
8453 0 : if (!NT_STATUS_IS_OK(status)) {
8454 0 : printf("cli_posix_unlink of %s failed (%s)\n",
8455 : fname,
8456 : nt_errstr(status));
8457 0 : goto out;
8458 : }
8459 :
8460 0 : printf("POSIX stream delete test passed\n");
8461 0 : correct = true;
8462 :
8463 0 : out:
8464 :
8465 0 : if (fnum1 != (uint16_t)-1) {
8466 0 : cli_close(cli1, fnum1);
8467 0 : fnum1 = (uint16_t)-1;
8468 : }
8469 :
8470 0 : cli_setatr(cli1, fname, 0, 0);
8471 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8472 :
8473 0 : if (!torture_close_connection(cli1)) {
8474 0 : correct = false;
8475 : }
8476 0 : if (!torture_close_connection(cli2)) {
8477 0 : correct = false;
8478 : }
8479 :
8480 0 : TALLOC_FREE(frame);
8481 0 : return correct;
8482 : }
8483 :
8484 : /*
8485 : Test setting EA's are rejected on symlinks.
8486 : */
8487 0 : static bool run_ea_symlink_test(int dummy)
8488 : {
8489 : static struct cli_state *cli;
8490 0 : const char *fname = "posix_file_ea";
8491 0 : const char *sname = "posix_symlink_ea";
8492 0 : const char *ea_name = "testea_name";
8493 0 : const char *ea_value = "testea_value";
8494 0 : uint16_t fnum = (uint16_t)-1;
8495 0 : bool correct = false;
8496 : NTSTATUS status;
8497 : size_t i, num_eas;
8498 0 : struct ea_struct *eas = NULL;
8499 0 : TALLOC_CTX *frame = NULL;
8500 :
8501 0 : frame = talloc_stackframe();
8502 :
8503 0 : printf("Starting EA symlink test\n");
8504 :
8505 0 : if (!torture_open_connection(&cli, 0)) {
8506 0 : TALLOC_FREE(frame);
8507 0 : return false;
8508 : }
8509 :
8510 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
8511 :
8512 0 : status = torture_setup_unix_extensions(cli);
8513 0 : if (!NT_STATUS_IS_OK(status)) {
8514 0 : TALLOC_FREE(frame);
8515 0 : return false;
8516 : }
8517 :
8518 0 : cli_setatr(cli, fname, 0, 0);
8519 0 : cli_posix_unlink(cli, fname);
8520 0 : cli_setatr(cli, sname, 0, 0);
8521 0 : cli_posix_unlink(cli, sname);
8522 :
8523 0 : status = cli_ntcreate(cli,
8524 : fname,
8525 : 0,
8526 : READ_CONTROL_ACCESS,
8527 : 0,
8528 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8529 : FILE_CREATE,
8530 : 0x0,
8531 : 0x0,
8532 : &fnum,
8533 : NULL);
8534 :
8535 0 : if (!NT_STATUS_IS_OK(status)) {
8536 0 : printf("cli_ntcreate of %s failed (%s)\n",
8537 : fname,
8538 : nt_errstr(status));
8539 0 : goto out;
8540 : }
8541 :
8542 0 : status = cli_close(cli, fnum);
8543 0 : if (!NT_STATUS_IS_OK(status)) {
8544 0 : printf("close failed (%s)\n",
8545 : nt_errstr(status));
8546 0 : goto out;
8547 : }
8548 0 : fnum = (uint16_t)-1;
8549 :
8550 : /* Set an EA on the path. */
8551 0 : status = cli_set_ea_path(cli,
8552 : fname,
8553 : ea_name,
8554 : ea_value,
8555 0 : strlen(ea_value)+1);
8556 :
8557 0 : if (!NT_STATUS_IS_OK(status)) {
8558 0 : printf("cli_set_ea_path failed (%s)\n",
8559 : nt_errstr(status));
8560 0 : goto out;
8561 : }
8562 :
8563 : /* Now create a symlink. */
8564 0 : status = cli_posix_symlink(cli, fname, sname);
8565 0 : if (!NT_STATUS_IS_OK(status)) {
8566 0 : printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8567 : sname,
8568 : fname,
8569 : nt_errstr(status));
8570 0 : goto out;
8571 : }
8572 :
8573 : /* Get the EA list on the path. Should return value set. */
8574 0 : status = cli_get_ea_list_path(cli,
8575 : fname,
8576 : frame,
8577 : &num_eas,
8578 : &eas);
8579 :
8580 0 : if (!NT_STATUS_IS_OK(status)) {
8581 0 : printf("cli_get_ea_list_path failed (%s)\n",
8582 : nt_errstr(status));
8583 0 : goto out;
8584 : }
8585 :
8586 : /* Ensure the EA we set is there. */
8587 0 : for (i=0; i<num_eas; i++) {
8588 0 : if (strcmp(eas[i].name, ea_name) == 0 &&
8589 0 : eas[i].value.length == strlen(ea_value)+1 &&
8590 0 : memcmp(eas[i].value.data,
8591 : ea_value,
8592 0 : eas[i].value.length) == 0) {
8593 0 : break;
8594 : }
8595 : }
8596 :
8597 0 : if (i == num_eas) {
8598 0 : printf("Didn't find EA on pathname %s\n",
8599 : fname);
8600 0 : goto out;
8601 : }
8602 :
8603 0 : num_eas = 0;
8604 0 : TALLOC_FREE(eas);
8605 :
8606 : /* Get the EA list on the symlink. Should return empty list. */
8607 0 : status = cli_get_ea_list_path(cli,
8608 : sname,
8609 : frame,
8610 : &num_eas,
8611 : &eas);
8612 :
8613 0 : if (!NT_STATUS_IS_OK(status)) {
8614 0 : printf("cli_get_ea_list_path failed (%s)\n",
8615 : nt_errstr(status));
8616 0 : goto out;
8617 : }
8618 :
8619 0 : if (num_eas != 0) {
8620 0 : printf("cli_get_ea_list_path failed (%s)\n",
8621 : nt_errstr(status));
8622 0 : goto out;
8623 : }
8624 :
8625 : /* Set an EA on the symlink. Should fail. */
8626 0 : status = cli_set_ea_path(cli,
8627 : sname,
8628 : ea_name,
8629 : ea_value,
8630 0 : strlen(ea_value)+1);
8631 :
8632 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8633 0 : printf("cli_set_ea_path on a symlink gave %s. "
8634 : "Should be NT_STATUS_ACCESS_DENIED.\n",
8635 : nt_errstr(status));
8636 0 : goto out;
8637 : }
8638 :
8639 0 : printf("EA symlink test passed\n");
8640 0 : correct = true;
8641 :
8642 0 : out:
8643 :
8644 0 : if (fnum != (uint16_t)-1) {
8645 0 : cli_close(cli, fnum);
8646 0 : fnum = (uint16_t)-1;
8647 : }
8648 :
8649 0 : cli_setatr(cli, sname, 0, 0);
8650 0 : cli_posix_unlink(cli, sname);
8651 0 : cli_setatr(cli, fname, 0, 0);
8652 0 : cli_posix_unlink(cli, fname);
8653 :
8654 0 : if (!torture_close_connection(cli)) {
8655 0 : correct = false;
8656 : }
8657 :
8658 0 : TALLOC_FREE(frame);
8659 0 : return correct;
8660 : }
8661 :
8662 : /*
8663 : Test POSIX locks are OFD-locks.
8664 : */
8665 0 : static bool run_posix_ofd_lock_test(int dummy)
8666 : {
8667 : static struct cli_state *cli;
8668 0 : const char *fname = "posix_file";
8669 0 : uint16_t fnum1 = (uint16_t)-1;
8670 0 : uint16_t fnum2 = (uint16_t)-1;
8671 0 : bool correct = false;
8672 : NTSTATUS status;
8673 0 : TALLOC_CTX *frame = NULL;
8674 :
8675 0 : frame = talloc_stackframe();
8676 :
8677 0 : printf("Starting POSIX ofd-lock test\n");
8678 :
8679 0 : if (!torture_open_connection(&cli, 0)) {
8680 0 : TALLOC_FREE(frame);
8681 0 : return false;
8682 : }
8683 :
8684 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
8685 :
8686 0 : status = torture_setup_unix_extensions(cli);
8687 0 : if (!NT_STATUS_IS_OK(status)) {
8688 0 : TALLOC_FREE(frame);
8689 0 : return false;
8690 : }
8691 :
8692 0 : cli_setatr(cli, fname, 0, 0);
8693 0 : cli_posix_unlink(cli, fname);
8694 :
8695 : /* Open the file twice. */
8696 0 : status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8697 : 0600, &fnum1);
8698 0 : if (!NT_STATUS_IS_OK(status)) {
8699 0 : printf("First POSIX open of %s failed\n", fname);
8700 0 : goto out;
8701 : }
8702 :
8703 0 : status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8704 0 : if (!NT_STATUS_IS_OK(status)) {
8705 0 : printf("First POSIX open of %s failed\n", fname);
8706 0 : goto out;
8707 : }
8708 :
8709 : /* Set a 0-50 lock on fnum1. */
8710 0 : status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8711 0 : if (!NT_STATUS_IS_OK(status)) {
8712 0 : printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8713 0 : goto out;
8714 : }
8715 :
8716 : /* Set a 60-100 lock on fnum2. */
8717 0 : status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8718 0 : if (!NT_STATUS_IS_OK(status)) {
8719 0 : printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8720 0 : goto out;
8721 : }
8722 :
8723 : /* close fnum1 - 0-50 lock should go away. */
8724 0 : status = cli_close(cli, fnum1);
8725 0 : if (!NT_STATUS_IS_OK(status)) {
8726 0 : printf("close failed (%s)\n",
8727 : nt_errstr(status));
8728 0 : goto out;
8729 : }
8730 0 : fnum1 = (uint16_t)-1;
8731 :
8732 : /* Change the lock context. */
8733 0 : cli_setpid(cli, cli_getpid(cli) + 1);
8734 :
8735 : /* Re-open fnum1. */
8736 0 : status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8737 0 : if (!NT_STATUS_IS_OK(status)) {
8738 0 : printf("Third POSIX open of %s failed\n", fname);
8739 0 : goto out;
8740 : }
8741 :
8742 : /* 60-100 lock should still be there. */
8743 0 : status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8744 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8745 0 : printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8746 0 : goto out;
8747 : }
8748 :
8749 : /* 0-50 lock should be gone. */
8750 0 : status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8751 0 : if (!NT_STATUS_IS_OK(status)) {
8752 0 : printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8753 0 : goto out;
8754 : }
8755 :
8756 0 : printf("POSIX OFD lock test passed\n");
8757 0 : correct = true;
8758 :
8759 0 : out:
8760 :
8761 0 : if (fnum1 != (uint16_t)-1) {
8762 0 : cli_close(cli, fnum1);
8763 0 : fnum1 = (uint16_t)-1;
8764 : }
8765 0 : if (fnum2 != (uint16_t)-1) {
8766 0 : cli_close(cli, fnum2);
8767 0 : fnum2 = (uint16_t)-1;
8768 : }
8769 :
8770 0 : cli_setatr(cli, fname, 0, 0);
8771 0 : cli_posix_unlink(cli, fname);
8772 :
8773 0 : if (!torture_close_connection(cli)) {
8774 0 : correct = false;
8775 : }
8776 :
8777 0 : TALLOC_FREE(frame);
8778 0 : return correct;
8779 : }
8780 :
8781 : struct posix_blocking_state {
8782 : struct tevent_context *ev;
8783 : struct cli_state *cli1;
8784 : uint16_t fnum1;
8785 : struct cli_state *cli2;
8786 : uint16_t fnum2;
8787 : bool gotblocked;
8788 : bool gotecho;
8789 : };
8790 :
8791 : static void posix_blocking_locked(struct tevent_req *subreq);
8792 : static void posix_blocking_gotblocked(struct tevent_req *subreq);
8793 : static void posix_blocking_gotecho(struct tevent_req *subreq);
8794 : static void posix_blocking_unlocked(struct tevent_req *subreq);
8795 :
8796 0 : static struct tevent_req *posix_blocking_send(
8797 : TALLOC_CTX *mem_ctx,
8798 : struct tevent_context *ev,
8799 : struct cli_state *cli1,
8800 : uint16_t fnum1,
8801 : struct cli_state *cli2,
8802 : uint16_t fnum2)
8803 : {
8804 0 : struct tevent_req *req = NULL, *subreq = NULL;
8805 0 : struct posix_blocking_state *state = NULL;
8806 :
8807 0 : req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8808 0 : if (req == NULL) {
8809 0 : return NULL;
8810 : }
8811 0 : state->ev = ev;
8812 0 : state->cli1 = cli1;
8813 0 : state->fnum1 = fnum1;
8814 0 : state->cli2 = cli2;
8815 0 : state->fnum2 = fnum2;
8816 :
8817 0 : subreq = cli_posix_lock_send(
8818 : state,
8819 0 : state->ev,
8820 0 : state->cli1,
8821 0 : state->fnum1,
8822 : 0,
8823 : 1,
8824 : false,
8825 : WRITE_LOCK);
8826 0 : if (tevent_req_nomem(subreq, req)) {
8827 0 : return tevent_req_post(req, ev);
8828 : }
8829 0 : tevent_req_set_callback(subreq, posix_blocking_locked, req);
8830 0 : return req;
8831 : }
8832 :
8833 0 : static void posix_blocking_locked(struct tevent_req *subreq)
8834 : {
8835 0 : struct tevent_req *req = tevent_req_callback_data(
8836 : subreq, struct tevent_req);
8837 0 : struct posix_blocking_state *state = tevent_req_data(
8838 : req, struct posix_blocking_state);
8839 : NTSTATUS status;
8840 :
8841 0 : status = cli_posix_lock_recv(subreq);
8842 0 : TALLOC_FREE(subreq);
8843 0 : if (tevent_req_nterror(req, status)) {
8844 0 : return;
8845 : }
8846 :
8847 0 : subreq = cli_posix_lock_send(
8848 : state,
8849 : state->ev,
8850 : state->cli2,
8851 0 : state->fnum2,
8852 : 0,
8853 : 1,
8854 : true,
8855 : WRITE_LOCK);
8856 0 : if (tevent_req_nomem(subreq, req)) {
8857 0 : return;
8858 : }
8859 0 : tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8860 :
8861 : /* Make sure the blocking request is delivered */
8862 0 : subreq = cli_echo_send(
8863 : state,
8864 : state->ev,
8865 : state->cli2,
8866 : 1,
8867 0 : (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8868 0 : if (tevent_req_nomem(subreq, req)) {
8869 0 : return;
8870 : }
8871 0 : tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8872 : }
8873 :
8874 0 : static void posix_blocking_gotblocked(struct tevent_req *subreq)
8875 : {
8876 0 : struct tevent_req *req = tevent_req_callback_data(
8877 : subreq, struct tevent_req);
8878 0 : struct posix_blocking_state *state = tevent_req_data(
8879 : req, struct posix_blocking_state);
8880 : NTSTATUS status;
8881 :
8882 0 : status = cli_posix_lock_recv(subreq);
8883 0 : TALLOC_FREE(subreq);
8884 0 : if (tevent_req_nterror(req, status)) {
8885 0 : return;
8886 : }
8887 0 : if (!state->gotecho) {
8888 0 : printf("blocked req got through before echo\n");
8889 0 : tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8890 0 : return;
8891 : }
8892 0 : tevent_req_done(req);
8893 : }
8894 :
8895 0 : static void posix_blocking_gotecho(struct tevent_req *subreq)
8896 : {
8897 0 : struct tevent_req *req = tevent_req_callback_data(
8898 : subreq, struct tevent_req);
8899 0 : struct posix_blocking_state *state = tevent_req_data(
8900 : req, struct posix_blocking_state);
8901 : NTSTATUS status;
8902 :
8903 0 : status = cli_echo_recv(subreq);
8904 0 : TALLOC_FREE(subreq);
8905 0 : if (tevent_req_nterror(req, status)) {
8906 0 : return;
8907 : }
8908 0 : if (state->gotblocked) {
8909 0 : printf("blocked req got through before echo\n");
8910 0 : tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8911 0 : return;
8912 : }
8913 0 : state->gotecho = true;
8914 :
8915 0 : subreq = cli_posix_lock_send(
8916 : state,
8917 : state->ev,
8918 : state->cli1,
8919 0 : state->fnum1,
8920 : 0,
8921 : 1,
8922 : false,
8923 : UNLOCK_LOCK);
8924 0 : if (tevent_req_nomem(subreq, req)) {
8925 0 : return;
8926 : }
8927 0 : tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
8928 : }
8929 :
8930 0 : static void posix_blocking_unlocked(struct tevent_req *subreq)
8931 : {
8932 0 : struct tevent_req *req = tevent_req_callback_data(
8933 : subreq, struct tevent_req);
8934 : NTSTATUS status;
8935 :
8936 0 : status = cli_posix_lock_recv(subreq);
8937 0 : TALLOC_FREE(subreq);
8938 0 : if (tevent_req_nterror(req, status)) {
8939 0 : return;
8940 : }
8941 : /* tevent_req_done in posix_blocking_gotlocked */
8942 : }
8943 :
8944 0 : static NTSTATUS posix_blocking_recv(struct tevent_req *req)
8945 : {
8946 0 : return tevent_req_simple_recv_ntstatus(req);
8947 : }
8948 :
8949 0 : static bool run_posix_blocking_lock(int dummy)
8950 : {
8951 0 : struct tevent_context *ev = NULL;
8952 0 : struct cli_state *cli1 = NULL, *cli2 = NULL;
8953 0 : const char *fname = "posix_blocking";
8954 0 : uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
8955 0 : struct tevent_req *req = NULL;
8956 : NTSTATUS status;
8957 0 : bool ret = false;
8958 : bool ok;
8959 :
8960 0 : printf("Starting posix blocking lock test\n");
8961 :
8962 0 : ev = samba_tevent_context_init(NULL);
8963 0 : if (ev == NULL) {
8964 0 : return false;
8965 : }
8966 :
8967 0 : ok = torture_open_connection(&cli1, 0);
8968 0 : if (!ok) {
8969 0 : goto fail;
8970 : }
8971 0 : ok = torture_open_connection(&cli2, 0);
8972 0 : if (!ok) {
8973 0 : goto fail;
8974 : }
8975 :
8976 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
8977 :
8978 0 : status = torture_setup_unix_extensions(cli1);
8979 0 : if (!NT_STATUS_IS_OK(status)) {
8980 0 : return false;
8981 : }
8982 :
8983 0 : status = torture_setup_unix_extensions(cli2);
8984 0 : if (!NT_STATUS_IS_OK(status)) {
8985 0 : return false;
8986 : }
8987 :
8988 0 : cli_setatr(cli1, fname, 0, 0);
8989 0 : cli_posix_unlink(cli1, fname);
8990 :
8991 0 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8992 : 0600, &fnum1);
8993 0 : if (!NT_STATUS_IS_OK(status)) {
8994 0 : printf("First POSIX open of %s failed: %s\n",
8995 : fname,
8996 : nt_errstr(status));
8997 0 : goto fail;
8998 : }
8999 :
9000 0 : status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
9001 0 : if (!NT_STATUS_IS_OK(status)) {
9002 0 : printf("Second POSIX open of %s failed: %s\n",
9003 : fname,
9004 : nt_errstr(status));
9005 0 : goto fail;
9006 : }
9007 :
9008 0 : req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9009 0 : if (req == NULL) {
9010 0 : printf("cli_posix_blocking failed\n");
9011 0 : goto fail;
9012 : }
9013 :
9014 0 : ok = tevent_req_poll_ntstatus(req, ev, &status);
9015 0 : if (!ok) {
9016 0 : printf("tevent_req_poll_ntstatus failed: %s\n",
9017 : nt_errstr(status));
9018 0 : goto fail;
9019 : }
9020 0 : status = posix_blocking_recv(req);
9021 0 : TALLOC_FREE(req);
9022 0 : if (!NT_STATUS_IS_OK(status)) {
9023 0 : printf("posix_blocking_recv returned %s\n",
9024 : nt_errstr(status));
9025 0 : goto fail;
9026 : }
9027 :
9028 0 : ret = true;
9029 0 : fail:
9030 :
9031 0 : if (fnum1 != UINT16_MAX) {
9032 0 : cli_close(cli1, fnum1);
9033 0 : fnum1 = UINT16_MAX;
9034 : }
9035 0 : if (fnum2 != UINT16_MAX) {
9036 0 : cli_close(cli2, fnum2);
9037 0 : fnum2 = UINT16_MAX;
9038 : }
9039 :
9040 0 : if (cli1 != NULL) {
9041 0 : cli_setatr(cli1, fname, 0, 0);
9042 0 : cli_posix_unlink(cli1, fname);
9043 : }
9044 :
9045 0 : ok = true;
9046 :
9047 0 : if (cli1 != NULL) {
9048 0 : ok &= torture_close_connection(cli1);
9049 0 : cli1 = NULL;
9050 : }
9051 0 : if (cli2 != NULL) {
9052 0 : ok &= torture_close_connection(cli2);
9053 0 : cli2 = NULL;
9054 : }
9055 :
9056 0 : if (!ok) {
9057 0 : ret = false;
9058 : }
9059 0 : TALLOC_FREE(ev);
9060 0 : return ret;
9061 : }
9062 :
9063 : /*
9064 : Test POSIX mkdir is case-sensitive.
9065 : */
9066 0 : static bool run_posix_mkdir_test(int dummy)
9067 : {
9068 : static struct cli_state *cli;
9069 0 : const char *fname_foo = "POSIX_foo";
9070 0 : const char *fname_foo_Foo = "POSIX_foo/Foo";
9071 0 : const char *fname_foo_foo = "POSIX_foo/foo";
9072 0 : const char *fname_Foo = "POSIX_Foo";
9073 0 : const char *fname_Foo_Foo = "POSIX_Foo/Foo";
9074 0 : const char *fname_Foo_foo = "POSIX_Foo/foo";
9075 0 : bool correct = false;
9076 : NTSTATUS status;
9077 0 : TALLOC_CTX *frame = NULL;
9078 0 : uint16_t fnum = (uint16_t)-1;
9079 :
9080 0 : frame = talloc_stackframe();
9081 :
9082 0 : printf("Starting POSIX mkdir test\n");
9083 :
9084 0 : if (!torture_open_connection(&cli, 0)) {
9085 0 : TALLOC_FREE(frame);
9086 0 : return false;
9087 : }
9088 :
9089 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
9090 :
9091 0 : status = torture_setup_unix_extensions(cli);
9092 0 : if (!NT_STATUS_IS_OK(status)) {
9093 0 : TALLOC_FREE(frame);
9094 0 : return false;
9095 : }
9096 :
9097 0 : cli_posix_rmdir(cli, fname_foo_foo);
9098 0 : cli_posix_rmdir(cli, fname_foo_Foo);
9099 0 : cli_posix_rmdir(cli, fname_foo);
9100 :
9101 0 : cli_posix_rmdir(cli, fname_Foo_foo);
9102 0 : cli_posix_rmdir(cli, fname_Foo_Foo);
9103 0 : cli_posix_rmdir(cli, fname_Foo);
9104 :
9105 : /*
9106 : * Create a file POSIX_foo then try
9107 : * and use it in a directory path by
9108 : * doing mkdir POSIX_foo/bar.
9109 : * The mkdir should fail with
9110 : * NT_STATUS_OBJECT_PATH_NOT_FOUND
9111 : */
9112 :
9113 0 : status = cli_posix_open(cli,
9114 : fname_foo,
9115 : O_RDWR|O_CREAT,
9116 : 0666,
9117 : &fnum);
9118 0 : if (!NT_STATUS_IS_OK(status)) {
9119 0 : printf("cli_posix_open of %s failed error %s\n",
9120 : fname_foo,
9121 : nt_errstr(status));
9122 0 : goto out;
9123 : }
9124 :
9125 0 : status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9126 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9127 0 : printf("cli_posix_mkdir of %s should fail with "
9128 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9129 : "%s instead\n",
9130 : fname_foo_foo,
9131 : nt_errstr(status));
9132 0 : goto out;
9133 : }
9134 :
9135 0 : status = cli_close(cli, fnum);
9136 0 : if (!NT_STATUS_IS_OK(status)) {
9137 0 : printf("cli_close failed %s\n", nt_errstr(status));
9138 0 : goto out;
9139 : }
9140 0 : fnum = (uint16_t)-1;
9141 :
9142 0 : status = cli_posix_unlink(cli, fname_foo);
9143 0 : if (!NT_STATUS_IS_OK(status)) {
9144 0 : printf("cli_posix_unlink of %s failed error %s\n",
9145 : fname_foo,
9146 : nt_errstr(status));
9147 0 : goto out;
9148 : }
9149 :
9150 : /*
9151 : * Now we've deleted everything, posix_mkdir, posix_rmdir,
9152 : * posix_open, posix_unlink, on
9153 : * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9154 : * not silently create POSIX_foo/foo.
9155 : */
9156 :
9157 0 : status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9158 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9159 0 : printf("cli_posix_mkdir of %s should fail with "
9160 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9161 : "%s instead\n",
9162 : fname_foo_foo,
9163 : nt_errstr(status));
9164 0 : goto out;
9165 : }
9166 :
9167 0 : status = cli_posix_rmdir(cli, fname_foo_foo);
9168 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9169 0 : printf("cli_posix_rmdir of %s should fail with "
9170 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9171 : "%s instead\n",
9172 : fname_foo_foo,
9173 : nt_errstr(status));
9174 0 : goto out;
9175 : }
9176 :
9177 0 : status = cli_posix_open(cli,
9178 : fname_foo_foo,
9179 : O_RDWR|O_CREAT,
9180 : 0666,
9181 : &fnum);
9182 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9183 0 : printf("cli_posix_open of %s should fail with "
9184 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9185 : "%s instead\n",
9186 : fname_foo_foo,
9187 : nt_errstr(status));
9188 0 : goto out;
9189 : }
9190 :
9191 0 : status = cli_posix_unlink(cli, fname_foo_foo);
9192 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9193 0 : printf("cli_posix_unlink of %s should fail with "
9194 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9195 : "%s instead\n",
9196 : fname_foo_foo,
9197 : nt_errstr(status));
9198 0 : goto out;
9199 : }
9200 :
9201 0 : status = cli_posix_mkdir(cli, fname_foo, 0777);
9202 0 : if (!NT_STATUS_IS_OK(status)) {
9203 0 : printf("cli_posix_mkdir of %s failed\n", fname_foo);
9204 0 : goto out;
9205 : }
9206 :
9207 0 : status = cli_posix_mkdir(cli, fname_Foo, 0777);
9208 0 : if (!NT_STATUS_IS_OK(status)) {
9209 0 : printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9210 0 : goto out;
9211 : }
9212 :
9213 0 : status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9214 0 : if (!NT_STATUS_IS_OK(status)) {
9215 0 : printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9216 0 : goto out;
9217 : }
9218 :
9219 0 : status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9220 0 : if (!NT_STATUS_IS_OK(status)) {
9221 0 : printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9222 0 : goto out;
9223 : }
9224 :
9225 0 : status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9226 0 : if (!NT_STATUS_IS_OK(status)) {
9227 0 : printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9228 0 : goto out;
9229 : }
9230 :
9231 0 : status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9232 0 : if (!NT_STATUS_IS_OK(status)) {
9233 0 : printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9234 0 : goto out;
9235 : }
9236 :
9237 0 : printf("POSIX mkdir test passed\n");
9238 0 : correct = true;
9239 :
9240 0 : out:
9241 :
9242 0 : if (fnum != (uint16_t)-1) {
9243 0 : cli_close(cli, fnum);
9244 0 : fnum = (uint16_t)-1;
9245 : }
9246 :
9247 0 : cli_posix_rmdir(cli, fname_foo_foo);
9248 0 : cli_posix_rmdir(cli, fname_foo_Foo);
9249 0 : cli_posix_rmdir(cli, fname_foo);
9250 :
9251 0 : cli_posix_rmdir(cli, fname_Foo_foo);
9252 0 : cli_posix_rmdir(cli, fname_Foo_Foo);
9253 0 : cli_posix_rmdir(cli, fname_Foo);
9254 :
9255 0 : if (!torture_close_connection(cli)) {
9256 0 : correct = false;
9257 : }
9258 :
9259 0 : TALLOC_FREE(frame);
9260 0 : return correct;
9261 : }
9262 :
9263 : struct posix_acl_oplock_state {
9264 : struct tevent_context *ev;
9265 : struct cli_state *cli;
9266 : bool *got_break;
9267 : bool *acl_ret;
9268 : NTSTATUS status;
9269 : };
9270 :
9271 0 : static void posix_acl_oplock_got_break(struct tevent_req *req)
9272 : {
9273 0 : struct posix_acl_oplock_state *state = tevent_req_callback_data(
9274 : req, struct posix_acl_oplock_state);
9275 : uint16_t fnum;
9276 : uint8_t level;
9277 : NTSTATUS status;
9278 :
9279 0 : status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9280 0 : TALLOC_FREE(req);
9281 0 : if (!NT_STATUS_IS_OK(status)) {
9282 0 : printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9283 : nt_errstr(status));
9284 0 : return;
9285 : }
9286 0 : *state->got_break = true;
9287 :
9288 0 : req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9289 : NO_OPLOCK);
9290 0 : if (req == NULL) {
9291 0 : printf("cli_oplock_ack_send failed\n");
9292 0 : return;
9293 : }
9294 : }
9295 :
9296 0 : static void posix_acl_oplock_got_acl(struct tevent_req *req)
9297 : {
9298 0 : struct posix_acl_oplock_state *state = tevent_req_callback_data(
9299 : req, struct posix_acl_oplock_state);
9300 0 : size_t ret_size = 0;
9301 0 : char *ret_data = NULL;
9302 :
9303 0 : state->status = cli_posix_getacl_recv(req,
9304 : state,
9305 : &ret_size,
9306 : &ret_data);
9307 :
9308 0 : if (!NT_STATUS_IS_OK(state->status)) {
9309 0 : printf("cli_posix_getacl_recv returned %s\n",
9310 : nt_errstr(state->status));
9311 : }
9312 0 : *state->acl_ret = true;
9313 0 : }
9314 :
9315 0 : static bool run_posix_acl_oplock_test(int dummy)
9316 : {
9317 : struct tevent_context *ev;
9318 : struct cli_state *cli1, *cli2;
9319 : struct tevent_req *oplock_req, *getacl_req;
9320 0 : const char *fname = "posix_acl_oplock";
9321 : uint16_t fnum;
9322 0 : int saved_use_oplocks = use_oplocks;
9323 : NTSTATUS status;
9324 0 : bool correct = true;
9325 0 : bool got_break = false;
9326 0 : bool acl_ret = false;
9327 :
9328 : struct posix_acl_oplock_state *state;
9329 :
9330 0 : printf("starting posix_acl_oplock test\n");
9331 :
9332 0 : if (!torture_open_connection(&cli1, 0)) {
9333 0 : use_level_II_oplocks = false;
9334 0 : use_oplocks = saved_use_oplocks;
9335 0 : return false;
9336 : }
9337 :
9338 0 : if (!torture_open_connection(&cli2, 1)) {
9339 0 : use_level_II_oplocks = false;
9340 0 : use_oplocks = saved_use_oplocks;
9341 0 : return false;
9342 : }
9343 :
9344 : /* Setup posix on cli2 only. */
9345 0 : status = torture_setup_unix_extensions(cli2);
9346 0 : if (!NT_STATUS_IS_OK(status)) {
9347 0 : return false;
9348 : }
9349 :
9350 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
9351 0 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
9352 :
9353 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9354 :
9355 : /* Create the file on the Windows connection. */
9356 0 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9357 : &fnum);
9358 0 : if (!NT_STATUS_IS_OK(status)) {
9359 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9360 0 : return false;
9361 : }
9362 :
9363 0 : status = cli_close(cli1, fnum);
9364 0 : if (!NT_STATUS_IS_OK(status)) {
9365 0 : printf("close1 failed (%s)\n", nt_errstr(status));
9366 0 : return false;
9367 : }
9368 :
9369 0 : cli1->use_oplocks = true;
9370 :
9371 : /* Open with oplock. */
9372 0 : status = cli_ntcreate(cli1,
9373 : fname,
9374 : 0,
9375 : FILE_READ_DATA,
9376 : FILE_ATTRIBUTE_NORMAL,
9377 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9378 : FILE_OPEN,
9379 : 0,
9380 : 0,
9381 : &fnum,
9382 : NULL);
9383 :
9384 0 : if (!NT_STATUS_IS_OK(status)) {
9385 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9386 0 : return false;
9387 : }
9388 :
9389 0 : ev = samba_tevent_context_init(talloc_tos());
9390 0 : if (ev == NULL) {
9391 0 : printf("tevent_context_init failed\n");
9392 0 : return false;
9393 : }
9394 :
9395 0 : state = talloc_zero(ev, struct posix_acl_oplock_state);
9396 0 : if (state == NULL) {
9397 0 : printf("talloc failed\n");
9398 0 : return false;
9399 : }
9400 0 : state->ev = ev;
9401 0 : state->cli = cli1;
9402 0 : state->got_break = &got_break;
9403 0 : state->acl_ret = &acl_ret;
9404 :
9405 0 : oplock_req = cli_smb_oplock_break_waiter_send(
9406 : talloc_tos(), ev, cli1);
9407 0 : if (oplock_req == NULL) {
9408 0 : printf("cli_smb_oplock_break_waiter_send failed\n");
9409 0 : return false;
9410 : }
9411 0 : tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9412 :
9413 : /* Get ACL on POSIX connection - should break oplock. */
9414 0 : getacl_req = cli_posix_getacl_send(talloc_tos(),
9415 : ev,
9416 : cli2,
9417 : fname);
9418 0 : if (getacl_req == NULL) {
9419 0 : printf("cli_posix_getacl_send failed\n");
9420 0 : return false;
9421 : }
9422 0 : tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9423 :
9424 0 : while (!got_break || !acl_ret) {
9425 : int ret;
9426 0 : ret = tevent_loop_once(ev);
9427 0 : if (ret == -1) {
9428 0 : printf("tevent_loop_once failed: %s\n",
9429 0 : strerror(errno));
9430 0 : return false;
9431 : }
9432 : }
9433 :
9434 0 : if (!NT_STATUS_IS_OK(state->status)) {
9435 0 : printf("getacl failed (%s)\n", nt_errstr(state->status));
9436 0 : correct = false;
9437 : }
9438 :
9439 0 : status = cli_close(cli1, fnum);
9440 0 : if (!NT_STATUS_IS_OK(status)) {
9441 0 : printf("close2 failed (%s)\n", nt_errstr(status));
9442 0 : correct = false;
9443 : }
9444 :
9445 0 : status = cli_unlink(cli1,
9446 : fname,
9447 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9448 0 : if (!NT_STATUS_IS_OK(status)) {
9449 0 : printf("unlink failed (%s)\n", nt_errstr(status));
9450 0 : correct = false;
9451 : }
9452 :
9453 0 : if (!torture_close_connection(cli1)) {
9454 0 : correct = false;
9455 : }
9456 0 : if (!torture_close_connection(cli2)) {
9457 0 : correct = false;
9458 : }
9459 :
9460 0 : if (!got_break) {
9461 0 : correct = false;
9462 : }
9463 :
9464 0 : printf("finished posix acl oplock test\n");
9465 :
9466 0 : return correct;
9467 : }
9468 :
9469 0 : static bool run_posix_acl_shareroot_test(int dummy)
9470 : {
9471 : struct cli_state *cli;
9472 : NTSTATUS status;
9473 0 : bool correct = false;
9474 0 : char *posix_acl = NULL;
9475 0 : size_t posix_acl_len = 0;
9476 0 : uint16_t num_file_acls = 0;
9477 0 : uint16_t num_dir_acls = 0;
9478 : uint16_t i;
9479 0 : uint32_t expected_size = 0;
9480 0 : bool got_user = false;
9481 0 : bool got_group = false;
9482 0 : bool got_other = false;
9483 0 : TALLOC_CTX *frame = NULL;
9484 :
9485 0 : frame = talloc_stackframe();
9486 :
9487 0 : printf("starting posix_acl_shareroot test\n");
9488 :
9489 0 : if (!torture_open_connection(&cli, 0)) {
9490 0 : TALLOC_FREE(frame);
9491 0 : return false;
9492 : }
9493 :
9494 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
9495 :
9496 0 : status = torture_setup_unix_extensions(cli);
9497 0 : if (!NT_STATUS_IS_OK(status)) {
9498 0 : printf("Failed to setup unix extensions\n");
9499 0 : goto out;
9500 : }
9501 :
9502 : /* Get the POSIX ACL on the root of the share. */
9503 0 : status = cli_posix_getacl(cli,
9504 : ".",
9505 : frame,
9506 : &posix_acl_len,
9507 : &posix_acl);
9508 :
9509 0 : if (!NT_STATUS_IS_OK(status)) {
9510 0 : printf("cli_posix_getacl of '.' failed (%s)\n",
9511 : nt_errstr(status));
9512 0 : goto out;
9513 : }
9514 :
9515 0 : if (posix_acl_len < 6 ||
9516 0 : SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9517 0 : printf("getfacl ., unknown POSIX acl version %u.\n",
9518 0 : (unsigned int)CVAL(posix_acl,0) );
9519 0 : goto out;
9520 : }
9521 :
9522 0 : num_file_acls = SVAL(posix_acl,2);
9523 0 : num_dir_acls = SVAL(posix_acl,4);
9524 0 : expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9525 0 : SMB_POSIX_ACL_ENTRY_SIZE*
9526 0 : (num_file_acls+num_dir_acls);
9527 :
9528 0 : if (posix_acl_len != expected_size) {
9529 0 : printf("incorrect POSIX acl buffer size "
9530 : "(should be %u, was %u).\n",
9531 : (unsigned int)expected_size,
9532 : (unsigned int)posix_acl_len);
9533 0 : goto out;
9534 : }
9535 :
9536 : /*
9537 : * We don't need to know what the ACL's are
9538 : * we just need to know we have at least 3
9539 : * file entries (u,g,o).
9540 : */
9541 :
9542 0 : for (i = 0; i < num_file_acls; i++) {
9543 0 : unsigned char tagtype =
9544 0 : CVAL(posix_acl,
9545 : SMB_POSIX_ACL_HEADER_SIZE+
9546 : (i*SMB_POSIX_ACL_ENTRY_SIZE));
9547 :
9548 0 : switch(tagtype) {
9549 0 : case SMB_POSIX_ACL_USER_OBJ:
9550 0 : got_user = true;
9551 0 : break;
9552 0 : case SMB_POSIX_ACL_GROUP_OBJ:
9553 0 : got_group = true;
9554 0 : break;
9555 0 : case SMB_POSIX_ACL_OTHER:
9556 0 : got_other = true;
9557 0 : break;
9558 0 : default:
9559 0 : break;
9560 : }
9561 : }
9562 :
9563 0 : if (!got_user) {
9564 0 : printf("Missing user entry\n");
9565 0 : goto out;
9566 : }
9567 :
9568 0 : if (!got_group) {
9569 0 : printf("Missing group entry\n");
9570 0 : goto out;
9571 : }
9572 :
9573 0 : if (!got_other) {
9574 0 : printf("Missing other entry\n");
9575 0 : goto out;
9576 : }
9577 :
9578 0 : correct = true;
9579 :
9580 0 : out:
9581 :
9582 0 : if (!torture_close_connection(cli)) {
9583 0 : correct = false;
9584 : }
9585 :
9586 0 : printf("finished posix acl shareroot test\n");
9587 0 : TALLOC_FREE(frame);
9588 :
9589 0 : return correct;
9590 : }
9591 :
9592 : static uint32_t open_attrs_table[] = {
9593 : FILE_ATTRIBUTE_NORMAL,
9594 : FILE_ATTRIBUTE_ARCHIVE,
9595 : FILE_ATTRIBUTE_READONLY,
9596 : FILE_ATTRIBUTE_HIDDEN,
9597 : FILE_ATTRIBUTE_SYSTEM,
9598 :
9599 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9600 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9601 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9602 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9603 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9604 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9605 :
9606 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9607 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9608 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9609 : FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9610 : };
9611 :
9612 : struct trunc_open_results {
9613 : unsigned int num;
9614 : uint32_t init_attr;
9615 : uint32_t trunc_attr;
9616 : uint32_t result_attr;
9617 : };
9618 :
9619 : static struct trunc_open_results attr_results[] = {
9620 : { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9621 : { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9622 : { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9623 : { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9624 : { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9625 : { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9626 : { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9627 : { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9628 : { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9629 : { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9630 : { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9631 : { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9632 : { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9633 : { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9634 : { 104, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9635 : { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9636 : { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9637 : { 121, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9638 : { 170, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN },
9639 : { 173, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM },
9640 : { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9641 : { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9642 : { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9643 : { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9644 : { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9645 : { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9646 : };
9647 :
9648 0 : static bool run_openattrtest(int dummy)
9649 : {
9650 : static struct cli_state *cli1;
9651 0 : const char *fname = "\\openattr.file";
9652 : uint16_t fnum1;
9653 0 : bool correct = True;
9654 : uint32_t attr;
9655 : unsigned int i, j, k, l;
9656 : NTSTATUS status;
9657 :
9658 0 : printf("starting open attr test\n");
9659 :
9660 0 : if (!torture_open_connection(&cli1, 0)) {
9661 0 : return False;
9662 : }
9663 :
9664 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
9665 :
9666 0 : for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9667 0 : cli_setatr(cli1, fname, 0, 0);
9668 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9669 :
9670 0 : status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9671 : open_attrs_table[i], FILE_SHARE_NONE,
9672 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9673 0 : if (!NT_STATUS_IS_OK(status)) {
9674 0 : printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9675 0 : return False;
9676 : }
9677 :
9678 0 : status = cli_close(cli1, fnum1);
9679 0 : if (!NT_STATUS_IS_OK(status)) {
9680 0 : printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9681 0 : return False;
9682 : }
9683 :
9684 0 : for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9685 0 : status = cli_ntcreate(cli1, fname, 0,
9686 : FILE_READ_DATA|FILE_WRITE_DATA,
9687 : open_attrs_table[j],
9688 : FILE_SHARE_NONE, FILE_OVERWRITE,
9689 : 0, 0, &fnum1, NULL);
9690 0 : if (!NT_STATUS_IS_OK(status)) {
9691 0 : for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9692 0 : if (attr_results[l].num == k) {
9693 0 : printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9694 : k, open_attrs_table[i],
9695 : open_attrs_table[j],
9696 : fname, NT_STATUS_V(status), nt_errstr(status));
9697 0 : correct = False;
9698 : }
9699 : }
9700 :
9701 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9702 0 : printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9703 : k, open_attrs_table[i], open_attrs_table[j],
9704 : nt_errstr(status));
9705 0 : correct = False;
9706 : }
9707 : #if 0
9708 : printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9709 : #endif
9710 0 : k++;
9711 0 : continue;
9712 : }
9713 :
9714 0 : status = cli_close(cli1, fnum1);
9715 0 : if (!NT_STATUS_IS_OK(status)) {
9716 0 : printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9717 0 : return False;
9718 : }
9719 :
9720 0 : status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9721 0 : if (!NT_STATUS_IS_OK(status)) {
9722 0 : printf("getatr(2) failed (%s)\n", nt_errstr(status));
9723 0 : return False;
9724 : }
9725 :
9726 : #if 0
9727 : printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9728 : k, open_attrs_table[i], open_attrs_table[j], attr );
9729 : #endif
9730 :
9731 0 : for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9732 0 : if (attr_results[l].num == k) {
9733 0 : if (attr != attr_results[l].result_attr ||
9734 0 : open_attrs_table[i] != attr_results[l].init_attr ||
9735 0 : open_attrs_table[j] != attr_results[l].trunc_attr) {
9736 0 : printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9737 : open_attrs_table[i],
9738 : open_attrs_table[j],
9739 : (unsigned int)attr,
9740 : attr_results[l].result_attr);
9741 0 : correct = False;
9742 : }
9743 0 : break;
9744 : }
9745 : }
9746 0 : k++;
9747 : }
9748 : }
9749 :
9750 0 : cli_setatr(cli1, fname, 0, 0);
9751 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9752 :
9753 0 : printf("open attr test %s.\n", correct ? "passed" : "failed");
9754 :
9755 0 : if (!torture_close_connection(cli1)) {
9756 0 : correct = False;
9757 : }
9758 0 : return correct;
9759 : }
9760 :
9761 0 : static NTSTATUS list_fn(struct file_info *finfo,
9762 : const char *name, void *state)
9763 : {
9764 0 : int *matched = (int *)state;
9765 0 : if (matched != NULL) {
9766 0 : *matched += 1;
9767 : }
9768 0 : return NT_STATUS_OK;
9769 : }
9770 :
9771 : /*
9772 : test directory listing speed
9773 : */
9774 1 : static bool run_dirtest(int dummy)
9775 : {
9776 : int i;
9777 : static struct cli_state *cli;
9778 : uint16_t fnum;
9779 : struct timeval core_start;
9780 1 : bool correct = True;
9781 : int matched;
9782 :
9783 1 : printf("starting directory test\n");
9784 :
9785 1 : if (!torture_open_connection(&cli, 0)) {
9786 0 : return False;
9787 : }
9788 :
9789 1 : smbXcli_conn_set_sockopt(cli->conn, sockops);
9790 :
9791 1 : srandom(0);
9792 101 : for (i=0;i<torture_numops;i++) {
9793 : fstring fname;
9794 100 : slprintf(fname, sizeof(fname), "\\%x", (int)random());
9795 100 : if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9796 0 : fprintf(stderr,"Failed to open %s\n", fname);
9797 0 : return False;
9798 : }
9799 100 : cli_close(cli, fnum);
9800 : }
9801 :
9802 1 : core_start = timeval_current();
9803 :
9804 1 : matched = 0;
9805 1 : cli_list(cli, "a*.*", 0, list_fn, &matched);
9806 1 : printf("Matched %d\n", matched);
9807 :
9808 1 : matched = 0;
9809 1 : cli_list(cli, "b*.*", 0, list_fn, &matched);
9810 1 : printf("Matched %d\n", matched);
9811 :
9812 1 : matched = 0;
9813 1 : cli_list(cli, "xyzabc", 0, list_fn, &matched);
9814 1 : printf("Matched %d\n", matched);
9815 :
9816 1 : printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9817 :
9818 1 : srandom(0);
9819 101 : for (i=0;i<torture_numops;i++) {
9820 : fstring fname;
9821 100 : slprintf(fname, sizeof(fname), "\\%x", (int)random());
9822 100 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9823 : }
9824 :
9825 1 : if (!torture_close_connection(cli)) {
9826 0 : correct = False;
9827 : }
9828 :
9829 1 : printf("finished dirtest\n");
9830 :
9831 1 : return correct;
9832 : }
9833 :
9834 0 : static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9835 : void *state)
9836 : {
9837 0 : struct cli_state *pcli = (struct cli_state *)state;
9838 : fstring fname;
9839 0 : slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9840 :
9841 0 : if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9842 0 : return NT_STATUS_OK;
9843 :
9844 0 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9845 0 : if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9846 0 : printf("del_fn: failed to rmdir %s\n,", fname );
9847 : } else {
9848 0 : if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9849 0 : printf("del_fn: failed to unlink %s\n,", fname );
9850 : }
9851 0 : return NT_STATUS_OK;
9852 : }
9853 :
9854 :
9855 : /*
9856 : sees what IOCTLs are supported
9857 : */
9858 1 : bool torture_ioctl_test(int dummy)
9859 : {
9860 : static struct cli_state *cli;
9861 : uint16_t device, function;
9862 : uint16_t fnum;
9863 1 : const char *fname = "\\ioctl.dat";
9864 : DATA_BLOB blob;
9865 : NTSTATUS status;
9866 :
9867 1 : if (!torture_open_connection(&cli, 0)) {
9868 0 : return False;
9869 : }
9870 :
9871 1 : printf("starting ioctl test\n");
9872 :
9873 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9874 :
9875 1 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9876 1 : if (!NT_STATUS_IS_OK(status)) {
9877 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9878 0 : return False;
9879 : }
9880 :
9881 1 : status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9882 1 : printf("ioctl device info: %s\n", nt_errstr(status));
9883 :
9884 1 : status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9885 1 : printf("ioctl job info: %s\n", nt_errstr(status));
9886 :
9887 257 : for (device=0;device<0x100;device++) {
9888 256 : printf("ioctl test with device = 0x%x\n", device);
9889 65792 : for (function=0;function<0x100;function++) {
9890 65536 : uint32_t code = (device<<16) | function;
9891 :
9892 65536 : status = cli_raw_ioctl(cli, fnum, code, &blob);
9893 :
9894 65536 : if (NT_STATUS_IS_OK(status)) {
9895 0 : printf("ioctl 0x%x OK : %d bytes\n", (int)code,
9896 0 : (int)blob.length);
9897 0 : data_blob_free(&blob);
9898 : }
9899 : }
9900 : }
9901 :
9902 1 : if (!torture_close_connection(cli)) {
9903 0 : return False;
9904 : }
9905 :
9906 1 : return True;
9907 : }
9908 :
9909 :
9910 : /*
9911 : tries varients of chkpath
9912 : */
9913 1 : bool torture_chkpath_test(int dummy)
9914 : {
9915 : static struct cli_state *cli;
9916 : uint16_t fnum;
9917 : bool ret;
9918 : NTSTATUS status;
9919 :
9920 1 : if (!torture_open_connection(&cli, 0)) {
9921 0 : return False;
9922 : }
9923 :
9924 1 : printf("starting chkpath test\n");
9925 :
9926 : /* cleanup from an old run */
9927 1 : torture_deltree(cli, "\\chkpath.dir");
9928 :
9929 1 : status = cli_mkdir(cli, "\\chkpath.dir");
9930 1 : if (!NT_STATUS_IS_OK(status)) {
9931 0 : printf("mkdir1 failed : %s\n", nt_errstr(status));
9932 0 : return False;
9933 : }
9934 :
9935 1 : status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
9936 1 : if (!NT_STATUS_IS_OK(status)) {
9937 0 : printf("mkdir2 failed : %s\n", nt_errstr(status));
9938 0 : return False;
9939 : }
9940 :
9941 1 : status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
9942 : DENY_NONE, &fnum);
9943 1 : if (!NT_STATUS_IS_OK(status)) {
9944 0 : printf("open1 failed (%s)\n", nt_errstr(status));
9945 0 : return False;
9946 : }
9947 1 : cli_close(cli, fnum);
9948 :
9949 1 : status = cli_chkpath(cli, "\\chkpath.dir");
9950 1 : if (!NT_STATUS_IS_OK(status)) {
9951 0 : printf("chkpath1 failed: %s\n", nt_errstr(status));
9952 0 : ret = False;
9953 : }
9954 :
9955 1 : status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
9956 1 : if (!NT_STATUS_IS_OK(status)) {
9957 0 : printf("chkpath2 failed: %s\n", nt_errstr(status));
9958 0 : ret = False;
9959 : }
9960 :
9961 1 : status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
9962 1 : if (!NT_STATUS_IS_OK(status)) {
9963 1 : ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9964 1 : NT_STATUS_NOT_A_DIRECTORY);
9965 : } else {
9966 0 : printf("* chkpath on a file should fail\n");
9967 0 : ret = False;
9968 : }
9969 :
9970 1 : status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
9971 1 : if (!NT_STATUS_IS_OK(status)) {
9972 1 : ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
9973 1 : NT_STATUS_OBJECT_NAME_NOT_FOUND);
9974 : } else {
9975 0 : printf("* chkpath on a non existent file should fail\n");
9976 0 : ret = False;
9977 : }
9978 :
9979 1 : status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
9980 1 : if (!NT_STATUS_IS_OK(status)) {
9981 1 : ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9982 1 : NT_STATUS_OBJECT_PATH_NOT_FOUND);
9983 : } else {
9984 0 : printf("* chkpath on a non existent component should fail\n");
9985 0 : ret = False;
9986 : }
9987 :
9988 1 : torture_deltree(cli, "\\chkpath.dir");
9989 :
9990 1 : if (!torture_close_connection(cli)) {
9991 0 : return False;
9992 : }
9993 :
9994 1 : return ret;
9995 : }
9996 :
9997 0 : static bool run_eatest(int dummy)
9998 : {
9999 : static struct cli_state *cli;
10000 0 : const char *fname = "\\eatest.txt";
10001 0 : bool correct = True;
10002 : uint16_t fnum;
10003 : size_t i, num_eas;
10004 0 : struct ea_struct *ea_list = NULL;
10005 0 : TALLOC_CTX *mem_ctx = talloc_init("eatest");
10006 : NTSTATUS status;
10007 :
10008 0 : printf("starting eatest\n");
10009 :
10010 0 : if (!torture_open_connection(&cli, 0)) {
10011 0 : talloc_destroy(mem_ctx);
10012 0 : return False;
10013 : }
10014 :
10015 0 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10016 :
10017 0 : status = cli_ntcreate(cli, fname, 0,
10018 : FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10019 : FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10020 : 0x4044, 0, &fnum, NULL);
10021 0 : if (!NT_STATUS_IS_OK(status)) {
10022 0 : printf("open failed - %s\n", nt_errstr(status));
10023 0 : talloc_destroy(mem_ctx);
10024 0 : return False;
10025 : }
10026 :
10027 0 : for (i = 0; i < 10; i++) {
10028 : fstring ea_name, ea_val;
10029 :
10030 0 : slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10031 0 : memset(ea_val, (char)i+1, i+1);
10032 0 : status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10033 0 : if (!NT_STATUS_IS_OK(status)) {
10034 0 : printf("ea_set of name %s failed - %s\n", ea_name,
10035 : nt_errstr(status));
10036 0 : talloc_destroy(mem_ctx);
10037 0 : return False;
10038 : }
10039 : }
10040 :
10041 0 : cli_close(cli, fnum);
10042 0 : for (i = 0; i < 10; i++) {
10043 : fstring ea_name, ea_val;
10044 :
10045 0 : slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10046 0 : memset(ea_val, (char)i+1, i+1);
10047 0 : status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10048 0 : if (!NT_STATUS_IS_OK(status)) {
10049 0 : printf("ea_set of name %s failed - %s\n", ea_name,
10050 : nt_errstr(status));
10051 0 : talloc_destroy(mem_ctx);
10052 0 : return False;
10053 : }
10054 : }
10055 :
10056 0 : status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10057 0 : if (!NT_STATUS_IS_OK(status)) {
10058 0 : printf("ea_get list failed - %s\n", nt_errstr(status));
10059 0 : correct = False;
10060 : }
10061 :
10062 0 : printf("num_eas = %d\n", (int)num_eas);
10063 :
10064 0 : if (num_eas != 20) {
10065 0 : printf("Should be 20 EA's stored... failing.\n");
10066 0 : correct = False;
10067 : }
10068 :
10069 0 : for (i = 0; i < num_eas; i++) {
10070 0 : printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10071 0 : dump_data(0, ea_list[i].value.data,
10072 0 : ea_list[i].value.length);
10073 : }
10074 :
10075 : /* Setting EA's to zero length deletes them. Test this */
10076 0 : printf("Now deleting all EA's - case indepenent....\n");
10077 :
10078 : #if 1
10079 0 : cli_set_ea_path(cli, fname, "", "", 0);
10080 : #else
10081 : for (i = 0; i < 20; i++) {
10082 : fstring ea_name;
10083 : slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10084 : status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10085 : if (!NT_STATUS_IS_OK(status)) {
10086 : printf("ea_set of name %s failed - %s\n", ea_name,
10087 : nt_errstr(status));
10088 : talloc_destroy(mem_ctx);
10089 : return False;
10090 : }
10091 : }
10092 : #endif
10093 :
10094 0 : status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10095 0 : if (!NT_STATUS_IS_OK(status)) {
10096 0 : printf("ea_get list failed - %s\n", nt_errstr(status));
10097 0 : correct = False;
10098 : }
10099 :
10100 0 : printf("num_eas = %d\n", (int)num_eas);
10101 0 : for (i = 0; i < num_eas; i++) {
10102 0 : printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10103 0 : dump_data(0, ea_list[i].value.data,
10104 0 : ea_list[i].value.length);
10105 : }
10106 :
10107 0 : if (num_eas != 0) {
10108 0 : printf("deleting EA's failed.\n");
10109 0 : correct = False;
10110 : }
10111 :
10112 : /* Try and delete a non existent EA. */
10113 0 : status = cli_set_ea_path(cli, fname, "foo", "", 0);
10114 0 : if (!NT_STATUS_IS_OK(status)) {
10115 0 : printf("deleting non-existent EA 'foo' should succeed. %s\n",
10116 : nt_errstr(status));
10117 0 : correct = False;
10118 : }
10119 :
10120 0 : talloc_destroy(mem_ctx);
10121 0 : if (!torture_close_connection(cli)) {
10122 0 : correct = False;
10123 : }
10124 :
10125 0 : return correct;
10126 : }
10127 :
10128 0 : static bool run_dirtest1(int dummy)
10129 : {
10130 : int i;
10131 : static struct cli_state *cli;
10132 : uint16_t fnum;
10133 : int num_seen;
10134 0 : bool correct = True;
10135 :
10136 0 : printf("starting directory test\n");
10137 :
10138 0 : if (!torture_open_connection(&cli, 0)) {
10139 0 : return False;
10140 : }
10141 :
10142 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
10143 :
10144 0 : cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10145 0 : cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10146 0 : cli_rmdir(cli, "\\LISTDIR");
10147 0 : cli_mkdir(cli, "\\LISTDIR");
10148 :
10149 : /* Create 1000 files and 1000 directories. */
10150 0 : for (i=0;i<1000;i++) {
10151 : fstring fname;
10152 0 : slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10153 0 : if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10154 : FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10155 : 0, 0, &fnum, NULL))) {
10156 0 : fprintf(stderr,"Failed to open %s\n", fname);
10157 0 : return False;
10158 : }
10159 0 : cli_close(cli, fnum);
10160 : }
10161 0 : for (i=0;i<1000;i++) {
10162 : fstring fname;
10163 0 : slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10164 0 : if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10165 0 : fprintf(stderr,"Failed to open %s\n", fname);
10166 0 : return False;
10167 : }
10168 : }
10169 :
10170 : /* Now ensure that doing an old list sees both files and directories. */
10171 0 : num_seen = 0;
10172 0 : cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10173 0 : printf("num_seen = %d\n", num_seen );
10174 : /* We should see 100 files + 1000 directories + . and .. */
10175 0 : if (num_seen != 2002)
10176 0 : correct = False;
10177 :
10178 : /* Ensure if we have the "must have" bits we only see the
10179 : * relevent entries.
10180 : */
10181 0 : num_seen = 0;
10182 0 : cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10183 0 : printf("num_seen = %d\n", num_seen );
10184 0 : if (num_seen != 1002)
10185 0 : correct = False;
10186 :
10187 0 : num_seen = 0;
10188 0 : cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10189 0 : printf("num_seen = %d\n", num_seen );
10190 0 : if (num_seen != 1000)
10191 0 : correct = False;
10192 :
10193 : /* Delete everything. */
10194 0 : cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10195 0 : cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10196 0 : cli_rmdir(cli, "\\LISTDIR");
10197 :
10198 : #if 0
10199 : printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10200 : printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10201 : printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10202 : #endif
10203 :
10204 0 : if (!torture_close_connection(cli)) {
10205 0 : correct = False;
10206 : }
10207 :
10208 0 : printf("finished dirtest1\n");
10209 :
10210 0 : return correct;
10211 : }
10212 :
10213 0 : static bool run_error_map_extract(int dummy) {
10214 :
10215 : static struct cli_state *c_dos;
10216 : static struct cli_state *c_nt;
10217 : NTSTATUS status;
10218 :
10219 : uint32_t error;
10220 :
10221 : uint32_t errnum;
10222 : uint8_t errclass;
10223 :
10224 : NTSTATUS nt_status;
10225 :
10226 : fstring user;
10227 :
10228 : /* NT-Error connection */
10229 :
10230 0 : disable_spnego = true;
10231 0 : if (!(c_nt = open_nbt_connection())) {
10232 0 : disable_spnego = false;
10233 0 : return False;
10234 : }
10235 0 : disable_spnego = false;
10236 :
10237 0 : status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
10238 : PROTOCOL_NT1);
10239 :
10240 0 : if (!NT_STATUS_IS_OK(status)) {
10241 0 : printf("%s rejected the NT-error negprot (%s)\n", host,
10242 : nt_errstr(status));
10243 0 : cli_shutdown(c_nt);
10244 0 : return False;
10245 : }
10246 :
10247 0 : status = cli_session_setup_anon(c_nt);
10248 0 : if (!NT_STATUS_IS_OK(status)) {
10249 0 : printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10250 0 : return False;
10251 : }
10252 :
10253 : /* DOS-Error connection */
10254 :
10255 0 : disable_spnego = true;
10256 0 : force_dos_errors = true;
10257 0 : if (!(c_dos = open_nbt_connection())) {
10258 0 : disable_spnego = false;
10259 0 : force_dos_errors = false;
10260 0 : return False;
10261 : }
10262 0 : disable_spnego = false;
10263 0 : force_dos_errors = false;
10264 :
10265 0 : status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
10266 : PROTOCOL_NT1);
10267 0 : if (!NT_STATUS_IS_OK(status)) {
10268 0 : printf("%s rejected the DOS-error negprot (%s)\n", host,
10269 : nt_errstr(status));
10270 0 : cli_shutdown(c_dos);
10271 0 : return False;
10272 : }
10273 :
10274 0 : status = cli_session_setup_anon(c_dos);
10275 0 : if (!NT_STATUS_IS_OK(status)) {
10276 0 : printf("%s rejected the DOS-error initial session setup (%s)\n",
10277 : host, nt_errstr(status));
10278 0 : return False;
10279 : }
10280 :
10281 0 : c_nt->map_dos_errors = false;
10282 0 : c_dos->map_dos_errors = false;
10283 :
10284 0 : for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10285 0 : struct cli_credentials *user_creds = NULL;
10286 :
10287 0 : fstr_sprintf(user, "%X", error);
10288 :
10289 0 : user_creds = cli_session_creds_init(talloc_tos(),
10290 : user,
10291 : workgroup,
10292 : NULL, /* realm */
10293 : password,
10294 : false, /* use_kerberos */
10295 : false, /* fallback_after_kerberos */
10296 : false, /* use_ccache */
10297 : false); /* password_is_nt_hash */
10298 0 : if (user_creds == NULL) {
10299 0 : printf("cli_session_creds_init(%s) failed\n", user);
10300 0 : return false;
10301 : }
10302 :
10303 0 : status = cli_session_setup_creds(c_nt, user_creds);
10304 0 : if (NT_STATUS_IS_OK(status)) {
10305 0 : printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10306 : }
10307 :
10308 : /* Case #1: 32-bit NT errors */
10309 0 : if (!NT_STATUS_IS_DOS(status)) {
10310 0 : nt_status = status;
10311 : } else {
10312 0 : printf("/** Dos error on NT connection! (%s) */\n",
10313 : nt_errstr(status));
10314 0 : nt_status = NT_STATUS(0xc0000000);
10315 : }
10316 :
10317 0 : status = cli_session_setup_creds(c_dos, user_creds);
10318 0 : if (NT_STATUS_IS_OK(status)) {
10319 0 : printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10320 : }
10321 :
10322 : /* Case #1: 32-bit NT errors */
10323 0 : if (NT_STATUS_IS_DOS(status)) {
10324 0 : printf("/** NT error on DOS connection! (%s) */\n",
10325 : nt_errstr(status));
10326 0 : errnum = errclass = 0;
10327 : } else {
10328 0 : errclass = NT_STATUS_DOS_CLASS(status);
10329 0 : errnum = NT_STATUS_DOS_CODE(status);
10330 : }
10331 :
10332 0 : if (NT_STATUS_V(nt_status) != error) {
10333 0 : printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10334 0 : get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
10335 0 : get_nt_error_c_code(talloc_tos(), nt_status));
10336 : }
10337 :
10338 0 : printf("\t{%s,\t%s,\t%s},\n",
10339 : smb_dos_err_class(errclass),
10340 : smb_dos_err_name(errclass, errnum),
10341 0 : get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10342 :
10343 0 : TALLOC_FREE(user_creds);
10344 : }
10345 0 : return True;
10346 : }
10347 :
10348 0 : static bool run_sesssetup_bench(int dummy)
10349 : {
10350 : static struct cli_state *c;
10351 0 : const char *fname = "\\file.dat";
10352 : uint16_t fnum;
10353 : NTSTATUS status;
10354 : int i;
10355 :
10356 0 : if (!torture_open_connection(&c, 0)) {
10357 0 : return false;
10358 : }
10359 :
10360 0 : status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10361 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10362 : FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10363 0 : if (!NT_STATUS_IS_OK(status)) {
10364 0 : d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10365 0 : return false;
10366 : }
10367 :
10368 0 : for (i=0; i<torture_numops; i++) {
10369 0 : status = cli_session_setup_creds(c, torture_creds);
10370 0 : if (!NT_STATUS_IS_OK(status)) {
10371 0 : d_printf("(%s) cli_session_setup_creds failed: %s\n",
10372 : __location__, nt_errstr(status));
10373 0 : return false;
10374 : }
10375 :
10376 0 : d_printf("\r%d ", (int)cli_state_get_uid(c));
10377 :
10378 0 : status = cli_ulogoff(c);
10379 0 : if (!NT_STATUS_IS_OK(status)) {
10380 0 : d_printf("(%s) cli_ulogoff failed: %s\n",
10381 : __location__, nt_errstr(status));
10382 0 : return false;
10383 : }
10384 : }
10385 :
10386 0 : return true;
10387 : }
10388 :
10389 0 : static bool subst_test(const char *str, const char *user, const char *domain,
10390 : uid_t uid, gid_t gid, const char *expected)
10391 : {
10392 : char *subst;
10393 0 : bool result = true;
10394 :
10395 0 : subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10396 :
10397 0 : if (strcmp(subst, expected) != 0) {
10398 0 : printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10399 : "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10400 : expected);
10401 0 : result = false;
10402 : }
10403 :
10404 0 : TALLOC_FREE(subst);
10405 0 : return result;
10406 : }
10407 :
10408 1 : static void chain1_open_completion(struct tevent_req *req)
10409 : {
10410 : uint16_t fnum;
10411 : NTSTATUS status;
10412 1 : status = cli_openx_recv(req, &fnum);
10413 1 : TALLOC_FREE(req);
10414 :
10415 1 : d_printf("cli_openx_recv returned %s: %d\n",
10416 : nt_errstr(status),
10417 1 : NT_STATUS_IS_OK(status) ? fnum : -1);
10418 1 : }
10419 :
10420 1 : static void chain1_write_completion(struct tevent_req *req)
10421 : {
10422 : size_t written;
10423 : NTSTATUS status;
10424 1 : status = cli_write_andx_recv(req, &written);
10425 1 : TALLOC_FREE(req);
10426 :
10427 1 : d_printf("cli_write_andx_recv returned %s: %d\n",
10428 : nt_errstr(status),
10429 1 : NT_STATUS_IS_OK(status) ? (int)written : -1);
10430 1 : }
10431 :
10432 1 : static void chain1_close_completion(struct tevent_req *req)
10433 : {
10434 : NTSTATUS status;
10435 1 : bool *done = (bool *)tevent_req_callback_data_void(req);
10436 :
10437 1 : status = cli_close_recv(req);
10438 1 : *done = true;
10439 :
10440 1 : TALLOC_FREE(req);
10441 :
10442 1 : d_printf("cli_close returned %s\n", nt_errstr(status));
10443 1 : }
10444 :
10445 1 : static bool run_chain1(int dummy)
10446 : {
10447 : struct cli_state *cli1;
10448 1 : struct tevent_context *evt = samba_tevent_context_init(NULL);
10449 : struct tevent_req *reqs[3], *smbreqs[3];
10450 1 : bool done = false;
10451 1 : const char *str = "foobar";
10452 1 : const char *fname = "\\test_chain";
10453 : NTSTATUS status;
10454 :
10455 1 : printf("starting chain1 test\n");
10456 1 : if (!torture_open_connection(&cli1, 0)) {
10457 0 : return False;
10458 : }
10459 :
10460 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
10461 :
10462 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10463 :
10464 1 : reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10465 : O_CREAT|O_RDWR, 0, &smbreqs[0]);
10466 1 : if (reqs[0] == NULL) return false;
10467 1 : tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10468 :
10469 :
10470 1 : reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10471 1 : (const uint8_t *)str, 0, strlen(str)+1,
10472 : smbreqs, 1, &smbreqs[1]);
10473 1 : if (reqs[1] == NULL) return false;
10474 1 : tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10475 :
10476 1 : reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10477 1 : if (reqs[2] == NULL) return false;
10478 1 : tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10479 :
10480 1 : status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10481 1 : if (!NT_STATUS_IS_OK(status)) {
10482 0 : return false;
10483 : }
10484 :
10485 7 : while (!done) {
10486 6 : tevent_loop_once(evt);
10487 : }
10488 :
10489 1 : torture_close_connection(cli1);
10490 1 : return True;
10491 : }
10492 :
10493 1 : static void chain2_sesssetup_completion(struct tevent_req *req)
10494 : {
10495 : NTSTATUS status;
10496 1 : status = cli_session_setup_guest_recv(req);
10497 1 : d_printf("sesssetup returned %s\n", nt_errstr(status));
10498 1 : }
10499 :
10500 1 : static void chain2_tcon_completion(struct tevent_req *req)
10501 : {
10502 1 : bool *done = (bool *)tevent_req_callback_data_void(req);
10503 : NTSTATUS status;
10504 1 : status = cli_tcon_andx_recv(req);
10505 1 : d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10506 1 : *done = true;
10507 1 : }
10508 :
10509 1 : static bool run_chain2(int dummy)
10510 : {
10511 : struct cli_state *cli1;
10512 1 : struct tevent_context *evt = samba_tevent_context_init(NULL);
10513 : struct tevent_req *reqs[2], *smbreqs[2];
10514 1 : bool done = false;
10515 : NTSTATUS status;
10516 1 : int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10517 :
10518 1 : printf("starting chain2 test\n");
10519 1 : status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10520 : port_to_use, SMB_SIGNING_DEFAULT, flags);
10521 1 : if (!NT_STATUS_IS_OK(status)) {
10522 0 : return False;
10523 : }
10524 :
10525 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
10526 :
10527 1 : reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10528 : &smbreqs[0]);
10529 1 : if (reqs[0] == NULL) return false;
10530 1 : tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10531 :
10532 1 : reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10533 : "?????", NULL, 0, &smbreqs[1]);
10534 1 : if (reqs[1] == NULL) return false;
10535 1 : tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10536 :
10537 1 : status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10538 1 : if (!NT_STATUS_IS_OK(status)) {
10539 0 : return false;
10540 : }
10541 :
10542 6 : while (!done) {
10543 5 : tevent_loop_once(evt);
10544 : }
10545 :
10546 1 : torture_close_connection(cli1);
10547 1 : return True;
10548 : }
10549 :
10550 :
10551 : struct torture_createdel_state {
10552 : struct tevent_context *ev;
10553 : struct cli_state *cli;
10554 : };
10555 :
10556 : static void torture_createdel_created(struct tevent_req *subreq);
10557 : static void torture_createdel_closed(struct tevent_req *subreq);
10558 :
10559 0 : static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10560 : struct tevent_context *ev,
10561 : struct cli_state *cli,
10562 : const char *name)
10563 : {
10564 : struct tevent_req *req, *subreq;
10565 : struct torture_createdel_state *state;
10566 :
10567 0 : req = tevent_req_create(mem_ctx, &state,
10568 : struct torture_createdel_state);
10569 0 : if (req == NULL) {
10570 0 : return NULL;
10571 : }
10572 0 : state->ev = ev;
10573 0 : state->cli = cli;
10574 :
10575 0 : subreq = cli_ntcreate_send(
10576 : state, ev, cli, name, 0,
10577 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10578 : FILE_ATTRIBUTE_NORMAL,
10579 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10580 : FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10581 : SMB2_IMPERSONATION_IMPERSONATION, 0);
10582 :
10583 0 : if (tevent_req_nomem(subreq, req)) {
10584 0 : return tevent_req_post(req, ev);
10585 : }
10586 0 : tevent_req_set_callback(subreq, torture_createdel_created, req);
10587 0 : return req;
10588 : }
10589 :
10590 0 : static void torture_createdel_created(struct tevent_req *subreq)
10591 : {
10592 0 : struct tevent_req *req = tevent_req_callback_data(
10593 : subreq, struct tevent_req);
10594 0 : struct torture_createdel_state *state = tevent_req_data(
10595 : req, struct torture_createdel_state);
10596 : NTSTATUS status;
10597 : uint16_t fnum;
10598 :
10599 0 : status = cli_ntcreate_recv(subreq, &fnum, NULL);
10600 0 : TALLOC_FREE(subreq);
10601 0 : if (tevent_req_nterror(req, status)) {
10602 0 : DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10603 : nt_errstr(status)));
10604 0 : return;
10605 : }
10606 :
10607 0 : subreq = cli_close_send(state, state->ev, state->cli, fnum);
10608 0 : if (tevent_req_nomem(subreq, req)) {
10609 0 : return;
10610 : }
10611 0 : tevent_req_set_callback(subreq, torture_createdel_closed, req);
10612 : }
10613 :
10614 0 : static void torture_createdel_closed(struct tevent_req *subreq)
10615 : {
10616 0 : struct tevent_req *req = tevent_req_callback_data(
10617 : subreq, struct tevent_req);
10618 : NTSTATUS status;
10619 :
10620 0 : status = cli_close_recv(subreq);
10621 0 : if (tevent_req_nterror(req, status)) {
10622 0 : DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10623 0 : return;
10624 : }
10625 0 : tevent_req_done(req);
10626 : }
10627 :
10628 0 : static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10629 : {
10630 0 : return tevent_req_simple_recv_ntstatus(req);
10631 : }
10632 :
10633 : struct torture_createdels_state {
10634 : struct tevent_context *ev;
10635 : struct cli_state *cli;
10636 : const char *base_name;
10637 : int sent;
10638 : int received;
10639 : int num_files;
10640 : struct tevent_req **reqs;
10641 : };
10642 :
10643 : static void torture_createdels_done(struct tevent_req *subreq);
10644 :
10645 0 : static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10646 : struct tevent_context *ev,
10647 : struct cli_state *cli,
10648 : const char *base_name,
10649 : int num_parallel,
10650 : int num_files)
10651 : {
10652 : struct tevent_req *req;
10653 : struct torture_createdels_state *state;
10654 : int i;
10655 :
10656 0 : req = tevent_req_create(mem_ctx, &state,
10657 : struct torture_createdels_state);
10658 0 : if (req == NULL) {
10659 0 : return NULL;
10660 : }
10661 0 : state->ev = ev;
10662 0 : state->cli = cli;
10663 0 : state->base_name = talloc_strdup(state, base_name);
10664 0 : if (tevent_req_nomem(state->base_name, req)) {
10665 0 : return tevent_req_post(req, ev);
10666 : }
10667 0 : state->num_files = MAX(num_parallel, num_files);
10668 0 : state->sent = 0;
10669 0 : state->received = 0;
10670 :
10671 0 : state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10672 0 : if (tevent_req_nomem(state->reqs, req)) {
10673 0 : return tevent_req_post(req, ev);
10674 : }
10675 :
10676 0 : for (i=0; i<num_parallel; i++) {
10677 : char *name;
10678 :
10679 0 : name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10680 0 : state->sent);
10681 0 : if (tevent_req_nomem(name, req)) {
10682 0 : return tevent_req_post(req, ev);
10683 : }
10684 0 : state->reqs[i] = torture_createdel_send(
10685 0 : state->reqs, state->ev, state->cli, name);
10686 0 : if (tevent_req_nomem(state->reqs[i], req)) {
10687 0 : return tevent_req_post(req, ev);
10688 : }
10689 0 : name = talloc_move(state->reqs[i], &name);
10690 0 : tevent_req_set_callback(state->reqs[i],
10691 : torture_createdels_done, req);
10692 0 : state->sent += 1;
10693 : }
10694 0 : return req;
10695 : }
10696 :
10697 0 : static void torture_createdels_done(struct tevent_req *subreq)
10698 : {
10699 0 : struct tevent_req *req = tevent_req_callback_data(
10700 : subreq, struct tevent_req);
10701 0 : struct torture_createdels_state *state = tevent_req_data(
10702 : req, struct torture_createdels_state);
10703 0 : size_t i, num_parallel = talloc_array_length(state->reqs);
10704 : NTSTATUS status;
10705 : char *name;
10706 :
10707 0 : status = torture_createdel_recv(subreq);
10708 0 : if (!NT_STATUS_IS_OK(status)){
10709 0 : DEBUG(10, ("torture_createdel_recv returned %s\n",
10710 : nt_errstr(status)));
10711 0 : TALLOC_FREE(subreq);
10712 0 : tevent_req_nterror(req, status);
10713 0 : return;
10714 : }
10715 :
10716 0 : for (i=0; i<num_parallel; i++) {
10717 0 : if (subreq == state->reqs[i]) {
10718 0 : break;
10719 : }
10720 : }
10721 0 : if (i == num_parallel) {
10722 0 : DEBUG(10, ("received something we did not send\n"));
10723 0 : tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10724 0 : return;
10725 : }
10726 0 : TALLOC_FREE(state->reqs[i]);
10727 :
10728 0 : if (state->sent >= state->num_files) {
10729 0 : tevent_req_done(req);
10730 0 : return;
10731 : }
10732 :
10733 0 : name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10734 : state->sent);
10735 0 : if (tevent_req_nomem(name, req)) {
10736 0 : return;
10737 : }
10738 0 : state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10739 : state->cli, name);
10740 0 : if (tevent_req_nomem(state->reqs[i], req)) {
10741 0 : return;
10742 : }
10743 0 : name = talloc_move(state->reqs[i], &name);
10744 0 : tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10745 0 : state->sent += 1;
10746 : }
10747 :
10748 0 : static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10749 : {
10750 0 : return tevent_req_simple_recv_ntstatus(req);
10751 : }
10752 :
10753 : struct swallow_notify_state {
10754 : struct tevent_context *ev;
10755 : struct cli_state *cli;
10756 : uint16_t fnum;
10757 : uint32_t completion_filter;
10758 : bool recursive;
10759 : bool (*fn)(uint32_t action, const char *name, void *priv);
10760 : void *priv;
10761 : };
10762 :
10763 : static void swallow_notify_done(struct tevent_req *subreq);
10764 :
10765 0 : static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10766 : struct tevent_context *ev,
10767 : struct cli_state *cli,
10768 : uint16_t fnum,
10769 : uint32_t completion_filter,
10770 : bool recursive,
10771 : bool (*fn)(uint32_t action,
10772 : const char *name,
10773 : void *priv),
10774 : void *priv)
10775 : {
10776 : struct tevent_req *req, *subreq;
10777 : struct swallow_notify_state *state;
10778 :
10779 0 : req = tevent_req_create(mem_ctx, &state,
10780 : struct swallow_notify_state);
10781 0 : if (req == NULL) {
10782 0 : return NULL;
10783 : }
10784 0 : state->ev = ev;
10785 0 : state->cli = cli;
10786 0 : state->fnum = fnum;
10787 0 : state->completion_filter = completion_filter;
10788 0 : state->recursive = recursive;
10789 0 : state->fn = fn;
10790 0 : state->priv = priv;
10791 :
10792 0 : subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10793 0 : 0xffff, state->completion_filter,
10794 0 : state->recursive);
10795 0 : if (tevent_req_nomem(subreq, req)) {
10796 0 : return tevent_req_post(req, ev);
10797 : }
10798 0 : tevent_req_set_callback(subreq, swallow_notify_done, req);
10799 0 : return req;
10800 : }
10801 :
10802 0 : static void swallow_notify_done(struct tevent_req *subreq)
10803 : {
10804 0 : struct tevent_req *req = tevent_req_callback_data(
10805 : subreq, struct tevent_req);
10806 0 : struct swallow_notify_state *state = tevent_req_data(
10807 : req, struct swallow_notify_state);
10808 : NTSTATUS status;
10809 : uint32_t i, num_changes;
10810 : struct notify_change *changes;
10811 :
10812 0 : status = cli_notify_recv(subreq, state, &num_changes, &changes);
10813 0 : TALLOC_FREE(subreq);
10814 0 : if (!NT_STATUS_IS_OK(status)) {
10815 0 : DEBUG(10, ("cli_notify_recv returned %s\n",
10816 : nt_errstr(status)));
10817 0 : tevent_req_nterror(req, status);
10818 0 : return;
10819 : }
10820 :
10821 0 : for (i=0; i<num_changes; i++) {
10822 0 : state->fn(changes[i].action, changes[i].name, state->priv);
10823 : }
10824 0 : TALLOC_FREE(changes);
10825 :
10826 0 : subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10827 : 0xffff, state->completion_filter,
10828 0 : state->recursive);
10829 0 : if (tevent_req_nomem(subreq, req)) {
10830 0 : return;
10831 : }
10832 0 : tevent_req_set_callback(subreq, swallow_notify_done, req);
10833 : }
10834 :
10835 0 : static bool print_notifies(uint32_t action, const char *name, void *priv)
10836 : {
10837 0 : if (DEBUGLEVEL > 5) {
10838 0 : d_printf("%d %s\n", (int)action, name);
10839 : }
10840 0 : return true;
10841 : }
10842 :
10843 0 : static void notify_bench_done(struct tevent_req *req)
10844 : {
10845 0 : int *num_finished = (int *)tevent_req_callback_data_void(req);
10846 0 : *num_finished += 1;
10847 0 : }
10848 :
10849 0 : static bool run_notify_bench(int dummy)
10850 : {
10851 0 : const char *dname = "\\notify-bench";
10852 : struct tevent_context *ev;
10853 : NTSTATUS status;
10854 : uint16_t dnum;
10855 : struct tevent_req *req1;
10856 0 : struct tevent_req *req2 = NULL;
10857 : int i, num_unc_names;
10858 0 : int num_finished = 0;
10859 :
10860 0 : printf("starting notify-bench test\n");
10861 :
10862 0 : if (use_multishare_conn) {
10863 : char **unc_list;
10864 0 : unc_list = file_lines_load(multishare_conn_fname,
10865 : &num_unc_names, 0, NULL);
10866 0 : if (!unc_list || num_unc_names <= 0) {
10867 0 : d_printf("Failed to load unc names list from '%s'\n",
10868 : multishare_conn_fname);
10869 0 : return false;
10870 : }
10871 0 : TALLOC_FREE(unc_list);
10872 : } else {
10873 0 : num_unc_names = 1;
10874 : }
10875 :
10876 0 : ev = samba_tevent_context_init(talloc_tos());
10877 0 : if (ev == NULL) {
10878 0 : d_printf("tevent_context_init failed\n");
10879 0 : return false;
10880 : }
10881 :
10882 0 : for (i=0; i<num_unc_names; i++) {
10883 : struct cli_state *cli;
10884 : char *base_fname;
10885 :
10886 0 : base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
10887 : dname, i);
10888 0 : if (base_fname == NULL) {
10889 0 : return false;
10890 : }
10891 :
10892 0 : if (!torture_open_connection(&cli, i)) {
10893 0 : return false;
10894 : }
10895 :
10896 0 : status = cli_ntcreate(cli, dname, 0,
10897 : MAXIMUM_ALLOWED_ACCESS,
10898 : 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
10899 : FILE_SHARE_DELETE,
10900 : FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
10901 : &dnum, NULL);
10902 :
10903 0 : if (!NT_STATUS_IS_OK(status)) {
10904 0 : d_printf("Could not create %s: %s\n", dname,
10905 : nt_errstr(status));
10906 0 : return false;
10907 : }
10908 :
10909 0 : req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
10910 : FILE_NOTIFY_CHANGE_FILE_NAME |
10911 : FILE_NOTIFY_CHANGE_DIR_NAME |
10912 : FILE_NOTIFY_CHANGE_ATTRIBUTES |
10913 : FILE_NOTIFY_CHANGE_LAST_WRITE,
10914 : false, print_notifies, NULL);
10915 0 : if (req1 == NULL) {
10916 0 : d_printf("Could not create notify request\n");
10917 0 : return false;
10918 : }
10919 :
10920 0 : req2 = torture_createdels_send(talloc_tos(), ev, cli,
10921 : base_fname, 10, torture_numops);
10922 0 : if (req2 == NULL) {
10923 0 : d_printf("Could not create createdels request\n");
10924 0 : return false;
10925 : }
10926 0 : TALLOC_FREE(base_fname);
10927 :
10928 0 : tevent_req_set_callback(req2, notify_bench_done,
10929 : &num_finished);
10930 : }
10931 :
10932 0 : while (num_finished < num_unc_names) {
10933 : int ret;
10934 0 : ret = tevent_loop_once(ev);
10935 0 : if (ret != 0) {
10936 0 : d_printf("tevent_loop_once failed\n");
10937 0 : return false;
10938 : }
10939 : }
10940 :
10941 0 : if (!tevent_req_poll(req2, ev)) {
10942 0 : d_printf("tevent_req_poll failed\n");
10943 : }
10944 :
10945 0 : status = torture_createdels_recv(req2);
10946 0 : d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
10947 :
10948 0 : return true;
10949 : }
10950 :
10951 0 : static bool run_mangle1(int dummy)
10952 : {
10953 : struct cli_state *cli;
10954 0 : const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
10955 : uint16_t fnum;
10956 : fstring alt_name;
10957 : NTSTATUS status;
10958 : time_t change_time, access_time, write_time;
10959 : off_t size;
10960 : uint32_t attr;
10961 :
10962 0 : printf("starting mangle1 test\n");
10963 0 : if (!torture_open_connection(&cli, 0)) {
10964 0 : return False;
10965 : }
10966 :
10967 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
10968 :
10969 0 : status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10970 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10971 : 0, 0, &fnum, NULL);
10972 0 : if (!NT_STATUS_IS_OK(status)) {
10973 0 : d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10974 0 : return false;
10975 : }
10976 0 : cli_close(cli, fnum);
10977 :
10978 0 : status = cli_qpathinfo_alt_name(cli, fname, alt_name);
10979 0 : if (!NT_STATUS_IS_OK(status)) {
10980 0 : d_printf("cli_qpathinfo_alt_name failed: %s\n",
10981 : nt_errstr(status));
10982 0 : return false;
10983 : }
10984 0 : d_printf("alt_name: %s\n", alt_name);
10985 :
10986 0 : status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
10987 0 : if (!NT_STATUS_IS_OK(status)) {
10988 0 : d_printf("cli_openx(%s) failed: %s\n", alt_name,
10989 : nt_errstr(status));
10990 0 : return false;
10991 : }
10992 0 : cli_close(cli, fnum);
10993 :
10994 0 : status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
10995 : &write_time, &size, &attr);
10996 0 : if (!NT_STATUS_IS_OK(status)) {
10997 0 : d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
10998 : nt_errstr(status));
10999 0 : return false;
11000 : }
11001 :
11002 0 : return true;
11003 : }
11004 :
11005 0 : static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
11006 : const char *mask,
11007 : void *state)
11008 : {
11009 0 : if (f->short_name == NULL) {
11010 0 : return NT_STATUS_OK;
11011 : }
11012 :
11013 0 : if (strlen(f->short_name) == 0) {
11014 0 : return NT_STATUS_OK;
11015 : }
11016 :
11017 0 : printf("unexpected shortname: %s\n", f->short_name);
11018 :
11019 0 : return NT_STATUS_OBJECT_NAME_INVALID;
11020 : }
11021 :
11022 0 : static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11023 : const char *mask,
11024 : void *state)
11025 : {
11026 0 : char *name = state;
11027 :
11028 0 : printf("name: %s\n", f->name);
11029 0 : fstrcpy(name, f->name);
11030 0 : return NT_STATUS_OK;
11031 : }
11032 :
11033 0 : static bool run_mangle_illegal(int dummy)
11034 : {
11035 0 : struct cli_state *cli = NULL;
11036 0 : struct cli_state *cli_posix = NULL;
11037 0 : const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11038 0 : const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11039 0 : char *mangled_path = NULL;
11040 : uint16_t fnum;
11041 : fstring name;
11042 : fstring alt_name;
11043 : NTSTATUS status;
11044 :
11045 0 : printf("starting mangle-illegal test\n");
11046 :
11047 0 : if (!torture_open_connection(&cli, 0)) {
11048 0 : return False;
11049 : }
11050 :
11051 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11052 :
11053 0 : if (!torture_open_connection(&cli_posix, 0)) {
11054 0 : return false;
11055 : }
11056 :
11057 0 : smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11058 :
11059 0 : status = torture_setup_unix_extensions(cli_posix);
11060 0 : if (!NT_STATUS_IS_OK(status)) {
11061 0 : return false;
11062 : }
11063 :
11064 0 : cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11065 0 : status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11066 0 : if (!NT_STATUS_IS_OK(status)) {
11067 0 : printf("mkdir1 failed : %s\n", nt_errstr(status));
11068 0 : return False;
11069 : }
11070 :
11071 : /*
11072 : * Create a file with illegal NTFS characters and test that we
11073 : * get a usable mangled name
11074 : */
11075 :
11076 0 : cli_setatr(cli_posix, illegal_fname, 0, 0);
11077 0 : cli_posix_unlink(cli_posix, illegal_fname);
11078 :
11079 0 : status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11080 : 0600, &fnum);
11081 0 : if (!NT_STATUS_IS_OK(status)) {
11082 0 : printf("POSIX create of %s failed (%s)\n",
11083 : illegal_fname, nt_errstr(status));
11084 0 : return false;
11085 : }
11086 :
11087 0 : status = cli_close(cli_posix, fnum);
11088 0 : if (!NT_STATUS_IS_OK(status)) {
11089 0 : printf("close failed (%s)\n", nt_errstr(status));
11090 0 : return false;
11091 : }
11092 :
11093 0 : status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11094 0 : if (!NT_STATUS_IS_OK(status)) {
11095 0 : d_printf("cli_list failed: %s\n", nt_errstr(status));
11096 0 : return false;
11097 : }
11098 :
11099 0 : mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11100 0 : if (mangled_path == NULL) {
11101 0 : return false;
11102 : }
11103 :
11104 0 : status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11105 0 : if (!NT_STATUS_IS_OK(status)) {
11106 0 : d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11107 0 : TALLOC_FREE(mangled_path);
11108 0 : return false;
11109 : }
11110 0 : TALLOC_FREE(mangled_path);
11111 0 : cli_close(cli, fnum);
11112 :
11113 0 : cli_setatr(cli_posix, illegal_fname, 0, 0);
11114 0 : cli_posix_unlink(cli_posix, illegal_fname);
11115 :
11116 : /*
11117 : * Create a file with a long name and check that we got *no* short name.
11118 : */
11119 :
11120 0 : status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11121 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11122 : 0, 0, &fnum, NULL);
11123 0 : if (!NT_STATUS_IS_OK(status)) {
11124 0 : d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11125 0 : return false;
11126 : }
11127 0 : cli_close(cli, fnum);
11128 :
11129 0 : status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11130 0 : if (!NT_STATUS_IS_OK(status)) {
11131 0 : d_printf("cli_list failed\n");
11132 0 : return false;
11133 : }
11134 :
11135 0 : cli_unlink(cli, fname, 0);
11136 0 : cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11137 :
11138 0 : if (!torture_close_connection(cli_posix)) {
11139 0 : return false;
11140 : }
11141 :
11142 0 : if (!torture_close_connection(cli)) {
11143 0 : return false;
11144 : }
11145 :
11146 0 : return true;
11147 : }
11148 :
11149 0 : static size_t null_source(uint8_t *buf, size_t n, void *priv)
11150 : {
11151 0 : size_t *to_pull = (size_t *)priv;
11152 0 : size_t thistime = *to_pull;
11153 :
11154 0 : thistime = MIN(thistime, n);
11155 0 : if (thistime == 0) {
11156 0 : return 0;
11157 : }
11158 :
11159 0 : memset(buf, 0, thistime);
11160 0 : *to_pull -= thistime;
11161 0 : return thistime;
11162 : }
11163 :
11164 0 : static bool run_windows_write(int dummy)
11165 : {
11166 : struct cli_state *cli1;
11167 : uint16_t fnum;
11168 : int i;
11169 0 : bool ret = false;
11170 0 : const char *fname = "\\writetest.txt";
11171 : struct timeval start_time;
11172 : double seconds;
11173 : double kbytes;
11174 : NTSTATUS status;
11175 :
11176 0 : printf("starting windows_write test\n");
11177 0 : if (!torture_open_connection(&cli1, 0)) {
11178 0 : return False;
11179 : }
11180 :
11181 0 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11182 0 : if (!NT_STATUS_IS_OK(status)) {
11183 0 : printf("open failed (%s)\n", nt_errstr(status));
11184 0 : return False;
11185 : }
11186 :
11187 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
11188 :
11189 0 : start_time = timeval_current();
11190 :
11191 0 : for (i=0; i<torture_numops; i++) {
11192 0 : uint8_t c = 0;
11193 0 : off_t start = i * torture_blocksize;
11194 0 : size_t to_pull = torture_blocksize - 1;
11195 :
11196 0 : status = cli_writeall(cli1, fnum, 0, &c,
11197 0 : start + torture_blocksize - 1, 1, NULL);
11198 0 : if (!NT_STATUS_IS_OK(status)) {
11199 0 : printf("cli_write failed: %s\n", nt_errstr(status));
11200 0 : goto fail;
11201 : }
11202 :
11203 0 : status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11204 : null_source, &to_pull);
11205 0 : if (!NT_STATUS_IS_OK(status)) {
11206 0 : printf("cli_push returned: %s\n", nt_errstr(status));
11207 0 : goto fail;
11208 : }
11209 : }
11210 :
11211 0 : seconds = timeval_elapsed(&start_time);
11212 0 : kbytes = (double)torture_blocksize * torture_numops;
11213 0 : kbytes /= 1024;
11214 :
11215 0 : printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11216 0 : (double)seconds, (int)(kbytes/seconds));
11217 :
11218 0 : ret = true;
11219 0 : fail:
11220 0 : cli_close(cli1, fnum);
11221 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11222 0 : torture_close_connection(cli1);
11223 0 : return ret;
11224 : }
11225 :
11226 16 : static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11227 : {
11228 16 : size_t max_pdu = 0x1FFFF;
11229 :
11230 16 : if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11231 0 : max_pdu = 0xFFFFFF;
11232 : }
11233 :
11234 16 : if (smb1cli_conn_signing_is_active(cli->conn)) {
11235 16 : max_pdu = 0x1FFFF;
11236 : }
11237 :
11238 16 : if (smb1cli_conn_encryption_on(cli->conn)) {
11239 0 : max_pdu = CLI_BUFFER_SIZE;
11240 : }
11241 :
11242 16 : if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11243 2 : len_requested &= 0xFFFF;
11244 : }
11245 :
11246 16 : return MIN(len_requested,
11247 : max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11248 : }
11249 :
11250 16 : static bool check_read_call(struct cli_state *cli,
11251 : uint16_t fnum,
11252 : uint8_t *buf,
11253 : size_t len_requested)
11254 : {
11255 : NTSTATUS status;
11256 16 : struct tevent_req *subreq = NULL;
11257 16 : ssize_t len_read = 0;
11258 16 : size_t len_expected = 0;
11259 16 : struct tevent_context *ev = NULL;
11260 :
11261 16 : ev = samba_tevent_context_init(talloc_tos());
11262 16 : if (ev == NULL) {
11263 0 : return false;
11264 : }
11265 :
11266 16 : subreq = cli_read_andx_send(talloc_tos(),
11267 : ev,
11268 : cli,
11269 : fnum,
11270 : 0,
11271 : len_requested);
11272 :
11273 16 : if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11274 0 : return false;
11275 : }
11276 :
11277 16 : status = cli_read_andx_recv(subreq, &len_read, &buf);
11278 16 : if (!NT_STATUS_IS_OK(status)) {
11279 0 : d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11280 0 : return false;
11281 : }
11282 :
11283 16 : TALLOC_FREE(subreq);
11284 16 : TALLOC_FREE(ev);
11285 :
11286 16 : len_expected = calc_expected_return(cli, len_requested);
11287 :
11288 16 : if (len_expected > 0x10000 && len_read == 0x10000) {
11289 : /* Windows servers only return a max of 0x10000,
11290 : doesn't matter if you set CAP_LARGE_READX in
11291 : the client sessionsetupX call or not. */
11292 12 : d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11293 : (unsigned int)len_requested);
11294 4 : } else if (len_read != len_expected) {
11295 0 : d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11296 : (unsigned int)len_requested,
11297 : (unsigned int)len_read,
11298 : (unsigned int)len_expected);
11299 0 : return false;
11300 : } else {
11301 4 : d_printf("Correct read reply.\n");
11302 : }
11303 :
11304 16 : return true;
11305 : }
11306 :
11307 : /* Test large readX variants. */
11308 2 : static bool large_readx_tests(struct cli_state *cli,
11309 : uint16_t fnum,
11310 : uint8_t *buf)
11311 : {
11312 : /* A read of 0xFFFF0001 should *always* return 1 byte. */
11313 2 : if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11314 0 : return false;
11315 : }
11316 : /* A read of 0x10000 should return 0x10000 bytes. */
11317 2 : if (check_read_call(cli, fnum, buf, 0x10000) == false) {
11318 0 : return false;
11319 : }
11320 : /* A read of 0x10000 should return 0x10001 bytes. */
11321 2 : if (check_read_call(cli, fnum, buf, 0x10001) == false) {
11322 0 : return false;
11323 : }
11324 : /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11325 : the requested number of bytes. */
11326 2 : if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11327 0 : return false;
11328 : }
11329 : /* A read of 1MB should return 1MB bytes (on Samba). */
11330 2 : if (check_read_call(cli, fnum, buf, 0x100000) == false) {
11331 0 : return false;
11332 : }
11333 :
11334 2 : if (check_read_call(cli, fnum, buf, 0x20001) == false) {
11335 0 : return false;
11336 : }
11337 2 : if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11338 0 : return false;
11339 : }
11340 2 : if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11341 0 : return false;
11342 : }
11343 2 : return true;
11344 : }
11345 :
11346 1 : static bool run_large_readx(int dummy)
11347 : {
11348 1 : uint8_t *buf = NULL;
11349 1 : struct cli_state *cli1 = NULL;
11350 1 : struct cli_state *cli2 = NULL;
11351 1 : bool correct = false;
11352 1 : const char *fname = "\\large_readx.dat";
11353 : NTSTATUS status;
11354 1 : uint16_t fnum1 = UINT16_MAX;
11355 1 : uint32_t normal_caps = 0;
11356 1 : size_t file_size = 20*1024*1024;
11357 1 : TALLOC_CTX *frame = talloc_stackframe();
11358 : size_t i;
11359 : struct {
11360 : const char *name;
11361 : enum smb_signing_setting signing_setting;
11362 : enum protocol_types protocol;
11363 1 : } runs[] = {
11364 : {
11365 : .name = "NT1",
11366 : .signing_setting = SMB_SIGNING_IF_REQUIRED,
11367 : .protocol = PROTOCOL_NT1,
11368 : },{
11369 : .name = "NT1 - SIGNING_REQUIRED",
11370 : .signing_setting = SMB_SIGNING_REQUIRED,
11371 : .protocol = PROTOCOL_NT1,
11372 : },
11373 : };
11374 :
11375 1 : printf("starting large_readx test\n");
11376 :
11377 1 : if (!torture_open_connection(&cli1, 0)) {
11378 0 : goto out;
11379 : }
11380 :
11381 1 : normal_caps = smb1cli_conn_capabilities(cli1->conn);
11382 :
11383 1 : if (!(normal_caps & CAP_LARGE_READX)) {
11384 0 : d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11385 : (unsigned int)normal_caps);
11386 0 : goto out;
11387 : }
11388 :
11389 : /* Create a file of size 4MB. */
11390 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11391 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11392 : 0, 0, &fnum1, NULL);
11393 :
11394 1 : if (!NT_STATUS_IS_OK(status)) {
11395 0 : d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11396 0 : goto out;
11397 : }
11398 :
11399 : /* Write file_size bytes. */
11400 1 : buf = talloc_zero_array(frame, uint8_t, file_size);
11401 1 : if (buf == NULL) {
11402 0 : goto out;
11403 : }
11404 :
11405 1 : status = cli_writeall(cli1,
11406 : fnum1,
11407 : 0,
11408 : buf,
11409 : 0,
11410 : file_size,
11411 : NULL);
11412 1 : if (!NT_STATUS_IS_OK(status)) {
11413 0 : d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11414 0 : goto out;
11415 : }
11416 :
11417 1 : status = cli_close(cli1, fnum1);
11418 1 : if (!NT_STATUS_IS_OK(status)) {
11419 0 : d_printf("cli_close failed: %s\n", nt_errstr(status));
11420 0 : goto out;
11421 : }
11422 :
11423 1 : fnum1 = UINT16_MAX;
11424 :
11425 3 : for (i=0; i < ARRAY_SIZE(runs); i++) {
11426 2 : enum smb_signing_setting saved_signing_setting = signing_state;
11427 2 : uint16_t fnum2 = -1;
11428 :
11429 2 : if (do_encrypt &&
11430 0 : (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11431 : {
11432 0 : d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11433 0 : continue;
11434 : }
11435 :
11436 2 : d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11437 :
11438 2 : signing_state = runs[i].signing_setting;
11439 2 : cli2 = open_nbt_connection();
11440 2 : signing_state = saved_signing_setting;
11441 2 : if (cli2 == NULL) {
11442 0 : goto out;
11443 : }
11444 :
11445 2 : status = smbXcli_negprot(cli2->conn,
11446 2 : cli2->timeout,
11447 : runs[i].protocol,
11448 : runs[i].protocol);
11449 2 : if (!NT_STATUS_IS_OK(status)) {
11450 0 : goto out;
11451 : }
11452 :
11453 2 : status = cli_session_setup_creds(cli2, torture_creds);
11454 2 : if (!NT_STATUS_IS_OK(status)) {
11455 0 : goto out;
11456 : }
11457 :
11458 2 : status = cli_tree_connect(cli2,
11459 : share,
11460 : "?????",
11461 : password);
11462 2 : if (!NT_STATUS_IS_OK(status)) {
11463 0 : goto out;
11464 : }
11465 :
11466 2 : cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11467 :
11468 2 : normal_caps = smb1cli_conn_capabilities(cli2->conn);
11469 :
11470 2 : if (!(normal_caps & CAP_LARGE_READX)) {
11471 0 : d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11472 : (unsigned int)normal_caps);
11473 0 : goto out;
11474 : }
11475 :
11476 2 : if (do_encrypt) {
11477 0 : if (force_cli_encryption(cli2, share) == false) {
11478 0 : goto out;
11479 : }
11480 2 : } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11481 : uint16_t major, minor;
11482 : uint32_t caplow, caphigh;
11483 :
11484 0 : status = cli_unix_extensions_version(cli2,
11485 : &major, &minor,
11486 : &caplow, &caphigh);
11487 0 : if (!NT_STATUS_IS_OK(status)) {
11488 0 : goto out;
11489 : }
11490 : }
11491 :
11492 2 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11493 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11494 : 0, 0, &fnum2, NULL);
11495 2 : if (!NT_STATUS_IS_OK(status)) {
11496 0 : d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11497 0 : goto out;
11498 : }
11499 :
11500 : /* All reads must return less than file_size bytes. */
11501 2 : if (!large_readx_tests(cli2, fnum2, buf)) {
11502 0 : goto out;
11503 : }
11504 :
11505 2 : status = cli_close(cli2, fnum2);
11506 2 : if (!NT_STATUS_IS_OK(status)) {
11507 0 : d_printf("cli_close failed: %s\n", nt_errstr(status));
11508 0 : goto out;
11509 : }
11510 2 : fnum2 = -1;
11511 :
11512 2 : if (!torture_close_connection(cli2)) {
11513 0 : goto out;
11514 : }
11515 2 : cli2 = NULL;
11516 : }
11517 :
11518 1 : correct = true;
11519 1 : printf("Success on large_readx test\n");
11520 :
11521 1 : out:
11522 :
11523 1 : if (cli2) {
11524 0 : if (!torture_close_connection(cli2)) {
11525 0 : correct = false;
11526 : }
11527 : }
11528 :
11529 1 : if (cli1) {
11530 1 : if (fnum1 != UINT16_MAX) {
11531 0 : status = cli_close(cli1, fnum1);
11532 0 : if (!NT_STATUS_IS_OK(status)) {
11533 0 : d_printf("cli_close failed: %s\n", nt_errstr(status));
11534 : }
11535 0 : fnum1 = UINT16_MAX;
11536 : }
11537 :
11538 1 : status = cli_unlink(cli1, fname,
11539 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11540 1 : if (!NT_STATUS_IS_OK(status)) {
11541 0 : printf("unlink failed (%s)\n", nt_errstr(status));
11542 : }
11543 :
11544 1 : if (!torture_close_connection(cli1)) {
11545 0 : correct = false;
11546 : }
11547 : }
11548 :
11549 1 : TALLOC_FREE(frame);
11550 :
11551 1 : printf("finished large_readx test\n");
11552 1 : return correct;
11553 : }
11554 :
11555 0 : static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11556 : const char *mask,
11557 : void *private_data)
11558 : {
11559 0 : uint32_t *p_attr = (uint32_t *)private_data;
11560 :
11561 0 : if (strequal(finfo->name, test_filename)) {
11562 0 : *p_attr = finfo->attr;
11563 : }
11564 :
11565 0 : return NT_STATUS_OK;
11566 : }
11567 :
11568 0 : static bool run_msdfs_attribute(int dummy)
11569 : {
11570 : static struct cli_state *cli;
11571 0 : bool correct = false;
11572 0 : uint32_t attr = 0;
11573 : NTSTATUS status;
11574 :
11575 0 : printf("Starting MSDFS-ATTRIBUTE test\n");
11576 :
11577 0 : if (test_filename == NULL || test_filename[0] == '\0') {
11578 0 : printf("MSDFS-ATTRIBUTE test "
11579 : "needs -f filename-of-msdfs-link\n");
11580 0 : return false;
11581 : }
11582 :
11583 : /*
11584 : * NB. We use torture_open_connection_flags() not
11585 : * torture_open_connection() as the latter forces
11586 : * SMB1.
11587 : */
11588 0 : if (!torture_open_connection_flags(&cli, 0, 0)) {
11589 0 : return false;
11590 : }
11591 :
11592 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11593 :
11594 0 : status = cli_list(cli,
11595 : "*",
11596 : FILE_ATTRIBUTE_DIRECTORY,
11597 : msdfs_attribute_list_fn,
11598 : &attr);
11599 :
11600 0 : if (!NT_STATUS_IS_OK(status)) {
11601 0 : printf("cli_list failed with %s\n",
11602 : nt_errstr(status));
11603 0 : goto out;
11604 : }
11605 0 : if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11606 0 : printf("file %s should have "
11607 : "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11608 : test_filename,
11609 : (unsigned int)attr);
11610 0 : goto out;
11611 : }
11612 :
11613 0 : if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11614 0 : printf("file %s should have "
11615 : "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11616 : test_filename,
11617 : (unsigned int)attr);
11618 0 : goto out;
11619 : }
11620 :
11621 0 : correct = true;
11622 :
11623 0 : out:
11624 :
11625 0 : torture_close_connection(cli);
11626 0 : return correct;
11627 : }
11628 :
11629 0 : static bool run_cli_echo(int dummy)
11630 : {
11631 : struct cli_state *cli;
11632 : NTSTATUS status;
11633 :
11634 0 : printf("starting cli_echo test\n");
11635 0 : if (!torture_open_connection(&cli, 0)) {
11636 0 : return false;
11637 : }
11638 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11639 :
11640 0 : status = cli_echo(cli, 5, data_blob_const("hello", 5));
11641 :
11642 0 : d_printf("cli_echo returned %s\n", nt_errstr(status));
11643 :
11644 0 : torture_close_connection(cli);
11645 0 : return NT_STATUS_IS_OK(status);
11646 : }
11647 :
11648 2 : static int splice_status(off_t written, void *priv)
11649 : {
11650 2 : return true;
11651 : }
11652 :
11653 1 : static bool run_cli_splice(int dummy)
11654 : {
11655 1 : uint8_t *buf = NULL;
11656 1 : struct cli_state *cli1 = NULL;
11657 1 : bool correct = false;
11658 1 : const char *fname_src = "\\splice_src.dat";
11659 1 : const char *fname_dst = "\\splice_dst.dat";
11660 : NTSTATUS status;
11661 1 : uint16_t fnum1 = UINT16_MAX;
11662 1 : uint16_t fnum2 = UINT16_MAX;
11663 1 : size_t file_size = 2*1024*1024;
11664 1 : size_t splice_size = 1*1024*1024 + 713;
11665 : uint8_t digest1[16], digest2[16];
11666 1 : off_t written = 0;
11667 1 : size_t nread = 0;
11668 1 : TALLOC_CTX *frame = talloc_stackframe();
11669 :
11670 1 : printf("starting cli_splice test\n");
11671 :
11672 1 : if (!torture_open_connection(&cli1, 0)) {
11673 0 : goto out;
11674 : }
11675 :
11676 1 : cli_unlink(cli1, fname_src,
11677 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11678 1 : cli_unlink(cli1, fname_dst,
11679 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11680 :
11681 : /* Create a file */
11682 1 : status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11683 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11684 : 0, 0, &fnum1, NULL);
11685 :
11686 1 : if (!NT_STATUS_IS_OK(status)) {
11687 0 : d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11688 0 : goto out;
11689 : }
11690 :
11691 : /* Write file_size bytes - must be bigger than splice_size. */
11692 1 : buf = talloc_zero_array(frame, uint8_t, file_size);
11693 1 : if (buf == NULL) {
11694 0 : d_printf("talloc_fail\n");
11695 0 : goto out;
11696 : }
11697 :
11698 : /* Fill it with random numbers. */
11699 1 : generate_random_buffer(buf, file_size);
11700 :
11701 : /* MD5 the first 1MB + 713 bytes. */
11702 1 : gnutls_hash_fast(GNUTLS_DIG_MD5,
11703 : buf,
11704 : splice_size,
11705 : digest1);
11706 :
11707 1 : status = cli_writeall(cli1,
11708 : fnum1,
11709 : 0,
11710 : buf,
11711 : 0,
11712 : file_size,
11713 : NULL);
11714 1 : if (!NT_STATUS_IS_OK(status)) {
11715 0 : d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11716 0 : goto out;
11717 : }
11718 :
11719 1 : status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11720 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11721 : 0, 0, &fnum2, NULL);
11722 :
11723 1 : if (!NT_STATUS_IS_OK(status)) {
11724 0 : d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11725 0 : goto out;
11726 : }
11727 :
11728 : /* Now splice 1MB + 713 bytes. */
11729 1 : status = cli_splice(cli1,
11730 : cli1,
11731 : fnum1,
11732 : fnum2,
11733 : splice_size,
11734 : 0,
11735 : 0,
11736 : &written,
11737 : splice_status,
11738 : NULL);
11739 :
11740 1 : if (!NT_STATUS_IS_OK(status)) {
11741 0 : d_printf("cli_splice failed: %s\n", nt_errstr(status));
11742 0 : goto out;
11743 : }
11744 :
11745 : /* Clear the old buffer. */
11746 1 : memset(buf, '\0', file_size);
11747 :
11748 : /* Read the new file. */
11749 1 : status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11750 1 : if (!NT_STATUS_IS_OK(status)) {
11751 0 : d_printf("cli_read failed: %s\n", nt_errstr(status));
11752 0 : goto out;
11753 : }
11754 1 : if (nread != splice_size) {
11755 0 : d_printf("bad read of 0x%x, should be 0x%x\n",
11756 : (unsigned int)nread,
11757 : (unsigned int)splice_size);
11758 0 : goto out;
11759 : }
11760 :
11761 : /* MD5 the first 1MB + 713 bytes. */
11762 1 : gnutls_hash_fast(GNUTLS_DIG_MD5,
11763 : buf,
11764 : splice_size,
11765 : digest2);
11766 :
11767 : /* Must be the same. */
11768 1 : if (memcmp(digest1, digest2, 16) != 0) {
11769 0 : d_printf("bad MD5 compare\n");
11770 0 : goto out;
11771 : }
11772 :
11773 1 : correct = true;
11774 1 : printf("Success on cli_splice test\n");
11775 :
11776 1 : out:
11777 :
11778 1 : if (cli1) {
11779 1 : if (fnum1 != UINT16_MAX) {
11780 1 : cli_close(cli1, fnum1);
11781 : }
11782 1 : if (fnum2 != UINT16_MAX) {
11783 1 : cli_close(cli1, fnum2);
11784 : }
11785 :
11786 1 : cli_unlink(cli1, fname_src,
11787 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11788 1 : cli_unlink(cli1, fname_dst,
11789 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11790 :
11791 1 : if (!torture_close_connection(cli1)) {
11792 0 : correct = false;
11793 : }
11794 : }
11795 :
11796 1 : TALLOC_FREE(frame);
11797 1 : return correct;
11798 : }
11799 :
11800 0 : static bool run_uid_regression_test(int dummy)
11801 : {
11802 : static struct cli_state *cli;
11803 : int16_t old_vuid;
11804 : int32_t old_cnum;
11805 0 : bool correct = True;
11806 0 : struct smbXcli_tcon *tcon_copy = NULL;
11807 : NTSTATUS status;
11808 :
11809 0 : printf("starting uid regression test\n");
11810 :
11811 0 : if (!torture_open_connection(&cli, 0)) {
11812 0 : return False;
11813 : }
11814 :
11815 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11816 :
11817 : /* Ok - now save then logoff our current user. */
11818 0 : old_vuid = cli_state_get_uid(cli);
11819 :
11820 0 : status = cli_ulogoff(cli);
11821 0 : if (!NT_STATUS_IS_OK(status)) {
11822 0 : d_printf("(%s) cli_ulogoff failed: %s\n",
11823 : __location__, nt_errstr(status));
11824 0 : correct = false;
11825 0 : goto out;
11826 : }
11827 :
11828 0 : cli_state_set_uid(cli, old_vuid);
11829 :
11830 : /* Try an operation. */
11831 0 : status = cli_mkdir(cli, "\\uid_reg_test");
11832 0 : if (NT_STATUS_IS_OK(status)) {
11833 0 : d_printf("(%s) cli_mkdir succeeded\n",
11834 : __location__);
11835 0 : correct = false;
11836 0 : goto out;
11837 : } else {
11838 : /* Should be bad uid. */
11839 0 : if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11840 0 : NT_STATUS_USER_SESSION_DELETED)) {
11841 0 : correct = false;
11842 0 : goto out;
11843 : }
11844 : }
11845 :
11846 0 : old_cnum = cli_state_get_tid(cli);
11847 : /*
11848 : * This is an SMB1-only test.
11849 : * Copy the tcon, not "save/restore".
11850 : *
11851 : * In SMB1 the cli_tdis() below frees
11852 : * cli->smb1.tcon so we need a copy
11853 : * of the struct to put back for the
11854 : * second tdis call with invalid vuid.
11855 : *
11856 : * This is a test-only hack. Real client code
11857 : * uses cli_state_save_tcon_share()/cli_state_restore_tcon_share().
11858 : */
11859 0 : tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
11860 0 : if (tcon_copy == NULL) {
11861 0 : correct = false;
11862 0 : goto out;
11863 : }
11864 :
11865 : /* Now try a SMBtdis with the invalid vuid set to zero. */
11866 0 : cli_state_set_uid(cli, 0);
11867 :
11868 : /* This should succeed. */
11869 0 : status = cli_tdis(cli);
11870 :
11871 0 : if (NT_STATUS_IS_OK(status)) {
11872 0 : d_printf("First tdis with invalid vuid should succeed.\n");
11873 : } else {
11874 0 : d_printf("First tdis failed (%s)\n", nt_errstr(status));
11875 0 : correct = false;
11876 0 : cli->smb1.tcon = tcon_copy;
11877 0 : goto out;
11878 : }
11879 :
11880 0 : cli->smb1.tcon = tcon_copy;
11881 0 : cli_state_set_uid(cli, old_vuid);
11882 0 : cli_state_set_tid(cli, old_cnum);
11883 :
11884 : /* This should fail. */
11885 0 : status = cli_tdis(cli);
11886 0 : if (NT_STATUS_IS_OK(status)) {
11887 0 : d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
11888 0 : correct = false;
11889 0 : goto out;
11890 : } else {
11891 : /* Should be bad tid. */
11892 0 : if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
11893 0 : NT_STATUS_NETWORK_NAME_DELETED)) {
11894 0 : correct = false;
11895 0 : goto out;
11896 : }
11897 : }
11898 :
11899 0 : cli_rmdir(cli, "\\uid_reg_test");
11900 :
11901 0 : out:
11902 :
11903 0 : cli_shutdown(cli);
11904 0 : return correct;
11905 : }
11906 :
11907 :
11908 : static const char *illegal_chars = "*\\/?<>|\":";
11909 : static char force_shortname_chars[] = " +,.[];=\177";
11910 :
11911 0 : static NTSTATUS shortname_del_fn(struct file_info *finfo,
11912 : const char *mask, void *state)
11913 : {
11914 0 : struct cli_state *pcli = (struct cli_state *)state;
11915 : fstring fname;
11916 0 : NTSTATUS status = NT_STATUS_OK;
11917 :
11918 0 : slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
11919 :
11920 0 : if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
11921 0 : return NT_STATUS_OK;
11922 :
11923 0 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
11924 0 : status = cli_rmdir(pcli, fname);
11925 0 : if (!NT_STATUS_IS_OK(status)) {
11926 0 : printf("del_fn: failed to rmdir %s\n,", fname );
11927 : }
11928 : } else {
11929 0 : status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11930 0 : if (!NT_STATUS_IS_OK(status)) {
11931 0 : printf("del_fn: failed to unlink %s\n,", fname );
11932 : }
11933 : }
11934 0 : return status;
11935 : }
11936 :
11937 : struct sn_state {
11938 : int matched;
11939 : int i;
11940 : bool val;
11941 : };
11942 :
11943 0 : static NTSTATUS shortname_list_fn(struct file_info *finfo,
11944 : const char *name, void *state)
11945 : {
11946 0 : struct sn_state *s = (struct sn_state *)state;
11947 0 : int i = s->i;
11948 :
11949 : #if 0
11950 : printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
11951 : i, finfo->name, finfo->short_name);
11952 : #endif
11953 :
11954 0 : if (strchr(force_shortname_chars, i)) {
11955 0 : if (!finfo->short_name) {
11956 : /* Shortname not created when it should be. */
11957 0 : d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
11958 : __location__, finfo->name, i);
11959 0 : s->val = true;
11960 : }
11961 0 : } else if (finfo->short_name){
11962 : /* Shortname created when it should not be. */
11963 0 : d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
11964 : __location__, finfo->short_name, finfo->name);
11965 0 : s->val = true;
11966 : }
11967 0 : s->matched += 1;
11968 0 : return NT_STATUS_OK;
11969 : }
11970 :
11971 0 : static bool run_shortname_test(int dummy)
11972 : {
11973 : static struct cli_state *cli;
11974 0 : bool correct = True;
11975 : int i;
11976 : struct sn_state s;
11977 : char fname[40];
11978 : NTSTATUS status;
11979 :
11980 0 : printf("starting shortname test\n");
11981 :
11982 0 : if (!torture_open_connection(&cli, 0)) {
11983 0 : return False;
11984 : }
11985 :
11986 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11987 :
11988 0 : cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11989 0 : cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11990 0 : cli_rmdir(cli, "\\shortname");
11991 :
11992 0 : status = cli_mkdir(cli, "\\shortname");
11993 0 : if (!NT_STATUS_IS_OK(status)) {
11994 0 : d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
11995 : __location__, nt_errstr(status));
11996 0 : correct = false;
11997 0 : goto out;
11998 : }
11999 :
12000 0 : if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
12001 0 : correct = false;
12002 0 : goto out;
12003 : }
12004 0 : if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
12005 0 : correct = false;
12006 0 : goto out;
12007 : }
12008 :
12009 0 : s.val = false;
12010 :
12011 0 : for (i = 32; i < 128; i++) {
12012 0 : uint16_t fnum = (uint16_t)-1;
12013 :
12014 0 : s.i = i;
12015 :
12016 0 : if (strchr(illegal_chars, i)) {
12017 0 : continue;
12018 : }
12019 0 : fname[15] = i;
12020 :
12021 0 : status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12022 : FILE_SHARE_READ|FILE_SHARE_WRITE,
12023 : FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12024 0 : if (!NT_STATUS_IS_OK(status)) {
12025 0 : d_printf("(%s) cli_nt_create of %s failed: %s\n",
12026 : __location__, fname, nt_errstr(status));
12027 0 : correct = false;
12028 0 : goto out;
12029 : }
12030 0 : cli_close(cli, fnum);
12031 :
12032 0 : s.matched = 0;
12033 0 : status = cli_list(cli, "\\shortname\\test*.*", 0,
12034 : shortname_list_fn, &s);
12035 0 : if (s.matched != 1) {
12036 0 : d_printf("(%s) failed to list %s: %s\n",
12037 : __location__, fname, nt_errstr(status));
12038 0 : correct = false;
12039 0 : goto out;
12040 : }
12041 :
12042 0 : status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12043 0 : if (!NT_STATUS_IS_OK(status)) {
12044 0 : d_printf("(%s) failed to delete %s: %s\n",
12045 : __location__, fname, nt_errstr(status));
12046 0 : correct = false;
12047 0 : goto out;
12048 : }
12049 :
12050 0 : if (s.val) {
12051 0 : correct = false;
12052 0 : goto out;
12053 : }
12054 : }
12055 :
12056 0 : out:
12057 :
12058 0 : cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12059 0 : cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12060 0 : cli_rmdir(cli, "\\shortname");
12061 0 : torture_close_connection(cli);
12062 0 : return correct;
12063 : }
12064 :
12065 : TLDAPRC callback_code;
12066 :
12067 0 : static void pagedsearch_cb(struct tevent_req *req)
12068 : {
12069 : TLDAPRC rc;
12070 : struct tldap_message *msg;
12071 : char *dn;
12072 :
12073 0 : rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12074 0 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12075 0 : d_printf("tldap_search_paged_recv failed: %s\n",
12076 : tldap_rc2string(rc));
12077 0 : callback_code = rc;
12078 0 : return;
12079 : }
12080 0 : if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12081 0 : TALLOC_FREE(msg);
12082 0 : return;
12083 : }
12084 0 : if (!tldap_entry_dn(msg, &dn)) {
12085 0 : d_printf("tldap_entry_dn failed\n");
12086 0 : return;
12087 : }
12088 0 : d_printf("%s\n", dn);
12089 0 : TALLOC_FREE(msg);
12090 : }
12091 :
12092 : enum tldap_extended_val {
12093 : EXTENDED_ZERO = 0,
12094 : EXTENDED_ONE = 1,
12095 : EXTENDED_NONE = 2,
12096 : };
12097 :
12098 : /*
12099 : * Construct an extended dn control with either no value, 0 or 1
12100 : *
12101 : * No value and 0 are equivalent (non-hyphenated GUID)
12102 : * 1 has the hyphenated GUID
12103 : */
12104 : static struct tldap_control *
12105 0 : tldap_build_extended_control(enum tldap_extended_val val)
12106 : {
12107 : struct tldap_control empty_control;
12108 : struct asn1_data *data;
12109 :
12110 0 : ZERO_STRUCT(empty_control);
12111 :
12112 0 : if (val != EXTENDED_NONE) {
12113 0 : data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12114 :
12115 0 : if (!data) {
12116 0 : return NULL;
12117 : }
12118 :
12119 0 : if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12120 0 : return NULL;
12121 : }
12122 :
12123 0 : if (!asn1_write_Integer(data, (int)val)) {
12124 0 : return NULL;
12125 : }
12126 :
12127 0 : if (!asn1_pop_tag(data)) {
12128 0 : return NULL;
12129 : }
12130 :
12131 0 : if (!asn1_blob(data, &empty_control.value)) {
12132 0 : return NULL;
12133 : }
12134 : }
12135 :
12136 0 : empty_control.oid = "1.2.840.113556.1.4.529";
12137 0 : empty_control.critical = true;
12138 :
12139 0 : return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12140 :
12141 : }
12142 :
12143 0 : static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12144 : enum tldap_extended_val control_val)
12145 : {
12146 0 : struct tldap_control *control = tldap_build_extended_control(control_val);
12147 0 : char *dn = NULL;
12148 : struct tldap_message **msg;
12149 : TLDAPRC rc;
12150 :
12151 0 : rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12152 : "(objectClass=*)", NULL, 0, 0,
12153 : control, 1, NULL,
12154 : 0, 0, 0, 0, talloc_tos(), &msg);
12155 0 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12156 0 : d_printf("tldap_search for domain DN failed: %s\n",
12157 : tldap_errstr(talloc_tos(), ld, rc));
12158 0 : return false;
12159 : }
12160 :
12161 0 : if (!tldap_entry_dn(msg[0], &dn)) {
12162 0 : d_printf("tldap_search domain DN fetch failed: %s\n",
12163 : tldap_errstr(talloc_tos(), ld, rc));
12164 0 : return false;
12165 : }
12166 :
12167 0 : d_printf("%s\n", dn);
12168 : {
12169 : uint32_t time_low;
12170 : uint32_t time_mid, time_hi_and_version;
12171 : uint32_t clock_seq[2];
12172 : uint32_t node[6];
12173 : char next;
12174 :
12175 0 : switch (control_val) {
12176 0 : case EXTENDED_NONE:
12177 : case EXTENDED_ZERO:
12178 : /*
12179 : * When reading GUIDs with hyphens, scanf will treat
12180 : * hyphen as a hex character (and counts as part of the
12181 : * width). This creates leftover GUID string which we
12182 : * check will for with 'next' and closing '>'.
12183 : */
12184 0 : if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12185 : &time_low, &time_mid,
12186 : &time_hi_and_version, &clock_seq[0],
12187 : &clock_seq[1], &node[0], &node[1],
12188 : &node[2], &node[3], &node[4],
12189 : &node[5], &next)) {
12190 : /* This GUID is good */
12191 : } else {
12192 0 : d_printf("GUID format in control (no hyphens) doesn't match output\n");
12193 0 : return false;
12194 : }
12195 :
12196 0 : break;
12197 0 : case EXTENDED_ONE:
12198 0 : if (12 == sscanf(dn,
12199 : "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12200 : &time_low, &time_mid,
12201 : &time_hi_and_version, &clock_seq[0],
12202 : &clock_seq[1], &node[0], &node[1],
12203 : &node[2], &node[3], &node[4],
12204 : &node[5], &next)) {
12205 : /* This GUID is good */
12206 : } else {
12207 0 : d_printf("GUID format in control (with hyphens) doesn't match output\n");
12208 0 : return false;
12209 : }
12210 :
12211 0 : break;
12212 0 : default:
12213 0 : return false;
12214 : }
12215 : }
12216 :
12217 0 : return true;
12218 : }
12219 :
12220 0 : static bool run_tldap(int dummy)
12221 : {
12222 : struct tldap_context *ld;
12223 : int fd;
12224 : TLDAPRC rc;
12225 : NTSTATUS status;
12226 : struct sockaddr_storage addr;
12227 : struct tevent_context *ev;
12228 : struct tevent_req *req;
12229 : char *basedn;
12230 : const char *filter;
12231 :
12232 0 : if (!resolve_name(host, &addr, 0, false)) {
12233 0 : d_printf("could not find host %s\n", host);
12234 0 : return false;
12235 : }
12236 0 : status = open_socket_out(&addr, 389, 9999, &fd);
12237 0 : if (!NT_STATUS_IS_OK(status)) {
12238 0 : d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12239 0 : return false;
12240 : }
12241 :
12242 0 : ld = tldap_context_create(talloc_tos(), fd);
12243 0 : if (ld == NULL) {
12244 0 : close(fd);
12245 0 : d_printf("tldap_context_create failed\n");
12246 0 : return false;
12247 : }
12248 :
12249 0 : rc = tldap_fetch_rootdse(ld);
12250 0 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12251 0 : d_printf("tldap_fetch_rootdse failed: %s\n",
12252 : tldap_errstr(talloc_tos(), ld, rc));
12253 0 : return false;
12254 : }
12255 :
12256 0 : basedn = tldap_talloc_single_attribute(
12257 : tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12258 0 : if (basedn == NULL) {
12259 0 : d_printf("no defaultNamingContext\n");
12260 0 : return false;
12261 : }
12262 0 : d_printf("defaultNamingContext: %s\n", basedn);
12263 :
12264 0 : ev = samba_tevent_context_init(talloc_tos());
12265 0 : if (ev == NULL) {
12266 0 : d_printf("tevent_context_init failed\n");
12267 0 : return false;
12268 : }
12269 :
12270 0 : rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12271 : loadparm_init_s3(talloc_tos(),
12272 : loadparm_s3_helpers()),
12273 : GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12274 :
12275 0 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12276 0 : d_printf("tldap_gensec_bind failed\n");
12277 0 : return false;
12278 : }
12279 :
12280 0 : callback_code = TLDAP_SUCCESS;
12281 :
12282 0 : req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12283 : TLDAP_SCOPE_SUB, "(objectclass=*)",
12284 : NULL, 0, 0,
12285 : NULL, 0, NULL, 0, 0, 0, 0, 5);
12286 0 : if (req == NULL) {
12287 0 : d_printf("tldap_search_paged_send failed\n");
12288 0 : return false;
12289 : }
12290 0 : tevent_req_set_callback(req, pagedsearch_cb, NULL);
12291 :
12292 0 : tevent_req_poll(req, ev);
12293 :
12294 0 : TALLOC_FREE(req);
12295 :
12296 0 : rc = callback_code;
12297 :
12298 0 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12299 0 : d_printf("tldap_search with paging failed: %s\n",
12300 : tldap_errstr(talloc_tos(), ld, rc));
12301 0 : return false;
12302 : }
12303 :
12304 : /* test search filters against rootDSE */
12305 0 : filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12306 : "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12307 :
12308 0 : rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12309 : NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12310 : talloc_tos(), NULL);
12311 0 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12312 0 : d_printf("tldap_search with complex filter failed: %s\n",
12313 : tldap_errstr(talloc_tos(), ld, rc));
12314 0 : return false;
12315 : }
12316 :
12317 : /*
12318 : * Tests to check for regression of:
12319 : *
12320 : * https://bugzilla.samba.org/show_bug.cgi?id=14029
12321 : *
12322 : * TLDAP used here to pick apart the original string DN (with GUID)
12323 : */
12324 0 : if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12325 0 : d_printf("tldap_search with extended dn (no val) failed: %s\n",
12326 : tldap_errstr(talloc_tos(), ld, rc));
12327 0 : return false;
12328 : }
12329 0 : if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12330 0 : d_printf("tldap_search with extended dn (0) failed: %s\n",
12331 : tldap_errstr(talloc_tos(), ld, rc));
12332 0 : return false;
12333 : }
12334 0 : if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12335 0 : d_printf("tldap_search with extended dn (1) failed: %s\n",
12336 : tldap_errstr(talloc_tos(), ld, rc));
12337 0 : return false;
12338 : }
12339 :
12340 0 : TALLOC_FREE(ld);
12341 0 : return true;
12342 : }
12343 :
12344 : /* Torture test to ensure no regression of :
12345 : https://bugzilla.samba.org/show_bug.cgi?id=7084
12346 : */
12347 :
12348 0 : static bool run_dir_createtime(int dummy)
12349 : {
12350 : struct cli_state *cli;
12351 0 : const char *dname = "\\testdir_createtime";
12352 0 : const char *fname = "\\testdir_createtime\\testfile";
12353 : NTSTATUS status;
12354 : struct timespec create_time;
12355 : struct timespec create_time1;
12356 : uint16_t fnum;
12357 0 : bool ret = false;
12358 : uint64_t ino;
12359 :
12360 0 : if (!torture_open_connection(&cli, 0)) {
12361 0 : return false;
12362 : }
12363 :
12364 0 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12365 : /* Ensure ino is zero, SMB2 gets a real one. */
12366 0 : ino = 0;
12367 : } else {
12368 : /* Ensure ino is -1, SMB1 never gets a real one. */
12369 0 : ino = (uint64_t)-1;
12370 : }
12371 :
12372 0 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12373 0 : cli_rmdir(cli, dname);
12374 :
12375 0 : status = cli_mkdir(cli, dname);
12376 0 : if (!NT_STATUS_IS_OK(status)) {
12377 0 : printf("mkdir failed: %s\n", nt_errstr(status));
12378 0 : goto out;
12379 : }
12380 :
12381 0 : status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
12382 : NULL, NULL, &ino);
12383 0 : if (!NT_STATUS_IS_OK(status)) {
12384 0 : printf("cli_qpathinfo2 returned %s\n",
12385 : nt_errstr(status));
12386 0 : goto out;
12387 : }
12388 :
12389 0 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12390 : /* SMB2 should always return an inode. */
12391 0 : if (ino == 0) {
12392 0 : printf("SMB2 bad inode (0)\n");
12393 0 : goto out;
12394 : }
12395 : } else {
12396 : /* SMB1 must always return zero here. */
12397 0 : if (ino != 0) {
12398 0 : printf("SMB1 bad inode (!0)\n");
12399 0 : goto out;
12400 : }
12401 : }
12402 :
12403 : /* Sleep 3 seconds, then create a file. */
12404 0 : sleep(3);
12405 :
12406 0 : status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12407 : DENY_NONE, &fnum);
12408 0 : if (!NT_STATUS_IS_OK(status)) {
12409 0 : printf("cli_openx failed: %s\n", nt_errstr(status));
12410 0 : goto out;
12411 : }
12412 :
12413 0 : status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
12414 : NULL, NULL, NULL);
12415 0 : if (!NT_STATUS_IS_OK(status)) {
12416 0 : printf("cli_qpathinfo2 (2) returned %s\n",
12417 : nt_errstr(status));
12418 0 : goto out;
12419 : }
12420 :
12421 0 : if (timespec_compare(&create_time1, &create_time)) {
12422 0 : printf("run_dir_createtime: create time was updated (error)\n");
12423 : } else {
12424 0 : printf("run_dir_createtime: create time was not updated (correct)\n");
12425 0 : ret = true;
12426 : }
12427 :
12428 0 : out:
12429 :
12430 0 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12431 0 : cli_rmdir(cli, dname);
12432 0 : if (!torture_close_connection(cli)) {
12433 0 : ret = false;
12434 : }
12435 0 : return ret;
12436 : }
12437 :
12438 :
12439 0 : static bool run_streamerror(int dummy)
12440 : {
12441 : struct cli_state *cli;
12442 0 : const char *dname = "\\testdir_streamerror";
12443 0 : const char *streamname =
12444 : "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12445 : NTSTATUS status;
12446 : time_t change_time, access_time, write_time;
12447 : off_t size;
12448 : uint16_t fnum;
12449 : uint32_t attr;
12450 0 : bool ret = true;
12451 :
12452 0 : if (!torture_open_connection(&cli, 0)) {
12453 0 : return false;
12454 : }
12455 :
12456 0 : torture_deltree(cli, dname);
12457 :
12458 0 : status = cli_mkdir(cli, dname);
12459 0 : if (!NT_STATUS_IS_OK(status)) {
12460 0 : printf("mkdir failed: %s\n", nt_errstr(status));
12461 0 : return false;
12462 : }
12463 :
12464 0 : status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12465 : &write_time, &size, &attr);
12466 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12467 0 : printf("pathinfo returned %s, expected "
12468 : "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12469 : nt_errstr(status));
12470 0 : ret = false;
12471 : }
12472 :
12473 0 : status = cli_ntcreate(cli, streamname, 0x16,
12474 : FILE_READ_DATA|FILE_READ_EA|
12475 : FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12476 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12477 : FILE_OPEN, 0, 0, &fnum, NULL);
12478 :
12479 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12480 0 : printf("ntcreate returned %s, expected "
12481 : "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12482 : nt_errstr(status));
12483 0 : ret = false;
12484 : }
12485 :
12486 :
12487 0 : cli_rmdir(cli, dname);
12488 0 : return ret;
12489 : }
12490 :
12491 : struct pidtest_state {
12492 : bool success;
12493 : uint16_t vwv[1];
12494 : DATA_BLOB data;
12495 : };
12496 :
12497 : static void pid_echo_done(struct tevent_req *subreq);
12498 :
12499 0 : static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12500 : struct tevent_context *ev,
12501 : struct cli_state *cli)
12502 : {
12503 : struct tevent_req *req, *subreq;
12504 : struct pidtest_state *state;
12505 :
12506 0 : req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12507 0 : if (req == NULL) {
12508 0 : return NULL;
12509 : }
12510 :
12511 0 : SSVAL(state->vwv, 0, 1);
12512 0 : state->data = data_blob_const("hello", 5);
12513 :
12514 0 : subreq = smb1cli_req_send(state,
12515 : ev,
12516 : cli->conn,
12517 : SMBecho,
12518 : 0, 0, /* *_flags */
12519 : 0, 0, /* *_flags2 */
12520 0 : cli->timeout,
12521 : 0xDEADBEEF, /* pid */
12522 : NULL, /* tcon */
12523 : NULL, /* session */
12524 0 : ARRAY_SIZE(state->vwv), state->vwv,
12525 0 : state->data.length, state->data.data);
12526 :
12527 0 : if (tevent_req_nomem(subreq, req)) {
12528 0 : return tevent_req_post(req, ev);
12529 : }
12530 0 : tevent_req_set_callback(subreq, pid_echo_done, req);
12531 0 : return req;
12532 : }
12533 :
12534 0 : static void pid_echo_done(struct tevent_req *subreq)
12535 : {
12536 0 : struct tevent_req *req = tevent_req_callback_data(
12537 : subreq, struct tevent_req);
12538 0 : struct pidtest_state *state = tevent_req_data(
12539 : req, struct pidtest_state);
12540 : NTSTATUS status;
12541 : uint32_t num_bytes;
12542 0 : uint8_t *bytes = NULL;
12543 0 : struct iovec *recv_iov = NULL;
12544 0 : uint8_t *phdr = NULL;
12545 0 : uint16_t pidlow = 0;
12546 0 : uint16_t pidhigh = 0;
12547 0 : struct smb1cli_req_expected_response expected[] = {
12548 : {
12549 : .status = NT_STATUS_OK,
12550 : .wct = 1,
12551 : },
12552 : };
12553 :
12554 0 : status = smb1cli_req_recv(subreq, state,
12555 : &recv_iov,
12556 : &phdr,
12557 : NULL, /* pwct */
12558 : NULL, /* pvwv */
12559 : NULL, /* pvwv_offset */
12560 : &num_bytes,
12561 : &bytes,
12562 : NULL, /* pbytes_offset */
12563 : NULL, /* pinbuf */
12564 : expected, ARRAY_SIZE(expected));
12565 :
12566 0 : TALLOC_FREE(subreq);
12567 :
12568 0 : if (!NT_STATUS_IS_OK(status)) {
12569 0 : tevent_req_nterror(req, status);
12570 0 : return;
12571 : }
12572 :
12573 0 : if (num_bytes != state->data.length) {
12574 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12575 0 : return;
12576 : }
12577 :
12578 0 : if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12579 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12580 0 : return;
12581 : }
12582 :
12583 : /* Check pid low/high == DEADBEEF */
12584 0 : pidlow = SVAL(phdr, HDR_PID);
12585 0 : if (pidlow != 0xBEEF){
12586 0 : printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12587 : (unsigned int)pidlow);
12588 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12589 0 : return;
12590 : }
12591 0 : pidhigh = SVAL(phdr, HDR_PIDHIGH);
12592 0 : if (pidhigh != 0xDEAD){
12593 0 : printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12594 : (unsigned int)pidhigh);
12595 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12596 0 : return;
12597 : }
12598 :
12599 0 : tevent_req_done(req);
12600 : }
12601 :
12602 0 : static NTSTATUS pid_echo_recv(struct tevent_req *req)
12603 : {
12604 0 : return tevent_req_simple_recv_ntstatus(req);
12605 : }
12606 :
12607 0 : static bool run_pidhigh(int dummy)
12608 : {
12609 0 : bool success = false;
12610 0 : struct cli_state *cli = NULL;
12611 : NTSTATUS status;
12612 0 : struct tevent_context *ev = NULL;
12613 0 : struct tevent_req *req = NULL;
12614 0 : TALLOC_CTX *frame = talloc_stackframe();
12615 :
12616 0 : printf("starting pid high test\n");
12617 0 : if (!torture_open_connection(&cli, 0)) {
12618 0 : return false;
12619 : }
12620 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
12621 :
12622 0 : ev = samba_tevent_context_init(frame);
12623 0 : if (ev == NULL) {
12624 0 : goto fail;
12625 : }
12626 :
12627 0 : req = pid_echo_send(frame, ev, cli);
12628 0 : if (req == NULL) {
12629 0 : goto fail;
12630 : }
12631 :
12632 0 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12633 0 : goto fail;
12634 : }
12635 :
12636 0 : status = pid_echo_recv(req);
12637 0 : if (NT_STATUS_IS_OK(status)) {
12638 0 : printf("pid high test ok\n");
12639 0 : success = true;
12640 : }
12641 :
12642 0 : fail:
12643 :
12644 0 : TALLOC_FREE(frame);
12645 0 : torture_close_connection(cli);
12646 0 : return success;
12647 : }
12648 :
12649 : /*
12650 : Test Windows open on a bad POSIX symlink.
12651 : */
12652 0 : static bool run_symlink_open_test(int dummy)
12653 : {
12654 : static struct cli_state *cli;
12655 0 : const char *fname = "non_existant_file";
12656 0 : const char *sname = "dangling_symlink";
12657 0 : uint16_t fnum = (uint16_t)-1;
12658 0 : bool correct = false;
12659 : NTSTATUS status;
12660 0 : TALLOC_CTX *frame = NULL;
12661 :
12662 0 : frame = talloc_stackframe();
12663 :
12664 0 : printf("Starting Windows bad symlink open test\n");
12665 :
12666 0 : if (!torture_open_connection(&cli, 0)) {
12667 0 : TALLOC_FREE(frame);
12668 0 : return false;
12669 : }
12670 :
12671 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
12672 :
12673 0 : status = torture_setup_unix_extensions(cli);
12674 0 : if (!NT_STATUS_IS_OK(status)) {
12675 0 : TALLOC_FREE(frame);
12676 0 : return false;
12677 : }
12678 :
12679 : /* Ensure nothing exists. */
12680 0 : cli_setatr(cli, fname, 0, 0);
12681 0 : cli_posix_unlink(cli, fname);
12682 0 : cli_setatr(cli, sname, 0, 0);
12683 0 : cli_posix_unlink(cli, sname);
12684 :
12685 : /* Create a symlink pointing nowhere. */
12686 0 : status = cli_posix_symlink(cli, fname, sname);
12687 0 : if (!NT_STATUS_IS_OK(status)) {
12688 0 : printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12689 : sname,
12690 : fname,
12691 : nt_errstr(status));
12692 0 : goto out;
12693 : }
12694 :
12695 : /* Now ensure that a Windows open doesn't hang. */
12696 0 : status = cli_ntcreate(cli,
12697 : sname,
12698 : 0,
12699 : FILE_READ_DATA|FILE_WRITE_DATA,
12700 : 0,
12701 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12702 : FILE_OPEN_IF,
12703 : 0x0,
12704 : 0x0,
12705 : &fnum,
12706 : NULL);
12707 :
12708 : /*
12709 : * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12710 : * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12711 : * we use O_NOFOLLOW on the server or not.
12712 : */
12713 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12714 0 : NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12715 : {
12716 0 : correct = true;
12717 : } else {
12718 0 : printf("cli_ntcreate of %s returned %s - should return"
12719 : " either (%s) or (%s)\n",
12720 : sname,
12721 : nt_errstr(status),
12722 0 : nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12723 0 : nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12724 0 : goto out;
12725 : }
12726 :
12727 0 : correct = true;
12728 :
12729 0 : out:
12730 :
12731 0 : if (fnum != (uint16_t)-1) {
12732 0 : cli_close(cli, fnum);
12733 0 : fnum = (uint16_t)-1;
12734 : }
12735 :
12736 0 : cli_setatr(cli, sname, 0, 0);
12737 0 : cli_posix_unlink(cli, sname);
12738 0 : cli_setatr(cli, fname, 0, 0);
12739 0 : cli_posix_unlink(cli, fname);
12740 :
12741 0 : if (!torture_close_connection(cli)) {
12742 0 : correct = false;
12743 : }
12744 :
12745 0 : TALLOC_FREE(frame);
12746 0 : return correct;
12747 : }
12748 :
12749 0 : static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12750 : const char *name,
12751 : void *state)
12752 : {
12753 0 : char **mangled_name_return = (char **)state;
12754 0 : bool is_mangled = strchr(finfo->name, '~');
12755 :
12756 0 : if (is_mangled) {
12757 0 : *mangled_name_return = talloc_strdup(NULL, finfo->name);
12758 0 : if (*mangled_name_return == NULL) {
12759 0 : return NT_STATUS_NO_MEMORY;
12760 : }
12761 : }
12762 0 : return NT_STATUS_OK;
12763 : }
12764 :
12765 0 : static bool run_smb1_wild_mangle_unlink_test(int dummy)
12766 : {
12767 : static struct cli_state *cli_posix = NULL;
12768 : static struct cli_state *cli = NULL;
12769 0 : uint16_t fnum = (uint16_t)-1;
12770 0 : bool correct = false;
12771 0 : const char *dname = "smb1_wild_mangle_unlink";
12772 0 : const char *aname = "smb1_wild_mangle_unlink/a";
12773 0 : const char *star_name = "smb1_wild_mangle_unlink/*";
12774 0 : char *windows_unlink_name = NULL;
12775 0 : char *mangled_name = NULL;
12776 : NTSTATUS status;
12777 :
12778 0 : printf("Starting SMB1 wild mangle unlink test\n");
12779 :
12780 : /* Open a Windows connection. */
12781 0 : if (!torture_open_connection(&cli, 0)) {
12782 0 : return false;
12783 : }
12784 :
12785 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
12786 :
12787 : /* Open a POSIX connection. */
12788 0 : if (!torture_open_connection(&cli_posix, 0)) {
12789 0 : goto out;
12790 : }
12791 :
12792 0 : smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12793 :
12794 0 : status = torture_setup_unix_extensions(cli_posix);
12795 0 : if (!NT_STATUS_IS_OK(status)) {
12796 0 : printf("server doesn't support POSIX\n");
12797 0 : goto out;
12798 : }
12799 :
12800 : /* Start fresh. */
12801 0 : torture_deltree(cli, dname);
12802 :
12803 : /*
12804 : * Create two files - 'a' and '*'.
12805 : * We need POSIX extensions for this as '*'
12806 : * is not a valid Windows name.
12807 : */
12808 :
12809 0 : status = cli_mkdir(cli, dname);
12810 0 : if (!NT_STATUS_IS_OK(status)) {
12811 0 : printf("cli_mkdir of %s returned %s\n",
12812 : dname,
12813 : nt_errstr(status));
12814 0 : goto out;
12815 : }
12816 :
12817 0 : status = cli_posix_open(cli_posix,
12818 : aname,
12819 : O_RDWR|O_CREAT|O_EXCL,
12820 : 0660,
12821 : &fnum);
12822 0 : if (!NT_STATUS_IS_OK(status)) {
12823 0 : printf("cli_posix_open (create) of %s returned %s\n",
12824 : aname,
12825 : nt_errstr(status));
12826 0 : goto out;
12827 : }
12828 0 : status = cli_close(cli_posix, fnum);
12829 0 : if (!NT_STATUS_IS_OK(status)) {
12830 0 : goto out;
12831 : }
12832 0 : status = cli_posix_open(cli_posix,
12833 : star_name,
12834 : O_RDWR|O_CREAT|O_EXCL,
12835 : 0660,
12836 : &fnum);
12837 0 : if (!NT_STATUS_IS_OK(status)) {
12838 0 : printf("cli_posix_open (create) of %s returned %s\n",
12839 : star_name,
12840 : nt_errstr(status));
12841 0 : goto out;
12842 : }
12843 0 : status = cli_close(cli_posix, fnum);
12844 0 : if (!NT_STATUS_IS_OK(status)) {
12845 0 : goto out;
12846 : }
12847 :
12848 0 : status = cli_list(cli,
12849 : star_name,
12850 : 0,
12851 : smb1_wild_mangle_list_fn,
12852 : &mangled_name);
12853 0 : if (!NT_STATUS_IS_OK(status)) {
12854 0 : printf("cli_list of %s returned %s\n",
12855 : star_name,
12856 : nt_errstr(status));
12857 0 : goto out;
12858 : }
12859 :
12860 0 : if (mangled_name == NULL) {
12861 0 : goto out;
12862 : }
12863 :
12864 0 : printf("mangled_name = %s\n",
12865 : mangled_name);
12866 :
12867 : /*
12868 : * Try a Windows unlink with the mangled name.
12869 : * This should *NOT* unlink the 'a' name.
12870 : */
12871 :
12872 0 : windows_unlink_name = talloc_asprintf(cli_posix,
12873 : "%s\\%s",
12874 : dname,
12875 : mangled_name);
12876 :
12877 0 : status = cli_unlink(cli, windows_unlink_name, 0);
12878 0 : if (!NT_STATUS_IS_OK(status)) {
12879 0 : printf("cli_unlink of %s returned %s\n",
12880 : windows_unlink_name,
12881 : nt_errstr(status));
12882 0 : goto out;
12883 : }
12884 :
12885 : /* Does 'a' still exist ? */
12886 0 : status = cli_posix_open(cli_posix,
12887 : aname,
12888 : O_RDONLY,
12889 : 0,
12890 : &fnum);
12891 0 : if (!NT_STATUS_IS_OK(status)) {
12892 0 : printf("cli_posix_open O_RNONLY of %s returned %s\n",
12893 : aname,
12894 : nt_errstr(status));
12895 0 : goto out;
12896 : }
12897 :
12898 0 : status = cli_close(cli_posix, fnum);
12899 0 : if (!NT_STATUS_IS_OK(status)) {
12900 0 : goto out;
12901 : }
12902 :
12903 0 : correct = true;
12904 :
12905 0 : out:
12906 :
12907 0 : TALLOC_FREE(windows_unlink_name);
12908 0 : TALLOC_FREE(mangled_name);
12909 :
12910 0 : if (cli != NULL) {
12911 0 : torture_deltree(cli, dname);
12912 0 : torture_close_connection(cli);
12913 : }
12914 :
12915 0 : if (cli_posix != NULL) {
12916 0 : torture_close_connection(cli_posix);
12917 : }
12918 :
12919 0 : return correct;
12920 : }
12921 :
12922 0 : static bool run_smb1_wild_mangle_rename_test(int dummy)
12923 : {
12924 : static struct cli_state *cli_posix = NULL;
12925 : static struct cli_state *cli = NULL;
12926 0 : uint16_t fnum = (uint16_t)-1;
12927 0 : bool correct = false;
12928 0 : const char *dname = "smb1_wild_mangle_rename";
12929 0 : const char *fooname = "smb1_wild_mangle_rename/foo";
12930 0 : const char *foostar_name = "smb1_wild_mangle_rename/fo*";
12931 0 : const char *wild_name = "smb1_wild_mangle_rename/*";
12932 0 : char *windows_rename_src = NULL;
12933 0 : const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
12934 0 : char *mangled_name = NULL;
12935 : NTSTATUS status;
12936 :
12937 0 : printf("Starting SMB1 wild mangle rename test\n");
12938 :
12939 0 : if (!torture_open_connection(&cli_posix, 0)) {
12940 0 : return false;
12941 : }
12942 :
12943 0 : smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12944 :
12945 0 : status = torture_setup_unix_extensions(cli_posix);
12946 0 : if (!NT_STATUS_IS_OK(status)) {
12947 0 : printf("server doesn't support POSIX\n");
12948 0 : return false;
12949 : }
12950 :
12951 : /* Open a Windows connection. */
12952 0 : if (!torture_open_connection(&cli, 0)) {
12953 0 : goto out;
12954 : }
12955 :
12956 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
12957 :
12958 : /* Ensure we start from fresh. */
12959 0 : torture_deltree(cli, dname);
12960 :
12961 : /*
12962 : * Create two files - 'foo' and 'fo*'.
12963 : * We need POSIX extensions for this as 'fo*'
12964 : * is not a valid Windows name.
12965 : */
12966 :
12967 0 : status = cli_posix_mkdir(cli_posix, dname, 0770);
12968 0 : if (!NT_STATUS_IS_OK(status)) {
12969 0 : printf("cli_posix_mkdir of %s returned %s\n",
12970 : dname,
12971 : nt_errstr(status));
12972 0 : goto out;
12973 : }
12974 :
12975 0 : status = cli_posix_open(cli_posix,
12976 : fooname,
12977 : O_RDWR|O_CREAT|O_EXCL,
12978 : 0660,
12979 : &fnum);
12980 0 : if (!NT_STATUS_IS_OK(status)) {
12981 0 : printf("cli_posix_open (create) of %s returned %s\n",
12982 : fooname,
12983 : nt_errstr(status));
12984 0 : goto out;
12985 : }
12986 0 : status = cli_close(cli_posix, fnum);
12987 0 : if (!NT_STATUS_IS_OK(status)) {
12988 0 : goto out;
12989 : }
12990 0 : status = cli_posix_open(cli_posix,
12991 : foostar_name,
12992 : O_RDWR|O_CREAT|O_EXCL,
12993 : 0660,
12994 : &fnum);
12995 0 : if (!NT_STATUS_IS_OK(status)) {
12996 0 : printf("cli_posix_open (create) of %s returned %s\n",
12997 : foostar_name,
12998 : nt_errstr(status));
12999 0 : goto out;
13000 : }
13001 0 : status = cli_close(cli_posix, fnum);
13002 0 : if (!NT_STATUS_IS_OK(status)) {
13003 0 : goto out;
13004 : }
13005 :
13006 : /*
13007 : * Get the mangled name. We can re-use the
13008 : * previous smb1_wild_mangle_list_fn for this.
13009 : */
13010 :
13011 0 : status = cli_list(cli,
13012 : wild_name,
13013 : 0,
13014 : smb1_wild_mangle_list_fn,
13015 : &mangled_name);
13016 0 : if (!NT_STATUS_IS_OK(status)) {
13017 0 : printf("cli_list of %s returned %s\n",
13018 : wild_name,
13019 : nt_errstr(status));
13020 0 : goto out;
13021 : }
13022 :
13023 0 : if (mangled_name == NULL) {
13024 0 : goto out;
13025 : }
13026 :
13027 0 : printf("mangled_name = %s\n",
13028 : mangled_name);
13029 :
13030 : /*
13031 : * Try a Windows rename with the mangled name.
13032 : * This should *NOT* rename the 'foo' name.
13033 : */
13034 :
13035 0 : windows_rename_src = talloc_asprintf(cli_posix,
13036 : "%s\\%s",
13037 : dname,
13038 : mangled_name);
13039 :
13040 0 : status = cli_rename(cli,
13041 : windows_rename_src,
13042 : windows_rename_dst,
13043 : false);
13044 0 : if (!NT_STATUS_IS_OK(status)) {
13045 0 : printf("cli_rename of %s -> %s returned %s\n",
13046 : windows_rename_src,
13047 : windows_rename_dst,
13048 : nt_errstr(status));
13049 0 : goto out;
13050 : }
13051 :
13052 : /* Does 'foo' still exist ? */
13053 0 : status = cli_posix_open(cli_posix,
13054 : fooname,
13055 : O_RDONLY,
13056 : 0,
13057 : &fnum);
13058 0 : if (!NT_STATUS_IS_OK(status)) {
13059 0 : printf("cli_posix_open O_RNONLY of %s returned %s\n",
13060 : fooname,
13061 : nt_errstr(status));
13062 0 : goto out;
13063 : }
13064 :
13065 0 : status = cli_close(cli_posix, fnum);
13066 0 : if (!NT_STATUS_IS_OK(status)) {
13067 0 : goto out;
13068 : }
13069 :
13070 0 : correct = true;
13071 :
13072 0 : out:
13073 :
13074 0 : TALLOC_FREE(mangled_name);
13075 0 : TALLOC_FREE(windows_rename_src);
13076 :
13077 0 : if (cli != NULL) {
13078 0 : torture_deltree(cli, dname);
13079 0 : torture_close_connection(cli);
13080 : }
13081 :
13082 0 : torture_close_connection(cli_posix);
13083 :
13084 0 : return correct;
13085 : }
13086 :
13087 : /*
13088 : * Only testing minimal time strings, as the others
13089 : * need (locale-dependent) guessing at what strftime does and
13090 : * even may differ in builds.
13091 : */
13092 0 : static bool timesubst_test(void)
13093 : {
13094 0 : TALLOC_CTX *ctx = NULL;
13095 : /* Sa 23. Dez 04:33:20 CET 2017 */
13096 0 : const struct timeval tv = { 1514000000, 123 };
13097 0 : const char* expect_minimal = "20171223_033320";
13098 0 : const char* expect_minus = "20171223_033320_000123";
13099 : char *s;
13100 0 : char *env_tz, *orig_tz = NULL;
13101 0 : bool result = true;
13102 :
13103 0 : ctx = talloc_new(NULL);
13104 :
13105 0 : env_tz = getenv("TZ");
13106 0 : if(env_tz) {
13107 0 : orig_tz = talloc_strdup(ctx, env_tz);
13108 : }
13109 0 : setenv("TZ", "UTC", 1);
13110 :
13111 0 : s = minimal_timeval_string(ctx, &tv, false);
13112 :
13113 0 : if(!s || strcmp(s, expect_minimal)) {
13114 0 : printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13115 : "[%s]\n", s ? s : "<nil>", expect_minimal);
13116 0 : result = false;
13117 : }
13118 0 : TALLOC_FREE(s);
13119 0 : s = minimal_timeval_string(ctx, &tv, true);
13120 0 : if(!s || strcmp(s, expect_minus)) {
13121 0 : printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13122 : "[%s]\n", s ? s : "<nil>", expect_minus);
13123 0 : result = false;
13124 : }
13125 0 : TALLOC_FREE(s);
13126 :
13127 0 : if(orig_tz) {
13128 0 : setenv("TZ", orig_tz, 1);
13129 : }
13130 :
13131 0 : TALLOC_FREE(ctx);
13132 0 : return result;
13133 : }
13134 :
13135 0 : static bool run_local_substitute(int dummy)
13136 : {
13137 0 : bool ok = true;
13138 :
13139 0 : ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13140 0 : ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13141 0 : ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13142 0 : ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13143 0 : ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13144 0 : ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13145 0 : ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13146 0 : ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13147 0 : ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13148 : /* Substitution depends on current time, so better test the underlying
13149 : formatting function. At least covers %t. */
13150 0 : ok &= timesubst_test();
13151 :
13152 : /* Different captialization rules in sub_basic... */
13153 :
13154 0 : ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13155 0 : "blaDOM") == 0);
13156 :
13157 0 : return ok;
13158 : }
13159 :
13160 0 : static bool run_local_base64(int dummy)
13161 : {
13162 : int i;
13163 0 : bool ret = true;
13164 :
13165 0 : for (i=1; i<2000; i++) {
13166 : DATA_BLOB blob1, blob2;
13167 : char *b64;
13168 :
13169 0 : blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13170 0 : blob1.length = i;
13171 0 : generate_random_buffer(blob1.data, blob1.length);
13172 :
13173 0 : b64 = base64_encode_data_blob(talloc_tos(), blob1);
13174 0 : if (b64 == NULL) {
13175 0 : d_fprintf(stderr, "base64_encode_data_blob failed "
13176 : "for %d bytes\n", i);
13177 0 : ret = false;
13178 : }
13179 0 : blob2 = base64_decode_data_blob(b64);
13180 0 : TALLOC_FREE(b64);
13181 :
13182 0 : if (data_blob_cmp(&blob1, &blob2)) {
13183 0 : d_fprintf(stderr, "data_blob_cmp failed for %d "
13184 : "bytes\n", i);
13185 0 : ret = false;
13186 : }
13187 0 : TALLOC_FREE(blob1.data);
13188 0 : data_blob_free(&blob2);
13189 : }
13190 0 : return ret;
13191 : }
13192 :
13193 0 : static void parse_fn(const struct gencache_timeout *t,
13194 : DATA_BLOB blob,
13195 : void *private_data)
13196 : {
13197 0 : return;
13198 : }
13199 :
13200 0 : static bool run_local_gencache(int dummy)
13201 : {
13202 : char *val;
13203 : time_t tm;
13204 : DATA_BLOB blob;
13205 : char v;
13206 : struct memcache *mem;
13207 : int i;
13208 :
13209 0 : mem = memcache_init(NULL, 0);
13210 0 : if (mem == NULL) {
13211 0 : d_printf("%s: memcache_init failed\n", __location__);
13212 0 : return false;
13213 : }
13214 0 : memcache_set_global(mem);
13215 :
13216 0 : if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13217 0 : d_printf("%s: gencache_set() failed\n", __location__);
13218 0 : return False;
13219 : }
13220 :
13221 0 : if (!gencache_get("foo", NULL, NULL, NULL)) {
13222 0 : d_printf("%s: gencache_get() failed\n", __location__);
13223 0 : return False;
13224 : }
13225 :
13226 0 : for (i=0; i<1000000; i++) {
13227 0 : gencache_parse("foo", parse_fn, NULL);
13228 : }
13229 :
13230 0 : if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13231 0 : d_printf("%s: gencache_get() failed\n", __location__);
13232 0 : return False;
13233 : }
13234 0 : TALLOC_FREE(val);
13235 :
13236 0 : if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13237 0 : d_printf("%s: gencache_get() failed\n", __location__);
13238 0 : return False;
13239 : }
13240 :
13241 0 : if (strcmp(val, "bar") != 0) {
13242 0 : d_printf("%s: gencache_get() returned %s, expected %s\n",
13243 : __location__, val, "bar");
13244 0 : TALLOC_FREE(val);
13245 0 : return False;
13246 : }
13247 :
13248 0 : TALLOC_FREE(val);
13249 :
13250 0 : if (!gencache_del("foo")) {
13251 0 : d_printf("%s: gencache_del() failed\n", __location__);
13252 0 : return False;
13253 : }
13254 0 : if (gencache_del("foo")) {
13255 0 : d_printf("%s: second gencache_del() succeeded\n",
13256 : __location__);
13257 0 : return False;
13258 : }
13259 :
13260 0 : if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13261 0 : d_printf("%s: gencache_get() on deleted entry "
13262 : "succeeded\n", __location__);
13263 0 : return False;
13264 : }
13265 :
13266 0 : blob = data_blob_string_const_null("bar");
13267 0 : tm = time(NULL) + 60;
13268 :
13269 0 : if (!gencache_set_data_blob("foo", blob, tm)) {
13270 0 : d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13271 0 : return False;
13272 : }
13273 :
13274 0 : if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13275 0 : d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13276 0 : return False;
13277 : }
13278 :
13279 0 : if (strcmp((const char *)blob.data, "bar") != 0) {
13280 0 : d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13281 0 : __location__, (const char *)blob.data, "bar");
13282 0 : data_blob_free(&blob);
13283 0 : return False;
13284 : }
13285 :
13286 0 : data_blob_free(&blob);
13287 :
13288 0 : if (!gencache_del("foo")) {
13289 0 : d_printf("%s: gencache_del() failed\n", __location__);
13290 0 : return False;
13291 : }
13292 0 : if (gencache_del("foo")) {
13293 0 : d_printf("%s: second gencache_del() succeeded\n",
13294 : __location__);
13295 0 : return False;
13296 : }
13297 :
13298 0 : if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13299 0 : d_printf("%s: gencache_get_data_blob() on deleted entry "
13300 : "succeeded\n", __location__);
13301 0 : return False;
13302 : }
13303 :
13304 0 : v = 1;
13305 0 : blob.data = (uint8_t *)&v;
13306 0 : blob.length = sizeof(v);
13307 :
13308 0 : if (!gencache_set_data_blob("blob", blob, tm)) {
13309 0 : d_printf("%s: gencache_set_data_blob() failed\n",
13310 : __location__);
13311 0 : return false;
13312 : }
13313 0 : if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13314 0 : d_printf("%s: gencache_get succeeded\n", __location__);
13315 0 : return false;
13316 : }
13317 :
13318 0 : return True;
13319 : }
13320 :
13321 0 : static bool rbt_testflags(struct db_context *db, const char *key,
13322 : const char *value)
13323 : {
13324 0 : bool ret = false;
13325 : NTSTATUS status;
13326 : struct db_record *rec;
13327 :
13328 0 : rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13329 0 : if (rec == NULL) {
13330 0 : d_fprintf(stderr, "fetch_locked failed\n");
13331 0 : goto done;
13332 : }
13333 :
13334 0 : status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13335 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13336 0 : d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13337 : nt_errstr(status));
13338 0 : goto done;
13339 : }
13340 :
13341 0 : status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13342 : TDB_INSERT);
13343 0 : if (!NT_STATUS_IS_OK(status)) {
13344 0 : d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13345 : nt_errstr(status));
13346 0 : goto done;
13347 : }
13348 :
13349 0 : status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13350 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13351 0 : d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13352 : nt_errstr(status));
13353 0 : goto done;
13354 : }
13355 :
13356 0 : status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13357 0 : if (!NT_STATUS_IS_OK(status)) {
13358 0 : d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13359 : nt_errstr(status));
13360 0 : goto done;
13361 : }
13362 :
13363 0 : ret = true;
13364 0 : done:
13365 0 : TALLOC_FREE(rec);
13366 0 : return ret;
13367 : }
13368 :
13369 0 : static bool rbt_testval(struct db_context *db, const char *key,
13370 : const char *value)
13371 : {
13372 : struct db_record *rec;
13373 0 : TDB_DATA data = string_tdb_data(value);
13374 0 : bool ret = false;
13375 : NTSTATUS status;
13376 : TDB_DATA dbvalue;
13377 :
13378 0 : rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13379 0 : if (rec == NULL) {
13380 0 : d_fprintf(stderr, "fetch_locked failed\n");
13381 0 : goto done;
13382 : }
13383 0 : status = dbwrap_record_store(rec, data, 0);
13384 0 : if (!NT_STATUS_IS_OK(status)) {
13385 0 : d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13386 0 : goto done;
13387 : }
13388 0 : TALLOC_FREE(rec);
13389 :
13390 0 : rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13391 0 : if (rec == NULL) {
13392 0 : d_fprintf(stderr, "second fetch_locked failed\n");
13393 0 : goto done;
13394 : }
13395 :
13396 0 : dbvalue = dbwrap_record_get_value(rec);
13397 0 : if ((dbvalue.dsize != data.dsize)
13398 0 : || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13399 0 : d_fprintf(stderr, "Got wrong data back\n");
13400 0 : goto done;
13401 : }
13402 :
13403 0 : ret = true;
13404 0 : done:
13405 0 : TALLOC_FREE(rec);
13406 0 : return ret;
13407 : }
13408 :
13409 0 : static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13410 : {
13411 0 : int *count2 = (int *)private_data;
13412 0 : (*count2)++;
13413 0 : return 0;
13414 : }
13415 :
13416 0 : static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13417 : {
13418 0 : int *count2 = (int *)private_data;
13419 0 : (*count2)++;
13420 0 : dbwrap_record_delete(rec);
13421 0 : return 0;
13422 : }
13423 :
13424 0 : static bool run_local_rbtree(int dummy)
13425 : {
13426 : struct db_context *db;
13427 0 : bool ret = false;
13428 : int i;
13429 : NTSTATUS status;
13430 0 : int count = 0;
13431 0 : int count2 = 0;
13432 :
13433 0 : db = db_open_rbt(NULL);
13434 :
13435 0 : if (db == NULL) {
13436 0 : d_fprintf(stderr, "db_open_rbt failed\n");
13437 0 : return false;
13438 : }
13439 :
13440 0 : if (!rbt_testflags(db, "firstkey", "firstval")) {
13441 0 : goto done;
13442 : }
13443 :
13444 0 : for (i = 0; i < 999; i++) {
13445 : char key[sizeof("key-9223372036854775807")];
13446 : char value[sizeof("value-9223372036854775807")];
13447 :
13448 0 : snprintf(key, sizeof(key), "key%ld", random());
13449 0 : snprintf(value, sizeof(value) ,"value%ld", random());
13450 :
13451 0 : if (!rbt_testval(db, key, value)) {
13452 0 : goto done;
13453 : }
13454 :
13455 0 : snprintf(value, sizeof(value) ,"value%ld", random());
13456 :
13457 0 : if (!rbt_testval(db, key, value)) {
13458 0 : goto done;
13459 : }
13460 : }
13461 :
13462 0 : ret = true;
13463 0 : count = 0; count2 = 0;
13464 0 : status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13465 : &count2, &count);
13466 0 : printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13467 0 : if ((count != count2) || (count != 1000)) {
13468 0 : ret = false;
13469 : }
13470 0 : count = 0; count2 = 0;
13471 0 : status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13472 : &count2, &count);
13473 0 : printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13474 0 : if ((count != count2) || (count != 1000)) {
13475 0 : ret = false;
13476 : }
13477 0 : count = 0; count2 = 0;
13478 0 : status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13479 : &count2, &count);
13480 0 : printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13481 0 : if ((count != count2) || (count != 0)) {
13482 0 : ret = false;
13483 : }
13484 :
13485 0 : done:
13486 0 : TALLOC_FREE(db);
13487 0 : return ret;
13488 : }
13489 :
13490 :
13491 : /*
13492 : local test for character set functions
13493 :
13494 : This is a very simple test for the functionality in convert_string_error()
13495 : */
13496 0 : static bool run_local_convert_string(int dummy)
13497 : {
13498 0 : TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13499 0 : const char *test_strings[2] = { "March", "M\303\244rz" };
13500 : char dst[7];
13501 : int i;
13502 :
13503 0 : for (i=0; i<2; i++) {
13504 0 : const char *str = test_strings[i];
13505 0 : int len = strlen(str);
13506 : size_t converted_size;
13507 : bool ret;
13508 :
13509 0 : memset(dst, 'X', sizeof(dst));
13510 :
13511 : /* first try with real source length */
13512 0 : ret = convert_string_error(CH_UNIX, CH_UTF8,
13513 : str, len,
13514 : dst, sizeof(dst),
13515 : &converted_size);
13516 0 : if (ret != true) {
13517 0 : d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13518 0 : goto failed;
13519 : }
13520 :
13521 0 : if (converted_size != len) {
13522 0 : d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13523 : str, len, (int)converted_size);
13524 0 : goto failed;
13525 : }
13526 :
13527 0 : if (strncmp(str, dst, converted_size) != 0) {
13528 0 : d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13529 0 : goto failed;
13530 : }
13531 :
13532 0 : if (strlen(str) != converted_size) {
13533 0 : d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13534 0 : (int)strlen(str), (int)converted_size);
13535 0 : goto failed;
13536 : }
13537 :
13538 0 : if (dst[converted_size] != 'X') {
13539 0 : d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13540 0 : goto failed;
13541 : }
13542 :
13543 : /* now with srclen==-1, this causes the nul to be
13544 : * converted too */
13545 0 : ret = convert_string_error(CH_UNIX, CH_UTF8,
13546 : str, -1,
13547 : dst, sizeof(dst),
13548 : &converted_size);
13549 0 : if (ret != true) {
13550 0 : d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13551 0 : goto failed;
13552 : }
13553 :
13554 0 : if (converted_size != len+1) {
13555 0 : d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13556 : str, len, (int)converted_size);
13557 0 : goto failed;
13558 : }
13559 :
13560 0 : if (strncmp(str, dst, converted_size) != 0) {
13561 0 : d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13562 0 : goto failed;
13563 : }
13564 :
13565 0 : if (len+1 != converted_size) {
13566 0 : d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13567 : len+1, (int)converted_size);
13568 0 : goto failed;
13569 : }
13570 :
13571 0 : if (dst[converted_size] != 'X') {
13572 0 : d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13573 0 : goto failed;
13574 : }
13575 :
13576 : }
13577 :
13578 :
13579 0 : TALLOC_FREE(tmp_ctx);
13580 0 : return true;
13581 0 : failed:
13582 0 : TALLOC_FREE(tmp_ctx);
13583 0 : return false;
13584 : }
13585 :
13586 0 : static bool run_local_string_to_sid(int dummy) {
13587 : struct dom_sid sid;
13588 :
13589 0 : if (string_to_sid(&sid, "S--1-5-32-545")) {
13590 0 : printf("allowing S--1-5-32-545\n");
13591 0 : return false;
13592 : }
13593 0 : if (string_to_sid(&sid, "S-1-5-32-+545")) {
13594 0 : printf("allowing S-1-5-32-+545\n");
13595 0 : return false;
13596 : }
13597 0 : if (string_to_sid(&sid, "S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0")) {
13598 0 : printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13599 0 : return false;
13600 : }
13601 0 : if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13602 0 : printf("allowing S-1-5-32-545-abc\n");
13603 0 : return false;
13604 : }
13605 0 : if (string_to_sid(&sid, "S-300-5-32-545")) {
13606 0 : printf("allowing S-300-5-32-545\n");
13607 0 : return false;
13608 : }
13609 0 : if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13610 0 : printf("allowing S-1-0xfffffffffffffe-32-545\n");
13611 0 : return false;
13612 : }
13613 0 : if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13614 0 : printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13615 0 : return false;
13616 : }
13617 0 : if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13618 0 : printf("could not parse S-1-0xfffffffffffe-32-545\n");
13619 0 : return false;
13620 : }
13621 0 : if (!string_to_sid(&sid, "S-1-5-32-545")) {
13622 0 : printf("could not parse S-1-5-32-545\n");
13623 0 : return false;
13624 : }
13625 0 : if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13626 : struct dom_sid_buf buf;
13627 0 : printf("mis-parsed S-1-5-32-545 as %s\n",
13628 : dom_sid_str_buf(&sid, &buf));
13629 0 : return false;
13630 : }
13631 0 : return true;
13632 : }
13633 :
13634 0 : static bool sid_to_string_test(const char *expected) {
13635 : char *str;
13636 0 : bool res = true;
13637 : struct dom_sid sid;
13638 :
13639 0 : if (!string_to_sid(&sid, expected)) {
13640 0 : printf("could not parse %s\n", expected);
13641 0 : return false;
13642 : }
13643 :
13644 0 : str = dom_sid_string(NULL, &sid);
13645 0 : if (strcmp(str, expected)) {
13646 0 : printf("Comparison failed (%s != %s)\n", str, expected);
13647 0 : res = false;
13648 : }
13649 0 : TALLOC_FREE(str);
13650 0 : return res;
13651 : }
13652 :
13653 0 : static bool run_local_sid_to_string(int dummy) {
13654 0 : if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13655 0 : return false;
13656 0 : if (!sid_to_string_test("S-1-545"))
13657 0 : return false;
13658 0 : if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13659 0 : return false;
13660 0 : return true;
13661 : }
13662 :
13663 0 : static bool run_local_binary_to_sid(int dummy) {
13664 : ssize_t ret;
13665 0 : struct dom_sid *sid = talloc(NULL, struct dom_sid);
13666 : static const uint8_t good_binary_sid[] = {
13667 : 0x1, /* revision number */
13668 : 15, /* num auths */
13669 : 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13670 : 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13671 : 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13672 : 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13673 : 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13674 : 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13675 : 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13676 : 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13677 : 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13678 : 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13679 : 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13680 : 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13681 : 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13682 : 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13683 : 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13684 : 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13685 : };
13686 :
13687 : static const uint8_t long_binary_sid[] = {
13688 : 0x1, /* revision number */
13689 : 15, /* num auths */
13690 : 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13691 : 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13692 : 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13693 : 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13694 : 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13695 : 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13696 : 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13697 : 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13698 : 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13699 : 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13700 : 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13701 : 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13702 : 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13703 : 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13704 : 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13705 : 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13706 : 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13707 : 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13708 : 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13709 : };
13710 :
13711 : static const uint8_t long_binary_sid2[] = {
13712 : 0x1, /* revision number */
13713 : 32, /* num auths */
13714 : 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13715 : 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13716 : 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13717 : 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13718 : 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13719 : 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13720 : 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13721 : 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13722 : 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13723 : 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13724 : 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13725 : 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13726 : 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13727 : 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13728 : 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13729 : 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13730 : 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13731 : 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13732 : 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13733 : 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13734 : 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13735 : 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13736 : 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13737 : 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13738 : 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13739 : 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13740 : 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13741 : 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13742 : 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13743 : 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13744 : 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13745 : 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13746 : 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13747 : };
13748 :
13749 0 : ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13750 0 : if (ret == -1) {
13751 0 : return false;
13752 : }
13753 0 : ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13754 0 : if (ret != -1) {
13755 0 : return false;
13756 : }
13757 0 : ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13758 0 : if (ret != -1) {
13759 0 : return false;
13760 : }
13761 0 : return true;
13762 : }
13763 :
13764 : /* Split a path name into filename and stream name components. Canonicalise
13765 : * such that an implicit $DATA token is always explicit.
13766 : *
13767 : * The "specification" of this function can be found in the
13768 : * run_local_stream_name() function in torture.c, I've tried those
13769 : * combinations against a W2k3 server.
13770 : */
13771 :
13772 0 : static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13773 : char **pbase, char **pstream)
13774 : {
13775 0 : char *base = NULL;
13776 0 : char *stream = NULL;
13777 : char *sname; /* stream name */
13778 : const char *stype; /* stream type */
13779 :
13780 0 : DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13781 :
13782 0 : sname = strchr_m(fname, ':');
13783 :
13784 0 : if (sname == NULL) {
13785 0 : if (pbase != NULL) {
13786 0 : base = talloc_strdup(mem_ctx, fname);
13787 0 : NT_STATUS_HAVE_NO_MEMORY(base);
13788 : }
13789 0 : goto done;
13790 : }
13791 :
13792 0 : if (pbase != NULL) {
13793 0 : base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13794 0 : NT_STATUS_HAVE_NO_MEMORY(base);
13795 : }
13796 :
13797 0 : sname += 1;
13798 :
13799 0 : stype = strchr_m(sname, ':');
13800 :
13801 0 : if (stype == NULL) {
13802 0 : sname = talloc_strdup(mem_ctx, sname);
13803 0 : stype = "$DATA";
13804 : }
13805 : else {
13806 0 : if (strcasecmp_m(stype, ":$DATA") != 0) {
13807 : /*
13808 : * If there is an explicit stream type, so far we only
13809 : * allow $DATA. Is there anything else allowed? -- vl
13810 : */
13811 0 : DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13812 0 : TALLOC_FREE(base);
13813 0 : return NT_STATUS_OBJECT_NAME_INVALID;
13814 : }
13815 0 : sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13816 0 : stype += 1;
13817 : }
13818 :
13819 0 : if (sname == NULL) {
13820 0 : TALLOC_FREE(base);
13821 0 : return NT_STATUS_NO_MEMORY;
13822 : }
13823 :
13824 0 : if (sname[0] == '\0') {
13825 : /*
13826 : * no stream name, so no stream
13827 : */
13828 0 : goto done;
13829 : }
13830 :
13831 0 : if (pstream != NULL) {
13832 0 : stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13833 0 : if (stream == NULL) {
13834 0 : TALLOC_FREE(sname);
13835 0 : TALLOC_FREE(base);
13836 0 : return NT_STATUS_NO_MEMORY;
13837 : }
13838 : /*
13839 : * upper-case the type field
13840 : */
13841 0 : (void)strupper_m(strchr_m(stream, ':')+1);
13842 : }
13843 :
13844 0 : done:
13845 0 : if (pbase != NULL) {
13846 0 : *pbase = base;
13847 : }
13848 0 : if (pstream != NULL) {
13849 0 : *pstream = stream;
13850 : }
13851 0 : return NT_STATUS_OK;
13852 : }
13853 :
13854 0 : static bool test_stream_name(const char *fname, const char *expected_base,
13855 : const char *expected_stream,
13856 : NTSTATUS expected_status)
13857 : {
13858 : NTSTATUS status;
13859 0 : char *base = NULL;
13860 0 : char *stream = NULL;
13861 :
13862 0 : status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13863 0 : if (!NT_STATUS_EQUAL(status, expected_status)) {
13864 0 : goto error;
13865 : }
13866 :
13867 0 : if (!NT_STATUS_IS_OK(status)) {
13868 0 : return true;
13869 : }
13870 :
13871 0 : if (base == NULL) goto error;
13872 :
13873 0 : if (strcmp(expected_base, base) != 0) goto error;
13874 :
13875 0 : if ((expected_stream != NULL) && (stream == NULL)) goto error;
13876 0 : if ((expected_stream == NULL) && (stream != NULL)) goto error;
13877 :
13878 0 : if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
13879 0 : goto error;
13880 :
13881 0 : TALLOC_FREE(base);
13882 0 : TALLOC_FREE(stream);
13883 0 : return true;
13884 :
13885 0 : error:
13886 0 : d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
13887 : fname, expected_base ? expected_base : "<NULL>",
13888 : expected_stream ? expected_stream : "<NULL>",
13889 : nt_errstr(expected_status));
13890 0 : d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
13891 0 : base ? base : "<NULL>", stream ? stream : "<NULL>",
13892 : nt_errstr(status));
13893 0 : TALLOC_FREE(base);
13894 0 : TALLOC_FREE(stream);
13895 0 : return false;
13896 : }
13897 :
13898 0 : static bool run_local_stream_name(int dummy)
13899 : {
13900 0 : bool ret = true;
13901 :
13902 0 : ret &= test_stream_name(
13903 0 : "bla", "bla", NULL, NT_STATUS_OK);
13904 0 : ret &= test_stream_name(
13905 0 : "bla::$DATA", "bla", NULL, NT_STATUS_OK);
13906 0 : ret &= test_stream_name(
13907 0 : "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13908 0 : ret &= test_stream_name(
13909 0 : "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
13910 0 : ret &= test_stream_name(
13911 0 : "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13912 0 : ret &= test_stream_name(
13913 0 : "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
13914 0 : ret &= test_stream_name(
13915 0 : "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
13916 0 : ret &= test_stream_name(
13917 0 : "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
13918 :
13919 0 : return ret;
13920 : }
13921 :
13922 0 : static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
13923 : {
13924 0 : if (a.length != b.length) {
13925 0 : printf("a.length=%d != b.length=%d\n",
13926 0 : (int)a.length, (int)b.length);
13927 0 : return false;
13928 : }
13929 0 : if (memcmp(a.data, b.data, a.length) != 0) {
13930 0 : printf("a.data and b.data differ\n");
13931 0 : return false;
13932 : }
13933 0 : return true;
13934 : }
13935 :
13936 0 : static bool run_local_memcache(int dummy)
13937 : {
13938 : struct memcache *cache;
13939 : DATA_BLOB k1, k2, k3, k4, k5;
13940 : DATA_BLOB d1, d3;
13941 : DATA_BLOB v1, v3;
13942 :
13943 : TALLOC_CTX *mem_ctx;
13944 0 : char *ptr1 = NULL;
13945 0 : char *ptr2 = NULL;
13946 0 : char *ptr3 = NULL;
13947 :
13948 : char *str1, *str2;
13949 : size_t size1, size2;
13950 0 : bool ret = false;
13951 :
13952 0 : mem_ctx = talloc_init("foo");
13953 0 : if (mem_ctx == NULL) {
13954 0 : return false;
13955 : }
13956 :
13957 : /* STAT_CACHE TESTS */
13958 :
13959 0 : cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13960 :
13961 0 : if (cache == NULL) {
13962 0 : printf("memcache_init failed\n");
13963 0 : return false;
13964 : }
13965 :
13966 0 : d1 = data_blob_const("d1", 2);
13967 0 : d3 = data_blob_const("d3", 2);
13968 :
13969 0 : k1 = data_blob_const("d1", 2);
13970 0 : k2 = data_blob_const("d2", 2);
13971 0 : k3 = data_blob_const("d3", 2);
13972 0 : k4 = data_blob_const("d4", 2);
13973 0 : k5 = data_blob_const("d5", 2);
13974 :
13975 0 : memcache_add(cache, STAT_CACHE, k1, d1);
13976 :
13977 0 : if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
13978 0 : printf("could not find k1\n");
13979 0 : return false;
13980 : }
13981 0 : if (!data_blob_equal(d1, v1)) {
13982 0 : return false;
13983 : }
13984 :
13985 0 : memcache_add(cache, STAT_CACHE, k1, d3);
13986 :
13987 0 : if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
13988 0 : printf("could not find replaced k1\n");
13989 0 : return false;
13990 : }
13991 0 : if (!data_blob_equal(d3, v3)) {
13992 0 : return false;
13993 : }
13994 :
13995 0 : TALLOC_FREE(cache);
13996 :
13997 : /* GETWD_CACHE TESTS */
13998 0 : str1 = talloc_strdup(mem_ctx, "string1");
13999 0 : if (str1 == NULL) {
14000 0 : return false;
14001 : }
14002 0 : ptr2 = str1; /* Keep an alias for comparison. */
14003 :
14004 0 : str2 = talloc_strdup(mem_ctx, "string2");
14005 0 : if (str2 == NULL) {
14006 0 : return false;
14007 : }
14008 :
14009 0 : cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14010 0 : if (cache == NULL) {
14011 0 : printf("memcache_init failed\n");
14012 0 : return false;
14013 : }
14014 :
14015 0 : memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14016 : /* str1 == NULL now. */
14017 0 : ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14018 0 : if (ptr1 == NULL) {
14019 0 : printf("could not find k2\n");
14020 0 : return false;
14021 : }
14022 0 : if (ptr1 != ptr2) {
14023 0 : printf("fetch of k2 got wrong string\n");
14024 0 : return false;
14025 : }
14026 :
14027 : /* Add a blob to ensure k2 gets purged. */
14028 0 : d3 = data_blob_talloc_zero(mem_ctx, 180);
14029 0 : memcache_add(cache, STAT_CACHE, k3, d3);
14030 :
14031 0 : ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14032 0 : if (ptr2 != NULL) {
14033 0 : printf("Did find k2, should have been purged\n");
14034 0 : return false;
14035 : }
14036 :
14037 : /*
14038 : * Test that talloc size also is accounted in memcache and
14039 : * causes purge of other object.
14040 : */
14041 :
14042 0 : str1 = talloc_zero_size(mem_ctx, 100);
14043 0 : str2 = talloc_zero_size(mem_ctx, 100);
14044 :
14045 0 : memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14046 0 : memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14047 :
14048 0 : ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14049 0 : if (ptr3 != NULL) {
14050 0 : printf("Did find k4, should have been purged\n");
14051 0 : return false;
14052 : }
14053 :
14054 : /*
14055 : * Test that adding a duplicate non-talloced
14056 : * key/value on top of a talloced key/value takes account
14057 : * of the talloc_freed value size.
14058 : */
14059 0 : TALLOC_FREE(cache);
14060 0 : TALLOC_FREE(mem_ctx);
14061 :
14062 0 : mem_ctx = talloc_init("key_replace");
14063 0 : if (mem_ctx == NULL) {
14064 0 : return false;
14065 : }
14066 :
14067 0 : cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14068 0 : if (cache == NULL) {
14069 0 : return false;
14070 : }
14071 :
14072 : /*
14073 : * Add a 100 byte talloced string. This will
14074 : * store a (4 or 8 byte) pointer and record the
14075 : * total talloced size.
14076 : */
14077 0 : str1 = talloc_zero_size(mem_ctx, 100);
14078 0 : memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14079 : /*
14080 : * Now overwrite with a small talloced
14081 : * value. This should fit in the existing size
14082 : * and the total talloced size should be removed
14083 : * from the cache size.
14084 : */
14085 0 : str1 = talloc_zero_size(mem_ctx, 2);
14086 0 : memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14087 : /*
14088 : * Now store a 20 byte string. If the
14089 : * total talloced size wasn't accounted for
14090 : * and removed in the overwrite, then this
14091 : * will evict k4.
14092 : */
14093 0 : str2 = talloc_zero_size(mem_ctx, 20);
14094 0 : memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14095 :
14096 0 : ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14097 0 : if (ptr3 == NULL) {
14098 0 : printf("Did not find k4, should not have been purged\n");
14099 0 : return false;
14100 : }
14101 :
14102 0 : TALLOC_FREE(cache);
14103 0 : TALLOC_FREE(mem_ctx);
14104 :
14105 0 : mem_ctx = talloc_init("foo");
14106 0 : if (mem_ctx == NULL) {
14107 0 : return false;
14108 : }
14109 :
14110 0 : cache = memcache_init(NULL, 0);
14111 0 : if (cache == NULL) {
14112 0 : return false;
14113 : }
14114 :
14115 0 : str1 = talloc_strdup(mem_ctx, "string1");
14116 0 : if (str1 == NULL) {
14117 0 : return false;
14118 : }
14119 0 : str2 = talloc_strdup(mem_ctx, "string2");
14120 0 : if (str2 == NULL) {
14121 0 : return false;
14122 : }
14123 0 : memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14124 : data_blob_string_const("torture"), &str1);
14125 0 : size1 = talloc_total_size(cache);
14126 :
14127 0 : memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14128 : data_blob_string_const("torture"), &str2);
14129 0 : size2 = talloc_total_size(cache);
14130 :
14131 0 : printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14132 :
14133 0 : if (size2 > size1) {
14134 0 : printf("memcache leaks memory!\n");
14135 0 : goto fail;
14136 : }
14137 :
14138 0 : ret = true;
14139 0 : fail:
14140 0 : TALLOC_FREE(cache);
14141 0 : return ret;
14142 : }
14143 :
14144 200 : static void wbclient_done(struct tevent_req *req)
14145 : {
14146 : wbcErr wbc_err;
14147 : struct winbindd_response *wb_resp;
14148 200 : int *i = (int *)tevent_req_callback_data_void(req);
14149 :
14150 200 : wbc_err = wb_trans_recv(req, req, &wb_resp);
14151 200 : TALLOC_FREE(req);
14152 200 : *i += 1;
14153 200 : d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14154 200 : }
14155 :
14156 2 : static bool run_wbclient_multi_ping(int dummy)
14157 : {
14158 : struct tevent_context *ev;
14159 : struct wb_context **wb_ctx;
14160 : struct winbindd_request wb_req;
14161 2 : bool result = false;
14162 : int i, j;
14163 :
14164 2 : BlockSignals(True, SIGPIPE);
14165 :
14166 2 : ev = tevent_context_init(talloc_tos());
14167 2 : if (ev == NULL) {
14168 0 : goto fail;
14169 : }
14170 :
14171 2 : wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14172 2 : if (wb_ctx == NULL) {
14173 0 : goto fail;
14174 : }
14175 :
14176 2 : ZERO_STRUCT(wb_req);
14177 2 : wb_req.cmd = WINBINDD_PING;
14178 :
14179 2 : d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14180 :
14181 4 : for (i=0; i<torture_nprocs; i++) {
14182 2 : wb_ctx[i] = wb_context_init(ev, NULL);
14183 2 : if (wb_ctx[i] == NULL) {
14184 0 : goto fail;
14185 : }
14186 202 : for (j=0; j<torture_numops; j++) {
14187 : struct tevent_req *req;
14188 200 : req = wb_trans_send(ev, ev, wb_ctx[i],
14189 200 : (j % 2) == 0, &wb_req);
14190 200 : if (req == NULL) {
14191 0 : goto fail;
14192 : }
14193 200 : tevent_req_set_callback(req, wbclient_done, &i);
14194 : }
14195 : }
14196 :
14197 2 : i = 0;
14198 :
14199 818 : while (i < torture_nprocs * torture_numops) {
14200 816 : tevent_loop_once(ev);
14201 : }
14202 :
14203 2 : result = true;
14204 2 : fail:
14205 2 : TALLOC_FREE(ev);
14206 2 : return result;
14207 : }
14208 :
14209 0 : static bool dbtrans_inc(struct db_context *db)
14210 : {
14211 : struct db_record *rec;
14212 : uint32_t val;
14213 0 : bool ret = false;
14214 : NTSTATUS status;
14215 : TDB_DATA value;
14216 :
14217 0 : rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14218 0 : if (rec == NULL) {
14219 0 : printf(__location__ "fetch_lock failed\n");
14220 0 : return false;
14221 : }
14222 :
14223 0 : value = dbwrap_record_get_value(rec);
14224 :
14225 0 : if (value.dsize != sizeof(uint32_t)) {
14226 0 : printf(__location__ "value.dsize = %d\n",
14227 0 : (int)value.dsize);
14228 0 : goto fail;
14229 : }
14230 :
14231 0 : memcpy(&val, value.dptr, sizeof(val));
14232 0 : val += 1;
14233 :
14234 0 : status = dbwrap_record_store(
14235 : rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14236 0 : if (!NT_STATUS_IS_OK(status)) {
14237 0 : printf(__location__ "store failed: %s\n",
14238 : nt_errstr(status));
14239 0 : goto fail;
14240 : }
14241 :
14242 0 : ret = true;
14243 0 : fail:
14244 0 : TALLOC_FREE(rec);
14245 0 : return ret;
14246 : }
14247 :
14248 0 : static bool run_local_dbtrans(int dummy)
14249 : {
14250 : struct db_context *db;
14251 : struct db_record *rec;
14252 : NTSTATUS status;
14253 : uint32_t initial;
14254 : int res;
14255 : TDB_DATA value;
14256 :
14257 0 : db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14258 : O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14259 : DBWRAP_FLAG_NONE);
14260 0 : if (db == NULL) {
14261 0 : printf("Could not open transtest.db\n");
14262 0 : return false;
14263 : }
14264 :
14265 0 : res = dbwrap_transaction_start(db);
14266 0 : if (res != 0) {
14267 0 : printf(__location__ "transaction_start failed\n");
14268 0 : return false;
14269 : }
14270 :
14271 0 : rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14272 0 : if (rec == NULL) {
14273 0 : printf(__location__ "fetch_lock failed\n");
14274 0 : return false;
14275 : }
14276 :
14277 0 : value = dbwrap_record_get_value(rec);
14278 :
14279 0 : if (value.dptr == NULL) {
14280 0 : initial = 0;
14281 0 : status = dbwrap_record_store(
14282 : rec, make_tdb_data((uint8_t *)&initial,
14283 : sizeof(initial)),
14284 : 0);
14285 0 : if (!NT_STATUS_IS_OK(status)) {
14286 0 : printf(__location__ "store returned %s\n",
14287 : nt_errstr(status));
14288 0 : return false;
14289 : }
14290 : }
14291 :
14292 0 : TALLOC_FREE(rec);
14293 :
14294 0 : res = dbwrap_transaction_commit(db);
14295 0 : if (res != 0) {
14296 0 : printf(__location__ "transaction_commit failed\n");
14297 0 : return false;
14298 : }
14299 :
14300 0 : while (true) {
14301 : uint32_t val, val2;
14302 : int i;
14303 :
14304 0 : res = dbwrap_transaction_start(db);
14305 0 : if (res != 0) {
14306 0 : printf(__location__ "transaction_start failed\n");
14307 0 : break;
14308 : }
14309 :
14310 0 : status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14311 0 : if (!NT_STATUS_IS_OK(status)) {
14312 0 : printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14313 : nt_errstr(status));
14314 0 : break;
14315 : }
14316 :
14317 0 : for (i=0; i<10; i++) {
14318 0 : if (!dbtrans_inc(db)) {
14319 0 : return false;
14320 : }
14321 : }
14322 :
14323 0 : status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14324 0 : if (!NT_STATUS_IS_OK(status)) {
14325 0 : printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14326 : nt_errstr(status));
14327 0 : break;
14328 : }
14329 :
14330 0 : if (val2 != val + 10) {
14331 0 : printf(__location__ "val=%d, val2=%d\n",
14332 : (int)val, (int)val2);
14333 0 : break;
14334 : }
14335 :
14336 0 : printf("val2=%d\r", val2);
14337 :
14338 0 : res = dbwrap_transaction_commit(db);
14339 0 : if (res != 0) {
14340 0 : printf(__location__ "transaction_commit failed\n");
14341 0 : break;
14342 : }
14343 : }
14344 :
14345 0 : TALLOC_FREE(db);
14346 0 : return true;
14347 : }
14348 :
14349 : /*
14350 : * Just a dummy test to be run under a debugger. There's no real way
14351 : * to inspect the tevent_poll specific function from outside of
14352 : * tevent_poll.c.
14353 : */
14354 :
14355 0 : static bool run_local_tevent_poll(int dummy)
14356 : {
14357 : struct tevent_context *ev;
14358 : struct tevent_fd *fd1, *fd2;
14359 0 : bool result = false;
14360 :
14361 0 : ev = tevent_context_init_byname(NULL, "poll");
14362 0 : if (ev == NULL) {
14363 0 : d_fprintf(stderr, "tevent_context_init_byname failed\n");
14364 0 : goto fail;
14365 : }
14366 :
14367 0 : fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14368 0 : if (fd1 == NULL) {
14369 0 : d_fprintf(stderr, "tevent_add_fd failed\n");
14370 0 : goto fail;
14371 : }
14372 0 : fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14373 0 : if (fd2 == NULL) {
14374 0 : d_fprintf(stderr, "tevent_add_fd failed\n");
14375 0 : goto fail;
14376 : }
14377 0 : TALLOC_FREE(fd2);
14378 :
14379 0 : fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14380 0 : if (fd2 == NULL) {
14381 0 : d_fprintf(stderr, "tevent_add_fd failed\n");
14382 0 : goto fail;
14383 : }
14384 :
14385 0 : result = true;
14386 0 : fail:
14387 0 : TALLOC_FREE(ev);
14388 0 : return result;
14389 : }
14390 :
14391 0 : static bool run_local_hex_encode_buf(int dummy)
14392 : {
14393 : char buf[17];
14394 : uint8_t src[8];
14395 : size_t i;
14396 :
14397 0 : for (i=0; i<sizeof(src); i++) {
14398 0 : src[i] = i;
14399 : }
14400 0 : hex_encode_buf(buf, src, sizeof(src));
14401 0 : if (strcmp(buf, "0001020304050607") != 0) {
14402 0 : return false;
14403 : }
14404 0 : hex_encode_buf(buf, NULL, 0);
14405 0 : if (buf[0] != '\0') {
14406 0 : return false;
14407 : }
14408 0 : return true;
14409 : }
14410 :
14411 : static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14412 : "0.0.0.0",
14413 : "::0",
14414 : "1.2.3.1",
14415 : "0.0.0.0",
14416 : "0.0.0.0",
14417 : "1.2.3.2",
14418 : "1.2.3.3",
14419 : "1.2.3.4",
14420 : "1.2.3.5",
14421 : "::0",
14422 : "1.2.3.6",
14423 : "1.2.3.7",
14424 : "::0",
14425 : "::0",
14426 : "::0",
14427 : "1.2.3.8",
14428 : "1.2.3.9",
14429 : "1.2.3.10",
14430 : "1.2.3.11",
14431 : "1.2.3.12",
14432 : "1.2.3.13",
14433 : "1001:1111:1111:1000:0:1111:1111:1111",
14434 : "1.2.3.1",
14435 : "1.2.3.2",
14436 : "1.2.3.3",
14437 : "1.2.3.12",
14438 : "::0",
14439 : "::0"
14440 : };
14441 :
14442 : static const char *remove_duplicate_addrs2_test_strings_result[] = {
14443 : "1.2.3.1",
14444 : "1.2.3.2",
14445 : "1.2.3.3",
14446 : "1.2.3.4",
14447 : "1.2.3.5",
14448 : "1.2.3.6",
14449 : "1.2.3.7",
14450 : "1.2.3.8",
14451 : "1.2.3.9",
14452 : "1.2.3.10",
14453 : "1.2.3.11",
14454 : "1.2.3.12",
14455 : "1.2.3.13",
14456 : "1001:1111:1111:1000:0:1111:1111:1111"
14457 : };
14458 :
14459 0 : static bool run_local_remove_duplicate_addrs2(int dummy)
14460 : {
14461 : struct samba_sockaddr test_vector[28];
14462 : size_t count, i;
14463 :
14464 : /* Construct the sockaddr_storage test vector. */
14465 0 : for (i = 0; i < 28; i++) {
14466 : struct addrinfo hints;
14467 0 : struct addrinfo *res = NULL;
14468 : int ret;
14469 :
14470 0 : memset(&hints, '\0', sizeof(hints));
14471 0 : hints.ai_flags = AI_NUMERICHOST;
14472 0 : ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14473 : NULL,
14474 : &hints,
14475 : &res);
14476 0 : if (ret) {
14477 0 : fprintf(stderr, "getaddrinfo failed on [%s]\n",
14478 : remove_duplicate_addrs2_test_strings_vector[i]);
14479 0 : return false;
14480 : }
14481 0 : memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14482 0 : memcpy(&test_vector[i].u.ss,
14483 0 : res->ai_addr,
14484 0 : res->ai_addrlen);
14485 0 : freeaddrinfo(res);
14486 : }
14487 :
14488 0 : count = remove_duplicate_addrs2(test_vector, i);
14489 :
14490 0 : if (count != 14) {
14491 0 : fprintf(stderr, "count wrong (%zu) should be 14\n",
14492 : count);
14493 0 : return false;
14494 : }
14495 :
14496 0 : for (i = 0; i < count; i++) {
14497 : char addr[INET6_ADDRSTRLEN];
14498 :
14499 0 : print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14500 :
14501 0 : if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14502 0 : fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14503 : i,
14504 : addr,
14505 : remove_duplicate_addrs2_test_strings_result[i]);
14506 0 : return false;
14507 : }
14508 : }
14509 :
14510 0 : printf("run_local_remove_duplicate_addrs2: success\n");
14511 0 : return true;
14512 : }
14513 :
14514 0 : static bool run_local_tdb_opener(int dummy)
14515 : {
14516 : TDB_CONTEXT *t;
14517 0 : unsigned v = 0;
14518 :
14519 : while (1) {
14520 0 : t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14521 : O_RDWR|O_CREAT, 0755);
14522 0 : if (t == NULL) {
14523 0 : perror("tdb_open failed");
14524 0 : return false;
14525 : }
14526 0 : tdb_close(t);
14527 :
14528 0 : v += 1;
14529 0 : printf("\r%u", v);
14530 : }
14531 : return true;
14532 : }
14533 :
14534 0 : static bool run_local_tdb_writer(int dummy)
14535 : {
14536 : TDB_CONTEXT *t;
14537 0 : unsigned v = 0;
14538 : TDB_DATA val;
14539 :
14540 0 : t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14541 0 : if (t == 0) {
14542 0 : perror("tdb_open failed");
14543 0 : return 1;
14544 : }
14545 :
14546 0 : val.dptr = (uint8_t *)&v;
14547 0 : val.dsize = sizeof(v);
14548 :
14549 0 : while (1) {
14550 : TDB_DATA data;
14551 : int ret;
14552 :
14553 0 : ret = tdb_store(t, val, val, 0);
14554 0 : if (ret != 0) {
14555 0 : printf("%s\n", tdb_errorstr(t));
14556 : }
14557 0 : v += 1;
14558 0 : printf("\r%u", v);
14559 :
14560 0 : data = tdb_fetch(t, val);
14561 0 : if (data.dptr != NULL) {
14562 0 : SAFE_FREE(data.dptr);
14563 : }
14564 : }
14565 : return true;
14566 : }
14567 :
14568 0 : static bool run_local_canonicalize_path(int dummy)
14569 : {
14570 0 : const char *src[] = {
14571 : "/foo/..",
14572 : "/..",
14573 : "/foo/bar/../baz",
14574 : "/foo/././",
14575 : "/../foo",
14576 : ".././././",
14577 : ".././././../../../boo",
14578 : "./..",
14579 : "/",
14580 : "/../../",
14581 : "/foo/../",
14582 : "/./././",
14583 : "/./././.",
14584 : "/.../././.",
14585 : "/./././.foo",
14586 : "/./././.foo.",
14587 : "/./././foo.",
14588 : "/foo/bar/..",
14589 : "/foo/bar/../baz/",
14590 : "////////////////",
14591 : "/////////./././././.",
14592 : "/./.././../.boo/../baz",
14593 : "/a/component/path",
14594 : "/a/component/path/",
14595 : "/a/component/path/..",
14596 : "/a/component/../path/",
14597 : "///a/./././///component/../////path/",
14598 : NULL
14599 : };
14600 0 : const char *dst[] = {
14601 : "/",
14602 : "/",
14603 : "/foo/baz",
14604 : "/foo",
14605 : "/foo",
14606 : "/",
14607 : "/boo",
14608 : "/",
14609 : "/",
14610 : "/",
14611 : "/",
14612 : "/",
14613 : "/",
14614 : "/...",
14615 : "/.foo",
14616 : "/.foo.",
14617 : "/foo.",
14618 : "/foo",
14619 : "/foo/baz",
14620 : "/",
14621 : "/",
14622 : "/baz",
14623 : "/a/component/path",
14624 : "/a/component/path",
14625 : "/a/component",
14626 : "/a/path",
14627 : "/a/path",
14628 : NULL
14629 : };
14630 : unsigned int i;
14631 :
14632 0 : for (i = 0; src[i] != NULL; i++) {
14633 0 : char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14634 0 : if (d == NULL) {
14635 0 : perror("talloc fail\n");
14636 0 : return false;
14637 : }
14638 0 : if (strcmp(d, dst[i]) != 0) {
14639 0 : d_fprintf(stderr,
14640 : "canonicalize mismatch %s -> %s != %s",
14641 : src[i], d, dst[i]);
14642 0 : return false;
14643 : }
14644 0 : talloc_free(d);
14645 : }
14646 0 : return true;
14647 : }
14648 : struct session_setup_nt1_truncated_state {
14649 : uint16_t vwv[13];
14650 : uint8_t bytes[20];
14651 : };
14652 :
14653 : static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq);
14654 :
14655 0 : static struct tevent_req *smb1_session_setup_nt1_truncated_send(
14656 : TALLOC_CTX *mem_ctx,
14657 : struct tevent_context *ev,
14658 : struct smbXcli_conn *conn)
14659 : {
14660 0 : uint16_t *vwv = NULL;
14661 0 : uint8_t *bytes = NULL;
14662 0 : const char *pass = "12345678";
14663 0 : const char *uname = "z";
14664 0 : struct session_setup_nt1_truncated_state *state = NULL;
14665 0 : struct tevent_req *req = NULL;
14666 0 : struct tevent_req *subreq = NULL;
14667 :
14668 0 : req = tevent_req_create(mem_ctx,
14669 : &state,
14670 : struct session_setup_nt1_truncated_state);
14671 0 : if (req == NULL) {
14672 0 : return NULL;
14673 : }
14674 0 : vwv = &state->vwv[0];
14675 0 : bytes = &state->bytes[0];
14676 :
14677 0 : SCVAL(vwv+0, 0, 0xff);
14678 0 : SCVAL(vwv+0, 1, 0);
14679 0 : SSVAL(vwv+1, 0, 0);
14680 0 : SSVAL(vwv+2, 0, 8192);
14681 0 : SSVAL(vwv+3, 0, 2);
14682 0 : SSVAL(vwv+4, 0, 1);
14683 0 : SIVAL(vwv+5, 0, 0);
14684 0 : SSVAL(vwv+7, 0, strlen(pass)); /* OEMPasswordLen */
14685 0 : SSVAL(vwv+8, 0, 0); /* UnicodePasswordLen */
14686 0 : SSVAL(vwv+9, 0, 0); /* reserved */
14687 0 : SSVAL(vwv+10, 0, 0); /* reserved */
14688 0 : SIVAL(vwv+11, 0, CAP_STATUS32);
14689 :
14690 0 : memcpy(bytes, pass, strlen(pass));
14691 0 : bytes += strlen(pass);
14692 0 : memcpy(bytes, uname, strlen(uname)+1);
14693 :
14694 0 : subreq = smb1cli_req_send(state, ev, conn,
14695 : SMBsesssetupX,
14696 : 0, /* additional_flags */
14697 : 0, /* clear_flags */
14698 : 0, /* additional_flags2 */
14699 : 0, /* clear_flags2 */
14700 : 10000, /* timeout_msec */
14701 0 : getpid(),
14702 : NULL, /* tcon */
14703 : NULL, /* session */
14704 : 13, /* wct */
14705 0 : state->vwv,
14706 0 : strlen(pass), /* Truncate length at password. */
14707 0 : state->bytes);
14708 0 : if (tevent_req_nomem(subreq, req)) {
14709 0 : return tevent_req_post(req, ev);
14710 : }
14711 0 : tevent_req_set_callback(subreq,
14712 : smb1_session_setup_nt1_truncated_done,
14713 : req);
14714 0 : return req;
14715 : }
14716 :
14717 0 : static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq)
14718 : {
14719 : struct tevent_req *req =
14720 0 : tevent_req_callback_data(subreq,
14721 : struct tevent_req);
14722 : struct session_setup_nt1_truncated_state *state =
14723 0 : tevent_req_data(req,
14724 : struct session_setup_nt1_truncated_state);
14725 : NTSTATUS status;
14726 0 : struct smb1cli_req_expected_response expected[] = {
14727 : {
14728 : .status = NT_STATUS_OK,
14729 : .wct = 3,
14730 : },
14731 : };
14732 :
14733 0 : status = smb1cli_req_recv(subreq, state,
14734 : NULL,
14735 : NULL,
14736 : NULL,
14737 : NULL,
14738 : NULL, /* pvwv_offset */
14739 : NULL,
14740 : NULL,
14741 : NULL, /* pbytes_offset */
14742 : NULL,
14743 : expected, ARRAY_SIZE(expected));
14744 0 : TALLOC_FREE(subreq);
14745 0 : if (tevent_req_nterror(req, status)) {
14746 0 : return;
14747 : }
14748 0 : tevent_req_done(req);
14749 : }
14750 :
14751 0 : static NTSTATUS smb1_session_setup_nt1_truncated_recv(struct tevent_req *req)
14752 : {
14753 0 : return tevent_req_simple_recv_ntstatus(req);
14754 : }
14755 :
14756 0 : static bool run_smb1_truncated_sesssetup(int dummy)
14757 : {
14758 : struct tevent_context *ev;
14759 : struct tevent_req *req;
14760 : struct smbXcli_conn *conn;
14761 : struct sockaddr_storage ss;
14762 : NTSTATUS status;
14763 : int fd;
14764 : bool ok;
14765 :
14766 0 : printf("Starting send truncated SMB1 sesssetup.\n");
14767 :
14768 0 : ok = resolve_name(host, &ss, 0x20, true);
14769 0 : if (!ok) {
14770 0 : d_fprintf(stderr, "Could not resolve name %s\n", host);
14771 0 : return false;
14772 : }
14773 :
14774 0 : status = open_socket_out(&ss, 445, 10000, &fd);
14775 0 : if (!NT_STATUS_IS_OK(status)) {
14776 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
14777 : nt_errstr(status));
14778 0 : return false;
14779 : }
14780 :
14781 0 : conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14782 : NULL, 0, NULL);
14783 0 : if (conn == NULL) {
14784 0 : d_fprintf(stderr, "smbXcli_conn_create failed\n");
14785 0 : return false;
14786 : }
14787 :
14788 0 : status = smbXcli_negprot(conn, 0, PROTOCOL_NT1, PROTOCOL_NT1);
14789 0 : if (!NT_STATUS_IS_OK(status)) {
14790 0 : d_fprintf(stderr, "smbXcli_negprot failed!\n");
14791 0 : return false;
14792 : }
14793 :
14794 0 : ev = samba_tevent_context_init(talloc_tos());
14795 0 : if (ev == NULL) {
14796 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
14797 0 : return false;
14798 : }
14799 :
14800 0 : req = smb1_session_setup_nt1_truncated_send(ev, ev, conn);
14801 0 : if (req == NULL) {
14802 0 : d_fprintf(stderr, "smb1_session_setup_nt1_truncated_send failed\n");
14803 0 : return false;
14804 : }
14805 :
14806 0 : ok = tevent_req_poll_ntstatus(req, ev, &status);
14807 0 : if (!ok) {
14808 0 : d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
14809 : nt_errstr(status));
14810 0 : return false;
14811 : }
14812 :
14813 0 : status = smb1_session_setup_nt1_truncated_recv(req);
14814 0 : if (!NT_STATUS_IS_OK(status)) {
14815 0 : d_fprintf(stderr, "smb1_session_setup_nt1_truncated_recv returned "
14816 : "%s, expected NT_STATUS_OK\n",
14817 : nt_errstr(status));
14818 0 : return false;
14819 : }
14820 :
14821 0 : TALLOC_FREE(conn);
14822 0 : return true;
14823 : }
14824 :
14825 : struct smb1_negotiate_exit_state {
14826 : int dummy;
14827 : };
14828 :
14829 : static void smb1_negotiate_exit_done(struct tevent_req *subreq);
14830 :
14831 0 : static struct tevent_req *smb1_negotiate_exit_send(
14832 : TALLOC_CTX *mem_ctx,
14833 : struct tevent_context *ev,
14834 : struct smbXcli_conn *conn)
14835 : {
14836 0 : struct smb1_negotiate_exit_state *state = NULL;
14837 0 : struct tevent_req *req = NULL;
14838 0 : struct tevent_req *subreq = NULL;
14839 :
14840 0 : req = tevent_req_create(mem_ctx,
14841 : &state,
14842 : struct smb1_negotiate_exit_state);
14843 0 : if (req == NULL) {
14844 0 : return NULL;
14845 : }
14846 0 : subreq = smb1cli_req_send(state, ev, conn,
14847 : SMBexit,
14848 : 0, /* additional_flags */
14849 : 0, /* clear_flags */
14850 : 0, /* additional_flags2 */
14851 : 0, /* clear_flags2 */
14852 : 10000, /* timeout_msec */
14853 0 : getpid(),
14854 : NULL, /* tcon */
14855 : NULL, /* session */
14856 : 0, /* wct */
14857 : NULL,
14858 : 0,
14859 : NULL);
14860 0 : if (tevent_req_nomem(subreq, req)) {
14861 0 : return tevent_req_post(req, ev);
14862 : }
14863 0 : tevent_req_set_callback(subreq,
14864 : smb1_negotiate_exit_done,
14865 : req);
14866 0 : return req;
14867 : }
14868 :
14869 0 : static void smb1_negotiate_exit_done(struct tevent_req *subreq)
14870 : {
14871 : struct tevent_req *req =
14872 0 : tevent_req_callback_data(subreq,
14873 : struct tevent_req);
14874 : struct smb1_negotiate_exit_state *state =
14875 0 : tevent_req_data(req,
14876 : struct smb1_negotiate_exit_state);
14877 : NTSTATUS status;
14878 0 : struct smb1cli_req_expected_response expected[] = {
14879 : {
14880 : .status = NT_STATUS_OK,
14881 : .wct = 0,
14882 : },
14883 : };
14884 :
14885 0 : status = smb1cli_req_recv(subreq, state,
14886 : NULL,
14887 : NULL,
14888 : NULL,
14889 : NULL,
14890 : NULL, /* pvwv_offset */
14891 : NULL,
14892 : NULL,
14893 : NULL, /* pbytes_offset */
14894 : NULL,
14895 : expected, ARRAY_SIZE(expected));
14896 0 : TALLOC_FREE(subreq);
14897 0 : if (tevent_req_nterror(req, status)) {
14898 0 : return;
14899 : }
14900 0 : tevent_req_done(req);
14901 : }
14902 :
14903 0 : static NTSTATUS smb1_negotiate_exit_recv(struct tevent_req *req)
14904 : {
14905 0 : return tevent_req_simple_recv_ntstatus(req);
14906 : }
14907 :
14908 0 : static bool do_smb1_exit(TALLOC_CTX *mem_ctx,
14909 : struct tevent_context *ev,
14910 : struct smbXcli_conn *conn)
14911 : {
14912 : struct tevent_req *req;
14913 : bool ok;
14914 : NTSTATUS status;
14915 0 : NTSTATUS expected_status = NT_STATUS_DOS(ERRSRV, ERRinvnid);;
14916 :
14917 0 : req = smb1_negotiate_exit_send(ev, ev, conn);
14918 0 : if (req == NULL) {
14919 0 : d_fprintf(stderr, "smb1_negotiate_exit_send failed\n");
14920 0 : return false;
14921 : }
14922 :
14923 0 : ok = tevent_req_poll_ntstatus(req, ev, &status);
14924 0 : if (!ok) {
14925 0 : d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
14926 : nt_errstr(status));
14927 0 : return false;
14928 : }
14929 :
14930 0 : status = smb1_negotiate_exit_recv(req);
14931 0 : if (!NT_STATUS_EQUAL(status, expected_status)) {
14932 0 : d_fprintf(stderr, "smb1_negotiate_exit_recv returned "
14933 : "%s, expected ERRSRV, ERRinvnid\n",
14934 : nt_errstr(status));
14935 0 : return false;
14936 : }
14937 0 : return true;
14938 : }
14939 :
14940 0 : static bool run_smb1_negotiate_exit(int dummy)
14941 : {
14942 : struct tevent_context *ev;
14943 : struct smbXcli_conn *conn;
14944 : struct sockaddr_storage ss;
14945 : NTSTATUS status;
14946 : int fd;
14947 : bool ok;
14948 :
14949 0 : printf("Starting send SMB1 negotiate+exit.\n");
14950 :
14951 0 : ok = resolve_name(host, &ss, 0x20, true);
14952 0 : if (!ok) {
14953 0 : d_fprintf(stderr, "Could not resolve name %s\n", host);
14954 0 : return false;
14955 : }
14956 :
14957 0 : status = open_socket_out(&ss, 445, 10000, &fd);
14958 0 : if (!NT_STATUS_IS_OK(status)) {
14959 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
14960 : nt_errstr(status));
14961 0 : return false;
14962 : }
14963 :
14964 0 : conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14965 : NULL, 0, NULL);
14966 0 : if (conn == NULL) {
14967 0 : d_fprintf(stderr, "smbXcli_conn_create failed\n");
14968 0 : return false;
14969 : }
14970 :
14971 0 : status = smbXcli_negprot(conn, 0, PROTOCOL_NT1, PROTOCOL_NT1);
14972 0 : if (!NT_STATUS_IS_OK(status)) {
14973 0 : d_fprintf(stderr, "smbXcli_negprot failed!\n");
14974 0 : return false;
14975 : }
14976 :
14977 0 : ev = samba_tevent_context_init(talloc_tos());
14978 0 : if (ev == NULL) {
14979 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
14980 0 : return false;
14981 : }
14982 :
14983 : /*
14984 : * Call do_smb1_exit twice to catch a server crash, the
14985 : * server sends the first return code then crashes.
14986 : */
14987 0 : ok = do_smb1_exit(ev, ev, conn);
14988 0 : if (!ok) {
14989 0 : d_fprintf(stderr, "do_smb1_exit (1) failed\n");
14990 0 : return false;
14991 : }
14992 0 : ok = do_smb1_exit(ev, ev, conn);
14993 0 : if (!ok) {
14994 0 : d_fprintf(stderr, "do_smb1_exit (2) failed\n");
14995 0 : return false;
14996 : }
14997 :
14998 0 : TALLOC_FREE(conn);
14999 0 : return true;
15000 : }
15001 :
15002 0 : static bool run_smb1_negotiate_tcon(int dummy)
15003 : {
15004 0 : struct cli_state *cli = NULL;
15005 0 : uint16_t cnum = 0;
15006 0 : uint16_t max_xmit = 0;
15007 : NTSTATUS status;
15008 :
15009 0 : printf("Starting send SMB1 negotiate+tcon.\n");
15010 0 : cli = open_nbt_connection();
15011 0 : if (cli == NULL) {
15012 0 : d_fprintf(stderr, "open_nbt_connection failed!\n");
15013 0 : return false;
15014 : }
15015 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
15016 :
15017 0 : status = smbXcli_negprot(cli->conn, 0, PROTOCOL_NT1, PROTOCOL_NT1);
15018 0 : if (!NT_STATUS_IS_OK(status)) {
15019 0 : d_fprintf(stderr, "smbXcli_negprot failed %s!\n",
15020 : nt_errstr(status));
15021 0 : return false;
15022 : }
15023 0 : status = cli_raw_tcon(cli,
15024 : share,
15025 : "",
15026 : "?????",
15027 : &max_xmit,
15028 : &cnum);
15029 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
15030 0 : d_fprintf(stderr, "cli_raw_tcon failed - got %s "
15031 : "(should get NT_STATUS_ACCESS_DENIED)!\n",
15032 : nt_errstr(status));
15033 0 : return false;
15034 : }
15035 0 : return true;
15036 : }
15037 :
15038 0 : static bool run_ign_bad_negprot(int dummy)
15039 : {
15040 : struct tevent_context *ev;
15041 : struct tevent_req *req;
15042 : struct smbXcli_conn *conn;
15043 : struct sockaddr_storage ss;
15044 : NTSTATUS status;
15045 : int fd;
15046 : bool ok;
15047 :
15048 0 : printf("starting ignore bad negprot\n");
15049 :
15050 0 : ok = resolve_name(host, &ss, 0x20, true);
15051 0 : if (!ok) {
15052 0 : d_fprintf(stderr, "Could not resolve name %s\n", host);
15053 0 : return false;
15054 : }
15055 :
15056 0 : status = open_socket_out(&ss, 445, 10000, &fd);
15057 0 : if (!NT_STATUS_IS_OK(status)) {
15058 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
15059 : nt_errstr(status));
15060 0 : return false;
15061 : }
15062 :
15063 0 : conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15064 : NULL, 0, NULL);
15065 0 : if (conn == NULL) {
15066 0 : d_fprintf(stderr, "smbXcli_conn_create failed\n");
15067 0 : return false;
15068 : }
15069 :
15070 0 : status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
15071 0 : if (NT_STATUS_IS_OK(status)) {
15072 0 : d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
15073 0 : return false;
15074 : }
15075 :
15076 0 : ev = samba_tevent_context_init(talloc_tos());
15077 0 : if (ev == NULL) {
15078 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
15079 0 : return false;
15080 : }
15081 :
15082 0 : req = smb1cli_session_setup_nt1_send(
15083 0 : ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
15084 : data_blob_null, data_blob_null, 0x40,
15085 : "Windows 2000 2195", "Windows 2000 5.0");
15086 0 : if (req == NULL) {
15087 0 : d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
15088 0 : return false;
15089 : }
15090 :
15091 0 : ok = tevent_req_poll_ntstatus(req, ev, &status);
15092 0 : if (!ok) {
15093 0 : d_fprintf(stderr, "tevent_req_poll failed\n");
15094 0 : return false;
15095 : }
15096 :
15097 0 : status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
15098 : NULL, NULL);
15099 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
15100 0 : d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
15101 : "%s, expected NT_STATUS_CONNECTION_RESET\n",
15102 : nt_errstr(status));
15103 0 : return false;
15104 : }
15105 :
15106 0 : TALLOC_FREE(conn);
15107 :
15108 0 : printf("starting ignore bad negprot\n");
15109 :
15110 0 : return true;
15111 : }
15112 :
15113 :
15114 2 : static double create_procs(bool (*fn)(int), bool *result)
15115 : {
15116 : int i, status;
15117 : volatile pid_t *child_status;
15118 : volatile bool *child_status_out;
15119 : int synccount;
15120 2 : int tries = 8;
15121 : struct timeval start;
15122 :
15123 2 : synccount = 0;
15124 :
15125 2 : child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
15126 2 : if (!child_status) {
15127 0 : printf("Failed to setup shared memory\n");
15128 0 : return -1;
15129 : }
15130 :
15131 2 : child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
15132 2 : if (!child_status_out) {
15133 0 : printf("Failed to setup result status shared memory\n");
15134 0 : return -1;
15135 : }
15136 :
15137 4 : for (i = 0; i < torture_nprocs; i++) {
15138 2 : child_status[i] = 0;
15139 2 : child_status_out[i] = True;
15140 : }
15141 :
15142 2 : start = timeval_current();
15143 :
15144 4 : for (i=0;i<torture_nprocs;i++) {
15145 2 : procnum = i;
15146 2 : if (fork() == 0) {
15147 0 : pid_t mypid = getpid();
15148 0 : sys_srandom(((int)mypid) ^ ((int)time(NULL)));
15149 :
15150 0 : slprintf(myname,sizeof(myname),"CLIENT%d", i);
15151 :
15152 : while (1) {
15153 0 : if (torture_open_connection(¤t_cli, i)) break;
15154 0 : if (tries-- == 0) {
15155 0 : printf("pid %d failed to start\n", (int)getpid());
15156 0 : _exit(1);
15157 : }
15158 0 : smb_msleep(10);
15159 : }
15160 :
15161 0 : child_status[i] = getpid();
15162 :
15163 0 : while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
15164 :
15165 0 : child_status_out[i] = fn(i);
15166 0 : _exit(0);
15167 : }
15168 : }
15169 :
15170 : do {
15171 8 : synccount = 0;
15172 16 : for (i=0;i<torture_nprocs;i++) {
15173 8 : if (child_status[i]) synccount++;
15174 : }
15175 8 : if (synccount == torture_nprocs) break;
15176 6 : smb_msleep(10);
15177 6 : } while (timeval_elapsed(&start) < 30);
15178 :
15179 2 : if (synccount != torture_nprocs) {
15180 0 : printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
15181 0 : *result = False;
15182 0 : return timeval_elapsed(&start);
15183 : }
15184 :
15185 : /* start the client load */
15186 2 : start = timeval_current();
15187 :
15188 4 : for (i=0;i<torture_nprocs;i++) {
15189 2 : child_status[i] = 0;
15190 : }
15191 :
15192 2 : printf("%d clients started\n", torture_nprocs);
15193 :
15194 4 : for (i=0;i<torture_nprocs;i++) {
15195 2 : while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
15196 : }
15197 :
15198 2 : printf("\n");
15199 :
15200 4 : for (i=0;i<torture_nprocs;i++) {
15201 2 : if (!child_status_out[i]) {
15202 0 : *result = False;
15203 : }
15204 : }
15205 2 : return timeval_elapsed(&start);
15206 : }
15207 :
15208 : #define FLAG_MULTIPROC 1
15209 :
15210 : static struct {
15211 : const char *name;
15212 : bool (*fn)(int);
15213 : unsigned flags;
15214 : } torture_ops[] = {
15215 : {
15216 : .name = "FDPASS",
15217 : .fn = run_fdpasstest,
15218 : },
15219 : {
15220 : .name = "LOCK1",
15221 : .fn = run_locktest1,
15222 : },
15223 : {
15224 : .name = "LOCK2",
15225 : .fn = run_locktest2,
15226 : },
15227 : {
15228 : .name = "LOCK3",
15229 : .fn = run_locktest3,
15230 : },
15231 : {
15232 : .name = "LOCK4",
15233 : .fn = run_locktest4,
15234 : },
15235 : {
15236 : .name = "LOCK5",
15237 : .fn = run_locktest5,
15238 : },
15239 : {
15240 : .name = "LOCK6",
15241 : .fn = run_locktest6,
15242 : },
15243 : {
15244 : .name = "LOCK7",
15245 : .fn = run_locktest7,
15246 : },
15247 : {
15248 : .name = "LOCK8",
15249 : .fn = run_locktest8,
15250 : },
15251 : {
15252 : .name = "LOCK9A",
15253 : .fn = run_locktest9a,
15254 : },
15255 : {
15256 : .name = "LOCK9B",
15257 : .fn = run_locktest9b,
15258 : },
15259 : {
15260 : .name = "LOCK10",
15261 : .fn = run_locktest10,
15262 : },
15263 : {
15264 : .name = "LOCK11",
15265 : .fn = run_locktest11,
15266 : },
15267 : {
15268 : .name = "LOCK12",
15269 : .fn = run_locktest12,
15270 : },
15271 : {
15272 : .name = "LOCK13",
15273 : .fn = run_locktest13,
15274 : },
15275 : {
15276 : .name = "UNLINK",
15277 : .fn = run_unlinktest,
15278 : },
15279 : {
15280 : .name = "BROWSE",
15281 : .fn = run_browsetest,
15282 : },
15283 : {
15284 : .name = "ATTR",
15285 : .fn = run_attrtest,
15286 : },
15287 : {
15288 : .name = "TRANS2",
15289 : .fn = run_trans2test,
15290 : },
15291 : {
15292 : .name = "MAXFID",
15293 : .fn = run_maxfidtest,
15294 : .flags = FLAG_MULTIPROC,
15295 : },
15296 : {
15297 : .name = "TORTURE",
15298 : .fn = run_torture,
15299 : .flags = FLAG_MULTIPROC,
15300 : },
15301 : {
15302 : .name = "RANDOMIPC",
15303 : .fn = run_randomipc,
15304 : },
15305 : {
15306 : .name = "NEGNOWAIT",
15307 : .fn = run_negprot_nowait,
15308 : },
15309 : {
15310 : .name = "NBENCH",
15311 : .fn = run_nbench,
15312 : },
15313 : {
15314 : .name = "NBENCH2",
15315 : .fn = run_nbench2,
15316 : },
15317 : {
15318 : .name = "OPLOCK1",
15319 : .fn = run_oplock1,
15320 : },
15321 : {
15322 : .name = "OPLOCK2",
15323 : .fn = run_oplock2,
15324 : },
15325 : {
15326 : .name = "OPLOCK4",
15327 : .fn = run_oplock4,
15328 : },
15329 : #ifdef HAVE_KERNEL_OPLOCKS_LINUX
15330 : {
15331 : .name = "OPLOCK5",
15332 : .fn = run_oplock5,
15333 : },
15334 : #endif
15335 : {
15336 : .name = "DIR",
15337 : .fn = run_dirtest,
15338 : },
15339 : {
15340 : .name = "DIR1",
15341 : .fn = run_dirtest1,
15342 : },
15343 : {
15344 : .name = "DIR-CREATETIME",
15345 : .fn = run_dir_createtime,
15346 : },
15347 : {
15348 : .name = "DENY1",
15349 : .fn = torture_denytest1,
15350 : },
15351 : {
15352 : .name = "DENY2",
15353 : .fn = torture_denytest2,
15354 : },
15355 : {
15356 : .name = "TCON",
15357 : .fn = run_tcon_test,
15358 : },
15359 : {
15360 : .name = "TCONDEV",
15361 : .fn = run_tcon_devtype_test,
15362 : },
15363 : {
15364 : .name = "RW1",
15365 : .fn = run_readwritetest,
15366 : },
15367 : {
15368 : .name = "RW2",
15369 : .fn = run_readwritemulti,
15370 : .flags = FLAG_MULTIPROC
15371 : },
15372 : {
15373 : .name = "RW3",
15374 : .fn = run_readwritelarge,
15375 : },
15376 : {
15377 : .name = "RW-SIGNING",
15378 : .fn = run_readwritelarge_signtest,
15379 : },
15380 : {
15381 : .name = "OPEN",
15382 : .fn = run_opentest,
15383 : },
15384 : {
15385 : .name = "POSIX",
15386 : .fn = run_simple_posix_open_test,
15387 : },
15388 : {
15389 : .name = "POSIX-APPEND",
15390 : .fn = run_posix_append,
15391 : },
15392 : {
15393 : .name = "POSIX-SYMLINK-ACL",
15394 : .fn = run_acl_symlink_test,
15395 : },
15396 : {
15397 : .name = "POSIX-SYMLINK-EA",
15398 : .fn = run_ea_symlink_test,
15399 : },
15400 : {
15401 : .name = "POSIX-STREAM-DELETE",
15402 : .fn = run_posix_stream_delete,
15403 : },
15404 : {
15405 : .name = "POSIX-OFD-LOCK",
15406 : .fn = run_posix_ofd_lock_test,
15407 : },
15408 : {
15409 : .name = "POSIX-BLOCKING-LOCK",
15410 : .fn = run_posix_blocking_lock,
15411 : },
15412 : {
15413 : .name = "POSIX-MKDIR",
15414 : .fn = run_posix_mkdir_test,
15415 : },
15416 : {
15417 : .name = "POSIX-ACL-OPLOCK",
15418 : .fn = run_posix_acl_oplock_test,
15419 : },
15420 : {
15421 : .name = "POSIX-ACL-SHAREROOT",
15422 : .fn = run_posix_acl_shareroot_test,
15423 : },
15424 : {
15425 : .name = "POSIX-LS-WILDCARD",
15426 : .fn = run_posix_ls_wildcard_test,
15427 : },
15428 : {
15429 : .name = "POSIX-LS-SINGLE",
15430 : .fn = run_posix_ls_single_test,
15431 : },
15432 : {
15433 : .name = "POSIX-READLINK",
15434 : .fn = run_posix_readlink_test,
15435 : },
15436 : {
15437 : .name = "POSIX-STAT",
15438 : .fn = run_posix_stat_test,
15439 : },
15440 : {
15441 : .name = "POSIX-SYMLINK-PARENT",
15442 : .fn = run_posix_symlink_parent_test,
15443 : },
15444 : {
15445 : .name = "POSIX-SYMLINK-CHMOD",
15446 : .fn = run_posix_symlink_chmod_test,
15447 : },
15448 : {
15449 : .name = "POSIX-SYMLINK-RENAME",
15450 : .fn = run_posix_symlink_rename_test,
15451 : },
15452 : {
15453 : .name = "POSIX-DIR-DEFAULT-ACL",
15454 : .fn = run_posix_dir_default_acl_test,
15455 : },
15456 : {
15457 : .name = "POSIX-SYMLINK-GETPATHINFO",
15458 : .fn = run_posix_symlink_getpathinfo_test,
15459 : },
15460 : {
15461 : .name = "POSIX-SYMLINK-SETPATHINFO",
15462 : .fn = run_posix_symlink_setpathinfo_test,
15463 : },
15464 : {
15465 : .name = "WINDOWS-BAD-SYMLINK",
15466 : .fn = run_symlink_open_test,
15467 : },
15468 : {
15469 : .name = "SMB1-WILD-MANGLE-UNLINK",
15470 : .fn = run_smb1_wild_mangle_unlink_test,
15471 : },
15472 : {
15473 : .name = "SMB1-WILD-MANGLE-RENAME",
15474 : .fn = run_smb1_wild_mangle_rename_test,
15475 : },
15476 : {
15477 : .name = "CASE-INSENSITIVE-CREATE",
15478 : .fn = run_case_insensitive_create,
15479 : },
15480 : {
15481 : .name = "ASYNC-ECHO",
15482 : .fn = run_async_echo,
15483 : },
15484 : {
15485 : .name = "UID-REGRESSION-TEST",
15486 : .fn = run_uid_regression_test,
15487 : },
15488 : {
15489 : .name = "SHORTNAME-TEST",
15490 : .fn = run_shortname_test,
15491 : },
15492 : {
15493 : .name = "ADDRCHANGE",
15494 : .fn = run_addrchange,
15495 : },
15496 : #if 1
15497 : {
15498 : .name = "OPENATTR",
15499 : .fn = run_openattrtest,
15500 : },
15501 : #endif
15502 : {
15503 : .name = "XCOPY",
15504 : .fn = run_xcopy,
15505 : },
15506 : {
15507 : .name = "RENAME",
15508 : .fn = run_rename,
15509 : },
15510 : {
15511 : .name = "RENAME-ACCESS",
15512 : .fn = run_rename_access,
15513 : },
15514 : {
15515 : .name = "OWNER-RIGHTS",
15516 : .fn = run_owner_rights,
15517 : },
15518 : {
15519 : .name = "DELETE",
15520 : .fn = run_deletetest,
15521 : },
15522 : {
15523 : .name = "DELETE-STREAM",
15524 : .fn = run_delete_stream,
15525 : },
15526 : {
15527 : .name = "DELETE-PRINT",
15528 : .fn = run_delete_print_test,
15529 : },
15530 : {
15531 : .name = "DELETE-LN",
15532 : .fn = run_deletetest_ln,
15533 : },
15534 : {
15535 : .name = "PROPERTIES",
15536 : .fn = run_properties,
15537 : },
15538 : {
15539 : .name = "MANGLE",
15540 : .fn = torture_mangle,
15541 : },
15542 : {
15543 : .name = "MANGLE1",
15544 : .fn = run_mangle1,
15545 : },
15546 : {
15547 : .name = "MANGLE-ILLEGAL",
15548 : .fn = run_mangle_illegal,
15549 : },
15550 : {
15551 : .name = "W2K",
15552 : .fn = run_w2ktest,
15553 : },
15554 : {
15555 : .name = "TRANS2SCAN",
15556 : .fn = torture_trans2_scan,
15557 : },
15558 : {
15559 : .name = "NTTRANSSCAN",
15560 : .fn = torture_nttrans_scan,
15561 : },
15562 : {
15563 : .name = "UTABLE",
15564 : .fn = torture_utable,
15565 : },
15566 : {
15567 : .name = "CASETABLE",
15568 : .fn = torture_casetable,
15569 : },
15570 : {
15571 : .name = "ERRMAPEXTRACT",
15572 : .fn = run_error_map_extract,
15573 : },
15574 : {
15575 : .name = "PIPE_NUMBER",
15576 : .fn = run_pipe_number,
15577 : },
15578 : {
15579 : .name = "TCON2",
15580 : .fn = run_tcon2_test,
15581 : },
15582 : {
15583 : .name = "IOCTL",
15584 : .fn = torture_ioctl_test,
15585 : },
15586 : {
15587 : .name = "CHKPATH",
15588 : .fn = torture_chkpath_test,
15589 : },
15590 : {
15591 : .name = "FDSESS",
15592 : .fn = run_fdsesstest,
15593 : },
15594 : {
15595 : .name = "EATEST",
15596 : .fn = run_eatest,
15597 : },
15598 : {
15599 : .name = "SESSSETUP_BENCH",
15600 : .fn = run_sesssetup_bench,
15601 : },
15602 : {
15603 : .name = "CHAIN1",
15604 : .fn = run_chain1,
15605 : },
15606 : {
15607 : .name = "CHAIN2",
15608 : .fn = run_chain2,
15609 : },
15610 : {
15611 : .name = "CHAIN3",
15612 : .fn = run_chain3,
15613 : },
15614 : {
15615 : .name = "WINDOWS-WRITE",
15616 : .fn = run_windows_write,
15617 : },
15618 : {
15619 : .name = "LARGE_READX",
15620 : .fn = run_large_readx,
15621 : },
15622 : {
15623 : .name = "MSDFS-ATTRIBUTE",
15624 : .fn = run_msdfs_attribute,
15625 : },
15626 : {
15627 : .name = "NTTRANS-CREATE",
15628 : .fn = run_nttrans_create,
15629 : },
15630 : {
15631 : .name = "NTTRANS-FSCTL",
15632 : .fn = run_nttrans_fsctl,
15633 : },
15634 : {
15635 : .name = "CLI_ECHO",
15636 : .fn = run_cli_echo,
15637 : },
15638 : {
15639 : .name = "CLI_SPLICE",
15640 : .fn = run_cli_splice,
15641 : },
15642 : {
15643 : .name = "TLDAP",
15644 : .fn = run_tldap,
15645 : },
15646 : {
15647 : .name = "STREAMERROR",
15648 : .fn = run_streamerror,
15649 : },
15650 : {
15651 : .name = "NOTIFY-BENCH",
15652 : .fn = run_notify_bench,
15653 : },
15654 : {
15655 : .name = "NOTIFY-BENCH2",
15656 : .fn = run_notify_bench2,
15657 : },
15658 : {
15659 : .name = "NOTIFY-BENCH3",
15660 : .fn = run_notify_bench3,
15661 : },
15662 : {
15663 : .name = "BAD-NBT-SESSION",
15664 : .fn = run_bad_nbt_session,
15665 : },
15666 : {
15667 : .name = "IGN-BAD-NEGPROT",
15668 : .fn = run_ign_bad_negprot,
15669 : },
15670 : {
15671 : .name = "SMB-ANY-CONNECT",
15672 : .fn = run_smb_any_connect,
15673 : },
15674 : {
15675 : .name = "NOTIFY-ONLINE",
15676 : .fn = run_notify_online,
15677 : },
15678 : {
15679 : .name = "SMB2-BASIC",
15680 : .fn = run_smb2_basic,
15681 : },
15682 : {
15683 : .name = "SMB2-NEGPROT",
15684 : .fn = run_smb2_negprot,
15685 : },
15686 : {
15687 : .name = "SMB2-ANONYMOUS",
15688 : .fn = run_smb2_anonymous,
15689 : },
15690 : {
15691 : .name = "SMB2-SESSION-RECONNECT",
15692 : .fn = run_smb2_session_reconnect,
15693 : },
15694 : {
15695 : .name = "SMB2-TCON-DEPENDENCE",
15696 : .fn = run_smb2_tcon_dependence,
15697 : },
15698 : {
15699 : .name = "SMB2-MULTI-CHANNEL",
15700 : .fn = run_smb2_multi_channel,
15701 : },
15702 : {
15703 : .name = "SMB2-SESSION-REAUTH",
15704 : .fn = run_smb2_session_reauth,
15705 : },
15706 : {
15707 : .name = "SMB2-FTRUNCATE",
15708 : .fn = run_smb2_ftruncate,
15709 : },
15710 : {
15711 : .name = "SMB2-DIR-FSYNC",
15712 : .fn = run_smb2_dir_fsync,
15713 : },
15714 : {
15715 : .name = "SMB2-PATH-SLASH",
15716 : .fn = run_smb2_path_slash,
15717 : },
15718 : {
15719 : .name = "SMB1-SYSTEM-SECURITY",
15720 : .fn = run_smb1_system_security,
15721 : },
15722 : {
15723 : .name = "SMB2-SACL",
15724 : .fn = run_smb2_sacl,
15725 : },
15726 : {
15727 : .name = "SMB2-QUOTA1",
15728 : .fn = run_smb2_quota1,
15729 : },
15730 : {
15731 : .name = "SMB2-STREAM-ACL",
15732 : .fn = run_smb2_stream_acl,
15733 : },
15734 : {
15735 : .name = "SMB2-LIST-DIR-ASYNC",
15736 : .fn = run_list_dir_async_test,
15737 : },
15738 : {
15739 : .name = "SMB2-DEL-ON-CLOSE-NONEMPTY",
15740 : .fn = run_delete_on_close_non_empty,
15741 : },
15742 : {
15743 : .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15744 : .fn = run_delete_on_close_nonwrite_delete_yes_test,
15745 : },
15746 : {
15747 : .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15748 : .fn = run_delete_on_close_nonwrite_delete_no_test,
15749 : },
15750 : {
15751 : .name = "SMB2-DFS-PATHS",
15752 : .fn = run_smb2_dfs_paths,
15753 : },
15754 : {
15755 : .name = "SMB2-NON-DFS-SHARE",
15756 : .fn = run_smb2_non_dfs_share,
15757 : },
15758 : {
15759 : .name = "SMB2-DFS-SHARE-NON-DFS-PATH",
15760 : .fn = run_smb2_dfs_share_non_dfs_path,
15761 : },
15762 : {
15763 : .name = "SMB2-DFS-FILENAME-LEADING-BACKSLASH",
15764 : .fn = run_smb2_dfs_filename_leading_backslash,
15765 : },
15766 : {
15767 : .name = "SMB2-INVALID-PIPENAME",
15768 : .fn = run_smb2_invalid_pipename,
15769 : },
15770 : {
15771 : .name = "SMB2-PIPE-READ-ASYNC-DISCONNECT",
15772 : .fn = run_smb2_pipe_read_async_disconnect,
15773 : },
15774 : {
15775 : .name = "SMB1-TRUNCATED-SESSSETUP",
15776 : .fn = run_smb1_truncated_sesssetup,
15777 : },
15778 : {
15779 : .name = "SMB1-NEGOTIATE-EXIT",
15780 : .fn = run_smb1_negotiate_exit,
15781 : },
15782 : {
15783 : .name = "SMB1-NEGOTIATE-TCON",
15784 : .fn = run_smb1_negotiate_tcon,
15785 : },
15786 : {
15787 : .name = "SMB1-DFS-PATHS",
15788 : .fn = run_smb1_dfs_paths,
15789 : },
15790 : {
15791 : .name = "SMB1-DFS-SEARCH-PATHS",
15792 : .fn = run_smb1_dfs_search_paths,
15793 : },
15794 : {
15795 : .name = "SMB1-DFS-OPERATIONS",
15796 : .fn = run_smb1_dfs_operations,
15797 : },
15798 : {
15799 : .name = "SMB1-DFS-BADPATH",
15800 : .fn = run_smb1_dfs_check_badpath,
15801 : },
15802 : {
15803 : .name = "CLEANUP1",
15804 : .fn = run_cleanup1,
15805 : },
15806 : {
15807 : .name = "CLEANUP2",
15808 : .fn = run_cleanup2,
15809 : },
15810 : {
15811 : .name = "CLEANUP4",
15812 : .fn = run_cleanup4,
15813 : },
15814 : {
15815 : .name = "OPLOCK-CANCEL",
15816 : .fn = run_oplock_cancel,
15817 : },
15818 : {
15819 : .name = "PIDHIGH",
15820 : .fn = run_pidhigh,
15821 : },
15822 : {
15823 : .name = "LOCAL-SUBSTITUTE",
15824 : .fn = run_local_substitute,
15825 : },
15826 : {
15827 : .name = "LOCAL-GENCACHE",
15828 : .fn = run_local_gencache,
15829 : },
15830 : {
15831 : .name = "LOCAL-DBWRAP-WATCH1",
15832 : .fn = run_dbwrap_watch1,
15833 : },
15834 : {
15835 : .name = "LOCAL-DBWRAP-WATCH2",
15836 : .fn = run_dbwrap_watch2,
15837 : },
15838 : {
15839 : .name = "LOCAL-DBWRAP-WATCH3",
15840 : .fn = run_dbwrap_watch3,
15841 : },
15842 : {
15843 : .name = "LOCAL-DBWRAP-WATCH4",
15844 : .fn = run_dbwrap_watch4,
15845 : },
15846 : {
15847 : .name = "LOCAL-DBWRAP-DO-LOCKED1",
15848 : .fn = run_dbwrap_do_locked1,
15849 : },
15850 : {
15851 : .name = "LOCAL-MESSAGING-READ1",
15852 : .fn = run_messaging_read1,
15853 : },
15854 : {
15855 : .name = "LOCAL-MESSAGING-READ2",
15856 : .fn = run_messaging_read2,
15857 : },
15858 : {
15859 : .name = "LOCAL-MESSAGING-READ3",
15860 : .fn = run_messaging_read3,
15861 : },
15862 : {
15863 : .name = "LOCAL-MESSAGING-READ4",
15864 : .fn = run_messaging_read4,
15865 : },
15866 : {
15867 : .name = "LOCAL-MESSAGING-FDPASS1",
15868 : .fn = run_messaging_fdpass1,
15869 : },
15870 : {
15871 : .name = "LOCAL-MESSAGING-FDPASS2",
15872 : .fn = run_messaging_fdpass2,
15873 : },
15874 : {
15875 : .name = "LOCAL-MESSAGING-FDPASS2a",
15876 : .fn = run_messaging_fdpass2a,
15877 : },
15878 : {
15879 : .name = "LOCAL-MESSAGING-FDPASS2b",
15880 : .fn = run_messaging_fdpass2b,
15881 : },
15882 : {
15883 : .name = "LOCAL-MESSAGING-SEND-ALL",
15884 : .fn = run_messaging_send_all,
15885 : },
15886 : {
15887 : .name = "LOCAL-BASE64",
15888 : .fn = run_local_base64,
15889 : },
15890 : {
15891 : .name = "LOCAL-RBTREE",
15892 : .fn = run_local_rbtree,
15893 : },
15894 : {
15895 : .name = "LOCAL-MEMCACHE",
15896 : .fn = run_local_memcache,
15897 : },
15898 : {
15899 : .name = "LOCAL-STREAM-NAME",
15900 : .fn = run_local_stream_name,
15901 : },
15902 : {
15903 : .name = "LOCAL-STR-MATCH-MSWILD",
15904 : .fn = run_str_match_mswild,
15905 : },
15906 : {
15907 : .name = "LOCAL-STR-MATCH-REGEX-SUB1",
15908 : .fn = run_str_match_regex_sub1,
15909 : },
15910 : {
15911 : .name = "WBCLIENT-MULTI-PING",
15912 : .fn = run_wbclient_multi_ping,
15913 : },
15914 : {
15915 : .name = "LOCAL-string_to_sid",
15916 : .fn = run_local_string_to_sid,
15917 : },
15918 : {
15919 : .name = "LOCAL-sid_to_string",
15920 : .fn = run_local_sid_to_string,
15921 : },
15922 : {
15923 : .name = "LOCAL-binary_to_sid",
15924 : .fn = run_local_binary_to_sid,
15925 : },
15926 : {
15927 : .name = "LOCAL-DBTRANS",
15928 : .fn = run_local_dbtrans,
15929 : },
15930 : {
15931 : .name = "LOCAL-TEVENT-POLL",
15932 : .fn = run_local_tevent_poll,
15933 : },
15934 : {
15935 : .name = "LOCAL-CONVERT-STRING",
15936 : .fn = run_local_convert_string,
15937 : },
15938 : {
15939 : .name = "LOCAL-CONV-AUTH-INFO",
15940 : .fn = run_local_conv_auth_info,
15941 : },
15942 : {
15943 : .name = "LOCAL-hex_encode_buf",
15944 : .fn = run_local_hex_encode_buf,
15945 : },
15946 : {
15947 : .name = "LOCAL-IDMAP-TDB-COMMON",
15948 : .fn = run_idmap_tdb_common_test,
15949 : },
15950 : {
15951 : .name = "LOCAL-remove_duplicate_addrs2",
15952 : .fn = run_local_remove_duplicate_addrs2,
15953 : },
15954 : {
15955 : .name = "local-tdb-opener",
15956 : .fn = run_local_tdb_opener,
15957 : },
15958 : {
15959 : .name = "local-tdb-writer",
15960 : .fn = run_local_tdb_writer,
15961 : },
15962 : {
15963 : .name = "LOCAL-DBWRAP-CTDB1",
15964 : .fn = run_local_dbwrap_ctdb1,
15965 : },
15966 : {
15967 : .name = "LOCAL-BENCH-PTHREADPOOL",
15968 : .fn = run_bench_pthreadpool,
15969 : },
15970 : {
15971 : .name = "LOCAL-PTHREADPOOL-TEVENT",
15972 : .fn = run_pthreadpool_tevent,
15973 : },
15974 : {
15975 : .name = "LOCAL-G-LOCK1",
15976 : .fn = run_g_lock1,
15977 : },
15978 : {
15979 : .name = "LOCAL-G-LOCK2",
15980 : .fn = run_g_lock2,
15981 : },
15982 : {
15983 : .name = "LOCAL-G-LOCK3",
15984 : .fn = run_g_lock3,
15985 : },
15986 : {
15987 : .name = "LOCAL-G-LOCK4",
15988 : .fn = run_g_lock4,
15989 : },
15990 : {
15991 : .name = "LOCAL-G-LOCK4A",
15992 : .fn = run_g_lock4a,
15993 : },
15994 : {
15995 : .name = "LOCAL-G-LOCK5",
15996 : .fn = run_g_lock5,
15997 : },
15998 : {
15999 : .name = "LOCAL-G-LOCK6",
16000 : .fn = run_g_lock6,
16001 : },
16002 : {
16003 : .name = "LOCAL-G-LOCK7",
16004 : .fn = run_g_lock7,
16005 : },
16006 : {
16007 : .name = "LOCAL-G-LOCK8",
16008 : .fn = run_g_lock8,
16009 : },
16010 : {
16011 : .name = "LOCAL-G-LOCK-PING-PONG",
16012 : .fn = run_g_lock_ping_pong,
16013 : },
16014 : {
16015 : .name = "LOCAL-CANONICALIZE-PATH",
16016 : .fn = run_local_canonicalize_path,
16017 : },
16018 : {
16019 : .name = "LOCAL-NAMEMAP-CACHE1",
16020 : .fn = run_local_namemap_cache1,
16021 : },
16022 : {
16023 : .name = "LOCAL-IDMAP-CACHE1",
16024 : .fn = run_local_idmap_cache1,
16025 : },
16026 : {
16027 : .name = "qpathinfo-bufsize",
16028 : .fn = run_qpathinfo_bufsize,
16029 : },
16030 : {
16031 : .name = "hide-new-files-timeout",
16032 : .fn = run_hidenewfiles,
16033 : },
16034 : {
16035 : .name = "hide-new-files-timeout-showdirs",
16036 : .fn = run_hidenewfiles_showdirs,
16037 : },
16038 : #ifdef CLUSTER_SUPPORT
16039 : {
16040 : .name = "ctdbd-conn1",
16041 : .fn = run_ctdbd_conn1,
16042 : },
16043 : #endif
16044 : {
16045 : .name = "readdir-timestamp",
16046 : .fn = run_readdir_timestamp,
16047 : },
16048 : {
16049 : .name = "rpc-scale",
16050 : .fn = run_rpc_scale,
16051 : },
16052 : {
16053 : .name = NULL,
16054 : },
16055 : };
16056 :
16057 : /****************************************************************************
16058 : run a specified test or "ALL"
16059 : ****************************************************************************/
16060 56 : static bool run_test(const char *name)
16061 : {
16062 56 : bool ret = True;
16063 56 : bool result = True;
16064 56 : bool found = False;
16065 : int i;
16066 : double t;
16067 56 : if (strequal(name,"ALL")) {
16068 0 : for (i=0;torture_ops[i].name;i++) {
16069 0 : run_test(torture_ops[i].name);
16070 : }
16071 0 : found = True;
16072 : }
16073 :
16074 11592 : for (i=0;torture_ops[i].name;i++) {
16075 11536 : fstr_sprintf(randomfname, "\\XX%x",
16076 11536 : (unsigned)random());
16077 :
16078 11536 : if (strequal(name, torture_ops[i].name)) {
16079 56 : found = True;
16080 56 : printf("Running %s\n", name);
16081 56 : if (torture_ops[i].flags & FLAG_MULTIPROC) {
16082 2 : t = create_procs(torture_ops[i].fn, &result);
16083 2 : if (!result) {
16084 0 : ret = False;
16085 0 : printf("TEST %s FAILED!\n", name);
16086 : }
16087 : } else {
16088 : struct timeval start;
16089 54 : start = timeval_current();
16090 54 : if (!torture_ops[i].fn(0)) {
16091 6 : ret = False;
16092 6 : printf("TEST %s FAILED!\n", name);
16093 : }
16094 54 : t = timeval_elapsed(&start);
16095 : }
16096 56 : printf("%s took %g secs\n\n", name, t);
16097 : }
16098 : }
16099 :
16100 56 : if (!found) {
16101 0 : printf("Did not find a test named %s\n", name);
16102 0 : ret = False;
16103 : }
16104 :
16105 56 : return ret;
16106 : }
16107 :
16108 :
16109 0 : static void usage(void)
16110 : {
16111 : int i;
16112 :
16113 0 : printf("WARNING samba4 test suite is much more complete nowadays.\n");
16114 0 : printf("Please use samba4 torture.\n\n");
16115 :
16116 0 : printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
16117 :
16118 0 : printf("\t-d debuglevel\n");
16119 0 : printf("\t-U user%%pass\n");
16120 0 : printf("\t-k use kerberos\n");
16121 0 : printf("\t-N numprocs\n");
16122 0 : printf("\t-n my_netbios_name\n");
16123 0 : printf("\t-W workgroup\n");
16124 0 : printf("\t-o num_operations\n");
16125 0 : printf("\t-O socket_options\n");
16126 0 : printf("\t-m maximum protocol\n");
16127 0 : printf("\t-L use oplocks\n");
16128 0 : printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
16129 0 : printf("\t-A showall\n");
16130 0 : printf("\t-p port\n");
16131 0 : printf("\t-s seed\n");
16132 0 : printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
16133 0 : printf("\t-f filename filename to test\n");
16134 0 : printf("\t-e encrypt\n");
16135 0 : printf("\n\n");
16136 :
16137 0 : printf("tests are:");
16138 0 : for (i=0;torture_ops[i].name;i++) {
16139 0 : printf(" %s", torture_ops[i].name);
16140 : }
16141 0 : printf("\n");
16142 :
16143 0 : printf("default test is ALL\n");
16144 :
16145 0 : exit(1);
16146 : }
16147 :
16148 : /****************************************************************************
16149 : main program
16150 : ****************************************************************************/
16151 56 : int main(int argc,char *argv[])
16152 : {
16153 : int opt, i;
16154 : char *p;
16155 56 : int gotuser = 0;
16156 56 : int gotpass = 0;
16157 56 : bool correct = True;
16158 56 : TALLOC_CTX *frame = talloc_stackframe();
16159 56 : int seed = time(NULL);
16160 :
16161 : #ifdef HAVE_SETBUFFER
16162 56 : setbuffer(stdout, NULL, 0);
16163 : #endif
16164 :
16165 56 : setup_logging("smbtorture", DEBUG_STDOUT);
16166 :
16167 56 : smb_init_locale();
16168 56 : fault_setup();
16169 :
16170 56 : if (is_default_dyn_CONFIGFILE()) {
16171 56 : if(getenv("SMB_CONF_PATH")) {
16172 56 : set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
16173 : }
16174 : }
16175 56 : lp_load_global(get_dyn_CONFIGFILE());
16176 56 : load_interfaces();
16177 :
16178 56 : if (argc < 2) {
16179 0 : usage();
16180 : }
16181 :
16182 996 : for(p = argv[1]; *p; p++)
16183 940 : if(*p == '\\')
16184 0 : *p = '/';
16185 :
16186 56 : if (strncmp(argv[1], "//", 2)) {
16187 0 : usage();
16188 : }
16189 :
16190 56 : fstrcpy(host, &argv[1][2]);
16191 56 : p = strchr_m(&host[2],'/');
16192 56 : if (!p) {
16193 0 : usage();
16194 : }
16195 56 : *p = 0;
16196 56 : fstrcpy(share, p+1);
16197 :
16198 56 : fstrcpy(myname, get_myname(talloc_tos()));
16199 56 : if (!*myname) {
16200 0 : fprintf(stderr, "Failed to get my hostname.\n");
16201 0 : return 1;
16202 : }
16203 :
16204 56 : if (*username == 0 && getenv("LOGNAME")) {
16205 0 : fstrcpy(username,getenv("LOGNAME"));
16206 : }
16207 :
16208 56 : argc--;
16209 56 : argv++;
16210 :
16211 56 : fstrcpy(workgroup, lp_workgroup());
16212 :
16213 164 : while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
16214 164 : != EOF) {
16215 108 : switch (opt) {
16216 0 : case 'p':
16217 0 : port_to_use = atoi(optarg);
16218 0 : break;
16219 0 : case 's':
16220 0 : seed = atoi(optarg);
16221 0 : break;
16222 0 : case 'W':
16223 0 : fstrcpy(workgroup,optarg);
16224 0 : break;
16225 0 : case 'm':
16226 0 : lp_set_cmdline("client max protocol", optarg);
16227 0 : break;
16228 0 : case 'N':
16229 0 : torture_nprocs = atoi(optarg);
16230 0 : break;
16231 0 : case 'o':
16232 0 : torture_numops = atoi(optarg);
16233 0 : break;
16234 0 : case 'd':
16235 0 : lp_set_cmdline("log level", optarg);
16236 0 : break;
16237 0 : case 'O':
16238 0 : sockops = optarg;
16239 0 : break;
16240 0 : case 'L':
16241 0 : use_oplocks = True;
16242 0 : break;
16243 52 : case 'l':
16244 52 : local_path = optarg;
16245 52 : break;
16246 0 : case 'A':
16247 0 : torture_showall = True;
16248 0 : break;
16249 0 : case 'n':
16250 0 : fstrcpy(myname, optarg);
16251 0 : break;
16252 0 : case 'c':
16253 0 : client_txt = optarg;
16254 0 : break;
16255 0 : case 'e':
16256 0 : do_encrypt = true;
16257 0 : break;
16258 0 : case 'k':
16259 : #ifdef HAVE_KRB5
16260 0 : use_kerberos = True;
16261 : #else
16262 : d_printf("No kerberos support compiled in\n");
16263 : exit(1);
16264 : #endif
16265 0 : break;
16266 56 : case 'U':
16267 56 : gotuser = 1;
16268 56 : fstrcpy(username,optarg);
16269 56 : p = strchr_m(username,'%');
16270 56 : if (p) {
16271 56 : *p = 0;
16272 56 : fstrcpy(password, p+1);
16273 56 : gotpass = 1;
16274 : }
16275 56 : break;
16276 0 : case 'b':
16277 0 : fstrcpy(multishare_conn_fname, optarg);
16278 0 : use_multishare_conn = True;
16279 0 : break;
16280 0 : case 'B':
16281 0 : torture_blocksize = atoi(optarg);
16282 0 : break;
16283 0 : case 'f':
16284 0 : test_filename = SMB_STRDUP(optarg);
16285 0 : break;
16286 0 : default:
16287 0 : printf("Unknown option %c (%d)\n", (char)opt, opt);
16288 0 : usage();
16289 : }
16290 : }
16291 :
16292 56 : d_printf("using seed %d\n", seed);
16293 :
16294 56 : srandom(seed);
16295 :
16296 56 : if(use_kerberos && !gotuser) gotpass = True;
16297 :
16298 56 : while (!gotpass) {
16299 0 : char pwd[256] = {0};
16300 : int rc;
16301 :
16302 0 : rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
16303 0 : if (rc == 0) {
16304 0 : fstrcpy(password, pwd);
16305 0 : gotpass = 1;
16306 : }
16307 : }
16308 :
16309 56 : printf("host=%s share=%s user=%s myname=%s\n",
16310 : host, share, username, myname);
16311 :
16312 56 : torture_creds = cli_session_creds_init(frame,
16313 : username,
16314 : workgroup,
16315 : NULL, /* realm */
16316 : password,
16317 : use_kerberos,
16318 : false, /* fallback_after_kerberos */
16319 : false, /* use_ccache */
16320 : false); /* password_is_nt_hash */
16321 56 : if (torture_creds == NULL) {
16322 0 : d_printf("cli_session_creds_init() failed.\n");
16323 0 : exit(1);
16324 : }
16325 :
16326 56 : if (argc == optind) {
16327 0 : correct = run_test("ALL");
16328 : } else {
16329 112 : for (i=optind;i<argc;i++) {
16330 56 : if (!run_test(argv[i])) {
16331 6 : correct = False;
16332 : }
16333 : }
16334 : }
16335 :
16336 56 : TALLOC_FREE(frame);
16337 :
16338 56 : if (correct) {
16339 50 : return(0);
16340 : } else {
16341 6 : return(1);
16342 : }
16343 : }
|