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 : uint16_t vuid1, vuid2;
1439 : char buf[4];
1440 1 : bool ret = True;
1441 : NTSTATUS status;
1442 :
1443 1 : memset(buf, '\0', sizeof(buf));
1444 :
1445 1 : if (!torture_open_connection(&cli, 0)) {
1446 0 : return False;
1447 : }
1448 1 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1449 :
1450 1 : printf("starting tcontest\n");
1451 :
1452 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1453 :
1454 1 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1455 1 : if (!NT_STATUS_IS_OK(status)) {
1456 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1457 0 : return False;
1458 : }
1459 :
1460 1 : cnum1 = cli_state_get_tid(cli);
1461 1 : vuid1 = cli_state_get_uid(cli);
1462 :
1463 1 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1464 1 : if (!NT_STATUS_IS_OK(status)) {
1465 0 : printf("initial write failed (%s)", nt_errstr(status));
1466 0 : return False;
1467 : }
1468 :
1469 1 : orig_tcon = cli_state_save_tcon(cli);
1470 1 : if (orig_tcon == NULL) {
1471 0 : return false;
1472 : }
1473 :
1474 1 : status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1475 1 : if (!NT_STATUS_IS_OK(status)) {
1476 0 : printf("%s refused 2nd tree connect (%s)\n", host,
1477 : nt_errstr(status));
1478 0 : cli_state_restore_tcon(cli, orig_tcon);
1479 0 : cli_shutdown(cli);
1480 0 : return False;
1481 : }
1482 :
1483 1 : cnum2 = cli_state_get_tid(cli);
1484 1 : cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1485 1 : vuid2 = cli_state_get_uid(cli) + 1;
1486 :
1487 : /* try a write with the wrong tid */
1488 1 : cli_state_set_tid(cli, cnum2);
1489 :
1490 1 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1491 1 : if (NT_STATUS_IS_OK(status)) {
1492 0 : printf("* server allows write with wrong TID\n");
1493 0 : ret = False;
1494 : } else {
1495 1 : printf("server fails write with wrong TID : %s\n",
1496 : nt_errstr(status));
1497 : }
1498 :
1499 :
1500 : /* try a write with an invalid tid */
1501 1 : cli_state_set_tid(cli, cnum3);
1502 :
1503 1 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1504 1 : if (NT_STATUS_IS_OK(status)) {
1505 0 : printf("* server allows write with invalid TID\n");
1506 0 : ret = False;
1507 : } else {
1508 1 : printf("server fails write with invalid TID : %s\n",
1509 : nt_errstr(status));
1510 : }
1511 :
1512 : /* try a write with an invalid vuid */
1513 1 : cli_state_set_uid(cli, vuid2);
1514 1 : cli_state_set_tid(cli, cnum1);
1515 :
1516 1 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1517 1 : if (NT_STATUS_IS_OK(status)) {
1518 0 : printf("* server allows write with invalid VUID\n");
1519 0 : ret = False;
1520 : } else {
1521 1 : printf("server fails write with invalid VUID : %s\n",
1522 : nt_errstr(status));
1523 : }
1524 :
1525 1 : cli_state_set_tid(cli, cnum1);
1526 1 : cli_state_set_uid(cli, vuid1);
1527 :
1528 1 : status = cli_close(cli, fnum1);
1529 1 : if (!NT_STATUS_IS_OK(status)) {
1530 0 : printf("close failed (%s)\n", nt_errstr(status));
1531 0 : cli_state_restore_tcon(cli, orig_tcon);
1532 0 : cli_shutdown(cli);
1533 0 : return False;
1534 : }
1535 :
1536 1 : cli_state_set_tid(cli, cnum2);
1537 :
1538 1 : status = cli_tdis(cli);
1539 1 : if (!NT_STATUS_IS_OK(status)) {
1540 0 : printf("secondary tdis failed (%s)\n", nt_errstr(status));
1541 0 : cli_state_restore_tcon(cli, orig_tcon);
1542 0 : cli_shutdown(cli);
1543 0 : return False;
1544 : }
1545 :
1546 1 : cli_state_restore_tcon(cli, orig_tcon);
1547 :
1548 1 : cli_state_set_tid(cli, cnum1);
1549 :
1550 1 : if (!torture_close_connection(cli)) {
1551 0 : return False;
1552 : }
1553 :
1554 1 : return ret;
1555 : }
1556 :
1557 :
1558 : /*
1559 : checks for old style tcon support
1560 : */
1561 1 : static bool run_tcon2_test(int dummy)
1562 : {
1563 : static struct cli_state *cli;
1564 : uint16_t cnum, max_xmit;
1565 : char *service;
1566 : NTSTATUS status;
1567 :
1568 1 : if (!torture_open_connection(&cli, 0)) {
1569 0 : return False;
1570 : }
1571 1 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1572 :
1573 1 : printf("starting tcon2 test\n");
1574 :
1575 1 : if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1576 0 : return false;
1577 : }
1578 :
1579 1 : status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1580 :
1581 1 : SAFE_FREE(service);
1582 :
1583 1 : if (!NT_STATUS_IS_OK(status)) {
1584 1 : printf("tcon2 failed : %s\n", nt_errstr(status));
1585 : } else {
1586 0 : printf("tcon OK : max_xmit=%d cnum=%d\n",
1587 : (int)max_xmit, (int)cnum);
1588 : }
1589 :
1590 1 : if (!torture_close_connection(cli)) {
1591 0 : return False;
1592 : }
1593 :
1594 1 : printf("Passed tcon2 test\n");
1595 1 : return True;
1596 : }
1597 :
1598 10 : static bool tcon_devtest(struct cli_state *cli,
1599 : const char *myshare, const char *devtype,
1600 : const char *return_devtype,
1601 : NTSTATUS expected_error)
1602 : {
1603 : NTSTATUS status;
1604 : bool ret;
1605 :
1606 10 : status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1607 :
1608 10 : if (NT_STATUS_IS_OK(expected_error)) {
1609 4 : if (NT_STATUS_IS_OK(status)) {
1610 8 : if (return_devtype != NULL &&
1611 4 : strequal(cli->dev, return_devtype)) {
1612 4 : ret = True;
1613 : } else {
1614 0 : printf("tconX to share %s with type %s "
1615 : "succeeded but returned the wrong "
1616 : "device type (got [%s] but should have got [%s])\n",
1617 : myshare, devtype, cli->dev, return_devtype);
1618 0 : ret = False;
1619 : }
1620 : } else {
1621 0 : printf("tconX to share %s with type %s "
1622 : "should have succeeded but failed\n",
1623 : myshare, devtype);
1624 0 : ret = False;
1625 : }
1626 4 : cli_tdis(cli);
1627 : } else {
1628 6 : if (NT_STATUS_IS_OK(status)) {
1629 0 : printf("tconx to share %s with type %s "
1630 : "should have failed but succeeded\n",
1631 : myshare, devtype);
1632 0 : ret = False;
1633 : } else {
1634 6 : if (NT_STATUS_EQUAL(status, expected_error)) {
1635 6 : ret = True;
1636 : } else {
1637 0 : printf("Returned unexpected error\n");
1638 0 : ret = False;
1639 : }
1640 : }
1641 : }
1642 10 : return ret;
1643 : }
1644 :
1645 : /*
1646 : checks for correct tconX support
1647 : */
1648 1 : static bool run_tcon_devtype_test(int dummy)
1649 : {
1650 : static struct cli_state *cli1 = NULL;
1651 1 : int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1652 : NTSTATUS status;
1653 1 : bool ret = True;
1654 :
1655 1 : status = cli_full_connection_creds(&cli1,
1656 : myname,
1657 : host,
1658 : NULL, /* dest_ss */
1659 : port_to_use,
1660 : NULL, /* service */
1661 : NULL, /* service_type */
1662 : torture_creds,
1663 : flags);
1664 :
1665 1 : if (!NT_STATUS_IS_OK(status)) {
1666 0 : printf("could not open connection\n");
1667 0 : return False;
1668 : }
1669 :
1670 1 : if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1671 0 : ret = False;
1672 :
1673 1 : if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1674 0 : ret = False;
1675 :
1676 1 : if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1677 0 : ret = False;
1678 :
1679 1 : if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1680 0 : ret = False;
1681 :
1682 1 : if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1683 0 : ret = False;
1684 :
1685 1 : if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1686 0 : ret = False;
1687 :
1688 1 : if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1689 0 : ret = False;
1690 :
1691 1 : if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1692 0 : ret = False;
1693 :
1694 1 : if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1695 0 : ret = False;
1696 :
1697 1 : if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1698 0 : ret = False;
1699 :
1700 1 : cli_shutdown(cli1);
1701 :
1702 1 : if (ret)
1703 1 : printf("Passed tcondevtest\n");
1704 :
1705 1 : return ret;
1706 : }
1707 :
1708 :
1709 : /*
1710 : This test checks that
1711 :
1712 : 1) the server supports multiple locking contexts on the one SMB
1713 : connection, distinguished by PID.
1714 :
1715 : 2) the server correctly fails overlapping locks made by the same PID (this
1716 : goes against POSIX behaviour, which is why it is tricky to implement)
1717 :
1718 : 3) the server denies unlock requests by an incorrect client PID
1719 : */
1720 1 : static bool run_locktest2(int dummy)
1721 : {
1722 : static struct cli_state *cli;
1723 1 : const char *fname = "\\lockt2.lck";
1724 : uint16_t fnum1, fnum2, fnum3;
1725 1 : bool correct = True;
1726 : NTSTATUS status;
1727 :
1728 1 : if (!torture_open_connection(&cli, 0)) {
1729 0 : return False;
1730 : }
1731 :
1732 1 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1733 :
1734 1 : printf("starting locktest2\n");
1735 :
1736 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1737 :
1738 1 : cli_setpid(cli, 1);
1739 :
1740 1 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1741 1 : if (!NT_STATUS_IS_OK(status)) {
1742 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1743 0 : return False;
1744 : }
1745 :
1746 1 : status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1747 1 : if (!NT_STATUS_IS_OK(status)) {
1748 0 : printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1749 0 : return False;
1750 : }
1751 :
1752 1 : cli_setpid(cli, 2);
1753 :
1754 1 : status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1755 1 : if (!NT_STATUS_IS_OK(status)) {
1756 0 : printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1757 0 : return False;
1758 : }
1759 :
1760 1 : cli_setpid(cli, 1);
1761 :
1762 1 : status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1763 1 : if (!NT_STATUS_IS_OK(status)) {
1764 0 : printf("lock1 failed (%s)\n", nt_errstr(status));
1765 0 : return false;
1766 : }
1767 :
1768 1 : status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1769 1 : if (NT_STATUS_IS_OK(status)) {
1770 0 : printf("WRITE lock1 succeeded! This is a locking bug\n");
1771 0 : correct = false;
1772 : } else {
1773 1 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1774 1 : NT_STATUS_LOCK_NOT_GRANTED)) {
1775 0 : return false;
1776 : }
1777 : }
1778 :
1779 1 : status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1780 1 : if (NT_STATUS_IS_OK(status)) {
1781 0 : printf("WRITE lock2 succeeded! This is a locking bug\n");
1782 0 : correct = false;
1783 : } else {
1784 1 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1785 1 : NT_STATUS_LOCK_NOT_GRANTED)) {
1786 0 : return false;
1787 : }
1788 : }
1789 :
1790 1 : status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1791 1 : if (NT_STATUS_IS_OK(status)) {
1792 0 : printf("READ lock2 succeeded! This is a locking bug\n");
1793 0 : correct = false;
1794 : } else {
1795 1 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1796 1 : NT_STATUS_FILE_LOCK_CONFLICT)) {
1797 0 : return false;
1798 : }
1799 : }
1800 :
1801 1 : status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1802 1 : if (!NT_STATUS_IS_OK(status)) {
1803 0 : printf("lock at 100 failed (%s)\n", nt_errstr(status));
1804 : }
1805 1 : cli_setpid(cli, 2);
1806 1 : if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1807 0 : printf("unlock at 100 succeeded! This is a locking bug\n");
1808 0 : correct = False;
1809 : }
1810 :
1811 1 : status = cli_unlock(cli, fnum1, 0, 4);
1812 1 : if (NT_STATUS_IS_OK(status)) {
1813 0 : printf("unlock1 succeeded! This is a locking bug\n");
1814 0 : correct = false;
1815 : } else {
1816 1 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1817 1 : NT_STATUS_RANGE_NOT_LOCKED)) {
1818 0 : return false;
1819 : }
1820 : }
1821 :
1822 1 : status = cli_unlock(cli, fnum1, 0, 8);
1823 1 : if (NT_STATUS_IS_OK(status)) {
1824 0 : printf("unlock2 succeeded! This is a locking bug\n");
1825 0 : correct = false;
1826 : } else {
1827 1 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1828 1 : NT_STATUS_RANGE_NOT_LOCKED)) {
1829 0 : return false;
1830 : }
1831 : }
1832 :
1833 1 : status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1834 1 : if (NT_STATUS_IS_OK(status)) {
1835 0 : printf("lock3 succeeded! This is a locking bug\n");
1836 0 : correct = false;
1837 : } else {
1838 1 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1839 1 : NT_STATUS_LOCK_NOT_GRANTED)) {
1840 0 : return false;
1841 : }
1842 : }
1843 :
1844 1 : cli_setpid(cli, 1);
1845 :
1846 1 : status = cli_close(cli, fnum1);
1847 1 : if (!NT_STATUS_IS_OK(status)) {
1848 0 : printf("close1 failed (%s)\n", nt_errstr(status));
1849 0 : return False;
1850 : }
1851 :
1852 1 : status = cli_close(cli, fnum2);
1853 1 : if (!NT_STATUS_IS_OK(status)) {
1854 0 : printf("close2 failed (%s)\n", nt_errstr(status));
1855 0 : return False;
1856 : }
1857 :
1858 1 : status = cli_close(cli, fnum3);
1859 1 : if (!NT_STATUS_IS_OK(status)) {
1860 0 : printf("close3 failed (%s)\n", nt_errstr(status));
1861 0 : return False;
1862 : }
1863 :
1864 1 : if (!torture_close_connection(cli)) {
1865 0 : correct = False;
1866 : }
1867 :
1868 1 : printf("locktest2 finished\n");
1869 :
1870 1 : return correct;
1871 : }
1872 :
1873 :
1874 : /*
1875 : This test checks that
1876 :
1877 : 1) the server supports the full offset range in lock requests
1878 : */
1879 1 : static bool run_locktest3(int dummy)
1880 : {
1881 : static struct cli_state *cli1, *cli2;
1882 1 : const char *fname = "\\lockt3.lck";
1883 : uint16_t fnum1, fnum2;
1884 : int i;
1885 : uint32_t offset;
1886 1 : bool correct = True;
1887 : NTSTATUS status;
1888 :
1889 : #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1890 :
1891 1 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1892 0 : return False;
1893 : }
1894 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
1895 1 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
1896 :
1897 1 : printf("starting locktest3\n");
1898 :
1899 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1900 :
1901 1 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1902 : &fnum1);
1903 1 : if (!NT_STATUS_IS_OK(status)) {
1904 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1905 0 : return False;
1906 : }
1907 :
1908 1 : status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1909 1 : if (!NT_STATUS_IS_OK(status)) {
1910 0 : printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1911 0 : return False;
1912 : }
1913 :
1914 101 : for (offset=i=0;i<torture_numops;i++) {
1915 100 : NEXT_OFFSET;
1916 :
1917 100 : status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1918 100 : if (!NT_STATUS_IS_OK(status)) {
1919 0 : printf("lock1 %d failed (%s)\n",
1920 : i,
1921 : nt_errstr(status));
1922 0 : return False;
1923 : }
1924 :
1925 100 : status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1926 100 : if (!NT_STATUS_IS_OK(status)) {
1927 0 : printf("lock2 %d failed (%s)\n",
1928 : i,
1929 : nt_errstr(status));
1930 0 : return False;
1931 : }
1932 : }
1933 :
1934 101 : for (offset=i=0;i<torture_numops;i++) {
1935 100 : NEXT_OFFSET;
1936 :
1937 100 : status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1938 100 : if (NT_STATUS_IS_OK(status)) {
1939 0 : printf("error: lock1 %d succeeded!\n", i);
1940 0 : return False;
1941 : }
1942 :
1943 100 : status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1944 100 : if (NT_STATUS_IS_OK(status)) {
1945 0 : printf("error: lock2 %d succeeded!\n", i);
1946 0 : return False;
1947 : }
1948 :
1949 100 : status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1950 100 : if (NT_STATUS_IS_OK(status)) {
1951 0 : printf("error: lock3 %d succeeded!\n", i);
1952 0 : return False;
1953 : }
1954 :
1955 100 : status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1956 100 : if (NT_STATUS_IS_OK(status)) {
1957 0 : printf("error: lock4 %d succeeded!\n", i);
1958 0 : return False;
1959 : }
1960 : }
1961 :
1962 101 : for (offset=i=0;i<torture_numops;i++) {
1963 100 : NEXT_OFFSET;
1964 :
1965 100 : status = cli_unlock(cli1, fnum1, offset-1, 1);
1966 100 : if (!NT_STATUS_IS_OK(status)) {
1967 0 : printf("unlock1 %d failed (%s)\n",
1968 : i,
1969 : nt_errstr(status));
1970 0 : return False;
1971 : }
1972 :
1973 100 : status = cli_unlock(cli2, fnum2, offset-2, 1);
1974 100 : if (!NT_STATUS_IS_OK(status)) {
1975 0 : printf("unlock2 %d failed (%s)\n",
1976 : i,
1977 : nt_errstr(status));
1978 0 : return False;
1979 : }
1980 : }
1981 :
1982 1 : status = cli_close(cli1, fnum1);
1983 1 : if (!NT_STATUS_IS_OK(status)) {
1984 0 : printf("close1 failed (%s)\n", nt_errstr(status));
1985 0 : return False;
1986 : }
1987 :
1988 1 : status = cli_close(cli2, fnum2);
1989 1 : if (!NT_STATUS_IS_OK(status)) {
1990 0 : printf("close2 failed (%s)\n", nt_errstr(status));
1991 0 : return False;
1992 : }
1993 :
1994 1 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1995 1 : if (!NT_STATUS_IS_OK(status)) {
1996 0 : printf("unlink failed (%s)\n", nt_errstr(status));
1997 0 : return False;
1998 : }
1999 :
2000 1 : if (!torture_close_connection(cli1)) {
2001 0 : correct = False;
2002 : }
2003 :
2004 1 : if (!torture_close_connection(cli2)) {
2005 0 : correct = False;
2006 : }
2007 :
2008 1 : printf("finished locktest3\n");
2009 :
2010 1 : return correct;
2011 : }
2012 :
2013 8 : static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
2014 : char *buf, off_t offset, size_t size,
2015 : size_t *nread, size_t expect)
2016 : {
2017 : NTSTATUS status;
2018 : size_t l_nread;
2019 :
2020 8 : status = cli_read(cli, fnum, buf, offset, size, &l_nread);
2021 :
2022 8 : if(!NT_STATUS_IS_OK(status)) {
2023 4 : return false;
2024 4 : } else if (l_nread != expect) {
2025 0 : return false;
2026 : }
2027 :
2028 4 : if (nread) {
2029 0 : *nread = l_nread;
2030 : }
2031 :
2032 4 : return true;
2033 : }
2034 :
2035 : #define EXPECTED(ret, v) if ((ret) != (v)) { \
2036 : printf("** "); correct = False; \
2037 : }
2038 :
2039 : /*
2040 : looks at overlapping locks
2041 : */
2042 1 : static bool run_locktest4(int dummy)
2043 : {
2044 : static struct cli_state *cli1, *cli2;
2045 1 : const char *fname = "\\lockt4.lck";
2046 : uint16_t fnum1, fnum2, f;
2047 : bool ret;
2048 : char buf[1000];
2049 1 : bool correct = True;
2050 : NTSTATUS status;
2051 :
2052 1 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2053 0 : return False;
2054 : }
2055 :
2056 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2057 1 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
2058 :
2059 1 : printf("starting locktest4\n");
2060 :
2061 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2062 :
2063 1 : cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2064 1 : cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2065 :
2066 1 : memset(buf, 0, sizeof(buf));
2067 :
2068 1 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2069 : NULL);
2070 1 : if (!NT_STATUS_IS_OK(status)) {
2071 0 : printf("Failed to create file: %s\n", nt_errstr(status));
2072 0 : correct = False;
2073 0 : goto fail;
2074 : }
2075 :
2076 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2077 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
2078 1 : EXPECTED(ret, False);
2079 1 : printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2080 :
2081 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2082 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2083 1 : EXPECTED(ret, True);
2084 1 : printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2085 :
2086 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2087 1 : NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2088 1 : EXPECTED(ret, False);
2089 1 : printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2090 :
2091 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2092 1 : NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2093 1 : EXPECTED(ret, True);
2094 1 : printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2095 :
2096 2 : ret = (cli_setpid(cli1, 1),
2097 2 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2098 1 : (cli_setpid(cli1, 2),
2099 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2100 1 : EXPECTED(ret, False);
2101 1 : printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2102 :
2103 2 : ret = (cli_setpid(cli1, 1),
2104 2 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2105 1 : (cli_setpid(cli1, 2),
2106 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2107 1 : EXPECTED(ret, True);
2108 1 : printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2109 :
2110 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2111 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2112 1 : EXPECTED(ret, True);
2113 1 : printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2114 :
2115 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2116 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2117 1 : EXPECTED(ret, False);
2118 1 : printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2119 :
2120 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2121 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2122 1 : EXPECTED(ret, False);
2123 1 : printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2124 :
2125 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2126 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2127 1 : EXPECTED(ret, True);
2128 1 : printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2129 :
2130 2 : ret = (cli_setpid(cli1, 1),
2131 2 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2132 1 : (cli_setpid(cli1, 2),
2133 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2134 1 : EXPECTED(ret, False);
2135 1 : printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2136 :
2137 3 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2138 2 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2139 1 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2140 1 : EXPECTED(ret, False);
2141 1 : printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2142 :
2143 :
2144 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2145 1 : test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2146 1 : EXPECTED(ret, False);
2147 1 : printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2148 :
2149 1 : status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2150 1 : ret = NT_STATUS_IS_OK(status);
2151 1 : if (ret) {
2152 1 : status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2153 : NULL);
2154 1 : ret = NT_STATUS_IS_OK(status);
2155 : }
2156 1 : EXPECTED(ret, False);
2157 1 : printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2158 :
2159 :
2160 3 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2161 2 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2162 3 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2163 1 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2164 1 : EXPECTED(ret, True);
2165 1 : printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2166 :
2167 :
2168 3 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2169 2 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2170 2 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2171 2 : test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2172 1 : !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2173 2 : 150, 4, NULL))) &&
2174 1 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2175 1 : EXPECTED(ret, True);
2176 1 : printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2177 :
2178 3 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2179 2 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2180 1 : NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2181 2 : 160, 4, NULL)) &&
2182 1 : test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2183 1 : EXPECTED(ret, True);
2184 1 : printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2185 :
2186 3 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2187 2 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2188 1 : NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2189 2 : 170, 4, NULL)) &&
2190 1 : test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2191 1 : EXPECTED(ret, True);
2192 1 : printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2193 :
2194 3 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2195 2 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2196 2 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2197 1 : !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2198 2 : 190, 4, NULL)) &&
2199 1 : test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2200 1 : EXPECTED(ret, True);
2201 1 : printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2202 :
2203 1 : cli_close(cli1, fnum1);
2204 1 : cli_close(cli2, fnum2);
2205 1 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2206 1 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2207 3 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2208 2 : NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2209 2 : NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2210 3 : NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2211 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2212 1 : cli_close(cli1, f);
2213 1 : cli_close(cli1, fnum1);
2214 1 : EXPECTED(ret, True);
2215 1 : printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2216 :
2217 1 : fail:
2218 1 : cli_close(cli1, fnum1);
2219 1 : cli_close(cli2, fnum2);
2220 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2221 1 : torture_close_connection(cli1);
2222 1 : torture_close_connection(cli2);
2223 :
2224 1 : printf("finished locktest4\n");
2225 1 : return correct;
2226 : }
2227 :
2228 : /*
2229 : looks at lock upgrade/downgrade.
2230 : */
2231 1 : static bool run_locktest5(int dummy)
2232 : {
2233 : static struct cli_state *cli1, *cli2;
2234 1 : const char *fname = "\\lockt5.lck";
2235 : uint16_t fnum1, fnum2, fnum3;
2236 : bool ret;
2237 : char buf[1000];
2238 1 : bool correct = True;
2239 : NTSTATUS status;
2240 :
2241 1 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2242 0 : return False;
2243 : }
2244 :
2245 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2246 1 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
2247 :
2248 1 : printf("starting locktest5\n");
2249 :
2250 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2251 :
2252 1 : cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2253 1 : cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2254 1 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2255 :
2256 1 : memset(buf, 0, sizeof(buf));
2257 :
2258 1 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2259 : NULL);
2260 1 : if (!NT_STATUS_IS_OK(status)) {
2261 0 : printf("Failed to create file: %s\n", nt_errstr(status));
2262 0 : correct = False;
2263 0 : goto fail;
2264 : }
2265 :
2266 : /* Check for NT bug... */
2267 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2268 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2269 1 : cli_close(cli1, fnum1);
2270 1 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2271 1 : status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2272 1 : ret = NT_STATUS_IS_OK(status);
2273 1 : EXPECTED(ret, True);
2274 1 : printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2275 1 : cli_close(cli1, fnum1);
2276 1 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2277 1 : cli_unlock(cli1, fnum3, 0, 1);
2278 :
2279 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2280 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2281 1 : EXPECTED(ret, True);
2282 1 : printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2283 :
2284 1 : status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2285 1 : ret = NT_STATUS_IS_OK(status);
2286 1 : EXPECTED(ret, False);
2287 :
2288 1 : printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2289 :
2290 : /* Unlock the process 2 lock. */
2291 1 : cli_unlock(cli2, fnum2, 0, 4);
2292 :
2293 1 : status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2294 1 : ret = NT_STATUS_IS_OK(status);
2295 1 : EXPECTED(ret, False);
2296 :
2297 1 : printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2298 :
2299 : /* Unlock the process 1 fnum3 lock. */
2300 1 : cli_unlock(cli1, fnum3, 0, 4);
2301 :
2302 : /* Stack 2 more locks here. */
2303 2 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2304 1 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2305 :
2306 1 : EXPECTED(ret, True);
2307 1 : printf("the same process %s stack read locks\n", ret?"can":"cannot");
2308 :
2309 : /* Unlock the first process lock, then check this was the WRITE lock that was
2310 : removed. */
2311 :
2312 2 : ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2313 1 : NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2314 :
2315 1 : EXPECTED(ret, True);
2316 1 : printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2317 :
2318 : /* Unlock the process 2 lock. */
2319 1 : cli_unlock(cli2, fnum2, 0, 4);
2320 :
2321 : /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2322 :
2323 3 : ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2324 2 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2325 1 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2326 :
2327 1 : EXPECTED(ret, True);
2328 1 : printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2329 :
2330 : /* Ensure the next unlock fails. */
2331 1 : ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2332 1 : EXPECTED(ret, False);
2333 1 : printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2334 :
2335 : /* Ensure connection 2 can get a write lock. */
2336 1 : status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2337 1 : ret = NT_STATUS_IS_OK(status);
2338 1 : EXPECTED(ret, True);
2339 :
2340 1 : printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2341 :
2342 :
2343 1 : fail:
2344 1 : cli_close(cli1, fnum1);
2345 1 : cli_close(cli2, fnum2);
2346 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2347 1 : if (!torture_close_connection(cli1)) {
2348 0 : correct = False;
2349 : }
2350 1 : if (!torture_close_connection(cli2)) {
2351 0 : correct = False;
2352 : }
2353 :
2354 1 : printf("finished locktest5\n");
2355 :
2356 1 : return correct;
2357 : }
2358 :
2359 : /*
2360 : tries the unusual lockingX locktype bits
2361 : */
2362 1 : static bool run_locktest6(int dummy)
2363 : {
2364 : static struct cli_state *cli;
2365 1 : const char *fname[1] = { "\\lock6.txt" };
2366 : int i;
2367 : uint16_t fnum;
2368 : NTSTATUS status;
2369 :
2370 1 : if (!torture_open_connection(&cli, 0)) {
2371 0 : return False;
2372 : }
2373 :
2374 1 : smbXcli_conn_set_sockopt(cli->conn, sockops);
2375 :
2376 1 : printf("starting locktest6\n");
2377 :
2378 2 : for (i=0;i<1;i++) {
2379 1 : printf("Testing %s\n", fname[i]);
2380 :
2381 1 : cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2382 :
2383 1 : cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2384 1 : status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2385 1 : cli_close(cli, fnum);
2386 1 : printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2387 :
2388 1 : cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2389 1 : status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2390 1 : cli_close(cli, fnum);
2391 1 : printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2392 :
2393 1 : cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2394 : }
2395 :
2396 1 : torture_close_connection(cli);
2397 :
2398 1 : printf("finished locktest6\n");
2399 1 : return True;
2400 : }
2401 :
2402 1 : static bool run_locktest7(int dummy)
2403 : {
2404 : struct cli_state *cli1;
2405 1 : const char *fname = "\\lockt7.lck";
2406 : uint16_t fnum1;
2407 : char buf[200];
2408 1 : bool correct = False;
2409 : size_t nread;
2410 : NTSTATUS status;
2411 :
2412 1 : if (!torture_open_connection(&cli1, 0)) {
2413 0 : return False;
2414 : }
2415 :
2416 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2417 :
2418 1 : printf("starting locktest7\n");
2419 :
2420 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2421 :
2422 1 : cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2423 :
2424 1 : memset(buf, 0, sizeof(buf));
2425 :
2426 1 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2427 : NULL);
2428 1 : if (!NT_STATUS_IS_OK(status)) {
2429 0 : printf("Failed to create file: %s\n", nt_errstr(status));
2430 0 : goto fail;
2431 : }
2432 :
2433 1 : cli_setpid(cli1, 1);
2434 :
2435 1 : status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2436 1 : if (!NT_STATUS_IS_OK(status)) {
2437 0 : printf("Unable to apply read lock on range 130:4, "
2438 : "error was %s\n", nt_errstr(status));
2439 0 : goto fail;
2440 : } else {
2441 1 : printf("pid1 successfully locked range 130:4 for READ\n");
2442 : }
2443 :
2444 1 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2445 1 : if (!NT_STATUS_IS_OK(status)) {
2446 0 : printf("pid1 unable to read the range 130:4, error was %s\n",
2447 : nt_errstr(status));
2448 0 : goto fail;
2449 1 : } else if (nread != 4) {
2450 0 : printf("pid1 unable to read the range 130:4, "
2451 : "recv %ld req %d\n", (unsigned long)nread, 4);
2452 0 : goto fail;
2453 : } else {
2454 1 : printf("pid1 successfully read the range 130:4\n");
2455 : }
2456 :
2457 1 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2458 1 : if (!NT_STATUS_IS_OK(status)) {
2459 1 : printf("pid1 unable to write to the range 130:4, error was "
2460 : "%s\n", nt_errstr(status));
2461 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2462 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2463 0 : goto fail;
2464 : }
2465 : } else {
2466 0 : printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2467 0 : goto fail;
2468 : }
2469 :
2470 1 : cli_setpid(cli1, 2);
2471 :
2472 1 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2473 1 : if (!NT_STATUS_IS_OK(status)) {
2474 0 : printf("pid2 unable to read the range 130:4, error was %s\n",
2475 : nt_errstr(status));
2476 0 : goto fail;
2477 1 : } else if (nread != 4) {
2478 0 : printf("pid2 unable to read the range 130:4, "
2479 : "recv %ld req %d\n", (unsigned long)nread, 4);
2480 0 : goto fail;
2481 : } else {
2482 1 : printf("pid2 successfully read the range 130:4\n");
2483 : }
2484 :
2485 1 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2486 1 : if (!NT_STATUS_IS_OK(status)) {
2487 1 : printf("pid2 unable to write to the range 130:4, error was "
2488 : "%s\n", nt_errstr(status));
2489 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2490 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2491 0 : goto fail;
2492 : }
2493 : } else {
2494 0 : printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2495 0 : goto fail;
2496 : }
2497 :
2498 1 : cli_setpid(cli1, 1);
2499 1 : cli_unlock(cli1, fnum1, 130, 4);
2500 :
2501 1 : status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2502 1 : if (!NT_STATUS_IS_OK(status)) {
2503 0 : printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2504 0 : goto fail;
2505 : } else {
2506 1 : printf("pid1 successfully locked range 130:4 for WRITE\n");
2507 : }
2508 :
2509 1 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2510 1 : if (!NT_STATUS_IS_OK(status)) {
2511 0 : printf("pid1 unable to read the range 130:4, error was %s\n",
2512 : nt_errstr(status));
2513 0 : goto fail;
2514 1 : } else if (nread != 4) {
2515 0 : printf("pid1 unable to read the range 130:4, "
2516 : "recv %ld req %d\n", (unsigned long)nread, 4);
2517 0 : goto fail;
2518 : } else {
2519 1 : printf("pid1 successfully read the range 130:4\n");
2520 : }
2521 :
2522 1 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2523 1 : if (!NT_STATUS_IS_OK(status)) {
2524 0 : printf("pid1 unable to write to the range 130:4, error was "
2525 : "%s\n", nt_errstr(status));
2526 0 : goto fail;
2527 : } else {
2528 1 : printf("pid1 successfully wrote to the range 130:4\n");
2529 : }
2530 :
2531 1 : cli_setpid(cli1, 2);
2532 :
2533 1 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2534 1 : if (!NT_STATUS_IS_OK(status)) {
2535 1 : printf("pid2 unable to read the range 130:4, error was "
2536 : "%s\n", nt_errstr(status));
2537 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2538 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2539 0 : goto fail;
2540 : }
2541 : } else {
2542 0 : printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2543 : (unsigned long)nread);
2544 0 : goto fail;
2545 : }
2546 :
2547 1 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2548 1 : if (!NT_STATUS_IS_OK(status)) {
2549 1 : printf("pid2 unable to write to the range 130:4, error was "
2550 : "%s\n", nt_errstr(status));
2551 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2552 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2553 0 : goto fail;
2554 : }
2555 : } else {
2556 0 : printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2557 0 : goto fail;
2558 : }
2559 :
2560 1 : cli_unlock(cli1, fnum1, 130, 0);
2561 1 : correct = True;
2562 :
2563 1 : fail:
2564 1 : cli_close(cli1, fnum1);
2565 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2566 1 : torture_close_connection(cli1);
2567 :
2568 1 : printf("finished locktest7\n");
2569 1 : return correct;
2570 : }
2571 :
2572 : /*
2573 : * This demonstrates a problem with our use of GPFS share modes: A file
2574 : * descriptor sitting in the pending close queue holding a GPFS share mode
2575 : * blocks opening a file another time. Happens with Word 2007 temp files.
2576 : * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2577 : * open is denied with NT_STATUS_SHARING_VIOLATION.
2578 : */
2579 :
2580 0 : static bool run_locktest8(int dummy)
2581 : {
2582 : struct cli_state *cli1;
2583 0 : const char *fname = "\\lockt8.lck";
2584 : uint16_t fnum1, fnum2;
2585 : char buf[200];
2586 0 : bool correct = False;
2587 : NTSTATUS status;
2588 :
2589 0 : if (!torture_open_connection(&cli1, 0)) {
2590 0 : return False;
2591 : }
2592 :
2593 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2594 :
2595 0 : printf("starting locktest8\n");
2596 :
2597 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2598 :
2599 0 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2600 : &fnum1);
2601 0 : if (!NT_STATUS_IS_OK(status)) {
2602 0 : d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2603 0 : return false;
2604 : }
2605 :
2606 0 : memset(buf, 0, sizeof(buf));
2607 :
2608 0 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2609 0 : if (!NT_STATUS_IS_OK(status)) {
2610 0 : d_fprintf(stderr, "cli_openx second time returned %s\n",
2611 : nt_errstr(status));
2612 0 : goto fail;
2613 : }
2614 :
2615 0 : status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2616 0 : if (!NT_STATUS_IS_OK(status)) {
2617 0 : printf("Unable to apply read lock on range 1:1, error was "
2618 : "%s\n", nt_errstr(status));
2619 0 : goto fail;
2620 : }
2621 :
2622 0 : status = cli_close(cli1, fnum1);
2623 0 : if (!NT_STATUS_IS_OK(status)) {
2624 0 : d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2625 0 : goto fail;
2626 : }
2627 :
2628 0 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2629 0 : if (!NT_STATUS_IS_OK(status)) {
2630 0 : d_fprintf(stderr, "cli_openx third time returned %s\n",
2631 : nt_errstr(status));
2632 0 : goto fail;
2633 : }
2634 :
2635 0 : correct = true;
2636 :
2637 0 : fail:
2638 0 : cli_close(cli1, fnum1);
2639 0 : cli_close(cli1, fnum2);
2640 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2641 0 : torture_close_connection(cli1);
2642 :
2643 0 : printf("finished locktest8\n");
2644 0 : return correct;
2645 : }
2646 :
2647 : /*
2648 : * This test is designed to be run in conjunction with
2649 : * external NFS or POSIX locks taken in the filesystem.
2650 : * It checks that the smbd server will block until the
2651 : * lock is released and then acquire it. JRA.
2652 : */
2653 :
2654 : static bool got_alarm;
2655 : static struct cli_state *alarm_cli;
2656 :
2657 0 : static void alarm_handler(int dummy)
2658 : {
2659 0 : got_alarm = True;
2660 0 : }
2661 :
2662 0 : static void alarm_handler_parent(int dummy)
2663 : {
2664 0 : smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2665 0 : }
2666 :
2667 0 : static void do_local_lock(const char *fname, int read_fd, int write_fd)
2668 : {
2669 : int fd;
2670 0 : char c = '\0';
2671 : struct flock lock;
2672 0 : const char *local_pathname = NULL;
2673 : int ret;
2674 :
2675 0 : local_pathname = talloc_asprintf(talloc_tos(),
2676 : "%s/%s", local_path, fname);
2677 0 : if (!local_pathname) {
2678 0 : printf("child: alloc fail\n");
2679 0 : exit(1);
2680 : }
2681 :
2682 0 : unlink(local_pathname);
2683 0 : fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2684 0 : if (fd == -1) {
2685 0 : printf("child: open of %s failed %s.\n",
2686 0 : local_pathname, strerror(errno));
2687 0 : exit(1);
2688 : }
2689 :
2690 : /* Now take a fcntl lock. */
2691 0 : lock.l_type = F_WRLCK;
2692 0 : lock.l_whence = SEEK_SET;
2693 0 : lock.l_start = 0;
2694 0 : lock.l_len = 4;
2695 0 : lock.l_pid = getpid();
2696 :
2697 0 : ret = fcntl(fd,F_SETLK,&lock);
2698 0 : if (ret == -1) {
2699 0 : printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2700 0 : local_pathname, strerror(errno));
2701 0 : exit(1);
2702 : } else {
2703 0 : printf("child: got lock 0:4 on file %s.\n",
2704 : local_pathname );
2705 0 : fflush(stdout);
2706 : }
2707 :
2708 0 : CatchSignal(SIGALRM, alarm_handler);
2709 0 : alarm(5);
2710 : /* Signal the parent. */
2711 0 : if (write(write_fd, &c, 1) != 1) {
2712 0 : printf("child: start signal fail %s.\n",
2713 0 : strerror(errno));
2714 0 : exit(1);
2715 : }
2716 0 : alarm(0);
2717 :
2718 0 : alarm(10);
2719 : /* Wait for the parent to be ready. */
2720 0 : if (read(read_fd, &c, 1) != 1) {
2721 0 : printf("child: reply signal fail %s.\n",
2722 0 : strerror(errno));
2723 0 : exit(1);
2724 : }
2725 0 : alarm(0);
2726 :
2727 0 : sleep(5);
2728 0 : close(fd);
2729 0 : printf("child: released lock 0:4 on file %s.\n",
2730 : local_pathname );
2731 0 : fflush(stdout);
2732 0 : exit(0);
2733 : }
2734 :
2735 0 : static bool _run_locktest9X(const char *fname, int timeout)
2736 : {
2737 : struct cli_state *cli1;
2738 0 : char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2739 : uint16_t fnum;
2740 0 : bool correct = False;
2741 : int pipe_in[2], pipe_out[2];
2742 : pid_t child_pid;
2743 0 : char c = '\0';
2744 : int ret;
2745 : struct timeval start;
2746 : double seconds;
2747 : NTSTATUS status;
2748 :
2749 0 : printf("starting locktest9X: %s\n", fname);
2750 :
2751 0 : if (local_path == NULL) {
2752 0 : d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2753 0 : return false;
2754 : }
2755 :
2756 0 : if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2757 0 : return false;
2758 : }
2759 :
2760 0 : child_pid = fork();
2761 0 : if (child_pid == -1) {
2762 0 : return false;
2763 : }
2764 :
2765 0 : if (child_pid == 0) {
2766 : /* Child. */
2767 0 : do_local_lock(fname, pipe_out[0], pipe_in[1]);
2768 0 : exit(0);
2769 : }
2770 :
2771 0 : close(pipe_out[0]);
2772 0 : close(pipe_in[1]);
2773 0 : pipe_out[0] = -1;
2774 0 : pipe_in[1] = -1;
2775 :
2776 : /* Parent. */
2777 0 : ret = read(pipe_in[0], &c, 1);
2778 0 : if (ret != 1) {
2779 0 : d_fprintf(stderr, "failed to read start signal from child. %s\n",
2780 0 : strerror(errno));
2781 0 : return false;
2782 : }
2783 :
2784 0 : if (!torture_open_connection(&cli1, 0)) {
2785 0 : return false;
2786 : }
2787 :
2788 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2789 :
2790 0 : status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2791 : &fnum);
2792 0 : if (!NT_STATUS_IS_OK(status)) {
2793 0 : d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2794 0 : return false;
2795 : }
2796 :
2797 : /* Ensure the child has the lock. */
2798 0 : status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2799 0 : if (NT_STATUS_IS_OK(status)) {
2800 0 : d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2801 0 : goto fail;
2802 : } else {
2803 0 : d_printf("Child has the lock.\n");
2804 : }
2805 :
2806 : /* Tell the child to wait 5 seconds then exit. */
2807 0 : ret = write(pipe_out[1], &c, 1);
2808 0 : if (ret != 1) {
2809 0 : d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2810 0 : strerror(errno));
2811 0 : goto fail;
2812 : }
2813 :
2814 : /* Wait 20 seconds for the lock. */
2815 0 : alarm_cli = cli1;
2816 0 : CatchSignal(SIGALRM, alarm_handler_parent);
2817 0 : alarm(20);
2818 :
2819 0 : start = timeval_current();
2820 :
2821 0 : status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2822 0 : if (!NT_STATUS_IS_OK(status)) {
2823 0 : d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2824 : "%s\n", nt_errstr(status));
2825 0 : goto fail_nofd;
2826 : }
2827 0 : alarm(0);
2828 :
2829 0 : seconds = timeval_elapsed(&start);
2830 :
2831 0 : printf("Parent got the lock after %.2f seconds.\n",
2832 : seconds);
2833 :
2834 0 : status = cli_close(cli1, fnum);
2835 0 : if (!NT_STATUS_IS_OK(status)) {
2836 0 : d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2837 0 : goto fail;
2838 : }
2839 :
2840 0 : correct = true;
2841 :
2842 0 : fail:
2843 0 : cli_close(cli1, fnum);
2844 0 : torture_close_connection(cli1);
2845 :
2846 0 : fail_nofd:
2847 :
2848 0 : printf("finished locktest9X: %s\n", fname);
2849 0 : return correct;
2850 : }
2851 :
2852 0 : static bool run_locktest9a(int dummy)
2853 : {
2854 0 : return _run_locktest9X("lock9a.dat", -1);
2855 : }
2856 :
2857 0 : static bool run_locktest9b(int dummy)
2858 : {
2859 0 : return _run_locktest9X("lock9b.dat", 10000);
2860 : }
2861 :
2862 : struct locktest10_state {
2863 : bool ok;
2864 : bool done;
2865 : };
2866 :
2867 : static void locktest10_lockingx_done(struct tevent_req *subreq);
2868 : static void locktest10_read_andx_done(struct tevent_req *subreq);
2869 :
2870 1 : static bool run_locktest10(int dummy)
2871 : {
2872 1 : struct tevent_context *ev = NULL;
2873 1 : struct cli_state *cli1 = NULL;
2874 1 : struct cli_state *cli2 = NULL;
2875 1 : struct smb1_lock_element lck = { 0 };
2876 1 : struct tevent_req *reqs[2] = { NULL };
2877 1 : struct tevent_req *smbreqs[2] = { NULL };
2878 1 : const char fname[] = "\\lockt10.lck";
2879 : uint16_t fnum1, fnum2;
2880 1 : bool ret = false;
2881 : bool ok;
2882 1 : uint8_t data = 1;
2883 1 : struct locktest10_state state = { .ok = true };
2884 : NTSTATUS status;
2885 :
2886 1 : printf("starting locktest10\n");
2887 :
2888 1 : ev = samba_tevent_context_init(NULL);
2889 1 : if (ev == NULL) {
2890 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
2891 0 : goto done;
2892 : }
2893 :
2894 1 : ok = torture_open_connection(&cli1, 0);
2895 1 : if (!ok) {
2896 0 : goto done;
2897 : }
2898 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2899 :
2900 1 : ok = torture_open_connection(&cli2, 1);
2901 1 : if (!ok) {
2902 0 : goto done;
2903 : }
2904 1 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
2905 :
2906 1 : status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2907 1 : if (!NT_STATUS_IS_OK(status)) {
2908 0 : d_fprintf(stderr,
2909 : "cli_openx failed: %s\n",
2910 : nt_errstr(status));
2911 0 : goto done;
2912 : }
2913 :
2914 1 : status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2915 1 : if (!NT_STATUS_IS_OK(status)) {
2916 0 : d_fprintf(stderr,
2917 : "cli_writeall failed: %s\n",
2918 : nt_errstr(status));
2919 0 : goto done;
2920 : }
2921 :
2922 1 : status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2923 1 : if (!NT_STATUS_IS_OK(status)) {
2924 0 : d_fprintf(stderr,
2925 : "cli_openx failed: %s\n",
2926 : nt_errstr(status));
2927 0 : goto done;
2928 : }
2929 :
2930 1 : status = cli_locktype(
2931 : cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2932 1 : if (!NT_STATUS_IS_OK(status)) {
2933 0 : d_fprintf(stderr,
2934 : "cli_locktype failed: %s\n",
2935 : nt_errstr(status));
2936 0 : goto done;
2937 : }
2938 :
2939 1 : lck = (struct smb1_lock_element) {
2940 1 : .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2941 : };
2942 :
2943 1 : reqs[0] = cli_lockingx_create(
2944 : ev, /* mem_ctx */
2945 : ev, /* tevent_context */
2946 : cli1, /* cli */
2947 : fnum1, /* fnum */
2948 : LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
2949 : 0, /* newoplocklevel */
2950 : 1, /* timeout */
2951 : 0, /* num_unlocks */
2952 : NULL, /* unlocks */
2953 : 1, /* num_locks */
2954 : &lck, /* locks */
2955 : &smbreqs[0]); /* psmbreq */
2956 1 : if (reqs[0] == NULL) {
2957 0 : d_fprintf(stderr, "cli_lockingx_create failed\n");
2958 0 : goto done;
2959 : }
2960 1 : tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
2961 :
2962 1 : reqs[1] = cli_read_andx_create(
2963 : ev, /* mem_ctx */
2964 : ev, /* ev */
2965 : cli1, /* cli */
2966 : fnum1, /* fnum */
2967 : 0, /* offset */
2968 : 1, /* size */
2969 : &smbreqs[1]); /* psmbreq */
2970 1 : if (reqs[1] == NULL) {
2971 0 : d_fprintf(stderr, "cli_read_andx_create failed\n");
2972 0 : goto done;
2973 : }
2974 1 : tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
2975 :
2976 1 : status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
2977 1 : if (!NT_STATUS_IS_OK(status)) {
2978 0 : d_fprintf(stderr,
2979 : "smb1cli_req_chain_submit failed: %s\n",
2980 : nt_errstr(status));
2981 0 : goto done;
2982 : }
2983 :
2984 7 : while (!state.done) {
2985 5 : tevent_loop_once(ev);
2986 : }
2987 :
2988 1 : torture_close_connection(cli1);
2989 :
2990 1 : if (state.ok) {
2991 1 : ret = true;
2992 : }
2993 1 : done:
2994 1 : return ret;
2995 : }
2996 :
2997 1 : static void locktest10_lockingx_done(struct tevent_req *subreq)
2998 : {
2999 1 : struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3000 : NTSTATUS status;
3001 :
3002 1 : status = cli_lockingx_recv(subreq);
3003 1 : TALLOC_FREE(subreq);
3004 :
3005 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3006 0 : d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3007 0 : state->ok = false;
3008 : }
3009 1 : }
3010 :
3011 1 : static void locktest10_read_andx_done(struct tevent_req *subreq)
3012 : {
3013 1 : struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3014 1 : ssize_t received = -1;
3015 1 : uint8_t *rcvbuf = NULL;
3016 : NTSTATUS status;
3017 :
3018 1 : status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3019 :
3020 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
3021 0 : d_printf("cli_read_andx returned %s\n", nt_errstr(status));
3022 0 : state->ok = false;
3023 : }
3024 :
3025 1 : state->done = true;
3026 1 : TALLOC_FREE(subreq);
3027 1 : }
3028 :
3029 1 : static bool run_locktest11(int dummy)
3030 : {
3031 : struct cli_state *cli1;
3032 1 : const char *fname = "\\lockt11.lck";
3033 : NTSTATUS status;
3034 : uint16_t fnum;
3035 1 : bool ret = false;
3036 :
3037 1 : if (!torture_open_connection(&cli1, 0)) {
3038 0 : return false;
3039 : }
3040 :
3041 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
3042 :
3043 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3044 :
3045 1 : status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
3046 1 : if (!NT_STATUS_IS_OK(status)) {
3047 0 : d_fprintf(stderr,
3048 : "cli_openx returned %s\n",
3049 : nt_errstr(status));
3050 0 : return false;
3051 : }
3052 :
3053 : /*
3054 : * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3055 : * returns NT_STATUS_OK
3056 : */
3057 :
3058 1 : status = cli_lockingx(
3059 : cli1, /* cli */
3060 : fnum, /* fnum */
3061 : LOCKING_ANDX_CANCEL_LOCK, /* typeoflock */
3062 : 0, /* newoplocklevel */
3063 : 0, /* timeout */
3064 : 0, /* num_unlocks */
3065 : NULL, /* unlocks */
3066 : 0, /* num_locks */
3067 : NULL); /* locks */
3068 :
3069 1 : if (!NT_STATUS_IS_OK(status)) {
3070 1 : d_printf("cli_lockingX returned %s\n", nt_errstr(status));
3071 1 : goto fail;
3072 : }
3073 :
3074 0 : ret = true;
3075 1 : fail:
3076 1 : cli_close(cli1, fnum);
3077 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3078 :
3079 1 : return ret;
3080 : }
3081 :
3082 : struct deferred_close_state {
3083 : struct tevent_context *ev;
3084 : struct cli_state *cli;
3085 : uint16_t fnum;
3086 : };
3087 :
3088 : static void deferred_close_waited(struct tevent_req *subreq);
3089 : static void deferred_close_done(struct tevent_req *subreq);
3090 :
3091 1 : static struct tevent_req *deferred_close_send(
3092 : TALLOC_CTX *mem_ctx,
3093 : struct tevent_context *ev,
3094 : int wait_secs,
3095 : struct cli_state *cli,
3096 : uint16_t fnum)
3097 : {
3098 1 : struct tevent_req *req = NULL, *subreq = NULL;
3099 1 : struct deferred_close_state *state = NULL;
3100 1 : struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
3101 :
3102 1 : req = tevent_req_create(
3103 : mem_ctx, &state, struct deferred_close_state);
3104 1 : if (req == NULL) {
3105 0 : return NULL;
3106 : }
3107 1 : state->ev = ev;
3108 1 : state->cli = cli;
3109 1 : state->fnum = fnum;
3110 :
3111 1 : subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
3112 1 : if (tevent_req_nomem(subreq, req)) {
3113 0 : return tevent_req_post(req, ev);
3114 : }
3115 1 : tevent_req_set_callback(subreq, deferred_close_waited, req);
3116 1 : return req;
3117 : }
3118 :
3119 1 : static void deferred_close_waited(struct tevent_req *subreq)
3120 : {
3121 1 : struct tevent_req *req = tevent_req_callback_data(
3122 : subreq, struct tevent_req);
3123 1 : struct deferred_close_state *state = tevent_req_data(
3124 : req, struct deferred_close_state);
3125 : bool ok;
3126 :
3127 1 : ok = tevent_wakeup_recv(subreq);
3128 1 : TALLOC_FREE(subreq);
3129 1 : if (!ok) {
3130 0 : tevent_req_oom(req);
3131 0 : return;
3132 : }
3133 :
3134 1 : subreq = cli_close_send(state, state->ev, state->cli, state->fnum);
3135 1 : if (tevent_req_nomem(subreq, req)) {
3136 0 : return;
3137 : }
3138 1 : tevent_req_set_callback(subreq, deferred_close_done, req);
3139 : }
3140 :
3141 1 : static void deferred_close_done(struct tevent_req *subreq)
3142 : {
3143 1 : NTSTATUS status = cli_close_recv(subreq);
3144 1 : tevent_req_simple_finish_ntstatus(subreq, status);
3145 1 : }
3146 :
3147 1 : static NTSTATUS deferred_close_recv(struct tevent_req *req)
3148 : {
3149 1 : return tevent_req_simple_recv_ntstatus(req);
3150 : }
3151 :
3152 : struct lockread_state {
3153 : struct smb1_lock_element lck;
3154 : struct tevent_req *reqs[2];
3155 : struct tevent_req *smbreqs[2];
3156 : NTSTATUS lock_status;
3157 : NTSTATUS read_status;
3158 : uint8_t *readbuf;
3159 : };
3160 :
3161 : static void lockread_lockingx_done(struct tevent_req *subreq);
3162 : static void lockread_read_andx_done(struct tevent_req *subreq);
3163 :
3164 1 : static struct tevent_req *lockread_send(
3165 : TALLOC_CTX *mem_ctx,
3166 : struct tevent_context *ev,
3167 : struct cli_state *cli,
3168 : uint16_t fnum)
3169 : {
3170 1 : struct tevent_req *req = NULL;
3171 1 : struct lockread_state *state = NULL;
3172 : NTSTATUS status;
3173 :
3174 1 : req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3175 1 : if (req == NULL) {
3176 0 : return NULL;
3177 : }
3178 :
3179 2 : state->lck = (struct smb1_lock_element) {
3180 1 : .pid = cli_getpid(cli), .offset = 0, .length = 1,
3181 : };
3182 :
3183 2 : state->reqs[0] = cli_lockingx_create(
3184 : ev, /* mem_ctx */
3185 : ev, /* tevent_context */
3186 : cli, /* cli */
3187 : fnum, /* fnum */
3188 : LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3189 : 0, /* newoplocklevel */
3190 : 10000, /* timeout */
3191 : 0, /* num_unlocks */
3192 : NULL, /* unlocks */
3193 : 1, /* num_locks */
3194 1 : &state->lck, /* locks */
3195 1 : &state->smbreqs[0]); /* psmbreq */
3196 1 : if (tevent_req_nomem(state->reqs[0], req)) {
3197 0 : return tevent_req_post(req, ev);
3198 : }
3199 1 : tevent_req_set_callback(
3200 1 : state->reqs[0], lockread_lockingx_done, req);
3201 :
3202 1 : state->reqs[1] = cli_read_andx_create(
3203 : ev, /* mem_ctx */
3204 : ev, /* ev */
3205 : cli, /* cli */
3206 : fnum, /* fnum */
3207 : 0, /* offset */
3208 : 1, /* size */
3209 1 : &state->smbreqs[1]); /* psmbreq */
3210 1 : if (tevent_req_nomem(state->reqs[1], req)) {
3211 0 : return tevent_req_post(req, ev);
3212 : }
3213 1 : tevent_req_set_callback(
3214 1 : state->reqs[1], lockread_read_andx_done, req);
3215 :
3216 1 : status = smb1cli_req_chain_submit(state->smbreqs, 2);
3217 1 : if (tevent_req_nterror(req, status)) {
3218 0 : return tevent_req_post(req, ev);
3219 : }
3220 1 : return req;
3221 : }
3222 :
3223 1 : static void lockread_lockingx_done(struct tevent_req *subreq)
3224 : {
3225 1 : struct tevent_req *req = tevent_req_callback_data(
3226 : subreq, struct tevent_req);
3227 1 : struct lockread_state *state = tevent_req_data(
3228 : req, struct lockread_state);
3229 1 : state->lock_status = cli_lockingx_recv(subreq);
3230 1 : TALLOC_FREE(subreq);
3231 1 : d_fprintf(stderr,
3232 : "lockingx returned %s\n",
3233 : nt_errstr(state->lock_status));
3234 1 : }
3235 :
3236 1 : static void lockread_read_andx_done(struct tevent_req *subreq)
3237 : {
3238 1 : struct tevent_req *req = tevent_req_callback_data(
3239 : subreq, struct tevent_req);
3240 1 : struct lockread_state *state = tevent_req_data(
3241 : req, struct lockread_state);
3242 1 : ssize_t received = -1;
3243 1 : uint8_t *rcvbuf = NULL;
3244 :
3245 1 : state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3246 :
3247 1 : d_fprintf(stderr,
3248 : "read returned %s\n",
3249 : nt_errstr(state->read_status));
3250 :
3251 1 : if (!NT_STATUS_IS_OK(state->read_status)) {
3252 0 : TALLOC_FREE(subreq);
3253 0 : tevent_req_done(req);
3254 0 : return;
3255 : }
3256 :
3257 1 : if (received > 0) {
3258 1 : state->readbuf = talloc_memdup(state, rcvbuf, received);
3259 1 : TALLOC_FREE(subreq);
3260 1 : if (tevent_req_nomem(state->readbuf, req)) {
3261 0 : return;
3262 : }
3263 : }
3264 1 : TALLOC_FREE(subreq);
3265 1 : tevent_req_done(req);
3266 : }
3267 :
3268 1 : static NTSTATUS lockread_recv(
3269 : struct tevent_req *req,
3270 : NTSTATUS *lock_status,
3271 : NTSTATUS *read_status,
3272 : TALLOC_CTX *mem_ctx,
3273 : uint8_t **read_buf)
3274 : {
3275 1 : struct lockread_state *state = tevent_req_data(
3276 : req, struct lockread_state);
3277 : NTSTATUS status;
3278 :
3279 1 : if (tevent_req_is_nterror(req, &status)) {
3280 0 : return status;
3281 : }
3282 :
3283 1 : *lock_status = state->lock_status;
3284 1 : *read_status = state->read_status;
3285 1 : if (state->readbuf != NULL) {
3286 1 : *read_buf = talloc_move(mem_ctx, &state->readbuf);
3287 : } else {
3288 0 : *read_buf = NULL;
3289 : }
3290 :
3291 1 : return NT_STATUS_OK;
3292 : }
3293 :
3294 : struct lock12_state {
3295 : uint8_t dummy;
3296 : };
3297 :
3298 : static void lock12_closed(struct tevent_req *subreq);
3299 : static void lock12_read(struct tevent_req *subreq);
3300 :
3301 1 : static struct tevent_req *lock12_send(
3302 : TALLOC_CTX *mem_ctx,
3303 : struct tevent_context *ev,
3304 : struct cli_state *cli,
3305 : uint16_t fnum1,
3306 : uint16_t fnum2)
3307 : {
3308 1 : struct tevent_req *req = NULL, *subreq = NULL;
3309 1 : struct lock12_state *state = NULL;
3310 :
3311 1 : req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3312 1 : if (req == NULL) {
3313 0 : return NULL;
3314 : }
3315 :
3316 1 : subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3317 1 : if (tevent_req_nomem(subreq, req)) {
3318 0 : return tevent_req_post(req, ev);
3319 : }
3320 1 : tevent_req_set_callback(subreq, lock12_closed, req);
3321 :
3322 1 : subreq = lockread_send(state, ev, cli, fnum2);
3323 1 : if (tevent_req_nomem(subreq, req)) {
3324 0 : return tevent_req_post(req, ev);
3325 : }
3326 1 : tevent_req_set_callback(subreq, lock12_read, req);
3327 :
3328 1 : return req;
3329 : }
3330 :
3331 1 : static void lock12_closed(struct tevent_req *subreq)
3332 : {
3333 1 : struct tevent_req *req = tevent_req_callback_data(
3334 : subreq, struct tevent_req);
3335 : NTSTATUS status;
3336 :
3337 1 : status = deferred_close_recv(subreq);
3338 1 : TALLOC_FREE(subreq);
3339 1 : DBG_DEBUG("close returned %s\n", nt_errstr(status));
3340 1 : if (tevent_req_nterror(req, status)) {
3341 0 : return;
3342 : }
3343 : }
3344 :
3345 1 : static void lock12_read(struct tevent_req *subreq)
3346 : {
3347 1 : struct tevent_req *req = tevent_req_callback_data(
3348 : subreq, struct tevent_req);
3349 1 : struct lock12_state *state = tevent_req_data(
3350 : req, struct lock12_state);
3351 : NTSTATUS status, lock_status, read_status;
3352 1 : uint8_t *buf = NULL;
3353 :
3354 1 : status = lockread_recv(
3355 : subreq, &lock_status, &read_status, state, &buf);
3356 1 : TALLOC_FREE(subreq);
3357 2 : if (tevent_req_nterror(req, status) ||
3358 2 : tevent_req_nterror(req, lock_status) ||
3359 1 : tevent_req_nterror(req, read_status)) {
3360 0 : return;
3361 : }
3362 1 : tevent_req_done(req);
3363 : }
3364 :
3365 1 : static NTSTATUS lock12_recv(struct tevent_req *req)
3366 :
3367 : {
3368 : NTSTATUS status;
3369 :
3370 1 : if (tevent_req_is_nterror(req, &status)) {
3371 0 : return status;
3372 : }
3373 1 : return NT_STATUS_OK;
3374 : }
3375 :
3376 1 : static bool run_locktest12(int dummy)
3377 : {
3378 1 : struct tevent_context *ev = NULL;
3379 1 : struct tevent_req *req = NULL;
3380 1 : struct cli_state *cli = NULL;
3381 1 : const char fname[] = "\\lockt12.lck";
3382 : uint16_t fnum1, fnum2;
3383 1 : bool ret = false;
3384 : bool ok;
3385 1 : uint8_t data = 1;
3386 : NTSTATUS status;
3387 :
3388 1 : printf("starting locktest12\n");
3389 :
3390 1 : ev = samba_tevent_context_init(NULL);
3391 1 : if (ev == NULL) {
3392 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
3393 0 : goto done;
3394 : }
3395 :
3396 1 : ok = torture_open_connection(&cli, 0);
3397 1 : if (!ok) {
3398 0 : goto done;
3399 : }
3400 1 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3401 :
3402 1 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3403 1 : if (!NT_STATUS_IS_OK(status)) {
3404 0 : d_fprintf(stderr,
3405 : "cli_openx failed: %s\n",
3406 : nt_errstr(status));
3407 0 : goto done;
3408 : }
3409 :
3410 1 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3411 1 : if (!NT_STATUS_IS_OK(status)) {
3412 0 : d_fprintf(stderr,
3413 : "cli_openx failed: %s\n",
3414 : nt_errstr(status));
3415 0 : goto done;
3416 : }
3417 :
3418 1 : status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3419 1 : if (!NT_STATUS_IS_OK(status)) {
3420 0 : d_fprintf(stderr,
3421 : "cli_writeall failed: %s\n",
3422 : nt_errstr(status));
3423 0 : goto done;
3424 : }
3425 :
3426 1 : status = cli_locktype(
3427 : cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3428 1 : if (!NT_STATUS_IS_OK(status)) {
3429 0 : d_fprintf(stderr,
3430 : "cli_locktype failed: %s\n",
3431 : nt_errstr(status));
3432 0 : goto done;
3433 : }
3434 :
3435 1 : req = lock12_send(ev, ev, cli, fnum1, fnum2);
3436 1 : if (req == NULL) {
3437 0 : d_fprintf(stderr, "lock12_send failed\n");
3438 0 : goto done;
3439 : }
3440 :
3441 1 : ok = tevent_req_poll_ntstatus(req, ev, &status);
3442 1 : if (!ok) {
3443 0 : d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3444 0 : goto done;
3445 : }
3446 :
3447 1 : if (!NT_STATUS_IS_OK(status)) {
3448 0 : d_fprintf(stderr,
3449 : "tevent_req_poll_ntstatus returned %s\n",
3450 : nt_errstr(status));
3451 0 : goto done;
3452 : }
3453 :
3454 1 : status = lock12_recv(req);
3455 1 : if (!NT_STATUS_IS_OK(status)) {
3456 0 : d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3457 0 : goto done;
3458 : }
3459 :
3460 1 : ret = true;
3461 1 : done:
3462 1 : if (cli != NULL) {
3463 1 : torture_close_connection(cli);
3464 : }
3465 1 : return ret;
3466 : }
3467 :
3468 : struct lock_ntcancel_state {
3469 : struct timeval start;
3470 : struct smb1_lock_element lck;
3471 : struct tevent_req *subreq;
3472 : };
3473 :
3474 : static void lock_ntcancel_waited(struct tevent_req *subreq);
3475 : static void lock_ntcancel_done(struct tevent_req *subreq);
3476 :
3477 1 : static struct tevent_req *lock_ntcancel_send(
3478 : TALLOC_CTX *mem_ctx,
3479 : struct tevent_context *ev,
3480 : struct cli_state *cli,
3481 : uint16_t fnum)
3482 : {
3483 1 : struct tevent_req *req = NULL, *subreq = NULL;
3484 1 : struct lock_ntcancel_state *state = NULL;
3485 :
3486 1 : req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3487 1 : if (req == NULL) {
3488 0 : return NULL;
3489 : }
3490 2 : state->lck = (struct smb1_lock_element) {
3491 1 : .pid = cli_getpid(cli), .offset = 0, .length = 1,
3492 : };
3493 1 : state->start = timeval_current();
3494 :
3495 1 : state->subreq = cli_lockingx_send(
3496 : state, /* mem_ctx */
3497 : ev, /* tevent_context */
3498 : cli, /* cli */
3499 : fnum, /* fnum */
3500 : LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3501 : 0, /* newoplocklevel */
3502 : 10000, /* timeout */
3503 : 0, /* num_unlocks */
3504 : NULL, /* unlocks */
3505 : 1, /* num_locks */
3506 1 : &state->lck); /* locks */
3507 1 : if (tevent_req_nomem(state->subreq, req)) {
3508 0 : return tevent_req_post(req, ev);
3509 : }
3510 1 : tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3511 :
3512 1 : subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3513 1 : if (tevent_req_nomem(subreq, req)) {
3514 0 : return tevent_req_post(req, ev);
3515 : }
3516 1 : tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3517 1 : return req;
3518 : }
3519 :
3520 1 : static void lock_ntcancel_waited(struct tevent_req *subreq)
3521 : {
3522 1 : struct tevent_req *req = tevent_req_callback_data(
3523 : subreq, struct tevent_req);
3524 1 : struct lock_ntcancel_state *state = tevent_req_data(
3525 : req, struct lock_ntcancel_state);
3526 : bool ok;
3527 :
3528 1 : ok = tevent_wakeup_recv(subreq);
3529 1 : TALLOC_FREE(subreq);
3530 1 : if (!ok) {
3531 0 : tevent_req_oom(req);
3532 0 : return;
3533 : }
3534 :
3535 1 : ok = tevent_req_cancel(state->subreq);
3536 1 : if (!ok) {
3537 0 : d_fprintf(stderr, "Could not cancel subreq\n");
3538 0 : tevent_req_oom(req);
3539 0 : return;
3540 : }
3541 : }
3542 :
3543 1 : static void lock_ntcancel_done(struct tevent_req *subreq)
3544 : {
3545 1 : struct tevent_req *req = tevent_req_callback_data(
3546 : subreq, struct tevent_req);
3547 1 : struct lock_ntcancel_state *state = tevent_req_data(
3548 : req, struct lock_ntcancel_state);
3549 : NTSTATUS status;
3550 : double elapsed;
3551 :
3552 1 : status = cli_lockingx_recv(subreq);
3553 1 : TALLOC_FREE(subreq);
3554 :
3555 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3556 0 : d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3557 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3558 0 : return;
3559 : }
3560 :
3561 1 : elapsed = timeval_elapsed(&state->start);
3562 :
3563 1 : if (elapsed > 3) {
3564 0 : d_printf("cli_lockingx was too slow, cancel did not work\n");
3565 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3566 0 : return;
3567 : }
3568 :
3569 1 : tevent_req_done(req);
3570 : }
3571 :
3572 1 : static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3573 : {
3574 1 : return tevent_req_simple_recv_ntstatus(req);
3575 : }
3576 :
3577 1 : static bool run_locktest13(int dummy)
3578 : {
3579 1 : struct tevent_context *ev = NULL;
3580 1 : struct tevent_req *req = NULL;
3581 1 : struct cli_state *cli = NULL;
3582 1 : const char fname[] = "\\lockt13.lck";
3583 : uint16_t fnum1, fnum2;
3584 1 : bool ret = false;
3585 : bool ok;
3586 1 : uint8_t data = 1;
3587 : NTSTATUS status;
3588 :
3589 1 : printf("starting locktest13\n");
3590 :
3591 1 : ev = samba_tevent_context_init(NULL);
3592 1 : if (ev == NULL) {
3593 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
3594 0 : goto done;
3595 : }
3596 :
3597 1 : ok = torture_open_connection(&cli, 0);
3598 1 : if (!ok) {
3599 0 : goto done;
3600 : }
3601 1 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3602 :
3603 1 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3604 1 : if (!NT_STATUS_IS_OK(status)) {
3605 0 : d_fprintf(stderr,
3606 : "cli_openx failed: %s\n",
3607 : nt_errstr(status));
3608 0 : goto done;
3609 : }
3610 :
3611 1 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3612 1 : if (!NT_STATUS_IS_OK(status)) {
3613 0 : d_fprintf(stderr,
3614 : "cli_openx failed: %s\n",
3615 : nt_errstr(status));
3616 0 : goto done;
3617 : }
3618 :
3619 1 : status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3620 1 : if (!NT_STATUS_IS_OK(status)) {
3621 0 : d_fprintf(stderr,
3622 : "cli_writeall failed: %s\n",
3623 : nt_errstr(status));
3624 0 : goto done;
3625 : }
3626 :
3627 1 : status = cli_locktype(
3628 : cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3629 1 : if (!NT_STATUS_IS_OK(status)) {
3630 0 : d_fprintf(stderr,
3631 : "cli_locktype failed: %s\n",
3632 : nt_errstr(status));
3633 0 : goto done;
3634 : }
3635 :
3636 1 : req = lock_ntcancel_send(ev, ev, cli, fnum2);
3637 1 : if (req == NULL) {
3638 0 : d_fprintf(stderr, "lock_ntcancel_send failed\n");
3639 0 : goto done;
3640 : }
3641 :
3642 1 : ok = tevent_req_poll_ntstatus(req, ev, &status);
3643 1 : if (!ok) {
3644 0 : d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3645 0 : goto done;
3646 : }
3647 :
3648 1 : if (!NT_STATUS_IS_OK(status)) {
3649 0 : d_fprintf(stderr,
3650 : "tevent_req_poll_ntstatus returned %s\n",
3651 : nt_errstr(status));
3652 0 : goto done;
3653 : }
3654 :
3655 1 : status = lock_ntcancel_recv(req);
3656 1 : if (!NT_STATUS_IS_OK(status)) {
3657 0 : d_fprintf(stderr,
3658 : "lock_ntcancel returned %s\n",
3659 : nt_errstr(status));
3660 0 : goto done;
3661 : }
3662 :
3663 1 : ret = true;
3664 1 : done:
3665 1 : if (cli != NULL) {
3666 1 : torture_close_connection(cli);
3667 : }
3668 1 : return ret;
3669 : }
3670 :
3671 : /*
3672 : test whether fnums and tids open on one VC are available on another (a major
3673 : security hole)
3674 : */
3675 1 : static bool run_fdpasstest(int dummy)
3676 : {
3677 : struct cli_state *cli1, *cli2;
3678 1 : const char *fname = "\\fdpass.tst";
3679 : uint16_t fnum1;
3680 : char buf[1024];
3681 : NTSTATUS status;
3682 :
3683 1 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3684 0 : return False;
3685 : }
3686 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
3687 1 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
3688 :
3689 1 : printf("starting fdpasstest\n");
3690 :
3691 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3692 :
3693 1 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3694 : &fnum1);
3695 1 : if (!NT_STATUS_IS_OK(status)) {
3696 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3697 0 : return False;
3698 : }
3699 :
3700 1 : status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3701 : 13, NULL);
3702 1 : if (!NT_STATUS_IS_OK(status)) {
3703 0 : printf("write failed (%s)\n", nt_errstr(status));
3704 0 : return False;
3705 : }
3706 :
3707 1 : cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3708 1 : cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3709 1 : cli_setpid(cli2, cli_getpid(cli1));
3710 :
3711 1 : if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3712 0 : printf("read succeeded! nasty security hole [%s]\n", buf);
3713 0 : return false;
3714 : }
3715 :
3716 1 : cli_close(cli1, fnum1);
3717 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3718 :
3719 1 : torture_close_connection(cli1);
3720 1 : torture_close_connection(cli2);
3721 :
3722 1 : printf("finished fdpasstest\n");
3723 1 : return True;
3724 : }
3725 :
3726 1 : static bool run_fdsesstest(int dummy)
3727 : {
3728 : struct cli_state *cli;
3729 : uint16_t new_vuid;
3730 : uint16_t saved_vuid;
3731 : uint32_t new_cnum;
3732 : uint32_t saved_cnum;
3733 1 : const char *fname = "\\fdsess.tst";
3734 1 : const char *fname1 = "\\fdsess1.tst";
3735 : uint16_t fnum1;
3736 : uint16_t fnum2;
3737 : char buf[1024];
3738 1 : bool ret = True;
3739 : NTSTATUS status;
3740 :
3741 1 : if (!torture_open_connection(&cli, 0))
3742 0 : return False;
3743 1 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3744 :
3745 1 : if (!torture_cli_session_setup2(cli, &new_vuid))
3746 0 : return False;
3747 :
3748 1 : saved_cnum = cli_state_get_tid(cli);
3749 1 : if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3750 0 : return False;
3751 1 : new_cnum = cli_state_get_tid(cli);
3752 1 : cli_state_set_tid(cli, saved_cnum);
3753 :
3754 1 : printf("starting fdsesstest\n");
3755 :
3756 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3757 1 : cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3758 :
3759 1 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3760 1 : if (!NT_STATUS_IS_OK(status)) {
3761 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3762 0 : return False;
3763 : }
3764 :
3765 1 : status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3766 : NULL);
3767 1 : if (!NT_STATUS_IS_OK(status)) {
3768 0 : printf("write failed (%s)\n", nt_errstr(status));
3769 0 : return False;
3770 : }
3771 :
3772 1 : saved_vuid = cli_state_get_uid(cli);
3773 1 : cli_state_set_uid(cli, new_vuid);
3774 :
3775 1 : if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3776 0 : printf("read succeeded with different vuid! "
3777 : "nasty security hole [%s]\n", buf);
3778 0 : ret = false;
3779 : }
3780 : /* Try to open a file with different vuid, samba cnum. */
3781 1 : if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3782 1 : printf("create with different vuid, same cnum succeeded.\n");
3783 1 : cli_close(cli, fnum2);
3784 1 : cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3785 : } else {
3786 0 : printf("create with different vuid, same cnum failed.\n");
3787 0 : printf("This will cause problems with service clients.\n");
3788 0 : ret = False;
3789 : }
3790 :
3791 1 : cli_state_set_uid(cli, saved_vuid);
3792 :
3793 : /* Try with same vuid, different cnum. */
3794 1 : cli_state_set_tid(cli, new_cnum);
3795 :
3796 1 : if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3797 0 : printf("read succeeded with different cnum![%s]\n", buf);
3798 0 : ret = false;
3799 : }
3800 :
3801 1 : cli_state_set_tid(cli, saved_cnum);
3802 1 : cli_close(cli, fnum1);
3803 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3804 :
3805 1 : torture_close_connection(cli);
3806 :
3807 1 : printf("finished fdsesstest\n");
3808 1 : return ret;
3809 : }
3810 :
3811 : /*
3812 : This test checks that
3813 :
3814 : 1) the server does not allow an unlink on a file that is open
3815 : */
3816 1 : static bool run_unlinktest(int dummy)
3817 : {
3818 : struct cli_state *cli;
3819 1 : const char *fname = "\\unlink.tst";
3820 : uint16_t fnum;
3821 1 : bool correct = True;
3822 : NTSTATUS status;
3823 :
3824 1 : if (!torture_open_connection(&cli, 0)) {
3825 0 : return False;
3826 : }
3827 :
3828 1 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3829 :
3830 1 : printf("starting unlink test\n");
3831 :
3832 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3833 :
3834 1 : cli_setpid(cli, 1);
3835 :
3836 1 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3837 1 : if (!NT_STATUS_IS_OK(status)) {
3838 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3839 0 : return False;
3840 : }
3841 :
3842 1 : status = cli_unlink(cli, fname,
3843 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3844 1 : if (NT_STATUS_IS_OK(status)) {
3845 0 : printf("error: server allowed unlink on an open file\n");
3846 0 : correct = False;
3847 : } else {
3848 1 : correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3849 1 : NT_STATUS_SHARING_VIOLATION);
3850 : }
3851 :
3852 1 : cli_close(cli, fnum);
3853 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3854 :
3855 1 : if (!torture_close_connection(cli)) {
3856 0 : correct = False;
3857 : }
3858 :
3859 1 : printf("unlink test finished\n");
3860 :
3861 1 : return correct;
3862 : }
3863 :
3864 :
3865 : /*
3866 : test how many open files this server supports on the one socket
3867 : */
3868 0 : static bool run_maxfidtest(int dummy)
3869 : {
3870 : struct cli_state *cli;
3871 : fstring fname;
3872 : uint16_t fnums[0x11000];
3873 : int i;
3874 0 : int retries=4;
3875 0 : bool correct = True;
3876 : NTSTATUS status;
3877 :
3878 0 : cli = current_cli;
3879 :
3880 0 : if (retries <= 0) {
3881 0 : printf("failed to connect\n");
3882 0 : return False;
3883 : }
3884 :
3885 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3886 :
3887 0 : for (i=0; i<0x11000; i++) {
3888 0 : slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3889 0 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3890 : &fnums[i]);
3891 0 : if (!NT_STATUS_IS_OK(status)) {
3892 0 : printf("open of %s failed (%s)\n",
3893 : fname, nt_errstr(status));
3894 0 : printf("maximum fnum is %d\n", i);
3895 0 : break;
3896 : }
3897 0 : printf("%6d\r", i);
3898 : }
3899 0 : printf("%6d\n", i);
3900 0 : i--;
3901 :
3902 0 : printf("cleaning up\n");
3903 0 : for (;i>=0;i--) {
3904 0 : slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3905 0 : cli_close(cli, fnums[i]);
3906 :
3907 0 : status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3908 0 : if (!NT_STATUS_IS_OK(status)) {
3909 0 : printf("unlink of %s failed (%s)\n",
3910 : fname, nt_errstr(status));
3911 0 : correct = False;
3912 : }
3913 0 : printf("%6d\r", i);
3914 : }
3915 0 : printf("%6d\n", 0);
3916 :
3917 0 : printf("maxfid test finished\n");
3918 0 : if (!torture_close_connection(cli)) {
3919 0 : correct = False;
3920 : }
3921 0 : return correct;
3922 : }
3923 :
3924 : /* generate a random buffer */
3925 0 : static void rand_buf(char *buf, int len)
3926 : {
3927 0 : while (len--) {
3928 0 : *buf = (char)sys_random();
3929 0 : buf++;
3930 : }
3931 0 : }
3932 :
3933 : /* send smb negprot commands, not reading the response */
3934 0 : static bool run_negprot_nowait(int dummy)
3935 : {
3936 : struct tevent_context *ev;
3937 : int i;
3938 : struct cli_state *cli;
3939 0 : bool correct = True;
3940 :
3941 0 : printf("starting negprot nowait test\n");
3942 :
3943 0 : ev = samba_tevent_context_init(talloc_tos());
3944 0 : if (ev == NULL) {
3945 0 : return false;
3946 : }
3947 :
3948 0 : if (!(cli = open_nbt_connection())) {
3949 0 : TALLOC_FREE(ev);
3950 0 : return False;
3951 : }
3952 :
3953 0 : for (i=0;i<50000;i++) {
3954 : struct tevent_req *req;
3955 :
3956 0 : req = smbXcli_negprot_send(
3957 : ev,
3958 : ev,
3959 : cli->conn,
3960 0 : cli->timeout,
3961 : PROTOCOL_CORE,
3962 : PROTOCOL_NT1,
3963 : 0,
3964 : NULL);
3965 0 : if (req == NULL) {
3966 0 : TALLOC_FREE(ev);
3967 0 : return false;
3968 : }
3969 0 : if (!tevent_req_poll(req, ev)) {
3970 0 : d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3971 0 : strerror(errno));
3972 0 : TALLOC_FREE(ev);
3973 0 : return false;
3974 : }
3975 0 : TALLOC_FREE(req);
3976 : }
3977 :
3978 0 : if (torture_close_connection(cli)) {
3979 0 : correct = False;
3980 : }
3981 :
3982 0 : printf("finished negprot nowait test\n");
3983 :
3984 0 : return correct;
3985 : }
3986 :
3987 : /* send smb negprot commands, not reading the response */
3988 0 : static bool run_bad_nbt_session(int dummy)
3989 : {
3990 : struct nmb_name called, calling;
3991 : struct sockaddr_storage ss;
3992 : NTSTATUS status;
3993 : int fd;
3994 : bool ret;
3995 :
3996 0 : printf("starting bad nbt session test\n");
3997 :
3998 0 : make_nmb_name(&calling, myname, 0x0);
3999 0 : make_nmb_name(&called , host, 0x20);
4000 :
4001 0 : if (!resolve_name(host, &ss, 0x20, true)) {
4002 0 : d_fprintf(stderr, "Could not resolve name %s\n", host);
4003 0 : return false;
4004 : }
4005 :
4006 0 : status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4007 0 : if (!NT_STATUS_IS_OK(status)) {
4008 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
4009 : nt_errstr(status));
4010 0 : return false;
4011 : }
4012 :
4013 0 : ret = cli_bad_session_request(fd, &calling, &called);
4014 0 : close(fd);
4015 0 : if (!ret) {
4016 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
4017 : nt_errstr(status));
4018 0 : return false;
4019 : }
4020 :
4021 0 : printf("finished bad nbt session test\n");
4022 0 : return true;
4023 : }
4024 :
4025 : /* send random IPC commands */
4026 0 : static bool run_randomipc(int dummy)
4027 : {
4028 0 : char *rparam = NULL;
4029 0 : char *rdata = NULL;
4030 : unsigned int rdrcnt,rprcnt;
4031 : char param[1024];
4032 : int api, param_len, i;
4033 : struct cli_state *cli;
4034 0 : bool correct = True;
4035 0 : int count = 50000;
4036 :
4037 0 : printf("starting random ipc test\n");
4038 :
4039 0 : if (!torture_open_connection(&cli, 0)) {
4040 0 : return False;
4041 : }
4042 :
4043 0 : for (i=0;i<count;i++) {
4044 0 : api = sys_random() % 500;
4045 0 : param_len = (sys_random() % 64);
4046 :
4047 0 : rand_buf(param, param_len);
4048 :
4049 0 : SSVAL(param,0,api);
4050 :
4051 0 : cli_api(cli,
4052 : param, param_len, 8,
4053 : NULL, 0, CLI_BUFFER_SIZE,
4054 : &rparam, &rprcnt,
4055 : &rdata, &rdrcnt);
4056 0 : if (i % 100 == 0) {
4057 0 : printf("%d/%d\r", i,count);
4058 : }
4059 : }
4060 0 : printf("%d/%d\n", i, count);
4061 :
4062 0 : if (!torture_close_connection(cli)) {
4063 0 : correct = False;
4064 : }
4065 :
4066 0 : SAFE_FREE(rparam);
4067 0 : SAFE_FREE(rdata);
4068 :
4069 0 : printf("finished random ipc test\n");
4070 :
4071 0 : return correct;
4072 : }
4073 :
4074 :
4075 :
4076 0 : static void browse_callback(const char *sname, uint32_t stype,
4077 : const char *comment, void *state)
4078 : {
4079 0 : printf("\t%20.20s %08x %s\n", sname, stype, comment);
4080 0 : }
4081 :
4082 :
4083 :
4084 : /*
4085 : This test checks the browse list code
4086 :
4087 : */
4088 1 : static bool run_browsetest(int dummy)
4089 : {
4090 : static struct cli_state *cli;
4091 1 : bool correct = True;
4092 :
4093 1 : printf("starting browse test\n");
4094 :
4095 1 : if (!torture_open_connection(&cli, 0)) {
4096 0 : return False;
4097 : }
4098 :
4099 1 : printf("domain list:\n");
4100 1 : cli_NetServerEnum(cli, cli->server_domain,
4101 : SV_TYPE_DOMAIN_ENUM,
4102 : browse_callback, NULL);
4103 :
4104 1 : printf("machine list:\n");
4105 1 : cli_NetServerEnum(cli, cli->server_domain,
4106 : SV_TYPE_ALL,
4107 : browse_callback, NULL);
4108 :
4109 1 : if (!torture_close_connection(cli)) {
4110 0 : correct = False;
4111 : }
4112 :
4113 1 : printf("browse test finished\n");
4114 :
4115 1 : return correct;
4116 :
4117 : }
4118 :
4119 4 : static bool check_attributes(struct cli_state *cli,
4120 : const char *fname,
4121 : uint32_t expected_attrs)
4122 : {
4123 4 : uint32_t attrs = 0;
4124 4 : NTSTATUS status = cli_getatr(cli,
4125 : fname,
4126 : &attrs,
4127 : NULL,
4128 : NULL);
4129 4 : if (!NT_STATUS_IS_OK(status)) {
4130 0 : printf("cli_getatr failed with %s\n",
4131 : nt_errstr(status));
4132 0 : return false;
4133 : }
4134 4 : if (attrs != expected_attrs) {
4135 0 : printf("Attributes incorrect 0x%x, should be 0x%x\n",
4136 : (unsigned int)attrs,
4137 : (unsigned int)expected_attrs);
4138 0 : return false;
4139 : }
4140 4 : return true;
4141 : }
4142 :
4143 : /*
4144 : This checks how the getatr calls works
4145 : */
4146 1 : static bool run_attrtest(int dummy)
4147 : {
4148 : struct cli_state *cli;
4149 : uint16_t fnum;
4150 : time_t t, t2;
4151 1 : const char *fname = "\\attrib123456789.tst";
4152 1 : bool correct = True;
4153 : NTSTATUS status;
4154 :
4155 1 : printf("starting attrib test\n");
4156 :
4157 1 : if (!torture_open_connection(&cli, 0)) {
4158 0 : return False;
4159 : }
4160 :
4161 : /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4162 1 : status = cli_unlink(cli, fname, 0x20000);
4163 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4164 0 : correct = false;
4165 0 : goto out;
4166 : }
4167 :
4168 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4169 1 : cli_openx(cli, fname,
4170 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4171 1 : cli_close(cli, fnum);
4172 :
4173 1 : status = cli_getatr(cli, fname, NULL, NULL, &t);
4174 1 : if (!NT_STATUS_IS_OK(status)) {
4175 0 : printf("getatr failed (%s)\n", nt_errstr(status));
4176 0 : correct = False;
4177 : }
4178 :
4179 1 : if (labs(t - time(NULL)) > 60*60*24*10) {
4180 0 : printf("ERROR: SMBgetatr bug. time is %s",
4181 : ctime(&t));
4182 0 : t = time(NULL);
4183 0 : correct = True;
4184 : }
4185 :
4186 1 : t2 = t-60*60*24; /* 1 day ago */
4187 :
4188 : /* Ensure we can't set with out-of-range (unknown) attribute. */
4189 1 : status = cli_setatr(cli, fname, 0x20000, t2);
4190 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4191 0 : correct = false;
4192 0 : goto out;
4193 : }
4194 :
4195 1 : status = cli_setatr(cli, fname, 0, t2);
4196 1 : if (!NT_STATUS_IS_OK(status)) {
4197 0 : printf("setatr failed (%s)\n", nt_errstr(status));
4198 0 : correct = True;
4199 : }
4200 :
4201 1 : status = cli_getatr(cli, fname, NULL, NULL, &t);
4202 1 : if (!NT_STATUS_IS_OK(status)) {
4203 0 : printf("getatr failed (%s)\n", nt_errstr(status));
4204 0 : correct = True;
4205 : }
4206 :
4207 1 : if (t != t2) {
4208 0 : printf("ERROR: getatr/setatr bug. times are\n%s",
4209 : ctime(&t));
4210 0 : printf("%s", ctime(&t2));
4211 0 : correct = True;
4212 : }
4213 :
4214 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4215 :
4216 : /* Check cli_setpathinfo_ext() */
4217 : /* Re-create the file. */
4218 1 : status = cli_openx(cli, fname,
4219 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4220 1 : if (!NT_STATUS_IS_OK(status)) {
4221 0 : printf("Failed to recreate %s (%s)\n",
4222 : fname, nt_errstr(status));
4223 0 : correct = false;
4224 : }
4225 1 : cli_close(cli, fnum);
4226 :
4227 1 : status = cli_setpathinfo_ext(
4228 : cli,
4229 : fname,
4230 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4231 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4232 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4233 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4234 : FILE_ATTRIBUTE_SYSTEM |
4235 : FILE_ATTRIBUTE_HIDDEN |
4236 : FILE_ATTRIBUTE_READONLY);
4237 1 : if (!NT_STATUS_IS_OK(status)) {
4238 0 : printf("cli_setpathinfo_ext failed with %s\n",
4239 : nt_errstr(status));
4240 0 : correct = false;
4241 : }
4242 :
4243 : /* Check attributes are correct. */
4244 1 : correct = check_attributes(cli,
4245 : fname,
4246 : FILE_ATTRIBUTE_SYSTEM |
4247 : FILE_ATTRIBUTE_HIDDEN |
4248 : FILE_ATTRIBUTE_READONLY);
4249 1 : if (correct == false) {
4250 0 : goto out;
4251 : }
4252 :
4253 : /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4254 1 : status = cli_setpathinfo_ext(
4255 : cli,
4256 : fname,
4257 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4258 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4259 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4260 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4261 : FILE_ATTRIBUTE_NORMAL);
4262 1 : if (!NT_STATUS_IS_OK(status)) {
4263 0 : printf("cli_setpathinfo_ext failed with %s\n",
4264 : nt_errstr(status));
4265 0 : correct = false;
4266 : }
4267 :
4268 : /* Check attributes are correct. */
4269 1 : correct = check_attributes(cli,
4270 : fname,
4271 : FILE_ATTRIBUTE_SYSTEM |
4272 : FILE_ATTRIBUTE_HIDDEN |
4273 : FILE_ATTRIBUTE_READONLY);
4274 1 : if (correct == false) {
4275 0 : goto out;
4276 : }
4277 :
4278 : /* Setting to (uint16_t)-1 should also be ignored. */
4279 1 : status = cli_setpathinfo_ext(
4280 : cli,
4281 : fname,
4282 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4283 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4284 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4285 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4286 : (uint32_t)-1);
4287 1 : if (!NT_STATUS_IS_OK(status)) {
4288 0 : printf("cli_setpathinfo_ext failed with %s\n",
4289 : nt_errstr(status));
4290 0 : correct = false;
4291 : }
4292 :
4293 : /* Check attributes are correct. */
4294 1 : correct = check_attributes(cli,
4295 : fname,
4296 : FILE_ATTRIBUTE_SYSTEM |
4297 : FILE_ATTRIBUTE_HIDDEN |
4298 : FILE_ATTRIBUTE_READONLY);
4299 1 : if (correct == false) {
4300 0 : goto out;
4301 : }
4302 :
4303 : /* Setting to 0 should clear them all. */
4304 1 : status = cli_setpathinfo_ext(
4305 : cli,
4306 : fname,
4307 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4308 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4309 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4310 1 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4311 : 0);
4312 1 : if (!NT_STATUS_IS_OK(status)) {
4313 0 : printf("cli_setpathinfo_ext failed with %s\n",
4314 : nt_errstr(status));
4315 0 : correct = false;
4316 : }
4317 :
4318 : /* Check attributes are correct. */
4319 1 : correct = check_attributes(cli,
4320 : fname,
4321 : FILE_ATTRIBUTE_NORMAL);
4322 1 : if (correct == false) {
4323 0 : goto out;
4324 : }
4325 :
4326 2 : out:
4327 :
4328 1 : cli_unlink(cli,
4329 : fname,
4330 : FILE_ATTRIBUTE_SYSTEM |
4331 : FILE_ATTRIBUTE_HIDDEN|
4332 : FILE_ATTRIBUTE_READONLY);
4333 :
4334 1 : if (!torture_close_connection(cli)) {
4335 0 : correct = False;
4336 : }
4337 :
4338 1 : printf("attrib test finished\n");
4339 :
4340 1 : return correct;
4341 : }
4342 :
4343 1 : static NTSTATUS cli_qfilename(
4344 : struct cli_state *cli,
4345 : uint16_t fnum,
4346 : TALLOC_CTX *mem_ctx,
4347 : char **_name)
4348 : {
4349 : uint16_t recv_flags2;
4350 : uint8_t *rdata;
4351 : uint32_t num_rdata;
4352 : NTSTATUS status;
4353 1 : char *name = NULL;
4354 : uint32_t namelen;
4355 :
4356 1 : status = cli_qfileinfo(talloc_tos(), cli, fnum,
4357 : SMB_QUERY_FILE_NAME_INFO,
4358 : 4, CLI_BUFFER_SIZE, &recv_flags2,
4359 : &rdata, &num_rdata);
4360 1 : if (!NT_STATUS_IS_OK(status)) {
4361 0 : return status;
4362 : }
4363 :
4364 1 : namelen = IVAL(rdata, 0);
4365 1 : if (namelen > (num_rdata - 4)) {
4366 0 : TALLOC_FREE(rdata);
4367 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
4368 : }
4369 :
4370 2 : pull_string_talloc(mem_ctx,
4371 : (const char *)rdata,
4372 : recv_flags2,
4373 : &name,
4374 1 : rdata + 4,
4375 : namelen,
4376 : STR_UNICODE);
4377 1 : if (name == NULL) {
4378 0 : status = map_nt_error_from_unix(errno);
4379 0 : TALLOC_FREE(rdata);
4380 0 : return status;
4381 : }
4382 :
4383 1 : *_name = name;
4384 1 : TALLOC_FREE(rdata);
4385 1 : return NT_STATUS_OK;
4386 : }
4387 :
4388 : /*
4389 : This checks a couple of trans2 calls
4390 : */
4391 1 : static bool run_trans2test(int dummy)
4392 : {
4393 : struct cli_state *cli;
4394 : uint16_t fnum;
4395 : off_t size;
4396 : time_t c_time, a_time, m_time;
4397 : struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4398 1 : const char *fname = "\\trans2.tst";
4399 1 : const char *dname = "\\trans2";
4400 1 : const char *fname2 = "\\trans2\\trans2.tst";
4401 1 : char *pname = NULL;
4402 1 : bool correct = True;
4403 : NTSTATUS status;
4404 : uint32_t fs_attr;
4405 : uint64_t ino;
4406 :
4407 1 : printf("starting trans2 test\n");
4408 :
4409 1 : if (!torture_open_connection(&cli, 0)) {
4410 0 : return False;
4411 : }
4412 :
4413 1 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4414 : /* Ensure ino is zero, SMB2 gets a real one. */
4415 0 : ino = 0;
4416 : } else {
4417 : /* Ensure ino is -1, SMB1 never gets a real one. */
4418 1 : ino = (uint64_t)-1;
4419 : }
4420 :
4421 1 : status = cli_get_fs_attr_info(cli, &fs_attr);
4422 1 : if (!NT_STATUS_IS_OK(status)) {
4423 0 : printf("ERROR: cli_get_fs_attr_info returned %s\n",
4424 : nt_errstr(status));
4425 0 : correct = false;
4426 : }
4427 :
4428 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4429 1 : cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4430 1 : status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4431 : &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4432 1 : if (!NT_STATUS_IS_OK(status)) {
4433 0 : printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4434 0 : correct = False;
4435 : }
4436 :
4437 1 : status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4438 1 : if (!NT_STATUS_IS_OK(status)) {
4439 0 : printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4440 0 : correct = False;
4441 : }
4442 1 : else if (strcmp(pname, fname)) {
4443 0 : printf("qfilename gave different name? [%s] [%s]\n",
4444 : fname, pname);
4445 0 : correct = False;
4446 : }
4447 :
4448 1 : cli_close(cli, fnum);
4449 :
4450 1 : sleep(2);
4451 :
4452 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4453 1 : status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4454 : &fnum);
4455 1 : if (!NT_STATUS_IS_OK(status)) {
4456 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4457 0 : return False;
4458 : }
4459 1 : cli_close(cli, fnum);
4460 :
4461 1 : status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4462 : NULL);
4463 1 : if (!NT_STATUS_IS_OK(status)) {
4464 0 : printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4465 0 : correct = False;
4466 : } else {
4467 1 : time_t t = time(NULL);
4468 :
4469 1 : if (c_time != m_time) {
4470 0 : printf("create time=%s", ctime(&c_time));
4471 0 : printf("modify time=%s", ctime(&m_time));
4472 0 : printf("This system appears to have sticky create times\n");
4473 : }
4474 1 : if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4475 0 : printf("access time=%s", ctime(&a_time));
4476 0 : printf("This system appears to set a midnight access time\n");
4477 0 : correct = False;
4478 : }
4479 :
4480 1 : if (labs(m_time - t) > 60*60*24*7) {
4481 0 : printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4482 0 : correct = False;
4483 : }
4484 : }
4485 :
4486 :
4487 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4488 1 : cli_openx(cli, fname,
4489 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4490 1 : cli_close(cli, fnum);
4491 1 : status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
4492 : &m_time_ts, &size, NULL, &ino);
4493 1 : if (!NT_STATUS_IS_OK(status)) {
4494 0 : printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4495 0 : correct = False;
4496 : } else {
4497 1 : if (w_time_ts.tv_sec < 60*60*24*2) {
4498 0 : printf("write time=%s", ctime(&w_time_ts.tv_sec));
4499 0 : printf("This system appears to set a initial 0 write time\n");
4500 0 : correct = False;
4501 : }
4502 1 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4503 : /* SMB2 should always return an inode. */
4504 0 : if (ino == 0) {
4505 0 : printf("SMB2 bad inode (0)\n");
4506 0 : correct = false;
4507 : }
4508 : } else {
4509 : /* SMB1 must always return zero here. */
4510 1 : if (ino != 0) {
4511 0 : printf("SMB1 bad inode (!0)\n");
4512 0 : correct = false;
4513 : }
4514 : }
4515 : }
4516 :
4517 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4518 :
4519 :
4520 : /* check if the server updates the directory modification time
4521 : when creating a new file */
4522 1 : status = cli_mkdir(cli, dname);
4523 1 : if (!NT_STATUS_IS_OK(status)) {
4524 0 : printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4525 0 : correct = False;
4526 : }
4527 1 : sleep(3);
4528 1 : status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4529 : &w_time_ts, &m_time_ts, &size, NULL, NULL);
4530 1 : if (!NT_STATUS_IS_OK(status)) {
4531 0 : printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4532 0 : correct = False;
4533 : }
4534 :
4535 1 : cli_openx(cli, fname2,
4536 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4537 1 : cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4538 1 : cli_close(cli, fnum);
4539 1 : status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4540 : &w_time_ts, &m_time2_ts, &size, NULL, NULL);
4541 1 : if (!NT_STATUS_IS_OK(status)) {
4542 0 : printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4543 0 : correct = False;
4544 : } else {
4545 1 : if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4546 : == 0) {
4547 0 : printf("This system does not update directory modification times\n");
4548 0 : correct = False;
4549 : }
4550 : }
4551 1 : cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4552 1 : cli_rmdir(cli, dname);
4553 :
4554 1 : if (!torture_close_connection(cli)) {
4555 0 : correct = False;
4556 : }
4557 :
4558 1 : printf("trans2 test finished\n");
4559 :
4560 1 : return correct;
4561 : }
4562 :
4563 : /*
4564 : This checks new W2K calls.
4565 : */
4566 :
4567 36 : static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4568 : {
4569 36 : uint8_t *buf = NULL;
4570 : uint32_t len;
4571 : NTSTATUS status;
4572 :
4573 36 : status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4574 : CLI_BUFFER_SIZE, NULL, &buf, &len);
4575 36 : if (!NT_STATUS_IS_OK(status)) {
4576 36 : printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4577 : nt_errstr(status));
4578 : } else {
4579 0 : printf("qfileinfo: level %d, len = %u\n", level, len);
4580 0 : dump_data(0, (uint8_t *)buf, len);
4581 0 : printf("\n");
4582 : }
4583 36 : TALLOC_FREE(buf);
4584 36 : return status;
4585 : }
4586 :
4587 1 : static bool run_w2ktest(int dummy)
4588 : {
4589 : struct cli_state *cli;
4590 : uint16_t fnum;
4591 1 : const char *fname = "\\w2ktest\\w2k.tst";
4592 : int level;
4593 1 : bool correct = True;
4594 :
4595 1 : printf("starting w2k test\n");
4596 :
4597 1 : if (!torture_open_connection(&cli, 0)) {
4598 0 : return False;
4599 : }
4600 :
4601 1 : cli_openx(cli, fname,
4602 : O_RDWR | O_CREAT , DENY_NONE, &fnum);
4603 :
4604 37 : for (level = 1004; level < 1040; level++) {
4605 36 : new_trans(cli, fnum, level);
4606 : }
4607 :
4608 1 : cli_close(cli, fnum);
4609 :
4610 1 : if (!torture_close_connection(cli)) {
4611 0 : correct = False;
4612 : }
4613 :
4614 1 : printf("w2k test finished\n");
4615 :
4616 1 : return correct;
4617 : }
4618 :
4619 :
4620 : /*
4621 : this is a harness for some oplock tests
4622 : */
4623 1 : static bool run_oplock1(int dummy)
4624 : {
4625 : struct cli_state *cli1;
4626 1 : const char *fname = "\\lockt1.lck";
4627 : uint16_t fnum1;
4628 1 : bool correct = True;
4629 : NTSTATUS status;
4630 :
4631 1 : printf("starting oplock test 1\n");
4632 :
4633 1 : if (!torture_open_connection(&cli1, 0)) {
4634 0 : return False;
4635 : }
4636 :
4637 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4638 :
4639 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
4640 :
4641 1 : cli1->use_oplocks = True;
4642 :
4643 1 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4644 : &fnum1);
4645 1 : if (!NT_STATUS_IS_OK(status)) {
4646 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4647 0 : return False;
4648 : }
4649 :
4650 1 : cli1->use_oplocks = False;
4651 :
4652 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4653 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4654 :
4655 1 : status = cli_close(cli1, fnum1);
4656 1 : if (!NT_STATUS_IS_OK(status)) {
4657 0 : printf("close2 failed (%s)\n", nt_errstr(status));
4658 0 : return False;
4659 : }
4660 :
4661 1 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4662 1 : if (!NT_STATUS_IS_OK(status)) {
4663 0 : printf("unlink failed (%s)\n", nt_errstr(status));
4664 0 : return False;
4665 : }
4666 :
4667 1 : if (!torture_close_connection(cli1)) {
4668 0 : correct = False;
4669 : }
4670 :
4671 1 : printf("finished oplock test 1\n");
4672 :
4673 1 : return correct;
4674 : }
4675 :
4676 0 : static bool run_oplock2(int dummy)
4677 : {
4678 : struct cli_state *cli1, *cli2;
4679 0 : const char *fname = "\\lockt2.lck";
4680 : uint16_t fnum1, fnum2;
4681 0 : int saved_use_oplocks = use_oplocks;
4682 : char buf[4];
4683 0 : bool correct = True;
4684 : volatile bool *shared_correct;
4685 : size_t nread;
4686 : NTSTATUS status;
4687 :
4688 0 : shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4689 0 : *shared_correct = True;
4690 :
4691 0 : use_level_II_oplocks = True;
4692 0 : use_oplocks = True;
4693 :
4694 0 : printf("starting oplock test 2\n");
4695 :
4696 0 : if (!torture_open_connection(&cli1, 0)) {
4697 0 : use_level_II_oplocks = False;
4698 0 : use_oplocks = saved_use_oplocks;
4699 0 : return False;
4700 : }
4701 :
4702 0 : if (!torture_open_connection(&cli2, 1)) {
4703 0 : use_level_II_oplocks = False;
4704 0 : use_oplocks = saved_use_oplocks;
4705 0 : return False;
4706 : }
4707 :
4708 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4709 :
4710 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
4711 0 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
4712 :
4713 0 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4714 : &fnum1);
4715 0 : if (!NT_STATUS_IS_OK(status)) {
4716 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4717 0 : return False;
4718 : }
4719 :
4720 : /* Don't need the globals any more. */
4721 0 : use_level_II_oplocks = False;
4722 0 : use_oplocks = saved_use_oplocks;
4723 :
4724 0 : if (fork() == 0) {
4725 : /* Child code */
4726 0 : status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4727 0 : if (!NT_STATUS_IS_OK(status)) {
4728 0 : printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4729 0 : *shared_correct = False;
4730 0 : exit(0);
4731 : }
4732 :
4733 0 : sleep(2);
4734 :
4735 0 : status = cli_close(cli2, fnum2);
4736 0 : if (!NT_STATUS_IS_OK(status)) {
4737 0 : printf("close2 failed (%s)\n", nt_errstr(status));
4738 0 : *shared_correct = False;
4739 : }
4740 :
4741 0 : exit(0);
4742 : }
4743 :
4744 0 : sleep(2);
4745 :
4746 : /* Ensure cli1 processes the break. Empty file should always return 0
4747 : * bytes. */
4748 0 : status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4749 0 : if (!NT_STATUS_IS_OK(status)) {
4750 0 : printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4751 0 : correct = false;
4752 0 : } else if (nread != 0) {
4753 0 : printf("read on empty fnum1 failed. recv %ld expected %d\n",
4754 : (unsigned long)nread, 0);
4755 0 : correct = false;
4756 : }
4757 :
4758 : /* Should now be at level II. */
4759 : /* Test if sending a write locks causes a break to none. */
4760 0 : status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4761 0 : if (!NT_STATUS_IS_OK(status)) {
4762 0 : printf("lock failed (%s)\n", nt_errstr(status));
4763 0 : correct = False;
4764 : }
4765 :
4766 0 : cli_unlock(cli1, fnum1, 0, 4);
4767 :
4768 0 : sleep(2);
4769 :
4770 0 : status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4771 0 : if (!NT_STATUS_IS_OK(status)) {
4772 0 : printf("lock failed (%s)\n", nt_errstr(status));
4773 0 : correct = False;
4774 : }
4775 :
4776 0 : cli_unlock(cli1, fnum1, 0, 4);
4777 :
4778 0 : sleep(2);
4779 :
4780 0 : cli_read(cli1, fnum1, buf, 0, 4, NULL);
4781 :
4782 0 : status = cli_close(cli1, fnum1);
4783 0 : if (!NT_STATUS_IS_OK(status)) {
4784 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4785 0 : correct = False;
4786 : }
4787 :
4788 0 : sleep(4);
4789 :
4790 0 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4791 0 : if (!NT_STATUS_IS_OK(status)) {
4792 0 : printf("unlink failed (%s)\n", nt_errstr(status));
4793 0 : correct = False;
4794 : }
4795 :
4796 0 : if (!torture_close_connection(cli1)) {
4797 0 : correct = False;
4798 : }
4799 :
4800 0 : if (!*shared_correct) {
4801 0 : correct = False;
4802 : }
4803 :
4804 0 : printf("finished oplock test 2\n");
4805 :
4806 0 : return correct;
4807 : }
4808 :
4809 : struct oplock4_state {
4810 : struct tevent_context *ev;
4811 : struct cli_state *cli;
4812 : bool *got_break;
4813 : uint16_t *fnum2;
4814 : };
4815 :
4816 : static void oplock4_got_break(struct tevent_req *req);
4817 : static void oplock4_got_open(struct tevent_req *req);
4818 :
4819 1 : static bool run_oplock4(int dummy)
4820 : {
4821 : struct tevent_context *ev;
4822 : struct cli_state *cli1, *cli2;
4823 : struct tevent_req *oplock_req, *open_req;
4824 1 : const char *fname = "\\lockt4.lck";
4825 1 : const char *fname_ln = "\\lockt4_ln.lck";
4826 : uint16_t fnum1, fnum2;
4827 1 : int saved_use_oplocks = use_oplocks;
4828 : NTSTATUS status;
4829 1 : bool correct = true;
4830 :
4831 : bool got_break;
4832 :
4833 : struct oplock4_state *state;
4834 :
4835 1 : printf("starting oplock test 4\n");
4836 :
4837 1 : if (!torture_open_connection(&cli1, 0)) {
4838 0 : use_level_II_oplocks = false;
4839 0 : use_oplocks = saved_use_oplocks;
4840 0 : return false;
4841 : }
4842 :
4843 1 : if (!torture_open_connection(&cli2, 1)) {
4844 0 : use_level_II_oplocks = false;
4845 0 : use_oplocks = saved_use_oplocks;
4846 0 : return false;
4847 : }
4848 :
4849 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4850 1 : cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4851 :
4852 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
4853 1 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
4854 :
4855 : /* Create the file. */
4856 1 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4857 : &fnum1);
4858 1 : if (!NT_STATUS_IS_OK(status)) {
4859 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4860 0 : return false;
4861 : }
4862 :
4863 1 : status = cli_close(cli1, fnum1);
4864 1 : if (!NT_STATUS_IS_OK(status)) {
4865 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4866 0 : return false;
4867 : }
4868 :
4869 : /* Now create a hardlink. */
4870 1 : status = cli_hardlink(cli1, fname, fname_ln);
4871 1 : if (!NT_STATUS_IS_OK(status)) {
4872 0 : printf("nt hardlink failed (%s)\n", nt_errstr(status));
4873 0 : return false;
4874 : }
4875 :
4876 : /* Prove that opening hardlinks cause deny modes to conflict. */
4877 1 : status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4878 1 : if (!NT_STATUS_IS_OK(status)) {
4879 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4880 0 : return false;
4881 : }
4882 :
4883 1 : status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4884 1 : if (NT_STATUS_IS_OK(status)) {
4885 0 : printf("open of %s succeeded - should fail with sharing violation.\n",
4886 : fname_ln);
4887 0 : return false;
4888 : }
4889 :
4890 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4891 0 : printf("open of %s should fail with sharing violation. Got %s\n",
4892 : fname_ln, nt_errstr(status));
4893 0 : return false;
4894 : }
4895 :
4896 1 : status = cli_close(cli1, fnum1);
4897 1 : if (!NT_STATUS_IS_OK(status)) {
4898 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4899 0 : return false;
4900 : }
4901 :
4902 1 : cli1->use_oplocks = true;
4903 1 : cli2->use_oplocks = true;
4904 :
4905 1 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4906 1 : if (!NT_STATUS_IS_OK(status)) {
4907 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4908 0 : return false;
4909 : }
4910 :
4911 1 : ev = samba_tevent_context_init(talloc_tos());
4912 1 : if (ev == NULL) {
4913 0 : printf("tevent_context_init failed\n");
4914 0 : return false;
4915 : }
4916 :
4917 1 : state = talloc(ev, struct oplock4_state);
4918 1 : if (state == NULL) {
4919 0 : printf("talloc failed\n");
4920 0 : return false;
4921 : }
4922 1 : state->ev = ev;
4923 1 : state->cli = cli1;
4924 1 : state->got_break = &got_break;
4925 1 : state->fnum2 = &fnum2;
4926 :
4927 1 : oplock_req = cli_smb_oplock_break_waiter_send(
4928 : talloc_tos(), ev, cli1);
4929 1 : if (oplock_req == NULL) {
4930 0 : printf("cli_smb_oplock_break_waiter_send failed\n");
4931 0 : return false;
4932 : }
4933 1 : tevent_req_set_callback(oplock_req, oplock4_got_break, state);
4934 :
4935 1 : open_req = cli_openx_send(
4936 : talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
4937 1 : if (open_req == NULL) {
4938 0 : printf("cli_openx_send failed\n");
4939 0 : return false;
4940 : }
4941 1 : tevent_req_set_callback(open_req, oplock4_got_open, state);
4942 :
4943 1 : got_break = false;
4944 1 : fnum2 = 0xffff;
4945 :
4946 9 : while (!got_break || fnum2 == 0xffff) {
4947 : int ret;
4948 7 : ret = tevent_loop_once(ev);
4949 7 : if (ret == -1) {
4950 0 : printf("tevent_loop_once failed: %s\n",
4951 0 : strerror(errno));
4952 0 : return false;
4953 : }
4954 : }
4955 :
4956 1 : status = cli_close(cli2, fnum2);
4957 1 : if (!NT_STATUS_IS_OK(status)) {
4958 0 : printf("close2 failed (%s)\n", nt_errstr(status));
4959 0 : correct = false;
4960 : }
4961 :
4962 1 : status = cli_close(cli1, fnum1);
4963 1 : if (!NT_STATUS_IS_OK(status)) {
4964 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4965 0 : correct = false;
4966 : }
4967 :
4968 1 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4969 1 : if (!NT_STATUS_IS_OK(status)) {
4970 0 : printf("unlink failed (%s)\n", nt_errstr(status));
4971 0 : correct = false;
4972 : }
4973 :
4974 1 : status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4975 1 : if (!NT_STATUS_IS_OK(status)) {
4976 0 : printf("unlink failed (%s)\n", nt_errstr(status));
4977 0 : correct = false;
4978 : }
4979 :
4980 1 : if (!torture_close_connection(cli1)) {
4981 0 : correct = false;
4982 : }
4983 :
4984 1 : if (!got_break) {
4985 0 : correct = false;
4986 : }
4987 :
4988 1 : printf("finished oplock test 4\n");
4989 :
4990 1 : return correct;
4991 : }
4992 :
4993 1 : static void oplock4_got_break(struct tevent_req *req)
4994 : {
4995 1 : struct oplock4_state *state = tevent_req_callback_data(
4996 : req, struct oplock4_state);
4997 : uint16_t fnum;
4998 : uint8_t level;
4999 : NTSTATUS status;
5000 :
5001 1 : status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
5002 1 : TALLOC_FREE(req);
5003 1 : if (!NT_STATUS_IS_OK(status)) {
5004 0 : printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5005 : nt_errstr(status));
5006 0 : return;
5007 : }
5008 1 : *state->got_break = true;
5009 :
5010 1 : req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5011 : NO_OPLOCK);
5012 1 : if (req == NULL) {
5013 0 : printf("cli_oplock_ack_send failed\n");
5014 0 : return;
5015 : }
5016 : }
5017 :
5018 1 : static void oplock4_got_open(struct tevent_req *req)
5019 : {
5020 1 : struct oplock4_state *state = tevent_req_callback_data(
5021 : req, struct oplock4_state);
5022 : NTSTATUS status;
5023 :
5024 1 : status = cli_openx_recv(req, state->fnum2);
5025 1 : if (!NT_STATUS_IS_OK(status)) {
5026 0 : printf("cli_openx_recv returned %s\n", nt_errstr(status));
5027 0 : *state->fnum2 = 0xffff;
5028 : }
5029 1 : }
5030 :
5031 : #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5032 :
5033 : struct oplock5_state {
5034 : int pipe_down_fd;
5035 : };
5036 :
5037 : /*
5038 : * Async open the file that has a kernel oplock, do an echo to get
5039 : * that 100% across, close the file to signal to the child fd that the
5040 : * oplock can be dropped, wait for the open reply.
5041 : */
5042 :
5043 : static void oplock5_opened(struct tevent_req *subreq);
5044 : static void oplock5_pong(struct tevent_req *subreq);
5045 : static void oplock5_timedout(struct tevent_req *subreq);
5046 :
5047 0 : static struct tevent_req *oplock5_send(
5048 : TALLOC_CTX *mem_ctx,
5049 : struct tevent_context *ev,
5050 : struct cli_state *cli,
5051 : const char *fname,
5052 : int pipe_down_fd)
5053 : {
5054 0 : struct tevent_req *req = NULL, *subreq = NULL;
5055 0 : struct oplock5_state *state = NULL;
5056 : static uint8_t data = 0;
5057 :
5058 0 : req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5059 0 : if (req == NULL) {
5060 0 : return NULL;
5061 : }
5062 0 : state->pipe_down_fd = pipe_down_fd;
5063 :
5064 0 : subreq = cli_ntcreate_send(
5065 : state,
5066 : ev,
5067 : cli,
5068 : fname,
5069 : 0, /* CreatFlags */
5070 : SEC_FILE_READ_DATA, /* DesiredAccess */
5071 : FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
5072 : FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5073 : FILE_OPEN, /* CreateDisposition */
5074 : FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5075 : 0, /* Impersonation */
5076 : 0); /* SecurityFlags */
5077 0 : if (tevent_req_nomem(subreq, req)) {
5078 0 : return tevent_req_post(req, ev);
5079 : }
5080 0 : tevent_req_set_callback(subreq, oplock5_opened, req);
5081 :
5082 0 : subreq = cli_echo_send(
5083 : state,
5084 : ev,
5085 : cli,
5086 : 1,
5087 0 : (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5088 0 : if (tevent_req_nomem(subreq, req)) {
5089 0 : return tevent_req_post(req, ev);
5090 : }
5091 0 : tevent_req_set_callback(subreq, oplock5_pong, req);
5092 :
5093 0 : subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5094 0 : if (tevent_req_nomem(subreq, req)) {
5095 0 : return tevent_req_post(req, ev);
5096 : }
5097 0 : tevent_req_set_callback(subreq, oplock5_timedout, req);
5098 :
5099 0 : return req;
5100 : }
5101 :
5102 0 : static void oplock5_opened(struct tevent_req *subreq)
5103 : {
5104 0 : struct tevent_req *req = tevent_req_callback_data(
5105 : subreq, struct tevent_req);
5106 : NTSTATUS status;
5107 : uint16_t fnum;
5108 :
5109 0 : status = cli_ntcreate_recv(subreq, &fnum, NULL);
5110 0 : TALLOC_FREE(subreq);
5111 0 : if (tevent_req_nterror(req, status)) {
5112 0 : return;
5113 : }
5114 0 : tevent_req_done(req);
5115 : }
5116 :
5117 0 : static void oplock5_pong(struct tevent_req *subreq)
5118 : {
5119 0 : struct tevent_req *req = tevent_req_callback_data(
5120 : subreq, struct tevent_req);
5121 0 : struct oplock5_state *state = tevent_req_data(
5122 : req, struct oplock5_state);
5123 : NTSTATUS status;
5124 :
5125 0 : status = cli_echo_recv(subreq);
5126 0 : TALLOC_FREE(subreq);
5127 0 : if (tevent_req_nterror(req, status)) {
5128 0 : return;
5129 : }
5130 :
5131 0 : close(state->pipe_down_fd);
5132 : }
5133 :
5134 0 : static void oplock5_timedout(struct tevent_req *subreq)
5135 : {
5136 0 : struct tevent_req *req = tevent_req_callback_data(
5137 : subreq, struct tevent_req);
5138 : bool ok;
5139 :
5140 0 : ok = tevent_wakeup_recv(subreq);
5141 0 : TALLOC_FREE(subreq);
5142 0 : if (!ok) {
5143 0 : tevent_req_oom(req);
5144 0 : return;
5145 : }
5146 0 : tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5147 : }
5148 :
5149 0 : static NTSTATUS oplock5_recv(struct tevent_req *req)
5150 : {
5151 0 : return tevent_req_simple_recv_ntstatus(req);
5152 : }
5153 :
5154 0 : static bool run_oplock5(int dummy)
5155 : {
5156 0 : struct tevent_context *ev = NULL;
5157 0 : struct tevent_req *req = NULL;
5158 0 : struct cli_state *cli = NULL;
5159 0 : const char *fname = "oplock5.txt";
5160 : int pipe_down[2], pipe_up[2];
5161 : pid_t child_pid;
5162 0 : uint8_t c = '\0';
5163 : NTSTATUS status;
5164 : int ret;
5165 : bool ok;
5166 :
5167 0 : printf("starting oplock5\n");
5168 :
5169 0 : if (local_path == NULL) {
5170 0 : d_fprintf(stderr, "oplock5 must be given a local path via "
5171 : "-l <localpath>\n");
5172 0 : return false;
5173 : }
5174 :
5175 0 : ret = pipe(pipe_down);
5176 0 : if (ret == -1) {
5177 0 : d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5178 0 : return false;
5179 : }
5180 0 : ret = pipe(pipe_up);
5181 0 : if (ret == -1) {
5182 0 : d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5183 0 : return false;
5184 : }
5185 :
5186 0 : child_pid = fork();
5187 0 : if (child_pid == -1) {
5188 0 : d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5189 0 : return false;
5190 : }
5191 :
5192 0 : if (child_pid == 0) {
5193 0 : char *local_file = NULL;
5194 : int fd;
5195 :
5196 0 : close(pipe_down[1]);
5197 0 : close(pipe_up[0]);
5198 :
5199 0 : local_file = talloc_asprintf(
5200 0 : talloc_tos(), "%s/%s", local_path, fname);
5201 0 : if (local_file == 0) {
5202 0 : c = 1;
5203 0 : goto do_write;
5204 : }
5205 0 : fd = open(local_file, O_RDWR|O_CREAT, 0644);
5206 0 : if (fd == -1) {
5207 0 : d_fprintf(stderr,
5208 : "open(%s) in child failed: %s\n",
5209 : local_file,
5210 0 : strerror(errno));
5211 0 : c = 2;
5212 0 : goto do_write;
5213 : }
5214 :
5215 0 : signal(SIGIO, SIG_IGN);
5216 :
5217 0 : ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5218 0 : if (ret == -1) {
5219 0 : d_fprintf(stderr,
5220 : "SETLEASE in child failed: %s\n",
5221 0 : strerror(errno));
5222 0 : c = 3;
5223 0 : goto do_write;
5224 : }
5225 :
5226 0 : do_write:
5227 0 : ret = sys_write(pipe_up[1], &c, sizeof(c));
5228 0 : if (ret == -1) {
5229 0 : d_fprintf(stderr,
5230 : "sys_write failed: %s\n",
5231 0 : strerror(errno));
5232 0 : exit(4);
5233 : }
5234 0 : ret = sys_read(pipe_down[0], &c, sizeof(c));
5235 0 : if (ret == -1) {
5236 0 : d_fprintf(stderr,
5237 : "sys_read failed: %s\n",
5238 0 : strerror(errno));
5239 0 : exit(5);
5240 : }
5241 0 : exit(0);
5242 : }
5243 :
5244 0 : close(pipe_up[1]);
5245 0 : close(pipe_down[0]);
5246 :
5247 0 : ret = sys_read(pipe_up[0], &c, sizeof(c));
5248 0 : if (ret != 1) {
5249 0 : d_fprintf(stderr,
5250 : "sys_read failed: %s\n",
5251 0 : strerror(errno));
5252 0 : return false;
5253 : }
5254 0 : if (c != 0) {
5255 0 : d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5256 0 : return false;
5257 : }
5258 :
5259 0 : ok = torture_open_connection(&cli, 0);
5260 0 : if (!ok) {
5261 0 : d_fprintf(stderr, "torture_open_connection failed\n");
5262 0 : return false;
5263 : }
5264 :
5265 0 : ev = samba_tevent_context_init(talloc_tos());
5266 0 : if (ev == NULL) {
5267 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
5268 0 : return false;
5269 : }
5270 :
5271 0 : req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5272 0 : if (req == NULL) {
5273 0 : d_fprintf(stderr, "oplock5_send failed\n");
5274 0 : return false;
5275 : }
5276 :
5277 0 : ok = tevent_req_poll_ntstatus(req, ev, &status);
5278 0 : if (!ok) {
5279 0 : d_fprintf(stderr,
5280 : "tevent_req_poll_ntstatus failed: %s\n",
5281 : nt_errstr(status));
5282 0 : return false;
5283 : }
5284 :
5285 0 : status = oplock5_recv(req);
5286 0 : TALLOC_FREE(req);
5287 0 : if (!NT_STATUS_IS_OK(status)) {
5288 0 : d_fprintf(stderr,
5289 : "oplock5 failed: %s\n",
5290 : nt_errstr(status));
5291 0 : return false;
5292 : }
5293 :
5294 0 : return true;
5295 : }
5296 :
5297 : #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5298 :
5299 : /*
5300 : Test delete on close semantics.
5301 : */
5302 1 : static bool run_deletetest(int dummy)
5303 : {
5304 1 : struct cli_state *cli1 = NULL;
5305 1 : struct cli_state *cli2 = NULL;
5306 1 : const char *fname = "\\delete.file";
5307 1 : uint16_t fnum1 = (uint16_t)-1;
5308 1 : uint16_t fnum2 = (uint16_t)-1;
5309 1 : bool correct = false;
5310 : NTSTATUS status;
5311 :
5312 1 : printf("starting delete test\n");
5313 :
5314 1 : if (!torture_open_connection(&cli1, 0)) {
5315 0 : return False;
5316 : }
5317 :
5318 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
5319 :
5320 : /* Test 1 - this should delete the file on close. */
5321 :
5322 1 : cli_setatr(cli1, fname, 0, 0);
5323 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5324 :
5325 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5326 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5327 : FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5328 1 : if (!NT_STATUS_IS_OK(status)) {
5329 0 : printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5330 0 : goto fail;
5331 : }
5332 :
5333 1 : status = cli_close(cli1, fnum1);
5334 1 : if (!NT_STATUS_IS_OK(status)) {
5335 0 : printf("[1] close failed (%s)\n", nt_errstr(status));
5336 0 : goto fail;
5337 : }
5338 :
5339 1 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5340 1 : if (NT_STATUS_IS_OK(status)) {
5341 0 : printf("[1] open of %s succeeded (should fail)\n", fname);
5342 0 : goto fail;
5343 : }
5344 :
5345 1 : printf("first delete on close test succeeded.\n");
5346 :
5347 : /* Test 2 - this should delete the file on close. */
5348 :
5349 1 : cli_setatr(cli1, fname, 0, 0);
5350 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5351 :
5352 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5353 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5354 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5355 1 : if (!NT_STATUS_IS_OK(status)) {
5356 0 : printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5357 0 : goto fail;
5358 : }
5359 :
5360 1 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5361 1 : if (!NT_STATUS_IS_OK(status)) {
5362 0 : printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5363 0 : goto fail;
5364 : }
5365 :
5366 1 : status = cli_close(cli1, fnum1);
5367 1 : if (!NT_STATUS_IS_OK(status)) {
5368 0 : printf("[2] close failed (%s)\n", nt_errstr(status));
5369 0 : goto fail;
5370 : }
5371 :
5372 1 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5373 1 : if (NT_STATUS_IS_OK(status)) {
5374 0 : printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5375 0 : status = cli_close(cli1, fnum1);
5376 0 : if (!NT_STATUS_IS_OK(status)) {
5377 0 : printf("[2] close failed (%s)\n", nt_errstr(status));
5378 : }
5379 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5380 0 : goto fail;
5381 : }
5382 :
5383 1 : printf("second delete on close test succeeded.\n");
5384 :
5385 : /* Test 3 - ... */
5386 1 : cli_setatr(cli1, fname, 0, 0);
5387 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5388 :
5389 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5390 : FILE_ATTRIBUTE_NORMAL,
5391 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5392 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5393 1 : if (!NT_STATUS_IS_OK(status)) {
5394 0 : printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5395 0 : goto fail;
5396 : }
5397 :
5398 : /* This should fail with a sharing violation - open for delete is only compatible
5399 : with SHARE_DELETE. */
5400 :
5401 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5402 : FILE_ATTRIBUTE_NORMAL,
5403 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5404 : FILE_OPEN, 0, 0, &fnum2, NULL);
5405 1 : if (NT_STATUS_IS_OK(status)) {
5406 0 : printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
5407 0 : goto fail;
5408 : }
5409 :
5410 : /* This should succeed. */
5411 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5412 : FILE_ATTRIBUTE_NORMAL,
5413 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5414 : FILE_OPEN, 0, 0, &fnum2, NULL);
5415 1 : if (!NT_STATUS_IS_OK(status)) {
5416 0 : printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5417 0 : goto fail;
5418 : }
5419 :
5420 1 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5421 1 : if (!NT_STATUS_IS_OK(status)) {
5422 0 : printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5423 0 : goto fail;
5424 : }
5425 :
5426 1 : status = cli_close(cli1, fnum1);
5427 1 : if (!NT_STATUS_IS_OK(status)) {
5428 0 : printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5429 0 : goto fail;
5430 : }
5431 :
5432 1 : status = cli_close(cli1, fnum2);
5433 1 : if (!NT_STATUS_IS_OK(status)) {
5434 0 : printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5435 0 : goto fail;
5436 : }
5437 :
5438 : /* This should fail - file should no longer be there. */
5439 :
5440 1 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5441 1 : if (NT_STATUS_IS_OK(status)) {
5442 0 : printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5443 0 : status = cli_close(cli1, fnum1);
5444 0 : if (!NT_STATUS_IS_OK(status)) {
5445 0 : printf("[3] close failed (%s)\n", nt_errstr(status));
5446 : }
5447 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5448 0 : goto fail;
5449 : }
5450 :
5451 1 : printf("third delete on close test succeeded.\n");
5452 :
5453 : /* Test 4 ... */
5454 1 : cli_setatr(cli1, fname, 0, 0);
5455 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5456 :
5457 1 : status = cli_ntcreate(cli1, fname, 0,
5458 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5459 : FILE_ATTRIBUTE_NORMAL,
5460 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5461 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5462 1 : if (!NT_STATUS_IS_OK(status)) {
5463 0 : printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5464 0 : goto fail;
5465 : }
5466 :
5467 : /* This should succeed. */
5468 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5469 : FILE_ATTRIBUTE_NORMAL,
5470 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5471 : FILE_OPEN, 0, 0, &fnum2, NULL);
5472 1 : if (!NT_STATUS_IS_OK(status)) {
5473 0 : printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5474 0 : goto fail;
5475 : }
5476 :
5477 1 : status = cli_close(cli1, fnum2);
5478 1 : if (!NT_STATUS_IS_OK(status)) {
5479 0 : printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5480 0 : goto fail;
5481 : }
5482 :
5483 1 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5484 1 : if (!NT_STATUS_IS_OK(status)) {
5485 0 : printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5486 0 : goto fail;
5487 : }
5488 :
5489 : /* This should fail - no more opens once delete on close set. */
5490 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5491 : FILE_ATTRIBUTE_NORMAL,
5492 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5493 : FILE_OPEN, 0, 0, &fnum2, NULL);
5494 1 : if (NT_STATUS_IS_OK(status)) {
5495 0 : printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
5496 0 : goto fail;
5497 : }
5498 :
5499 1 : status = cli_close(cli1, fnum1);
5500 1 : if (!NT_STATUS_IS_OK(status)) {
5501 0 : printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5502 0 : goto fail;
5503 : }
5504 :
5505 1 : printf("fourth delete on close test succeeded.\n");
5506 :
5507 : /* Test 5 ... */
5508 1 : cli_setatr(cli1, fname, 0, 0);
5509 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5510 :
5511 1 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5512 1 : if (!NT_STATUS_IS_OK(status)) {
5513 0 : printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5514 0 : goto fail;
5515 : }
5516 :
5517 : /* This should fail - only allowed on NT opens with DELETE access. */
5518 :
5519 1 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5520 1 : if (NT_STATUS_IS_OK(status)) {
5521 0 : printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5522 0 : goto fail;
5523 : }
5524 :
5525 1 : status = cli_close(cli1, fnum1);
5526 1 : if (!NT_STATUS_IS_OK(status)) {
5527 0 : printf("[5] close failed (%s)\n", nt_errstr(status));
5528 0 : goto fail;
5529 : }
5530 :
5531 1 : printf("fifth delete on close test succeeded.\n");
5532 :
5533 : /* Test 6 ... */
5534 1 : cli_setatr(cli1, fname, 0, 0);
5535 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5536 :
5537 1 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5538 : FILE_ATTRIBUTE_NORMAL,
5539 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5540 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5541 1 : if (!NT_STATUS_IS_OK(status)) {
5542 0 : printf("[6] open of %s failed (%s)\n", fname,
5543 : nt_errstr(status));
5544 0 : goto fail;
5545 : }
5546 :
5547 : /* This should fail - only allowed on NT opens with DELETE access. */
5548 :
5549 1 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5550 1 : if (NT_STATUS_IS_OK(status)) {
5551 0 : printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5552 0 : goto fail;
5553 : }
5554 :
5555 1 : status = cli_close(cli1, fnum1);
5556 1 : if (!NT_STATUS_IS_OK(status)) {
5557 0 : printf("[6] close failed (%s)\n", nt_errstr(status));
5558 0 : goto fail;
5559 : }
5560 :
5561 1 : printf("sixth delete on close test succeeded.\n");
5562 :
5563 : /* Test 7 ... */
5564 1 : cli_setatr(cli1, fname, 0, 0);
5565 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5566 :
5567 1 : status = cli_ntcreate(cli1, fname, 0,
5568 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5569 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5570 : 0, 0, &fnum1, NULL);
5571 1 : if (!NT_STATUS_IS_OK(status)) {
5572 0 : printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5573 0 : goto fail;
5574 : }
5575 :
5576 1 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5577 1 : if (!NT_STATUS_IS_OK(status)) {
5578 0 : printf("[7] setting delete_on_close on file failed !\n");
5579 0 : goto fail;
5580 : }
5581 :
5582 1 : status = cli_nt_delete_on_close(cli1, fnum1, false);
5583 1 : if (!NT_STATUS_IS_OK(status)) {
5584 0 : printf("[7] unsetting delete_on_close on file failed !\n");
5585 0 : goto fail;
5586 : }
5587 :
5588 1 : status = cli_close(cli1, fnum1);
5589 1 : if (!NT_STATUS_IS_OK(status)) {
5590 0 : printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5591 0 : goto fail;
5592 : }
5593 :
5594 : /* This next open should succeed - we reset the flag. */
5595 1 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5596 1 : if (!NT_STATUS_IS_OK(status)) {
5597 0 : printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5598 0 : goto fail;
5599 : }
5600 :
5601 1 : status = cli_close(cli1, fnum1);
5602 1 : if (!NT_STATUS_IS_OK(status)) {
5603 0 : printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5604 0 : goto fail;
5605 : }
5606 :
5607 1 : printf("seventh delete on close test succeeded.\n");
5608 :
5609 : /* Test 8 ... */
5610 1 : cli_setatr(cli1, fname, 0, 0);
5611 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5612 :
5613 1 : if (!torture_open_connection(&cli2, 1)) {
5614 0 : printf("[8] failed to open second connection.\n");
5615 0 : goto fail;
5616 : }
5617 :
5618 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
5619 :
5620 1 : status = cli_ntcreate(cli1, fname, 0,
5621 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5622 : FILE_ATTRIBUTE_NORMAL,
5623 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5624 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5625 1 : if (!NT_STATUS_IS_OK(status)) {
5626 0 : printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5627 0 : goto fail;
5628 : }
5629 :
5630 1 : status = cli_ntcreate(cli2, fname, 0,
5631 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5632 : FILE_ATTRIBUTE_NORMAL,
5633 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5634 : FILE_OPEN, 0, 0, &fnum2, NULL);
5635 1 : if (!NT_STATUS_IS_OK(status)) {
5636 0 : printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5637 0 : goto fail;
5638 : }
5639 :
5640 1 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5641 1 : if (!NT_STATUS_IS_OK(status)) {
5642 0 : printf("[8] setting delete_on_close on file failed !\n");
5643 0 : goto fail;
5644 : }
5645 :
5646 1 : status = cli_close(cli1, fnum1);
5647 1 : if (!NT_STATUS_IS_OK(status)) {
5648 0 : printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5649 0 : goto fail;
5650 : }
5651 :
5652 1 : status = cli_close(cli2, fnum2);
5653 1 : if (!NT_STATUS_IS_OK(status)) {
5654 0 : printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5655 0 : goto fail;
5656 : }
5657 :
5658 : /* This should fail.. */
5659 1 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5660 1 : if (NT_STATUS_IS_OK(status)) {
5661 0 : printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5662 0 : goto fail;
5663 : }
5664 :
5665 1 : printf("eighth delete on close test succeeded.\n");
5666 :
5667 : /* Test 9 ... */
5668 :
5669 : /* This should fail - we need to set DELETE_ACCESS. */
5670 1 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5671 : FILE_ATTRIBUTE_NORMAL,
5672 : FILE_SHARE_NONE,
5673 : FILE_OVERWRITE_IF,
5674 : FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5675 1 : if (NT_STATUS_IS_OK(status)) {
5676 0 : printf("[9] open of %s succeeded should have failed!\n", fname);
5677 0 : goto fail;
5678 : }
5679 :
5680 1 : printf("ninth delete on close test succeeded.\n");
5681 :
5682 : /* Test 10 ... */
5683 :
5684 1 : status = cli_ntcreate(cli1, fname, 0,
5685 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5686 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5687 : FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5688 : 0, &fnum1, NULL);
5689 1 : if (!NT_STATUS_IS_OK(status)) {
5690 0 : printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5691 0 : goto fail;
5692 : }
5693 :
5694 : /* This should delete the file. */
5695 1 : status = cli_close(cli1, fnum1);
5696 1 : if (!NT_STATUS_IS_OK(status)) {
5697 0 : printf("[10] close failed (%s)\n", nt_errstr(status));
5698 0 : goto fail;
5699 : }
5700 :
5701 : /* This should fail.. */
5702 1 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5703 1 : if (NT_STATUS_IS_OK(status)) {
5704 0 : printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5705 0 : goto fail;
5706 : }
5707 :
5708 1 : printf("tenth delete on close test succeeded.\n");
5709 :
5710 : /* Test 11 ... */
5711 :
5712 1 : cli_setatr(cli1, fname, 0, 0);
5713 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5714 :
5715 : /* Can we open a read-only file with delete access? */
5716 :
5717 : /* Create a readonly file. */
5718 1 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5719 : FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5720 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5721 1 : if (!NT_STATUS_IS_OK(status)) {
5722 0 : printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5723 0 : goto fail;
5724 : }
5725 :
5726 1 : status = cli_close(cli1, fnum1);
5727 1 : if (!NT_STATUS_IS_OK(status)) {
5728 0 : printf("[11] close failed (%s)\n", nt_errstr(status));
5729 0 : goto fail;
5730 : }
5731 :
5732 : /* Now try open for delete access. */
5733 1 : status = cli_ntcreate(cli1, fname, 0,
5734 : FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5735 : 0,
5736 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5737 : FILE_OPEN, 0, 0, &fnum1, NULL);
5738 1 : if (!NT_STATUS_IS_OK(status)) {
5739 0 : printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5740 0 : goto fail;
5741 : }
5742 :
5743 1 : cli_close(cli1, fnum1);
5744 :
5745 1 : printf("eleventh delete on close test succeeded.\n");
5746 :
5747 : /*
5748 : * Test 12
5749 : * like test 4 but with initial delete on close
5750 : */
5751 :
5752 1 : cli_setatr(cli1, fname, 0, 0);
5753 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5754 :
5755 1 : status = cli_ntcreate(cli1, fname, 0,
5756 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5757 : FILE_ATTRIBUTE_NORMAL,
5758 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5759 : FILE_OVERWRITE_IF,
5760 : FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5761 1 : if (!NT_STATUS_IS_OK(status)) {
5762 0 : printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5763 0 : goto fail;
5764 : }
5765 :
5766 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5767 : FILE_ATTRIBUTE_NORMAL,
5768 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5769 : FILE_OPEN, 0, 0, &fnum2, NULL);
5770 1 : if (!NT_STATUS_IS_OK(status)) {
5771 0 : printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5772 0 : goto fail;
5773 : }
5774 :
5775 1 : status = cli_close(cli1, fnum2);
5776 1 : if (!NT_STATUS_IS_OK(status)) {
5777 0 : printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5778 0 : goto fail;
5779 : }
5780 :
5781 1 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5782 1 : if (!NT_STATUS_IS_OK(status)) {
5783 0 : printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5784 0 : goto fail;
5785 : }
5786 :
5787 : /* This should fail - no more opens once delete on close set. */
5788 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5789 : FILE_ATTRIBUTE_NORMAL,
5790 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5791 : FILE_OPEN, 0, 0, &fnum2, NULL);
5792 1 : if (NT_STATUS_IS_OK(status)) {
5793 0 : printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5794 0 : goto fail;
5795 : }
5796 :
5797 1 : status = cli_nt_delete_on_close(cli1, fnum1, false);
5798 1 : if (!NT_STATUS_IS_OK(status)) {
5799 0 : printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5800 0 : goto fail;
5801 : }
5802 :
5803 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5804 : FILE_ATTRIBUTE_NORMAL,
5805 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5806 : FILE_OPEN, 0, 0, &fnum2, NULL);
5807 1 : if (!NT_STATUS_IS_OK(status)) {
5808 0 : printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5809 0 : goto fail;
5810 : }
5811 :
5812 1 : status = cli_close(cli1, fnum2);
5813 1 : if (!NT_STATUS_IS_OK(status)) {
5814 0 : printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5815 0 : goto fail;
5816 : }
5817 :
5818 1 : status = cli_close(cli1, fnum1);
5819 1 : if (!NT_STATUS_IS_OK(status)) {
5820 0 : printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5821 0 : goto fail;
5822 : }
5823 :
5824 : /*
5825 : * setting delete on close on the handle does
5826 : * not unset the initial delete on close...
5827 : */
5828 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5829 : FILE_ATTRIBUTE_NORMAL,
5830 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5831 : FILE_OPEN, 0, 0, &fnum2, NULL);
5832 1 : if (NT_STATUS_IS_OK(status)) {
5833 0 : printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5834 0 : goto fail;
5835 1 : } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5836 0 : printf("ntcreate returned %s, expected "
5837 : "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5838 : nt_errstr(status));
5839 0 : goto fail;
5840 : }
5841 :
5842 1 : printf("twelfth delete on close test succeeded.\n");
5843 :
5844 :
5845 1 : printf("finished delete test\n");
5846 :
5847 1 : correct = true;
5848 :
5849 1 : fail:
5850 : /* FIXME: This will crash if we aborted before cli2 got
5851 : * intialized, because these functions don't handle
5852 : * uninitialized connections. */
5853 :
5854 1 : if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5855 1 : if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5856 1 : cli_setatr(cli1, fname, 0, 0);
5857 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5858 :
5859 1 : if (cli1 && !torture_close_connection(cli1)) {
5860 0 : correct = False;
5861 : }
5862 1 : if (cli2 && !torture_close_connection(cli2)) {
5863 0 : correct = False;
5864 : }
5865 1 : return correct;
5866 : }
5867 :
5868 : struct delete_stream_state {
5869 : bool closed;
5870 : };
5871 :
5872 : static void delete_stream_unlinked(struct tevent_req *subreq);
5873 : static void delete_stream_closed(struct tevent_req *subreq);
5874 :
5875 1 : static struct tevent_req *delete_stream_send(
5876 : TALLOC_CTX *mem_ctx,
5877 : struct tevent_context *ev,
5878 : struct cli_state *cli,
5879 : const char *base_fname,
5880 : uint16_t stream_fnum)
5881 : {
5882 1 : struct tevent_req *req = NULL, *subreq = NULL;
5883 1 : struct delete_stream_state *state = NULL;
5884 :
5885 1 : req = tevent_req_create(
5886 : mem_ctx, &state, struct delete_stream_state);
5887 1 : if (req == NULL) {
5888 0 : return NULL;
5889 : }
5890 :
5891 1 : subreq = cli_unlink_send(
5892 : state,
5893 : ev,
5894 : cli,
5895 : base_fname,
5896 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5897 1 : if (tevent_req_nomem(subreq, req)) {
5898 0 : return tevent_req_post(req, ev);
5899 : }
5900 1 : tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5901 :
5902 1 : subreq = cli_close_send(state, ev, cli, stream_fnum);
5903 1 : if (tevent_req_nomem(subreq, req)) {
5904 0 : return tevent_req_post(req, ev);
5905 : }
5906 1 : tevent_req_set_callback(subreq, delete_stream_closed, req);
5907 :
5908 1 : return req;
5909 : }
5910 :
5911 1 : static void delete_stream_unlinked(struct tevent_req *subreq)
5912 : {
5913 1 : struct tevent_req *req = tevent_req_callback_data(
5914 : subreq, struct tevent_req);
5915 1 : struct delete_stream_state *state = tevent_req_data(
5916 : req, struct delete_stream_state);
5917 : NTSTATUS status;
5918 :
5919 1 : status = cli_unlink_recv(subreq);
5920 1 : TALLOC_FREE(subreq);
5921 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5922 0 : printf("cli_unlink returned %s\n",
5923 : nt_errstr(status));
5924 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5925 0 : return;
5926 : }
5927 1 : if (!state->closed) {
5928 : /* close reply should have come in first */
5929 0 : printf("Not closed\n");
5930 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5931 0 : return;
5932 : }
5933 1 : tevent_req_done(req);
5934 : }
5935 :
5936 1 : static void delete_stream_closed(struct tevent_req *subreq)
5937 : {
5938 1 : struct tevent_req *req = tevent_req_callback_data(
5939 : subreq, struct tevent_req);
5940 1 : struct delete_stream_state *state = tevent_req_data(
5941 : req, struct delete_stream_state);
5942 : NTSTATUS status;
5943 :
5944 1 : status = cli_close_recv(subreq);
5945 1 : TALLOC_FREE(subreq);
5946 1 : if (tevent_req_nterror(req, status)) {
5947 0 : return;
5948 : }
5949 : /* also waiting for the unlink to come back */
5950 1 : state->closed = true;
5951 : }
5952 :
5953 1 : static NTSTATUS delete_stream_recv(struct tevent_req *req)
5954 : {
5955 1 : return tevent_req_simple_recv_ntstatus(req);
5956 : }
5957 :
5958 1 : static bool run_delete_stream(int dummy)
5959 : {
5960 1 : struct tevent_context *ev = NULL;
5961 1 : struct tevent_req *req = NULL;
5962 1 : struct cli_state *cli = NULL;
5963 1 : const char fname[] = "delete_stream";
5964 1 : const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
5965 : uint16_t fnum1, fnum2;
5966 : NTSTATUS status;
5967 : bool ok;
5968 :
5969 1 : printf("Starting stream delete test\n");
5970 :
5971 1 : ok = torture_open_connection(&cli, 0);
5972 1 : if (!ok) {
5973 0 : return false;
5974 : }
5975 :
5976 1 : cli_setatr(cli, fname, 0, 0);
5977 1 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5978 :
5979 : /* Create the file. */
5980 1 : status = cli_ntcreate(
5981 : cli,
5982 : fname,
5983 : 0,
5984 : READ_CONTROL_ACCESS,
5985 : 0,
5986 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5987 : FILE_CREATE,
5988 : 0x0,
5989 : 0x0,
5990 : &fnum1,
5991 : NULL);
5992 1 : if (!NT_STATUS_IS_OK(status)) {
5993 0 : d_fprintf(stderr,
5994 : "cli_ntcreate of %s failed (%s)\n",
5995 : fname,
5996 : nt_errstr(status));
5997 0 : return false;
5998 : }
5999 1 : status = cli_close(cli, fnum1);
6000 1 : if (!NT_STATUS_IS_OK(status)) {
6001 0 : d_fprintf(stderr,
6002 : "cli_close of %s failed (%s)\n",
6003 : fname,
6004 : nt_errstr(status));
6005 0 : return false;
6006 : }
6007 :
6008 : /* Now create the stream. */
6009 1 : status = cli_ntcreate(
6010 : cli,
6011 : fname_stream,
6012 : 0,
6013 : FILE_WRITE_DATA,
6014 : 0,
6015 : FILE_SHARE_READ|FILE_SHARE_WRITE,
6016 : FILE_CREATE,
6017 : 0x0,
6018 : 0x0,
6019 : &fnum1,
6020 : NULL);
6021 :
6022 1 : if (!NT_STATUS_IS_OK(status)) {
6023 0 : d_fprintf(stderr,
6024 : "cli_ntcreate of %s failed (%s)\n",
6025 : fname_stream,
6026 : nt_errstr(status));
6027 0 : return false;
6028 : }
6029 :
6030 : /* open it a second time */
6031 :
6032 1 : status = cli_ntcreate(
6033 : cli,
6034 : fname_stream,
6035 : 0,
6036 : FILE_WRITE_DATA,
6037 : 0,
6038 : FILE_SHARE_READ|FILE_SHARE_WRITE,
6039 : FILE_OPEN,
6040 : 0x0,
6041 : 0x0,
6042 : &fnum2,
6043 : NULL);
6044 :
6045 1 : if (!NT_STATUS_IS_OK(status)) {
6046 0 : d_fprintf(stderr,
6047 : "2nd cli_ntcreate of %s failed (%s)\n",
6048 : fname_stream,
6049 : nt_errstr(status));
6050 0 : return false;
6051 : }
6052 :
6053 1 : ev = samba_tevent_context_init(talloc_tos());
6054 1 : if (ev == NULL) {
6055 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
6056 0 : return false;
6057 : }
6058 :
6059 1 : req = delete_stream_send(ev, ev, cli, fname, fnum1);
6060 1 : if (req == NULL) {
6061 0 : d_fprintf(stderr, "delete_stream_send failed\n");
6062 0 : return false;
6063 : }
6064 :
6065 1 : ok = tevent_req_poll_ntstatus(req, ev, &status);
6066 1 : if (!ok) {
6067 0 : d_fprintf(stderr,
6068 : "tevent_req_poll_ntstatus failed: %s\n",
6069 : nt_errstr(status));
6070 0 : return false;
6071 : }
6072 :
6073 1 : status = delete_stream_recv(req);
6074 1 : TALLOC_FREE(req);
6075 1 : if (!NT_STATUS_IS_OK(status)) {
6076 0 : d_fprintf(stderr,
6077 : "delete_stream failed: %s\n",
6078 : nt_errstr(status));
6079 0 : return false;
6080 : }
6081 :
6082 1 : status = cli_close(cli, fnum2);
6083 1 : if (!NT_STATUS_IS_OK(status)) {
6084 0 : d_fprintf(stderr,
6085 : "close failed: %s\n",
6086 : nt_errstr(status));
6087 0 : return false;
6088 : }
6089 :
6090 1 : status = cli_unlink(
6091 : cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6092 1 : if (!NT_STATUS_IS_OK(status)) {
6093 0 : d_fprintf(stderr,
6094 : "unlink failed: %s\n",
6095 : nt_errstr(status));
6096 0 : return false;
6097 : }
6098 :
6099 1 : return true;
6100 : }
6101 :
6102 : /*
6103 : Exercise delete on close semantics - use on the PRINT1 share in torture
6104 : testing.
6105 : */
6106 0 : static bool run_delete_print_test(int dummy)
6107 : {
6108 0 : struct cli_state *cli1 = NULL;
6109 0 : const char *fname = "print_delete.file";
6110 0 : uint16_t fnum1 = (uint16_t)-1;
6111 0 : bool correct = false;
6112 0 : const char *buf = "print file data\n";
6113 : NTSTATUS status;
6114 :
6115 0 : printf("starting print delete test\n");
6116 :
6117 0 : if (!torture_open_connection(&cli1, 0)) {
6118 0 : return false;
6119 : }
6120 :
6121 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
6122 :
6123 0 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6124 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6125 : 0, 0, &fnum1, NULL);
6126 0 : if (!NT_STATUS_IS_OK(status)) {
6127 0 : printf("open of %s failed (%s)\n",
6128 : fname,
6129 : nt_errstr(status));
6130 0 : goto fail;
6131 : }
6132 :
6133 0 : status = cli_writeall(cli1,
6134 : fnum1,
6135 : 0,
6136 : (const uint8_t *)buf,
6137 : 0, /* offset */
6138 : strlen(buf), /* size */
6139 : NULL);
6140 0 : if (!NT_STATUS_IS_OK(status)) {
6141 0 : printf("writing print file data failed (%s)\n",
6142 : nt_errstr(status));
6143 0 : goto fail;
6144 : }
6145 :
6146 0 : status = cli_nt_delete_on_close(cli1, fnum1, true);
6147 0 : if (!NT_STATUS_IS_OK(status)) {
6148 0 : printf("setting delete_on_close failed (%s)\n",
6149 : nt_errstr(status));
6150 0 : goto fail;
6151 : }
6152 :
6153 0 : status = cli_close(cli1, fnum1);
6154 0 : if (!NT_STATUS_IS_OK(status)) {
6155 0 : printf("close failed (%s)\n", nt_errstr(status));
6156 0 : goto fail;
6157 : }
6158 :
6159 0 : printf("finished print delete test\n");
6160 :
6161 0 : correct = true;
6162 :
6163 0 : fail:
6164 :
6165 0 : if (fnum1 != (uint16_t)-1) {
6166 0 : cli_close(cli1, fnum1);
6167 : }
6168 :
6169 0 : if (cli1 && !torture_close_connection(cli1)) {
6170 0 : correct = false;
6171 : }
6172 0 : return correct;
6173 : }
6174 :
6175 0 : static bool run_deletetest_ln(int dummy)
6176 : {
6177 : struct cli_state *cli;
6178 0 : const char *fname = "\\delete1";
6179 0 : const char *fname_ln = "\\delete1_ln";
6180 : uint16_t fnum;
6181 : uint16_t fnum1;
6182 : NTSTATUS status;
6183 0 : bool correct = true;
6184 : time_t t;
6185 :
6186 0 : printf("starting deletetest-ln\n");
6187 :
6188 0 : if (!torture_open_connection(&cli, 0)) {
6189 0 : return false;
6190 : }
6191 :
6192 0 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6193 0 : cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6194 :
6195 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6196 :
6197 : /* Create the file. */
6198 0 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6199 0 : if (!NT_STATUS_IS_OK(status)) {
6200 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6201 0 : return false;
6202 : }
6203 :
6204 0 : status = cli_close(cli, fnum);
6205 0 : if (!NT_STATUS_IS_OK(status)) {
6206 0 : printf("close1 failed (%s)\n", nt_errstr(status));
6207 0 : return false;
6208 : }
6209 :
6210 : /* Now create a hardlink. */
6211 0 : status = cli_hardlink(cli, fname, fname_ln);
6212 0 : if (!NT_STATUS_IS_OK(status)) {
6213 0 : printf("nt hardlink failed (%s)\n", nt_errstr(status));
6214 0 : return false;
6215 : }
6216 :
6217 : /* Open the original file. */
6218 0 : status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6219 : FILE_ATTRIBUTE_NORMAL,
6220 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6221 : FILE_OPEN_IF, 0, 0, &fnum, NULL);
6222 0 : if (!NT_STATUS_IS_OK(status)) {
6223 0 : printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6224 0 : return false;
6225 : }
6226 :
6227 : /* Unlink the hard link path. */
6228 0 : status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6229 : FILE_ATTRIBUTE_NORMAL,
6230 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6231 : FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6232 0 : if (!NT_STATUS_IS_OK(status)) {
6233 0 : printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6234 0 : return false;
6235 : }
6236 0 : status = cli_nt_delete_on_close(cli, fnum1, true);
6237 0 : if (!NT_STATUS_IS_OK(status)) {
6238 0 : d_printf("(%s) failed to set delete_on_close %s: %s\n",
6239 : __location__, fname_ln, nt_errstr(status));
6240 0 : return false;
6241 : }
6242 :
6243 0 : status = cli_close(cli, fnum1);
6244 0 : if (!NT_STATUS_IS_OK(status)) {
6245 0 : printf("close %s failed (%s)\n",
6246 : fname_ln, nt_errstr(status));
6247 0 : return false;
6248 : }
6249 :
6250 0 : status = cli_close(cli, fnum);
6251 0 : if (!NT_STATUS_IS_OK(status)) {
6252 0 : printf("close %s failed (%s)\n",
6253 : fname, nt_errstr(status));
6254 0 : return false;
6255 : }
6256 :
6257 : /* Ensure the original file is still there. */
6258 0 : status = cli_getatr(cli, fname, NULL, NULL, &t);
6259 0 : if (!NT_STATUS_IS_OK(status)) {
6260 0 : printf("%s getatr on file %s failed (%s)\n",
6261 : __location__,
6262 : fname,
6263 : nt_errstr(status));
6264 0 : correct = False;
6265 : }
6266 :
6267 : /* Ensure the link path is gone. */
6268 0 : status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6269 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6270 0 : printf("%s, getatr for file %s returned wrong error code %s "
6271 : "- should have been deleted\n",
6272 : __location__,
6273 : fname_ln, nt_errstr(status));
6274 0 : correct = False;
6275 : }
6276 :
6277 0 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6278 0 : cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6279 :
6280 0 : if (!torture_close_connection(cli)) {
6281 0 : correct = false;
6282 : }
6283 :
6284 0 : printf("finished deletetest-ln\n");
6285 :
6286 0 : return correct;
6287 : }
6288 :
6289 : /*
6290 : print out server properties
6291 : */
6292 1 : static bool run_properties(int dummy)
6293 : {
6294 : struct cli_state *cli;
6295 1 : bool correct = True;
6296 :
6297 1 : printf("starting properties test\n");
6298 :
6299 1 : ZERO_STRUCT(cli);
6300 :
6301 1 : if (!torture_open_connection(&cli, 0)) {
6302 0 : return False;
6303 : }
6304 :
6305 1 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6306 :
6307 1 : d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6308 :
6309 1 : if (!torture_close_connection(cli)) {
6310 0 : correct = False;
6311 : }
6312 :
6313 1 : return correct;
6314 : }
6315 :
6316 :
6317 :
6318 : /* FIRST_DESIRED_ACCESS 0xf019f */
6319 : #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6320 : FILE_READ_EA| /* 0xf */ \
6321 : FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
6322 : FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
6323 : DELETE_ACCESS|READ_CONTROL_ACCESS|\
6324 : WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
6325 : /* SECOND_DESIRED_ACCESS 0xe0080 */
6326 : #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6327 : READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6328 : WRITE_OWNER_ACCESS /* 0xe0000 */
6329 :
6330 : #if 0
6331 : #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6332 : READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6333 : FILE_READ_DATA|\
6334 : WRITE_OWNER_ACCESS /* */
6335 : #endif
6336 :
6337 : /*
6338 : Test ntcreate calls made by xcopy
6339 : */
6340 1 : static bool run_xcopy(int dummy)
6341 : {
6342 : static struct cli_state *cli1;
6343 1 : const char *fname = "\\test.txt";
6344 1 : bool correct = True;
6345 : uint16_t fnum1, fnum2;
6346 : NTSTATUS status;
6347 :
6348 1 : printf("starting xcopy test\n");
6349 :
6350 1 : if (!torture_open_connection(&cli1, 0)) {
6351 0 : return False;
6352 : }
6353 :
6354 1 : status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6355 : FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6356 : FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6357 1 : if (!NT_STATUS_IS_OK(status)) {
6358 0 : printf("First open failed - %s\n", nt_errstr(status));
6359 0 : return False;
6360 : }
6361 :
6362 1 : status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6363 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6364 : FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6365 1 : if (!NT_STATUS_IS_OK(status)) {
6366 0 : printf("second open failed - %s\n", nt_errstr(status));
6367 0 : return False;
6368 : }
6369 :
6370 1 : if (!torture_close_connection(cli1)) {
6371 0 : correct = False;
6372 : }
6373 :
6374 1 : return correct;
6375 : }
6376 :
6377 : /*
6378 : Test rename on files open with share delete and no share delete.
6379 : */
6380 1 : static bool run_rename(int dummy)
6381 : {
6382 : static struct cli_state *cli1;
6383 1 : const char *fname = "\\test.txt";
6384 1 : const char *fname1 = "\\test1.txt";
6385 1 : bool correct = True;
6386 : uint16_t fnum1;
6387 : uint32_t attr;
6388 : NTSTATUS status;
6389 :
6390 1 : printf("starting rename test\n");
6391 :
6392 1 : if (!torture_open_connection(&cli1, 0)) {
6393 0 : return False;
6394 : }
6395 :
6396 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6397 1 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6398 :
6399 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6400 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6401 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6402 1 : if (!NT_STATUS_IS_OK(status)) {
6403 0 : printf("First open failed - %s\n", nt_errstr(status));
6404 0 : return False;
6405 : }
6406 :
6407 1 : status = cli_rename(cli1, fname, fname1, false);
6408 1 : if (!NT_STATUS_IS_OK(status)) {
6409 1 : printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6410 : } else {
6411 0 : printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6412 0 : correct = False;
6413 : }
6414 :
6415 1 : status = cli_close(cli1, fnum1);
6416 1 : if (!NT_STATUS_IS_OK(status)) {
6417 0 : printf("close - 1 failed (%s)\n", nt_errstr(status));
6418 0 : return False;
6419 : }
6420 :
6421 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6422 1 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6423 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6424 : #if 0
6425 : FILE_SHARE_DELETE|FILE_SHARE_NONE,
6426 : #else
6427 : FILE_SHARE_DELETE|FILE_SHARE_READ,
6428 : #endif
6429 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6430 1 : if (!NT_STATUS_IS_OK(status)) {
6431 0 : printf("Second open failed - %s\n", nt_errstr(status));
6432 0 : return False;
6433 : }
6434 :
6435 1 : status = cli_rename(cli1, fname, fname1, false);
6436 1 : if (!NT_STATUS_IS_OK(status)) {
6437 0 : printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6438 0 : correct = False;
6439 : } else {
6440 1 : printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6441 : }
6442 :
6443 1 : status = cli_close(cli1, fnum1);
6444 1 : if (!NT_STATUS_IS_OK(status)) {
6445 0 : printf("close - 2 failed (%s)\n", nt_errstr(status));
6446 0 : return False;
6447 : }
6448 :
6449 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6450 1 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6451 :
6452 1 : status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6453 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6454 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6455 1 : if (!NT_STATUS_IS_OK(status)) {
6456 0 : printf("Third open failed - %s\n", nt_errstr(status));
6457 0 : return False;
6458 : }
6459 :
6460 :
6461 1 : status = cli_rename(cli1, fname, fname1, false);
6462 1 : if (!NT_STATUS_IS_OK(status)) {
6463 0 : printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6464 0 : correct = False;
6465 : } else {
6466 1 : printf("Third rename succeeded (SHARE_NONE)\n");
6467 : }
6468 :
6469 1 : status = cli_close(cli1, fnum1);
6470 1 : if (!NT_STATUS_IS_OK(status)) {
6471 0 : printf("close - 3 failed (%s)\n", nt_errstr(status));
6472 0 : return False;
6473 : }
6474 :
6475 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6476 1 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6477 :
6478 : /*----*/
6479 :
6480 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6481 : FILE_ATTRIBUTE_NORMAL,
6482 : FILE_SHARE_READ | FILE_SHARE_WRITE,
6483 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6484 1 : if (!NT_STATUS_IS_OK(status)) {
6485 0 : printf("Fourth open failed - %s\n", nt_errstr(status));
6486 0 : return False;
6487 : }
6488 :
6489 1 : status = cli_rename(cli1, fname, fname1, false);
6490 1 : if (!NT_STATUS_IS_OK(status)) {
6491 1 : printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6492 : } else {
6493 0 : printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6494 0 : correct = False;
6495 : }
6496 :
6497 1 : status = cli_close(cli1, fnum1);
6498 1 : if (!NT_STATUS_IS_OK(status)) {
6499 0 : printf("close - 4 failed (%s)\n", nt_errstr(status));
6500 0 : return False;
6501 : }
6502 :
6503 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6504 1 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6505 :
6506 : /*--*/
6507 :
6508 1 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6509 : FILE_ATTRIBUTE_NORMAL,
6510 : FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6511 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6512 1 : if (!NT_STATUS_IS_OK(status)) {
6513 0 : printf("Fifth open failed - %s\n", nt_errstr(status));
6514 0 : return False;
6515 : }
6516 :
6517 1 : status = cli_rename(cli1, fname, fname1, false);
6518 1 : if (!NT_STATUS_IS_OK(status)) {
6519 0 : printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6520 0 : correct = False;
6521 : } else {
6522 1 : printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6523 : }
6524 :
6525 : /*--*/
6526 1 : status = cli_close(cli1, fnum1);
6527 1 : if (!NT_STATUS_IS_OK(status)) {
6528 0 : printf("close - 5 failed (%s)\n", nt_errstr(status));
6529 0 : return False;
6530 : }
6531 :
6532 : /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6533 1 : status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6534 1 : if (!NT_STATUS_IS_OK(status)) {
6535 0 : printf("getatr on file %s failed - %s ! \n",
6536 : fname1, nt_errstr(status));
6537 0 : correct = False;
6538 : } else {
6539 1 : if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6540 0 : printf("Renamed file %s has wrong attr 0x%x "
6541 : "(should be 0x%x)\n",
6542 : fname1,
6543 : attr,
6544 : (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6545 0 : correct = False;
6546 : } else {
6547 1 : printf("Renamed file %s has archive bit set\n", fname1);
6548 : }
6549 : }
6550 :
6551 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6552 1 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6553 :
6554 1 : if (!torture_close_connection(cli1)) {
6555 0 : correct = False;
6556 : }
6557 :
6558 1 : return correct;
6559 : }
6560 :
6561 : /*
6562 : Test rename into a directory with an ACL denying it.
6563 : */
6564 0 : static bool run_rename_access(int dummy)
6565 : {
6566 : static struct cli_state *cli = NULL;
6567 : static struct cli_state *posix_cli = NULL;
6568 0 : const char *src = "test.txt";
6569 0 : const char *dname = "dir";
6570 0 : const char *dst = "dir\\test.txt";
6571 0 : const char *dsrc = "test.dir";
6572 0 : const char *ddst = "dir\\test.dir";
6573 0 : uint16_t fnum = (uint16_t)-1;
6574 0 : struct security_descriptor *sd = NULL;
6575 0 : struct security_descriptor *newsd = NULL;
6576 : NTSTATUS status;
6577 0 : TALLOC_CTX *frame = NULL;
6578 :
6579 0 : frame = talloc_stackframe();
6580 0 : printf("starting rename access test\n");
6581 :
6582 : /* Windows connection. */
6583 0 : if (!torture_open_connection(&cli, 0)) {
6584 0 : goto fail;
6585 : }
6586 :
6587 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6588 :
6589 : /* Posix connection. */
6590 0 : if (!torture_open_connection(&posix_cli, 0)) {
6591 0 : goto fail;
6592 : }
6593 :
6594 0 : smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6595 :
6596 0 : status = torture_setup_unix_extensions(posix_cli);
6597 0 : if (!NT_STATUS_IS_OK(status)) {
6598 0 : goto fail;
6599 : }
6600 :
6601 : /* Start with a clean slate. */
6602 0 : cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6603 0 : cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6604 0 : cli_rmdir(cli, dsrc);
6605 0 : cli_rmdir(cli, ddst);
6606 0 : cli_rmdir(cli, dname);
6607 :
6608 : /*
6609 : * Setup the destination directory with a DENY ACE to
6610 : * prevent new files within it.
6611 : */
6612 0 : status = cli_ntcreate(cli,
6613 : dname,
6614 : 0,
6615 : FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6616 : WRITE_DAC_ACCESS|FILE_READ_DATA|
6617 : WRITE_OWNER_ACCESS,
6618 : FILE_ATTRIBUTE_DIRECTORY,
6619 : FILE_SHARE_READ|FILE_SHARE_WRITE,
6620 : FILE_CREATE,
6621 : FILE_DIRECTORY_FILE,
6622 : 0,
6623 : &fnum,
6624 : NULL);
6625 0 : if (!NT_STATUS_IS_OK(status)) {
6626 0 : printf("Create of %s - %s\n", dname, nt_errstr(status));
6627 0 : goto fail;
6628 : }
6629 :
6630 0 : status = cli_query_secdesc(cli,
6631 : fnum,
6632 : frame,
6633 : &sd);
6634 0 : if (!NT_STATUS_IS_OK(status)) {
6635 0 : printf("cli_query_secdesc failed for %s (%s)\n",
6636 : dname, nt_errstr(status));
6637 0 : goto fail;
6638 : }
6639 :
6640 0 : newsd = security_descriptor_dacl_create(frame,
6641 : 0,
6642 : NULL,
6643 : NULL,
6644 : SID_WORLD,
6645 : SEC_ACE_TYPE_ACCESS_DENIED,
6646 : SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6647 : 0,
6648 : NULL);
6649 0 : if (newsd == NULL) {
6650 0 : goto fail;
6651 : }
6652 0 : sd->dacl = security_acl_concatenate(frame,
6653 0 : newsd->dacl,
6654 0 : sd->dacl);
6655 0 : if (sd->dacl == NULL) {
6656 0 : goto fail;
6657 : }
6658 0 : status = cli_set_secdesc(cli, fnum, sd);
6659 0 : if (!NT_STATUS_IS_OK(status)) {
6660 0 : printf("cli_set_secdesc failed for %s (%s)\n",
6661 : dname, nt_errstr(status));
6662 0 : goto fail;
6663 : }
6664 0 : status = cli_close(cli, fnum);
6665 0 : if (!NT_STATUS_IS_OK(status)) {
6666 0 : printf("close failed for %s (%s)\n",
6667 : dname, nt_errstr(status));
6668 0 : goto fail;
6669 : }
6670 : /* Now go around the back and chmod to 777 via POSIX. */
6671 0 : status = cli_posix_chmod(posix_cli, dname, 0777);
6672 0 : if (!NT_STATUS_IS_OK(status)) {
6673 0 : printf("cli_posix_chmod failed for %s (%s)\n",
6674 : dname, nt_errstr(status));
6675 0 : goto fail;
6676 : }
6677 :
6678 : /* Check we can't create a file within dname via Windows. */
6679 0 : status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6680 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6681 0 : cli_close(posix_cli, fnum);
6682 0 : printf("Create of %s should be ACCESS denied, was %s\n",
6683 : dst, nt_errstr(status));
6684 0 : goto fail;
6685 : }
6686 :
6687 : /* Make the sample file/directory. */
6688 0 : status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6689 0 : if (!NT_STATUS_IS_OK(status)) {
6690 0 : printf("open of %s failed (%s)\n", src, nt_errstr(status));
6691 0 : goto fail;
6692 : }
6693 0 : status = cli_close(cli, fnum);
6694 0 : if (!NT_STATUS_IS_OK(status)) {
6695 0 : printf("cli_close failed (%s)\n", nt_errstr(status));
6696 0 : goto fail;
6697 : }
6698 :
6699 0 : status = cli_mkdir(cli, dsrc);
6700 0 : if (!NT_STATUS_IS_OK(status)) {
6701 0 : printf("cli_mkdir of %s failed (%s)\n",
6702 : dsrc, nt_errstr(status));
6703 0 : goto fail;
6704 : }
6705 :
6706 : /*
6707 : * OK - renames of the new file and directory into the
6708 : * dst directory should fail.
6709 : */
6710 :
6711 0 : status = cli_rename(cli, src, dst, false);
6712 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6713 0 : printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6714 : src, dst, nt_errstr(status));
6715 0 : goto fail;
6716 : }
6717 0 : status = cli_rename(cli, dsrc, ddst, false);
6718 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6719 0 : printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6720 : src, dst, nt_errstr(status));
6721 0 : goto fail;
6722 : }
6723 :
6724 0 : TALLOC_FREE(frame);
6725 0 : return true;
6726 :
6727 0 : fail:
6728 :
6729 0 : if (posix_cli) {
6730 0 : torture_close_connection(posix_cli);
6731 : }
6732 :
6733 0 : if (cli) {
6734 0 : if (fnum != (uint16_t)-1) {
6735 0 : cli_close(cli, fnum);
6736 : }
6737 0 : cli_unlink(cli, src,
6738 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6739 0 : cli_unlink(cli, dst,
6740 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6741 0 : cli_rmdir(cli, dsrc);
6742 0 : cli_rmdir(cli, ddst);
6743 0 : cli_rmdir(cli, dname);
6744 :
6745 0 : torture_close_connection(cli);
6746 : }
6747 :
6748 0 : TALLOC_FREE(frame);
6749 0 : return false;
6750 : }
6751 :
6752 : /*
6753 : Test owner rights ACE.
6754 : */
6755 0 : static bool run_owner_rights(int dummy)
6756 : {
6757 : static struct cli_state *cli = NULL;
6758 0 : const char *fname = "owner_rights.txt";
6759 0 : uint16_t fnum = (uint16_t)-1;
6760 0 : struct security_descriptor *sd = NULL;
6761 0 : struct security_descriptor *newsd = NULL;
6762 : NTSTATUS status;
6763 0 : TALLOC_CTX *frame = NULL;
6764 :
6765 0 : frame = talloc_stackframe();
6766 0 : printf("starting owner rights test\n");
6767 :
6768 : /* Windows connection. */
6769 0 : if (!torture_open_connection(&cli, 0)) {
6770 0 : goto fail;
6771 : }
6772 :
6773 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6774 :
6775 : /* Start with a clean slate. */
6776 0 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6777 :
6778 : /* Create the test file. */
6779 : /* Now try and open for read and write-dac. */
6780 0 : status = cli_ntcreate(cli,
6781 : fname,
6782 : 0,
6783 : GENERIC_ALL_ACCESS,
6784 : FILE_ATTRIBUTE_NORMAL,
6785 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6786 : FILE_SHARE_DELETE,
6787 : FILE_CREATE,
6788 : 0,
6789 : 0,
6790 : &fnum,
6791 : NULL);
6792 0 : if (!NT_STATUS_IS_OK(status)) {
6793 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
6794 0 : goto fail;
6795 : }
6796 :
6797 : /* Get the original SD. */
6798 0 : status = cli_query_secdesc(cli,
6799 : fnum,
6800 : frame,
6801 : &sd);
6802 0 : if (!NT_STATUS_IS_OK(status)) {
6803 0 : printf("cli_query_secdesc failed for %s (%s)\n",
6804 : fname, nt_errstr(status));
6805 0 : goto fail;
6806 : }
6807 :
6808 : /*
6809 : * Add an "owner-rights" ACE denying WRITE_DATA,
6810 : * and an "owner-rights" ACE allowing READ_DATA.
6811 : */
6812 :
6813 0 : newsd = security_descriptor_dacl_create(frame,
6814 : 0,
6815 : NULL,
6816 : NULL,
6817 : SID_OWNER_RIGHTS,
6818 : SEC_ACE_TYPE_ACCESS_DENIED,
6819 : FILE_WRITE_DATA,
6820 : 0,
6821 : SID_OWNER_RIGHTS,
6822 : SEC_ACE_TYPE_ACCESS_ALLOWED,
6823 : FILE_READ_DATA,
6824 : 0,
6825 : NULL);
6826 0 : if (newsd == NULL) {
6827 0 : goto fail;
6828 : }
6829 0 : sd->dacl = security_acl_concatenate(frame,
6830 0 : newsd->dacl,
6831 0 : sd->dacl);
6832 0 : if (sd->dacl == NULL) {
6833 0 : goto fail;
6834 : }
6835 0 : status = cli_set_secdesc(cli, fnum, sd);
6836 0 : if (!NT_STATUS_IS_OK(status)) {
6837 0 : printf("cli_set_secdesc failed for %s (%s)\n",
6838 : fname, nt_errstr(status));
6839 0 : goto fail;
6840 : }
6841 0 : status = cli_close(cli, fnum);
6842 0 : if (!NT_STATUS_IS_OK(status)) {
6843 0 : printf("close failed for %s (%s)\n",
6844 : fname, nt_errstr(status));
6845 0 : goto fail;
6846 : }
6847 0 : fnum = (uint16_t)-1;
6848 :
6849 : /* Try and open for FILE_WRITE_DATA */
6850 0 : status = cli_ntcreate(cli,
6851 : fname,
6852 : 0,
6853 : FILE_WRITE_DATA,
6854 : FILE_ATTRIBUTE_NORMAL,
6855 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6856 : FILE_SHARE_DELETE,
6857 : FILE_OPEN,
6858 : 0,
6859 : 0,
6860 : &fnum,
6861 : NULL);
6862 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6863 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
6864 0 : goto fail;
6865 : }
6866 :
6867 : /* Now try and open for FILE_READ_DATA */
6868 0 : status = cli_ntcreate(cli,
6869 : fname,
6870 : 0,
6871 : FILE_READ_DATA,
6872 : FILE_ATTRIBUTE_NORMAL,
6873 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6874 : FILE_SHARE_DELETE,
6875 : FILE_OPEN,
6876 : 0,
6877 : 0,
6878 : &fnum,
6879 : NULL);
6880 0 : if (!NT_STATUS_IS_OK(status)) {
6881 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
6882 0 : goto fail;
6883 : }
6884 :
6885 0 : status = cli_close(cli, fnum);
6886 0 : if (!NT_STATUS_IS_OK(status)) {
6887 0 : printf("close failed for %s (%s)\n",
6888 : fname, nt_errstr(status));
6889 0 : goto fail;
6890 : }
6891 :
6892 : /* Restore clean slate. */
6893 0 : TALLOC_FREE(sd);
6894 0 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6895 :
6896 : /* Create the test file. */
6897 0 : status = cli_ntcreate(cli,
6898 : fname,
6899 : 0,
6900 : GENERIC_ALL_ACCESS,
6901 : FILE_ATTRIBUTE_NORMAL,
6902 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6903 : FILE_SHARE_DELETE,
6904 : FILE_CREATE,
6905 : 0,
6906 : 0,
6907 : &fnum,
6908 : NULL);
6909 0 : if (!NT_STATUS_IS_OK(status)) {
6910 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
6911 0 : goto fail;
6912 : }
6913 :
6914 : /* Get the original SD. */
6915 0 : status = cli_query_secdesc(cli,
6916 : fnum,
6917 : frame,
6918 : &sd);
6919 0 : if (!NT_STATUS_IS_OK(status)) {
6920 0 : printf("cli_query_secdesc failed for %s (%s)\n",
6921 : fname, nt_errstr(status));
6922 0 : goto fail;
6923 : }
6924 :
6925 : /*
6926 : * Add an "owner-rights ACE denying WRITE_DATA,
6927 : * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6928 : */
6929 :
6930 0 : newsd = security_descriptor_dacl_create(frame,
6931 : 0,
6932 : NULL,
6933 : NULL,
6934 : SID_OWNER_RIGHTS,
6935 : SEC_ACE_TYPE_ACCESS_DENIED,
6936 : FILE_WRITE_DATA,
6937 : 0,
6938 : SID_OWNER_RIGHTS,
6939 : SEC_ACE_TYPE_ACCESS_ALLOWED,
6940 : FILE_READ_DATA|FILE_WRITE_DATA,
6941 : 0,
6942 : NULL);
6943 0 : if (newsd == NULL) {
6944 0 : goto fail;
6945 : }
6946 0 : sd->dacl = security_acl_concatenate(frame,
6947 0 : newsd->dacl,
6948 0 : sd->dacl);
6949 0 : if (sd->dacl == NULL) {
6950 0 : goto fail;
6951 : }
6952 0 : status = cli_set_secdesc(cli, fnum, sd);
6953 0 : if (!NT_STATUS_IS_OK(status)) {
6954 0 : printf("cli_set_secdesc failed for %s (%s)\n",
6955 : fname, nt_errstr(status));
6956 0 : goto fail;
6957 : }
6958 0 : status = cli_close(cli, fnum);
6959 0 : if (!NT_STATUS_IS_OK(status)) {
6960 0 : printf("close failed for %s (%s)\n",
6961 : fname, nt_errstr(status));
6962 0 : goto fail;
6963 : }
6964 0 : fnum = (uint16_t)-1;
6965 :
6966 : /* Try and open for FILE_WRITE_DATA */
6967 0 : status = cli_ntcreate(cli,
6968 : fname,
6969 : 0,
6970 : FILE_WRITE_DATA,
6971 : FILE_ATTRIBUTE_NORMAL,
6972 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6973 : FILE_SHARE_DELETE,
6974 : FILE_OPEN,
6975 : 0,
6976 : 0,
6977 : &fnum,
6978 : NULL);
6979 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6980 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
6981 0 : goto fail;
6982 : }
6983 :
6984 : /* Now try and open for FILE_READ_DATA */
6985 0 : status = cli_ntcreate(cli,
6986 : fname,
6987 : 0,
6988 : FILE_READ_DATA,
6989 : FILE_ATTRIBUTE_NORMAL,
6990 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6991 : FILE_SHARE_DELETE,
6992 : FILE_OPEN,
6993 : 0,
6994 : 0,
6995 : &fnum,
6996 : NULL);
6997 0 : if (!NT_STATUS_IS_OK(status)) {
6998 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
6999 0 : goto fail;
7000 : }
7001 :
7002 0 : status = cli_close(cli, fnum);
7003 0 : if (!NT_STATUS_IS_OK(status)) {
7004 0 : printf("close failed for %s (%s)\n",
7005 : fname, nt_errstr(status));
7006 0 : goto fail;
7007 : }
7008 :
7009 : /* Restore clean slate. */
7010 0 : TALLOC_FREE(sd);
7011 0 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7012 :
7013 :
7014 : /* Create the test file. */
7015 0 : status = cli_ntcreate(cli,
7016 : fname,
7017 : 0,
7018 : GENERIC_ALL_ACCESS,
7019 : FILE_ATTRIBUTE_NORMAL,
7020 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7021 : FILE_SHARE_DELETE,
7022 : FILE_CREATE,
7023 : 0,
7024 : 0,
7025 : &fnum,
7026 : NULL);
7027 0 : if (!NT_STATUS_IS_OK(status)) {
7028 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
7029 0 : goto fail;
7030 : }
7031 :
7032 : /* Get the original SD. */
7033 0 : status = cli_query_secdesc(cli,
7034 : fnum,
7035 : frame,
7036 : &sd);
7037 0 : if (!NT_STATUS_IS_OK(status)) {
7038 0 : printf("cli_query_secdesc failed for %s (%s)\n",
7039 : fname, nt_errstr(status));
7040 0 : goto fail;
7041 : }
7042 :
7043 : /*
7044 : * Add an "authenticated users" ACE allowing READ_DATA,
7045 : * add an "owner-rights" denying READ_DATA,
7046 : * and an "authenticated users" ACE allowing WRITE_DATA.
7047 : */
7048 :
7049 0 : newsd = security_descriptor_dacl_create(frame,
7050 : 0,
7051 : NULL,
7052 : NULL,
7053 : SID_NT_AUTHENTICATED_USERS,
7054 : SEC_ACE_TYPE_ACCESS_ALLOWED,
7055 : FILE_READ_DATA,
7056 : 0,
7057 : SID_OWNER_RIGHTS,
7058 : SEC_ACE_TYPE_ACCESS_DENIED,
7059 : FILE_READ_DATA,
7060 : 0,
7061 : SID_NT_AUTHENTICATED_USERS,
7062 : SEC_ACE_TYPE_ACCESS_ALLOWED,
7063 : FILE_WRITE_DATA,
7064 : 0,
7065 : NULL);
7066 0 : if (newsd == NULL) {
7067 0 : printf("newsd == NULL\n");
7068 0 : goto fail;
7069 : }
7070 0 : sd->dacl = security_acl_concatenate(frame,
7071 0 : newsd->dacl,
7072 0 : sd->dacl);
7073 0 : if (sd->dacl == NULL) {
7074 0 : printf("sd->dacl == NULL\n");
7075 0 : goto fail;
7076 : }
7077 0 : status = cli_set_secdesc(cli, fnum, sd);
7078 0 : if (!NT_STATUS_IS_OK(status)) {
7079 0 : printf("cli_set_secdesc failed for %s (%s)\n",
7080 : fname, nt_errstr(status));
7081 0 : goto fail;
7082 : }
7083 0 : status = cli_close(cli, fnum);
7084 0 : if (!NT_STATUS_IS_OK(status)) {
7085 0 : printf("close failed for %s (%s)\n",
7086 : fname, nt_errstr(status));
7087 0 : goto fail;
7088 : }
7089 0 : fnum = (uint16_t)-1;
7090 :
7091 : /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7092 0 : status = cli_ntcreate(cli,
7093 : fname,
7094 : 0,
7095 : FILE_READ_DATA|FILE_WRITE_DATA,
7096 : FILE_ATTRIBUTE_NORMAL,
7097 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7098 : FILE_SHARE_DELETE,
7099 : FILE_OPEN,
7100 : 0,
7101 : 0,
7102 : &fnum,
7103 : NULL);
7104 0 : if (!NT_STATUS_IS_OK(status)) {
7105 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
7106 0 : goto fail;
7107 : }
7108 :
7109 0 : status = cli_close(cli, fnum);
7110 0 : if (!NT_STATUS_IS_OK(status)) {
7111 0 : printf("close failed for %s (%s)\n",
7112 : fname, nt_errstr(status));
7113 0 : goto fail;
7114 : }
7115 :
7116 0 : cli_unlink(cli, fname,
7117 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7118 :
7119 0 : TALLOC_FREE(frame);
7120 0 : return true;
7121 :
7122 0 : fail:
7123 :
7124 0 : if (cli) {
7125 0 : if (fnum != (uint16_t)-1) {
7126 0 : cli_close(cli, fnum);
7127 : }
7128 0 : cli_unlink(cli, fname,
7129 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7130 0 : torture_close_connection(cli);
7131 : }
7132 :
7133 0 : TALLOC_FREE(frame);
7134 0 : return false;
7135 : }
7136 :
7137 : /*
7138 : * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7139 : * Note this test only works with a user with SeSecurityPrivilege set.
7140 : *
7141 : * NB. This is also tested in samba3.base.createx_access
7142 : * but this makes it very explicit what we're looking for.
7143 : */
7144 0 : static bool run_smb1_system_security(int dummy)
7145 : {
7146 : static struct cli_state *cli = NULL;
7147 0 : const char *fname = "system_security.txt";
7148 0 : uint16_t fnum = (uint16_t)-1;
7149 : NTSTATUS status;
7150 0 : TALLOC_CTX *frame = NULL;
7151 :
7152 0 : frame = talloc_stackframe();
7153 0 : printf("starting smb1 system security test\n");
7154 :
7155 : /* SMB1 connection - torture_open_connection() forces this. */
7156 0 : if (!torture_open_connection(&cli, 0)) {
7157 0 : goto fail;
7158 : }
7159 :
7160 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
7161 :
7162 : /* Start with a clean slate. */
7163 0 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7164 :
7165 : /* Create the test file. */
7166 0 : status = cli_ntcreate(cli,
7167 : fname,
7168 : 0,
7169 : GENERIC_ALL_ACCESS,
7170 : FILE_ATTRIBUTE_NORMAL,
7171 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7172 : FILE_SHARE_DELETE,
7173 : FILE_CREATE,
7174 : 0,
7175 : 0,
7176 : &fnum,
7177 : NULL);
7178 0 : if (!NT_STATUS_IS_OK(status)) {
7179 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
7180 0 : goto fail;
7181 : }
7182 :
7183 0 : status = cli_close(cli, fnum);
7184 :
7185 : /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7186 : /*
7187 : * On SMB1 this succeeds - SMB2 it fails,
7188 : * see the SMB2-SACL test.
7189 : */
7190 0 : status = cli_ntcreate(cli,
7191 : fname,
7192 : 0,
7193 : SEC_FLAG_SYSTEM_SECURITY,
7194 : FILE_ATTRIBUTE_NORMAL,
7195 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7196 : FILE_SHARE_DELETE,
7197 : FILE_OPEN,
7198 : 0,
7199 : 0,
7200 : &fnum,
7201 : NULL);
7202 0 : if (!NT_STATUS_IS_OK(status)) {
7203 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
7204 0 : goto fail;
7205 : }
7206 :
7207 0 : status = cli_close(cli, fnum);
7208 :
7209 0 : cli_unlink(cli, fname,
7210 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7211 :
7212 0 : torture_close_connection(cli);
7213 0 : TALLOC_FREE(frame);
7214 0 : return true;
7215 :
7216 0 : fail:
7217 :
7218 0 : if (cli) {
7219 0 : if (fnum != (uint16_t)-1) {
7220 0 : cli_close(cli, fnum);
7221 : }
7222 0 : cli_unlink(cli, fname,
7223 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7224 0 : torture_close_connection(cli);
7225 : }
7226 :
7227 0 : TALLOC_FREE(frame);
7228 0 : return false;
7229 : }
7230 :
7231 0 : static bool run_pipe_number(int dummy)
7232 : {
7233 : struct cli_state *cli1;
7234 0 : const char *pipe_name = "\\SPOOLSS";
7235 : uint16_t fnum;
7236 0 : int num_pipes = 0;
7237 : NTSTATUS status;
7238 :
7239 0 : printf("starting pipenumber test\n");
7240 0 : if (!torture_open_connection(&cli1, 0)) {
7241 0 : return False;
7242 : }
7243 :
7244 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
7245 : while(1) {
7246 0 : status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7247 : FILE_ATTRIBUTE_NORMAL,
7248 : FILE_SHARE_READ|FILE_SHARE_WRITE,
7249 : FILE_OPEN_IF, 0, 0, &fnum, NULL);
7250 0 : if (!NT_STATUS_IS_OK(status)) {
7251 0 : printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7252 0 : break;
7253 : }
7254 0 : num_pipes++;
7255 0 : printf("\r%6d", num_pipes);
7256 : }
7257 :
7258 0 : printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7259 0 : torture_close_connection(cli1);
7260 0 : return True;
7261 : }
7262 :
7263 : /*
7264 : Test open mode returns on read-only files.
7265 : */
7266 1 : static bool run_opentest(int dummy)
7267 : {
7268 : static struct cli_state *cli1;
7269 : static struct cli_state *cli2;
7270 1 : const char *fname = "\\readonly.file";
7271 : uint16_t fnum1, fnum2;
7272 : char buf[20];
7273 : off_t fsize;
7274 1 : bool correct = True;
7275 : char *tmp_path;
7276 : NTSTATUS status;
7277 :
7278 1 : printf("starting open test\n");
7279 :
7280 1 : if (!torture_open_connection(&cli1, 0)) {
7281 0 : return False;
7282 : }
7283 :
7284 1 : cli_setatr(cli1, fname, 0, 0);
7285 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7286 :
7287 1 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
7288 :
7289 1 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7290 1 : if (!NT_STATUS_IS_OK(status)) {
7291 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7292 0 : return False;
7293 : }
7294 :
7295 1 : status = cli_close(cli1, fnum1);
7296 1 : if (!NT_STATUS_IS_OK(status)) {
7297 0 : printf("close2 failed (%s)\n", nt_errstr(status));
7298 0 : return False;
7299 : }
7300 :
7301 1 : status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7302 1 : if (!NT_STATUS_IS_OK(status)) {
7303 0 : printf("cli_setatr failed (%s)\n", nt_errstr(status));
7304 0 : return False;
7305 : }
7306 :
7307 1 : status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7308 1 : if (!NT_STATUS_IS_OK(status)) {
7309 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7310 0 : return False;
7311 : }
7312 :
7313 : /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7314 1 : status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7315 :
7316 1 : if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7317 1 : NT_STATUS_ACCESS_DENIED)) {
7318 0 : printf("correct error code ERRDOS/ERRnoaccess returned\n");
7319 : }
7320 :
7321 1 : printf("finished open test 1\n");
7322 :
7323 1 : cli_close(cli1, fnum1);
7324 :
7325 : /* Now try not readonly and ensure ERRbadshare is returned. */
7326 :
7327 1 : cli_setatr(cli1, fname, 0, 0);
7328 :
7329 1 : status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7330 1 : if (!NT_STATUS_IS_OK(status)) {
7331 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7332 0 : return False;
7333 : }
7334 :
7335 : /* This will fail - but the error should be ERRshare. */
7336 1 : status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7337 :
7338 1 : if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7339 1 : NT_STATUS_SHARING_VIOLATION)) {
7340 1 : printf("correct error code ERRDOS/ERRbadshare returned\n");
7341 : }
7342 :
7343 1 : status = cli_close(cli1, fnum1);
7344 1 : if (!NT_STATUS_IS_OK(status)) {
7345 0 : printf("close2 failed (%s)\n", nt_errstr(status));
7346 0 : return False;
7347 : }
7348 :
7349 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7350 :
7351 1 : printf("finished open test 2\n");
7352 :
7353 : /* Test truncate open disposition on file opened for read. */
7354 1 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7355 1 : if (!NT_STATUS_IS_OK(status)) {
7356 0 : printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7357 0 : return False;
7358 : }
7359 :
7360 : /* write 20 bytes. */
7361 :
7362 1 : memset(buf, '\0', 20);
7363 :
7364 1 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7365 1 : if (!NT_STATUS_IS_OK(status)) {
7366 0 : printf("write failed (%s)\n", nt_errstr(status));
7367 0 : correct = False;
7368 : }
7369 :
7370 1 : status = cli_close(cli1, fnum1);
7371 1 : if (!NT_STATUS_IS_OK(status)) {
7372 0 : printf("(3) close1 failed (%s)\n", nt_errstr(status));
7373 0 : return False;
7374 : }
7375 :
7376 : /* Ensure size == 20. */
7377 1 : status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7378 1 : if (!NT_STATUS_IS_OK(status)) {
7379 0 : printf("(3) getatr failed (%s)\n", nt_errstr(status));
7380 0 : return False;
7381 : }
7382 :
7383 1 : if (fsize != 20) {
7384 0 : printf("(3) file size != 20\n");
7385 0 : return False;
7386 : }
7387 :
7388 : /* Now test if we can truncate a file opened for readonly. */
7389 1 : status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7390 1 : if (!NT_STATUS_IS_OK(status)) {
7391 0 : printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7392 0 : return False;
7393 : }
7394 :
7395 1 : status = cli_close(cli1, fnum1);
7396 1 : if (!NT_STATUS_IS_OK(status)) {
7397 0 : printf("close2 failed (%s)\n", nt_errstr(status));
7398 0 : return False;
7399 : }
7400 :
7401 : /* Ensure size == 0. */
7402 1 : status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7403 1 : if (!NT_STATUS_IS_OK(status)) {
7404 0 : printf("(3) getatr failed (%s)\n", nt_errstr(status));
7405 0 : return False;
7406 : }
7407 :
7408 1 : if (fsize != 0) {
7409 0 : printf("(3) file size != 0\n");
7410 0 : return False;
7411 : }
7412 1 : printf("finished open test 3\n");
7413 :
7414 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7415 :
7416 1 : printf("Do ctemp tests\n");
7417 1 : status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7418 1 : if (!NT_STATUS_IS_OK(status)) {
7419 0 : printf("ctemp failed (%s)\n", nt_errstr(status));
7420 0 : return False;
7421 : }
7422 :
7423 1 : printf("ctemp gave path %s\n", tmp_path);
7424 1 : status = cli_close(cli1, fnum1);
7425 1 : if (!NT_STATUS_IS_OK(status)) {
7426 0 : printf("close of temp failed (%s)\n", nt_errstr(status));
7427 : }
7428 :
7429 1 : status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7430 1 : if (!NT_STATUS_IS_OK(status)) {
7431 0 : printf("unlink of temp failed (%s)\n", nt_errstr(status));
7432 : }
7433 :
7434 : /* Test the non-io opens... */
7435 :
7436 1 : if (!torture_open_connection(&cli2, 1)) {
7437 0 : return False;
7438 : }
7439 :
7440 1 : cli_setatr(cli2, fname, 0, 0);
7441 1 : cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7442 :
7443 1 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
7444 :
7445 1 : printf("TEST #1 testing 2 non-io opens (no delete)\n");
7446 1 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7447 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7448 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7449 1 : if (!NT_STATUS_IS_OK(status)) {
7450 0 : printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7451 0 : return False;
7452 : }
7453 :
7454 1 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7455 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7456 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7457 1 : if (!NT_STATUS_IS_OK(status)) {
7458 0 : printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7459 0 : return False;
7460 : }
7461 :
7462 1 : status = cli_close(cli1, fnum1);
7463 1 : if (!NT_STATUS_IS_OK(status)) {
7464 0 : printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7465 0 : return False;
7466 : }
7467 :
7468 1 : status = cli_close(cli2, fnum2);
7469 1 : if (!NT_STATUS_IS_OK(status)) {
7470 0 : printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7471 0 : return False;
7472 : }
7473 :
7474 1 : printf("non-io open test #1 passed.\n");
7475 :
7476 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7477 :
7478 1 : printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7479 :
7480 1 : status = cli_ntcreate(cli1, fname, 0,
7481 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7482 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7483 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7484 1 : if (!NT_STATUS_IS_OK(status)) {
7485 0 : printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7486 0 : return False;
7487 : }
7488 :
7489 1 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7490 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7491 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7492 1 : if (!NT_STATUS_IS_OK(status)) {
7493 0 : printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7494 0 : return False;
7495 : }
7496 :
7497 1 : status = cli_close(cli1, fnum1);
7498 1 : if (!NT_STATUS_IS_OK(status)) {
7499 0 : printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7500 0 : return False;
7501 : }
7502 :
7503 1 : status = cli_close(cli2, fnum2);
7504 1 : if (!NT_STATUS_IS_OK(status)) {
7505 0 : printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7506 0 : return False;
7507 : }
7508 :
7509 1 : printf("non-io open test #2 passed.\n");
7510 :
7511 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7512 :
7513 1 : printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7514 :
7515 1 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7516 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7517 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7518 1 : if (!NT_STATUS_IS_OK(status)) {
7519 0 : printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7520 0 : return False;
7521 : }
7522 :
7523 1 : status = cli_ntcreate(cli2, fname, 0,
7524 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7525 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7526 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7527 1 : if (!NT_STATUS_IS_OK(status)) {
7528 0 : printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7529 0 : return False;
7530 : }
7531 :
7532 1 : status = cli_close(cli1, fnum1);
7533 1 : if (!NT_STATUS_IS_OK(status)) {
7534 0 : printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7535 0 : return False;
7536 : }
7537 :
7538 1 : status = cli_close(cli2, fnum2);
7539 1 : if (!NT_STATUS_IS_OK(status)) {
7540 0 : printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7541 0 : return False;
7542 : }
7543 :
7544 1 : printf("non-io open test #3 passed.\n");
7545 :
7546 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7547 :
7548 1 : printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7549 :
7550 1 : status = cli_ntcreate(cli1, fname, 0,
7551 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7552 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7553 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7554 1 : if (!NT_STATUS_IS_OK(status)) {
7555 0 : printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7556 0 : return False;
7557 : }
7558 :
7559 1 : status = cli_ntcreate(cli2, fname, 0,
7560 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7561 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7562 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7563 1 : if (NT_STATUS_IS_OK(status)) {
7564 0 : printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7565 0 : return False;
7566 : }
7567 :
7568 1 : printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7569 :
7570 1 : status = cli_close(cli1, fnum1);
7571 1 : if (!NT_STATUS_IS_OK(status)) {
7572 0 : printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7573 0 : return False;
7574 : }
7575 :
7576 1 : printf("non-io open test #4 passed.\n");
7577 :
7578 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7579 :
7580 1 : printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7581 :
7582 1 : status = cli_ntcreate(cli1, fname, 0,
7583 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7584 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7585 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7586 1 : if (!NT_STATUS_IS_OK(status)) {
7587 0 : printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7588 0 : return False;
7589 : }
7590 :
7591 1 : status = cli_ntcreate(cli2, fname, 0,
7592 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7593 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7594 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7595 1 : if (!NT_STATUS_IS_OK(status)) {
7596 0 : printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7597 0 : return False;
7598 : }
7599 :
7600 1 : status = cli_close(cli1, fnum1);
7601 1 : if (!NT_STATUS_IS_OK(status)) {
7602 0 : printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7603 0 : return False;
7604 : }
7605 :
7606 1 : status = cli_close(cli2, fnum2);
7607 1 : if (!NT_STATUS_IS_OK(status)) {
7608 0 : printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7609 0 : return False;
7610 : }
7611 :
7612 1 : printf("non-io open test #5 passed.\n");
7613 :
7614 1 : printf("TEST #6 testing 1 non-io open, one io open\n");
7615 :
7616 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7617 :
7618 1 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7619 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7620 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7621 1 : if (!NT_STATUS_IS_OK(status)) {
7622 0 : printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7623 0 : return False;
7624 : }
7625 :
7626 1 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7627 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7628 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7629 1 : if (!NT_STATUS_IS_OK(status)) {
7630 0 : printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7631 0 : return False;
7632 : }
7633 :
7634 1 : status = cli_close(cli1, fnum1);
7635 1 : if (!NT_STATUS_IS_OK(status)) {
7636 0 : printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7637 0 : return False;
7638 : }
7639 :
7640 1 : status = cli_close(cli2, fnum2);
7641 1 : if (!NT_STATUS_IS_OK(status)) {
7642 0 : printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7643 0 : return False;
7644 : }
7645 :
7646 1 : printf("non-io open test #6 passed.\n");
7647 :
7648 1 : printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7649 :
7650 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7651 :
7652 1 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7653 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7654 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7655 1 : if (!NT_STATUS_IS_OK(status)) {
7656 0 : printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7657 0 : return False;
7658 : }
7659 :
7660 1 : status = cli_ntcreate(cli2, fname, 0,
7661 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7662 : FILE_ATTRIBUTE_NORMAL,
7663 : FILE_SHARE_READ|FILE_SHARE_DELETE,
7664 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7665 1 : if (NT_STATUS_IS_OK(status)) {
7666 0 : printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7667 0 : return False;
7668 : }
7669 :
7670 1 : printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7671 :
7672 1 : status = cli_close(cli1, fnum1);
7673 1 : if (!NT_STATUS_IS_OK(status)) {
7674 0 : printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7675 0 : return False;
7676 : }
7677 :
7678 1 : printf("non-io open test #7 passed.\n");
7679 :
7680 1 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7681 :
7682 1 : printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7683 1 : status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7684 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7685 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7686 1 : if (!NT_STATUS_IS_OK(status)) {
7687 0 : printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7688 0 : correct = false;
7689 0 : goto out;
7690 : }
7691 :
7692 : /* Write to ensure we have to update the file time. */
7693 1 : status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7694 : NULL);
7695 1 : if (!NT_STATUS_IS_OK(status)) {
7696 0 : printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7697 0 : correct = false;
7698 0 : goto out;
7699 : }
7700 :
7701 1 : status = cli_close(cli1, fnum1);
7702 1 : if (!NT_STATUS_IS_OK(status)) {
7703 0 : printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7704 0 : correct = false;
7705 : }
7706 :
7707 2 : out:
7708 :
7709 1 : if (!torture_close_connection(cli1)) {
7710 0 : correct = False;
7711 : }
7712 1 : if (!torture_close_connection(cli2)) {
7713 0 : correct = False;
7714 : }
7715 :
7716 1 : return correct;
7717 : }
7718 :
7719 0 : NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7720 : {
7721 : uint16_t major, minor;
7722 : uint32_t caplow, caphigh;
7723 : NTSTATUS status;
7724 :
7725 0 : if (!SERVER_HAS_UNIX_CIFS(cli)) {
7726 0 : printf("Server doesn't support UNIX CIFS extensions.\n");
7727 0 : return NT_STATUS_NOT_SUPPORTED;
7728 : }
7729 :
7730 0 : status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7731 : &caphigh);
7732 0 : if (!NT_STATUS_IS_OK(status)) {
7733 0 : printf("Server didn't return UNIX CIFS extensions: %s\n",
7734 : nt_errstr(status));
7735 0 : return status;
7736 : }
7737 :
7738 0 : status = cli_set_unix_extensions_capabilities(cli, major, minor,
7739 : caplow, caphigh);
7740 0 : if (!NT_STATUS_IS_OK(status)) {
7741 0 : printf("Server doesn't support setting UNIX CIFS extensions: "
7742 : "%s.\n", nt_errstr(status));
7743 0 : return status;
7744 : }
7745 :
7746 0 : return NT_STATUS_OK;
7747 : }
7748 :
7749 : /*
7750 : Test POSIX open /mkdir calls.
7751 : */
7752 0 : static bool run_simple_posix_open_test(int dummy)
7753 : {
7754 : static struct cli_state *cli1;
7755 0 : const char *fname = "posix:file";
7756 0 : const char *hname = "posix:hlink";
7757 0 : const char *sname = "posix:symlink";
7758 0 : const char *dname = "posix:dir";
7759 : char buf[10];
7760 0 : char *target = NULL;
7761 0 : uint16_t fnum1 = (uint16_t)-1;
7762 : SMB_STRUCT_STAT sbuf;
7763 0 : bool correct = false;
7764 : NTSTATUS status;
7765 : size_t nread;
7766 0 : const char *fname_windows = "windows_file";
7767 0 : uint16_t fnum2 = (uint16_t)-1;
7768 :
7769 0 : printf("Starting simple POSIX open test\n");
7770 :
7771 0 : if (!torture_open_connection(&cli1, 0)) {
7772 0 : return false;
7773 : }
7774 :
7775 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
7776 :
7777 0 : status = torture_setup_unix_extensions(cli1);
7778 0 : if (!NT_STATUS_IS_OK(status)) {
7779 0 : return false;
7780 : }
7781 :
7782 0 : cli_setatr(cli1, fname, 0, 0);
7783 0 : cli_posix_unlink(cli1, fname);
7784 0 : cli_setatr(cli1, dname, 0, 0);
7785 0 : cli_posix_rmdir(cli1, dname);
7786 0 : cli_setatr(cli1, hname, 0, 0);
7787 0 : cli_posix_unlink(cli1, hname);
7788 0 : cli_setatr(cli1, sname, 0, 0);
7789 0 : cli_posix_unlink(cli1, sname);
7790 0 : cli_setatr(cli1, fname_windows, 0, 0);
7791 0 : cli_posix_unlink(cli1, fname_windows);
7792 :
7793 : /* Create a directory. */
7794 0 : status = cli_posix_mkdir(cli1, dname, 0777);
7795 0 : if (!NT_STATUS_IS_OK(status)) {
7796 0 : printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7797 0 : goto out;
7798 : }
7799 :
7800 0 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7801 : 0600, &fnum1);
7802 0 : if (!NT_STATUS_IS_OK(status)) {
7803 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7804 0 : goto out;
7805 : }
7806 :
7807 : /* Test ftruncate - set file size. */
7808 0 : status = cli_ftruncate(cli1, fnum1, 1000);
7809 0 : if (!NT_STATUS_IS_OK(status)) {
7810 0 : printf("ftruncate failed (%s)\n", nt_errstr(status));
7811 0 : goto out;
7812 : }
7813 :
7814 : /* Ensure st_size == 1000 */
7815 0 : status = cli_posix_stat(cli1, fname, &sbuf);
7816 0 : if (!NT_STATUS_IS_OK(status)) {
7817 0 : printf("stat failed (%s)\n", nt_errstr(status));
7818 0 : goto out;
7819 : }
7820 :
7821 0 : if (sbuf.st_ex_size != 1000) {
7822 0 : printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7823 0 : goto out;
7824 : }
7825 :
7826 : /* Ensure st_mode == 0600 */
7827 0 : if ((sbuf.st_ex_mode & 07777) != 0600) {
7828 0 : printf("posix_open - bad permissions 0%o != 0600\n",
7829 0 : (unsigned int)(sbuf.st_ex_mode & 07777));
7830 0 : goto out;
7831 : }
7832 :
7833 : /* Test ftruncate - set file size back to zero. */
7834 0 : status = cli_ftruncate(cli1, fnum1, 0);
7835 0 : if (!NT_STATUS_IS_OK(status)) {
7836 0 : printf("ftruncate failed (%s)\n", nt_errstr(status));
7837 0 : goto out;
7838 : }
7839 :
7840 0 : status = cli_close(cli1, fnum1);
7841 0 : if (!NT_STATUS_IS_OK(status)) {
7842 0 : printf("close failed (%s)\n", nt_errstr(status));
7843 0 : goto out;
7844 : }
7845 :
7846 : /* Now open the file again for read only. */
7847 0 : status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7848 0 : if (!NT_STATUS_IS_OK(status)) {
7849 0 : printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7850 0 : goto out;
7851 : }
7852 :
7853 : /* Now unlink while open. */
7854 0 : status = cli_posix_unlink(cli1, fname);
7855 0 : if (!NT_STATUS_IS_OK(status)) {
7856 0 : printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7857 0 : goto out;
7858 : }
7859 :
7860 0 : status = cli_close(cli1, fnum1);
7861 0 : if (!NT_STATUS_IS_OK(status)) {
7862 0 : printf("close(2) failed (%s)\n", nt_errstr(status));
7863 0 : goto out;
7864 : }
7865 :
7866 : /* Ensure the file has gone. */
7867 0 : status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7868 0 : if (NT_STATUS_IS_OK(status)) {
7869 0 : printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7870 0 : goto out;
7871 : }
7872 :
7873 : /* Create again to test open with O_TRUNC. */
7874 0 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7875 0 : if (!NT_STATUS_IS_OK(status)) {
7876 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7877 0 : goto out;
7878 : }
7879 :
7880 : /* Test ftruncate - set file size. */
7881 0 : status = cli_ftruncate(cli1, fnum1, 1000);
7882 0 : if (!NT_STATUS_IS_OK(status)) {
7883 0 : printf("ftruncate failed (%s)\n", nt_errstr(status));
7884 0 : goto out;
7885 : }
7886 :
7887 : /* Ensure st_size == 1000 */
7888 0 : status = cli_posix_stat(cli1, fname, &sbuf);
7889 0 : if (!NT_STATUS_IS_OK(status)) {
7890 0 : printf("stat failed (%s)\n", nt_errstr(status));
7891 0 : goto out;
7892 : }
7893 :
7894 0 : if (sbuf.st_ex_size != 1000) {
7895 0 : printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7896 0 : goto out;
7897 : }
7898 :
7899 0 : status = cli_close(cli1, fnum1);
7900 0 : if (!NT_STATUS_IS_OK(status)) {
7901 0 : printf("close(2) failed (%s)\n", nt_errstr(status));
7902 0 : goto out;
7903 : }
7904 :
7905 : /* Re-open with O_TRUNC. */
7906 0 : status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7907 0 : if (!NT_STATUS_IS_OK(status)) {
7908 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7909 0 : goto out;
7910 : }
7911 :
7912 : /* Ensure st_size == 0 */
7913 0 : status = cli_posix_stat(cli1, fname, &sbuf);
7914 0 : if (!NT_STATUS_IS_OK(status)) {
7915 0 : printf("stat failed (%s)\n", nt_errstr(status));
7916 0 : goto out;
7917 : }
7918 :
7919 0 : if (sbuf.st_ex_size != 0) {
7920 0 : printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7921 0 : goto out;
7922 : }
7923 :
7924 0 : status = cli_close(cli1, fnum1);
7925 0 : if (!NT_STATUS_IS_OK(status)) {
7926 0 : printf("close failed (%s)\n", nt_errstr(status));
7927 0 : goto out;
7928 : }
7929 :
7930 0 : status = cli_posix_unlink(cli1, fname);
7931 0 : if (!NT_STATUS_IS_OK(status)) {
7932 0 : printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7933 0 : goto out;
7934 : }
7935 :
7936 0 : status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
7937 0 : if (!NT_STATUS_IS_OK(status)) {
7938 0 : printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
7939 : dname, nt_errstr(status));
7940 0 : goto out;
7941 : }
7942 :
7943 0 : cli_close(cli1, fnum1);
7944 :
7945 : /* What happens when we try and POSIX open a directory for write ? */
7946 0 : status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
7947 0 : if (NT_STATUS_IS_OK(status)) {
7948 0 : printf("POSIX open of directory %s succeeded, "
7949 : "should have failed.\n",
7950 : dname);
7951 0 : goto out;
7952 : } else {
7953 0 : if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
7954 0 : NT_STATUS_FILE_IS_A_DIRECTORY)) {
7955 0 : goto out;
7956 : }
7957 : }
7958 :
7959 : /* Create the file. */
7960 0 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7961 : 0600, &fnum1);
7962 0 : if (!NT_STATUS_IS_OK(status)) {
7963 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7964 0 : goto out;
7965 : }
7966 :
7967 : /* Write some data into it. */
7968 0 : status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7969 : NULL);
7970 0 : if (!NT_STATUS_IS_OK(status)) {
7971 0 : printf("cli_write failed: %s\n", nt_errstr(status));
7972 0 : goto out;
7973 : }
7974 :
7975 0 : cli_close(cli1, fnum1);
7976 :
7977 : /* Now create a hardlink. */
7978 0 : status = cli_posix_hardlink(cli1, fname, hname);
7979 0 : if (!NT_STATUS_IS_OK(status)) {
7980 0 : printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
7981 0 : goto out;
7982 : }
7983 :
7984 : /* Now create a symlink. */
7985 0 : status = cli_posix_symlink(cli1, fname, sname);
7986 0 : if (!NT_STATUS_IS_OK(status)) {
7987 0 : printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
7988 0 : goto out;
7989 : }
7990 :
7991 : /* Open the hardlink for read. */
7992 0 : status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
7993 0 : if (!NT_STATUS_IS_OK(status)) {
7994 0 : printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
7995 0 : goto out;
7996 : }
7997 :
7998 0 : status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
7999 0 : if (!NT_STATUS_IS_OK(status)) {
8000 0 : printf("POSIX read of %s failed (%s)\n", hname,
8001 : nt_errstr(status));
8002 0 : goto out;
8003 0 : } else if (nread != 10) {
8004 0 : printf("POSIX read of %s failed. Received %ld, expected %d\n",
8005 : hname, (unsigned long)nread, 10);
8006 0 : goto out;
8007 : }
8008 :
8009 0 : if (memcmp(buf, "TEST DATA\n", 10)) {
8010 0 : printf("invalid data read from hardlink\n");
8011 0 : goto out;
8012 : }
8013 :
8014 : /* Do a POSIX lock/unlock. */
8015 0 : status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8016 0 : if (!NT_STATUS_IS_OK(status)) {
8017 0 : printf("POSIX lock failed %s\n", nt_errstr(status));
8018 0 : goto out;
8019 : }
8020 :
8021 : /* Punch a hole in the locked area. */
8022 0 : status = cli_posix_unlock(cli1, fnum1, 10, 80);
8023 0 : if (!NT_STATUS_IS_OK(status)) {
8024 0 : printf("POSIX unlock failed %s\n", nt_errstr(status));
8025 0 : goto out;
8026 : }
8027 :
8028 0 : cli_close(cli1, fnum1);
8029 :
8030 : /* Open the symlink for read - this should fail. A POSIX
8031 : client should not be doing opens on a symlink. */
8032 0 : status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8033 0 : if (NT_STATUS_IS_OK(status)) {
8034 0 : printf("POSIX open of %s succeeded (should have failed)\n", sname);
8035 0 : goto out;
8036 : } else {
8037 0 : if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
8038 0 : NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
8039 0 : printf("POSIX open of %s should have failed "
8040 : "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8041 : "failed with %s instead.\n",
8042 : sname, nt_errstr(status));
8043 0 : goto out;
8044 : }
8045 : }
8046 :
8047 0 : status = cli_posix_readlink(cli1, sname, talloc_tos(), &target);
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 2 : d_printf("cli_write_andx_recv returned %s: %d\n",
10428 : nt_errstr(status),
10429 2 : 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 8 : 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 7 : 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 4 : 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()/cli_state_restore_tcon().
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 819 : 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 0 : struct tevent_req *req =
14720 0 : tevent_req_callback_data(subreq,
14721 : struct tevent_req);
14722 0 : 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 0 : struct tevent_req *req =
14872 0 : tevent_req_callback_data(subreq,
14873 : struct tevent_req);
14874 0 : 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 = "CLEANUP1",
15752 : .fn = run_cleanup1,
15753 : },
15754 : {
15755 : .name = "CLEANUP2",
15756 : .fn = run_cleanup2,
15757 : },
15758 : {
15759 : .name = "CLEANUP4",
15760 : .fn = run_cleanup4,
15761 : },
15762 : {
15763 : .name = "OPLOCK-CANCEL",
15764 : .fn = run_oplock_cancel,
15765 : },
15766 : {
15767 : .name = "SMB2-INVALID-PIPENAME",
15768 : .fn = run_smb2_invalid_pipename,
15769 : },
15770 : {
15771 : .name = "SMB1-TRUNCATED-SESSSETUP",
15772 : .fn = run_smb1_truncated_sesssetup,
15773 : },
15774 : {
15775 : .name = "SMB1-NEGOTIATE-EXIT",
15776 : .fn = run_smb1_negotiate_exit,
15777 : },
15778 : {
15779 : .name = "SMB1-NEGOTIATE-TCON",
15780 : .fn = run_smb1_negotiate_tcon,
15781 : },
15782 : {
15783 : .name = "PIDHIGH",
15784 : .fn = run_pidhigh,
15785 : },
15786 : {
15787 : .name = "LOCAL-SUBSTITUTE",
15788 : .fn = run_local_substitute,
15789 : },
15790 : {
15791 : .name = "LOCAL-GENCACHE",
15792 : .fn = run_local_gencache,
15793 : },
15794 : {
15795 : .name = "LOCAL-DBWRAP-WATCH1",
15796 : .fn = run_dbwrap_watch1,
15797 : },
15798 : {
15799 : .name = "LOCAL-DBWRAP-WATCH2",
15800 : .fn = run_dbwrap_watch2,
15801 : },
15802 : {
15803 : .name = "LOCAL-DBWRAP-WATCH3",
15804 : .fn = run_dbwrap_watch3,
15805 : },
15806 : {
15807 : .name = "LOCAL-DBWRAP-WATCH4",
15808 : .fn = run_dbwrap_watch4,
15809 : },
15810 : {
15811 : .name = "LOCAL-DBWRAP-DO-LOCKED1",
15812 : .fn = run_dbwrap_do_locked1,
15813 : },
15814 : {
15815 : .name = "LOCAL-MESSAGING-READ1",
15816 : .fn = run_messaging_read1,
15817 : },
15818 : {
15819 : .name = "LOCAL-MESSAGING-READ2",
15820 : .fn = run_messaging_read2,
15821 : },
15822 : {
15823 : .name = "LOCAL-MESSAGING-READ3",
15824 : .fn = run_messaging_read3,
15825 : },
15826 : {
15827 : .name = "LOCAL-MESSAGING-READ4",
15828 : .fn = run_messaging_read4,
15829 : },
15830 : {
15831 : .name = "LOCAL-MESSAGING-FDPASS1",
15832 : .fn = run_messaging_fdpass1,
15833 : },
15834 : {
15835 : .name = "LOCAL-MESSAGING-FDPASS2",
15836 : .fn = run_messaging_fdpass2,
15837 : },
15838 : {
15839 : .name = "LOCAL-MESSAGING-FDPASS2a",
15840 : .fn = run_messaging_fdpass2a,
15841 : },
15842 : {
15843 : .name = "LOCAL-MESSAGING-FDPASS2b",
15844 : .fn = run_messaging_fdpass2b,
15845 : },
15846 : {
15847 : .name = "LOCAL-MESSAGING-SEND-ALL",
15848 : .fn = run_messaging_send_all,
15849 : },
15850 : {
15851 : .name = "LOCAL-BASE64",
15852 : .fn = run_local_base64,
15853 : },
15854 : {
15855 : .name = "LOCAL-RBTREE",
15856 : .fn = run_local_rbtree,
15857 : },
15858 : {
15859 : .name = "LOCAL-MEMCACHE",
15860 : .fn = run_local_memcache,
15861 : },
15862 : {
15863 : .name = "LOCAL-STREAM-NAME",
15864 : .fn = run_local_stream_name,
15865 : },
15866 : {
15867 : .name = "LOCAL-STR-MATCH-MSWILD",
15868 : .fn = run_str_match_mswild,
15869 : },
15870 : {
15871 : .name = "LOCAL-STR-MATCH-REGEX-SUB1",
15872 : .fn = run_str_match_regex_sub1,
15873 : },
15874 : {
15875 : .name = "WBCLIENT-MULTI-PING",
15876 : .fn = run_wbclient_multi_ping,
15877 : },
15878 : {
15879 : .name = "LOCAL-string_to_sid",
15880 : .fn = run_local_string_to_sid,
15881 : },
15882 : {
15883 : .name = "LOCAL-sid_to_string",
15884 : .fn = run_local_sid_to_string,
15885 : },
15886 : {
15887 : .name = "LOCAL-binary_to_sid",
15888 : .fn = run_local_binary_to_sid,
15889 : },
15890 : {
15891 : .name = "LOCAL-DBTRANS",
15892 : .fn = run_local_dbtrans,
15893 : },
15894 : {
15895 : .name = "LOCAL-TEVENT-POLL",
15896 : .fn = run_local_tevent_poll,
15897 : },
15898 : {
15899 : .name = "LOCAL-CONVERT-STRING",
15900 : .fn = run_local_convert_string,
15901 : },
15902 : {
15903 : .name = "LOCAL-CONV-AUTH-INFO",
15904 : .fn = run_local_conv_auth_info,
15905 : },
15906 : {
15907 : .name = "LOCAL-hex_encode_buf",
15908 : .fn = run_local_hex_encode_buf,
15909 : },
15910 : {
15911 : .name = "LOCAL-IDMAP-TDB-COMMON",
15912 : .fn = run_idmap_tdb_common_test,
15913 : },
15914 : {
15915 : .name = "LOCAL-remove_duplicate_addrs2",
15916 : .fn = run_local_remove_duplicate_addrs2,
15917 : },
15918 : {
15919 : .name = "local-tdb-opener",
15920 : .fn = run_local_tdb_opener,
15921 : },
15922 : {
15923 : .name = "local-tdb-writer",
15924 : .fn = run_local_tdb_writer,
15925 : },
15926 : {
15927 : .name = "LOCAL-DBWRAP-CTDB1",
15928 : .fn = run_local_dbwrap_ctdb1,
15929 : },
15930 : {
15931 : .name = "LOCAL-BENCH-PTHREADPOOL",
15932 : .fn = run_bench_pthreadpool,
15933 : },
15934 : {
15935 : .name = "LOCAL-PTHREADPOOL-TEVENT",
15936 : .fn = run_pthreadpool_tevent,
15937 : },
15938 : {
15939 : .name = "LOCAL-G-LOCK1",
15940 : .fn = run_g_lock1,
15941 : },
15942 : {
15943 : .name = "LOCAL-G-LOCK2",
15944 : .fn = run_g_lock2,
15945 : },
15946 : {
15947 : .name = "LOCAL-G-LOCK3",
15948 : .fn = run_g_lock3,
15949 : },
15950 : {
15951 : .name = "LOCAL-G-LOCK4",
15952 : .fn = run_g_lock4,
15953 : },
15954 : {
15955 : .name = "LOCAL-G-LOCK4A",
15956 : .fn = run_g_lock4a,
15957 : },
15958 : {
15959 : .name = "LOCAL-G-LOCK5",
15960 : .fn = run_g_lock5,
15961 : },
15962 : {
15963 : .name = "LOCAL-G-LOCK6",
15964 : .fn = run_g_lock6,
15965 : },
15966 : {
15967 : .name = "LOCAL-G-LOCK7",
15968 : .fn = run_g_lock7,
15969 : },
15970 : {
15971 : .name = "LOCAL-G-LOCK8",
15972 : .fn = run_g_lock8,
15973 : },
15974 : {
15975 : .name = "LOCAL-G-LOCK-PING-PONG",
15976 : .fn = run_g_lock_ping_pong,
15977 : },
15978 : {
15979 : .name = "LOCAL-CANONICALIZE-PATH",
15980 : .fn = run_local_canonicalize_path,
15981 : },
15982 : {
15983 : .name = "LOCAL-NAMEMAP-CACHE1",
15984 : .fn = run_local_namemap_cache1,
15985 : },
15986 : {
15987 : .name = "LOCAL-IDMAP-CACHE1",
15988 : .fn = run_local_idmap_cache1,
15989 : },
15990 : {
15991 : .name = "qpathinfo-bufsize",
15992 : .fn = run_qpathinfo_bufsize,
15993 : },
15994 : {
15995 : .name = "hide-new-files-timeout",
15996 : .fn = run_hidenewfiles,
15997 : },
15998 : #ifdef CLUSTER_SUPPORT
15999 : {
16000 : .name = "ctdbd-conn1",
16001 : .fn = run_ctdbd_conn1,
16002 : },
16003 : #endif
16004 : {
16005 : .name = "readdir-timestamp",
16006 : .fn = run_readdir_timestamp,
16007 : },
16008 : {
16009 : .name = "rpc-scale",
16010 : .fn = run_rpc_scale,
16011 : },
16012 : {
16013 : .name = NULL,
16014 : },
16015 : };
16016 :
16017 : /****************************************************************************
16018 : run a specified test or "ALL"
16019 : ****************************************************************************/
16020 56 : static bool run_test(const char *name)
16021 : {
16022 56 : bool ret = True;
16023 56 : bool result = True;
16024 56 : bool found = False;
16025 : int i;
16026 : double t;
16027 56 : if (strequal(name,"ALL")) {
16028 0 : for (i=0;torture_ops[i].name;i++) {
16029 0 : run_test(torture_ops[i].name);
16030 : }
16031 0 : found = True;
16032 : }
16033 :
16034 11032 : for (i=0;torture_ops[i].name;i++) {
16035 10976 : fstr_sprintf(randomfname, "\\XX%x",
16036 10976 : (unsigned)random());
16037 :
16038 10976 : if (strequal(name, torture_ops[i].name)) {
16039 56 : found = True;
16040 56 : printf("Running %s\n", name);
16041 56 : if (torture_ops[i].flags & FLAG_MULTIPROC) {
16042 2 : t = create_procs(torture_ops[i].fn, &result);
16043 2 : if (!result) {
16044 0 : ret = False;
16045 0 : printf("TEST %s FAILED!\n", name);
16046 : }
16047 : } else {
16048 : struct timeval start;
16049 54 : start = timeval_current();
16050 54 : if (!torture_ops[i].fn(0)) {
16051 6 : ret = False;
16052 6 : printf("TEST %s FAILED!\n", name);
16053 : }
16054 54 : t = timeval_elapsed(&start);
16055 : }
16056 56 : printf("%s took %g secs\n\n", name, t);
16057 : }
16058 : }
16059 :
16060 56 : if (!found) {
16061 0 : printf("Did not find a test named %s\n", name);
16062 0 : ret = False;
16063 : }
16064 :
16065 56 : return ret;
16066 : }
16067 :
16068 :
16069 0 : static void usage(void)
16070 : {
16071 : int i;
16072 :
16073 0 : printf("WARNING samba4 test suite is much more complete nowadays.\n");
16074 0 : printf("Please use samba4 torture.\n\n");
16075 :
16076 0 : printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
16077 :
16078 0 : printf("\t-d debuglevel\n");
16079 0 : printf("\t-U user%%pass\n");
16080 0 : printf("\t-k use kerberos\n");
16081 0 : printf("\t-N numprocs\n");
16082 0 : printf("\t-n my_netbios_name\n");
16083 0 : printf("\t-W workgroup\n");
16084 0 : printf("\t-o num_operations\n");
16085 0 : printf("\t-O socket_options\n");
16086 0 : printf("\t-m maximum protocol\n");
16087 0 : printf("\t-L use oplocks\n");
16088 0 : printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
16089 0 : printf("\t-A showall\n");
16090 0 : printf("\t-p port\n");
16091 0 : printf("\t-s seed\n");
16092 0 : printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
16093 0 : printf("\t-f filename filename to test\n");
16094 0 : printf("\t-e encrypt\n");
16095 0 : printf("\n\n");
16096 :
16097 0 : printf("tests are:");
16098 0 : for (i=0;torture_ops[i].name;i++) {
16099 0 : printf(" %s", torture_ops[i].name);
16100 : }
16101 0 : printf("\n");
16102 :
16103 0 : printf("default test is ALL\n");
16104 :
16105 0 : exit(1);
16106 : }
16107 :
16108 : /****************************************************************************
16109 : main program
16110 : ****************************************************************************/
16111 56 : int main(int argc,char *argv[])
16112 : {
16113 : int opt, i;
16114 : char *p;
16115 56 : int gotuser = 0;
16116 56 : int gotpass = 0;
16117 56 : bool correct = True;
16118 56 : TALLOC_CTX *frame = talloc_stackframe();
16119 56 : int seed = time(NULL);
16120 :
16121 : #ifdef HAVE_SETBUFFER
16122 56 : setbuffer(stdout, NULL, 0);
16123 : #endif
16124 :
16125 56 : setup_logging("smbtorture", DEBUG_STDOUT);
16126 :
16127 56 : smb_init_locale();
16128 56 : fault_setup();
16129 :
16130 56 : if (is_default_dyn_CONFIGFILE()) {
16131 56 : if(getenv("SMB_CONF_PATH")) {
16132 56 : set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
16133 : }
16134 : }
16135 56 : lp_load_global(get_dyn_CONFIGFILE());
16136 56 : load_interfaces();
16137 :
16138 56 : if (argc < 2) {
16139 0 : usage();
16140 : }
16141 :
16142 996 : for(p = argv[1]; *p; p++)
16143 940 : if(*p == '\\')
16144 0 : *p = '/';
16145 :
16146 56 : if (strncmp(argv[1], "//", 2)) {
16147 0 : usage();
16148 : }
16149 :
16150 56 : fstrcpy(host, &argv[1][2]);
16151 56 : p = strchr_m(&host[2],'/');
16152 56 : if (!p) {
16153 0 : usage();
16154 : }
16155 56 : *p = 0;
16156 56 : fstrcpy(share, p+1);
16157 :
16158 56 : fstrcpy(myname, get_myname(talloc_tos()));
16159 56 : if (!*myname) {
16160 0 : fprintf(stderr, "Failed to get my hostname.\n");
16161 0 : return 1;
16162 : }
16163 :
16164 56 : if (*username == 0 && getenv("LOGNAME")) {
16165 0 : fstrcpy(username,getenv("LOGNAME"));
16166 : }
16167 :
16168 56 : argc--;
16169 56 : argv++;
16170 :
16171 56 : fstrcpy(workgroup, lp_workgroup());
16172 :
16173 218 : while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
16174 4 : != EOF) {
16175 108 : switch (opt) {
16176 0 : case 'p':
16177 0 : port_to_use = atoi(optarg);
16178 0 : break;
16179 0 : case 's':
16180 0 : seed = atoi(optarg);
16181 0 : break;
16182 0 : case 'W':
16183 0 : fstrcpy(workgroup,optarg);
16184 0 : break;
16185 0 : case 'm':
16186 0 : lp_set_cmdline("client max protocol", optarg);
16187 0 : break;
16188 0 : case 'N':
16189 0 : torture_nprocs = atoi(optarg);
16190 0 : break;
16191 0 : case 'o':
16192 0 : torture_numops = atoi(optarg);
16193 0 : break;
16194 0 : case 'd':
16195 0 : lp_set_cmdline("log level", optarg);
16196 0 : break;
16197 0 : case 'O':
16198 0 : sockops = optarg;
16199 0 : break;
16200 0 : case 'L':
16201 0 : use_oplocks = True;
16202 0 : break;
16203 52 : case 'l':
16204 52 : local_path = optarg;
16205 52 : break;
16206 0 : case 'A':
16207 0 : torture_showall = True;
16208 0 : break;
16209 0 : case 'n':
16210 0 : fstrcpy(myname, optarg);
16211 0 : break;
16212 0 : case 'c':
16213 0 : client_txt = optarg;
16214 0 : break;
16215 0 : case 'e':
16216 0 : do_encrypt = true;
16217 0 : break;
16218 0 : case 'k':
16219 : #ifdef HAVE_KRB5
16220 0 : use_kerberos = True;
16221 : #else
16222 : d_printf("No kerberos support compiled in\n");
16223 : exit(1);
16224 : #endif
16225 0 : break;
16226 56 : case 'U':
16227 56 : gotuser = 1;
16228 56 : fstrcpy(username,optarg);
16229 56 : p = strchr_m(username,'%');
16230 56 : if (p) {
16231 56 : *p = 0;
16232 56 : fstrcpy(password, p+1);
16233 56 : gotpass = 1;
16234 : }
16235 56 : break;
16236 0 : case 'b':
16237 0 : fstrcpy(multishare_conn_fname, optarg);
16238 0 : use_multishare_conn = True;
16239 0 : break;
16240 0 : case 'B':
16241 0 : torture_blocksize = atoi(optarg);
16242 0 : break;
16243 0 : case 'f':
16244 0 : test_filename = SMB_STRDUP(optarg);
16245 0 : break;
16246 0 : default:
16247 0 : printf("Unknown option %c (%d)\n", (char)opt, opt);
16248 0 : usage();
16249 : }
16250 : }
16251 :
16252 56 : d_printf("using seed %d\n", seed);
16253 :
16254 56 : srandom(seed);
16255 :
16256 56 : if(use_kerberos && !gotuser) gotpass = True;
16257 :
16258 110 : while (!gotpass) {
16259 0 : char pwd[256] = {0};
16260 : int rc;
16261 :
16262 0 : rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
16263 0 : if (rc == 0) {
16264 0 : fstrcpy(password, pwd);
16265 0 : gotpass = 1;
16266 : }
16267 : }
16268 :
16269 56 : printf("host=%s share=%s user=%s myname=%s\n",
16270 : host, share, username, myname);
16271 :
16272 56 : torture_creds = cli_session_creds_init(frame,
16273 : username,
16274 : workgroup,
16275 : NULL, /* realm */
16276 : password,
16277 : use_kerberos,
16278 : false, /* fallback_after_kerberos */
16279 : false, /* use_ccache */
16280 : false); /* password_is_nt_hash */
16281 56 : if (torture_creds == NULL) {
16282 0 : d_printf("cli_session_creds_init() failed.\n");
16283 0 : exit(1);
16284 : }
16285 :
16286 56 : if (argc == optind) {
16287 0 : correct = run_test("ALL");
16288 : } else {
16289 112 : for (i=optind;i<argc;i++) {
16290 56 : if (!run_test(argv[i])) {
16291 6 : correct = False;
16292 : }
16293 : }
16294 : }
16295 :
16296 56 : TALLOC_FREE(frame);
16297 :
16298 56 : if (correct) {
16299 50 : return(0);
16300 : } else {
16301 6 : return(1);
16302 : }
16303 : }
|