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 "tldap_tls_connect.h"
31 : #include "../librpc/gen_ndr/svcctl.h"
32 : #include "../lib/util/memcache.h"
33 : #include "nsswitch/winbind_client.h"
34 : #include "dbwrap/dbwrap.h"
35 : #include "dbwrap/dbwrap_open.h"
36 : #include "dbwrap/dbwrap_rbt.h"
37 : #include "async_smb.h"
38 : #include "libsmb/libsmb.h"
39 : #include "libsmb/clirap.h"
40 : #include "trans2.h"
41 : #include "libsmb/nmblib.h"
42 : #include "../lib/util/tevent_ntstatus.h"
43 : #include "util_tdb.h"
44 : #include "../libcli/smb/read_smb.h"
45 : #include "../libcli/smb/smbXcli_base.h"
46 : #include "lib/util/sys_rw_data.h"
47 : #include "lib/util/base64.h"
48 : #include "lib/util/time.h"
49 : #include "lib/gencache.h"
50 : #include "lib/util/sys_rw.h"
51 : #include "lib/util/asn1.h"
52 : #include "lib/util/util_file.h"
53 : #include "lib/param/param.h"
54 : #include "auth/gensec/gensec.h"
55 : #include "lib/util/string_wrappers.h"
56 : #include "source3/lib/substitute.h"
57 : #include "ads.h"
58 :
59 : #include <gnutls/gnutls.h>
60 : #include <gnutls/crypto.h>
61 :
62 : extern char *optarg;
63 : extern int optind;
64 :
65 : fstring host, workgroup, share, password, username, myname;
66 : struct cli_credentials *torture_creds;
67 : static const char *sockops="TCP_NODELAY";
68 : int torture_nprocs=1;
69 : static int port_to_use=0;
70 : int torture_numops=100;
71 : int torture_blocksize=1024*1024;
72 : static int procnum; /* records process count number when forking */
73 : static struct cli_state *current_cli;
74 : static fstring randomfname;
75 : static bool use_oplocks;
76 : static bool use_level_II_oplocks;
77 : static const char *client_txt = "client_oplocks.txt";
78 : static bool disable_spnego;
79 : static bool use_kerberos;
80 : static bool force_dos_errors;
81 : static fstring multishare_conn_fname;
82 : static bool use_multishare_conn = False;
83 : static bool do_encrypt;
84 : static const char *local_path = NULL;
85 : static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
86 : char *test_filename;
87 :
88 : bool torture_showall = False;
89 :
90 : static double create_procs(bool (*fn)(int), bool *result);
91 :
92 : /********************************************************************
93 : Ensure a connection is encrypted.
94 : ********************************************************************/
95 :
96 200 : static bool force_cli_encryption(struct cli_state *c,
97 : const char *sharename)
98 : {
99 0 : uint16_t major, minor;
100 0 : uint32_t caplow, caphigh;
101 0 : NTSTATUS status;
102 :
103 200 : if (!SERVER_HAS_UNIX_CIFS(c)) {
104 0 : d_printf("Encryption required and "
105 : "server that doesn't support "
106 : "UNIX extensions - failing connect\n");
107 0 : return false;
108 : }
109 :
110 200 : status = cli_unix_extensions_version(c, &major, &minor, &caplow,
111 : &caphigh);
112 200 : if (!NT_STATUS_IS_OK(status)) {
113 0 : d_printf("Encryption required and "
114 : "can't get UNIX CIFS extensions "
115 : "version from server: %s\n", nt_errstr(status));
116 0 : return false;
117 : }
118 :
119 200 : if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
120 0 : d_printf("Encryption required and "
121 : "share %s doesn't support "
122 : "encryption.\n", sharename);
123 0 : return false;
124 : }
125 :
126 200 : status = cli_smb1_setup_encryption(c, torture_creds);
127 200 : if (!NT_STATUS_IS_OK(status)) {
128 0 : d_printf("Encryption required and "
129 : "setup failed with error %s.\n",
130 : nt_errstr(status));
131 0 : return false;
132 : }
133 :
134 200 : return true;
135 : }
136 :
137 :
138 100 : static struct cli_state *open_nbt_connection(void)
139 : {
140 0 : struct cli_state *c;
141 0 : NTSTATUS status;
142 100 : int flags = 0;
143 :
144 100 : if (disable_spnego) {
145 0 : flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
146 : }
147 :
148 100 : if (use_oplocks) {
149 0 : flags |= CLI_FULL_CONNECTION_OPLOCKS;
150 : }
151 :
152 100 : if (use_level_II_oplocks) {
153 0 : flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
154 : }
155 :
156 100 : if (force_dos_errors) {
157 0 : flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
158 : }
159 :
160 100 : status = cli_connect_nb(NULL,
161 : host,
162 : NULL,
163 : port_to_use,
164 : 0x20,
165 : myname,
166 : signing_state,
167 : flags,
168 : &c);
169 100 : if (!NT_STATUS_IS_OK(status)) {
170 0 : printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
171 0 : return NULL;
172 : }
173 :
174 100 : cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
175 :
176 100 : return c;
177 : }
178 :
179 : /****************************************************************************
180 : Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
181 : ****************************************************************************/
182 :
183 4 : static bool cli_bad_session_request(int fd,
184 : struct nmb_name *calling, struct nmb_name *called)
185 : {
186 0 : TALLOC_CTX *frame;
187 0 : uint8_t len_buf[4];
188 0 : struct iovec iov[3];
189 0 : ssize_t len;
190 0 : uint8_t *inbuf;
191 0 : int err;
192 4 : bool ret = false;
193 0 : uint8_t message_type;
194 0 : uint8_t error;
195 0 : struct tevent_context *ev;
196 0 : struct tevent_req *req;
197 :
198 4 : frame = talloc_stackframe();
199 :
200 4 : iov[0].iov_base = len_buf;
201 4 : iov[0].iov_len = sizeof(len_buf);
202 :
203 : /* put in the destination name */
204 :
205 4 : iov[1].iov_base = name_mangle(talloc_tos(), called->name,
206 4 : called->name_type);
207 4 : if (iov[1].iov_base == NULL) {
208 0 : goto fail;
209 : }
210 4 : iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
211 4 : talloc_get_size(iov[1].iov_base));
212 :
213 : /* and my name */
214 :
215 4 : iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
216 4 : calling->name_type);
217 4 : if (iov[2].iov_base == NULL) {
218 0 : goto fail;
219 : }
220 4 : iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
221 4 : talloc_get_size(iov[2].iov_base));
222 :
223 : /* Deliberately corrupt the name len (first byte) */
224 4 : *((uint8_t *)iov[2].iov_base) = 100;
225 :
226 : /* send a session request (RFC 1002) */
227 : /* setup the packet length
228 : * Remove four bytes from the length count, since the length
229 : * field in the NBT Session Service header counts the number
230 : * of bytes which follow. The cli_send_smb() function knows
231 : * about this and accounts for those four bytes.
232 : * CRH.
233 : */
234 :
235 4 : _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
236 4 : SCVAL(len_buf,0,0x81);
237 :
238 4 : len = write_data_iov(fd, iov, 3);
239 4 : if (len == -1) {
240 0 : goto fail;
241 : }
242 :
243 4 : ev = samba_tevent_context_init(frame);
244 4 : if (ev == NULL) {
245 0 : goto fail;
246 : }
247 4 : req = read_smb_send(frame, ev, fd);
248 4 : if (req == NULL) {
249 0 : goto fail;
250 : }
251 4 : if (!tevent_req_poll(req, ev)) {
252 0 : goto fail;
253 : }
254 4 : len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
255 4 : if (len == -1) {
256 0 : errno = err;
257 0 : goto fail;
258 : }
259 4 : TALLOC_FREE(ev);
260 :
261 4 : message_type = CVAL(inbuf, 0);
262 4 : if (message_type != 0x83) {
263 0 : d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
264 : message_type);
265 0 : goto fail;
266 : }
267 :
268 4 : if (smb_len(inbuf) != 1) {
269 0 : d_fprintf(stderr, "Expected smb_len 1, got %d\n",
270 0 : (int)smb_len(inbuf));
271 0 : goto fail;
272 : }
273 :
274 4 : error = CVAL(inbuf, 4);
275 4 : if (error != 0x82) {
276 0 : d_fprintf(stderr, "Expected error 0x82, got %d\n",
277 : (int)error);
278 0 : goto fail;
279 : }
280 :
281 4 : ret = true;
282 4 : fail:
283 4 : TALLOC_FREE(frame);
284 4 : return ret;
285 : }
286 :
287 : /* Insert a NULL at the first separator of the given path and return a pointer
288 : * to the remainder of the string.
289 : */
290 : static char *
291 0 : terminate_path_at_separator(char * path)
292 : {
293 0 : char * p;
294 :
295 0 : if (!path) {
296 0 : return NULL;
297 : }
298 :
299 0 : if ((p = strchr_m(path, '/'))) {
300 0 : *p = '\0';
301 0 : return p + 1;
302 : }
303 :
304 0 : if ((p = strchr_m(path, '\\'))) {
305 0 : *p = '\0';
306 0 : return p + 1;
307 : }
308 :
309 : /* No separator. */
310 0 : return NULL;
311 : }
312 :
313 : /*
314 : parse a //server/share type UNC name
315 : */
316 0 : bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
317 : char **hostname, char **sharename)
318 : {
319 0 : char *p;
320 :
321 0 : *hostname = *sharename = NULL;
322 :
323 0 : if (strncmp(unc_name, "\\\\", 2) &&
324 0 : strncmp(unc_name, "//", 2)) {
325 0 : return False;
326 : }
327 :
328 0 : *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
329 0 : p = terminate_path_at_separator(*hostname);
330 :
331 0 : if (p && *p) {
332 0 : *sharename = talloc_strdup(mem_ctx, p);
333 0 : terminate_path_at_separator(*sharename);
334 : }
335 :
336 0 : if (*hostname && *sharename) {
337 0 : return True;
338 : }
339 :
340 0 : TALLOC_FREE(*hostname);
341 0 : TALLOC_FREE(*sharename);
342 0 : return False;
343 : }
344 :
345 497 : static bool torture_open_connection_share(struct cli_state **c,
346 : const char *hostname,
347 : const char *sharename,
348 : int flags)
349 : {
350 0 : NTSTATUS status;
351 :
352 497 : status = cli_full_connection_creds(NULL,
353 : c,
354 : myname,
355 : hostname,
356 : NULL, /* dest_ss */
357 : port_to_use,
358 : sharename,
359 : "?????",
360 : torture_creds,
361 : flags);
362 497 : if (!NT_STATUS_IS_OK(status)) {
363 2 : printf("failed to open share connection: //%s/%s port:%d - %s\n",
364 : hostname, sharename, port_to_use, nt_errstr(status));
365 2 : return False;
366 : }
367 :
368 495 : cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
369 :
370 495 : if (do_encrypt) {
371 198 : return force_cli_encryption(*c,
372 : sharename);
373 : }
374 297 : return True;
375 : }
376 :
377 497 : bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
378 : {
379 497 : char **unc_list = NULL;
380 497 : int num_unc_names = 0;
381 0 : bool result;
382 :
383 497 : if (use_multishare_conn==True) {
384 0 : char *h, *s;
385 0 : unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
386 0 : if (!unc_list || num_unc_names <= 0) {
387 0 : printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
388 0 : exit(1);
389 : }
390 :
391 0 : if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
392 : NULL, &h, &s)) {
393 0 : printf("Failed to parse UNC name %s\n",
394 0 : unc_list[conn_index % num_unc_names]);
395 0 : TALLOC_FREE(unc_list);
396 0 : exit(1);
397 : }
398 :
399 0 : result = torture_open_connection_share(c, h, s, flags);
400 :
401 : /* h, s were copied earlier */
402 0 : TALLOC_FREE(unc_list);
403 0 : return result;
404 : }
405 :
406 497 : return torture_open_connection_share(c, host, share, flags);
407 : }
408 :
409 485 : bool torture_open_connection(struct cli_state **c, int conn_index)
410 : {
411 485 : int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
412 :
413 485 : if (use_oplocks) {
414 8 : flags |= CLI_FULL_CONNECTION_OPLOCKS;
415 : }
416 485 : if (use_level_II_oplocks) {
417 8 : flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
418 : }
419 :
420 485 : return torture_open_connection_flags(c, conn_index, flags);
421 : }
422 :
423 90 : bool torture_init_connection(struct cli_state **pcli)
424 : {
425 0 : struct cli_state *cli;
426 :
427 90 : cli = open_nbt_connection();
428 90 : if (cli == NULL) {
429 0 : return false;
430 : }
431 :
432 90 : *pcli = cli;
433 90 : return true;
434 : }
435 :
436 5 : bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
437 : {
438 5 : uint16_t old_vuid = cli_state_get_uid(cli);
439 0 : NTSTATUS status;
440 0 : bool ret;
441 :
442 5 : cli_state_set_uid(cli, 0);
443 5 : status = cli_session_setup_creds(cli, torture_creds);
444 5 : ret = NT_STATUS_IS_OK(status);
445 5 : *new_vuid = cli_state_get_uid(cli);
446 5 : cli_state_set_uid(cli, old_vuid);
447 5 : return ret;
448 : }
449 :
450 :
451 421 : bool torture_close_connection(struct cli_state *c)
452 : {
453 421 : bool ret = True;
454 0 : NTSTATUS status;
455 :
456 421 : status = cli_tdis(c);
457 421 : if (!NT_STATUS_IS_OK(status)) {
458 5 : printf("tdis failed (%s)\n", nt_errstr(status));
459 5 : ret = False;
460 : }
461 :
462 421 : cli_shutdown(c);
463 :
464 421 : return ret;
465 : }
466 :
467 48 : void torture_conn_set_sockopt(struct cli_state *cli)
468 : {
469 48 : smbXcli_conn_set_sockopt(cli->conn, sockops);
470 48 : }
471 :
472 58 : static NTSTATUS torture_delete_fn(struct file_info *finfo,
473 : const char *pattern,
474 : void *state)
475 : {
476 0 : NTSTATUS status;
477 58 : char *filename = NULL;
478 58 : char *dirname = NULL;
479 58 : char *p = NULL;
480 58 : TALLOC_CTX *frame = talloc_stackframe();
481 58 : struct cli_state *cli = (struct cli_state *)state;
482 :
483 58 : if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
484 36 : TALLOC_FREE(frame);
485 36 : return NT_STATUS_OK;
486 : }
487 :
488 22 : dirname = talloc_strdup(frame, pattern);
489 22 : if (dirname == NULL) {
490 0 : TALLOC_FREE(frame);
491 0 : return NT_STATUS_NO_MEMORY;
492 : }
493 22 : p = strrchr_m(dirname, '\\');
494 22 : if (p != NULL) {
495 : /* Remove the terminating '\' */
496 22 : *p = '\0';
497 : }
498 22 : if (dirname[0] != '\0') {
499 22 : filename = talloc_asprintf(frame,
500 : "%s\\%s",
501 : dirname,
502 : finfo->name);
503 : } else {
504 0 : filename = talloc_asprintf(frame,
505 : "%s",
506 : finfo->name);
507 : }
508 22 : if (filename == NULL) {
509 0 : TALLOC_FREE(frame);
510 0 : return NT_STATUS_NO_MEMORY;
511 : }
512 22 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
513 5 : char *subdirname = talloc_asprintf(frame,
514 : "%s\\*",
515 : filename);
516 5 : if (subdirname == NULL) {
517 0 : TALLOC_FREE(frame);
518 0 : return NT_STATUS_NO_MEMORY;
519 : }
520 5 : status = cli_list(cli,
521 : subdirname,
522 : FILE_ATTRIBUTE_DIRECTORY |
523 : FILE_ATTRIBUTE_HIDDEN |
524 : FILE_ATTRIBUTE_SYSTEM,
525 : torture_delete_fn,
526 : cli);
527 5 : if (!NT_STATUS_IS_OK(status)) {
528 0 : printf("torture_delete_fn: cli_list "
529 : "of %s failed (%s)\n",
530 : subdirname,
531 : nt_errstr(status));
532 0 : TALLOC_FREE(frame);
533 0 : return status;
534 : }
535 5 : status = cli_rmdir(cli, filename);
536 : } else {
537 17 : status = cli_unlink(cli,
538 : filename,
539 : FILE_ATTRIBUTE_SYSTEM |
540 : FILE_ATTRIBUTE_HIDDEN);
541 : }
542 22 : if (!NT_STATUS_IS_OK(status)) {
543 0 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
544 0 : printf("torture_delete_fn: cli_rmdir"
545 : " of %s failed (%s)\n",
546 : filename,
547 : nt_errstr(status));
548 : } else {
549 0 : printf("torture_delete_fn: cli_unlink"
550 : " of %s failed (%s)\n",
551 : filename,
552 : nt_errstr(status));
553 : }
554 : }
555 22 : TALLOC_FREE(frame);
556 22 : return status;
557 : }
558 :
559 30 : void torture_deltree(struct cli_state *cli, const char *dname)
560 : {
561 30 : char *mask = NULL;
562 0 : NTSTATUS status;
563 :
564 : /* It might be a file */
565 30 : (void)cli_unlink(cli,
566 : dname,
567 : FILE_ATTRIBUTE_SYSTEM |
568 : FILE_ATTRIBUTE_HIDDEN);
569 :
570 30 : mask = talloc_asprintf(cli,
571 : "%s\\*",
572 : dname);
573 30 : if (mask == NULL) {
574 0 : printf("torture_deltree: talloc_asprintf failed\n");
575 0 : return;
576 : }
577 :
578 30 : status = cli_list(cli,
579 : mask,
580 : FILE_ATTRIBUTE_DIRECTORY |
581 : FILE_ATTRIBUTE_HIDDEN|
582 : FILE_ATTRIBUTE_SYSTEM,
583 : torture_delete_fn,
584 : cli);
585 30 : if (!NT_STATUS_IS_OK(status)) {
586 17 : printf("torture_deltree: cli_list of %s failed (%s)\n",
587 : mask,
588 : nt_errstr(status));
589 : }
590 30 : TALLOC_FREE(mask);
591 30 : status = cli_rmdir(cli, dname);
592 30 : if (!NT_STATUS_IS_OK(status)) {
593 17 : printf("torture_deltree: cli_rmdir of %s failed (%s)\n",
594 : dname,
595 : nt_errstr(status));
596 : }
597 : }
598 :
599 : /* check if the server produced the expected dos or nt error code */
600 53 : static bool check_both_error(int line, NTSTATUS status,
601 : uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
602 : {
603 53 : if (NT_STATUS_IS_DOS(status)) {
604 0 : uint8_t cclass;
605 0 : uint32_t num;
606 :
607 : /* Check DOS error */
608 0 : cclass = NT_STATUS_DOS_CLASS(status);
609 0 : num = NT_STATUS_DOS_CODE(status);
610 :
611 0 : if (eclass != cclass || ecode != num) {
612 0 : printf("unexpected error code class=%d code=%d\n",
613 : (int)cclass, (int)num);
614 0 : printf(" expected %d/%d %s (line=%d)\n",
615 : (int)eclass, (int)ecode, nt_errstr(nterr), line);
616 0 : return false;
617 : }
618 : } else {
619 : /* Check NT error */
620 53 : if (!NT_STATUS_EQUAL(nterr, status)) {
621 0 : printf("unexpected error code %s\n",
622 : nt_errstr(status));
623 0 : printf(" expected %s (line=%d)\n",
624 : nt_errstr(nterr), line);
625 0 : return false;
626 : }
627 : }
628 :
629 53 : return true;
630 : }
631 :
632 :
633 : /* check if the server produced the expected error code */
634 38 : static bool check_error(int line, NTSTATUS status,
635 : uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
636 : {
637 38 : if (NT_STATUS_IS_DOS(status)) {
638 0 : uint8_t cclass;
639 0 : uint32_t num;
640 :
641 : /* Check DOS error */
642 :
643 0 : cclass = NT_STATUS_DOS_CLASS(status);
644 0 : num = NT_STATUS_DOS_CODE(status);
645 :
646 0 : if (eclass != cclass || ecode != num) {
647 0 : printf("unexpected error code class=%d code=%d\n",
648 : (int)cclass, (int)num);
649 0 : printf(" expected %d/%d %s (line=%d)\n",
650 : (int)eclass, (int)ecode, nt_errstr(nterr),
651 : line);
652 0 : return False;
653 : }
654 :
655 : } else {
656 : /* Check NT error */
657 :
658 38 : if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
659 1 : printf("unexpected error code %s\n",
660 : nt_errstr(status));
661 1 : printf(" expected %s (line=%d)\n", nt_errstr(nterr),
662 : line);
663 1 : return False;
664 : }
665 : }
666 :
667 37 : return True;
668 : }
669 :
670 9 : NTSTATUS cli_qpathinfo1(struct cli_state *cli,
671 : const char *fname,
672 : time_t *change_time,
673 : time_t *access_time,
674 : time_t *write_time,
675 : off_t *size,
676 : uint32_t *pattr)
677 : {
678 9 : int timezone = smb1cli_conn_server_time_zone(cli->conn);
679 9 : time_t (*date_fn)(const void *buf, int serverzone) = NULL;
680 9 : uint8_t *rdata = NULL;
681 0 : uint32_t num_rdata;
682 0 : NTSTATUS status;
683 :
684 9 : status = cli_qpathinfo(talloc_tos(),
685 : cli,
686 : fname,
687 : SMB_INFO_STANDARD,
688 : 22,
689 : CLI_BUFFER_SIZE,
690 : &rdata,
691 : &num_rdata);
692 9 : if (!NT_STATUS_IS_OK(status)) {
693 4 : return status;
694 : }
695 5 : if (cli->win95) {
696 0 : date_fn = make_unix_date;
697 : } else {
698 5 : date_fn = make_unix_date2;
699 : }
700 :
701 5 : if (change_time) {
702 5 : *change_time = date_fn(rdata + 0, timezone);
703 : }
704 5 : if (access_time) {
705 5 : *access_time = date_fn(rdata + 4, timezone);
706 : }
707 5 : if (write_time) {
708 5 : *write_time = date_fn(rdata + 8, timezone);
709 : }
710 5 : if (size) {
711 5 : *size = PULL_LE_U32(rdata, 12);
712 : }
713 5 : if (pattr) {
714 0 : *pattr = PULL_LE_U16(rdata, l1_attrFile);
715 : }
716 5 : return NT_STATUS_OK;
717 : }
718 :
719 0 : static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
720 : {
721 0 : NTSTATUS status;
722 :
723 0 : status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
724 :
725 0 : while (!NT_STATUS_IS_OK(status)) {
726 0 : if (!check_both_error(__LINE__, status, ERRDOS,
727 0 : ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
728 0 : return false;
729 : }
730 :
731 0 : status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
732 : }
733 :
734 0 : return true;
735 : }
736 :
737 :
738 0 : static bool rw_torture(struct cli_state *c)
739 : {
740 0 : const char *lockfname = "\\torture.lck";
741 0 : fstring fname;
742 0 : uint16_t fnum;
743 0 : uint16_t fnum2;
744 0 : pid_t pid2, pid = getpid();
745 0 : int i, j;
746 0 : char buf[1024];
747 0 : bool correct = True;
748 0 : size_t nread = 0;
749 0 : NTSTATUS status;
750 :
751 0 : memset(buf, '\0', sizeof(buf));
752 :
753 0 : status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
754 : DENY_NONE, &fnum2);
755 0 : if (!NT_STATUS_IS_OK(status)) {
756 0 : status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
757 : }
758 0 : if (!NT_STATUS_IS_OK(status)) {
759 0 : printf("open of %s failed (%s)\n",
760 : lockfname, nt_errstr(status));
761 0 : return False;
762 : }
763 :
764 0 : for (i=0;i<torture_numops;i++) {
765 0 : unsigned n = (unsigned)sys_random()%10;
766 :
767 0 : if (i % 10 == 0) {
768 0 : printf("%d\r", i); fflush(stdout);
769 : }
770 0 : slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
771 :
772 0 : if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
773 0 : return False;
774 : }
775 :
776 0 : status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
777 : DENY_ALL, &fnum);
778 0 : if (!NT_STATUS_IS_OK(status)) {
779 0 : printf("open failed (%s)\n", nt_errstr(status));
780 0 : correct = False;
781 0 : break;
782 : }
783 :
784 0 : status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
785 : sizeof(pid), NULL);
786 0 : if (!NT_STATUS_IS_OK(status)) {
787 0 : printf("write failed (%s)\n", nt_errstr(status));
788 0 : correct = False;
789 : }
790 :
791 0 : for (j=0;j<50;j++) {
792 0 : status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
793 0 : sizeof(pid)+(j*sizeof(buf)),
794 : sizeof(buf), NULL);
795 0 : if (!NT_STATUS_IS_OK(status)) {
796 0 : printf("write failed (%s)\n",
797 : nt_errstr(status));
798 0 : correct = False;
799 : }
800 : }
801 :
802 0 : pid2 = 0;
803 :
804 0 : status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
805 : &nread);
806 0 : if (!NT_STATUS_IS_OK(status)) {
807 0 : printf("read failed (%s)\n", nt_errstr(status));
808 0 : correct = false;
809 0 : } else if (nread != sizeof(pid)) {
810 0 : printf("read/write compare failed: "
811 : "recv %ld req %ld\n", (unsigned long)nread,
812 : (unsigned long)sizeof(pid));
813 0 : correct = false;
814 : }
815 :
816 0 : if (pid2 != pid) {
817 0 : printf("data corruption!\n");
818 0 : correct = False;
819 : }
820 :
821 0 : status = cli_close(c, fnum);
822 0 : if (!NT_STATUS_IS_OK(status)) {
823 0 : printf("close failed (%s)\n", nt_errstr(status));
824 0 : correct = False;
825 : }
826 :
827 0 : status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
828 0 : if (!NT_STATUS_IS_OK(status)) {
829 0 : printf("unlink failed (%s)\n", nt_errstr(status));
830 0 : correct = False;
831 : }
832 :
833 0 : status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
834 0 : if (!NT_STATUS_IS_OK(status)) {
835 0 : printf("unlock failed (%s)\n", nt_errstr(status));
836 0 : correct = False;
837 : }
838 : }
839 :
840 0 : cli_close(c, fnum2);
841 0 : cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
842 :
843 0 : printf("%d\n", i);
844 :
845 0 : return correct;
846 : }
847 :
848 0 : static bool run_torture(int dummy)
849 : {
850 0 : struct cli_state *cli;
851 0 : bool ret;
852 :
853 0 : cli = current_cli;
854 :
855 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
856 :
857 0 : ret = rw_torture(cli);
858 :
859 0 : if (!torture_close_connection(cli)) {
860 0 : ret = False;
861 : }
862 :
863 0 : return ret;
864 : }
865 :
866 0 : static bool rw_torture3(struct cli_state *c, char *lockfname)
867 : {
868 0 : uint16_t fnum = (uint16_t)-1;
869 0 : unsigned int i = 0;
870 0 : char buf[131072];
871 0 : char buf_rd[131072];
872 0 : unsigned count;
873 0 : unsigned countprev = 0;
874 0 : size_t sent = 0;
875 0 : bool correct = True;
876 0 : NTSTATUS status = NT_STATUS_OK;
877 :
878 0 : srandom(1);
879 0 : for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
880 : {
881 0 : SIVAL(buf, i, sys_random());
882 : }
883 :
884 0 : if (procnum == 0)
885 : {
886 0 : status = cli_unlink(
887 : c, lockfname,
888 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
889 0 : if (!NT_STATUS_IS_OK(status)) {
890 0 : printf("unlink failed (%s) (normal, this file should "
891 : "not exist)\n", nt_errstr(status));
892 : }
893 :
894 0 : status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
895 : DENY_NONE, &fnum);
896 0 : if (!NT_STATUS_IS_OK(status)) {
897 0 : printf("first open read/write of %s failed (%s)\n",
898 : lockfname, nt_errstr(status));
899 0 : return False;
900 : }
901 : }
902 : else
903 : {
904 0 : for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
905 : {
906 0 : status = cli_openx(c, lockfname, O_RDONLY,
907 : DENY_NONE, &fnum);
908 0 : if (NT_STATUS_IS_OK(status)) {
909 0 : break;
910 : }
911 0 : smb_msleep(10);
912 : }
913 0 : if (!NT_STATUS_IS_OK(status)) {
914 0 : printf("second open read-only of %s failed (%s)\n",
915 : lockfname, nt_errstr(status));
916 0 : return False;
917 : }
918 : }
919 :
920 0 : i = 0;
921 0 : for (count = 0; count < sizeof(buf); count += sent)
922 : {
923 0 : if (count >= countprev) {
924 0 : printf("%d %8d\r", i, count);
925 0 : fflush(stdout);
926 0 : i++;
927 0 : countprev += (sizeof(buf) / 20);
928 : }
929 :
930 0 : if (procnum == 0)
931 : {
932 0 : sent = ((unsigned)sys_random()%(20))+ 1;
933 0 : if (sent > sizeof(buf) - count)
934 : {
935 0 : sent = sizeof(buf) - count;
936 : }
937 :
938 0 : status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
939 : count, sent, NULL);
940 0 : if (!NT_STATUS_IS_OK(status)) {
941 0 : printf("write failed (%s)\n",
942 : nt_errstr(status));
943 0 : correct = False;
944 : }
945 : }
946 : else
947 : {
948 0 : status = cli_read(c, fnum, buf_rd+count, count,
949 : sizeof(buf)-count, &sent);
950 0 : if(!NT_STATUS_IS_OK(status)) {
951 0 : printf("read failed offset:%d size:%ld (%s)\n",
952 : count, (unsigned long)sizeof(buf)-count,
953 : nt_errstr(status));
954 0 : correct = False;
955 0 : sent = 0;
956 0 : } else if (sent > 0) {
957 0 : if (memcmp(buf_rd+count, buf+count, sent) != 0)
958 : {
959 0 : printf("read/write compare failed\n");
960 0 : printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
961 0 : correct = False;
962 0 : break;
963 : }
964 : }
965 : }
966 :
967 : }
968 :
969 0 : status = cli_close(c, fnum);
970 0 : if (!NT_STATUS_IS_OK(status)) {
971 0 : printf("close failed (%s)\n", nt_errstr(status));
972 0 : correct = False;
973 : }
974 :
975 0 : return correct;
976 : }
977 :
978 18 : static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
979 : {
980 18 : const char *lockfname = "\\torture2.lck";
981 0 : uint16_t fnum1;
982 0 : uint16_t fnum2;
983 0 : int i;
984 0 : char buf[131072];
985 0 : char buf_rd[131072];
986 18 : bool correct = True;
987 0 : size_t bytes_read;
988 0 : NTSTATUS status;
989 :
990 18 : status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
991 18 : if (!NT_STATUS_IS_OK(status)) {
992 18 : printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
993 : }
994 :
995 18 : status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
996 : DENY_NONE, &fnum1);
997 18 : if (!NT_STATUS_IS_OK(status)) {
998 0 : printf("first open read/write of %s failed (%s)\n",
999 : lockfname, nt_errstr(status));
1000 0 : return False;
1001 : }
1002 :
1003 18 : status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
1004 18 : if (!NT_STATUS_IS_OK(status)) {
1005 0 : printf("second open read-only of %s failed (%s)\n",
1006 : lockfname, nt_errstr(status));
1007 0 : cli_close(c1, fnum1);
1008 0 : return False;
1009 : }
1010 :
1011 1818 : for (i = 0; i < torture_numops; i++)
1012 : {
1013 1800 : size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
1014 1800 : if (i % 10 == 0) {
1015 180 : printf("%d\r", i); fflush(stdout);
1016 : }
1017 :
1018 1800 : generate_random_buffer((unsigned char *)buf, buf_size);
1019 :
1020 1800 : status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
1021 : buf_size, NULL);
1022 1800 : if (!NT_STATUS_IS_OK(status)) {
1023 0 : printf("write failed (%s)\n", nt_errstr(status));
1024 0 : correct = False;
1025 0 : break;
1026 : }
1027 :
1028 1800 : status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
1029 1800 : if(!NT_STATUS_IS_OK(status)) {
1030 0 : printf("read failed (%s)\n", nt_errstr(status));
1031 0 : correct = false;
1032 0 : break;
1033 1800 : } else if (bytes_read != buf_size) {
1034 0 : printf("read failed\n");
1035 0 : printf("read %ld, expected %ld\n",
1036 : (unsigned long)bytes_read,
1037 : (unsigned long)buf_size);
1038 0 : correct = False;
1039 0 : break;
1040 : }
1041 :
1042 1800 : if (memcmp(buf_rd, buf, buf_size) != 0)
1043 : {
1044 0 : printf("read/write compare failed\n");
1045 0 : correct = False;
1046 0 : break;
1047 : }
1048 : }
1049 :
1050 18 : status = cli_close(c2, fnum2);
1051 18 : if (!NT_STATUS_IS_OK(status)) {
1052 0 : printf("close failed (%s)\n", nt_errstr(status));
1053 0 : correct = False;
1054 : }
1055 :
1056 18 : status = cli_close(c1, fnum1);
1057 18 : if (!NT_STATUS_IS_OK(status)) {
1058 0 : printf("close failed (%s)\n", nt_errstr(status));
1059 0 : correct = False;
1060 : }
1061 :
1062 18 : status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1063 18 : if (!NT_STATUS_IS_OK(status)) {
1064 0 : printf("unlink failed (%s)\n", nt_errstr(status));
1065 0 : correct = False;
1066 : }
1067 :
1068 18 : return correct;
1069 : }
1070 :
1071 9 : static bool run_readwritetest(int dummy)
1072 : {
1073 0 : struct cli_state *cli1, *cli2;
1074 9 : bool test1, test2 = False;
1075 :
1076 9 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1077 0 : return False;
1078 : }
1079 9 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
1080 9 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
1081 :
1082 9 : printf("starting readwritetest\n");
1083 :
1084 9 : test1 = rw_torture2(cli1, cli2);
1085 9 : printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
1086 :
1087 9 : if (test1) {
1088 9 : test2 = rw_torture2(cli1, cli1);
1089 9 : printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
1090 : }
1091 :
1092 9 : if (!torture_close_connection(cli1)) {
1093 0 : test1 = False;
1094 : }
1095 :
1096 9 : if (!torture_close_connection(cli2)) {
1097 0 : test2 = False;
1098 : }
1099 :
1100 9 : return (test1 && test2);
1101 : }
1102 :
1103 0 : static bool run_readwritemulti(int dummy)
1104 : {
1105 0 : struct cli_state *cli;
1106 0 : bool test;
1107 :
1108 0 : cli = current_cli;
1109 :
1110 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1111 :
1112 0 : printf("run_readwritemulti: fname %s\n", randomfname);
1113 0 : test = rw_torture3(cli, randomfname);
1114 :
1115 0 : if (!torture_close_connection(cli)) {
1116 0 : test = False;
1117 : }
1118 :
1119 0 : return test;
1120 : }
1121 :
1122 14 : static bool run_readwritelarge_internal(void)
1123 : {
1124 0 : static struct cli_state *cli1;
1125 0 : uint16_t fnum1;
1126 14 : const char *lockfname = "\\large.dat";
1127 0 : off_t fsize;
1128 0 : char buf[126*1024];
1129 14 : bool correct = True;
1130 0 : NTSTATUS status;
1131 :
1132 14 : if (!torture_open_connection(&cli1, 0)) {
1133 0 : return False;
1134 : }
1135 14 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
1136 14 : memset(buf,'\0',sizeof(buf));
1137 :
1138 14 : printf("starting readwritelarge_internal\n");
1139 :
1140 14 : cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1141 :
1142 14 : status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1143 : DENY_NONE, &fnum1);
1144 14 : if (!NT_STATUS_IS_OK(status)) {
1145 0 : printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1146 0 : return False;
1147 : }
1148 :
1149 14 : cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1150 :
1151 14 : status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1152 : NULL, NULL, NULL);
1153 14 : if (!NT_STATUS_IS_OK(status)) {
1154 0 : printf("qfileinfo failed (%s)\n", nt_errstr(status));
1155 0 : correct = False;
1156 : }
1157 :
1158 14 : if (fsize == sizeof(buf))
1159 14 : printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1160 : (unsigned long)fsize);
1161 : else {
1162 0 : printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1163 : (unsigned long)fsize);
1164 0 : correct = False;
1165 : }
1166 :
1167 14 : status = cli_close(cli1, fnum1);
1168 14 : if (!NT_STATUS_IS_OK(status)) {
1169 0 : printf("close failed (%s)\n", nt_errstr(status));
1170 0 : correct = False;
1171 : }
1172 :
1173 14 : status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1174 14 : if (!NT_STATUS_IS_OK(status)) {
1175 0 : printf("unlink failed (%s)\n", nt_errstr(status));
1176 0 : correct = False;
1177 : }
1178 :
1179 14 : status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1180 : DENY_NONE, &fnum1);
1181 14 : if (!NT_STATUS_IS_OK(status)) {
1182 0 : printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1183 0 : return False;
1184 : }
1185 :
1186 14 : cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1187 :
1188 14 : status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1189 : NULL, NULL, NULL);
1190 14 : if (!NT_STATUS_IS_OK(status)) {
1191 0 : printf("qfileinfo failed (%s)\n", nt_errstr(status));
1192 0 : correct = False;
1193 : }
1194 :
1195 14 : if (fsize == sizeof(buf))
1196 14 : printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1197 : (unsigned long)fsize);
1198 : else {
1199 0 : printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1200 : (unsigned long)fsize);
1201 0 : correct = False;
1202 : }
1203 :
1204 14 : status = cli_close(cli1, fnum1);
1205 14 : if (!NT_STATUS_IS_OK(status)) {
1206 0 : printf("close failed (%s)\n", nt_errstr(status));
1207 0 : correct = False;
1208 : }
1209 :
1210 14 : if (!torture_close_connection(cli1)) {
1211 0 : correct = False;
1212 : }
1213 14 : return correct;
1214 : }
1215 :
1216 9 : static bool run_readwritelarge(int dummy)
1217 : {
1218 9 : return run_readwritelarge_internal();
1219 : }
1220 :
1221 5 : static bool run_readwritelarge_signtest(int dummy)
1222 : {
1223 0 : bool ret;
1224 5 : signing_state = SMB_SIGNING_REQUIRED;
1225 5 : ret = run_readwritelarge_internal();
1226 5 : signing_state = SMB_SIGNING_DEFAULT;
1227 5 : return ret;
1228 : }
1229 :
1230 : int line_count = 0;
1231 : int nbio_id;
1232 :
1233 : #define ival(s) strtol(s, NULL, 0)
1234 :
1235 : /* run a test that simulates an approximate netbench client load */
1236 0 : static bool run_netbench(int client)
1237 : {
1238 0 : struct cli_state *cli;
1239 0 : int i;
1240 0 : char line[1024];
1241 0 : char cname[20];
1242 0 : FILE *f;
1243 0 : const char *params[20];
1244 0 : bool correct = True;
1245 :
1246 0 : cli = current_cli;
1247 :
1248 0 : nbio_id = client;
1249 :
1250 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1251 :
1252 0 : nb_setup(cli);
1253 :
1254 0 : slprintf(cname,sizeof(cname)-1, "client%d", client);
1255 :
1256 0 : f = fopen(client_txt, "r");
1257 :
1258 0 : if (!f) {
1259 0 : perror(client_txt);
1260 0 : return False;
1261 : }
1262 :
1263 0 : while (fgets(line, sizeof(line)-1, f)) {
1264 0 : char *saveptr;
1265 0 : line_count++;
1266 :
1267 0 : line[strlen(line)-1] = 0;
1268 :
1269 : /* printf("[%d] %s\n", line_count, line); */
1270 :
1271 0 : all_string_sub(line,"client1", cname, sizeof(line));
1272 :
1273 : /* parse the command parameters */
1274 0 : params[0] = strtok_r(line, " ", &saveptr);
1275 0 : i = 0;
1276 0 : while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1277 :
1278 0 : params[i] = "";
1279 :
1280 0 : if (i < 2) continue;
1281 :
1282 0 : if (!strncmp(params[0],"SMB", 3)) {
1283 0 : printf("ERROR: You are using a dbench 1 load file\n");
1284 0 : exit(1);
1285 : }
1286 :
1287 0 : if (!strcmp(params[0],"NTCreateX")) {
1288 0 : nb_createx(params[1], ival(params[2]), ival(params[3]),
1289 0 : ival(params[4]));
1290 0 : } else if (!strcmp(params[0],"Close")) {
1291 0 : nb_close(ival(params[1]));
1292 0 : } else if (!strcmp(params[0],"Rename")) {
1293 0 : nb_rename(params[1], params[2]);
1294 0 : } else if (!strcmp(params[0],"Unlink")) {
1295 0 : nb_unlink(params[1]);
1296 0 : } else if (!strcmp(params[0],"Deltree")) {
1297 0 : nb_deltree(params[1]);
1298 0 : } else if (!strcmp(params[0],"Rmdir")) {
1299 0 : nb_rmdir(params[1]);
1300 0 : } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1301 0 : nb_qpathinfo(params[1]);
1302 0 : } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1303 0 : nb_qfileinfo(ival(params[1]));
1304 0 : } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1305 0 : nb_qfsinfo(ival(params[1]));
1306 0 : } else if (!strcmp(params[0],"FIND_FIRST")) {
1307 0 : nb_findfirst(params[1]);
1308 0 : } else if (!strcmp(params[0],"WriteX")) {
1309 0 : nb_writex(ival(params[1]),
1310 0 : ival(params[2]), ival(params[3]), ival(params[4]));
1311 0 : } else if (!strcmp(params[0],"ReadX")) {
1312 0 : nb_readx(ival(params[1]),
1313 0 : ival(params[2]), ival(params[3]), ival(params[4]));
1314 0 : } else if (!strcmp(params[0],"Flush")) {
1315 0 : nb_flush(ival(params[1]));
1316 : } else {
1317 0 : printf("Unknown operation %s\n", params[0]);
1318 0 : exit(1);
1319 : }
1320 : }
1321 0 : fclose(f);
1322 :
1323 0 : nb_cleanup();
1324 :
1325 0 : if (!torture_close_connection(cli)) {
1326 0 : correct = False;
1327 : }
1328 :
1329 0 : return correct;
1330 : }
1331 :
1332 :
1333 : /* run a test that simulates an approximate netbench client load */
1334 0 : static bool run_nbench(int dummy)
1335 : {
1336 0 : double t;
1337 0 : bool correct = True;
1338 :
1339 0 : nbio_shmem(torture_nprocs);
1340 :
1341 0 : nbio_id = -1;
1342 :
1343 0 : signal(SIGALRM, nb_alarm);
1344 0 : alarm(1);
1345 0 : t = create_procs(run_netbench, &correct);
1346 0 : alarm(0);
1347 :
1348 0 : printf("\nThroughput %g MB/sec\n",
1349 0 : 1.0e-6 * nbio_total() / t);
1350 0 : return correct;
1351 : }
1352 :
1353 :
1354 : /*
1355 : This test checks for two things:
1356 :
1357 : 1) correct support for retaining locks over a close (ie. the server
1358 : must not use posix semantics)
1359 : 2) support for lock timeouts
1360 : */
1361 5 : static bool run_locktest1(int dummy)
1362 : {
1363 0 : struct cli_state *cli1, *cli2;
1364 5 : const char *fname = "\\lockt1.lck";
1365 0 : uint16_t fnum1, fnum2, fnum3;
1366 0 : time_t t1, t2;
1367 0 : unsigned lock_timeout;
1368 0 : NTSTATUS status;
1369 :
1370 5 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1371 0 : return False;
1372 : }
1373 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
1374 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
1375 :
1376 5 : printf("starting locktest1\n");
1377 :
1378 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1379 :
1380 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1381 : &fnum1);
1382 5 : if (!NT_STATUS_IS_OK(status)) {
1383 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1384 0 : return False;
1385 : }
1386 :
1387 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1388 5 : if (!NT_STATUS_IS_OK(status)) {
1389 0 : printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1390 0 : return False;
1391 : }
1392 :
1393 5 : status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1394 5 : if (!NT_STATUS_IS_OK(status)) {
1395 0 : printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1396 0 : return False;
1397 : }
1398 :
1399 5 : status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1400 5 : if (!NT_STATUS_IS_OK(status)) {
1401 0 : printf("lock1 failed (%s)\n", nt_errstr(status));
1402 0 : return false;
1403 : }
1404 :
1405 5 : status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1406 5 : if (NT_STATUS_IS_OK(status)) {
1407 0 : printf("lock2 succeeded! This is a locking bug\n");
1408 0 : return false;
1409 : } else {
1410 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1411 5 : NT_STATUS_LOCK_NOT_GRANTED)) {
1412 0 : return false;
1413 : }
1414 : }
1415 :
1416 5 : lock_timeout = (1 + (random() % 20));
1417 5 : printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1418 5 : t1 = time(NULL);
1419 5 : status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1420 5 : if (NT_STATUS_IS_OK(status)) {
1421 0 : printf("lock3 succeeded! This is a locking bug\n");
1422 0 : return false;
1423 : } else {
1424 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1425 5 : NT_STATUS_FILE_LOCK_CONFLICT)) {
1426 0 : return false;
1427 : }
1428 : }
1429 5 : t2 = time(NULL);
1430 :
1431 5 : if (ABS(t2 - t1) < lock_timeout-1) {
1432 0 : printf("error: This server appears not to support timed lock requests\n");
1433 : }
1434 :
1435 5 : printf("server slept for %u seconds for a %u second timeout\n",
1436 : (unsigned int)(t2-t1), lock_timeout);
1437 :
1438 5 : status = cli_close(cli1, fnum2);
1439 5 : if (!NT_STATUS_IS_OK(status)) {
1440 0 : printf("close1 failed (%s)\n", nt_errstr(status));
1441 0 : return False;
1442 : }
1443 :
1444 5 : status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1445 5 : if (NT_STATUS_IS_OK(status)) {
1446 0 : printf("lock4 succeeded! This is a locking bug\n");
1447 0 : return false;
1448 : } else {
1449 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1450 5 : NT_STATUS_FILE_LOCK_CONFLICT)) {
1451 0 : return false;
1452 : }
1453 : }
1454 :
1455 5 : status = cli_close(cli1, fnum1);
1456 5 : if (!NT_STATUS_IS_OK(status)) {
1457 0 : printf("close2 failed (%s)\n", nt_errstr(status));
1458 0 : return False;
1459 : }
1460 :
1461 5 : status = cli_close(cli2, fnum3);
1462 5 : if (!NT_STATUS_IS_OK(status)) {
1463 0 : printf("close3 failed (%s)\n", nt_errstr(status));
1464 0 : return False;
1465 : }
1466 :
1467 5 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1468 5 : if (!NT_STATUS_IS_OK(status)) {
1469 0 : printf("unlink failed (%s)\n", nt_errstr(status));
1470 0 : return False;
1471 : }
1472 :
1473 :
1474 5 : if (!torture_close_connection(cli1)) {
1475 0 : return False;
1476 : }
1477 :
1478 5 : if (!torture_close_connection(cli2)) {
1479 0 : return False;
1480 : }
1481 :
1482 5 : printf("Passed locktest1\n");
1483 5 : return True;
1484 : }
1485 :
1486 : /*
1487 : this checks to see if a secondary tconx can use open files from an
1488 : earlier tconx
1489 : */
1490 5 : static bool run_tcon_test(int dummy)
1491 : {
1492 0 : static struct cli_state *cli;
1493 5 : const char *fname = "\\tcontest.tmp";
1494 0 : uint16_t fnum1;
1495 0 : uint32_t cnum1, cnum2, cnum3;
1496 5 : struct smbXcli_tcon *orig_tcon = NULL;
1497 5 : char *orig_share = NULL;
1498 0 : uint16_t vuid1, vuid2;
1499 0 : char buf[4];
1500 5 : bool ret = True;
1501 0 : NTSTATUS status;
1502 :
1503 5 : memset(buf, '\0', sizeof(buf));
1504 :
1505 5 : if (!torture_open_connection(&cli, 0)) {
1506 0 : return False;
1507 : }
1508 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1509 :
1510 5 : printf("starting tcontest\n");
1511 :
1512 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1513 :
1514 5 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1515 5 : if (!NT_STATUS_IS_OK(status)) {
1516 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1517 0 : return False;
1518 : }
1519 :
1520 5 : cnum1 = cli_state_get_tid(cli);
1521 5 : vuid1 = cli_state_get_uid(cli);
1522 :
1523 5 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1524 5 : if (!NT_STATUS_IS_OK(status)) {
1525 0 : printf("initial write failed (%s)", nt_errstr(status));
1526 0 : return False;
1527 : }
1528 :
1529 5 : cli_state_save_tcon_share(cli, &orig_tcon, &orig_share);
1530 :
1531 5 : status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1532 5 : if (!NT_STATUS_IS_OK(status)) {
1533 0 : printf("%s refused 2nd tree connect (%s)\n", host,
1534 : nt_errstr(status));
1535 0 : cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1536 0 : cli_shutdown(cli);
1537 0 : return False;
1538 : }
1539 :
1540 5 : cnum2 = cli_state_get_tid(cli);
1541 5 : cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1542 5 : vuid2 = cli_state_get_uid(cli) + 1;
1543 :
1544 : /* try a write with the wrong tid */
1545 5 : cli_state_set_tid(cli, cnum2);
1546 :
1547 5 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1548 5 : if (NT_STATUS_IS_OK(status)) {
1549 0 : printf("* server allows write with wrong TID\n");
1550 0 : ret = False;
1551 : } else {
1552 5 : printf("server fails write with wrong TID : %s\n",
1553 : nt_errstr(status));
1554 : }
1555 :
1556 :
1557 : /* try a write with an invalid tid */
1558 5 : cli_state_set_tid(cli, cnum3);
1559 :
1560 5 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1561 5 : if (NT_STATUS_IS_OK(status)) {
1562 0 : printf("* server allows write with invalid TID\n");
1563 0 : ret = False;
1564 : } else {
1565 5 : printf("server fails write with invalid TID : %s\n",
1566 : nt_errstr(status));
1567 : }
1568 :
1569 : /* try a write with an invalid vuid */
1570 5 : cli_state_set_uid(cli, vuid2);
1571 5 : cli_state_set_tid(cli, cnum1);
1572 :
1573 5 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1574 5 : if (NT_STATUS_IS_OK(status)) {
1575 0 : printf("* server allows write with invalid VUID\n");
1576 0 : ret = False;
1577 : } else {
1578 5 : printf("server fails write with invalid VUID : %s\n",
1579 : nt_errstr(status));
1580 : }
1581 :
1582 5 : cli_state_set_tid(cli, cnum1);
1583 5 : cli_state_set_uid(cli, vuid1);
1584 :
1585 5 : status = cli_close(cli, fnum1);
1586 5 : if (!NT_STATUS_IS_OK(status)) {
1587 0 : printf("close failed (%s)\n", nt_errstr(status));
1588 0 : cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1589 0 : cli_shutdown(cli);
1590 0 : return False;
1591 : }
1592 :
1593 5 : cli_state_set_tid(cli, cnum2);
1594 :
1595 5 : status = cli_tdis(cli);
1596 5 : if (!NT_STATUS_IS_OK(status)) {
1597 0 : printf("secondary tdis failed (%s)\n", nt_errstr(status));
1598 0 : cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1599 0 : cli_shutdown(cli);
1600 0 : return False;
1601 : }
1602 :
1603 5 : cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1604 :
1605 5 : cli_state_set_tid(cli, cnum1);
1606 :
1607 5 : if (!torture_close_connection(cli)) {
1608 0 : return False;
1609 : }
1610 :
1611 5 : return ret;
1612 : }
1613 :
1614 :
1615 : /*
1616 : checks for old style tcon support
1617 : */
1618 5 : static bool run_tcon2_test(int dummy)
1619 : {
1620 0 : static struct cli_state *cli;
1621 0 : uint16_t cnum, max_xmit;
1622 0 : char *service;
1623 0 : NTSTATUS status;
1624 :
1625 5 : if (!torture_open_connection(&cli, 0)) {
1626 0 : return False;
1627 : }
1628 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1629 :
1630 5 : printf("starting tcon2 test\n");
1631 :
1632 5 : if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1633 0 : return false;
1634 : }
1635 :
1636 5 : status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1637 :
1638 5 : SAFE_FREE(service);
1639 :
1640 5 : if (!NT_STATUS_IS_OK(status)) {
1641 5 : printf("tcon2 failed : %s\n", nt_errstr(status));
1642 : } else {
1643 0 : printf("tcon OK : max_xmit=%d cnum=%d\n",
1644 : (int)max_xmit, (int)cnum);
1645 : }
1646 :
1647 5 : if (!torture_close_connection(cli)) {
1648 0 : return False;
1649 : }
1650 :
1651 5 : printf("Passed tcon2 test\n");
1652 5 : return True;
1653 : }
1654 :
1655 50 : static bool tcon_devtest(struct cli_state *cli,
1656 : const char *myshare, const char *devtype,
1657 : const char *return_devtype,
1658 : NTSTATUS expected_error)
1659 : {
1660 0 : NTSTATUS status;
1661 0 : bool ret;
1662 :
1663 50 : status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1664 :
1665 50 : if (NT_STATUS_IS_OK(expected_error)) {
1666 20 : if (NT_STATUS_IS_OK(status)) {
1667 40 : if (return_devtype != NULL &&
1668 20 : strequal(cli->dev, return_devtype)) {
1669 20 : ret = True;
1670 : } else {
1671 0 : printf("tconX to share %s with type %s "
1672 : "succeeded but returned the wrong "
1673 : "device type (got [%s] but should have got [%s])\n",
1674 : myshare, devtype, cli->dev, return_devtype);
1675 0 : ret = False;
1676 : }
1677 : } else {
1678 0 : printf("tconX to share %s with type %s "
1679 : "should have succeeded but failed\n",
1680 : myshare, devtype);
1681 0 : ret = False;
1682 : }
1683 20 : cli_tdis(cli);
1684 : } else {
1685 30 : if (NT_STATUS_IS_OK(status)) {
1686 0 : printf("tconx to share %s with type %s "
1687 : "should have failed but succeeded\n",
1688 : myshare, devtype);
1689 0 : ret = False;
1690 : } else {
1691 30 : if (NT_STATUS_EQUAL(status, expected_error)) {
1692 30 : ret = True;
1693 : } else {
1694 0 : printf("Returned unexpected error\n");
1695 0 : ret = False;
1696 : }
1697 : }
1698 : }
1699 50 : return ret;
1700 : }
1701 :
1702 : /*
1703 : checks for correct tconX support
1704 : */
1705 5 : static bool run_tcon_devtype_test(int dummy)
1706 : {
1707 0 : static struct cli_state *cli1 = NULL;
1708 5 : int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1709 0 : NTSTATUS status;
1710 5 : bool ret = True;
1711 :
1712 5 : status = cli_full_connection_creds(NULL,
1713 : &cli1,
1714 : myname,
1715 : host,
1716 : NULL, /* dest_ss */
1717 : port_to_use,
1718 : NULL, /* service */
1719 : NULL, /* service_type */
1720 : torture_creds,
1721 : flags);
1722 :
1723 5 : if (!NT_STATUS_IS_OK(status)) {
1724 0 : printf("could not open connection\n");
1725 0 : return False;
1726 : }
1727 :
1728 5 : if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1729 0 : ret = False;
1730 :
1731 5 : if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1732 0 : ret = False;
1733 :
1734 5 : if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1735 0 : ret = False;
1736 :
1737 5 : if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1738 0 : ret = False;
1739 :
1740 5 : if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1741 0 : ret = False;
1742 :
1743 5 : if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1744 0 : ret = False;
1745 :
1746 5 : if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1747 0 : ret = False;
1748 :
1749 5 : if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1750 0 : ret = False;
1751 :
1752 5 : if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1753 0 : ret = False;
1754 :
1755 5 : if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1756 0 : ret = False;
1757 :
1758 5 : cli_shutdown(cli1);
1759 :
1760 5 : if (ret)
1761 5 : printf("Passed tcondevtest\n");
1762 :
1763 5 : return ret;
1764 : }
1765 :
1766 :
1767 : /*
1768 : This test checks that
1769 :
1770 : 1) the server supports multiple locking contexts on the one SMB
1771 : connection, distinguished by PID.
1772 :
1773 : 2) the server correctly fails overlapping locks made by the same PID (this
1774 : goes against POSIX behaviour, which is why it is tricky to implement)
1775 :
1776 : 3) the server denies unlock requests by an incorrect client PID
1777 : */
1778 5 : static bool run_locktest2(int dummy)
1779 : {
1780 0 : static struct cli_state *cli;
1781 5 : const char *fname = "\\lockt2.lck";
1782 0 : uint16_t fnum1, fnum2, fnum3;
1783 5 : bool correct = True;
1784 0 : NTSTATUS status;
1785 :
1786 5 : if (!torture_open_connection(&cli, 0)) {
1787 0 : return False;
1788 : }
1789 :
1790 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1791 :
1792 5 : printf("starting locktest2\n");
1793 :
1794 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1795 :
1796 5 : cli_setpid(cli, 1);
1797 :
1798 5 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1799 5 : if (!NT_STATUS_IS_OK(status)) {
1800 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1801 0 : return False;
1802 : }
1803 :
1804 5 : status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1805 5 : if (!NT_STATUS_IS_OK(status)) {
1806 0 : printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1807 0 : return False;
1808 : }
1809 :
1810 5 : cli_setpid(cli, 2);
1811 :
1812 5 : status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1813 5 : if (!NT_STATUS_IS_OK(status)) {
1814 0 : printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1815 0 : return False;
1816 : }
1817 :
1818 5 : cli_setpid(cli, 1);
1819 :
1820 5 : status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1821 5 : if (!NT_STATUS_IS_OK(status)) {
1822 0 : printf("lock1 failed (%s)\n", nt_errstr(status));
1823 0 : return false;
1824 : }
1825 :
1826 5 : status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1827 5 : if (NT_STATUS_IS_OK(status)) {
1828 0 : printf("WRITE lock1 succeeded! This is a locking bug\n");
1829 0 : correct = false;
1830 : } else {
1831 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1832 5 : NT_STATUS_LOCK_NOT_GRANTED)) {
1833 0 : return false;
1834 : }
1835 : }
1836 :
1837 5 : status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1838 5 : if (NT_STATUS_IS_OK(status)) {
1839 0 : printf("WRITE lock2 succeeded! This is a locking bug\n");
1840 0 : correct = false;
1841 : } else {
1842 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1843 5 : NT_STATUS_LOCK_NOT_GRANTED)) {
1844 0 : return false;
1845 : }
1846 : }
1847 :
1848 5 : status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1849 5 : if (NT_STATUS_IS_OK(status)) {
1850 0 : printf("READ lock2 succeeded! This is a locking bug\n");
1851 0 : correct = false;
1852 : } else {
1853 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1854 5 : NT_STATUS_FILE_LOCK_CONFLICT)) {
1855 0 : return false;
1856 : }
1857 : }
1858 :
1859 5 : status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1860 5 : if (!NT_STATUS_IS_OK(status)) {
1861 0 : printf("lock at 100 failed (%s)\n", nt_errstr(status));
1862 : }
1863 5 : cli_setpid(cli, 2);
1864 5 : if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1865 0 : printf("unlock at 100 succeeded! This is a locking bug\n");
1866 0 : correct = False;
1867 : }
1868 :
1869 5 : status = cli_unlock(cli, fnum1, 0, 4);
1870 5 : if (NT_STATUS_IS_OK(status)) {
1871 0 : printf("unlock1 succeeded! This is a locking bug\n");
1872 0 : correct = false;
1873 : } else {
1874 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1875 5 : NT_STATUS_RANGE_NOT_LOCKED)) {
1876 0 : return false;
1877 : }
1878 : }
1879 :
1880 5 : status = cli_unlock(cli, fnum1, 0, 8);
1881 5 : if (NT_STATUS_IS_OK(status)) {
1882 0 : printf("unlock2 succeeded! This is a locking bug\n");
1883 0 : correct = false;
1884 : } else {
1885 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1886 5 : NT_STATUS_RANGE_NOT_LOCKED)) {
1887 0 : return false;
1888 : }
1889 : }
1890 :
1891 5 : status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1892 5 : if (NT_STATUS_IS_OK(status)) {
1893 0 : printf("lock3 succeeded! This is a locking bug\n");
1894 0 : correct = false;
1895 : } else {
1896 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1897 5 : NT_STATUS_LOCK_NOT_GRANTED)) {
1898 0 : return false;
1899 : }
1900 : }
1901 :
1902 5 : cli_setpid(cli, 1);
1903 :
1904 5 : status = cli_close(cli, fnum1);
1905 5 : if (!NT_STATUS_IS_OK(status)) {
1906 0 : printf("close1 failed (%s)\n", nt_errstr(status));
1907 0 : return False;
1908 : }
1909 :
1910 5 : status = cli_close(cli, fnum2);
1911 5 : if (!NT_STATUS_IS_OK(status)) {
1912 0 : printf("close2 failed (%s)\n", nt_errstr(status));
1913 0 : return False;
1914 : }
1915 :
1916 5 : status = cli_close(cli, fnum3);
1917 5 : if (!NT_STATUS_IS_OK(status)) {
1918 0 : printf("close3 failed (%s)\n", nt_errstr(status));
1919 0 : return False;
1920 : }
1921 :
1922 5 : if (!torture_close_connection(cli)) {
1923 0 : correct = False;
1924 : }
1925 :
1926 5 : printf("locktest2 finished\n");
1927 :
1928 5 : return correct;
1929 : }
1930 :
1931 :
1932 : /*
1933 : This test checks that
1934 :
1935 : 1) the server supports the full offset range in lock requests
1936 : */
1937 5 : static bool run_locktest3(int dummy)
1938 : {
1939 0 : static struct cli_state *cli1, *cli2;
1940 5 : const char *fname = "\\lockt3.lck";
1941 0 : uint16_t fnum1, fnum2;
1942 0 : int i;
1943 0 : uint32_t offset;
1944 5 : bool correct = True;
1945 0 : NTSTATUS status;
1946 :
1947 : #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1948 :
1949 5 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1950 0 : return False;
1951 : }
1952 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
1953 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
1954 :
1955 5 : printf("starting locktest3\n");
1956 :
1957 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1958 :
1959 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1960 : &fnum1);
1961 5 : if (!NT_STATUS_IS_OK(status)) {
1962 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1963 0 : return False;
1964 : }
1965 :
1966 5 : status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1967 5 : if (!NT_STATUS_IS_OK(status)) {
1968 0 : printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1969 0 : return False;
1970 : }
1971 :
1972 505 : for (offset=i=0;i<torture_numops;i++) {
1973 500 : NEXT_OFFSET;
1974 :
1975 500 : status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1976 500 : if (!NT_STATUS_IS_OK(status)) {
1977 0 : printf("lock1 %d failed (%s)\n",
1978 : i,
1979 : nt_errstr(status));
1980 0 : return False;
1981 : }
1982 :
1983 500 : status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1984 500 : if (!NT_STATUS_IS_OK(status)) {
1985 0 : printf("lock2 %d failed (%s)\n",
1986 : i,
1987 : nt_errstr(status));
1988 0 : return False;
1989 : }
1990 : }
1991 :
1992 505 : for (offset=i=0;i<torture_numops;i++) {
1993 500 : NEXT_OFFSET;
1994 :
1995 500 : status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1996 500 : if (NT_STATUS_IS_OK(status)) {
1997 0 : printf("error: lock1 %d succeeded!\n", i);
1998 0 : return False;
1999 : }
2000 :
2001 500 : status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
2002 500 : if (NT_STATUS_IS_OK(status)) {
2003 0 : printf("error: lock2 %d succeeded!\n", i);
2004 0 : return False;
2005 : }
2006 :
2007 500 : status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
2008 500 : if (NT_STATUS_IS_OK(status)) {
2009 0 : printf("error: lock3 %d succeeded!\n", i);
2010 0 : return False;
2011 : }
2012 :
2013 500 : status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
2014 500 : if (NT_STATUS_IS_OK(status)) {
2015 0 : printf("error: lock4 %d succeeded!\n", i);
2016 0 : return False;
2017 : }
2018 : }
2019 :
2020 505 : for (offset=i=0;i<torture_numops;i++) {
2021 500 : NEXT_OFFSET;
2022 :
2023 500 : status = cli_unlock(cli1, fnum1, offset-1, 1);
2024 500 : if (!NT_STATUS_IS_OK(status)) {
2025 0 : printf("unlock1 %d failed (%s)\n",
2026 : i,
2027 : nt_errstr(status));
2028 0 : return False;
2029 : }
2030 :
2031 500 : status = cli_unlock(cli2, fnum2, offset-2, 1);
2032 500 : if (!NT_STATUS_IS_OK(status)) {
2033 0 : printf("unlock2 %d failed (%s)\n",
2034 : i,
2035 : nt_errstr(status));
2036 0 : return False;
2037 : }
2038 : }
2039 :
2040 5 : status = cli_close(cli1, fnum1);
2041 5 : if (!NT_STATUS_IS_OK(status)) {
2042 0 : printf("close1 failed (%s)\n", nt_errstr(status));
2043 0 : return False;
2044 : }
2045 :
2046 5 : status = cli_close(cli2, fnum2);
2047 5 : if (!NT_STATUS_IS_OK(status)) {
2048 0 : printf("close2 failed (%s)\n", nt_errstr(status));
2049 0 : return False;
2050 : }
2051 :
2052 5 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2053 5 : if (!NT_STATUS_IS_OK(status)) {
2054 0 : printf("unlink failed (%s)\n", nt_errstr(status));
2055 0 : return False;
2056 : }
2057 :
2058 5 : if (!torture_close_connection(cli1)) {
2059 0 : correct = False;
2060 : }
2061 :
2062 5 : if (!torture_close_connection(cli2)) {
2063 0 : correct = False;
2064 : }
2065 :
2066 5 : printf("finished locktest3\n");
2067 :
2068 5 : return correct;
2069 : }
2070 :
2071 40 : static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
2072 : char *buf, off_t offset, size_t size,
2073 : size_t *nread, size_t expect)
2074 : {
2075 0 : NTSTATUS status;
2076 0 : size_t l_nread;
2077 :
2078 40 : status = cli_read(cli, fnum, buf, offset, size, &l_nread);
2079 :
2080 40 : if(!NT_STATUS_IS_OK(status)) {
2081 20 : return false;
2082 20 : } else if (l_nread != expect) {
2083 0 : return false;
2084 : }
2085 :
2086 20 : if (nread) {
2087 0 : *nread = l_nread;
2088 : }
2089 :
2090 20 : return true;
2091 : }
2092 :
2093 : #define EXPECTED(ret, v) if ((ret) != (v)) { \
2094 : printf("** "); correct = False; \
2095 : }
2096 :
2097 : /*
2098 : looks at overlapping locks
2099 : */
2100 5 : static bool run_locktest4(int dummy)
2101 : {
2102 0 : static struct cli_state *cli1, *cli2;
2103 5 : const char *fname = "\\lockt4.lck";
2104 0 : uint16_t fnum1, fnum2, f;
2105 0 : bool ret;
2106 0 : char buf[1000];
2107 5 : bool correct = True;
2108 0 : NTSTATUS status;
2109 :
2110 5 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2111 0 : return False;
2112 : }
2113 :
2114 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2115 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
2116 :
2117 5 : printf("starting locktest4\n");
2118 :
2119 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2120 :
2121 5 : cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2122 5 : cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2123 :
2124 5 : memset(buf, 0, sizeof(buf));
2125 :
2126 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2127 : NULL);
2128 5 : if (!NT_STATUS_IS_OK(status)) {
2129 0 : printf("Failed to create file: %s\n", nt_errstr(status));
2130 0 : correct = False;
2131 0 : goto fail;
2132 : }
2133 :
2134 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2135 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
2136 5 : EXPECTED(ret, False);
2137 5 : printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2138 :
2139 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2140 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2141 5 : EXPECTED(ret, True);
2142 5 : printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2143 :
2144 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2145 5 : NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2146 5 : EXPECTED(ret, False);
2147 5 : printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2148 :
2149 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2150 5 : NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2151 5 : EXPECTED(ret, True);
2152 5 : printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2153 :
2154 5 : ret = (cli_setpid(cli1, 1),
2155 10 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2156 5 : (cli_setpid(cli1, 2),
2157 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2158 5 : EXPECTED(ret, False);
2159 5 : printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2160 :
2161 5 : ret = (cli_setpid(cli1, 1),
2162 10 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2163 5 : (cli_setpid(cli1, 2),
2164 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2165 5 : EXPECTED(ret, True);
2166 5 : printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2167 :
2168 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2169 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2170 5 : EXPECTED(ret, True);
2171 5 : printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2172 :
2173 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2174 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2175 5 : EXPECTED(ret, False);
2176 5 : printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2177 :
2178 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2179 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2180 5 : EXPECTED(ret, False);
2181 5 : printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2182 :
2183 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2184 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2185 5 : EXPECTED(ret, True);
2186 5 : printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2187 :
2188 5 : ret = (cli_setpid(cli1, 1),
2189 10 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2190 5 : (cli_setpid(cli1, 2),
2191 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2192 5 : EXPECTED(ret, False);
2193 5 : printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2194 :
2195 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2196 10 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2197 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2198 5 : EXPECTED(ret, False);
2199 5 : printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2200 :
2201 :
2202 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2203 5 : test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2204 5 : EXPECTED(ret, False);
2205 5 : printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2206 :
2207 5 : status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2208 5 : ret = NT_STATUS_IS_OK(status);
2209 5 : if (ret) {
2210 5 : status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2211 : NULL);
2212 5 : ret = NT_STATUS_IS_OK(status);
2213 : }
2214 5 : EXPECTED(ret, False);
2215 5 : printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2216 :
2217 :
2218 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2219 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2220 15 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2221 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2222 5 : EXPECTED(ret, True);
2223 5 : printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2224 :
2225 :
2226 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2227 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2228 10 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2229 5 : test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2230 5 : !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2231 10 : 150, 4, NULL))) &&
2232 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2233 5 : EXPECTED(ret, True);
2234 5 : printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2235 :
2236 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2237 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2238 5 : NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2239 10 : 160, 4, NULL)) &&
2240 5 : test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2241 5 : EXPECTED(ret, True);
2242 5 : printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2243 :
2244 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2245 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2246 5 : NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2247 10 : 170, 4, NULL)) &&
2248 5 : test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2249 5 : EXPECTED(ret, True);
2250 5 : printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2251 :
2252 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2253 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2254 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2255 5 : !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2256 10 : 190, 4, NULL)) &&
2257 5 : test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2258 5 : EXPECTED(ret, True);
2259 5 : printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2260 :
2261 5 : cli_close(cli1, fnum1);
2262 5 : cli_close(cli2, fnum2);
2263 5 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2264 5 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2265 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2266 5 : NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2267 5 : NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2268 15 : NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2269 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2270 5 : cli_close(cli1, f);
2271 5 : cli_close(cli1, fnum1);
2272 5 : EXPECTED(ret, True);
2273 5 : printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2274 :
2275 5 : fail:
2276 5 : cli_close(cli1, fnum1);
2277 5 : cli_close(cli2, fnum2);
2278 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2279 5 : torture_close_connection(cli1);
2280 5 : torture_close_connection(cli2);
2281 :
2282 5 : printf("finished locktest4\n");
2283 5 : return correct;
2284 : }
2285 :
2286 : /*
2287 : looks at lock upgrade/downgrade.
2288 : */
2289 5 : static bool run_locktest5(int dummy)
2290 : {
2291 0 : static struct cli_state *cli1, *cli2;
2292 5 : const char *fname = "\\lockt5.lck";
2293 0 : uint16_t fnum1, fnum2, fnum3;
2294 0 : bool ret;
2295 0 : char buf[1000];
2296 5 : bool correct = True;
2297 0 : NTSTATUS status;
2298 :
2299 5 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2300 0 : return False;
2301 : }
2302 :
2303 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2304 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
2305 :
2306 5 : printf("starting locktest5\n");
2307 :
2308 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2309 :
2310 5 : cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2311 5 : cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2312 5 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2313 :
2314 5 : memset(buf, 0, sizeof(buf));
2315 :
2316 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2317 : NULL);
2318 5 : if (!NT_STATUS_IS_OK(status)) {
2319 0 : printf("Failed to create file: %s\n", nt_errstr(status));
2320 0 : correct = False;
2321 0 : goto fail;
2322 : }
2323 :
2324 : /* Check for NT bug... */
2325 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2326 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2327 5 : cli_close(cli1, fnum1);
2328 5 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2329 5 : status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2330 5 : ret = NT_STATUS_IS_OK(status);
2331 5 : EXPECTED(ret, True);
2332 5 : printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2333 5 : cli_close(cli1, fnum1);
2334 5 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2335 5 : cli_unlock(cli1, fnum3, 0, 1);
2336 :
2337 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2338 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2339 5 : EXPECTED(ret, True);
2340 5 : printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2341 :
2342 5 : status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2343 5 : ret = NT_STATUS_IS_OK(status);
2344 5 : EXPECTED(ret, False);
2345 :
2346 5 : printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2347 :
2348 : /* Unlock the process 2 lock. */
2349 5 : cli_unlock(cli2, fnum2, 0, 4);
2350 :
2351 5 : status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2352 5 : ret = NT_STATUS_IS_OK(status);
2353 5 : EXPECTED(ret, False);
2354 :
2355 5 : printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2356 :
2357 : /* Unlock the process 1 fnum3 lock. */
2358 5 : cli_unlock(cli1, fnum3, 0, 4);
2359 :
2360 : /* Stack 2 more locks here. */
2361 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2362 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2363 :
2364 5 : EXPECTED(ret, True);
2365 5 : printf("the same process %s stack read locks\n", ret?"can":"cannot");
2366 :
2367 : /* Unlock the first process lock, then check this was the WRITE lock that was
2368 : removed. */
2369 :
2370 10 : ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2371 5 : NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2372 :
2373 5 : EXPECTED(ret, True);
2374 5 : printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2375 :
2376 : /* Unlock the process 2 lock. */
2377 5 : cli_unlock(cli2, fnum2, 0, 4);
2378 :
2379 : /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2380 :
2381 5 : ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2382 10 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2383 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2384 :
2385 5 : EXPECTED(ret, True);
2386 5 : printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2387 :
2388 : /* Ensure the next unlock fails. */
2389 5 : ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2390 5 : EXPECTED(ret, False);
2391 5 : printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2392 :
2393 : /* Ensure connection 2 can get a write lock. */
2394 5 : status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2395 5 : ret = NT_STATUS_IS_OK(status);
2396 5 : EXPECTED(ret, True);
2397 :
2398 5 : printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2399 :
2400 :
2401 5 : fail:
2402 5 : cli_close(cli1, fnum1);
2403 5 : cli_close(cli2, fnum2);
2404 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2405 5 : if (!torture_close_connection(cli1)) {
2406 0 : correct = False;
2407 : }
2408 5 : if (!torture_close_connection(cli2)) {
2409 0 : correct = False;
2410 : }
2411 :
2412 5 : printf("finished locktest5\n");
2413 :
2414 5 : return correct;
2415 : }
2416 :
2417 : /*
2418 : tries the unusual lockingX locktype bits
2419 : */
2420 5 : static bool run_locktest6(int dummy)
2421 : {
2422 0 : static struct cli_state *cli;
2423 5 : const char *fname[1] = { "\\lock6.txt" };
2424 0 : int i;
2425 0 : uint16_t fnum;
2426 0 : NTSTATUS status;
2427 :
2428 5 : if (!torture_open_connection(&cli, 0)) {
2429 0 : return False;
2430 : }
2431 :
2432 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
2433 :
2434 5 : printf("starting locktest6\n");
2435 :
2436 10 : for (i=0;i<1;i++) {
2437 5 : printf("Testing %s\n", fname[i]);
2438 :
2439 5 : cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2440 :
2441 5 : cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2442 5 : status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2443 5 : cli_close(cli, fnum);
2444 5 : printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2445 :
2446 5 : cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2447 5 : status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2448 5 : cli_close(cli, fnum);
2449 5 : printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2450 :
2451 5 : cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2452 : }
2453 :
2454 5 : torture_close_connection(cli);
2455 :
2456 5 : printf("finished locktest6\n");
2457 5 : return True;
2458 : }
2459 :
2460 5 : static bool run_locktest7(int dummy)
2461 : {
2462 0 : struct cli_state *cli1;
2463 5 : const char *fname = "\\lockt7.lck";
2464 0 : uint16_t fnum1;
2465 0 : char buf[200];
2466 5 : bool correct = False;
2467 0 : size_t nread;
2468 0 : NTSTATUS status;
2469 :
2470 5 : if (!torture_open_connection(&cli1, 0)) {
2471 0 : return False;
2472 : }
2473 :
2474 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2475 :
2476 5 : printf("starting locktest7\n");
2477 :
2478 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2479 :
2480 5 : cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2481 :
2482 5 : memset(buf, 0, sizeof(buf));
2483 :
2484 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2485 : NULL);
2486 5 : if (!NT_STATUS_IS_OK(status)) {
2487 0 : printf("Failed to create file: %s\n", nt_errstr(status));
2488 0 : goto fail;
2489 : }
2490 :
2491 5 : cli_setpid(cli1, 1);
2492 :
2493 5 : status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2494 5 : if (!NT_STATUS_IS_OK(status)) {
2495 0 : printf("Unable to apply read lock on range 130:4, "
2496 : "error was %s\n", nt_errstr(status));
2497 0 : goto fail;
2498 : } else {
2499 5 : printf("pid1 successfully locked range 130:4 for READ\n");
2500 : }
2501 :
2502 5 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2503 5 : if (!NT_STATUS_IS_OK(status)) {
2504 0 : printf("pid1 unable to read the range 130:4, error was %s\n",
2505 : nt_errstr(status));
2506 0 : goto fail;
2507 5 : } else if (nread != 4) {
2508 0 : printf("pid1 unable to read the range 130:4, "
2509 : "recv %ld req %d\n", (unsigned long)nread, 4);
2510 0 : goto fail;
2511 : } else {
2512 5 : printf("pid1 successfully read the range 130:4\n");
2513 : }
2514 :
2515 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2516 5 : if (!NT_STATUS_IS_OK(status)) {
2517 5 : printf("pid1 unable to write to the range 130:4, error was "
2518 : "%s\n", nt_errstr(status));
2519 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2520 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2521 0 : goto fail;
2522 : }
2523 : } else {
2524 0 : printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2525 0 : goto fail;
2526 : }
2527 :
2528 5 : cli_setpid(cli1, 2);
2529 :
2530 5 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2531 5 : if (!NT_STATUS_IS_OK(status)) {
2532 0 : printf("pid2 unable to read the range 130:4, error was %s\n",
2533 : nt_errstr(status));
2534 0 : goto fail;
2535 5 : } else if (nread != 4) {
2536 0 : printf("pid2 unable to read the range 130:4, "
2537 : "recv %ld req %d\n", (unsigned long)nread, 4);
2538 0 : goto fail;
2539 : } else {
2540 5 : printf("pid2 successfully read the range 130:4\n");
2541 : }
2542 :
2543 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2544 5 : if (!NT_STATUS_IS_OK(status)) {
2545 5 : printf("pid2 unable to write to the range 130:4, error was "
2546 : "%s\n", nt_errstr(status));
2547 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2548 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2549 0 : goto fail;
2550 : }
2551 : } else {
2552 0 : printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2553 0 : goto fail;
2554 : }
2555 :
2556 5 : cli_setpid(cli1, 1);
2557 5 : cli_unlock(cli1, fnum1, 130, 4);
2558 :
2559 5 : status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2560 5 : if (!NT_STATUS_IS_OK(status)) {
2561 0 : printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2562 0 : goto fail;
2563 : } else {
2564 5 : printf("pid1 successfully locked range 130:4 for WRITE\n");
2565 : }
2566 :
2567 5 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2568 5 : if (!NT_STATUS_IS_OK(status)) {
2569 0 : printf("pid1 unable to read the range 130:4, error was %s\n",
2570 : nt_errstr(status));
2571 0 : goto fail;
2572 5 : } else if (nread != 4) {
2573 0 : printf("pid1 unable to read the range 130:4, "
2574 : "recv %ld req %d\n", (unsigned long)nread, 4);
2575 0 : goto fail;
2576 : } else {
2577 5 : printf("pid1 successfully read the range 130:4\n");
2578 : }
2579 :
2580 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2581 5 : if (!NT_STATUS_IS_OK(status)) {
2582 0 : printf("pid1 unable to write to the range 130:4, error was "
2583 : "%s\n", nt_errstr(status));
2584 0 : goto fail;
2585 : } else {
2586 5 : printf("pid1 successfully wrote to the range 130:4\n");
2587 : }
2588 :
2589 5 : cli_setpid(cli1, 2);
2590 :
2591 5 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2592 5 : if (!NT_STATUS_IS_OK(status)) {
2593 5 : printf("pid2 unable to read the range 130:4, error was "
2594 : "%s\n", nt_errstr(status));
2595 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2596 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2597 0 : goto fail;
2598 : }
2599 : } else {
2600 0 : printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2601 : (unsigned long)nread);
2602 0 : goto fail;
2603 : }
2604 :
2605 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2606 5 : if (!NT_STATUS_IS_OK(status)) {
2607 5 : printf("pid2 unable to write to the range 130:4, error was "
2608 : "%s\n", nt_errstr(status));
2609 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2610 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2611 0 : goto fail;
2612 : }
2613 : } else {
2614 0 : printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2615 0 : goto fail;
2616 : }
2617 :
2618 5 : cli_unlock(cli1, fnum1, 130, 0);
2619 5 : correct = True;
2620 :
2621 5 : fail:
2622 5 : cli_close(cli1, fnum1);
2623 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2624 5 : torture_close_connection(cli1);
2625 :
2626 5 : printf("finished locktest7\n");
2627 5 : return correct;
2628 : }
2629 :
2630 : /*
2631 : * This demonstrates a problem with our use of GPFS share modes: A file
2632 : * descriptor sitting in the pending close queue holding a GPFS share mode
2633 : * blocks opening a file another time. Happens with Word 2007 temp files.
2634 : * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2635 : * open is denied with NT_STATUS_SHARING_VIOLATION.
2636 : */
2637 :
2638 0 : static bool run_locktest8(int dummy)
2639 : {
2640 0 : struct cli_state *cli1;
2641 0 : const char *fname = "\\lockt8.lck";
2642 0 : uint16_t fnum1, fnum2;
2643 0 : char buf[200];
2644 0 : bool correct = False;
2645 0 : NTSTATUS status;
2646 :
2647 0 : if (!torture_open_connection(&cli1, 0)) {
2648 0 : return False;
2649 : }
2650 :
2651 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2652 :
2653 0 : printf("starting locktest8\n");
2654 :
2655 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2656 :
2657 0 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2658 : &fnum1);
2659 0 : if (!NT_STATUS_IS_OK(status)) {
2660 0 : d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2661 0 : return false;
2662 : }
2663 :
2664 0 : memset(buf, 0, sizeof(buf));
2665 :
2666 0 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2667 0 : if (!NT_STATUS_IS_OK(status)) {
2668 0 : d_fprintf(stderr, "cli_openx second time returned %s\n",
2669 : nt_errstr(status));
2670 0 : goto fail;
2671 : }
2672 :
2673 0 : status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2674 0 : if (!NT_STATUS_IS_OK(status)) {
2675 0 : printf("Unable to apply read lock on range 1:1, error was "
2676 : "%s\n", nt_errstr(status));
2677 0 : goto fail;
2678 : }
2679 :
2680 0 : status = cli_close(cli1, fnum1);
2681 0 : if (!NT_STATUS_IS_OK(status)) {
2682 0 : d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2683 0 : goto fail;
2684 : }
2685 :
2686 0 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2687 0 : if (!NT_STATUS_IS_OK(status)) {
2688 0 : d_fprintf(stderr, "cli_openx third time returned %s\n",
2689 : nt_errstr(status));
2690 0 : goto fail;
2691 : }
2692 :
2693 0 : correct = true;
2694 :
2695 0 : fail:
2696 0 : cli_close(cli1, fnum1);
2697 0 : cli_close(cli1, fnum2);
2698 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2699 0 : torture_close_connection(cli1);
2700 :
2701 0 : printf("finished locktest8\n");
2702 0 : return correct;
2703 : }
2704 :
2705 : /*
2706 : * This test is designed to be run in conjunction with
2707 : * external NFS or POSIX locks taken in the filesystem.
2708 : * It checks that the smbd server will block until the
2709 : * lock is released and then acquire it. JRA.
2710 : */
2711 :
2712 : static bool got_alarm;
2713 : static struct cli_state *alarm_cli;
2714 :
2715 0 : static void alarm_handler(int dummy)
2716 : {
2717 0 : got_alarm = True;
2718 0 : }
2719 :
2720 0 : static void alarm_handler_parent(int dummy)
2721 : {
2722 0 : smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2723 0 : }
2724 :
2725 8 : static void do_local_lock(const char *fname, int read_fd, int write_fd)
2726 : {
2727 0 : int fd;
2728 8 : char c = '\0';
2729 0 : struct flock lock;
2730 8 : const char *local_pathname = NULL;
2731 0 : int ret;
2732 :
2733 8 : local_pathname = talloc_asprintf(talloc_tos(),
2734 : "%s/%s", local_path, fname);
2735 8 : if (!local_pathname) {
2736 0 : printf("child: alloc fail\n");
2737 0 : exit(1);
2738 : }
2739 :
2740 8 : unlink(local_pathname);
2741 8 : fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2742 8 : if (fd == -1) {
2743 0 : printf("child: open of %s failed %s.\n",
2744 0 : local_pathname, strerror(errno));
2745 0 : exit(1);
2746 : }
2747 :
2748 : /* Now take a fcntl lock. */
2749 8 : lock.l_type = F_WRLCK;
2750 8 : lock.l_whence = SEEK_SET;
2751 8 : lock.l_start = 0;
2752 8 : lock.l_len = 4;
2753 8 : lock.l_pid = getpid();
2754 :
2755 8 : ret = fcntl(fd,F_SETLK,&lock);
2756 8 : if (ret == -1) {
2757 0 : printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2758 0 : local_pathname, strerror(errno));
2759 0 : exit(1);
2760 : } else {
2761 8 : printf("child: got lock 0:4 on file %s.\n",
2762 : local_pathname );
2763 8 : fflush(stdout);
2764 : }
2765 :
2766 8 : CatchSignal(SIGALRM, alarm_handler);
2767 8 : alarm(5);
2768 : /* Signal the parent. */
2769 8 : if (write(write_fd, &c, 1) != 1) {
2770 0 : printf("child: start signal fail %s.\n",
2771 0 : strerror(errno));
2772 0 : exit(1);
2773 : }
2774 8 : alarm(0);
2775 :
2776 8 : alarm(10);
2777 : /* Wait for the parent to be ready. */
2778 8 : if (read(read_fd, &c, 1) != 1) {
2779 0 : printf("child: reply signal fail %s.\n",
2780 0 : strerror(errno));
2781 0 : exit(1);
2782 : }
2783 8 : alarm(0);
2784 :
2785 8 : sleep(5);
2786 8 : close(fd);
2787 8 : printf("child: released lock 0:4 on file %s.\n",
2788 : local_pathname );
2789 8 : fflush(stdout);
2790 8 : exit(0);
2791 : }
2792 :
2793 8 : static bool _run_locktest9X(const char *fname, int timeout)
2794 : {
2795 0 : struct cli_state *cli1;
2796 8 : char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2797 0 : uint16_t fnum;
2798 8 : bool correct = False;
2799 0 : int pipe_in[2], pipe_out[2];
2800 0 : pid_t child_pid;
2801 8 : char c = '\0';
2802 0 : int ret;
2803 0 : struct timeval start;
2804 0 : double seconds;
2805 0 : NTSTATUS status;
2806 :
2807 8 : printf("starting locktest9X: %s\n", fname);
2808 :
2809 8 : if (local_path == NULL) {
2810 0 : d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2811 0 : return false;
2812 : }
2813 :
2814 8 : if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2815 0 : return false;
2816 : }
2817 :
2818 8 : child_pid = fork();
2819 16 : if (child_pid == -1) {
2820 0 : return false;
2821 : }
2822 :
2823 16 : if (child_pid == 0) {
2824 : /* Child. */
2825 8 : do_local_lock(fname, pipe_out[0], pipe_in[1]);
2826 0 : exit(0);
2827 : }
2828 :
2829 8 : close(pipe_out[0]);
2830 8 : close(pipe_in[1]);
2831 8 : pipe_out[0] = -1;
2832 8 : pipe_in[1] = -1;
2833 :
2834 : /* Parent. */
2835 8 : ret = read(pipe_in[0], &c, 1);
2836 8 : if (ret != 1) {
2837 0 : d_fprintf(stderr, "failed to read start signal from child. %s\n",
2838 0 : strerror(errno));
2839 0 : return false;
2840 : }
2841 :
2842 8 : if (!torture_open_connection(&cli1, 0)) {
2843 0 : return false;
2844 : }
2845 :
2846 8 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2847 :
2848 8 : status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2849 : &fnum);
2850 8 : if (!NT_STATUS_IS_OK(status)) {
2851 0 : d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2852 0 : return false;
2853 : }
2854 :
2855 : /* Ensure the child has the lock. */
2856 8 : status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2857 8 : if (NT_STATUS_IS_OK(status)) {
2858 0 : d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2859 0 : goto fail;
2860 : } else {
2861 8 : d_printf("Child has the lock.\n");
2862 : }
2863 :
2864 : /* Tell the child to wait 5 seconds then exit. */
2865 8 : ret = write(pipe_out[1], &c, 1);
2866 8 : if (ret != 1) {
2867 0 : d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2868 0 : strerror(errno));
2869 0 : goto fail;
2870 : }
2871 :
2872 : /* Wait 20 seconds for the lock. */
2873 8 : alarm_cli = cli1;
2874 8 : CatchSignal(SIGALRM, alarm_handler_parent);
2875 8 : alarm(20);
2876 :
2877 8 : start = timeval_current();
2878 :
2879 8 : status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2880 8 : if (!NT_STATUS_IS_OK(status)) {
2881 0 : d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2882 : "%s\n", nt_errstr(status));
2883 0 : goto fail_nofd;
2884 : }
2885 8 : alarm(0);
2886 :
2887 8 : seconds = timeval_elapsed(&start);
2888 :
2889 8 : printf("Parent got the lock after %.2f seconds.\n",
2890 : seconds);
2891 :
2892 8 : status = cli_close(cli1, fnum);
2893 8 : if (!NT_STATUS_IS_OK(status)) {
2894 0 : d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2895 0 : goto fail;
2896 : }
2897 :
2898 8 : correct = true;
2899 :
2900 8 : fail:
2901 8 : cli_close(cli1, fnum);
2902 8 : torture_close_connection(cli1);
2903 :
2904 8 : fail_nofd:
2905 :
2906 8 : printf("finished locktest9X: %s\n", fname);
2907 8 : return correct;
2908 : }
2909 :
2910 4 : static bool run_locktest9a(int dummy)
2911 : {
2912 4 : return _run_locktest9X("lock9a.dat", -1);
2913 : }
2914 :
2915 4 : static bool run_locktest9b(int dummy)
2916 : {
2917 4 : return _run_locktest9X("lock9b.dat", 10000);
2918 : }
2919 :
2920 : struct locktest10_state {
2921 : bool ok;
2922 : bool done;
2923 : };
2924 :
2925 : static void locktest10_lockingx_done(struct tevent_req *subreq);
2926 : static void locktest10_read_andx_done(struct tevent_req *subreq);
2927 :
2928 5 : static bool run_locktest10(int dummy)
2929 : {
2930 5 : struct tevent_context *ev = NULL;
2931 5 : struct cli_state *cli1 = NULL;
2932 5 : struct cli_state *cli2 = NULL;
2933 5 : struct smb1_lock_element lck = { 0 };
2934 5 : struct tevent_req *reqs[2] = { NULL };
2935 5 : struct tevent_req *smbreqs[2] = { NULL };
2936 5 : const char fname[] = "\\lockt10.lck";
2937 0 : uint16_t fnum1, fnum2;
2938 5 : bool ret = false;
2939 0 : bool ok;
2940 5 : uint8_t data = 1;
2941 5 : struct locktest10_state state = { .ok = true };
2942 0 : NTSTATUS status;
2943 :
2944 5 : printf("starting locktest10\n");
2945 :
2946 5 : ev = samba_tevent_context_init(NULL);
2947 5 : if (ev == NULL) {
2948 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
2949 0 : goto done;
2950 : }
2951 :
2952 5 : ok = torture_open_connection(&cli1, 0);
2953 5 : if (!ok) {
2954 0 : goto done;
2955 : }
2956 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2957 :
2958 5 : ok = torture_open_connection(&cli2, 1);
2959 5 : if (!ok) {
2960 0 : goto done;
2961 : }
2962 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
2963 :
2964 5 : status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2965 5 : if (!NT_STATUS_IS_OK(status)) {
2966 0 : d_fprintf(stderr,
2967 : "cli_openx failed: %s\n",
2968 : nt_errstr(status));
2969 0 : goto done;
2970 : }
2971 :
2972 5 : status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2973 5 : if (!NT_STATUS_IS_OK(status)) {
2974 0 : d_fprintf(stderr,
2975 : "cli_writeall failed: %s\n",
2976 : nt_errstr(status));
2977 0 : goto done;
2978 : }
2979 :
2980 5 : status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2981 5 : if (!NT_STATUS_IS_OK(status)) {
2982 0 : d_fprintf(stderr,
2983 : "cli_openx failed: %s\n",
2984 : nt_errstr(status));
2985 0 : goto done;
2986 : }
2987 :
2988 5 : status = cli_locktype(
2989 : cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2990 5 : if (!NT_STATUS_IS_OK(status)) {
2991 0 : d_fprintf(stderr,
2992 : "cli_locktype failed: %s\n",
2993 : nt_errstr(status));
2994 0 : goto done;
2995 : }
2996 :
2997 5 : lck = (struct smb1_lock_element) {
2998 5 : .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2999 : };
3000 :
3001 5 : reqs[0] = cli_lockingx_create(
3002 : ev, /* mem_ctx */
3003 : ev, /* tevent_context */
3004 : cli1, /* cli */
3005 : fnum1, /* fnum */
3006 : LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3007 : 0, /* newoplocklevel */
3008 : 1, /* timeout */
3009 : 0, /* num_unlocks */
3010 : NULL, /* unlocks */
3011 : 1, /* num_locks */
3012 : &lck, /* locks */
3013 : &smbreqs[0]); /* psmbreq */
3014 5 : if (reqs[0] == NULL) {
3015 0 : d_fprintf(stderr, "cli_lockingx_create failed\n");
3016 0 : goto done;
3017 : }
3018 5 : tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
3019 :
3020 5 : reqs[1] = cli_read_andx_create(
3021 : ev, /* mem_ctx */
3022 : ev, /* ev */
3023 : cli1, /* cli */
3024 : fnum1, /* fnum */
3025 : 0, /* offset */
3026 : 1, /* size */
3027 : &smbreqs[1]); /* psmbreq */
3028 5 : if (reqs[1] == NULL) {
3029 0 : d_fprintf(stderr, "cli_read_andx_create failed\n");
3030 0 : goto done;
3031 : }
3032 5 : tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
3033 :
3034 5 : status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
3035 5 : if (!NT_STATUS_IS_OK(status)) {
3036 0 : d_fprintf(stderr,
3037 : "smb1cli_req_chain_submit failed: %s\n",
3038 : nt_errstr(status));
3039 0 : goto done;
3040 : }
3041 :
3042 30 : while (!state.done) {
3043 25 : tevent_loop_once(ev);
3044 : }
3045 :
3046 5 : torture_close_connection(cli1);
3047 :
3048 5 : if (state.ok) {
3049 5 : ret = true;
3050 : }
3051 0 : done:
3052 5 : return ret;
3053 : }
3054 :
3055 5 : static void locktest10_lockingx_done(struct tevent_req *subreq)
3056 : {
3057 5 : struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3058 0 : NTSTATUS status;
3059 :
3060 5 : status = cli_lockingx_recv(subreq);
3061 5 : TALLOC_FREE(subreq);
3062 :
3063 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3064 0 : d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3065 0 : state->ok = false;
3066 : }
3067 5 : }
3068 :
3069 5 : static void locktest10_read_andx_done(struct tevent_req *subreq)
3070 : {
3071 5 : struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3072 5 : ssize_t received = -1;
3073 5 : uint8_t *rcvbuf = NULL;
3074 0 : NTSTATUS status;
3075 :
3076 5 : status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3077 :
3078 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
3079 0 : d_printf("cli_read_andx returned %s\n", nt_errstr(status));
3080 0 : state->ok = false;
3081 : }
3082 :
3083 5 : state->done = true;
3084 5 : TALLOC_FREE(subreq);
3085 5 : }
3086 :
3087 5 : static bool run_locktest11(int dummy)
3088 : {
3089 0 : struct cli_state *cli1;
3090 5 : const char *fname = "\\lockt11.lck";
3091 0 : NTSTATUS status;
3092 0 : uint16_t fnum;
3093 5 : bool ret = false;
3094 :
3095 5 : if (!torture_open_connection(&cli1, 0)) {
3096 0 : return false;
3097 : }
3098 :
3099 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
3100 :
3101 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3102 :
3103 5 : status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
3104 5 : if (!NT_STATUS_IS_OK(status)) {
3105 0 : d_fprintf(stderr,
3106 : "cli_openx returned %s\n",
3107 : nt_errstr(status));
3108 0 : return false;
3109 : }
3110 :
3111 : /*
3112 : * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3113 : * returns NT_STATUS_OK
3114 : */
3115 :
3116 5 : status = cli_lockingx(
3117 : cli1, /* cli */
3118 : fnum, /* fnum */
3119 : LOCKING_ANDX_CANCEL_LOCK, /* typeoflock */
3120 : 0, /* newoplocklevel */
3121 : 0, /* timeout */
3122 : 0, /* num_unlocks */
3123 : NULL, /* unlocks */
3124 : 0, /* num_locks */
3125 : NULL); /* locks */
3126 :
3127 5 : if (!NT_STATUS_IS_OK(status)) {
3128 1 : d_printf("cli_lockingX returned %s\n", nt_errstr(status));
3129 1 : goto fail;
3130 : }
3131 :
3132 4 : ret = true;
3133 5 : fail:
3134 5 : cli_close(cli1, fnum);
3135 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3136 :
3137 5 : return ret;
3138 : }
3139 :
3140 : struct deferred_close_state {
3141 : struct tevent_context *ev;
3142 : struct cli_state *cli;
3143 : uint16_t fnum;
3144 : };
3145 :
3146 : static void deferred_close_waited(struct tevent_req *subreq);
3147 : static void deferred_close_done(struct tevent_req *subreq);
3148 :
3149 5 : static struct tevent_req *deferred_close_send(
3150 : TALLOC_CTX *mem_ctx,
3151 : struct tevent_context *ev,
3152 : int wait_secs,
3153 : struct cli_state *cli,
3154 : uint16_t fnum)
3155 : {
3156 5 : struct tevent_req *req = NULL, *subreq = NULL;
3157 5 : struct deferred_close_state *state = NULL;
3158 5 : struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
3159 :
3160 5 : req = tevent_req_create(
3161 : mem_ctx, &state, struct deferred_close_state);
3162 5 : if (req == NULL) {
3163 0 : return NULL;
3164 : }
3165 5 : state->ev = ev;
3166 5 : state->cli = cli;
3167 5 : state->fnum = fnum;
3168 :
3169 5 : subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
3170 5 : if (tevent_req_nomem(subreq, req)) {
3171 0 : return tevent_req_post(req, ev);
3172 : }
3173 5 : tevent_req_set_callback(subreq, deferred_close_waited, req);
3174 5 : return req;
3175 : }
3176 :
3177 5 : static void deferred_close_waited(struct tevent_req *subreq)
3178 : {
3179 5 : struct tevent_req *req = tevent_req_callback_data(
3180 : subreq, struct tevent_req);
3181 5 : struct deferred_close_state *state = tevent_req_data(
3182 : req, struct deferred_close_state);
3183 0 : bool ok;
3184 :
3185 5 : ok = tevent_wakeup_recv(subreq);
3186 5 : TALLOC_FREE(subreq);
3187 5 : if (!ok) {
3188 0 : tevent_req_oom(req);
3189 0 : return;
3190 : }
3191 :
3192 5 : subreq = cli_close_send(state, state->ev, state->cli, state->fnum, 0);
3193 5 : if (tevent_req_nomem(subreq, req)) {
3194 0 : return;
3195 : }
3196 5 : tevent_req_set_callback(subreq, deferred_close_done, req);
3197 : }
3198 :
3199 5 : static void deferred_close_done(struct tevent_req *subreq)
3200 : {
3201 5 : NTSTATUS status = cli_close_recv(subreq);
3202 5 : tevent_req_simple_finish_ntstatus(subreq, status);
3203 5 : }
3204 :
3205 5 : static NTSTATUS deferred_close_recv(struct tevent_req *req)
3206 : {
3207 5 : return tevent_req_simple_recv_ntstatus(req);
3208 : }
3209 :
3210 : struct lockread_state {
3211 : struct smb1_lock_element lck;
3212 : struct tevent_req *reqs[2];
3213 : struct tevent_req *smbreqs[2];
3214 : NTSTATUS lock_status;
3215 : NTSTATUS read_status;
3216 : uint8_t *readbuf;
3217 : };
3218 :
3219 : static void lockread_lockingx_done(struct tevent_req *subreq);
3220 : static void lockread_read_andx_done(struct tevent_req *subreq);
3221 :
3222 5 : static struct tevent_req *lockread_send(
3223 : TALLOC_CTX *mem_ctx,
3224 : struct tevent_context *ev,
3225 : struct cli_state *cli,
3226 : uint16_t fnum)
3227 : {
3228 5 : struct tevent_req *req = NULL;
3229 5 : struct lockread_state *state = NULL;
3230 0 : NTSTATUS status;
3231 :
3232 5 : req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3233 5 : if (req == NULL) {
3234 0 : return NULL;
3235 : }
3236 :
3237 10 : state->lck = (struct smb1_lock_element) {
3238 5 : .pid = cli_getpid(cli), .offset = 0, .length = 1,
3239 : };
3240 :
3241 10 : state->reqs[0] = cli_lockingx_create(
3242 : ev, /* mem_ctx */
3243 : ev, /* tevent_context */
3244 : cli, /* cli */
3245 : fnum, /* fnum */
3246 : LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3247 : 0, /* newoplocklevel */
3248 : 10000, /* timeout */
3249 : 0, /* num_unlocks */
3250 : NULL, /* unlocks */
3251 : 1, /* num_locks */
3252 5 : &state->lck, /* locks */
3253 5 : &state->smbreqs[0]); /* psmbreq */
3254 5 : if (tevent_req_nomem(state->reqs[0], req)) {
3255 0 : return tevent_req_post(req, ev);
3256 : }
3257 5 : tevent_req_set_callback(
3258 : state->reqs[0], lockread_lockingx_done, req);
3259 :
3260 10 : state->reqs[1] = cli_read_andx_create(
3261 : ev, /* mem_ctx */
3262 : ev, /* ev */
3263 : cli, /* cli */
3264 : fnum, /* fnum */
3265 : 0, /* offset */
3266 : 1, /* size */
3267 5 : &state->smbreqs[1]); /* psmbreq */
3268 5 : if (tevent_req_nomem(state->reqs[1], req)) {
3269 0 : return tevent_req_post(req, ev);
3270 : }
3271 5 : tevent_req_set_callback(
3272 : state->reqs[1], lockread_read_andx_done, req);
3273 :
3274 5 : status = smb1cli_req_chain_submit(state->smbreqs, 2);
3275 5 : if (tevent_req_nterror(req, status)) {
3276 0 : return tevent_req_post(req, ev);
3277 : }
3278 5 : return req;
3279 : }
3280 :
3281 5 : static void lockread_lockingx_done(struct tevent_req *subreq)
3282 : {
3283 5 : struct tevent_req *req = tevent_req_callback_data(
3284 : subreq, struct tevent_req);
3285 5 : struct lockread_state *state = tevent_req_data(
3286 : req, struct lockread_state);
3287 5 : state->lock_status = cli_lockingx_recv(subreq);
3288 5 : TALLOC_FREE(subreq);
3289 5 : d_fprintf(stderr,
3290 : "lockingx returned %s\n",
3291 : nt_errstr(state->lock_status));
3292 5 : }
3293 :
3294 5 : static void lockread_read_andx_done(struct tevent_req *subreq)
3295 : {
3296 5 : struct tevent_req *req = tevent_req_callback_data(
3297 : subreq, struct tevent_req);
3298 5 : struct lockread_state *state = tevent_req_data(
3299 : req, struct lockread_state);
3300 5 : ssize_t received = -1;
3301 5 : uint8_t *rcvbuf = NULL;
3302 :
3303 5 : state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3304 :
3305 5 : d_fprintf(stderr,
3306 : "read returned %s\n",
3307 : nt_errstr(state->read_status));
3308 :
3309 5 : if (!NT_STATUS_IS_OK(state->read_status)) {
3310 4 : TALLOC_FREE(subreq);
3311 4 : tevent_req_done(req);
3312 4 : return;
3313 : }
3314 :
3315 1 : if (received > 0) {
3316 1 : state->readbuf = talloc_memdup(state, rcvbuf, received);
3317 1 : TALLOC_FREE(subreq);
3318 1 : if (tevent_req_nomem(state->readbuf, req)) {
3319 0 : return;
3320 : }
3321 : }
3322 1 : TALLOC_FREE(subreq);
3323 1 : tevent_req_done(req);
3324 : }
3325 :
3326 5 : static NTSTATUS lockread_recv(
3327 : struct tevent_req *req,
3328 : NTSTATUS *lock_status,
3329 : NTSTATUS *read_status,
3330 : TALLOC_CTX *mem_ctx,
3331 : uint8_t **read_buf)
3332 : {
3333 5 : struct lockread_state *state = tevent_req_data(
3334 : req, struct lockread_state);
3335 0 : NTSTATUS status;
3336 :
3337 5 : if (tevent_req_is_nterror(req, &status)) {
3338 0 : return status;
3339 : }
3340 :
3341 5 : *lock_status = state->lock_status;
3342 5 : *read_status = state->read_status;
3343 5 : if (state->readbuf != NULL) {
3344 1 : *read_buf = talloc_move(mem_ctx, &state->readbuf);
3345 : } else {
3346 4 : *read_buf = NULL;
3347 : }
3348 :
3349 5 : return NT_STATUS_OK;
3350 : }
3351 :
3352 : struct lock12_state {
3353 : uint8_t dummy;
3354 : };
3355 :
3356 : static void lock12_closed(struct tevent_req *subreq);
3357 : static void lock12_read(struct tevent_req *subreq);
3358 :
3359 5 : static struct tevent_req *lock12_send(
3360 : TALLOC_CTX *mem_ctx,
3361 : struct tevent_context *ev,
3362 : struct cli_state *cli,
3363 : uint16_t fnum1,
3364 : uint16_t fnum2)
3365 : {
3366 5 : struct tevent_req *req = NULL, *subreq = NULL;
3367 5 : struct lock12_state *state = NULL;
3368 :
3369 5 : req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3370 5 : if (req == NULL) {
3371 0 : return NULL;
3372 : }
3373 :
3374 5 : subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3375 5 : if (tevent_req_nomem(subreq, req)) {
3376 0 : return tevent_req_post(req, ev);
3377 : }
3378 5 : tevent_req_set_callback(subreq, lock12_closed, req);
3379 :
3380 5 : subreq = lockread_send(state, ev, cli, fnum2);
3381 5 : if (tevent_req_nomem(subreq, req)) {
3382 0 : return tevent_req_post(req, ev);
3383 : }
3384 5 : tevent_req_set_callback(subreq, lock12_read, req);
3385 :
3386 5 : return req;
3387 : }
3388 :
3389 5 : static void lock12_closed(struct tevent_req *subreq)
3390 : {
3391 5 : struct tevent_req *req = tevent_req_callback_data(
3392 : subreq, struct tevent_req);
3393 0 : NTSTATUS status;
3394 :
3395 5 : status = deferred_close_recv(subreq);
3396 5 : TALLOC_FREE(subreq);
3397 5 : DBG_DEBUG("close returned %s\n", nt_errstr(status));
3398 5 : if (tevent_req_nterror(req, status)) {
3399 0 : return;
3400 : }
3401 : }
3402 :
3403 5 : static void lock12_read(struct tevent_req *subreq)
3404 : {
3405 5 : struct tevent_req *req = tevent_req_callback_data(
3406 : subreq, struct tevent_req);
3407 5 : struct lock12_state *state = tevent_req_data(
3408 : req, struct lock12_state);
3409 0 : NTSTATUS status, lock_status, read_status;
3410 5 : uint8_t *buf = NULL;
3411 :
3412 5 : status = lockread_recv(
3413 : subreq, &lock_status, &read_status, state, &buf);
3414 5 : TALLOC_FREE(subreq);
3415 10 : if (tevent_req_nterror(req, status) ||
3416 10 : tevent_req_nterror(req, lock_status) ||
3417 5 : tevent_req_nterror(req, read_status)) {
3418 4 : return;
3419 : }
3420 1 : tevent_req_done(req);
3421 : }
3422 :
3423 5 : static NTSTATUS lock12_recv(struct tevent_req *req)
3424 :
3425 : {
3426 0 : NTSTATUS status;
3427 :
3428 5 : if (tevent_req_is_nterror(req, &status)) {
3429 4 : return status;
3430 : }
3431 1 : return NT_STATUS_OK;
3432 : }
3433 :
3434 5 : static bool run_locktest12(int dummy)
3435 : {
3436 5 : struct tevent_context *ev = NULL;
3437 5 : struct tevent_req *req = NULL;
3438 5 : struct cli_state *cli = NULL;
3439 5 : const char fname[] = "\\lockt12.lck";
3440 0 : uint16_t fnum1, fnum2;
3441 5 : bool ret = false;
3442 0 : bool ok;
3443 5 : uint8_t data = 1;
3444 0 : NTSTATUS status;
3445 :
3446 5 : printf("starting locktest12\n");
3447 :
3448 5 : ev = samba_tevent_context_init(NULL);
3449 5 : if (ev == NULL) {
3450 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
3451 0 : goto done;
3452 : }
3453 :
3454 5 : ok = torture_open_connection(&cli, 0);
3455 5 : if (!ok) {
3456 0 : goto done;
3457 : }
3458 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3459 :
3460 5 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3461 5 : if (!NT_STATUS_IS_OK(status)) {
3462 0 : d_fprintf(stderr,
3463 : "cli_openx failed: %s\n",
3464 : nt_errstr(status));
3465 0 : goto done;
3466 : }
3467 :
3468 5 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3469 5 : if (!NT_STATUS_IS_OK(status)) {
3470 0 : d_fprintf(stderr,
3471 : "cli_openx failed: %s\n",
3472 : nt_errstr(status));
3473 0 : goto done;
3474 : }
3475 :
3476 5 : status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3477 5 : if (!NT_STATUS_IS_OK(status)) {
3478 0 : d_fprintf(stderr,
3479 : "cli_writeall failed: %s\n",
3480 : nt_errstr(status));
3481 0 : goto done;
3482 : }
3483 :
3484 5 : status = cli_locktype(
3485 : cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3486 5 : if (!NT_STATUS_IS_OK(status)) {
3487 0 : d_fprintf(stderr,
3488 : "cli_locktype failed: %s\n",
3489 : nt_errstr(status));
3490 0 : goto done;
3491 : }
3492 :
3493 5 : req = lock12_send(ev, ev, cli, fnum1, fnum2);
3494 5 : if (req == NULL) {
3495 0 : d_fprintf(stderr, "lock12_send failed\n");
3496 0 : goto done;
3497 : }
3498 :
3499 5 : ok = tevent_req_poll_ntstatus(req, ev, &status);
3500 5 : if (!ok) {
3501 0 : d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3502 0 : goto done;
3503 : }
3504 :
3505 5 : if (!NT_STATUS_IS_OK(status)) {
3506 0 : d_fprintf(stderr,
3507 : "tevent_req_poll_ntstatus returned %s\n",
3508 : nt_errstr(status));
3509 0 : goto done;
3510 : }
3511 :
3512 5 : status = lock12_recv(req);
3513 5 : if (!NT_STATUS_IS_OK(status)) {
3514 4 : d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3515 4 : goto done;
3516 : }
3517 :
3518 1 : ret = true;
3519 5 : done:
3520 5 : if (cli != NULL) {
3521 5 : torture_close_connection(cli);
3522 : }
3523 5 : return ret;
3524 : }
3525 :
3526 : struct lock_ntcancel_state {
3527 : struct timeval start;
3528 : struct smb1_lock_element lck;
3529 : struct tevent_req *subreq;
3530 : };
3531 :
3532 : static void lock_ntcancel_waited(struct tevent_req *subreq);
3533 : static void lock_ntcancel_done(struct tevent_req *subreq);
3534 :
3535 5 : static struct tevent_req *lock_ntcancel_send(
3536 : TALLOC_CTX *mem_ctx,
3537 : struct tevent_context *ev,
3538 : struct cli_state *cli,
3539 : uint16_t fnum)
3540 : {
3541 5 : struct tevent_req *req = NULL, *subreq = NULL;
3542 5 : struct lock_ntcancel_state *state = NULL;
3543 :
3544 5 : req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3545 5 : if (req == NULL) {
3546 0 : return NULL;
3547 : }
3548 10 : state->lck = (struct smb1_lock_element) {
3549 5 : .pid = cli_getpid(cli), .offset = 0, .length = 1,
3550 : };
3551 5 : state->start = timeval_current();
3552 :
3553 10 : state->subreq = cli_lockingx_send(
3554 : state, /* mem_ctx */
3555 : ev, /* tevent_context */
3556 : cli, /* cli */
3557 : fnum, /* fnum */
3558 : LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3559 : 0, /* newoplocklevel */
3560 : 10000, /* timeout */
3561 : 0, /* num_unlocks */
3562 : NULL, /* unlocks */
3563 : 1, /* num_locks */
3564 5 : &state->lck); /* locks */
3565 5 : if (tevent_req_nomem(state->subreq, req)) {
3566 0 : return tevent_req_post(req, ev);
3567 : }
3568 5 : tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3569 :
3570 5 : subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3571 5 : if (tevent_req_nomem(subreq, req)) {
3572 0 : return tevent_req_post(req, ev);
3573 : }
3574 5 : tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3575 5 : return req;
3576 : }
3577 :
3578 5 : static void lock_ntcancel_waited(struct tevent_req *subreq)
3579 : {
3580 5 : struct tevent_req *req = tevent_req_callback_data(
3581 : subreq, struct tevent_req);
3582 5 : struct lock_ntcancel_state *state = tevent_req_data(
3583 : req, struct lock_ntcancel_state);
3584 0 : bool ok;
3585 :
3586 5 : ok = tevent_wakeup_recv(subreq);
3587 5 : TALLOC_FREE(subreq);
3588 5 : if (!ok) {
3589 0 : tevent_req_oom(req);
3590 0 : return;
3591 : }
3592 :
3593 5 : ok = tevent_req_cancel(state->subreq);
3594 5 : if (!ok) {
3595 0 : d_fprintf(stderr, "Could not cancel subreq\n");
3596 0 : tevent_req_oom(req);
3597 0 : return;
3598 : }
3599 : }
3600 :
3601 5 : static void lock_ntcancel_done(struct tevent_req *subreq)
3602 : {
3603 5 : struct tevent_req *req = tevent_req_callback_data(
3604 : subreq, struct tevent_req);
3605 5 : struct lock_ntcancel_state *state = tevent_req_data(
3606 : req, struct lock_ntcancel_state);
3607 0 : NTSTATUS status;
3608 0 : double elapsed;
3609 :
3610 5 : status = cli_lockingx_recv(subreq);
3611 5 : TALLOC_FREE(subreq);
3612 :
3613 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3614 0 : d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3615 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3616 0 : return;
3617 : }
3618 :
3619 5 : elapsed = timeval_elapsed(&state->start);
3620 :
3621 5 : if (elapsed > 3) {
3622 0 : d_printf("cli_lockingx was too slow, cancel did not work\n");
3623 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3624 0 : return;
3625 : }
3626 :
3627 5 : tevent_req_done(req);
3628 : }
3629 :
3630 5 : static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3631 : {
3632 5 : return tevent_req_simple_recv_ntstatus(req);
3633 : }
3634 :
3635 5 : static bool run_locktest13(int dummy)
3636 : {
3637 5 : struct tevent_context *ev = NULL;
3638 5 : struct tevent_req *req = NULL;
3639 5 : struct cli_state *cli = NULL;
3640 5 : const char fname[] = "\\lockt13.lck";
3641 0 : uint16_t fnum1, fnum2;
3642 5 : bool ret = false;
3643 0 : bool ok;
3644 5 : uint8_t data = 1;
3645 0 : NTSTATUS status;
3646 :
3647 5 : printf("starting locktest13\n");
3648 :
3649 5 : ev = samba_tevent_context_init(NULL);
3650 5 : if (ev == NULL) {
3651 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
3652 0 : goto done;
3653 : }
3654 :
3655 5 : ok = torture_open_connection(&cli, 0);
3656 5 : if (!ok) {
3657 0 : goto done;
3658 : }
3659 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3660 :
3661 5 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3662 5 : if (!NT_STATUS_IS_OK(status)) {
3663 0 : d_fprintf(stderr,
3664 : "cli_openx failed: %s\n",
3665 : nt_errstr(status));
3666 0 : goto done;
3667 : }
3668 :
3669 5 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3670 5 : if (!NT_STATUS_IS_OK(status)) {
3671 0 : d_fprintf(stderr,
3672 : "cli_openx failed: %s\n",
3673 : nt_errstr(status));
3674 0 : goto done;
3675 : }
3676 :
3677 5 : status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3678 5 : if (!NT_STATUS_IS_OK(status)) {
3679 0 : d_fprintf(stderr,
3680 : "cli_writeall failed: %s\n",
3681 : nt_errstr(status));
3682 0 : goto done;
3683 : }
3684 :
3685 5 : status = cli_locktype(
3686 : cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3687 5 : if (!NT_STATUS_IS_OK(status)) {
3688 0 : d_fprintf(stderr,
3689 : "cli_locktype failed: %s\n",
3690 : nt_errstr(status));
3691 0 : goto done;
3692 : }
3693 :
3694 5 : req = lock_ntcancel_send(ev, ev, cli, fnum2);
3695 5 : if (req == NULL) {
3696 0 : d_fprintf(stderr, "lock_ntcancel_send failed\n");
3697 0 : goto done;
3698 : }
3699 :
3700 5 : ok = tevent_req_poll_ntstatus(req, ev, &status);
3701 5 : if (!ok) {
3702 0 : d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3703 0 : goto done;
3704 : }
3705 :
3706 5 : if (!NT_STATUS_IS_OK(status)) {
3707 0 : d_fprintf(stderr,
3708 : "tevent_req_poll_ntstatus returned %s\n",
3709 : nt_errstr(status));
3710 0 : goto done;
3711 : }
3712 :
3713 5 : status = lock_ntcancel_recv(req);
3714 5 : if (!NT_STATUS_IS_OK(status)) {
3715 0 : d_fprintf(stderr,
3716 : "lock_ntcancel returned %s\n",
3717 : nt_errstr(status));
3718 0 : goto done;
3719 : }
3720 :
3721 5 : ret = true;
3722 5 : done:
3723 5 : if (cli != NULL) {
3724 5 : torture_close_connection(cli);
3725 : }
3726 5 : return ret;
3727 : }
3728 :
3729 : /*
3730 : test whether fnums and tids open on one VC are available on another (a major
3731 : security hole)
3732 : */
3733 5 : static bool run_fdpasstest(int dummy)
3734 : {
3735 0 : struct cli_state *cli1, *cli2;
3736 5 : const char *fname = "\\fdpass.tst";
3737 0 : uint16_t fnum1;
3738 0 : char buf[1024];
3739 0 : NTSTATUS status;
3740 :
3741 5 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3742 0 : return False;
3743 : }
3744 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
3745 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
3746 :
3747 5 : printf("starting fdpasstest\n");
3748 :
3749 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3750 :
3751 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3752 : &fnum1);
3753 5 : if (!NT_STATUS_IS_OK(status)) {
3754 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3755 0 : return False;
3756 : }
3757 :
3758 5 : status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3759 : 13, NULL);
3760 5 : if (!NT_STATUS_IS_OK(status)) {
3761 0 : printf("write failed (%s)\n", nt_errstr(status));
3762 0 : return False;
3763 : }
3764 :
3765 5 : cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3766 5 : cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3767 5 : cli_setpid(cli2, cli_getpid(cli1));
3768 :
3769 5 : if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3770 0 : printf("read succeeded! nasty security hole [%s]\n", buf);
3771 0 : return false;
3772 : }
3773 :
3774 5 : cli_close(cli1, fnum1);
3775 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3776 :
3777 5 : torture_close_connection(cli1);
3778 5 : torture_close_connection(cli2);
3779 :
3780 5 : printf("finished fdpasstest\n");
3781 5 : return True;
3782 : }
3783 :
3784 5 : static bool run_fdsesstest(int dummy)
3785 : {
3786 0 : struct cli_state *cli;
3787 0 : uint16_t new_vuid;
3788 0 : uint16_t saved_vuid;
3789 0 : uint32_t new_cnum;
3790 0 : uint32_t saved_cnum;
3791 5 : const char *fname = "\\fdsess.tst";
3792 5 : const char *fname1 = "\\fdsess1.tst";
3793 0 : uint16_t fnum1;
3794 0 : uint16_t fnum2;
3795 0 : char buf[1024];
3796 5 : bool ret = True;
3797 0 : NTSTATUS status;
3798 :
3799 5 : if (!torture_open_connection(&cli, 0))
3800 0 : return False;
3801 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3802 :
3803 5 : if (!torture_cli_session_setup2(cli, &new_vuid))
3804 0 : return False;
3805 :
3806 5 : saved_cnum = cli_state_get_tid(cli);
3807 5 : if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3808 0 : return False;
3809 5 : new_cnum = cli_state_get_tid(cli);
3810 5 : cli_state_set_tid(cli, saved_cnum);
3811 :
3812 5 : printf("starting fdsesstest\n");
3813 :
3814 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3815 5 : cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3816 :
3817 5 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3818 5 : if (!NT_STATUS_IS_OK(status)) {
3819 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3820 0 : return False;
3821 : }
3822 :
3823 5 : status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3824 : NULL);
3825 5 : if (!NT_STATUS_IS_OK(status)) {
3826 0 : printf("write failed (%s)\n", nt_errstr(status));
3827 0 : return False;
3828 : }
3829 :
3830 5 : saved_vuid = cli_state_get_uid(cli);
3831 5 : cli_state_set_uid(cli, new_vuid);
3832 :
3833 5 : if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3834 0 : printf("read succeeded with different vuid! "
3835 : "nasty security hole [%s]\n", buf);
3836 0 : ret = false;
3837 : }
3838 : /* Try to open a file with different vuid, samba cnum. */
3839 5 : if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3840 5 : printf("create with different vuid, same cnum succeeded.\n");
3841 5 : cli_close(cli, fnum2);
3842 5 : cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3843 : } else {
3844 0 : printf("create with different vuid, same cnum failed.\n");
3845 0 : printf("This will cause problems with service clients.\n");
3846 0 : ret = False;
3847 : }
3848 :
3849 5 : cli_state_set_uid(cli, saved_vuid);
3850 :
3851 : /* Try with same vuid, different cnum. */
3852 5 : cli_state_set_tid(cli, new_cnum);
3853 :
3854 5 : if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3855 0 : printf("read succeeded with different cnum![%s]\n", buf);
3856 0 : ret = false;
3857 : }
3858 :
3859 5 : cli_state_set_tid(cli, saved_cnum);
3860 5 : cli_close(cli, fnum1);
3861 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3862 :
3863 5 : torture_close_connection(cli);
3864 :
3865 5 : printf("finished fdsesstest\n");
3866 5 : return ret;
3867 : }
3868 :
3869 : /*
3870 : This test checks that
3871 :
3872 : 1) the server does not allow an unlink on a file that is open
3873 : */
3874 5 : static bool run_unlinktest(int dummy)
3875 : {
3876 0 : struct cli_state *cli;
3877 5 : const char *fname = "\\unlink.tst";
3878 0 : uint16_t fnum;
3879 5 : bool correct = True;
3880 0 : NTSTATUS status;
3881 :
3882 5 : if (!torture_open_connection(&cli, 0)) {
3883 0 : return False;
3884 : }
3885 :
3886 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3887 :
3888 5 : printf("starting unlink test\n");
3889 :
3890 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3891 :
3892 5 : cli_setpid(cli, 1);
3893 :
3894 5 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3895 5 : if (!NT_STATUS_IS_OK(status)) {
3896 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3897 0 : return False;
3898 : }
3899 :
3900 5 : status = cli_unlink(cli, fname,
3901 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3902 5 : if (NT_STATUS_IS_OK(status)) {
3903 0 : printf("error: server allowed unlink on an open file\n");
3904 0 : correct = False;
3905 : } else {
3906 5 : correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3907 5 : NT_STATUS_SHARING_VIOLATION);
3908 : }
3909 :
3910 5 : cli_close(cli, fnum);
3911 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3912 :
3913 5 : if (!torture_close_connection(cli)) {
3914 0 : correct = False;
3915 : }
3916 :
3917 5 : printf("unlink test finished\n");
3918 :
3919 5 : return correct;
3920 : }
3921 :
3922 :
3923 : /*
3924 : test how many open files this server supports on the one socket
3925 : */
3926 0 : static bool run_maxfidtest(int dummy)
3927 : {
3928 0 : struct cli_state *cli;
3929 0 : fstring fname;
3930 0 : uint16_t fnums[0x11000];
3931 0 : int i;
3932 0 : int retries=4;
3933 0 : bool correct = True;
3934 0 : NTSTATUS status;
3935 :
3936 0 : cli = current_cli;
3937 :
3938 0 : if (retries <= 0) {
3939 0 : printf("failed to connect\n");
3940 0 : return False;
3941 : }
3942 :
3943 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3944 :
3945 0 : for (i=0; i<0x11000; i++) {
3946 0 : slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3947 0 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3948 : &fnums[i]);
3949 0 : if (!NT_STATUS_IS_OK(status)) {
3950 0 : printf("open of %s failed (%s)\n",
3951 : fname, nt_errstr(status));
3952 0 : printf("maximum fnum is %d\n", i);
3953 0 : break;
3954 : }
3955 0 : printf("%6d\r", i);
3956 : }
3957 0 : printf("%6d\n", i);
3958 0 : i--;
3959 :
3960 0 : printf("cleaning up\n");
3961 0 : for (;i>=0;i--) {
3962 0 : slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3963 0 : cli_close(cli, fnums[i]);
3964 :
3965 0 : status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3966 0 : if (!NT_STATUS_IS_OK(status)) {
3967 0 : printf("unlink of %s failed (%s)\n",
3968 : fname, nt_errstr(status));
3969 0 : correct = False;
3970 : }
3971 0 : printf("%6d\r", i);
3972 : }
3973 0 : printf("%6d\n", 0);
3974 :
3975 0 : printf("maxfid test finished\n");
3976 0 : if (!torture_close_connection(cli)) {
3977 0 : correct = False;
3978 : }
3979 0 : return correct;
3980 : }
3981 :
3982 : /* generate a random buffer */
3983 0 : static void rand_buf(char *buf, int len)
3984 : {
3985 0 : while (len--) {
3986 0 : *buf = (char)sys_random();
3987 0 : buf++;
3988 : }
3989 0 : }
3990 :
3991 : /* send smb negprot commands, not reading the response */
3992 0 : static bool run_negprot_nowait(int dummy)
3993 : {
3994 0 : struct tevent_context *ev;
3995 0 : int i;
3996 0 : struct cli_state *cli;
3997 0 : bool correct = True;
3998 :
3999 0 : printf("starting negprot nowait test\n");
4000 :
4001 0 : ev = samba_tevent_context_init(talloc_tos());
4002 0 : if (ev == NULL) {
4003 0 : return false;
4004 : }
4005 :
4006 0 : if (!(cli = open_nbt_connection())) {
4007 0 : TALLOC_FREE(ev);
4008 0 : return False;
4009 : }
4010 :
4011 0 : for (i=0;i<50000;i++) {
4012 0 : struct tevent_req *req;
4013 :
4014 0 : req = smbXcli_negprot_send(
4015 : ev,
4016 : ev,
4017 : cli->conn,
4018 0 : cli->timeout,
4019 : PROTOCOL_CORE,
4020 : PROTOCOL_NT1,
4021 : 0,
4022 : NULL);
4023 0 : if (req == NULL) {
4024 0 : TALLOC_FREE(ev);
4025 0 : return false;
4026 : }
4027 0 : if (!tevent_req_poll(req, ev)) {
4028 0 : d_fprintf(stderr, "tevent_req_poll failed: %s\n",
4029 0 : strerror(errno));
4030 0 : TALLOC_FREE(ev);
4031 0 : return false;
4032 : }
4033 0 : TALLOC_FREE(req);
4034 : }
4035 :
4036 0 : if (torture_close_connection(cli)) {
4037 0 : correct = False;
4038 : }
4039 :
4040 0 : printf("finished negprot nowait test\n");
4041 :
4042 0 : return correct;
4043 : }
4044 :
4045 : /* send smb negprot commands, not reading the response */
4046 4 : static bool run_bad_nbt_session(int dummy)
4047 : {
4048 0 : struct nmb_name called, calling;
4049 0 : struct sockaddr_storage ss;
4050 0 : NTSTATUS status;
4051 0 : int fd;
4052 0 : bool ret;
4053 :
4054 4 : printf("starting bad nbt session test\n");
4055 :
4056 4 : make_nmb_name(&calling, myname, 0x0);
4057 4 : make_nmb_name(&called , host, 0x20);
4058 :
4059 4 : if (!resolve_name(host, &ss, 0x20, true)) {
4060 0 : d_fprintf(stderr, "Could not resolve name %s\n", host);
4061 0 : return false;
4062 : }
4063 :
4064 4 : status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4065 4 : if (!NT_STATUS_IS_OK(status)) {
4066 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
4067 : nt_errstr(status));
4068 0 : return false;
4069 : }
4070 :
4071 4 : ret = cli_bad_session_request(fd, &calling, &called);
4072 4 : close(fd);
4073 4 : if (!ret) {
4074 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
4075 : nt_errstr(status));
4076 0 : return false;
4077 : }
4078 :
4079 4 : printf("finished bad nbt session test\n");
4080 4 : return true;
4081 : }
4082 :
4083 : /* send random IPC commands */
4084 0 : static bool run_randomipc(int dummy)
4085 : {
4086 0 : char *rparam = NULL;
4087 0 : char *rdata = NULL;
4088 0 : unsigned int rdrcnt,rprcnt;
4089 0 : char param[1024];
4090 0 : int api, param_len, i;
4091 0 : struct cli_state *cli;
4092 0 : bool correct = True;
4093 0 : int count = 50000;
4094 :
4095 0 : printf("starting random ipc test\n");
4096 :
4097 0 : if (!torture_open_connection(&cli, 0)) {
4098 0 : return False;
4099 : }
4100 :
4101 0 : for (i=0;i<count;i++) {
4102 0 : api = sys_random() % 500;
4103 0 : param_len = (sys_random() % 64);
4104 :
4105 0 : rand_buf(param, param_len);
4106 :
4107 0 : SSVAL(param,0,api);
4108 :
4109 0 : cli_api(cli,
4110 : param, param_len, 8,
4111 : NULL, 0, CLI_BUFFER_SIZE,
4112 : &rparam, &rprcnt,
4113 : &rdata, &rdrcnt);
4114 0 : if (i % 100 == 0) {
4115 0 : printf("%d/%d\r", i,count);
4116 : }
4117 : }
4118 0 : printf("%d/%d\n", i, count);
4119 :
4120 0 : if (!torture_close_connection(cli)) {
4121 0 : correct = False;
4122 : }
4123 :
4124 0 : SAFE_FREE(rparam);
4125 0 : SAFE_FREE(rdata);
4126 :
4127 0 : printf("finished random ipc test\n");
4128 :
4129 0 : return correct;
4130 : }
4131 :
4132 :
4133 :
4134 8 : static void browse_callback(const char *sname, uint32_t stype,
4135 : const char *comment, void *state)
4136 : {
4137 8 : printf("\t%20.20s %08x %s\n", sname, stype, comment);
4138 8 : }
4139 :
4140 :
4141 :
4142 : /*
4143 : This test checks the browse list code
4144 :
4145 : */
4146 5 : static bool run_browsetest(int dummy)
4147 : {
4148 0 : static struct cli_state *cli;
4149 5 : bool correct = True;
4150 :
4151 5 : printf("starting browse test\n");
4152 :
4153 5 : if (!torture_open_connection(&cli, 0)) {
4154 0 : return False;
4155 : }
4156 :
4157 5 : printf("domain list:\n");
4158 5 : cli_NetServerEnum(cli, cli->server_domain,
4159 : SV_TYPE_DOMAIN_ENUM,
4160 : browse_callback, NULL);
4161 :
4162 5 : printf("machine list:\n");
4163 5 : cli_NetServerEnum(cli, cli->server_domain,
4164 : SV_TYPE_ALL,
4165 : browse_callback, NULL);
4166 :
4167 5 : if (!torture_close_connection(cli)) {
4168 0 : correct = False;
4169 : }
4170 :
4171 5 : printf("browse test finished\n");
4172 :
4173 5 : return correct;
4174 :
4175 : }
4176 :
4177 20 : static bool check_attributes(struct cli_state *cli,
4178 : const char *fname,
4179 : uint32_t expected_attrs)
4180 : {
4181 20 : uint32_t attrs = 0;
4182 20 : NTSTATUS status = cli_getatr(cli,
4183 : fname,
4184 : &attrs,
4185 : NULL,
4186 : NULL);
4187 20 : if (!NT_STATUS_IS_OK(status)) {
4188 0 : printf("cli_getatr failed with %s\n",
4189 : nt_errstr(status));
4190 0 : return false;
4191 : }
4192 20 : if (attrs != expected_attrs) {
4193 0 : printf("Attributes incorrect 0x%x, should be 0x%x\n",
4194 : (unsigned int)attrs,
4195 : (unsigned int)expected_attrs);
4196 0 : return false;
4197 : }
4198 20 : return true;
4199 : }
4200 :
4201 : /*
4202 : This checks how the getatr calls works
4203 : */
4204 5 : static bool run_attrtest(int dummy)
4205 : {
4206 0 : struct cli_state *cli;
4207 0 : uint16_t fnum;
4208 0 : time_t t, t2;
4209 5 : const char *fname = "\\attrib123456789.tst";
4210 5 : bool correct = True;
4211 0 : NTSTATUS status;
4212 :
4213 5 : printf("starting attrib test\n");
4214 :
4215 5 : if (!torture_open_connection(&cli, 0)) {
4216 0 : return False;
4217 : }
4218 :
4219 : /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4220 5 : status = cli_unlink(cli, fname, 0x20000);
4221 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4222 0 : correct = false;
4223 0 : goto out;
4224 : }
4225 :
4226 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4227 5 : cli_openx(cli, fname,
4228 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4229 5 : cli_close(cli, fnum);
4230 :
4231 5 : status = cli_getatr(cli, fname, NULL, NULL, &t);
4232 5 : if (!NT_STATUS_IS_OK(status)) {
4233 0 : printf("getatr failed (%s)\n", nt_errstr(status));
4234 0 : correct = False;
4235 : }
4236 :
4237 5 : if (labs(t - time(NULL)) > 60*60*24*10) {
4238 0 : printf("ERROR: SMBgetatr bug. time is %s",
4239 : ctime(&t));
4240 0 : t = time(NULL);
4241 0 : correct = True;
4242 : }
4243 :
4244 5 : t2 = t-60*60*24; /* 1 day ago */
4245 :
4246 : /* Ensure we can't set with out-of-range (unknown) attribute. */
4247 5 : status = cli_setatr(cli, fname, 0x20000, t2);
4248 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4249 0 : correct = false;
4250 0 : goto out;
4251 : }
4252 :
4253 5 : status = cli_setatr(cli, fname, 0, t2);
4254 5 : if (!NT_STATUS_IS_OK(status)) {
4255 0 : printf("setatr failed (%s)\n", nt_errstr(status));
4256 0 : correct = True;
4257 : }
4258 :
4259 5 : status = cli_getatr(cli, fname, NULL, NULL, &t);
4260 5 : if (!NT_STATUS_IS_OK(status)) {
4261 0 : printf("getatr failed (%s)\n", nt_errstr(status));
4262 0 : correct = True;
4263 : }
4264 :
4265 5 : if (t != t2) {
4266 0 : printf("ERROR: getatr/setatr bug. times are\n%s",
4267 : ctime(&t));
4268 0 : printf("%s", ctime(&t2));
4269 0 : correct = True;
4270 : }
4271 :
4272 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4273 :
4274 : /* Check cli_setpathinfo_ext() */
4275 : /* Re-create the file. */
4276 5 : status = cli_openx(cli, fname,
4277 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4278 5 : if (!NT_STATUS_IS_OK(status)) {
4279 0 : printf("Failed to recreate %s (%s)\n",
4280 : fname, nt_errstr(status));
4281 0 : correct = false;
4282 : }
4283 5 : cli_close(cli, fnum);
4284 :
4285 5 : status = cli_setpathinfo_ext(
4286 : cli,
4287 : fname,
4288 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4289 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4290 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4291 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4292 : FILE_ATTRIBUTE_SYSTEM |
4293 : FILE_ATTRIBUTE_HIDDEN |
4294 : FILE_ATTRIBUTE_READONLY);
4295 5 : if (!NT_STATUS_IS_OK(status)) {
4296 0 : printf("cli_setpathinfo_ext failed with %s\n",
4297 : nt_errstr(status));
4298 0 : correct = false;
4299 : }
4300 :
4301 : /* Check attributes are correct. */
4302 5 : correct = check_attributes(cli,
4303 : fname,
4304 : FILE_ATTRIBUTE_SYSTEM |
4305 : FILE_ATTRIBUTE_HIDDEN |
4306 : FILE_ATTRIBUTE_READONLY);
4307 5 : if (correct == false) {
4308 0 : goto out;
4309 : }
4310 :
4311 : /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4312 5 : status = cli_setpathinfo_ext(
4313 : cli,
4314 : fname,
4315 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4316 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4317 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4318 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4319 : FILE_ATTRIBUTE_NORMAL);
4320 5 : if (!NT_STATUS_IS_OK(status)) {
4321 0 : printf("cli_setpathinfo_ext failed with %s\n",
4322 : nt_errstr(status));
4323 0 : correct = false;
4324 : }
4325 :
4326 : /* Check attributes are correct. */
4327 5 : correct = check_attributes(cli,
4328 : fname,
4329 : FILE_ATTRIBUTE_SYSTEM |
4330 : FILE_ATTRIBUTE_HIDDEN |
4331 : FILE_ATTRIBUTE_READONLY);
4332 5 : if (correct == false) {
4333 0 : goto out;
4334 : }
4335 :
4336 : /* Setting to (uint16_t)-1 should also be ignored. */
4337 5 : status = cli_setpathinfo_ext(
4338 : cli,
4339 : fname,
4340 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4341 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4342 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4343 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4344 : (uint32_t)-1);
4345 5 : if (!NT_STATUS_IS_OK(status)) {
4346 0 : printf("cli_setpathinfo_ext failed with %s\n",
4347 : nt_errstr(status));
4348 0 : correct = false;
4349 : }
4350 :
4351 : /* Check attributes are correct. */
4352 5 : correct = check_attributes(cli,
4353 : fname,
4354 : FILE_ATTRIBUTE_SYSTEM |
4355 : FILE_ATTRIBUTE_HIDDEN |
4356 : FILE_ATTRIBUTE_READONLY);
4357 5 : if (correct == false) {
4358 0 : goto out;
4359 : }
4360 :
4361 : /* Setting to 0 should clear them all. */
4362 5 : status = cli_setpathinfo_ext(
4363 : cli,
4364 : fname,
4365 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4366 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4367 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4368 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4369 : 0);
4370 5 : if (!NT_STATUS_IS_OK(status)) {
4371 0 : printf("cli_setpathinfo_ext failed with %s\n",
4372 : nt_errstr(status));
4373 0 : correct = false;
4374 : }
4375 :
4376 : /* Check attributes are correct. */
4377 5 : correct = check_attributes(cli,
4378 : fname,
4379 : FILE_ATTRIBUTE_NORMAL);
4380 5 : if (correct == false) {
4381 0 : goto out;
4382 : }
4383 :
4384 5 : out:
4385 :
4386 5 : cli_unlink(cli,
4387 : fname,
4388 : FILE_ATTRIBUTE_SYSTEM |
4389 : FILE_ATTRIBUTE_HIDDEN|
4390 : FILE_ATTRIBUTE_READONLY);
4391 :
4392 5 : if (!torture_close_connection(cli)) {
4393 0 : correct = False;
4394 : }
4395 :
4396 5 : printf("attrib test finished\n");
4397 :
4398 5 : return correct;
4399 : }
4400 :
4401 5 : static NTSTATUS cli_qfilename(
4402 : struct cli_state *cli,
4403 : uint16_t fnum,
4404 : TALLOC_CTX *mem_ctx,
4405 : char **_name)
4406 : {
4407 0 : uint16_t recv_flags2;
4408 0 : uint8_t *rdata;
4409 0 : uint32_t num_rdata;
4410 0 : NTSTATUS status;
4411 5 : char *name = NULL;
4412 0 : uint32_t namelen;
4413 :
4414 5 : status = cli_qfileinfo(talloc_tos(),
4415 : cli,
4416 : fnum,
4417 : FSCC_FILE_NAME_INFORMATION,
4418 : 4,
4419 : CLI_BUFFER_SIZE,
4420 : &recv_flags2,
4421 : &rdata,
4422 : &num_rdata);
4423 5 : if (!NT_STATUS_IS_OK(status)) {
4424 0 : return status;
4425 : }
4426 :
4427 5 : namelen = IVAL(rdata, 0);
4428 5 : if (namelen > (num_rdata - 4)) {
4429 0 : TALLOC_FREE(rdata);
4430 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
4431 : }
4432 :
4433 5 : pull_string_talloc(mem_ctx,
4434 : (const char *)rdata,
4435 : recv_flags2,
4436 : &name,
4437 5 : rdata + 4,
4438 : namelen,
4439 : STR_UNICODE);
4440 5 : if (name == NULL) {
4441 0 : status = map_nt_error_from_unix(errno);
4442 0 : TALLOC_FREE(rdata);
4443 0 : return status;
4444 : }
4445 :
4446 5 : *_name = name;
4447 5 : TALLOC_FREE(rdata);
4448 5 : return NT_STATUS_OK;
4449 : }
4450 :
4451 : /*
4452 : This checks a couple of trans2 calls
4453 : */
4454 5 : static bool run_trans2test(int dummy)
4455 : {
4456 0 : struct cli_state *cli;
4457 0 : uint16_t fnum;
4458 0 : off_t size;
4459 0 : time_t c_time, a_time, m_time;
4460 0 : struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4461 5 : const char *fname = "\\trans2.tst";
4462 5 : const char *dname = "\\trans2";
4463 5 : const char *fname2 = "\\trans2\\trans2.tst";
4464 5 : char *pname = NULL;
4465 5 : bool correct = True;
4466 0 : NTSTATUS status;
4467 0 : uint32_t fs_attr;
4468 0 : uint64_t ino;
4469 :
4470 5 : printf("starting trans2 test\n");
4471 :
4472 5 : if (!torture_open_connection(&cli, 0)) {
4473 0 : return False;
4474 : }
4475 :
4476 5 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4477 : /* Ensure ino is zero, SMB2 gets a real one. */
4478 0 : ino = 0;
4479 : } else {
4480 : /* Ensure ino is -1, SMB1 never gets a real one. */
4481 5 : ino = (uint64_t)-1;
4482 : }
4483 :
4484 5 : status = cli_get_fs_attr_info(cli, &fs_attr);
4485 5 : if (!NT_STATUS_IS_OK(status)) {
4486 0 : printf("ERROR: cli_get_fs_attr_info returned %s\n",
4487 : nt_errstr(status));
4488 0 : correct = false;
4489 : }
4490 :
4491 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4492 5 : cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4493 5 : status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4494 : &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4495 5 : if (!NT_STATUS_IS_OK(status)) {
4496 0 : printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4497 0 : correct = False;
4498 : }
4499 :
4500 5 : status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4501 5 : if (!NT_STATUS_IS_OK(status)) {
4502 0 : printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4503 0 : correct = False;
4504 : }
4505 5 : else if (strcmp(pname, fname)) {
4506 0 : printf("qfilename gave different name? [%s] [%s]\n",
4507 : fname, pname);
4508 0 : correct = False;
4509 : }
4510 :
4511 5 : cli_close(cli, fnum);
4512 :
4513 5 : sleep(2);
4514 :
4515 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4516 5 : status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4517 : &fnum);
4518 5 : if (!NT_STATUS_IS_OK(status)) {
4519 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4520 0 : return False;
4521 : }
4522 5 : cli_close(cli, fnum);
4523 :
4524 5 : status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4525 : NULL);
4526 5 : if (!NT_STATUS_IS_OK(status)) {
4527 0 : printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4528 0 : correct = False;
4529 : } else {
4530 5 : time_t t = time(NULL);
4531 :
4532 5 : if (c_time != m_time) {
4533 0 : printf("create time=%s", ctime(&c_time));
4534 0 : printf("modify time=%s", ctime(&m_time));
4535 0 : printf("This system appears to have sticky create times\n");
4536 : }
4537 5 : if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4538 0 : printf("access time=%s", ctime(&a_time));
4539 0 : printf("This system appears to set a midnight access time\n");
4540 0 : correct = False;
4541 : }
4542 :
4543 5 : if (labs(m_time - t) > 60*60*24*7) {
4544 0 : printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4545 0 : correct = False;
4546 : }
4547 : }
4548 :
4549 :
4550 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4551 5 : cli_openx(cli, fname,
4552 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4553 5 : cli_close(cli, fnum);
4554 5 : status = cli_qpathinfo2(cli,
4555 : fname,
4556 : &c_time_ts,
4557 : &a_time_ts,
4558 : &w_time_ts,
4559 : &m_time_ts,
4560 : &size,
4561 : NULL,
4562 : &ino,
4563 : NULL);
4564 5 : if (!NT_STATUS_IS_OK(status)) {
4565 0 : printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4566 0 : correct = False;
4567 : } else {
4568 5 : if (w_time_ts.tv_sec < 60*60*24*2) {
4569 0 : printf("write time=%s", ctime(&w_time_ts.tv_sec));
4570 0 : printf("This system appears to set a initial 0 write time\n");
4571 0 : correct = False;
4572 : }
4573 5 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4574 : /* SMB2 should always return an inode. */
4575 0 : if (ino == 0) {
4576 0 : printf("SMB2 bad inode (0)\n");
4577 0 : correct = false;
4578 : }
4579 : } else {
4580 : /* SMB1 must always return zero here. */
4581 5 : if (ino != 0) {
4582 0 : printf("SMB1 bad inode (!0)\n");
4583 0 : correct = false;
4584 : }
4585 : }
4586 : }
4587 :
4588 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4589 :
4590 :
4591 : /* check if the server updates the directory modification time
4592 : when creating a new file */
4593 5 : status = cli_mkdir(cli, dname);
4594 5 : if (!NT_STATUS_IS_OK(status)) {
4595 0 : printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4596 0 : correct = False;
4597 : }
4598 5 : sleep(3);
4599 5 : status = cli_qpathinfo2(cli,
4600 : "\\trans2\\",
4601 : &c_time_ts,
4602 : &a_time_ts,
4603 : &w_time_ts,
4604 : &m_time_ts,
4605 : &size,
4606 : NULL,
4607 : NULL,
4608 : NULL);
4609 5 : if (!NT_STATUS_IS_OK(status)) {
4610 0 : printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4611 0 : correct = False;
4612 : }
4613 :
4614 5 : cli_openx(cli, fname2,
4615 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4616 5 : cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4617 5 : cli_close(cli, fnum);
4618 5 : status = cli_qpathinfo2(cli,
4619 : "\\trans2\\",
4620 : &c_time_ts,
4621 : &a_time_ts,
4622 : &w_time_ts,
4623 : &m_time2_ts,
4624 : &size,
4625 : NULL,
4626 : NULL,
4627 : NULL);
4628 5 : if (!NT_STATUS_IS_OK(status)) {
4629 0 : printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4630 0 : correct = False;
4631 : } else {
4632 5 : if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4633 : == 0) {
4634 0 : printf("This system does not update directory modification times\n");
4635 0 : correct = False;
4636 : }
4637 : }
4638 5 : cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4639 5 : cli_rmdir(cli, dname);
4640 :
4641 5 : if (!torture_close_connection(cli)) {
4642 0 : correct = False;
4643 : }
4644 :
4645 5 : printf("trans2 test finished\n");
4646 :
4647 5 : return correct;
4648 : }
4649 :
4650 : /*
4651 : This checks new W2K calls.
4652 : */
4653 :
4654 180 : static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4655 : {
4656 180 : uint8_t *buf = NULL;
4657 0 : uint32_t len;
4658 0 : NTSTATUS status;
4659 :
4660 180 : status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4661 : CLI_BUFFER_SIZE, NULL, &buf, &len);
4662 180 : if (!NT_STATUS_IS_OK(status)) {
4663 180 : printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4664 : nt_errstr(status));
4665 : } else {
4666 0 : printf("qfileinfo: level %d, len = %u\n", level, len);
4667 0 : dump_data(0, (uint8_t *)buf, len);
4668 0 : printf("\n");
4669 : }
4670 180 : TALLOC_FREE(buf);
4671 180 : return status;
4672 : }
4673 :
4674 5 : static bool run_w2ktest(int dummy)
4675 : {
4676 0 : struct cli_state *cli;
4677 0 : uint16_t fnum;
4678 5 : const char *fname = "\\w2ktest\\w2k.tst";
4679 0 : int level;
4680 5 : bool correct = True;
4681 :
4682 5 : printf("starting w2k test\n");
4683 :
4684 5 : if (!torture_open_connection(&cli, 0)) {
4685 0 : return False;
4686 : }
4687 :
4688 5 : cli_openx(cli, fname,
4689 : O_RDWR | O_CREAT , DENY_NONE, &fnum);
4690 :
4691 185 : for (level = 1004; level < 1040; level++) {
4692 180 : new_trans(cli, fnum, level);
4693 : }
4694 :
4695 5 : cli_close(cli, fnum);
4696 :
4697 5 : if (!torture_close_connection(cli)) {
4698 0 : correct = False;
4699 : }
4700 :
4701 5 : printf("w2k test finished\n");
4702 :
4703 5 : return correct;
4704 : }
4705 :
4706 :
4707 : /*
4708 : this is a harness for some oplock tests
4709 : */
4710 5 : static bool run_oplock1(int dummy)
4711 : {
4712 0 : struct cli_state *cli1;
4713 5 : const char *fname = "\\lockt1.lck";
4714 0 : uint16_t fnum1;
4715 5 : bool correct = True;
4716 0 : NTSTATUS status;
4717 :
4718 5 : printf("starting oplock test 1\n");
4719 :
4720 5 : if (!torture_open_connection(&cli1, 0)) {
4721 0 : return False;
4722 : }
4723 :
4724 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4725 :
4726 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
4727 :
4728 5 : cli1->use_oplocks = True;
4729 :
4730 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4731 : &fnum1);
4732 5 : if (!NT_STATUS_IS_OK(status)) {
4733 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4734 0 : return False;
4735 : }
4736 :
4737 5 : cli1->use_oplocks = False;
4738 :
4739 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4740 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4741 :
4742 5 : status = cli_close(cli1, fnum1);
4743 5 : if (!NT_STATUS_IS_OK(status)) {
4744 0 : printf("close2 failed (%s)\n", nt_errstr(status));
4745 0 : return False;
4746 : }
4747 :
4748 5 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4749 5 : if (!NT_STATUS_IS_OK(status)) {
4750 0 : printf("unlink failed (%s)\n", nt_errstr(status));
4751 0 : return False;
4752 : }
4753 :
4754 5 : if (!torture_close_connection(cli1)) {
4755 0 : correct = False;
4756 : }
4757 :
4758 5 : printf("finished oplock test 1\n");
4759 :
4760 5 : return correct;
4761 : }
4762 :
4763 4 : static bool run_oplock2(int dummy)
4764 : {
4765 0 : struct cli_state *cli1, *cli2;
4766 4 : const char *fname = "\\lockt2.lck";
4767 0 : uint16_t fnum1, fnum2;
4768 4 : int saved_use_oplocks = use_oplocks;
4769 0 : char buf[4];
4770 4 : bool correct = True;
4771 0 : volatile bool *shared_correct;
4772 0 : size_t nread;
4773 0 : NTSTATUS status;
4774 :
4775 4 : shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4776 4 : *shared_correct = True;
4777 :
4778 4 : use_level_II_oplocks = True;
4779 4 : use_oplocks = True;
4780 :
4781 4 : printf("starting oplock test 2\n");
4782 :
4783 4 : if (!torture_open_connection(&cli1, 0)) {
4784 0 : use_level_II_oplocks = False;
4785 0 : use_oplocks = saved_use_oplocks;
4786 0 : return False;
4787 : }
4788 :
4789 4 : if (!torture_open_connection(&cli2, 1)) {
4790 0 : use_level_II_oplocks = False;
4791 0 : use_oplocks = saved_use_oplocks;
4792 0 : return False;
4793 : }
4794 :
4795 4 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4796 :
4797 4 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
4798 4 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
4799 :
4800 4 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4801 : &fnum1);
4802 4 : if (!NT_STATUS_IS_OK(status)) {
4803 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4804 0 : return False;
4805 : }
4806 :
4807 : /* Don't need the globals any more. */
4808 4 : use_level_II_oplocks = False;
4809 4 : use_oplocks = saved_use_oplocks;
4810 :
4811 4 : if (fork() == 0) {
4812 : /* Child code */
4813 4 : status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4814 4 : if (!NT_STATUS_IS_OK(status)) {
4815 0 : printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4816 0 : *shared_correct = False;
4817 0 : exit(0);
4818 : }
4819 :
4820 4 : sleep(2);
4821 :
4822 4 : status = cli_close(cli2, fnum2);
4823 4 : if (!NT_STATUS_IS_OK(status)) {
4824 0 : printf("close2 failed (%s)\n", nt_errstr(status));
4825 0 : *shared_correct = False;
4826 : }
4827 :
4828 4 : exit(0);
4829 : }
4830 :
4831 4 : sleep(2);
4832 :
4833 : /* Ensure cli1 processes the break. Empty file should always return 0
4834 : * bytes. */
4835 4 : status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4836 4 : if (!NT_STATUS_IS_OK(status)) {
4837 0 : printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4838 0 : correct = false;
4839 4 : } else if (nread != 0) {
4840 0 : printf("read on empty fnum1 failed. recv %ld expected %d\n",
4841 : (unsigned long)nread, 0);
4842 0 : correct = false;
4843 : }
4844 :
4845 : /* Should now be at level II. */
4846 : /* Test if sending a write locks causes a break to none. */
4847 4 : status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4848 4 : if (!NT_STATUS_IS_OK(status)) {
4849 0 : printf("lock failed (%s)\n", nt_errstr(status));
4850 0 : correct = False;
4851 : }
4852 :
4853 4 : cli_unlock(cli1, fnum1, 0, 4);
4854 :
4855 4 : sleep(2);
4856 :
4857 4 : status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4858 4 : if (!NT_STATUS_IS_OK(status)) {
4859 0 : printf("lock failed (%s)\n", nt_errstr(status));
4860 0 : correct = False;
4861 : }
4862 :
4863 4 : cli_unlock(cli1, fnum1, 0, 4);
4864 :
4865 4 : sleep(2);
4866 :
4867 4 : cli_read(cli1, fnum1, buf, 0, 4, NULL);
4868 :
4869 4 : status = cli_close(cli1, fnum1);
4870 4 : if (!NT_STATUS_IS_OK(status)) {
4871 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4872 0 : correct = False;
4873 : }
4874 :
4875 4 : sleep(4);
4876 :
4877 4 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4878 4 : if (!NT_STATUS_IS_OK(status)) {
4879 0 : printf("unlink failed (%s)\n", nt_errstr(status));
4880 0 : correct = False;
4881 : }
4882 :
4883 4 : if (!torture_close_connection(cli1)) {
4884 0 : correct = False;
4885 : }
4886 :
4887 4 : if (!*shared_correct) {
4888 0 : correct = False;
4889 : }
4890 :
4891 4 : printf("finished oplock test 2\n");
4892 :
4893 4 : return correct;
4894 : }
4895 :
4896 : struct oplock4_state {
4897 : struct tevent_context *ev;
4898 : struct cli_state *cli;
4899 : bool *got_break;
4900 : uint16_t *fnum2;
4901 : };
4902 :
4903 : static void oplock4_got_break(struct tevent_req *req);
4904 : static void oplock4_got_open(struct tevent_req *req);
4905 :
4906 5 : static bool run_oplock4(int dummy)
4907 : {
4908 0 : struct tevent_context *ev;
4909 0 : struct cli_state *cli1, *cli2;
4910 0 : struct tevent_req *oplock_req, *open_req;
4911 5 : const char *fname = "\\lockt4.lck";
4912 5 : const char *fname_ln = "\\lockt4_ln.lck";
4913 0 : uint16_t fnum1, fnum2;
4914 5 : int saved_use_oplocks = use_oplocks;
4915 0 : NTSTATUS status;
4916 5 : bool correct = true;
4917 :
4918 0 : bool got_break;
4919 :
4920 0 : struct oplock4_state *state;
4921 :
4922 5 : printf("starting oplock test 4\n");
4923 :
4924 5 : if (!torture_open_connection(&cli1, 0)) {
4925 0 : use_level_II_oplocks = false;
4926 0 : use_oplocks = saved_use_oplocks;
4927 0 : return false;
4928 : }
4929 :
4930 5 : if (!torture_open_connection(&cli2, 1)) {
4931 0 : use_level_II_oplocks = false;
4932 0 : use_oplocks = saved_use_oplocks;
4933 0 : return false;
4934 : }
4935 :
4936 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4937 5 : cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4938 :
4939 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
4940 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
4941 :
4942 : /* Create the file. */
4943 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4944 : &fnum1);
4945 5 : if (!NT_STATUS_IS_OK(status)) {
4946 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4947 0 : return false;
4948 : }
4949 :
4950 5 : status = cli_close(cli1, fnum1);
4951 5 : if (!NT_STATUS_IS_OK(status)) {
4952 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4953 0 : return false;
4954 : }
4955 :
4956 : /* Now create a hardlink. */
4957 5 : status = cli_hardlink(cli1, fname, fname_ln);
4958 5 : if (!NT_STATUS_IS_OK(status)) {
4959 0 : printf("nt hardlink failed (%s)\n", nt_errstr(status));
4960 0 : return false;
4961 : }
4962 :
4963 : /* Prove that opening hardlinks cause deny modes to conflict. */
4964 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4965 5 : if (!NT_STATUS_IS_OK(status)) {
4966 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4967 0 : return false;
4968 : }
4969 :
4970 5 : status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4971 5 : if (NT_STATUS_IS_OK(status)) {
4972 0 : printf("open of %s succeeded - should fail with sharing violation.\n",
4973 : fname_ln);
4974 0 : return false;
4975 : }
4976 :
4977 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4978 0 : printf("open of %s should fail with sharing violation. Got %s\n",
4979 : fname_ln, nt_errstr(status));
4980 0 : return false;
4981 : }
4982 :
4983 5 : status = cli_close(cli1, fnum1);
4984 5 : if (!NT_STATUS_IS_OK(status)) {
4985 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4986 0 : return false;
4987 : }
4988 :
4989 5 : cli1->use_oplocks = true;
4990 5 : cli2->use_oplocks = true;
4991 :
4992 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4993 5 : if (!NT_STATUS_IS_OK(status)) {
4994 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4995 0 : return false;
4996 : }
4997 :
4998 5 : ev = samba_tevent_context_init(talloc_tos());
4999 5 : if (ev == NULL) {
5000 0 : printf("tevent_context_init failed\n");
5001 0 : return false;
5002 : }
5003 :
5004 5 : state = talloc(ev, struct oplock4_state);
5005 5 : if (state == NULL) {
5006 0 : printf("talloc failed\n");
5007 0 : return false;
5008 : }
5009 5 : state->ev = ev;
5010 5 : state->cli = cli1;
5011 5 : state->got_break = &got_break;
5012 5 : state->fnum2 = &fnum2;
5013 :
5014 5 : oplock_req = cli_smb_oplock_break_waiter_send(
5015 : talloc_tos(), ev, cli1);
5016 5 : if (oplock_req == NULL) {
5017 0 : printf("cli_smb_oplock_break_waiter_send failed\n");
5018 0 : return false;
5019 : }
5020 5 : tevent_req_set_callback(oplock_req, oplock4_got_break, state);
5021 :
5022 5 : open_req = cli_openx_send(
5023 : talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
5024 5 : if (open_req == NULL) {
5025 0 : printf("cli_openx_send failed\n");
5026 0 : return false;
5027 : }
5028 5 : tevent_req_set_callback(open_req, oplock4_got_open, state);
5029 :
5030 5 : got_break = false;
5031 5 : fnum2 = 0xffff;
5032 :
5033 40 : while (!got_break || fnum2 == 0xffff) {
5034 0 : int ret;
5035 35 : ret = tevent_loop_once(ev);
5036 35 : if (ret == -1) {
5037 0 : printf("tevent_loop_once failed: %s\n",
5038 0 : strerror(errno));
5039 0 : return false;
5040 : }
5041 : }
5042 :
5043 5 : status = cli_close(cli2, fnum2);
5044 5 : if (!NT_STATUS_IS_OK(status)) {
5045 0 : printf("close2 failed (%s)\n", nt_errstr(status));
5046 0 : correct = false;
5047 : }
5048 :
5049 5 : status = cli_close(cli1, fnum1);
5050 5 : if (!NT_STATUS_IS_OK(status)) {
5051 0 : printf("close1 failed (%s)\n", nt_errstr(status));
5052 0 : correct = false;
5053 : }
5054 :
5055 5 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5056 5 : if (!NT_STATUS_IS_OK(status)) {
5057 0 : printf("unlink failed (%s)\n", nt_errstr(status));
5058 0 : correct = false;
5059 : }
5060 :
5061 5 : status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5062 5 : if (!NT_STATUS_IS_OK(status)) {
5063 0 : printf("unlink failed (%s)\n", nt_errstr(status));
5064 0 : correct = false;
5065 : }
5066 :
5067 5 : if (!torture_close_connection(cli1)) {
5068 0 : correct = false;
5069 : }
5070 :
5071 5 : if (!got_break) {
5072 0 : correct = false;
5073 : }
5074 :
5075 5 : printf("finished oplock test 4\n");
5076 :
5077 5 : return correct;
5078 : }
5079 :
5080 5 : static void oplock4_got_break(struct tevent_req *req)
5081 : {
5082 5 : struct oplock4_state *state = tevent_req_callback_data(
5083 : req, struct oplock4_state);
5084 0 : uint16_t fnum;
5085 0 : uint8_t level;
5086 0 : NTSTATUS status;
5087 :
5088 5 : status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
5089 5 : TALLOC_FREE(req);
5090 5 : if (!NT_STATUS_IS_OK(status)) {
5091 0 : printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5092 : nt_errstr(status));
5093 0 : return;
5094 : }
5095 5 : *state->got_break = true;
5096 :
5097 5 : req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5098 : NO_OPLOCK);
5099 5 : if (req == NULL) {
5100 0 : printf("cli_oplock_ack_send failed\n");
5101 0 : return;
5102 : }
5103 : }
5104 :
5105 5 : static void oplock4_got_open(struct tevent_req *req)
5106 : {
5107 5 : struct oplock4_state *state = tevent_req_callback_data(
5108 : req, struct oplock4_state);
5109 0 : NTSTATUS status;
5110 :
5111 5 : status = cli_openx_recv(req, state->fnum2);
5112 5 : if (!NT_STATUS_IS_OK(status)) {
5113 0 : printf("cli_openx_recv returned %s\n", nt_errstr(status));
5114 0 : *state->fnum2 = 0xffff;
5115 : }
5116 5 : }
5117 :
5118 : #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5119 :
5120 : struct oplock5_state {
5121 : int pipe_down_fd;
5122 : };
5123 :
5124 : /*
5125 : * Async open the file that has a kernel oplock, do an echo to get
5126 : * that 100% across, close the file to signal to the child fd that the
5127 : * oplock can be dropped, wait for the open reply.
5128 : */
5129 :
5130 : static void oplock5_opened(struct tevent_req *subreq);
5131 : static void oplock5_pong(struct tevent_req *subreq);
5132 : static void oplock5_timedout(struct tevent_req *subreq);
5133 :
5134 1 : static struct tevent_req *oplock5_send(
5135 : TALLOC_CTX *mem_ctx,
5136 : struct tevent_context *ev,
5137 : struct cli_state *cli,
5138 : const char *fname,
5139 : int pipe_down_fd)
5140 : {
5141 1 : struct tevent_req *req = NULL, *subreq = NULL;
5142 1 : struct oplock5_state *state = NULL;
5143 0 : static uint8_t data = 0;
5144 :
5145 1 : req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5146 1 : if (req == NULL) {
5147 0 : return NULL;
5148 : }
5149 1 : state->pipe_down_fd = pipe_down_fd;
5150 :
5151 1 : subreq = cli_ntcreate_send(
5152 : state,
5153 : ev,
5154 : cli,
5155 : fname,
5156 : 0, /* CreatFlags */
5157 : SEC_FILE_READ_DATA, /* DesiredAccess */
5158 : FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
5159 : FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5160 : FILE_OPEN, /* CreateDisposition */
5161 : FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5162 : 0, /* Impersonation */
5163 : 0); /* SecurityFlags */
5164 1 : if (tevent_req_nomem(subreq, req)) {
5165 0 : return tevent_req_post(req, ev);
5166 : }
5167 1 : tevent_req_set_callback(subreq, oplock5_opened, req);
5168 :
5169 1 : subreq = cli_echo_send(
5170 : state,
5171 : ev,
5172 : cli,
5173 : 1,
5174 1 : (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5175 1 : if (tevent_req_nomem(subreq, req)) {
5176 0 : return tevent_req_post(req, ev);
5177 : }
5178 1 : tevent_req_set_callback(subreq, oplock5_pong, req);
5179 :
5180 1 : subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5181 1 : if (tevent_req_nomem(subreq, req)) {
5182 0 : return tevent_req_post(req, ev);
5183 : }
5184 1 : tevent_req_set_callback(subreq, oplock5_timedout, req);
5185 :
5186 1 : return req;
5187 : }
5188 :
5189 1 : static void oplock5_opened(struct tevent_req *subreq)
5190 : {
5191 1 : struct tevent_req *req = tevent_req_callback_data(
5192 : subreq, struct tevent_req);
5193 0 : NTSTATUS status;
5194 0 : uint16_t fnum;
5195 :
5196 1 : status = cli_ntcreate_recv(subreq, &fnum, NULL);
5197 1 : TALLOC_FREE(subreq);
5198 1 : if (tevent_req_nterror(req, status)) {
5199 0 : return;
5200 : }
5201 1 : tevent_req_done(req);
5202 : }
5203 :
5204 1 : static void oplock5_pong(struct tevent_req *subreq)
5205 : {
5206 1 : struct tevent_req *req = tevent_req_callback_data(
5207 : subreq, struct tevent_req);
5208 1 : struct oplock5_state *state = tevent_req_data(
5209 : req, struct oplock5_state);
5210 0 : NTSTATUS status;
5211 :
5212 1 : status = cli_echo_recv(subreq);
5213 1 : TALLOC_FREE(subreq);
5214 1 : if (tevent_req_nterror(req, status)) {
5215 0 : return;
5216 : }
5217 :
5218 1 : close(state->pipe_down_fd);
5219 : }
5220 :
5221 0 : static void oplock5_timedout(struct tevent_req *subreq)
5222 : {
5223 0 : struct tevent_req *req = tevent_req_callback_data(
5224 : subreq, struct tevent_req);
5225 0 : bool ok;
5226 :
5227 0 : ok = tevent_wakeup_recv(subreq);
5228 0 : TALLOC_FREE(subreq);
5229 0 : if (!ok) {
5230 0 : tevent_req_oom(req);
5231 0 : return;
5232 : }
5233 0 : tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5234 : }
5235 :
5236 1 : static NTSTATUS oplock5_recv(struct tevent_req *req)
5237 : {
5238 1 : return tevent_req_simple_recv_ntstatus(req);
5239 : }
5240 :
5241 1 : static bool run_oplock5(int dummy)
5242 : {
5243 1 : struct tevent_context *ev = NULL;
5244 1 : struct tevent_req *req = NULL;
5245 1 : struct cli_state *cli = NULL;
5246 1 : const char *fname = "oplock5.txt";
5247 0 : int pipe_down[2], pipe_up[2];
5248 0 : pid_t child_pid;
5249 1 : uint8_t c = '\0';
5250 0 : NTSTATUS status;
5251 0 : int ret;
5252 0 : bool ok;
5253 :
5254 1 : printf("starting oplock5\n");
5255 :
5256 1 : if (local_path == NULL) {
5257 0 : d_fprintf(stderr, "oplock5 must be given a local path via "
5258 : "-l <localpath>\n");
5259 0 : return false;
5260 : }
5261 :
5262 1 : ret = pipe(pipe_down);
5263 1 : if (ret == -1) {
5264 0 : d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5265 0 : return false;
5266 : }
5267 1 : ret = pipe(pipe_up);
5268 1 : if (ret == -1) {
5269 0 : d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5270 0 : return false;
5271 : }
5272 :
5273 1 : child_pid = fork();
5274 2 : if (child_pid == -1) {
5275 0 : d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5276 0 : return false;
5277 : }
5278 :
5279 2 : if (child_pid == 0) {
5280 1 : char *local_file = NULL;
5281 0 : int fd;
5282 :
5283 1 : close(pipe_down[1]);
5284 1 : close(pipe_up[0]);
5285 :
5286 1 : local_file = talloc_asprintf(
5287 1 : talloc_tos(), "%s/%s", local_path, fname);
5288 1 : if (local_file == 0) {
5289 0 : c = 1;
5290 0 : goto do_write;
5291 : }
5292 1 : fd = open(local_file, O_RDWR|O_CREAT, 0644);
5293 1 : if (fd == -1) {
5294 0 : d_fprintf(stderr,
5295 : "open(%s) in child failed: %s\n",
5296 : local_file,
5297 0 : strerror(errno));
5298 0 : c = 2;
5299 0 : goto do_write;
5300 : }
5301 :
5302 1 : signal(SIGIO, SIG_IGN);
5303 :
5304 1 : ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5305 1 : if (ret == -1) {
5306 0 : d_fprintf(stderr,
5307 : "SETLEASE in child failed: %s\n",
5308 0 : strerror(errno));
5309 0 : c = 3;
5310 0 : goto do_write;
5311 : }
5312 :
5313 1 : do_write:
5314 1 : ret = sys_write(pipe_up[1], &c, sizeof(c));
5315 1 : if (ret == -1) {
5316 0 : d_fprintf(stderr,
5317 : "sys_write failed: %s\n",
5318 0 : strerror(errno));
5319 0 : exit(4);
5320 : }
5321 1 : ret = sys_read(pipe_down[0], &c, sizeof(c));
5322 1 : if (ret == -1) {
5323 0 : d_fprintf(stderr,
5324 : "sys_read failed: %s\n",
5325 0 : strerror(errno));
5326 0 : exit(5);
5327 : }
5328 1 : exit(0);
5329 : }
5330 :
5331 1 : close(pipe_up[1]);
5332 1 : close(pipe_down[0]);
5333 :
5334 1 : ret = sys_read(pipe_up[0], &c, sizeof(c));
5335 1 : if (ret != 1) {
5336 0 : d_fprintf(stderr,
5337 : "sys_read failed: %s\n",
5338 0 : strerror(errno));
5339 0 : return false;
5340 : }
5341 1 : if (c != 0) {
5342 0 : d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5343 0 : return false;
5344 : }
5345 :
5346 1 : ok = torture_open_connection(&cli, 0);
5347 1 : if (!ok) {
5348 0 : d_fprintf(stderr, "torture_open_connection failed\n");
5349 0 : return false;
5350 : }
5351 :
5352 1 : ev = samba_tevent_context_init(talloc_tos());
5353 1 : if (ev == NULL) {
5354 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
5355 0 : return false;
5356 : }
5357 :
5358 1 : req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5359 1 : if (req == NULL) {
5360 0 : d_fprintf(stderr, "oplock5_send failed\n");
5361 0 : return false;
5362 : }
5363 :
5364 1 : ok = tevent_req_poll_ntstatus(req, ev, &status);
5365 1 : if (!ok) {
5366 0 : d_fprintf(stderr,
5367 : "tevent_req_poll_ntstatus failed: %s\n",
5368 : nt_errstr(status));
5369 0 : return false;
5370 : }
5371 :
5372 1 : status = oplock5_recv(req);
5373 1 : TALLOC_FREE(req);
5374 1 : if (!NT_STATUS_IS_OK(status)) {
5375 0 : d_fprintf(stderr,
5376 : "oplock5 failed: %s\n",
5377 : nt_errstr(status));
5378 0 : return false;
5379 : }
5380 :
5381 1 : return true;
5382 : }
5383 :
5384 : #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5385 :
5386 : /*
5387 : Test delete on close semantics.
5388 : */
5389 5 : static bool run_deletetest(int dummy)
5390 : {
5391 5 : struct cli_state *cli1 = NULL;
5392 5 : struct cli_state *cli2 = NULL;
5393 5 : const char *fname = "\\delete.file";
5394 5 : uint16_t fnum1 = (uint16_t)-1;
5395 5 : uint16_t fnum2 = (uint16_t)-1;
5396 5 : bool correct = false;
5397 0 : NTSTATUS status;
5398 :
5399 5 : printf("starting delete test\n");
5400 :
5401 5 : if (!torture_open_connection(&cli1, 0)) {
5402 0 : return False;
5403 : }
5404 :
5405 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
5406 :
5407 : /* Test 1 - this should delete the file on close. */
5408 :
5409 5 : cli_setatr(cli1, fname, 0, 0);
5410 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5411 :
5412 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5413 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5414 : FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5415 5 : if (!NT_STATUS_IS_OK(status)) {
5416 0 : printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5417 0 : goto fail;
5418 : }
5419 :
5420 5 : status = cli_close(cli1, fnum1);
5421 5 : if (!NT_STATUS_IS_OK(status)) {
5422 0 : printf("[1] close failed (%s)\n", nt_errstr(status));
5423 0 : goto fail;
5424 : }
5425 :
5426 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5427 5 : if (NT_STATUS_IS_OK(status)) {
5428 0 : printf("[1] open of %s succeeded (should fail)\n", fname);
5429 0 : goto fail;
5430 : }
5431 :
5432 5 : printf("first delete on close test succeeded.\n");
5433 :
5434 : /* Test 2 - this should delete the file on close. */
5435 :
5436 5 : cli_setatr(cli1, fname, 0, 0);
5437 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5438 :
5439 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5440 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5441 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5442 5 : if (!NT_STATUS_IS_OK(status)) {
5443 0 : printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5444 0 : goto fail;
5445 : }
5446 :
5447 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5448 5 : if (!NT_STATUS_IS_OK(status)) {
5449 0 : printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5450 0 : goto fail;
5451 : }
5452 :
5453 5 : status = cli_close(cli1, fnum1);
5454 5 : if (!NT_STATUS_IS_OK(status)) {
5455 0 : printf("[2] close failed (%s)\n", nt_errstr(status));
5456 0 : goto fail;
5457 : }
5458 :
5459 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5460 5 : if (NT_STATUS_IS_OK(status)) {
5461 0 : printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5462 0 : status = cli_close(cli1, fnum1);
5463 0 : if (!NT_STATUS_IS_OK(status)) {
5464 0 : printf("[2] close failed (%s)\n", nt_errstr(status));
5465 : }
5466 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5467 0 : goto fail;
5468 : }
5469 :
5470 5 : printf("second delete on close test succeeded.\n");
5471 :
5472 : /* Test 3 - ... */
5473 5 : cli_setatr(cli1, fname, 0, 0);
5474 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5475 :
5476 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5477 : FILE_ATTRIBUTE_NORMAL,
5478 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5479 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5480 5 : if (!NT_STATUS_IS_OK(status)) {
5481 0 : printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5482 0 : goto fail;
5483 : }
5484 :
5485 : /* This should fail with a sharing violation - open for delete is only compatible
5486 : with SHARE_DELETE. */
5487 :
5488 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5489 : FILE_ATTRIBUTE_NORMAL,
5490 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5491 : FILE_OPEN, 0, 0, &fnum2, NULL);
5492 5 : if (NT_STATUS_IS_OK(status)) {
5493 0 : printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
5494 0 : goto fail;
5495 : }
5496 :
5497 : /* This should succeed. */
5498 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5499 : FILE_ATTRIBUTE_NORMAL,
5500 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5501 : FILE_OPEN, 0, 0, &fnum2, NULL);
5502 5 : if (!NT_STATUS_IS_OK(status)) {
5503 0 : printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5504 0 : goto fail;
5505 : }
5506 :
5507 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5508 5 : if (!NT_STATUS_IS_OK(status)) {
5509 0 : printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5510 0 : goto fail;
5511 : }
5512 :
5513 5 : status = cli_close(cli1, fnum1);
5514 5 : if (!NT_STATUS_IS_OK(status)) {
5515 0 : printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5516 0 : goto fail;
5517 : }
5518 :
5519 5 : status = cli_close(cli1, fnum2);
5520 5 : if (!NT_STATUS_IS_OK(status)) {
5521 0 : printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5522 0 : goto fail;
5523 : }
5524 :
5525 : /* This should fail - file should no longer be there. */
5526 :
5527 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5528 5 : if (NT_STATUS_IS_OK(status)) {
5529 0 : printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5530 0 : status = cli_close(cli1, fnum1);
5531 0 : if (!NT_STATUS_IS_OK(status)) {
5532 0 : printf("[3] close failed (%s)\n", nt_errstr(status));
5533 : }
5534 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5535 0 : goto fail;
5536 : }
5537 :
5538 5 : printf("third delete on close test succeeded.\n");
5539 :
5540 : /* Test 4 ... */
5541 5 : cli_setatr(cli1, fname, 0, 0);
5542 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5543 :
5544 5 : status = cli_ntcreate(cli1, fname, 0,
5545 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5546 : FILE_ATTRIBUTE_NORMAL,
5547 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5548 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5549 5 : if (!NT_STATUS_IS_OK(status)) {
5550 0 : printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5551 0 : goto fail;
5552 : }
5553 :
5554 : /* This should succeed. */
5555 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5556 : FILE_ATTRIBUTE_NORMAL,
5557 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5558 : FILE_OPEN, 0, 0, &fnum2, NULL);
5559 5 : if (!NT_STATUS_IS_OK(status)) {
5560 0 : printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5561 0 : goto fail;
5562 : }
5563 :
5564 5 : status = cli_close(cli1, fnum2);
5565 5 : if (!NT_STATUS_IS_OK(status)) {
5566 0 : printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5567 0 : goto fail;
5568 : }
5569 :
5570 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5571 5 : if (!NT_STATUS_IS_OK(status)) {
5572 0 : printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5573 0 : goto fail;
5574 : }
5575 :
5576 : /* This should fail - no more opens once delete on close set. */
5577 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5578 : FILE_ATTRIBUTE_NORMAL,
5579 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5580 : FILE_OPEN, 0, 0, &fnum2, NULL);
5581 5 : if (NT_STATUS_IS_OK(status)) {
5582 0 : printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
5583 0 : goto fail;
5584 : }
5585 :
5586 5 : status = cli_close(cli1, fnum1);
5587 5 : if (!NT_STATUS_IS_OK(status)) {
5588 0 : printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5589 0 : goto fail;
5590 : }
5591 :
5592 5 : printf("fourth delete on close test succeeded.\n");
5593 :
5594 : /* Test 5 ... */
5595 5 : cli_setatr(cli1, fname, 0, 0);
5596 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5597 :
5598 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5599 5 : if (!NT_STATUS_IS_OK(status)) {
5600 0 : printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5601 0 : goto fail;
5602 : }
5603 :
5604 : /* This should fail - only allowed on NT opens with DELETE access. */
5605 :
5606 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5607 5 : if (NT_STATUS_IS_OK(status)) {
5608 0 : printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5609 0 : goto fail;
5610 : }
5611 :
5612 5 : status = cli_close(cli1, fnum1);
5613 5 : if (!NT_STATUS_IS_OK(status)) {
5614 0 : printf("[5] close failed (%s)\n", nt_errstr(status));
5615 0 : goto fail;
5616 : }
5617 :
5618 5 : printf("fifth delete on close test succeeded.\n");
5619 :
5620 : /* Test 6 ... */
5621 5 : cli_setatr(cli1, fname, 0, 0);
5622 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5623 :
5624 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5625 : FILE_ATTRIBUTE_NORMAL,
5626 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5627 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5628 5 : if (!NT_STATUS_IS_OK(status)) {
5629 0 : printf("[6] open of %s failed (%s)\n", fname,
5630 : nt_errstr(status));
5631 0 : goto fail;
5632 : }
5633 :
5634 : /* This should fail - only allowed on NT opens with DELETE access. */
5635 :
5636 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5637 5 : if (NT_STATUS_IS_OK(status)) {
5638 0 : printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5639 0 : goto fail;
5640 : }
5641 :
5642 5 : status = cli_close(cli1, fnum1);
5643 5 : if (!NT_STATUS_IS_OK(status)) {
5644 0 : printf("[6] close failed (%s)\n", nt_errstr(status));
5645 0 : goto fail;
5646 : }
5647 :
5648 5 : printf("sixth delete on close test succeeded.\n");
5649 :
5650 : /* Test 7 ... */
5651 5 : cli_setatr(cli1, fname, 0, 0);
5652 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5653 :
5654 5 : status = cli_ntcreate(cli1, fname, 0,
5655 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5656 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5657 : 0, 0, &fnum1, NULL);
5658 5 : if (!NT_STATUS_IS_OK(status)) {
5659 0 : printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5660 0 : goto fail;
5661 : }
5662 :
5663 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5664 5 : if (!NT_STATUS_IS_OK(status)) {
5665 0 : printf("[7] setting delete_on_close on file failed !\n");
5666 0 : goto fail;
5667 : }
5668 :
5669 5 : status = cli_nt_delete_on_close(cli1, fnum1, false);
5670 5 : if (!NT_STATUS_IS_OK(status)) {
5671 0 : printf("[7] unsetting delete_on_close on file failed !\n");
5672 0 : goto fail;
5673 : }
5674 :
5675 5 : status = cli_close(cli1, fnum1);
5676 5 : if (!NT_STATUS_IS_OK(status)) {
5677 0 : printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5678 0 : goto fail;
5679 : }
5680 :
5681 : /* This next open should succeed - we reset the flag. */
5682 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5683 5 : if (!NT_STATUS_IS_OK(status)) {
5684 0 : printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5685 0 : goto fail;
5686 : }
5687 :
5688 5 : status = cli_close(cli1, fnum1);
5689 5 : if (!NT_STATUS_IS_OK(status)) {
5690 0 : printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5691 0 : goto fail;
5692 : }
5693 :
5694 5 : printf("seventh delete on close test succeeded.\n");
5695 :
5696 : /* Test 8 ... */
5697 5 : cli_setatr(cli1, fname, 0, 0);
5698 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5699 :
5700 5 : if (!torture_open_connection(&cli2, 1)) {
5701 0 : printf("[8] failed to open second connection.\n");
5702 0 : goto fail;
5703 : }
5704 :
5705 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
5706 :
5707 5 : status = cli_ntcreate(cli1, fname, 0,
5708 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5709 : FILE_ATTRIBUTE_NORMAL,
5710 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5711 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5712 5 : if (!NT_STATUS_IS_OK(status)) {
5713 0 : printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5714 0 : goto fail;
5715 : }
5716 :
5717 5 : status = cli_ntcreate(cli2, fname, 0,
5718 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5719 : FILE_ATTRIBUTE_NORMAL,
5720 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5721 : FILE_OPEN, 0, 0, &fnum2, NULL);
5722 5 : if (!NT_STATUS_IS_OK(status)) {
5723 0 : printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5724 0 : goto fail;
5725 : }
5726 :
5727 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5728 5 : if (!NT_STATUS_IS_OK(status)) {
5729 0 : printf("[8] setting delete_on_close on file failed !\n");
5730 0 : goto fail;
5731 : }
5732 :
5733 5 : status = cli_close(cli1, fnum1);
5734 5 : if (!NT_STATUS_IS_OK(status)) {
5735 0 : printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5736 0 : goto fail;
5737 : }
5738 :
5739 5 : status = cli_close(cli2, fnum2);
5740 5 : if (!NT_STATUS_IS_OK(status)) {
5741 0 : printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5742 0 : goto fail;
5743 : }
5744 :
5745 : /* This should fail.. */
5746 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5747 5 : if (NT_STATUS_IS_OK(status)) {
5748 0 : printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5749 0 : goto fail;
5750 : }
5751 :
5752 5 : printf("eighth delete on close test succeeded.\n");
5753 :
5754 : /* Test 9 ... */
5755 :
5756 : /* This should fail - we need to set DELETE_ACCESS. */
5757 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5758 : FILE_ATTRIBUTE_NORMAL,
5759 : FILE_SHARE_NONE,
5760 : FILE_OVERWRITE_IF,
5761 : FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5762 5 : if (NT_STATUS_IS_OK(status)) {
5763 0 : printf("[9] open of %s succeeded should have failed!\n", fname);
5764 0 : goto fail;
5765 : }
5766 :
5767 5 : printf("ninth delete on close test succeeded.\n");
5768 :
5769 : /* Test 10 ... */
5770 :
5771 5 : status = cli_ntcreate(cli1, fname, 0,
5772 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5773 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5774 : FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5775 : 0, &fnum1, NULL);
5776 5 : if (!NT_STATUS_IS_OK(status)) {
5777 0 : printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5778 0 : goto fail;
5779 : }
5780 :
5781 : /* This should delete the file. */
5782 5 : status = cli_close(cli1, fnum1);
5783 5 : if (!NT_STATUS_IS_OK(status)) {
5784 0 : printf("[10] close failed (%s)\n", nt_errstr(status));
5785 0 : goto fail;
5786 : }
5787 :
5788 : /* This should fail.. */
5789 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5790 5 : if (NT_STATUS_IS_OK(status)) {
5791 0 : printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5792 0 : goto fail;
5793 : }
5794 :
5795 5 : printf("tenth delete on close test succeeded.\n");
5796 :
5797 : /* Test 11 ... */
5798 :
5799 5 : cli_setatr(cli1, fname, 0, 0);
5800 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5801 :
5802 : /* Can we open a read-only file with delete access? */
5803 :
5804 : /* Create a readonly file. */
5805 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5806 : FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5807 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5808 5 : if (!NT_STATUS_IS_OK(status)) {
5809 0 : printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5810 0 : goto fail;
5811 : }
5812 :
5813 5 : status = cli_close(cli1, fnum1);
5814 5 : if (!NT_STATUS_IS_OK(status)) {
5815 0 : printf("[11] close failed (%s)\n", nt_errstr(status));
5816 0 : goto fail;
5817 : }
5818 :
5819 : /* Now try open for delete access. */
5820 5 : status = cli_ntcreate(cli1, fname, 0,
5821 : FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5822 : 0,
5823 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5824 : FILE_OPEN, 0, 0, &fnum1, NULL);
5825 5 : if (!NT_STATUS_IS_OK(status)) {
5826 0 : printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5827 0 : goto fail;
5828 : }
5829 :
5830 5 : cli_close(cli1, fnum1);
5831 :
5832 5 : printf("eleventh delete on close test succeeded.\n");
5833 :
5834 : /*
5835 : * Test 12
5836 : * like test 4 but with initial delete on close
5837 : */
5838 :
5839 5 : cli_setatr(cli1, fname, 0, 0);
5840 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5841 :
5842 5 : status = cli_ntcreate(cli1, fname, 0,
5843 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5844 : FILE_ATTRIBUTE_NORMAL,
5845 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5846 : FILE_OVERWRITE_IF,
5847 : FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5848 5 : if (!NT_STATUS_IS_OK(status)) {
5849 0 : printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5850 0 : goto fail;
5851 : }
5852 :
5853 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5854 : FILE_ATTRIBUTE_NORMAL,
5855 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5856 : FILE_OPEN, 0, 0, &fnum2, NULL);
5857 5 : if (!NT_STATUS_IS_OK(status)) {
5858 0 : printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5859 0 : goto fail;
5860 : }
5861 :
5862 5 : status = cli_close(cli1, fnum2);
5863 5 : if (!NT_STATUS_IS_OK(status)) {
5864 0 : printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5865 0 : goto fail;
5866 : }
5867 :
5868 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5869 5 : if (!NT_STATUS_IS_OK(status)) {
5870 0 : printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5871 0 : goto fail;
5872 : }
5873 :
5874 : /* This should fail - no more opens once delete on close set. */
5875 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5876 : FILE_ATTRIBUTE_NORMAL,
5877 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5878 : FILE_OPEN, 0, 0, &fnum2, NULL);
5879 5 : if (NT_STATUS_IS_OK(status)) {
5880 0 : printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5881 0 : goto fail;
5882 : }
5883 :
5884 5 : status = cli_nt_delete_on_close(cli1, fnum1, false);
5885 5 : if (!NT_STATUS_IS_OK(status)) {
5886 0 : printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5887 0 : goto fail;
5888 : }
5889 :
5890 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5891 : FILE_ATTRIBUTE_NORMAL,
5892 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5893 : FILE_OPEN, 0, 0, &fnum2, NULL);
5894 5 : if (!NT_STATUS_IS_OK(status)) {
5895 0 : printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5896 0 : goto fail;
5897 : }
5898 :
5899 5 : status = cli_close(cli1, fnum2);
5900 5 : if (!NT_STATUS_IS_OK(status)) {
5901 0 : printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5902 0 : goto fail;
5903 : }
5904 :
5905 5 : status = cli_close(cli1, fnum1);
5906 5 : if (!NT_STATUS_IS_OK(status)) {
5907 0 : printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5908 0 : goto fail;
5909 : }
5910 :
5911 : /*
5912 : * setting delete on close on the handle does
5913 : * not unset the initial delete on close...
5914 : */
5915 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5916 : FILE_ATTRIBUTE_NORMAL,
5917 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5918 : FILE_OPEN, 0, 0, &fnum2, NULL);
5919 5 : if (NT_STATUS_IS_OK(status)) {
5920 0 : printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5921 0 : goto fail;
5922 5 : } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5923 0 : printf("ntcreate returned %s, expected "
5924 : "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5925 : nt_errstr(status));
5926 0 : goto fail;
5927 : }
5928 :
5929 5 : printf("twelfth delete on close test succeeded.\n");
5930 :
5931 :
5932 5 : printf("finished delete test\n");
5933 :
5934 5 : correct = true;
5935 :
5936 5 : fail:
5937 : /* FIXME: This will crash if we aborted before cli2 got
5938 : * initialized, because these functions don't handle
5939 : * uninitialized connections. */
5940 :
5941 5 : if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5942 5 : if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5943 5 : cli_setatr(cli1, fname, 0, 0);
5944 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5945 :
5946 5 : if (cli1 && !torture_close_connection(cli1)) {
5947 0 : correct = False;
5948 : }
5949 5 : if (cli2 && !torture_close_connection(cli2)) {
5950 0 : correct = False;
5951 : }
5952 5 : return correct;
5953 : }
5954 :
5955 : struct delete_stream_state {
5956 : bool closed;
5957 : };
5958 :
5959 : static void delete_stream_unlinked(struct tevent_req *subreq);
5960 : static void delete_stream_closed(struct tevent_req *subreq);
5961 :
5962 5 : static struct tevent_req *delete_stream_send(
5963 : TALLOC_CTX *mem_ctx,
5964 : struct tevent_context *ev,
5965 : struct cli_state *cli,
5966 : const char *base_fname,
5967 : uint16_t stream_fnum)
5968 : {
5969 5 : struct tevent_req *req = NULL, *subreq = NULL;
5970 5 : struct delete_stream_state *state = NULL;
5971 :
5972 5 : req = tevent_req_create(
5973 : mem_ctx, &state, struct delete_stream_state);
5974 5 : if (req == NULL) {
5975 0 : return NULL;
5976 : }
5977 :
5978 5 : subreq = cli_unlink_send(
5979 : state,
5980 : ev,
5981 : cli,
5982 : base_fname,
5983 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5984 5 : if (tevent_req_nomem(subreq, req)) {
5985 0 : return tevent_req_post(req, ev);
5986 : }
5987 5 : tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5988 :
5989 5 : subreq = cli_close_send(state, ev, cli, stream_fnum, 0);
5990 5 : if (tevent_req_nomem(subreq, req)) {
5991 0 : return tevent_req_post(req, ev);
5992 : }
5993 5 : tevent_req_set_callback(subreq, delete_stream_closed, req);
5994 :
5995 5 : return req;
5996 : }
5997 :
5998 5 : static void delete_stream_unlinked(struct tevent_req *subreq)
5999 : {
6000 5 : struct tevent_req *req = tevent_req_callback_data(
6001 : subreq, struct tevent_req);
6002 5 : struct delete_stream_state *state = tevent_req_data(
6003 : req, struct delete_stream_state);
6004 0 : NTSTATUS status;
6005 :
6006 5 : status = cli_unlink_recv(subreq);
6007 5 : TALLOC_FREE(subreq);
6008 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6009 0 : printf("cli_unlink returned %s\n",
6010 : nt_errstr(status));
6011 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6012 0 : return;
6013 : }
6014 5 : if (!state->closed) {
6015 : /* close reply should have come in first */
6016 0 : printf("Not closed\n");
6017 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6018 0 : return;
6019 : }
6020 5 : tevent_req_done(req);
6021 : }
6022 :
6023 5 : static void delete_stream_closed(struct tevent_req *subreq)
6024 : {
6025 5 : struct tevent_req *req = tevent_req_callback_data(
6026 : subreq, struct tevent_req);
6027 5 : struct delete_stream_state *state = tevent_req_data(
6028 : req, struct delete_stream_state);
6029 0 : NTSTATUS status;
6030 :
6031 5 : status = cli_close_recv(subreq);
6032 5 : TALLOC_FREE(subreq);
6033 5 : if (tevent_req_nterror(req, status)) {
6034 0 : return;
6035 : }
6036 : /* also waiting for the unlink to come back */
6037 5 : state->closed = true;
6038 : }
6039 :
6040 5 : static NTSTATUS delete_stream_recv(struct tevent_req *req)
6041 : {
6042 5 : return tevent_req_simple_recv_ntstatus(req);
6043 : }
6044 :
6045 5 : static bool run_delete_stream(int dummy)
6046 : {
6047 5 : struct tevent_context *ev = NULL;
6048 5 : struct tevent_req *req = NULL;
6049 5 : struct cli_state *cli = NULL;
6050 5 : const char fname[] = "delete_stream";
6051 5 : const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
6052 0 : uint16_t fnum1, fnum2;
6053 0 : NTSTATUS status;
6054 0 : bool ok;
6055 :
6056 5 : printf("Starting stream delete test\n");
6057 :
6058 5 : ok = torture_open_connection(&cli, 0);
6059 5 : if (!ok) {
6060 0 : return false;
6061 : }
6062 :
6063 5 : cli_setatr(cli, fname, 0, 0);
6064 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6065 :
6066 : /* Create the file. */
6067 5 : status = cli_ntcreate(
6068 : cli,
6069 : fname,
6070 : 0,
6071 : READ_CONTROL_ACCESS,
6072 : 0,
6073 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6074 : FILE_CREATE,
6075 : 0x0,
6076 : 0x0,
6077 : &fnum1,
6078 : NULL);
6079 5 : if (!NT_STATUS_IS_OK(status)) {
6080 0 : d_fprintf(stderr,
6081 : "cli_ntcreate of %s failed (%s)\n",
6082 : fname,
6083 : nt_errstr(status));
6084 0 : return false;
6085 : }
6086 5 : status = cli_close(cli, fnum1);
6087 5 : if (!NT_STATUS_IS_OK(status)) {
6088 0 : d_fprintf(stderr,
6089 : "cli_close of %s failed (%s)\n",
6090 : fname,
6091 : nt_errstr(status));
6092 0 : return false;
6093 : }
6094 :
6095 : /* Now create the stream. */
6096 5 : status = cli_ntcreate(
6097 : cli,
6098 : fname_stream,
6099 : 0,
6100 : FILE_WRITE_DATA,
6101 : 0,
6102 : FILE_SHARE_READ|FILE_SHARE_WRITE,
6103 : FILE_CREATE,
6104 : 0x0,
6105 : 0x0,
6106 : &fnum1,
6107 : NULL);
6108 :
6109 5 : if (!NT_STATUS_IS_OK(status)) {
6110 0 : d_fprintf(stderr,
6111 : "cli_ntcreate of %s failed (%s)\n",
6112 : fname_stream,
6113 : nt_errstr(status));
6114 0 : return false;
6115 : }
6116 :
6117 : /* open it a second time */
6118 :
6119 5 : status = cli_ntcreate(
6120 : cli,
6121 : fname_stream,
6122 : 0,
6123 : FILE_WRITE_DATA,
6124 : 0,
6125 : FILE_SHARE_READ|FILE_SHARE_WRITE,
6126 : FILE_OPEN,
6127 : 0x0,
6128 : 0x0,
6129 : &fnum2,
6130 : NULL);
6131 :
6132 5 : if (!NT_STATUS_IS_OK(status)) {
6133 0 : d_fprintf(stderr,
6134 : "2nd cli_ntcreate of %s failed (%s)\n",
6135 : fname_stream,
6136 : nt_errstr(status));
6137 0 : return false;
6138 : }
6139 :
6140 5 : ev = samba_tevent_context_init(talloc_tos());
6141 5 : if (ev == NULL) {
6142 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
6143 0 : return false;
6144 : }
6145 :
6146 5 : req = delete_stream_send(ev, ev, cli, fname, fnum1);
6147 5 : if (req == NULL) {
6148 0 : d_fprintf(stderr, "delete_stream_send failed\n");
6149 0 : return false;
6150 : }
6151 :
6152 5 : ok = tevent_req_poll_ntstatus(req, ev, &status);
6153 5 : if (!ok) {
6154 0 : d_fprintf(stderr,
6155 : "tevent_req_poll_ntstatus failed: %s\n",
6156 : nt_errstr(status));
6157 0 : return false;
6158 : }
6159 :
6160 5 : status = delete_stream_recv(req);
6161 5 : TALLOC_FREE(req);
6162 5 : if (!NT_STATUS_IS_OK(status)) {
6163 0 : d_fprintf(stderr,
6164 : "delete_stream failed: %s\n",
6165 : nt_errstr(status));
6166 0 : return false;
6167 : }
6168 :
6169 5 : status = cli_close(cli, fnum2);
6170 5 : if (!NT_STATUS_IS_OK(status)) {
6171 0 : d_fprintf(stderr,
6172 : "close failed: %s\n",
6173 : nt_errstr(status));
6174 0 : return false;
6175 : }
6176 :
6177 5 : status = cli_unlink(
6178 : cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6179 5 : if (!NT_STATUS_IS_OK(status)) {
6180 0 : d_fprintf(stderr,
6181 : "unlink failed: %s\n",
6182 : nt_errstr(status));
6183 0 : return false;
6184 : }
6185 :
6186 5 : return true;
6187 : }
6188 :
6189 : /*
6190 : Exercise delete on close semantics - use on the PRINT1 share in torture
6191 : testing.
6192 : */
6193 2 : static bool run_delete_print_test(int dummy)
6194 : {
6195 2 : struct cli_state *cli1 = NULL;
6196 2 : const char *fname = "print_delete.file";
6197 2 : uint16_t fnum1 = (uint16_t)-1;
6198 2 : bool correct = false;
6199 2 : const char *buf = "print file data\n";
6200 0 : NTSTATUS status;
6201 :
6202 2 : printf("starting print delete test\n");
6203 :
6204 2 : if (!torture_open_connection(&cli1, 0)) {
6205 0 : return false;
6206 : }
6207 :
6208 2 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
6209 :
6210 2 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6211 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6212 : 0, 0, &fnum1, NULL);
6213 2 : if (!NT_STATUS_IS_OK(status)) {
6214 0 : printf("open of %s failed (%s)\n",
6215 : fname,
6216 : nt_errstr(status));
6217 0 : goto fail;
6218 : }
6219 :
6220 2 : status = cli_writeall(cli1,
6221 : fnum1,
6222 : 0,
6223 : (const uint8_t *)buf,
6224 : 0, /* offset */
6225 : strlen(buf), /* size */
6226 : NULL);
6227 2 : if (!NT_STATUS_IS_OK(status)) {
6228 0 : printf("writing print file data failed (%s)\n",
6229 : nt_errstr(status));
6230 0 : goto fail;
6231 : }
6232 :
6233 2 : status = cli_nt_delete_on_close(cli1, fnum1, true);
6234 2 : if (!NT_STATUS_IS_OK(status)) {
6235 0 : printf("setting delete_on_close failed (%s)\n",
6236 : nt_errstr(status));
6237 0 : goto fail;
6238 : }
6239 :
6240 2 : status = cli_close(cli1, fnum1);
6241 2 : if (!NT_STATUS_IS_OK(status)) {
6242 0 : printf("close failed (%s)\n", nt_errstr(status));
6243 0 : goto fail;
6244 : }
6245 :
6246 2 : printf("finished print delete test\n");
6247 :
6248 2 : correct = true;
6249 :
6250 2 : fail:
6251 :
6252 2 : if (fnum1 != (uint16_t)-1) {
6253 2 : cli_close(cli1, fnum1);
6254 : }
6255 :
6256 2 : if (cli1 && !torture_close_connection(cli1)) {
6257 0 : correct = false;
6258 : }
6259 2 : return correct;
6260 : }
6261 :
6262 4 : static bool run_deletetest_ln(int dummy)
6263 : {
6264 0 : struct cli_state *cli;
6265 4 : const char *fname = "\\delete1";
6266 4 : const char *fname_ln = "\\delete1_ln";
6267 0 : uint16_t fnum;
6268 0 : uint16_t fnum1;
6269 0 : NTSTATUS status;
6270 4 : bool correct = true;
6271 0 : time_t t;
6272 :
6273 4 : printf("starting deletetest-ln\n");
6274 :
6275 4 : if (!torture_open_connection(&cli, 0)) {
6276 0 : return false;
6277 : }
6278 :
6279 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6280 4 : cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6281 :
6282 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6283 :
6284 : /* Create the file. */
6285 4 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6286 4 : if (!NT_STATUS_IS_OK(status)) {
6287 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6288 0 : return false;
6289 : }
6290 :
6291 4 : status = cli_close(cli, fnum);
6292 4 : if (!NT_STATUS_IS_OK(status)) {
6293 0 : printf("close1 failed (%s)\n", nt_errstr(status));
6294 0 : return false;
6295 : }
6296 :
6297 : /* Now create a hardlink. */
6298 4 : status = cli_hardlink(cli, fname, fname_ln);
6299 4 : if (!NT_STATUS_IS_OK(status)) {
6300 0 : printf("nt hardlink failed (%s)\n", nt_errstr(status));
6301 0 : return false;
6302 : }
6303 :
6304 : /* Open the original file. */
6305 4 : status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6306 : FILE_ATTRIBUTE_NORMAL,
6307 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6308 : FILE_OPEN_IF, 0, 0, &fnum, NULL);
6309 4 : if (!NT_STATUS_IS_OK(status)) {
6310 0 : printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6311 0 : return false;
6312 : }
6313 :
6314 : /* Unlink the hard link path. */
6315 4 : status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6316 : FILE_ATTRIBUTE_NORMAL,
6317 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6318 : FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6319 4 : if (!NT_STATUS_IS_OK(status)) {
6320 0 : printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6321 0 : return false;
6322 : }
6323 4 : status = cli_nt_delete_on_close(cli, fnum1, true);
6324 4 : if (!NT_STATUS_IS_OK(status)) {
6325 0 : d_printf("(%s) failed to set delete_on_close %s: %s\n",
6326 : __location__, fname_ln, nt_errstr(status));
6327 0 : return false;
6328 : }
6329 :
6330 4 : status = cli_close(cli, fnum1);
6331 4 : if (!NT_STATUS_IS_OK(status)) {
6332 0 : printf("close %s failed (%s)\n",
6333 : fname_ln, nt_errstr(status));
6334 0 : return false;
6335 : }
6336 :
6337 4 : status = cli_close(cli, fnum);
6338 4 : if (!NT_STATUS_IS_OK(status)) {
6339 0 : printf("close %s failed (%s)\n",
6340 : fname, nt_errstr(status));
6341 0 : return false;
6342 : }
6343 :
6344 : /* Ensure the original file is still there. */
6345 4 : status = cli_getatr(cli, fname, NULL, NULL, &t);
6346 4 : if (!NT_STATUS_IS_OK(status)) {
6347 0 : printf("%s getatr on file %s failed (%s)\n",
6348 : __location__,
6349 : fname,
6350 : nt_errstr(status));
6351 0 : correct = False;
6352 : }
6353 :
6354 : /* Ensure the link path is gone. */
6355 4 : status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6356 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6357 0 : printf("%s, getatr for file %s returned wrong error code %s "
6358 : "- should have been deleted\n",
6359 : __location__,
6360 : fname_ln, nt_errstr(status));
6361 0 : correct = False;
6362 : }
6363 :
6364 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6365 4 : cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6366 :
6367 4 : if (!torture_close_connection(cli)) {
6368 0 : correct = false;
6369 : }
6370 :
6371 4 : printf("finished deletetest-ln\n");
6372 :
6373 4 : return correct;
6374 : }
6375 :
6376 : /*
6377 : print out server properties
6378 : */
6379 5 : static bool run_properties(int dummy)
6380 : {
6381 0 : struct cli_state *cli;
6382 5 : bool correct = True;
6383 :
6384 5 : printf("starting properties test\n");
6385 :
6386 5 : ZERO_STRUCT(cli);
6387 :
6388 5 : if (!torture_open_connection(&cli, 0)) {
6389 0 : return False;
6390 : }
6391 :
6392 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6393 :
6394 5 : d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6395 :
6396 5 : if (!torture_close_connection(cli)) {
6397 0 : correct = False;
6398 : }
6399 :
6400 5 : return correct;
6401 : }
6402 :
6403 :
6404 :
6405 : /* FIRST_DESIRED_ACCESS 0xf019f */
6406 : #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6407 : FILE_READ_EA| /* 0xf */ \
6408 : FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
6409 : FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
6410 : DELETE_ACCESS|READ_CONTROL_ACCESS|\
6411 : WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
6412 : /* SECOND_DESIRED_ACCESS 0xe0080 */
6413 : #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6414 : READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6415 : WRITE_OWNER_ACCESS /* 0xe0000 */
6416 :
6417 : #if 0
6418 : #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6419 : READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6420 : FILE_READ_DATA|\
6421 : WRITE_OWNER_ACCESS /* */
6422 : #endif
6423 :
6424 : /*
6425 : Test ntcreate calls made by xcopy
6426 : */
6427 5 : static bool run_xcopy(int dummy)
6428 : {
6429 0 : static struct cli_state *cli1;
6430 5 : const char *fname = "\\test.txt";
6431 5 : bool correct = True;
6432 0 : uint16_t fnum1, fnum2;
6433 0 : NTSTATUS status;
6434 :
6435 5 : printf("starting xcopy test\n");
6436 :
6437 5 : if (!torture_open_connection(&cli1, 0)) {
6438 0 : return False;
6439 : }
6440 :
6441 5 : status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6442 : FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6443 : FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6444 5 : if (!NT_STATUS_IS_OK(status)) {
6445 0 : printf("First open failed - %s\n", nt_errstr(status));
6446 0 : return False;
6447 : }
6448 :
6449 5 : status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6450 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6451 : FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6452 5 : if (!NT_STATUS_IS_OK(status)) {
6453 0 : printf("second open failed - %s\n", nt_errstr(status));
6454 0 : return False;
6455 : }
6456 :
6457 5 : if (!torture_close_connection(cli1)) {
6458 0 : correct = False;
6459 : }
6460 :
6461 5 : return correct;
6462 : }
6463 :
6464 : /*
6465 : Test rename on files open with share delete and no share delete.
6466 : */
6467 5 : static bool run_rename(int dummy)
6468 : {
6469 0 : static struct cli_state *cli1;
6470 5 : const char *fname = "\\test.txt";
6471 5 : const char *fname1 = "\\test1.txt";
6472 5 : bool correct = True;
6473 0 : uint16_t fnum1;
6474 0 : uint32_t attr;
6475 0 : NTSTATUS status;
6476 :
6477 5 : printf("starting rename test\n");
6478 :
6479 5 : if (!torture_open_connection(&cli1, 0)) {
6480 0 : return False;
6481 : }
6482 :
6483 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6484 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6485 :
6486 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6487 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6488 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6489 5 : if (!NT_STATUS_IS_OK(status)) {
6490 0 : printf("First open failed - %s\n", nt_errstr(status));
6491 0 : return False;
6492 : }
6493 :
6494 5 : status = cli_rename(cli1, fname, fname1, false);
6495 5 : if (!NT_STATUS_IS_OK(status)) {
6496 5 : printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6497 : } else {
6498 0 : printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6499 0 : correct = False;
6500 : }
6501 :
6502 5 : status = cli_close(cli1, fnum1);
6503 5 : if (!NT_STATUS_IS_OK(status)) {
6504 0 : printf("close - 1 failed (%s)\n", nt_errstr(status));
6505 0 : return False;
6506 : }
6507 :
6508 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6509 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6510 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6511 : #if 0
6512 : FILE_SHARE_DELETE|FILE_SHARE_NONE,
6513 : #else
6514 : FILE_SHARE_DELETE|FILE_SHARE_READ,
6515 : #endif
6516 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6517 5 : if (!NT_STATUS_IS_OK(status)) {
6518 0 : printf("Second open failed - %s\n", nt_errstr(status));
6519 0 : return False;
6520 : }
6521 :
6522 5 : status = cli_rename(cli1, fname, fname1, false);
6523 5 : if (!NT_STATUS_IS_OK(status)) {
6524 0 : printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6525 0 : correct = False;
6526 : } else {
6527 5 : printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6528 : }
6529 :
6530 5 : status = cli_close(cli1, fnum1);
6531 5 : if (!NT_STATUS_IS_OK(status)) {
6532 0 : printf("close - 2 failed (%s)\n", nt_errstr(status));
6533 0 : return False;
6534 : }
6535 :
6536 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6537 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6538 :
6539 5 : status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6540 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6541 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6542 5 : if (!NT_STATUS_IS_OK(status)) {
6543 0 : printf("Third open failed - %s\n", nt_errstr(status));
6544 0 : return False;
6545 : }
6546 :
6547 :
6548 5 : status = cli_rename(cli1, fname, fname1, false);
6549 5 : if (!NT_STATUS_IS_OK(status)) {
6550 0 : printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6551 0 : correct = False;
6552 : } else {
6553 5 : printf("Third rename succeeded (SHARE_NONE)\n");
6554 : }
6555 :
6556 5 : status = cli_close(cli1, fnum1);
6557 5 : if (!NT_STATUS_IS_OK(status)) {
6558 0 : printf("close - 3 failed (%s)\n", nt_errstr(status));
6559 0 : return False;
6560 : }
6561 :
6562 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6563 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6564 :
6565 : /*----*/
6566 :
6567 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6568 : FILE_ATTRIBUTE_NORMAL,
6569 : FILE_SHARE_READ | FILE_SHARE_WRITE,
6570 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6571 5 : if (!NT_STATUS_IS_OK(status)) {
6572 0 : printf("Fourth open failed - %s\n", nt_errstr(status));
6573 0 : return False;
6574 : }
6575 :
6576 5 : status = cli_rename(cli1, fname, fname1, false);
6577 5 : if (!NT_STATUS_IS_OK(status)) {
6578 5 : printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6579 : } else {
6580 0 : printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6581 0 : correct = False;
6582 : }
6583 :
6584 5 : status = cli_close(cli1, fnum1);
6585 5 : if (!NT_STATUS_IS_OK(status)) {
6586 0 : printf("close - 4 failed (%s)\n", nt_errstr(status));
6587 0 : return False;
6588 : }
6589 :
6590 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6591 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6592 :
6593 : /*--*/
6594 :
6595 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6596 : FILE_ATTRIBUTE_NORMAL,
6597 : FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6598 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6599 5 : if (!NT_STATUS_IS_OK(status)) {
6600 0 : printf("Fifth open failed - %s\n", nt_errstr(status));
6601 0 : return False;
6602 : }
6603 :
6604 5 : status = cli_rename(cli1, fname, fname1, false);
6605 5 : if (!NT_STATUS_IS_OK(status)) {
6606 0 : printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6607 0 : correct = False;
6608 : } else {
6609 5 : printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6610 : }
6611 :
6612 : /*--*/
6613 5 : status = cli_close(cli1, fnum1);
6614 5 : if (!NT_STATUS_IS_OK(status)) {
6615 0 : printf("close - 5 failed (%s)\n", nt_errstr(status));
6616 0 : return False;
6617 : }
6618 :
6619 : /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6620 5 : status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6621 5 : if (!NT_STATUS_IS_OK(status)) {
6622 0 : printf("getatr on file %s failed - %s ! \n",
6623 : fname1, nt_errstr(status));
6624 0 : correct = False;
6625 : } else {
6626 5 : if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6627 0 : printf("Renamed file %s has wrong attr 0x%x "
6628 : "(should be 0x%x)\n",
6629 : fname1,
6630 : attr,
6631 : (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6632 0 : correct = False;
6633 : } else {
6634 5 : printf("Renamed file %s has archive bit set\n", fname1);
6635 : }
6636 : }
6637 :
6638 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6639 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6640 :
6641 5 : if (!torture_close_connection(cli1)) {
6642 0 : correct = False;
6643 : }
6644 :
6645 5 : return correct;
6646 : }
6647 :
6648 : /*
6649 : Test rename into a directory with an ACL denying it.
6650 : */
6651 4 : static bool run_rename_access(int dummy)
6652 : {
6653 0 : static struct cli_state *cli = NULL;
6654 0 : static struct cli_state *posix_cli = NULL;
6655 4 : const char *src = "test.txt";
6656 4 : const char *dname = "dir";
6657 4 : const char *dst = "dir\\test.txt";
6658 4 : const char *dsrc = "test.dir";
6659 4 : const char *ddst = "dir\\test.dir";
6660 4 : uint16_t fnum = (uint16_t)-1;
6661 4 : struct security_descriptor *sd = NULL;
6662 4 : struct security_descriptor *newsd = NULL;
6663 0 : NTSTATUS status;
6664 4 : TALLOC_CTX *frame = NULL;
6665 :
6666 4 : frame = talloc_stackframe();
6667 4 : printf("starting rename access test\n");
6668 :
6669 : /* Windows connection. */
6670 4 : if (!torture_open_connection(&cli, 0)) {
6671 0 : goto fail;
6672 : }
6673 :
6674 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6675 :
6676 : /* Posix connection. */
6677 4 : if (!torture_open_connection(&posix_cli, 0)) {
6678 0 : goto fail;
6679 : }
6680 :
6681 4 : smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6682 :
6683 4 : status = torture_setup_unix_extensions(posix_cli);
6684 4 : if (!NT_STATUS_IS_OK(status)) {
6685 0 : goto fail;
6686 : }
6687 :
6688 : /* Start with a clean slate. */
6689 4 : cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6690 4 : cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6691 4 : cli_rmdir(cli, dsrc);
6692 4 : cli_rmdir(cli, ddst);
6693 4 : cli_rmdir(cli, dname);
6694 :
6695 : /*
6696 : * Setup the destination directory with a DENY ACE to
6697 : * prevent new files within it.
6698 : */
6699 4 : status = cli_ntcreate(cli,
6700 : dname,
6701 : 0,
6702 : FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6703 : WRITE_DAC_ACCESS|FILE_READ_DATA|
6704 : WRITE_OWNER_ACCESS,
6705 : FILE_ATTRIBUTE_DIRECTORY,
6706 : FILE_SHARE_READ|FILE_SHARE_WRITE,
6707 : FILE_CREATE,
6708 : FILE_DIRECTORY_FILE,
6709 : 0,
6710 : &fnum,
6711 : NULL);
6712 4 : if (!NT_STATUS_IS_OK(status)) {
6713 0 : printf("Create of %s - %s\n", dname, nt_errstr(status));
6714 0 : goto fail;
6715 : }
6716 :
6717 4 : status = cli_query_secdesc(cli,
6718 : fnum,
6719 : frame,
6720 : &sd);
6721 4 : if (!NT_STATUS_IS_OK(status)) {
6722 0 : printf("cli_query_secdesc failed for %s (%s)\n",
6723 : dname, nt_errstr(status));
6724 0 : goto fail;
6725 : }
6726 :
6727 4 : newsd = security_descriptor_dacl_create(frame,
6728 : 0,
6729 : NULL,
6730 : NULL,
6731 : SID_WORLD,
6732 : SEC_ACE_TYPE_ACCESS_DENIED,
6733 : SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6734 : 0,
6735 : NULL);
6736 4 : if (newsd == NULL) {
6737 0 : goto fail;
6738 : }
6739 8 : sd->dacl = security_acl_concatenate(frame,
6740 4 : newsd->dacl,
6741 4 : sd->dacl);
6742 4 : if (sd->dacl == NULL) {
6743 0 : goto fail;
6744 : }
6745 4 : status = cli_set_secdesc(cli, fnum, sd);
6746 4 : if (!NT_STATUS_IS_OK(status)) {
6747 0 : printf("cli_set_secdesc failed for %s (%s)\n",
6748 : dname, nt_errstr(status));
6749 0 : goto fail;
6750 : }
6751 4 : status = cli_close(cli, fnum);
6752 4 : if (!NT_STATUS_IS_OK(status)) {
6753 0 : printf("close failed for %s (%s)\n",
6754 : dname, nt_errstr(status));
6755 0 : goto fail;
6756 : }
6757 : /* Now go around the back and chmod to 777 via POSIX. */
6758 4 : status = cli_posix_chmod(posix_cli, dname, 0777);
6759 4 : if (!NT_STATUS_IS_OK(status)) {
6760 0 : printf("cli_posix_chmod failed for %s (%s)\n",
6761 : dname, nt_errstr(status));
6762 0 : goto fail;
6763 : }
6764 :
6765 : /* Check we can't create a file within dname via Windows. */
6766 4 : status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6767 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6768 0 : cli_close(posix_cli, fnum);
6769 0 : printf("Create of %s should be ACCESS denied, was %s\n",
6770 : dst, nt_errstr(status));
6771 0 : goto fail;
6772 : }
6773 :
6774 : /* Make the sample file/directory. */
6775 4 : status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6776 4 : if (!NT_STATUS_IS_OK(status)) {
6777 0 : printf("open of %s failed (%s)\n", src, nt_errstr(status));
6778 0 : goto fail;
6779 : }
6780 4 : status = cli_close(cli, fnum);
6781 4 : if (!NT_STATUS_IS_OK(status)) {
6782 0 : printf("cli_close failed (%s)\n", nt_errstr(status));
6783 0 : goto fail;
6784 : }
6785 :
6786 4 : status = cli_mkdir(cli, dsrc);
6787 4 : if (!NT_STATUS_IS_OK(status)) {
6788 0 : printf("cli_mkdir of %s failed (%s)\n",
6789 : dsrc, nt_errstr(status));
6790 0 : goto fail;
6791 : }
6792 :
6793 : /*
6794 : * OK - renames of the new file and directory into the
6795 : * dst directory should fail.
6796 : */
6797 :
6798 4 : status = cli_rename(cli, src, dst, false);
6799 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6800 0 : printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6801 : src, dst, nt_errstr(status));
6802 0 : goto fail;
6803 : }
6804 4 : status = cli_rename(cli, dsrc, ddst, false);
6805 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6806 0 : printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6807 : src, dst, nt_errstr(status));
6808 0 : goto fail;
6809 : }
6810 :
6811 4 : TALLOC_FREE(frame);
6812 4 : return true;
6813 :
6814 0 : fail:
6815 :
6816 0 : if (posix_cli) {
6817 0 : torture_close_connection(posix_cli);
6818 : }
6819 :
6820 0 : if (cli) {
6821 0 : if (fnum != (uint16_t)-1) {
6822 0 : cli_close(cli, fnum);
6823 : }
6824 0 : cli_unlink(cli, src,
6825 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6826 0 : cli_unlink(cli, dst,
6827 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6828 0 : cli_rmdir(cli, dsrc);
6829 0 : cli_rmdir(cli, ddst);
6830 0 : cli_rmdir(cli, dname);
6831 :
6832 0 : torture_close_connection(cli);
6833 : }
6834 :
6835 0 : TALLOC_FREE(frame);
6836 0 : return false;
6837 : }
6838 :
6839 : /*
6840 : Test owner rights ACE.
6841 : */
6842 4 : static bool run_owner_rights(int dummy)
6843 : {
6844 0 : static struct cli_state *cli = NULL;
6845 4 : const char *fname = "owner_rights.txt";
6846 4 : uint16_t fnum = (uint16_t)-1;
6847 4 : struct security_descriptor *sd = NULL;
6848 4 : struct security_descriptor *newsd = NULL;
6849 0 : NTSTATUS status;
6850 4 : TALLOC_CTX *frame = NULL;
6851 :
6852 4 : frame = talloc_stackframe();
6853 4 : printf("starting owner rights test\n");
6854 :
6855 : /* Windows connection. */
6856 4 : if (!torture_open_connection(&cli, 0)) {
6857 0 : goto fail;
6858 : }
6859 :
6860 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6861 :
6862 : /* Start with a clean slate. */
6863 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6864 :
6865 : /* Create the test file. */
6866 : /* Now try and open for read and write-dac. */
6867 4 : status = cli_ntcreate(cli,
6868 : fname,
6869 : 0,
6870 : GENERIC_ALL_ACCESS,
6871 : FILE_ATTRIBUTE_NORMAL,
6872 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6873 : FILE_SHARE_DELETE,
6874 : FILE_CREATE,
6875 : 0,
6876 : 0,
6877 : &fnum,
6878 : NULL);
6879 4 : if (!NT_STATUS_IS_OK(status)) {
6880 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
6881 0 : goto fail;
6882 : }
6883 :
6884 : /* Get the original SD. */
6885 4 : status = cli_query_secdesc(cli,
6886 : fnum,
6887 : frame,
6888 : &sd);
6889 4 : if (!NT_STATUS_IS_OK(status)) {
6890 0 : printf("cli_query_secdesc failed for %s (%s)\n",
6891 : fname, nt_errstr(status));
6892 0 : goto fail;
6893 : }
6894 :
6895 : /*
6896 : * Add an "owner-rights" ACE denying WRITE_DATA,
6897 : * and an "owner-rights" ACE allowing READ_DATA.
6898 : */
6899 :
6900 4 : newsd = security_descriptor_dacl_create(frame,
6901 : 0,
6902 : NULL,
6903 : NULL,
6904 : SID_OWNER_RIGHTS,
6905 : SEC_ACE_TYPE_ACCESS_DENIED,
6906 : FILE_WRITE_DATA,
6907 : 0,
6908 : SID_OWNER_RIGHTS,
6909 : SEC_ACE_TYPE_ACCESS_ALLOWED,
6910 : FILE_READ_DATA,
6911 : 0,
6912 : NULL);
6913 4 : if (newsd == NULL) {
6914 0 : goto fail;
6915 : }
6916 8 : sd->dacl = security_acl_concatenate(frame,
6917 4 : newsd->dacl,
6918 4 : sd->dacl);
6919 4 : if (sd->dacl == NULL) {
6920 0 : goto fail;
6921 : }
6922 4 : status = cli_set_secdesc(cli, fnum, sd);
6923 4 : if (!NT_STATUS_IS_OK(status)) {
6924 0 : printf("cli_set_secdesc failed for %s (%s)\n",
6925 : fname, nt_errstr(status));
6926 0 : goto fail;
6927 : }
6928 4 : status = cli_close(cli, fnum);
6929 4 : if (!NT_STATUS_IS_OK(status)) {
6930 0 : printf("close failed for %s (%s)\n",
6931 : fname, nt_errstr(status));
6932 0 : goto fail;
6933 : }
6934 4 : fnum = (uint16_t)-1;
6935 :
6936 : /* Try and open for FILE_WRITE_DATA */
6937 4 : status = cli_ntcreate(cli,
6938 : fname,
6939 : 0,
6940 : FILE_WRITE_DATA,
6941 : FILE_ATTRIBUTE_NORMAL,
6942 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6943 : FILE_SHARE_DELETE,
6944 : FILE_OPEN,
6945 : 0,
6946 : 0,
6947 : &fnum,
6948 : NULL);
6949 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6950 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
6951 0 : goto fail;
6952 : }
6953 :
6954 : /* Now try and open for FILE_READ_DATA */
6955 4 : status = cli_ntcreate(cli,
6956 : fname,
6957 : 0,
6958 : FILE_READ_DATA,
6959 : FILE_ATTRIBUTE_NORMAL,
6960 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6961 : FILE_SHARE_DELETE,
6962 : FILE_OPEN,
6963 : 0,
6964 : 0,
6965 : &fnum,
6966 : NULL);
6967 4 : if (!NT_STATUS_IS_OK(status)) {
6968 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
6969 0 : goto fail;
6970 : }
6971 :
6972 4 : status = cli_close(cli, fnum);
6973 4 : if (!NT_STATUS_IS_OK(status)) {
6974 0 : printf("close failed for %s (%s)\n",
6975 : fname, nt_errstr(status));
6976 0 : goto fail;
6977 : }
6978 :
6979 : /* Restore clean slate. */
6980 4 : TALLOC_FREE(sd);
6981 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6982 :
6983 : /* Create the test file. */
6984 4 : status = cli_ntcreate(cli,
6985 : fname,
6986 : 0,
6987 : GENERIC_ALL_ACCESS,
6988 : FILE_ATTRIBUTE_NORMAL,
6989 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6990 : FILE_SHARE_DELETE,
6991 : FILE_CREATE,
6992 : 0,
6993 : 0,
6994 : &fnum,
6995 : NULL);
6996 4 : if (!NT_STATUS_IS_OK(status)) {
6997 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
6998 0 : goto fail;
6999 : }
7000 :
7001 : /* Get the original SD. */
7002 4 : status = cli_query_secdesc(cli,
7003 : fnum,
7004 : frame,
7005 : &sd);
7006 4 : if (!NT_STATUS_IS_OK(status)) {
7007 0 : printf("cli_query_secdesc failed for %s (%s)\n",
7008 : fname, nt_errstr(status));
7009 0 : goto fail;
7010 : }
7011 :
7012 : /*
7013 : * Add an "owner-rights ACE denying WRITE_DATA,
7014 : * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
7015 : */
7016 :
7017 4 : newsd = security_descriptor_dacl_create(frame,
7018 : 0,
7019 : NULL,
7020 : NULL,
7021 : SID_OWNER_RIGHTS,
7022 : SEC_ACE_TYPE_ACCESS_DENIED,
7023 : FILE_WRITE_DATA,
7024 : 0,
7025 : SID_OWNER_RIGHTS,
7026 : SEC_ACE_TYPE_ACCESS_ALLOWED,
7027 : FILE_READ_DATA|FILE_WRITE_DATA,
7028 : 0,
7029 : NULL);
7030 4 : if (newsd == NULL) {
7031 0 : goto fail;
7032 : }
7033 8 : sd->dacl = security_acl_concatenate(frame,
7034 4 : newsd->dacl,
7035 4 : sd->dacl);
7036 4 : if (sd->dacl == NULL) {
7037 0 : goto fail;
7038 : }
7039 4 : status = cli_set_secdesc(cli, fnum, sd);
7040 4 : if (!NT_STATUS_IS_OK(status)) {
7041 0 : printf("cli_set_secdesc failed for %s (%s)\n",
7042 : fname, nt_errstr(status));
7043 0 : goto fail;
7044 : }
7045 4 : status = cli_close(cli, fnum);
7046 4 : if (!NT_STATUS_IS_OK(status)) {
7047 0 : printf("close failed for %s (%s)\n",
7048 : fname, nt_errstr(status));
7049 0 : goto fail;
7050 : }
7051 4 : fnum = (uint16_t)-1;
7052 :
7053 : /* Try and open for FILE_WRITE_DATA */
7054 4 : status = cli_ntcreate(cli,
7055 : fname,
7056 : 0,
7057 : FILE_WRITE_DATA,
7058 : FILE_ATTRIBUTE_NORMAL,
7059 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7060 : FILE_SHARE_DELETE,
7061 : FILE_OPEN,
7062 : 0,
7063 : 0,
7064 : &fnum,
7065 : NULL);
7066 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7067 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
7068 0 : goto fail;
7069 : }
7070 :
7071 : /* Now try and open for FILE_READ_DATA */
7072 4 : status = cli_ntcreate(cli,
7073 : fname,
7074 : 0,
7075 : FILE_READ_DATA,
7076 : FILE_ATTRIBUTE_NORMAL,
7077 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7078 : FILE_SHARE_DELETE,
7079 : FILE_OPEN,
7080 : 0,
7081 : 0,
7082 : &fnum,
7083 : NULL);
7084 4 : if (!NT_STATUS_IS_OK(status)) {
7085 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
7086 0 : goto fail;
7087 : }
7088 :
7089 4 : status = cli_close(cli, fnum);
7090 4 : if (!NT_STATUS_IS_OK(status)) {
7091 0 : printf("close failed for %s (%s)\n",
7092 : fname, nt_errstr(status));
7093 0 : goto fail;
7094 : }
7095 :
7096 : /* Restore clean slate. */
7097 4 : TALLOC_FREE(sd);
7098 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7099 :
7100 :
7101 : /* Create the test file. */
7102 4 : status = cli_ntcreate(cli,
7103 : fname,
7104 : 0,
7105 : GENERIC_ALL_ACCESS,
7106 : FILE_ATTRIBUTE_NORMAL,
7107 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7108 : FILE_SHARE_DELETE,
7109 : FILE_CREATE,
7110 : 0,
7111 : 0,
7112 : &fnum,
7113 : NULL);
7114 4 : if (!NT_STATUS_IS_OK(status)) {
7115 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
7116 0 : goto fail;
7117 : }
7118 :
7119 : /* Get the original SD. */
7120 4 : status = cli_query_secdesc(cli,
7121 : fnum,
7122 : frame,
7123 : &sd);
7124 4 : if (!NT_STATUS_IS_OK(status)) {
7125 0 : printf("cli_query_secdesc failed for %s (%s)\n",
7126 : fname, nt_errstr(status));
7127 0 : goto fail;
7128 : }
7129 :
7130 : /*
7131 : * Add an "authenticated users" ACE allowing READ_DATA,
7132 : * add an "owner-rights" denying READ_DATA,
7133 : * and an "authenticated users" ACE allowing WRITE_DATA.
7134 : */
7135 :
7136 4 : newsd = security_descriptor_dacl_create(frame,
7137 : 0,
7138 : NULL,
7139 : NULL,
7140 : SID_NT_AUTHENTICATED_USERS,
7141 : SEC_ACE_TYPE_ACCESS_ALLOWED,
7142 : FILE_READ_DATA,
7143 : 0,
7144 : SID_OWNER_RIGHTS,
7145 : SEC_ACE_TYPE_ACCESS_DENIED,
7146 : FILE_READ_DATA,
7147 : 0,
7148 : SID_NT_AUTHENTICATED_USERS,
7149 : SEC_ACE_TYPE_ACCESS_ALLOWED,
7150 : FILE_WRITE_DATA,
7151 : 0,
7152 : NULL);
7153 4 : if (newsd == NULL) {
7154 0 : printf("newsd == NULL\n");
7155 0 : goto fail;
7156 : }
7157 8 : sd->dacl = security_acl_concatenate(frame,
7158 4 : newsd->dacl,
7159 4 : sd->dacl);
7160 4 : if (sd->dacl == NULL) {
7161 0 : printf("sd->dacl == NULL\n");
7162 0 : goto fail;
7163 : }
7164 4 : status = cli_set_secdesc(cli, fnum, sd);
7165 4 : if (!NT_STATUS_IS_OK(status)) {
7166 0 : printf("cli_set_secdesc failed for %s (%s)\n",
7167 : fname, nt_errstr(status));
7168 0 : goto fail;
7169 : }
7170 4 : status = cli_close(cli, fnum);
7171 4 : if (!NT_STATUS_IS_OK(status)) {
7172 0 : printf("close failed for %s (%s)\n",
7173 : fname, nt_errstr(status));
7174 0 : goto fail;
7175 : }
7176 4 : fnum = (uint16_t)-1;
7177 :
7178 : /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7179 4 : status = cli_ntcreate(cli,
7180 : fname,
7181 : 0,
7182 : FILE_READ_DATA|FILE_WRITE_DATA,
7183 : FILE_ATTRIBUTE_NORMAL,
7184 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7185 : FILE_SHARE_DELETE,
7186 : FILE_OPEN,
7187 : 0,
7188 : 0,
7189 : &fnum,
7190 : NULL);
7191 4 : if (!NT_STATUS_IS_OK(status)) {
7192 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
7193 0 : goto fail;
7194 : }
7195 :
7196 4 : status = cli_close(cli, fnum);
7197 4 : if (!NT_STATUS_IS_OK(status)) {
7198 0 : printf("close failed for %s (%s)\n",
7199 : fname, nt_errstr(status));
7200 0 : goto fail;
7201 : }
7202 :
7203 4 : cli_unlink(cli, fname,
7204 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7205 :
7206 4 : TALLOC_FREE(frame);
7207 4 : return true;
7208 :
7209 0 : fail:
7210 :
7211 0 : if (cli) {
7212 0 : if (fnum != (uint16_t)-1) {
7213 0 : cli_close(cli, fnum);
7214 : }
7215 0 : cli_unlink(cli, fname,
7216 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7217 0 : torture_close_connection(cli);
7218 : }
7219 :
7220 0 : TALLOC_FREE(frame);
7221 0 : return false;
7222 : }
7223 :
7224 : /*
7225 : * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7226 : * Note this test only works with a user with SeSecurityPrivilege set.
7227 : *
7228 : * NB. This is also tested in samba3.base.createx_access
7229 : * but this makes it very explicit what we're looking for.
7230 : */
7231 2 : static bool run_smb1_system_security(int dummy)
7232 : {
7233 0 : static struct cli_state *cli = NULL;
7234 2 : const char *fname = "system_security.txt";
7235 2 : uint16_t fnum = (uint16_t)-1;
7236 0 : NTSTATUS status;
7237 2 : TALLOC_CTX *frame = NULL;
7238 :
7239 2 : frame = talloc_stackframe();
7240 2 : printf("starting smb1 system security test\n");
7241 :
7242 : /* SMB1 connection - torture_open_connection() forces this. */
7243 2 : if (!torture_open_connection(&cli, 0)) {
7244 0 : goto fail;
7245 : }
7246 :
7247 2 : smbXcli_conn_set_sockopt(cli->conn, sockops);
7248 :
7249 : /* Start with a clean slate. */
7250 2 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7251 :
7252 : /* Create the test file. */
7253 2 : status = cli_ntcreate(cli,
7254 : fname,
7255 : 0,
7256 : GENERIC_ALL_ACCESS,
7257 : FILE_ATTRIBUTE_NORMAL,
7258 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7259 : FILE_SHARE_DELETE,
7260 : FILE_CREATE,
7261 : 0,
7262 : 0,
7263 : &fnum,
7264 : NULL);
7265 2 : if (!NT_STATUS_IS_OK(status)) {
7266 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
7267 0 : goto fail;
7268 : }
7269 :
7270 2 : status = cli_close(cli, fnum);
7271 :
7272 : /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7273 : /*
7274 : * On SMB1 this succeeds - SMB2 it fails,
7275 : * see the SMB2-SACL test.
7276 : */
7277 2 : status = cli_ntcreate(cli,
7278 : fname,
7279 : 0,
7280 : SEC_FLAG_SYSTEM_SECURITY,
7281 : FILE_ATTRIBUTE_NORMAL,
7282 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7283 : FILE_SHARE_DELETE,
7284 : FILE_OPEN,
7285 : 0,
7286 : 0,
7287 : &fnum,
7288 : NULL);
7289 2 : if (!NT_STATUS_IS_OK(status)) {
7290 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
7291 0 : goto fail;
7292 : }
7293 :
7294 2 : status = cli_close(cli, fnum);
7295 :
7296 2 : cli_unlink(cli, fname,
7297 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7298 :
7299 2 : torture_close_connection(cli);
7300 2 : TALLOC_FREE(frame);
7301 2 : return true;
7302 :
7303 0 : fail:
7304 :
7305 0 : if (cli) {
7306 0 : if (fnum != (uint16_t)-1) {
7307 0 : cli_close(cli, fnum);
7308 : }
7309 0 : cli_unlink(cli, fname,
7310 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7311 0 : torture_close_connection(cli);
7312 : }
7313 :
7314 0 : TALLOC_FREE(frame);
7315 0 : return false;
7316 : }
7317 :
7318 0 : static bool run_pipe_number(int dummy)
7319 : {
7320 0 : struct cli_state *cli1;
7321 0 : const char *pipe_name = "\\SPOOLSS";
7322 0 : uint16_t fnum;
7323 0 : int num_pipes = 0;
7324 0 : NTSTATUS status;
7325 :
7326 0 : printf("starting pipenumber test\n");
7327 0 : if (!torture_open_connection(&cli1, 0)) {
7328 0 : return False;
7329 : }
7330 :
7331 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
7332 0 : while(1) {
7333 0 : status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7334 : FILE_ATTRIBUTE_NORMAL,
7335 : FILE_SHARE_READ|FILE_SHARE_WRITE,
7336 : FILE_OPEN_IF, 0, 0, &fnum, NULL);
7337 0 : if (!NT_STATUS_IS_OK(status)) {
7338 0 : printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7339 0 : break;
7340 : }
7341 0 : num_pipes++;
7342 0 : printf("\r%6d", num_pipes);
7343 : }
7344 :
7345 0 : printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7346 0 : torture_close_connection(cli1);
7347 0 : return True;
7348 : }
7349 :
7350 : /*
7351 : Test open mode returns on read-only files.
7352 : */
7353 5 : static bool run_opentest(int dummy)
7354 : {
7355 0 : static struct cli_state *cli1;
7356 0 : static struct cli_state *cli2;
7357 5 : const char *fname = "\\readonly.file";
7358 0 : uint16_t fnum1, fnum2;
7359 0 : char buf[20];
7360 0 : off_t fsize;
7361 5 : bool correct = True;
7362 0 : char *tmp_path;
7363 0 : NTSTATUS status;
7364 :
7365 5 : printf("starting open test\n");
7366 :
7367 5 : if (!torture_open_connection(&cli1, 0)) {
7368 0 : return False;
7369 : }
7370 :
7371 5 : cli_setatr(cli1, fname, 0, 0);
7372 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7373 :
7374 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
7375 :
7376 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7377 5 : if (!NT_STATUS_IS_OK(status)) {
7378 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7379 0 : return False;
7380 : }
7381 :
7382 5 : status = cli_close(cli1, fnum1);
7383 5 : if (!NT_STATUS_IS_OK(status)) {
7384 0 : printf("close2 failed (%s)\n", nt_errstr(status));
7385 0 : return False;
7386 : }
7387 :
7388 5 : status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7389 5 : if (!NT_STATUS_IS_OK(status)) {
7390 0 : printf("cli_setatr failed (%s)\n", nt_errstr(status));
7391 0 : return False;
7392 : }
7393 :
7394 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7395 5 : if (!NT_STATUS_IS_OK(status)) {
7396 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7397 0 : return False;
7398 : }
7399 :
7400 : /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7401 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7402 :
7403 5 : if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7404 5 : NT_STATUS_ACCESS_DENIED)) {
7405 4 : printf("correct error code ERRDOS/ERRnoaccess returned\n");
7406 : }
7407 :
7408 5 : printf("finished open test 1\n");
7409 :
7410 5 : cli_close(cli1, fnum1);
7411 :
7412 : /* Now try not readonly and ensure ERRbadshare is returned. */
7413 :
7414 5 : cli_setatr(cli1, fname, 0, 0);
7415 :
7416 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7417 5 : if (!NT_STATUS_IS_OK(status)) {
7418 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7419 0 : return False;
7420 : }
7421 :
7422 : /* This will fail - but the error should be ERRshare. */
7423 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7424 :
7425 5 : if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7426 5 : NT_STATUS_SHARING_VIOLATION)) {
7427 5 : printf("correct error code ERRDOS/ERRbadshare returned\n");
7428 : }
7429 :
7430 5 : status = cli_close(cli1, fnum1);
7431 5 : if (!NT_STATUS_IS_OK(status)) {
7432 0 : printf("close2 failed (%s)\n", nt_errstr(status));
7433 0 : return False;
7434 : }
7435 :
7436 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7437 :
7438 5 : printf("finished open test 2\n");
7439 :
7440 : /* Test truncate open disposition on file opened for read. */
7441 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7442 5 : if (!NT_STATUS_IS_OK(status)) {
7443 0 : printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7444 0 : return False;
7445 : }
7446 :
7447 : /* write 20 bytes. */
7448 :
7449 5 : memset(buf, '\0', 20);
7450 :
7451 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7452 5 : if (!NT_STATUS_IS_OK(status)) {
7453 0 : printf("write failed (%s)\n", nt_errstr(status));
7454 0 : correct = False;
7455 : }
7456 :
7457 5 : status = cli_close(cli1, fnum1);
7458 5 : if (!NT_STATUS_IS_OK(status)) {
7459 0 : printf("(3) close1 failed (%s)\n", nt_errstr(status));
7460 0 : return False;
7461 : }
7462 :
7463 : /* Ensure size == 20. */
7464 5 : status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7465 5 : if (!NT_STATUS_IS_OK(status)) {
7466 0 : printf("(3) getatr failed (%s)\n", nt_errstr(status));
7467 0 : return False;
7468 : }
7469 :
7470 5 : if (fsize != 20) {
7471 0 : printf("(3) file size != 20\n");
7472 0 : return False;
7473 : }
7474 :
7475 : /* Now test if we can truncate a file opened for readonly. */
7476 5 : status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7477 5 : if (!NT_STATUS_IS_OK(status)) {
7478 0 : printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7479 0 : return False;
7480 : }
7481 :
7482 5 : status = cli_close(cli1, fnum1);
7483 5 : if (!NT_STATUS_IS_OK(status)) {
7484 0 : printf("close2 failed (%s)\n", nt_errstr(status));
7485 0 : return False;
7486 : }
7487 :
7488 : /* Ensure size == 0. */
7489 5 : status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7490 5 : if (!NT_STATUS_IS_OK(status)) {
7491 0 : printf("(3) getatr failed (%s)\n", nt_errstr(status));
7492 0 : return False;
7493 : }
7494 :
7495 5 : if (fsize != 0) {
7496 0 : printf("(3) file size != 0\n");
7497 0 : return False;
7498 : }
7499 5 : printf("finished open test 3\n");
7500 :
7501 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7502 :
7503 5 : printf("Do ctemp tests\n");
7504 5 : status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7505 5 : if (!NT_STATUS_IS_OK(status)) {
7506 0 : printf("ctemp failed (%s)\n", nt_errstr(status));
7507 0 : return False;
7508 : }
7509 :
7510 5 : printf("ctemp gave path %s\n", tmp_path);
7511 5 : status = cli_close(cli1, fnum1);
7512 5 : if (!NT_STATUS_IS_OK(status)) {
7513 0 : printf("close of temp failed (%s)\n", nt_errstr(status));
7514 : }
7515 :
7516 5 : status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7517 5 : if (!NT_STATUS_IS_OK(status)) {
7518 0 : printf("unlink of temp failed (%s)\n", nt_errstr(status));
7519 : }
7520 :
7521 : /* Test the non-io opens... */
7522 :
7523 5 : if (!torture_open_connection(&cli2, 1)) {
7524 0 : return False;
7525 : }
7526 :
7527 5 : cli_setatr(cli2, fname, 0, 0);
7528 5 : cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7529 :
7530 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
7531 :
7532 5 : printf("TEST #1 testing 2 non-io opens (no delete)\n");
7533 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7534 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7535 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7536 5 : if (!NT_STATUS_IS_OK(status)) {
7537 0 : printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7538 0 : return False;
7539 : }
7540 :
7541 5 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7542 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7543 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7544 5 : if (!NT_STATUS_IS_OK(status)) {
7545 0 : printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7546 0 : return False;
7547 : }
7548 :
7549 5 : status = cli_close(cli1, fnum1);
7550 5 : if (!NT_STATUS_IS_OK(status)) {
7551 0 : printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7552 0 : return False;
7553 : }
7554 :
7555 5 : status = cli_close(cli2, fnum2);
7556 5 : if (!NT_STATUS_IS_OK(status)) {
7557 0 : printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7558 0 : return False;
7559 : }
7560 :
7561 5 : printf("non-io open test #1 passed.\n");
7562 :
7563 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7564 :
7565 5 : printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7566 :
7567 5 : status = cli_ntcreate(cli1, fname, 0,
7568 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7569 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7570 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7571 5 : if (!NT_STATUS_IS_OK(status)) {
7572 0 : printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7573 0 : return False;
7574 : }
7575 :
7576 5 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7577 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7578 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7579 5 : if (!NT_STATUS_IS_OK(status)) {
7580 0 : printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7581 0 : return False;
7582 : }
7583 :
7584 5 : status = cli_close(cli1, fnum1);
7585 5 : if (!NT_STATUS_IS_OK(status)) {
7586 0 : printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7587 0 : return False;
7588 : }
7589 :
7590 5 : status = cli_close(cli2, fnum2);
7591 5 : if (!NT_STATUS_IS_OK(status)) {
7592 0 : printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7593 0 : return False;
7594 : }
7595 :
7596 5 : printf("non-io open test #2 passed.\n");
7597 :
7598 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7599 :
7600 5 : printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7601 :
7602 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7603 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7604 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7605 5 : if (!NT_STATUS_IS_OK(status)) {
7606 0 : printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7607 0 : return False;
7608 : }
7609 :
7610 5 : status = cli_ntcreate(cli2, fname, 0,
7611 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7612 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7613 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7614 5 : if (!NT_STATUS_IS_OK(status)) {
7615 0 : printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7616 0 : return False;
7617 : }
7618 :
7619 5 : status = cli_close(cli1, fnum1);
7620 5 : if (!NT_STATUS_IS_OK(status)) {
7621 0 : printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7622 0 : return False;
7623 : }
7624 :
7625 5 : status = cli_close(cli2, fnum2);
7626 5 : if (!NT_STATUS_IS_OK(status)) {
7627 0 : printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7628 0 : return False;
7629 : }
7630 :
7631 5 : printf("non-io open test #3 passed.\n");
7632 :
7633 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7634 :
7635 5 : printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7636 :
7637 5 : status = cli_ntcreate(cli1, fname, 0,
7638 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7639 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7640 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7641 5 : if (!NT_STATUS_IS_OK(status)) {
7642 0 : printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7643 0 : return False;
7644 : }
7645 :
7646 5 : status = cli_ntcreate(cli2, fname, 0,
7647 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7648 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7649 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7650 5 : if (NT_STATUS_IS_OK(status)) {
7651 0 : printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7652 0 : return False;
7653 : }
7654 :
7655 5 : printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7656 :
7657 5 : status = cli_close(cli1, fnum1);
7658 5 : if (!NT_STATUS_IS_OK(status)) {
7659 0 : printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7660 0 : return False;
7661 : }
7662 :
7663 5 : printf("non-io open test #4 passed.\n");
7664 :
7665 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7666 :
7667 5 : printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7668 :
7669 5 : status = cli_ntcreate(cli1, fname, 0,
7670 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7671 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7672 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7673 5 : if (!NT_STATUS_IS_OK(status)) {
7674 0 : printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7675 0 : return False;
7676 : }
7677 :
7678 5 : status = cli_ntcreate(cli2, fname, 0,
7679 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7680 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7681 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7682 5 : if (!NT_STATUS_IS_OK(status)) {
7683 0 : printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7684 0 : return False;
7685 : }
7686 :
7687 5 : status = cli_close(cli1, fnum1);
7688 5 : if (!NT_STATUS_IS_OK(status)) {
7689 0 : printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7690 0 : return False;
7691 : }
7692 :
7693 5 : status = cli_close(cli2, fnum2);
7694 5 : if (!NT_STATUS_IS_OK(status)) {
7695 0 : printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7696 0 : return False;
7697 : }
7698 :
7699 5 : printf("non-io open test #5 passed.\n");
7700 :
7701 5 : printf("TEST #6 testing 1 non-io open, one io open\n");
7702 :
7703 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7704 :
7705 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7706 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7707 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7708 5 : if (!NT_STATUS_IS_OK(status)) {
7709 0 : printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7710 0 : return False;
7711 : }
7712 :
7713 5 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7714 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7715 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7716 5 : if (!NT_STATUS_IS_OK(status)) {
7717 0 : printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7718 0 : return False;
7719 : }
7720 :
7721 5 : status = cli_close(cli1, fnum1);
7722 5 : if (!NT_STATUS_IS_OK(status)) {
7723 0 : printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7724 0 : return False;
7725 : }
7726 :
7727 5 : status = cli_close(cli2, fnum2);
7728 5 : if (!NT_STATUS_IS_OK(status)) {
7729 0 : printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7730 0 : return False;
7731 : }
7732 :
7733 5 : printf("non-io open test #6 passed.\n");
7734 :
7735 5 : printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7736 :
7737 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7738 :
7739 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7740 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7741 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7742 5 : if (!NT_STATUS_IS_OK(status)) {
7743 0 : printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7744 0 : return False;
7745 : }
7746 :
7747 5 : status = cli_ntcreate(cli2, fname, 0,
7748 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7749 : FILE_ATTRIBUTE_NORMAL,
7750 : FILE_SHARE_READ|FILE_SHARE_DELETE,
7751 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7752 5 : if (NT_STATUS_IS_OK(status)) {
7753 0 : printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7754 0 : return False;
7755 : }
7756 :
7757 5 : printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7758 :
7759 5 : status = cli_close(cli1, fnum1);
7760 5 : if (!NT_STATUS_IS_OK(status)) {
7761 0 : printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7762 0 : return False;
7763 : }
7764 :
7765 5 : printf("non-io open test #7 passed.\n");
7766 :
7767 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7768 :
7769 5 : printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7770 5 : status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7771 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7772 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7773 5 : if (!NT_STATUS_IS_OK(status)) {
7774 0 : printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7775 0 : correct = false;
7776 0 : goto out;
7777 : }
7778 :
7779 : /* Write to ensure we have to update the file time. */
7780 5 : status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7781 : NULL);
7782 5 : if (!NT_STATUS_IS_OK(status)) {
7783 0 : printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7784 0 : correct = false;
7785 0 : goto out;
7786 : }
7787 :
7788 5 : status = cli_close(cli1, fnum1);
7789 5 : if (!NT_STATUS_IS_OK(status)) {
7790 0 : printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7791 0 : correct = false;
7792 : }
7793 :
7794 5 : out:
7795 :
7796 5 : if (!torture_close_connection(cli1)) {
7797 0 : correct = False;
7798 : }
7799 5 : if (!torture_close_connection(cli2)) {
7800 0 : correct = False;
7801 : }
7802 :
7803 5 : return correct;
7804 : }
7805 :
7806 102 : NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7807 : {
7808 0 : uint16_t major, minor;
7809 0 : uint32_t caplow, caphigh;
7810 0 : NTSTATUS status;
7811 :
7812 102 : if (!SERVER_HAS_UNIX_CIFS(cli)) {
7813 0 : printf("Server doesn't support UNIX CIFS extensions.\n");
7814 0 : return NT_STATUS_NOT_SUPPORTED;
7815 : }
7816 :
7817 102 : status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7818 : &caphigh);
7819 102 : if (!NT_STATUS_IS_OK(status)) {
7820 0 : printf("Server didn't return UNIX CIFS extensions: %s\n",
7821 : nt_errstr(status));
7822 0 : return status;
7823 : }
7824 :
7825 102 : status = cli_set_unix_extensions_capabilities(cli, major, minor,
7826 : caplow, caphigh);
7827 102 : if (!NT_STATUS_IS_OK(status)) {
7828 0 : printf("Server doesn't support setting UNIX CIFS extensions: "
7829 : "%s.\n", nt_errstr(status));
7830 0 : return status;
7831 : }
7832 :
7833 102 : return NT_STATUS_OK;
7834 : }
7835 :
7836 : /*
7837 : Test POSIX open /mkdir calls.
7838 : */
7839 4 : static bool run_simple_posix_open_test(int dummy)
7840 : {
7841 0 : static struct cli_state *cli1;
7842 4 : const char *fname = "posix:file";
7843 4 : const char *hname = "posix:hlink";
7844 4 : const char *sname = "posix:symlink";
7845 4 : const char *dname = "posix:dir";
7846 0 : char buf[10];
7847 4 : char *target = NULL;
7848 4 : uint16_t fnum1 = (uint16_t)-1;
7849 0 : SMB_STRUCT_STAT sbuf;
7850 4 : bool correct = false;
7851 0 : NTSTATUS status;
7852 0 : size_t nread;
7853 4 : const char *fname_windows = "windows_file";
7854 4 : uint16_t fnum2 = (uint16_t)-1;
7855 0 : bool ok;
7856 :
7857 4 : printf("Starting simple POSIX open test\n");
7858 :
7859 4 : if (!torture_open_connection(&cli1, 0)) {
7860 0 : return false;
7861 : }
7862 :
7863 4 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
7864 :
7865 4 : status = torture_setup_unix_extensions(cli1);
7866 4 : if (!NT_STATUS_IS_OK(status)) {
7867 0 : return false;
7868 : }
7869 :
7870 4 : cli_setatr(cli1, fname, 0, 0);
7871 4 : cli_posix_unlink(cli1, fname);
7872 4 : cli_setatr(cli1, dname, 0, 0);
7873 4 : cli_posix_rmdir(cli1, dname);
7874 4 : cli_setatr(cli1, hname, 0, 0);
7875 4 : cli_posix_unlink(cli1, hname);
7876 4 : cli_setatr(cli1, sname, 0, 0);
7877 4 : cli_posix_unlink(cli1, sname);
7878 4 : cli_setatr(cli1, fname_windows, 0, 0);
7879 4 : cli_posix_unlink(cli1, fname_windows);
7880 :
7881 : /* Create a directory. */
7882 4 : status = cli_posix_mkdir(cli1, dname, 0777);
7883 4 : if (!NT_STATUS_IS_OK(status)) {
7884 0 : printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7885 0 : goto out;
7886 : }
7887 :
7888 4 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7889 : 0600, &fnum1);
7890 4 : if (!NT_STATUS_IS_OK(status)) {
7891 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7892 0 : goto out;
7893 : }
7894 :
7895 : /* Test ftruncate - set file size. */
7896 4 : status = cli_ftruncate(cli1, fnum1, 1000);
7897 4 : if (!NT_STATUS_IS_OK(status)) {
7898 0 : printf("ftruncate failed (%s)\n", nt_errstr(status));
7899 0 : goto out;
7900 : }
7901 :
7902 : /* Ensure st_size == 1000 */
7903 4 : status = cli_posix_stat(cli1, fname, &sbuf);
7904 4 : if (!NT_STATUS_IS_OK(status)) {
7905 0 : printf("stat failed (%s)\n", nt_errstr(status));
7906 0 : goto out;
7907 : }
7908 :
7909 4 : if (sbuf.st_ex_size != 1000) {
7910 0 : printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7911 0 : goto out;
7912 : }
7913 :
7914 : /* Ensure st_mode == 0600 */
7915 4 : if ((sbuf.st_ex_mode & 07777) != 0600) {
7916 0 : printf("posix_open - bad permissions 0%o != 0600\n",
7917 0 : (unsigned int)(sbuf.st_ex_mode & 07777));
7918 0 : goto out;
7919 : }
7920 :
7921 : /* Test ftruncate - set file size back to zero. */
7922 4 : status = cli_ftruncate(cli1, fnum1, 0);
7923 4 : if (!NT_STATUS_IS_OK(status)) {
7924 0 : printf("ftruncate failed (%s)\n", nt_errstr(status));
7925 0 : goto out;
7926 : }
7927 :
7928 4 : status = cli_close(cli1, fnum1);
7929 4 : if (!NT_STATUS_IS_OK(status)) {
7930 0 : printf("close failed (%s)\n", nt_errstr(status));
7931 0 : goto out;
7932 : }
7933 :
7934 : /* Now open the file again for read only. */
7935 4 : status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7936 4 : if (!NT_STATUS_IS_OK(status)) {
7937 0 : printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7938 0 : goto out;
7939 : }
7940 :
7941 : /* Now unlink while open. */
7942 4 : status = cli_posix_unlink(cli1, fname);
7943 4 : if (!NT_STATUS_IS_OK(status)) {
7944 0 : printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7945 0 : goto out;
7946 : }
7947 :
7948 4 : status = cli_close(cli1, fnum1);
7949 4 : if (!NT_STATUS_IS_OK(status)) {
7950 0 : printf("close(2) failed (%s)\n", nt_errstr(status));
7951 0 : goto out;
7952 : }
7953 :
7954 : /* Ensure the file has gone. */
7955 4 : status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7956 4 : if (NT_STATUS_IS_OK(status)) {
7957 0 : printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7958 0 : goto out;
7959 : }
7960 :
7961 : /* Create again to test open with O_TRUNC. */
7962 4 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7963 4 : if (!NT_STATUS_IS_OK(status)) {
7964 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7965 0 : goto out;
7966 : }
7967 :
7968 : /* Test ftruncate - set file size. */
7969 4 : status = cli_ftruncate(cli1, fnum1, 1000);
7970 4 : if (!NT_STATUS_IS_OK(status)) {
7971 0 : printf("ftruncate failed (%s)\n", nt_errstr(status));
7972 0 : goto out;
7973 : }
7974 :
7975 : /* Ensure st_size == 1000 */
7976 4 : status = cli_posix_stat(cli1, fname, &sbuf);
7977 4 : if (!NT_STATUS_IS_OK(status)) {
7978 0 : printf("stat failed (%s)\n", nt_errstr(status));
7979 0 : goto out;
7980 : }
7981 :
7982 4 : if (sbuf.st_ex_size != 1000) {
7983 0 : printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7984 0 : goto out;
7985 : }
7986 :
7987 4 : status = cli_close(cli1, fnum1);
7988 4 : if (!NT_STATUS_IS_OK(status)) {
7989 0 : printf("close(2) failed (%s)\n", nt_errstr(status));
7990 0 : goto out;
7991 : }
7992 :
7993 : /* Re-open with O_TRUNC. */
7994 4 : status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7995 4 : if (!NT_STATUS_IS_OK(status)) {
7996 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7997 0 : goto out;
7998 : }
7999 :
8000 : /* Ensure st_size == 0 */
8001 4 : status = cli_posix_stat(cli1, fname, &sbuf);
8002 4 : if (!NT_STATUS_IS_OK(status)) {
8003 0 : printf("stat failed (%s)\n", nt_errstr(status));
8004 0 : goto out;
8005 : }
8006 :
8007 4 : if (sbuf.st_ex_size != 0) {
8008 0 : printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
8009 0 : goto out;
8010 : }
8011 :
8012 4 : status = cli_close(cli1, fnum1);
8013 4 : if (!NT_STATUS_IS_OK(status)) {
8014 0 : printf("close failed (%s)\n", nt_errstr(status));
8015 0 : goto out;
8016 : }
8017 :
8018 4 : status = cli_posix_unlink(cli1, fname);
8019 4 : if (!NT_STATUS_IS_OK(status)) {
8020 0 : printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
8021 0 : goto out;
8022 : }
8023 :
8024 4 : status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
8025 4 : if (!NT_STATUS_IS_OK(status)) {
8026 0 : printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
8027 : dname, nt_errstr(status));
8028 0 : goto out;
8029 : }
8030 :
8031 4 : cli_close(cli1, fnum1);
8032 :
8033 : /* What happens when we try and POSIX open a directory for write ? */
8034 4 : status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
8035 4 : if (NT_STATUS_IS_OK(status)) {
8036 0 : printf("POSIX open of directory %s succeeded, "
8037 : "should have failed.\n",
8038 : dname);
8039 0 : goto out;
8040 : } else {
8041 4 : if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
8042 4 : NT_STATUS_FILE_IS_A_DIRECTORY)) {
8043 0 : goto out;
8044 : }
8045 : }
8046 :
8047 : /* Create the file. */
8048 4 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8049 : 0600, &fnum1);
8050 4 : if (!NT_STATUS_IS_OK(status)) {
8051 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
8052 0 : goto out;
8053 : }
8054 :
8055 : /* Write some data into it. */
8056 4 : status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
8057 : NULL);
8058 4 : if (!NT_STATUS_IS_OK(status)) {
8059 0 : printf("cli_write failed: %s\n", nt_errstr(status));
8060 0 : goto out;
8061 : }
8062 :
8063 4 : cli_close(cli1, fnum1);
8064 :
8065 : /* Now create a hardlink. */
8066 4 : status = cli_posix_hardlink(cli1, fname, hname);
8067 4 : if (!NT_STATUS_IS_OK(status)) {
8068 0 : printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
8069 0 : goto out;
8070 : }
8071 :
8072 : /* Now create a symlink. */
8073 4 : status = cli_posix_symlink(cli1, fname, sname);
8074 4 : if (!NT_STATUS_IS_OK(status)) {
8075 0 : printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
8076 0 : goto out;
8077 : }
8078 :
8079 : /* Open the hardlink for read. */
8080 4 : status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
8081 4 : if (!NT_STATUS_IS_OK(status)) {
8082 0 : printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
8083 0 : goto out;
8084 : }
8085 :
8086 4 : status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
8087 4 : if (!NT_STATUS_IS_OK(status)) {
8088 0 : printf("POSIX read of %s failed (%s)\n", hname,
8089 : nt_errstr(status));
8090 0 : goto out;
8091 4 : } else if (nread != 10) {
8092 0 : printf("POSIX read of %s failed. Received %ld, expected %d\n",
8093 : hname, (unsigned long)nread, 10);
8094 0 : goto out;
8095 : }
8096 :
8097 4 : if (memcmp(buf, "TEST DATA\n", 10)) {
8098 0 : printf("invalid data read from hardlink\n");
8099 0 : goto out;
8100 : }
8101 :
8102 : /* Do a POSIX lock/unlock. */
8103 4 : status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8104 4 : if (!NT_STATUS_IS_OK(status)) {
8105 0 : printf("POSIX lock failed %s\n", nt_errstr(status));
8106 0 : goto out;
8107 : }
8108 :
8109 : /* Punch a hole in the locked area. */
8110 4 : status = cli_posix_unlock(cli1, fnum1, 10, 80);
8111 4 : if (!NT_STATUS_IS_OK(status)) {
8112 0 : printf("POSIX unlock failed %s\n", nt_errstr(status));
8113 0 : goto out;
8114 : }
8115 :
8116 4 : cli_close(cli1, fnum1);
8117 :
8118 : /* Open the symlink for read - this should fail. A POSIX
8119 : client should not be doing opens on a symlink. */
8120 4 : status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8121 4 : if (NT_STATUS_IS_OK(status)) {
8122 0 : printf("POSIX open of %s succeeded (should have failed)\n", sname);
8123 0 : goto out;
8124 : }
8125 4 : ok = check_both_error(
8126 : __LINE__, status, ERRDOS, ERRbadpath,
8127 4 : NT_STATUS_OBJECT_NAME_NOT_FOUND);
8128 4 : if (!ok) {
8129 0 : printf("POSIX open of %s should have failed "
8130 : "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8131 : "failed with %s instead.\n",
8132 : sname, nt_errstr(status));
8133 0 : goto out;
8134 : }
8135 :
8136 4 : status = cli_readlink(cli1, sname, talloc_tos(), &target, NULL, NULL);
8137 4 : if (!NT_STATUS_IS_OK(status)) {
8138 0 : printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8139 0 : goto out;
8140 : }
8141 :
8142 4 : if (strcmp(target, fname) != 0) {
8143 0 : printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8144 : sname, fname, target);
8145 0 : goto out;
8146 : }
8147 :
8148 4 : status = cli_posix_rmdir(cli1, dname);
8149 4 : if (!NT_STATUS_IS_OK(status)) {
8150 0 : printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8151 0 : goto out;
8152 : }
8153 :
8154 : /* Check directory opens with a specific permission. */
8155 4 : status = cli_posix_mkdir(cli1, dname, 0700);
8156 4 : if (!NT_STATUS_IS_OK(status)) {
8157 0 : printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8158 0 : goto out;
8159 : }
8160 :
8161 : /* Ensure st_mode == 0700 */
8162 4 : status = cli_posix_stat(cli1, dname, &sbuf);
8163 4 : if (!NT_STATUS_IS_OK(status)) {
8164 0 : printf("stat failed (%s)\n", nt_errstr(status));
8165 0 : goto out;
8166 : }
8167 :
8168 4 : if ((sbuf.st_ex_mode & 07777) != 0700) {
8169 0 : printf("posix_mkdir - bad permissions 0%o != 0700\n",
8170 0 : (unsigned int)(sbuf.st_ex_mode & 07777));
8171 0 : goto out;
8172 : }
8173 :
8174 : /*
8175 : * Now create a Windows file, and attempt a POSIX unlink.
8176 : * This should fail with a sharing violation but due to:
8177 : *
8178 : * [Bug 9571] Unlink after open causes smbd to panic
8179 : *
8180 : * ensure we've fixed the lock ordering violation.
8181 : */
8182 :
8183 4 : status = cli_ntcreate(cli1, fname_windows, 0,
8184 : FILE_READ_DATA|FILE_WRITE_DATA, 0,
8185 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8186 : FILE_CREATE,
8187 : 0x0, 0x0, &fnum2, NULL);
8188 4 : if (!NT_STATUS_IS_OK(status)) {
8189 0 : printf("Windows create of %s failed (%s)\n", fname_windows,
8190 : nt_errstr(status));
8191 0 : goto out;
8192 : }
8193 :
8194 : /* Now try posix_unlink. */
8195 4 : status = cli_posix_unlink(cli1, fname_windows);
8196 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8197 0 : printf("POSIX unlink of %s should fail "
8198 : "with NT_STATUS_SHARING_VIOLATION "
8199 : "got %s instead !\n",
8200 : fname_windows,
8201 : nt_errstr(status));
8202 0 : goto out;
8203 : }
8204 :
8205 4 : cli_close(cli1, fnum2);
8206 :
8207 4 : printf("Simple POSIX open test passed\n");
8208 4 : correct = true;
8209 :
8210 4 : out:
8211 :
8212 4 : if (fnum1 != (uint16_t)-1) {
8213 4 : cli_close(cli1, fnum1);
8214 4 : fnum1 = (uint16_t)-1;
8215 : }
8216 :
8217 4 : if (fnum2 != (uint16_t)-1) {
8218 4 : cli_close(cli1, fnum2);
8219 4 : fnum2 = (uint16_t)-1;
8220 : }
8221 :
8222 4 : cli_setatr(cli1, sname, 0, 0);
8223 4 : cli_posix_unlink(cli1, sname);
8224 4 : cli_setatr(cli1, hname, 0, 0);
8225 4 : cli_posix_unlink(cli1, hname);
8226 4 : cli_setatr(cli1, fname, 0, 0);
8227 4 : cli_posix_unlink(cli1, fname);
8228 4 : cli_setatr(cli1, dname, 0, 0);
8229 4 : cli_posix_rmdir(cli1, dname);
8230 4 : cli_setatr(cli1, fname_windows, 0, 0);
8231 4 : cli_posix_unlink(cli1, fname_windows);
8232 :
8233 4 : if (!torture_close_connection(cli1)) {
8234 0 : correct = false;
8235 : }
8236 :
8237 4 : return correct;
8238 : }
8239 :
8240 : /*
8241 : Test POSIX and Windows ACLs are rejected on symlinks.
8242 : */
8243 4 : static bool run_acl_symlink_test(int dummy)
8244 : {
8245 0 : static struct cli_state *cli;
8246 4 : const char *fname = "posix_file";
8247 4 : const char *sname = "posix_symlink";
8248 4 : uint16_t fnum = (uint16_t)-1;
8249 4 : bool correct = false;
8250 0 : NTSTATUS status;
8251 4 : char *posix_acl = NULL;
8252 4 : size_t posix_acl_len = 0;
8253 4 : char *posix_acl_sym = NULL;
8254 4 : size_t posix_acl_len_sym = 0;
8255 4 : struct security_descriptor *sd = NULL;
8256 4 : TALLOC_CTX *frame = NULL;
8257 :
8258 4 : frame = talloc_stackframe();
8259 :
8260 4 : printf("Starting acl symlink test\n");
8261 :
8262 4 : if (!torture_open_connection(&cli, 0)) {
8263 0 : TALLOC_FREE(frame);
8264 0 : return false;
8265 : }
8266 :
8267 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
8268 :
8269 4 : status = torture_setup_unix_extensions(cli);
8270 4 : if (!NT_STATUS_IS_OK(status)) {
8271 0 : TALLOC_FREE(frame);
8272 0 : return false;
8273 : }
8274 :
8275 4 : cli_setatr(cli, fname, 0, 0);
8276 4 : cli_posix_unlink(cli, fname);
8277 4 : cli_setatr(cli, sname, 0, 0);
8278 4 : cli_posix_unlink(cli, sname);
8279 :
8280 4 : status = cli_ntcreate(cli,
8281 : fname,
8282 : 0,
8283 : READ_CONTROL_ACCESS,
8284 : 0,
8285 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8286 : FILE_CREATE,
8287 : 0x0,
8288 : 0x0,
8289 : &fnum,
8290 : NULL);
8291 :
8292 4 : if (!NT_STATUS_IS_OK(status)) {
8293 0 : printf("cli_ntcreate of %s failed (%s)\n",
8294 : fname,
8295 : nt_errstr(status));
8296 0 : goto out;
8297 : }
8298 :
8299 : /* Get the Windows ACL on the file. */
8300 4 : status = cli_query_secdesc(cli,
8301 : fnum,
8302 : frame,
8303 : &sd);
8304 4 : if (!NT_STATUS_IS_OK(status)) {
8305 0 : printf("cli_query_secdesc failed (%s)\n",
8306 : nt_errstr(status));
8307 0 : goto out;
8308 : }
8309 :
8310 : /* Get the POSIX ACL on the file. */
8311 4 : status = cli_posix_getacl(cli,
8312 : fname,
8313 : frame,
8314 : &posix_acl_len,
8315 : &posix_acl);
8316 :
8317 4 : if (!NT_STATUS_IS_OK(status)) {
8318 0 : printf("cli_posix_getacl failed (%s)\n",
8319 : nt_errstr(status));
8320 0 : goto out;
8321 : }
8322 :
8323 4 : status = cli_close(cli, fnum);
8324 4 : if (!NT_STATUS_IS_OK(status)) {
8325 0 : printf("close failed (%s)\n", nt_errstr(status));
8326 0 : goto out;
8327 : }
8328 4 : fnum = (uint16_t)-1;
8329 :
8330 : /* Now create a symlink. */
8331 4 : status = cli_posix_symlink(cli, fname, sname);
8332 4 : if (!NT_STATUS_IS_OK(status)) {
8333 0 : printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8334 : sname,
8335 : fname,
8336 : nt_errstr(status));
8337 0 : goto out;
8338 : }
8339 :
8340 : /* Open a handle on the symlink for SD set/get should fail. */
8341 4 : status = cli_ntcreate(cli,
8342 : sname,
8343 : 0,
8344 : READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8345 : 0,
8346 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8347 : FILE_OPEN,
8348 : 0x0,
8349 : 0x0,
8350 : &fnum,
8351 : NULL);
8352 :
8353 4 : if (NT_STATUS_IS_OK(status)) {
8354 0 : printf("Symlink open for getsd/setsd of %s "
8355 : "succeeded (should fail)\n",
8356 : sname);
8357 0 : goto out;
8358 : }
8359 :
8360 : /* Try a stat-open on the symlink, should also fail. */
8361 4 : status = cli_ntcreate(cli,
8362 : sname,
8363 : 0,
8364 : FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8365 : 0,
8366 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8367 : FILE_OPEN,
8368 : 0x0,
8369 : 0x0,
8370 : &fnum,
8371 : NULL);
8372 :
8373 4 : if (NT_STATUS_IS_OK(status)) {
8374 0 : printf("Stat-open of symlink succeeded (should fail)\n");
8375 0 : goto out;
8376 : }
8377 :
8378 : /* Get the POSIX ACL on the symlink pathname. Should fail. */
8379 4 : status = cli_posix_getacl(cli,
8380 : sname,
8381 : frame,
8382 : &posix_acl_len_sym,
8383 : &posix_acl_sym);
8384 :
8385 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8386 0 : printf("cli_posix_getacl on a symlink gave %s. "
8387 : "Should be NT_STATUS_ACCESS_DENIED.\n",
8388 : nt_errstr(status));
8389 0 : goto out;
8390 : }
8391 :
8392 : /* Set the POSIX ACL on the symlink pathname. Should fail. */
8393 4 : status = cli_posix_setacl(cli,
8394 : sname,
8395 : posix_acl,
8396 : posix_acl_len);
8397 :
8398 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8399 0 : printf("cli_posix_setacl on a symlink gave %s. "
8400 : "Should be NT_STATUS_ACCESS_DENIED.\n",
8401 : nt_errstr(status));
8402 0 : goto out;
8403 : }
8404 :
8405 4 : printf("ACL symlink test passed\n");
8406 4 : correct = true;
8407 :
8408 4 : out:
8409 :
8410 4 : if (fnum != (uint16_t)-1) {
8411 0 : cli_close(cli, fnum);
8412 0 : fnum = (uint16_t)-1;
8413 : }
8414 :
8415 4 : cli_setatr(cli, sname, 0, 0);
8416 4 : cli_posix_unlink(cli, sname);
8417 4 : cli_setatr(cli, fname, 0, 0);
8418 4 : cli_posix_unlink(cli, fname);
8419 :
8420 4 : if (!torture_close_connection(cli)) {
8421 0 : correct = false;
8422 : }
8423 :
8424 4 : TALLOC_FREE(frame);
8425 4 : return correct;
8426 : }
8427 :
8428 : /*
8429 : Test POSIX can delete a file containing streams.
8430 : */
8431 4 : static bool run_posix_stream_delete(int dummy)
8432 : {
8433 4 : struct cli_state *cli1 = NULL;
8434 4 : struct cli_state *cli2 = NULL;
8435 4 : const char *fname = "streamfile";
8436 4 : const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8437 4 : uint16_t fnum1 = (uint16_t)-1;
8438 4 : bool correct = false;
8439 0 : NTSTATUS status;
8440 4 : TALLOC_CTX *frame = NULL;
8441 :
8442 4 : frame = talloc_stackframe();
8443 :
8444 4 : printf("Starting POSIX stream delete test\n");
8445 :
8446 4 : if (!torture_open_connection(&cli1, 0) ||
8447 4 : !torture_open_connection(&cli2, 1)) {
8448 0 : TALLOC_FREE(frame);
8449 0 : return false;
8450 : }
8451 :
8452 4 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
8453 4 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
8454 :
8455 4 : status = torture_setup_unix_extensions(cli2);
8456 4 : if (!NT_STATUS_IS_OK(status)) {
8457 0 : goto out;
8458 : }
8459 :
8460 4 : cli_setatr(cli1, fname, 0, 0);
8461 4 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8462 :
8463 : /* Create the file. */
8464 4 : status = cli_ntcreate(cli1,
8465 : fname,
8466 : 0,
8467 : READ_CONTROL_ACCESS,
8468 : 0,
8469 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8470 : FILE_CREATE,
8471 : 0x0,
8472 : 0x0,
8473 : &fnum1,
8474 : NULL);
8475 :
8476 4 : if (!NT_STATUS_IS_OK(status)) {
8477 0 : printf("cli_ntcreate of %s failed (%s)\n",
8478 : fname,
8479 : nt_errstr(status));
8480 0 : goto out;
8481 : }
8482 :
8483 4 : status = cli_close(cli1, fnum1);
8484 4 : if (!NT_STATUS_IS_OK(status)) {
8485 0 : printf("cli_close of %s failed (%s)\n",
8486 : fname,
8487 : nt_errstr(status));
8488 0 : goto out;
8489 : }
8490 4 : fnum1 = (uint16_t)-1;
8491 :
8492 : /* Now create the stream. */
8493 4 : status = cli_ntcreate(cli1,
8494 : stream_fname,
8495 : 0,
8496 : FILE_WRITE_DATA,
8497 : 0,
8498 : FILE_SHARE_READ|FILE_SHARE_WRITE,
8499 : FILE_CREATE,
8500 : 0x0,
8501 : 0x0,
8502 : &fnum1,
8503 : NULL);
8504 :
8505 4 : if (!NT_STATUS_IS_OK(status)) {
8506 0 : printf("cli_ntcreate of %s failed (%s)\n",
8507 : stream_fname,
8508 : nt_errstr(status));
8509 0 : goto out;
8510 : }
8511 :
8512 : /* Leave the stream handle open... */
8513 :
8514 : /* POSIX unlink should fail. */
8515 4 : status = cli_posix_unlink(cli2, fname);
8516 4 : if (NT_STATUS_IS_OK(status)) {
8517 0 : printf("cli_posix_unlink of %s succeeded, should have failed\n",
8518 : fname);
8519 0 : goto out;
8520 : }
8521 :
8522 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8523 0 : printf("cli_posix_unlink of %s failed with (%s) "
8524 : "should have been NT_STATUS_SHARING_VIOLATION\n",
8525 : fname,
8526 : nt_errstr(status));
8527 0 : goto out;
8528 : }
8529 :
8530 : /* Close the stream handle. */
8531 4 : status = cli_close(cli1, fnum1);
8532 4 : if (!NT_STATUS_IS_OK(status)) {
8533 0 : printf("cli_close of %s failed (%s)\n",
8534 : stream_fname,
8535 : nt_errstr(status));
8536 0 : goto out;
8537 : }
8538 4 : fnum1 = (uint16_t)-1;
8539 :
8540 : /* POSIX unlink after stream handle closed should succeed. */
8541 4 : status = cli_posix_unlink(cli2, fname);
8542 4 : if (!NT_STATUS_IS_OK(status)) {
8543 0 : printf("cli_posix_unlink of %s failed (%s)\n",
8544 : fname,
8545 : nt_errstr(status));
8546 0 : goto out;
8547 : }
8548 :
8549 4 : printf("POSIX stream delete test passed\n");
8550 4 : correct = true;
8551 :
8552 4 : out:
8553 :
8554 4 : if (fnum1 != (uint16_t)-1) {
8555 0 : cli_close(cli1, fnum1);
8556 0 : fnum1 = (uint16_t)-1;
8557 : }
8558 :
8559 4 : cli_setatr(cli1, fname, 0, 0);
8560 4 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8561 :
8562 4 : if (!torture_close_connection(cli1)) {
8563 0 : correct = false;
8564 : }
8565 4 : if (!torture_close_connection(cli2)) {
8566 0 : correct = false;
8567 : }
8568 :
8569 4 : TALLOC_FREE(frame);
8570 4 : return correct;
8571 : }
8572 :
8573 : /*
8574 : Test setting EA's are rejected on symlinks.
8575 : */
8576 4 : static bool run_ea_symlink_test(int dummy)
8577 : {
8578 0 : static struct cli_state *cli;
8579 4 : const char *fname = "posix_file_ea";
8580 4 : const char *sname = "posix_symlink_ea";
8581 4 : const char *ea_name = "testea_name";
8582 4 : const char *ea_value = "testea_value";
8583 4 : uint16_t fnum = (uint16_t)-1;
8584 4 : bool correct = false;
8585 0 : NTSTATUS status;
8586 0 : size_t i, num_eas;
8587 4 : struct ea_struct *eas = NULL;
8588 4 : TALLOC_CTX *frame = NULL;
8589 :
8590 4 : frame = talloc_stackframe();
8591 :
8592 4 : printf("Starting EA symlink test\n");
8593 :
8594 4 : if (!torture_open_connection(&cli, 0)) {
8595 0 : TALLOC_FREE(frame);
8596 0 : return false;
8597 : }
8598 :
8599 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
8600 :
8601 4 : status = torture_setup_unix_extensions(cli);
8602 4 : if (!NT_STATUS_IS_OK(status)) {
8603 0 : TALLOC_FREE(frame);
8604 0 : return false;
8605 : }
8606 :
8607 4 : cli_setatr(cli, fname, 0, 0);
8608 4 : cli_posix_unlink(cli, fname);
8609 4 : cli_setatr(cli, sname, 0, 0);
8610 4 : cli_posix_unlink(cli, sname);
8611 :
8612 4 : status = cli_ntcreate(cli,
8613 : fname,
8614 : 0,
8615 : READ_CONTROL_ACCESS,
8616 : 0,
8617 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8618 : FILE_CREATE,
8619 : 0x0,
8620 : 0x0,
8621 : &fnum,
8622 : NULL);
8623 :
8624 4 : if (!NT_STATUS_IS_OK(status)) {
8625 0 : printf("cli_ntcreate of %s failed (%s)\n",
8626 : fname,
8627 : nt_errstr(status));
8628 0 : goto out;
8629 : }
8630 :
8631 4 : status = cli_close(cli, fnum);
8632 4 : if (!NT_STATUS_IS_OK(status)) {
8633 0 : printf("close failed (%s)\n",
8634 : nt_errstr(status));
8635 0 : goto out;
8636 : }
8637 4 : fnum = (uint16_t)-1;
8638 :
8639 : /* Set an EA on the path. */
8640 4 : status = cli_set_ea_path(cli,
8641 : fname,
8642 : ea_name,
8643 : ea_value,
8644 4 : strlen(ea_value)+1);
8645 :
8646 4 : if (!NT_STATUS_IS_OK(status)) {
8647 0 : printf("cli_set_ea_path failed (%s)\n",
8648 : nt_errstr(status));
8649 0 : goto out;
8650 : }
8651 :
8652 : /* Now create a symlink. */
8653 4 : status = cli_posix_symlink(cli, fname, sname);
8654 4 : if (!NT_STATUS_IS_OK(status)) {
8655 0 : printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8656 : sname,
8657 : fname,
8658 : nt_errstr(status));
8659 0 : goto out;
8660 : }
8661 :
8662 : /* Get the EA list on the path. Should return value set. */
8663 4 : status = cli_get_ea_list_path(cli,
8664 : fname,
8665 : frame,
8666 : &num_eas,
8667 : &eas);
8668 :
8669 4 : if (!NT_STATUS_IS_OK(status)) {
8670 0 : printf("cli_get_ea_list_path failed (%s)\n",
8671 : nt_errstr(status));
8672 0 : goto out;
8673 : }
8674 :
8675 : /* Ensure the EA we set is there. */
8676 4 : for (i=0; i<num_eas; i++) {
8677 4 : if (strcmp(eas[i].name, ea_name) == 0 &&
8678 4 : eas[i].value.length == strlen(ea_value)+1 &&
8679 4 : memcmp(eas[i].value.data,
8680 : ea_value,
8681 4 : eas[i].value.length) == 0) {
8682 4 : break;
8683 : }
8684 : }
8685 :
8686 4 : if (i == num_eas) {
8687 0 : printf("Didn't find EA on pathname %s\n",
8688 : fname);
8689 0 : goto out;
8690 : }
8691 :
8692 4 : num_eas = 0;
8693 4 : TALLOC_FREE(eas);
8694 :
8695 : /* Get the EA list on the symlink. Should return empty list. */
8696 4 : status = cli_get_ea_list_path(cli,
8697 : sname,
8698 : frame,
8699 : &num_eas,
8700 : &eas);
8701 :
8702 4 : if (!NT_STATUS_IS_OK(status)) {
8703 0 : printf("cli_get_ea_list_path failed (%s)\n",
8704 : nt_errstr(status));
8705 0 : goto out;
8706 : }
8707 :
8708 4 : if (num_eas != 0) {
8709 0 : printf("cli_get_ea_list_path failed (%s)\n",
8710 : nt_errstr(status));
8711 0 : goto out;
8712 : }
8713 :
8714 : /* Set an EA on the symlink. Should fail. */
8715 4 : status = cli_set_ea_path(cli,
8716 : sname,
8717 : ea_name,
8718 : ea_value,
8719 4 : strlen(ea_value)+1);
8720 :
8721 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8722 0 : printf("cli_set_ea_path on a symlink gave %s. "
8723 : "Should be NT_STATUS_ACCESS_DENIED.\n",
8724 : nt_errstr(status));
8725 0 : goto out;
8726 : }
8727 :
8728 4 : printf("EA symlink test passed\n");
8729 4 : correct = true;
8730 :
8731 4 : out:
8732 :
8733 4 : if (fnum != (uint16_t)-1) {
8734 0 : cli_close(cli, fnum);
8735 0 : fnum = (uint16_t)-1;
8736 : }
8737 :
8738 4 : cli_setatr(cli, sname, 0, 0);
8739 4 : cli_posix_unlink(cli, sname);
8740 4 : cli_setatr(cli, fname, 0, 0);
8741 4 : cli_posix_unlink(cli, fname);
8742 :
8743 4 : if (!torture_close_connection(cli)) {
8744 0 : correct = false;
8745 : }
8746 :
8747 4 : TALLOC_FREE(frame);
8748 4 : return correct;
8749 : }
8750 :
8751 : /*
8752 : Test POSIX locks are OFD-locks.
8753 : */
8754 4 : static bool run_posix_ofd_lock_test(int dummy)
8755 : {
8756 0 : static struct cli_state *cli;
8757 4 : const char *fname = "posix_file";
8758 4 : uint16_t fnum1 = (uint16_t)-1;
8759 4 : uint16_t fnum2 = (uint16_t)-1;
8760 4 : bool correct = false;
8761 0 : NTSTATUS status;
8762 4 : TALLOC_CTX *frame = NULL;
8763 :
8764 4 : frame = talloc_stackframe();
8765 :
8766 4 : printf("Starting POSIX ofd-lock test\n");
8767 :
8768 4 : if (!torture_open_connection(&cli, 0)) {
8769 0 : TALLOC_FREE(frame);
8770 0 : return false;
8771 : }
8772 :
8773 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
8774 :
8775 4 : status = torture_setup_unix_extensions(cli);
8776 4 : if (!NT_STATUS_IS_OK(status)) {
8777 0 : TALLOC_FREE(frame);
8778 0 : return false;
8779 : }
8780 :
8781 4 : cli_setatr(cli, fname, 0, 0);
8782 4 : cli_posix_unlink(cli, fname);
8783 :
8784 : /* Open the file twice. */
8785 4 : status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8786 : 0600, &fnum1);
8787 4 : if (!NT_STATUS_IS_OK(status)) {
8788 0 : printf("First POSIX open of %s failed\n", fname);
8789 0 : goto out;
8790 : }
8791 :
8792 4 : status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8793 4 : if (!NT_STATUS_IS_OK(status)) {
8794 0 : printf("First POSIX open of %s failed\n", fname);
8795 0 : goto out;
8796 : }
8797 :
8798 : /* Set a 0-50 lock on fnum1. */
8799 4 : status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8800 4 : if (!NT_STATUS_IS_OK(status)) {
8801 0 : printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8802 0 : goto out;
8803 : }
8804 :
8805 : /* Set a 60-100 lock on fnum2. */
8806 4 : status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8807 4 : if (!NT_STATUS_IS_OK(status)) {
8808 0 : printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8809 0 : goto out;
8810 : }
8811 :
8812 : /* close fnum1 - 0-50 lock should go away. */
8813 4 : status = cli_close(cli, fnum1);
8814 4 : if (!NT_STATUS_IS_OK(status)) {
8815 0 : printf("close failed (%s)\n",
8816 : nt_errstr(status));
8817 0 : goto out;
8818 : }
8819 4 : fnum1 = (uint16_t)-1;
8820 :
8821 : /* Change the lock context. */
8822 4 : cli_setpid(cli, cli_getpid(cli) + 1);
8823 :
8824 : /* Re-open fnum1. */
8825 4 : status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8826 4 : if (!NT_STATUS_IS_OK(status)) {
8827 0 : printf("Third POSIX open of %s failed\n", fname);
8828 0 : goto out;
8829 : }
8830 :
8831 : /* 60-100 lock should still be there. */
8832 4 : status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8833 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8834 0 : printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8835 0 : goto out;
8836 : }
8837 :
8838 : /* 0-50 lock should be gone. */
8839 4 : status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8840 4 : if (!NT_STATUS_IS_OK(status)) {
8841 0 : printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8842 0 : goto out;
8843 : }
8844 :
8845 4 : printf("POSIX OFD lock test passed\n");
8846 4 : correct = true;
8847 :
8848 4 : out:
8849 :
8850 4 : if (fnum1 != (uint16_t)-1) {
8851 4 : cli_close(cli, fnum1);
8852 4 : fnum1 = (uint16_t)-1;
8853 : }
8854 4 : if (fnum2 != (uint16_t)-1) {
8855 4 : cli_close(cli, fnum2);
8856 4 : fnum2 = (uint16_t)-1;
8857 : }
8858 :
8859 4 : cli_setatr(cli, fname, 0, 0);
8860 4 : cli_posix_unlink(cli, fname);
8861 :
8862 4 : if (!torture_close_connection(cli)) {
8863 0 : correct = false;
8864 : }
8865 :
8866 4 : TALLOC_FREE(frame);
8867 4 : return correct;
8868 : }
8869 :
8870 : struct posix_blocking_state {
8871 : struct tevent_context *ev;
8872 : struct cli_state *cli1;
8873 : uint16_t fnum1;
8874 : struct cli_state *cli2;
8875 : uint16_t fnum2;
8876 : bool gotblocked;
8877 : bool gotecho;
8878 : };
8879 :
8880 : static void posix_blocking_locked(struct tevent_req *subreq);
8881 : static void posix_blocking_gotblocked(struct tevent_req *subreq);
8882 : static void posix_blocking_gotecho(struct tevent_req *subreq);
8883 : static void posix_blocking_unlocked(struct tevent_req *subreq);
8884 :
8885 4 : static struct tevent_req *posix_blocking_send(
8886 : TALLOC_CTX *mem_ctx,
8887 : struct tevent_context *ev,
8888 : struct cli_state *cli1,
8889 : uint16_t fnum1,
8890 : struct cli_state *cli2,
8891 : uint16_t fnum2)
8892 : {
8893 4 : struct tevent_req *req = NULL, *subreq = NULL;
8894 4 : struct posix_blocking_state *state = NULL;
8895 :
8896 4 : req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8897 4 : if (req == NULL) {
8898 0 : return NULL;
8899 : }
8900 4 : state->ev = ev;
8901 4 : state->cli1 = cli1;
8902 4 : state->fnum1 = fnum1;
8903 4 : state->cli2 = cli2;
8904 4 : state->fnum2 = fnum2;
8905 :
8906 4 : subreq = cli_posix_lock_send(
8907 : state,
8908 4 : state->ev,
8909 4 : state->cli1,
8910 4 : state->fnum1,
8911 : 0,
8912 : 1,
8913 : false,
8914 : WRITE_LOCK);
8915 4 : if (tevent_req_nomem(subreq, req)) {
8916 0 : return tevent_req_post(req, ev);
8917 : }
8918 4 : tevent_req_set_callback(subreq, posix_blocking_locked, req);
8919 4 : return req;
8920 : }
8921 :
8922 4 : static void posix_blocking_locked(struct tevent_req *subreq)
8923 : {
8924 4 : struct tevent_req *req = tevent_req_callback_data(
8925 : subreq, struct tevent_req);
8926 4 : struct posix_blocking_state *state = tevent_req_data(
8927 : req, struct posix_blocking_state);
8928 0 : NTSTATUS status;
8929 :
8930 4 : status = cli_posix_lock_recv(subreq);
8931 4 : TALLOC_FREE(subreq);
8932 4 : if (tevent_req_nterror(req, status)) {
8933 0 : return;
8934 : }
8935 :
8936 4 : subreq = cli_posix_lock_send(
8937 : state,
8938 : state->ev,
8939 : state->cli2,
8940 4 : state->fnum2,
8941 : 0,
8942 : 1,
8943 : true,
8944 : WRITE_LOCK);
8945 4 : if (tevent_req_nomem(subreq, req)) {
8946 0 : return;
8947 : }
8948 4 : tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8949 :
8950 : /* Make sure the blocking request is delivered */
8951 4 : subreq = cli_echo_send(
8952 : state,
8953 : state->ev,
8954 : state->cli2,
8955 : 1,
8956 4 : (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8957 4 : if (tevent_req_nomem(subreq, req)) {
8958 0 : return;
8959 : }
8960 4 : tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8961 : }
8962 :
8963 4 : static void posix_blocking_gotblocked(struct tevent_req *subreq)
8964 : {
8965 4 : struct tevent_req *req = tevent_req_callback_data(
8966 : subreq, struct tevent_req);
8967 4 : struct posix_blocking_state *state = tevent_req_data(
8968 : req, struct posix_blocking_state);
8969 0 : NTSTATUS status;
8970 :
8971 4 : status = cli_posix_lock_recv(subreq);
8972 4 : TALLOC_FREE(subreq);
8973 4 : if (tevent_req_nterror(req, status)) {
8974 0 : return;
8975 : }
8976 4 : if (!state->gotecho) {
8977 0 : printf("blocked req got through before echo\n");
8978 0 : tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8979 0 : return;
8980 : }
8981 4 : tevent_req_done(req);
8982 : }
8983 :
8984 4 : static void posix_blocking_gotecho(struct tevent_req *subreq)
8985 : {
8986 4 : struct tevent_req *req = tevent_req_callback_data(
8987 : subreq, struct tevent_req);
8988 4 : struct posix_blocking_state *state = tevent_req_data(
8989 : req, struct posix_blocking_state);
8990 0 : NTSTATUS status;
8991 :
8992 4 : status = cli_echo_recv(subreq);
8993 4 : TALLOC_FREE(subreq);
8994 4 : if (tevent_req_nterror(req, status)) {
8995 0 : return;
8996 : }
8997 4 : if (state->gotblocked) {
8998 0 : printf("blocked req got through before echo\n");
8999 0 : tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
9000 0 : return;
9001 : }
9002 4 : state->gotecho = true;
9003 :
9004 4 : subreq = cli_posix_lock_send(
9005 : state,
9006 : state->ev,
9007 : state->cli1,
9008 4 : state->fnum1,
9009 : 0,
9010 : 1,
9011 : false,
9012 : UNLOCK_LOCK);
9013 4 : if (tevent_req_nomem(subreq, req)) {
9014 0 : return;
9015 : }
9016 4 : tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
9017 : }
9018 :
9019 4 : static void posix_blocking_unlocked(struct tevent_req *subreq)
9020 : {
9021 4 : struct tevent_req *req = tevent_req_callback_data(
9022 : subreq, struct tevent_req);
9023 0 : NTSTATUS status;
9024 :
9025 4 : status = cli_posix_lock_recv(subreq);
9026 4 : TALLOC_FREE(subreq);
9027 4 : if (tevent_req_nterror(req, status)) {
9028 0 : return;
9029 : }
9030 : /* tevent_req_done in posix_blocking_gotlocked */
9031 : }
9032 :
9033 4 : static NTSTATUS posix_blocking_recv(struct tevent_req *req)
9034 : {
9035 4 : return tevent_req_simple_recv_ntstatus(req);
9036 : }
9037 :
9038 4 : static bool run_posix_blocking_lock(int dummy)
9039 : {
9040 4 : struct tevent_context *ev = NULL;
9041 4 : struct cli_state *cli1 = NULL, *cli2 = NULL;
9042 4 : const char *fname = "posix_blocking";
9043 4 : uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
9044 4 : struct tevent_req *req = NULL;
9045 0 : NTSTATUS status;
9046 4 : bool ret = false;
9047 0 : bool ok;
9048 :
9049 4 : printf("Starting posix blocking lock test\n");
9050 :
9051 4 : ev = samba_tevent_context_init(NULL);
9052 4 : if (ev == NULL) {
9053 0 : return false;
9054 : }
9055 :
9056 4 : ok = torture_open_connection(&cli1, 0);
9057 4 : if (!ok) {
9058 0 : goto fail;
9059 : }
9060 4 : ok = torture_open_connection(&cli2, 0);
9061 4 : if (!ok) {
9062 0 : goto fail;
9063 : }
9064 :
9065 4 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
9066 :
9067 4 : status = torture_setup_unix_extensions(cli1);
9068 4 : if (!NT_STATUS_IS_OK(status)) {
9069 0 : return false;
9070 : }
9071 :
9072 4 : status = torture_setup_unix_extensions(cli2);
9073 4 : if (!NT_STATUS_IS_OK(status)) {
9074 0 : return false;
9075 : }
9076 :
9077 4 : cli_setatr(cli1, fname, 0, 0);
9078 4 : cli_posix_unlink(cli1, fname);
9079 :
9080 4 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
9081 : 0600, &fnum1);
9082 4 : if (!NT_STATUS_IS_OK(status)) {
9083 0 : printf("First POSIX open of %s failed: %s\n",
9084 : fname,
9085 : nt_errstr(status));
9086 0 : goto fail;
9087 : }
9088 :
9089 4 : status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
9090 4 : if (!NT_STATUS_IS_OK(status)) {
9091 0 : printf("Second POSIX open of %s failed: %s\n",
9092 : fname,
9093 : nt_errstr(status));
9094 0 : goto fail;
9095 : }
9096 :
9097 4 : req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9098 4 : if (req == NULL) {
9099 0 : printf("cli_posix_blocking failed\n");
9100 0 : goto fail;
9101 : }
9102 :
9103 4 : ok = tevent_req_poll_ntstatus(req, ev, &status);
9104 4 : if (!ok) {
9105 0 : printf("tevent_req_poll_ntstatus failed: %s\n",
9106 : nt_errstr(status));
9107 0 : goto fail;
9108 : }
9109 4 : status = posix_blocking_recv(req);
9110 4 : TALLOC_FREE(req);
9111 4 : if (!NT_STATUS_IS_OK(status)) {
9112 0 : printf("posix_blocking_recv returned %s\n",
9113 : nt_errstr(status));
9114 0 : goto fail;
9115 : }
9116 :
9117 4 : ret = true;
9118 4 : fail:
9119 :
9120 4 : if (fnum1 != UINT16_MAX) {
9121 4 : cli_close(cli1, fnum1);
9122 4 : fnum1 = UINT16_MAX;
9123 : }
9124 4 : if (fnum2 != UINT16_MAX) {
9125 4 : cli_close(cli2, fnum2);
9126 4 : fnum2 = UINT16_MAX;
9127 : }
9128 :
9129 4 : if (cli1 != NULL) {
9130 4 : cli_setatr(cli1, fname, 0, 0);
9131 4 : cli_posix_unlink(cli1, fname);
9132 : }
9133 :
9134 4 : ok = true;
9135 :
9136 4 : if (cli1 != NULL) {
9137 4 : ok &= torture_close_connection(cli1);
9138 4 : cli1 = NULL;
9139 : }
9140 4 : if (cli2 != NULL) {
9141 4 : ok &= torture_close_connection(cli2);
9142 4 : cli2 = NULL;
9143 : }
9144 :
9145 4 : if (!ok) {
9146 0 : ret = false;
9147 : }
9148 4 : TALLOC_FREE(ev);
9149 4 : return ret;
9150 : }
9151 :
9152 : /*
9153 : Test POSIX mkdir is case-sensitive.
9154 : */
9155 4 : static bool run_posix_mkdir_test(int dummy)
9156 : {
9157 0 : static struct cli_state *cli;
9158 4 : const char *fname_foo = "POSIX_foo";
9159 4 : const char *fname_foo_Foo = "POSIX_foo/Foo";
9160 4 : const char *fname_foo_foo = "POSIX_foo/foo";
9161 4 : const char *fname_Foo = "POSIX_Foo";
9162 4 : const char *fname_Foo_Foo = "POSIX_Foo/Foo";
9163 4 : const char *fname_Foo_foo = "POSIX_Foo/foo";
9164 4 : bool correct = false;
9165 0 : NTSTATUS status;
9166 4 : TALLOC_CTX *frame = NULL;
9167 4 : uint16_t fnum = (uint16_t)-1;
9168 :
9169 4 : frame = talloc_stackframe();
9170 :
9171 4 : printf("Starting POSIX mkdir test\n");
9172 :
9173 4 : if (!torture_open_connection(&cli, 0)) {
9174 0 : TALLOC_FREE(frame);
9175 0 : return false;
9176 : }
9177 :
9178 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
9179 :
9180 4 : status = torture_setup_unix_extensions(cli);
9181 4 : if (!NT_STATUS_IS_OK(status)) {
9182 0 : TALLOC_FREE(frame);
9183 0 : return false;
9184 : }
9185 :
9186 4 : cli_posix_rmdir(cli, fname_foo_foo);
9187 4 : cli_posix_rmdir(cli, fname_foo_Foo);
9188 4 : cli_posix_rmdir(cli, fname_foo);
9189 :
9190 4 : cli_posix_rmdir(cli, fname_Foo_foo);
9191 4 : cli_posix_rmdir(cli, fname_Foo_Foo);
9192 4 : cli_posix_rmdir(cli, fname_Foo);
9193 :
9194 : /*
9195 : * Create a file POSIX_foo then try
9196 : * and use it in a directory path by
9197 : * doing mkdir POSIX_foo/bar.
9198 : * The mkdir should fail with
9199 : * NT_STATUS_OBJECT_PATH_NOT_FOUND
9200 : */
9201 :
9202 4 : status = cli_posix_open(cli,
9203 : fname_foo,
9204 : O_RDWR|O_CREAT,
9205 : 0666,
9206 : &fnum);
9207 4 : if (!NT_STATUS_IS_OK(status)) {
9208 0 : printf("cli_posix_open of %s failed error %s\n",
9209 : fname_foo,
9210 : nt_errstr(status));
9211 0 : goto out;
9212 : }
9213 :
9214 4 : status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9215 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9216 0 : printf("cli_posix_mkdir of %s should fail with "
9217 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9218 : "%s instead\n",
9219 : fname_foo_foo,
9220 : nt_errstr(status));
9221 0 : goto out;
9222 : }
9223 :
9224 4 : status = cli_close(cli, fnum);
9225 4 : if (!NT_STATUS_IS_OK(status)) {
9226 0 : printf("cli_close failed %s\n", nt_errstr(status));
9227 0 : goto out;
9228 : }
9229 4 : fnum = (uint16_t)-1;
9230 :
9231 4 : status = cli_posix_unlink(cli, fname_foo);
9232 4 : if (!NT_STATUS_IS_OK(status)) {
9233 0 : printf("cli_posix_unlink of %s failed error %s\n",
9234 : fname_foo,
9235 : nt_errstr(status));
9236 0 : goto out;
9237 : }
9238 :
9239 : /*
9240 : * Now we've deleted everything, posix_mkdir, posix_rmdir,
9241 : * posix_open, posix_unlink, on
9242 : * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9243 : * not silently create POSIX_foo/foo.
9244 : */
9245 :
9246 4 : status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9247 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9248 0 : printf("cli_posix_mkdir of %s should fail with "
9249 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9250 : "%s instead\n",
9251 : fname_foo_foo,
9252 : nt_errstr(status));
9253 0 : goto out;
9254 : }
9255 :
9256 4 : status = cli_posix_rmdir(cli, fname_foo_foo);
9257 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9258 0 : printf("cli_posix_rmdir of %s should fail with "
9259 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9260 : "%s instead\n",
9261 : fname_foo_foo,
9262 : nt_errstr(status));
9263 0 : goto out;
9264 : }
9265 :
9266 4 : status = cli_posix_open(cli,
9267 : fname_foo_foo,
9268 : O_RDWR|O_CREAT,
9269 : 0666,
9270 : &fnum);
9271 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9272 0 : printf("cli_posix_open of %s should fail with "
9273 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9274 : "%s instead\n",
9275 : fname_foo_foo,
9276 : nt_errstr(status));
9277 0 : goto out;
9278 : }
9279 :
9280 4 : status = cli_posix_unlink(cli, fname_foo_foo);
9281 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9282 0 : printf("cli_posix_unlink of %s should fail with "
9283 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9284 : "%s instead\n",
9285 : fname_foo_foo,
9286 : nt_errstr(status));
9287 0 : goto out;
9288 : }
9289 :
9290 4 : status = cli_posix_mkdir(cli, fname_foo, 0777);
9291 4 : if (!NT_STATUS_IS_OK(status)) {
9292 0 : printf("cli_posix_mkdir of %s failed\n", fname_foo);
9293 0 : goto out;
9294 : }
9295 :
9296 4 : status = cli_posix_mkdir(cli, fname_Foo, 0777);
9297 4 : if (!NT_STATUS_IS_OK(status)) {
9298 0 : printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9299 0 : goto out;
9300 : }
9301 :
9302 4 : status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9303 4 : if (!NT_STATUS_IS_OK(status)) {
9304 0 : printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9305 0 : goto out;
9306 : }
9307 :
9308 4 : status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9309 4 : if (!NT_STATUS_IS_OK(status)) {
9310 0 : printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9311 0 : goto out;
9312 : }
9313 :
9314 4 : status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9315 4 : if (!NT_STATUS_IS_OK(status)) {
9316 0 : printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9317 0 : goto out;
9318 : }
9319 :
9320 4 : status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9321 4 : if (!NT_STATUS_IS_OK(status)) {
9322 0 : printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9323 0 : goto out;
9324 : }
9325 :
9326 4 : printf("POSIX mkdir test passed\n");
9327 4 : correct = true;
9328 :
9329 4 : out:
9330 :
9331 4 : if (fnum != (uint16_t)-1) {
9332 0 : cli_close(cli, fnum);
9333 0 : fnum = (uint16_t)-1;
9334 : }
9335 :
9336 4 : cli_posix_rmdir(cli, fname_foo_foo);
9337 4 : cli_posix_rmdir(cli, fname_foo_Foo);
9338 4 : cli_posix_rmdir(cli, fname_foo);
9339 :
9340 4 : cli_posix_rmdir(cli, fname_Foo_foo);
9341 4 : cli_posix_rmdir(cli, fname_Foo_Foo);
9342 4 : cli_posix_rmdir(cli, fname_Foo);
9343 :
9344 4 : if (!torture_close_connection(cli)) {
9345 0 : correct = false;
9346 : }
9347 :
9348 4 : TALLOC_FREE(frame);
9349 4 : return correct;
9350 : }
9351 :
9352 : struct posix_acl_oplock_state {
9353 : struct tevent_context *ev;
9354 : struct cli_state *cli;
9355 : bool *got_break;
9356 : bool *acl_ret;
9357 : NTSTATUS status;
9358 : };
9359 :
9360 4 : static void posix_acl_oplock_got_break(struct tevent_req *req)
9361 : {
9362 4 : struct posix_acl_oplock_state *state = tevent_req_callback_data(
9363 : req, struct posix_acl_oplock_state);
9364 0 : uint16_t fnum;
9365 0 : uint8_t level;
9366 0 : NTSTATUS status;
9367 :
9368 4 : status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9369 4 : TALLOC_FREE(req);
9370 4 : if (!NT_STATUS_IS_OK(status)) {
9371 0 : printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9372 : nt_errstr(status));
9373 0 : return;
9374 : }
9375 4 : *state->got_break = true;
9376 :
9377 4 : req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9378 : NO_OPLOCK);
9379 4 : if (req == NULL) {
9380 0 : printf("cli_oplock_ack_send failed\n");
9381 0 : return;
9382 : }
9383 : }
9384 :
9385 4 : static void posix_acl_oplock_got_acl(struct tevent_req *req)
9386 : {
9387 4 : struct posix_acl_oplock_state *state = tevent_req_callback_data(
9388 : req, struct posix_acl_oplock_state);
9389 4 : size_t ret_size = 0;
9390 4 : char *ret_data = NULL;
9391 :
9392 4 : state->status = cli_posix_getacl_recv(req,
9393 : state,
9394 : &ret_size,
9395 : &ret_data);
9396 :
9397 4 : if (!NT_STATUS_IS_OK(state->status)) {
9398 0 : printf("cli_posix_getacl_recv returned %s\n",
9399 : nt_errstr(state->status));
9400 : }
9401 4 : *state->acl_ret = true;
9402 4 : }
9403 :
9404 4 : static bool run_posix_acl_oplock_test(int dummy)
9405 : {
9406 0 : struct tevent_context *ev;
9407 0 : struct cli_state *cli1, *cli2;
9408 0 : struct tevent_req *oplock_req, *getacl_req;
9409 4 : const char *fname = "posix_acl_oplock";
9410 0 : uint16_t fnum;
9411 4 : int saved_use_oplocks = use_oplocks;
9412 0 : NTSTATUS status;
9413 4 : bool correct = true;
9414 4 : bool got_break = false;
9415 4 : bool acl_ret = false;
9416 :
9417 0 : struct posix_acl_oplock_state *state;
9418 :
9419 4 : printf("starting posix_acl_oplock test\n");
9420 :
9421 4 : if (!torture_open_connection(&cli1, 0)) {
9422 0 : use_level_II_oplocks = false;
9423 0 : use_oplocks = saved_use_oplocks;
9424 0 : return false;
9425 : }
9426 :
9427 4 : if (!torture_open_connection(&cli2, 1)) {
9428 0 : use_level_II_oplocks = false;
9429 0 : use_oplocks = saved_use_oplocks;
9430 0 : return false;
9431 : }
9432 :
9433 : /* Setup posix on cli2 only. */
9434 4 : status = torture_setup_unix_extensions(cli2);
9435 4 : if (!NT_STATUS_IS_OK(status)) {
9436 0 : return false;
9437 : }
9438 :
9439 4 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
9440 4 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
9441 :
9442 4 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9443 :
9444 : /* Create the file on the Windows connection. */
9445 4 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9446 : &fnum);
9447 4 : if (!NT_STATUS_IS_OK(status)) {
9448 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9449 0 : return false;
9450 : }
9451 :
9452 4 : status = cli_close(cli1, fnum);
9453 4 : if (!NT_STATUS_IS_OK(status)) {
9454 0 : printf("close1 failed (%s)\n", nt_errstr(status));
9455 0 : return false;
9456 : }
9457 :
9458 4 : cli1->use_oplocks = true;
9459 :
9460 : /* Open with oplock. */
9461 4 : status = cli_ntcreate(cli1,
9462 : fname,
9463 : 0,
9464 : FILE_READ_DATA,
9465 : FILE_ATTRIBUTE_NORMAL,
9466 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9467 : FILE_OPEN,
9468 : 0,
9469 : 0,
9470 : &fnum,
9471 : NULL);
9472 :
9473 4 : if (!NT_STATUS_IS_OK(status)) {
9474 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9475 0 : return false;
9476 : }
9477 :
9478 4 : ev = samba_tevent_context_init(talloc_tos());
9479 4 : if (ev == NULL) {
9480 0 : printf("tevent_context_init failed\n");
9481 0 : return false;
9482 : }
9483 :
9484 4 : state = talloc_zero(ev, struct posix_acl_oplock_state);
9485 4 : if (state == NULL) {
9486 0 : printf("talloc failed\n");
9487 0 : return false;
9488 : }
9489 4 : state->ev = ev;
9490 4 : state->cli = cli1;
9491 4 : state->got_break = &got_break;
9492 4 : state->acl_ret = &acl_ret;
9493 :
9494 4 : oplock_req = cli_smb_oplock_break_waiter_send(
9495 : talloc_tos(), ev, cli1);
9496 4 : if (oplock_req == NULL) {
9497 0 : printf("cli_smb_oplock_break_waiter_send failed\n");
9498 0 : return false;
9499 : }
9500 4 : tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9501 :
9502 : /* Get ACL on POSIX connection - should break oplock. */
9503 4 : getacl_req = cli_posix_getacl_send(talloc_tos(),
9504 : ev,
9505 : cli2,
9506 : fname);
9507 4 : if (getacl_req == NULL) {
9508 0 : printf("cli_posix_getacl_send failed\n");
9509 0 : return false;
9510 : }
9511 4 : tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9512 :
9513 36 : while (!got_break || !acl_ret) {
9514 0 : int ret;
9515 32 : ret = tevent_loop_once(ev);
9516 32 : if (ret == -1) {
9517 0 : printf("tevent_loop_once failed: %s\n",
9518 0 : strerror(errno));
9519 0 : return false;
9520 : }
9521 : }
9522 :
9523 4 : if (!NT_STATUS_IS_OK(state->status)) {
9524 0 : printf("getacl failed (%s)\n", nt_errstr(state->status));
9525 0 : correct = false;
9526 : }
9527 :
9528 4 : status = cli_close(cli1, fnum);
9529 4 : if (!NT_STATUS_IS_OK(status)) {
9530 0 : printf("close2 failed (%s)\n", nt_errstr(status));
9531 0 : correct = false;
9532 : }
9533 :
9534 4 : status = cli_unlink(cli1,
9535 : fname,
9536 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9537 4 : if (!NT_STATUS_IS_OK(status)) {
9538 0 : printf("unlink failed (%s)\n", nt_errstr(status));
9539 0 : correct = false;
9540 : }
9541 :
9542 4 : if (!torture_close_connection(cli1)) {
9543 0 : correct = false;
9544 : }
9545 4 : if (!torture_close_connection(cli2)) {
9546 0 : correct = false;
9547 : }
9548 :
9549 4 : if (!got_break) {
9550 0 : correct = false;
9551 : }
9552 :
9553 4 : printf("finished posix acl oplock test\n");
9554 :
9555 4 : return correct;
9556 : }
9557 :
9558 4 : static bool run_posix_acl_shareroot_test(int dummy)
9559 : {
9560 0 : struct cli_state *cli;
9561 0 : NTSTATUS status;
9562 4 : bool correct = false;
9563 4 : char *posix_acl = NULL;
9564 4 : size_t posix_acl_len = 0;
9565 4 : uint16_t num_file_acls = 0;
9566 4 : uint16_t num_dir_acls = 0;
9567 0 : uint16_t i;
9568 4 : uint32_t expected_size = 0;
9569 4 : bool got_user = false;
9570 4 : bool got_group = false;
9571 4 : bool got_other = false;
9572 4 : TALLOC_CTX *frame = NULL;
9573 :
9574 4 : frame = talloc_stackframe();
9575 :
9576 4 : printf("starting posix_acl_shareroot test\n");
9577 :
9578 4 : if (!torture_open_connection(&cli, 0)) {
9579 0 : TALLOC_FREE(frame);
9580 0 : return false;
9581 : }
9582 :
9583 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
9584 :
9585 4 : status = torture_setup_unix_extensions(cli);
9586 4 : if (!NT_STATUS_IS_OK(status)) {
9587 0 : printf("Failed to setup unix extensions\n");
9588 0 : goto out;
9589 : }
9590 :
9591 : /* Get the POSIX ACL on the root of the share. */
9592 4 : status = cli_posix_getacl(cli,
9593 : ".",
9594 : frame,
9595 : &posix_acl_len,
9596 : &posix_acl);
9597 :
9598 4 : if (!NT_STATUS_IS_OK(status)) {
9599 0 : printf("cli_posix_getacl of '.' failed (%s)\n",
9600 : nt_errstr(status));
9601 0 : goto out;
9602 : }
9603 :
9604 4 : if (posix_acl_len < 6 ||
9605 4 : SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9606 0 : printf("getfacl ., unknown POSIX acl version %u.\n",
9607 0 : (unsigned int)CVAL(posix_acl,0) );
9608 0 : goto out;
9609 : }
9610 :
9611 4 : num_file_acls = SVAL(posix_acl,2);
9612 4 : num_dir_acls = SVAL(posix_acl,4);
9613 4 : expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9614 4 : SMB_POSIX_ACL_ENTRY_SIZE*
9615 4 : (num_file_acls+num_dir_acls);
9616 :
9617 4 : if (posix_acl_len != expected_size) {
9618 0 : printf("incorrect POSIX acl buffer size "
9619 : "(should be %u, was %u).\n",
9620 : (unsigned int)expected_size,
9621 : (unsigned int)posix_acl_len);
9622 0 : goto out;
9623 : }
9624 :
9625 : /*
9626 : * We don't need to know what the ACL's are
9627 : * we just need to know we have at least 3
9628 : * file entries (u,g,o).
9629 : */
9630 :
9631 16 : for (i = 0; i < num_file_acls; i++) {
9632 12 : unsigned char tagtype =
9633 12 : CVAL(posix_acl,
9634 : SMB_POSIX_ACL_HEADER_SIZE+
9635 : (i*SMB_POSIX_ACL_ENTRY_SIZE));
9636 :
9637 12 : switch(tagtype) {
9638 4 : case SMB_POSIX_ACL_USER_OBJ:
9639 4 : got_user = true;
9640 4 : break;
9641 4 : case SMB_POSIX_ACL_GROUP_OBJ:
9642 4 : got_group = true;
9643 4 : break;
9644 4 : case SMB_POSIX_ACL_OTHER:
9645 4 : got_other = true;
9646 4 : break;
9647 0 : default:
9648 0 : break;
9649 : }
9650 : }
9651 :
9652 4 : if (!got_user) {
9653 0 : printf("Missing user entry\n");
9654 0 : goto out;
9655 : }
9656 :
9657 4 : if (!got_group) {
9658 0 : printf("Missing group entry\n");
9659 0 : goto out;
9660 : }
9661 :
9662 4 : if (!got_other) {
9663 0 : printf("Missing other entry\n");
9664 0 : goto out;
9665 : }
9666 :
9667 4 : correct = true;
9668 :
9669 4 : out:
9670 :
9671 4 : if (!torture_close_connection(cli)) {
9672 0 : correct = false;
9673 : }
9674 :
9675 4 : printf("finished posix acl shareroot test\n");
9676 4 : TALLOC_FREE(frame);
9677 :
9678 4 : return correct;
9679 : }
9680 :
9681 : static uint32_t open_attrs_table[] = {
9682 : FILE_ATTRIBUTE_NORMAL,
9683 : FILE_ATTRIBUTE_ARCHIVE,
9684 : FILE_ATTRIBUTE_READONLY,
9685 : FILE_ATTRIBUTE_HIDDEN,
9686 : FILE_ATTRIBUTE_SYSTEM,
9687 :
9688 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9689 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9690 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9691 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9692 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9693 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9694 :
9695 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9696 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9697 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9698 : FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9699 : };
9700 :
9701 : struct trunc_open_results {
9702 : unsigned int num;
9703 : uint32_t init_attr;
9704 : uint32_t trunc_attr;
9705 : uint32_t result_attr;
9706 : };
9707 :
9708 : static struct trunc_open_results attr_results[] = {
9709 : { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9710 : { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9711 : { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9712 : { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9713 : { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9714 : { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9715 : { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9716 : { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9717 : { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9718 : { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9719 : { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9720 : { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9721 : { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9722 : { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9723 : { 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 },
9724 : { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9725 : { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9726 : { 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 },
9727 : { 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 },
9728 : { 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 },
9729 : { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9730 : { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9731 : { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9732 : { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9733 : { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9734 : { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9735 : };
9736 :
9737 0 : static bool run_openattrtest(int dummy)
9738 : {
9739 0 : static struct cli_state *cli1;
9740 0 : const char *fname = "\\openattr.file";
9741 0 : uint16_t fnum1;
9742 0 : bool correct = True;
9743 0 : uint32_t attr;
9744 0 : unsigned int i, j, k, l;
9745 0 : NTSTATUS status;
9746 :
9747 0 : printf("starting open attr test\n");
9748 :
9749 0 : if (!torture_open_connection(&cli1, 0)) {
9750 0 : return False;
9751 : }
9752 :
9753 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
9754 :
9755 0 : for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9756 0 : cli_setatr(cli1, fname, 0, 0);
9757 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9758 :
9759 0 : status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9760 : open_attrs_table[i], FILE_SHARE_NONE,
9761 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9762 0 : if (!NT_STATUS_IS_OK(status)) {
9763 0 : printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9764 0 : return False;
9765 : }
9766 :
9767 0 : status = cli_close(cli1, fnum1);
9768 0 : if (!NT_STATUS_IS_OK(status)) {
9769 0 : printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9770 0 : return False;
9771 : }
9772 :
9773 0 : for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9774 0 : status = cli_ntcreate(cli1, fname, 0,
9775 : FILE_READ_DATA|FILE_WRITE_DATA,
9776 : open_attrs_table[j],
9777 : FILE_SHARE_NONE, FILE_OVERWRITE,
9778 : 0, 0, &fnum1, NULL);
9779 0 : if (!NT_STATUS_IS_OK(status)) {
9780 0 : for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9781 0 : if (attr_results[l].num == k) {
9782 0 : printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9783 : k, open_attrs_table[i],
9784 : open_attrs_table[j],
9785 : fname, NT_STATUS_V(status), nt_errstr(status));
9786 0 : correct = False;
9787 : }
9788 : }
9789 :
9790 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9791 0 : printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9792 : k, open_attrs_table[i], open_attrs_table[j],
9793 : nt_errstr(status));
9794 0 : correct = False;
9795 : }
9796 : #if 0
9797 : printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9798 : #endif
9799 0 : k++;
9800 0 : continue;
9801 : }
9802 :
9803 0 : status = cli_close(cli1, fnum1);
9804 0 : if (!NT_STATUS_IS_OK(status)) {
9805 0 : printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9806 0 : return False;
9807 : }
9808 :
9809 0 : status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9810 0 : if (!NT_STATUS_IS_OK(status)) {
9811 0 : printf("getatr(2) failed (%s)\n", nt_errstr(status));
9812 0 : return False;
9813 : }
9814 :
9815 : #if 0
9816 : printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9817 : k, open_attrs_table[i], open_attrs_table[j], attr );
9818 : #endif
9819 :
9820 0 : for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9821 0 : if (attr_results[l].num == k) {
9822 0 : if (attr != attr_results[l].result_attr ||
9823 0 : open_attrs_table[i] != attr_results[l].init_attr ||
9824 0 : open_attrs_table[j] != attr_results[l].trunc_attr) {
9825 0 : printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9826 : open_attrs_table[i],
9827 : open_attrs_table[j],
9828 : (unsigned int)attr,
9829 : attr_results[l].result_attr);
9830 0 : correct = False;
9831 : }
9832 0 : break;
9833 : }
9834 : }
9835 0 : k++;
9836 : }
9837 : }
9838 :
9839 0 : cli_setatr(cli1, fname, 0, 0);
9840 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9841 :
9842 0 : printf("open attr test %s.\n", correct ? "passed" : "failed");
9843 :
9844 0 : if (!torture_close_connection(cli1)) {
9845 0 : correct = False;
9846 : }
9847 0 : return correct;
9848 : }
9849 :
9850 0 : static NTSTATUS list_fn(struct file_info *finfo,
9851 : const char *name, void *state)
9852 : {
9853 0 : int *matched = (int *)state;
9854 0 : if (matched != NULL) {
9855 0 : *matched += 1;
9856 : }
9857 0 : return NT_STATUS_OK;
9858 : }
9859 :
9860 : /*
9861 : test directory listing speed
9862 : */
9863 5 : static bool run_dirtest(int dummy)
9864 : {
9865 0 : int i;
9866 0 : static struct cli_state *cli;
9867 0 : uint16_t fnum;
9868 0 : struct timeval core_start;
9869 5 : bool correct = True;
9870 0 : int matched;
9871 :
9872 5 : printf("starting directory test\n");
9873 :
9874 5 : if (!torture_open_connection(&cli, 0)) {
9875 0 : return False;
9876 : }
9877 :
9878 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
9879 :
9880 5 : srandom(0);
9881 505 : for (i=0;i<torture_numops;i++) {
9882 0 : fstring fname;
9883 500 : slprintf(fname, sizeof(fname), "\\%x", (int)random());
9884 500 : if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9885 0 : fprintf(stderr,"Failed to open %s\n", fname);
9886 0 : return False;
9887 : }
9888 500 : cli_close(cli, fnum);
9889 : }
9890 :
9891 5 : core_start = timeval_current();
9892 :
9893 5 : matched = 0;
9894 5 : cli_list(cli, "a*.*", 0, list_fn, &matched);
9895 5 : printf("Matched %d\n", matched);
9896 :
9897 5 : matched = 0;
9898 5 : cli_list(cli, "b*.*", 0, list_fn, &matched);
9899 5 : printf("Matched %d\n", matched);
9900 :
9901 5 : matched = 0;
9902 5 : cli_list(cli, "xyzabc", 0, list_fn, &matched);
9903 5 : printf("Matched %d\n", matched);
9904 :
9905 5 : printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9906 :
9907 5 : srandom(0);
9908 505 : for (i=0;i<torture_numops;i++) {
9909 0 : fstring fname;
9910 500 : slprintf(fname, sizeof(fname), "\\%x", (int)random());
9911 500 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9912 : }
9913 :
9914 5 : if (!torture_close_connection(cli)) {
9915 0 : correct = False;
9916 : }
9917 :
9918 5 : printf("finished dirtest\n");
9919 :
9920 5 : return correct;
9921 : }
9922 :
9923 0 : static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9924 : void *state)
9925 : {
9926 0 : struct cli_state *pcli = (struct cli_state *)state;
9927 0 : fstring fname;
9928 0 : slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9929 :
9930 0 : if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9931 0 : return NT_STATUS_OK;
9932 :
9933 0 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9934 0 : if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9935 0 : printf("del_fn: failed to rmdir %s\n,", fname );
9936 : } else {
9937 0 : if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9938 0 : printf("del_fn: failed to unlink %s\n,", fname );
9939 : }
9940 0 : return NT_STATUS_OK;
9941 : }
9942 :
9943 :
9944 : /*
9945 : send a raw ioctl - used by the torture code
9946 : */
9947 327690 : static NTSTATUS cli_raw_ioctl(struct cli_state *cli,
9948 : uint16_t fnum,
9949 : uint32_t code,
9950 : DATA_BLOB *blob)
9951 : {
9952 0 : uint16_t vwv[3];
9953 0 : NTSTATUS status;
9954 :
9955 327690 : PUSH_LE_U16(vwv + 0, 0, fnum);
9956 327690 : PUSH_LE_U16(vwv + 1, 0, code >> 16);
9957 327690 : PUSH_LE_U16(vwv + 2, 0, (code & 0xFFFF));
9958 :
9959 327690 : status = cli_smb(talloc_tos(),
9960 : cli,
9961 : SMBioctl,
9962 : 0,
9963 : 3,
9964 : vwv,
9965 : 0,
9966 : NULL,
9967 : NULL,
9968 : 0,
9969 : NULL,
9970 : NULL,
9971 : NULL,
9972 : NULL);
9973 327690 : if (!NT_STATUS_IS_OK(status)) {
9974 327682 : return status;
9975 : }
9976 8 : *blob = data_blob_null;
9977 8 : return NT_STATUS_OK;
9978 : }
9979 :
9980 : /*
9981 : sees what IOCTLs are supported
9982 : */
9983 5 : bool torture_ioctl_test(int dummy)
9984 : {
9985 0 : static struct cli_state *cli;
9986 0 : uint16_t device, function;
9987 0 : uint16_t fnum;
9988 5 : const char *fname = "\\ioctl.dat";
9989 0 : DATA_BLOB blob;
9990 0 : NTSTATUS status;
9991 :
9992 5 : if (!torture_open_connection(&cli, 0)) {
9993 0 : return False;
9994 : }
9995 :
9996 5 : printf("starting ioctl test\n");
9997 :
9998 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9999 :
10000 5 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
10001 5 : if (!NT_STATUS_IS_OK(status)) {
10002 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
10003 0 : return False;
10004 : }
10005 :
10006 5 : status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
10007 5 : printf("ioctl device info: %s\n", nt_errstr(status));
10008 :
10009 5 : status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
10010 5 : printf("ioctl job info: %s\n", nt_errstr(status));
10011 :
10012 1285 : for (device=0;device<0x100;device++) {
10013 1280 : printf("ioctl test with device = 0x%x\n", device);
10014 328960 : for (function=0;function<0x100;function++) {
10015 327680 : uint32_t code = (device<<16) | function;
10016 :
10017 327680 : status = cli_raw_ioctl(cli, fnum, code, &blob);
10018 :
10019 327680 : if (NT_STATUS_IS_OK(status)) {
10020 4 : printf("ioctl 0x%x OK : %d bytes\n", (int)code,
10021 4 : (int)blob.length);
10022 4 : data_blob_free(&blob);
10023 : }
10024 : }
10025 : }
10026 :
10027 5 : if (!torture_close_connection(cli)) {
10028 0 : return False;
10029 : }
10030 :
10031 5 : return True;
10032 : }
10033 :
10034 :
10035 : /*
10036 : tries variants of chkpath
10037 : */
10038 5 : bool torture_chkpath_test(int dummy)
10039 : {
10040 0 : static struct cli_state *cli;
10041 0 : uint16_t fnum;
10042 0 : bool ret;
10043 0 : NTSTATUS status;
10044 :
10045 5 : if (!torture_open_connection(&cli, 0)) {
10046 0 : return False;
10047 : }
10048 :
10049 5 : printf("starting chkpath test\n");
10050 :
10051 : /* cleanup from an old run */
10052 5 : torture_deltree(cli, "\\chkpath.dir");
10053 :
10054 5 : status = cli_mkdir(cli, "\\chkpath.dir");
10055 5 : if (!NT_STATUS_IS_OK(status)) {
10056 0 : printf("mkdir1 failed : %s\n", nt_errstr(status));
10057 0 : return False;
10058 : }
10059 :
10060 5 : status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
10061 5 : if (!NT_STATUS_IS_OK(status)) {
10062 0 : printf("mkdir2 failed : %s\n", nt_errstr(status));
10063 0 : return False;
10064 : }
10065 :
10066 5 : status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
10067 : DENY_NONE, &fnum);
10068 5 : if (!NT_STATUS_IS_OK(status)) {
10069 0 : printf("open1 failed (%s)\n", nt_errstr(status));
10070 0 : return False;
10071 : }
10072 5 : cli_close(cli, fnum);
10073 :
10074 5 : status = cli_chkpath(cli, "\\chkpath.dir");
10075 5 : if (!NT_STATUS_IS_OK(status)) {
10076 0 : printf("chkpath1 failed: %s\n", nt_errstr(status));
10077 0 : ret = False;
10078 : }
10079 :
10080 5 : status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
10081 5 : if (!NT_STATUS_IS_OK(status)) {
10082 0 : printf("chkpath2 failed: %s\n", nt_errstr(status));
10083 0 : ret = False;
10084 : }
10085 :
10086 5 : status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
10087 5 : if (!NT_STATUS_IS_OK(status)) {
10088 5 : ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10089 5 : NT_STATUS_NOT_A_DIRECTORY);
10090 : } else {
10091 0 : printf("* chkpath on a file should fail\n");
10092 0 : ret = False;
10093 : }
10094 :
10095 5 : status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
10096 5 : if (!NT_STATUS_IS_OK(status)) {
10097 5 : ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
10098 5 : NT_STATUS_OBJECT_NAME_NOT_FOUND);
10099 : } else {
10100 0 : printf("* chkpath on a non existent file should fail\n");
10101 0 : ret = False;
10102 : }
10103 :
10104 5 : status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
10105 5 : if (!NT_STATUS_IS_OK(status)) {
10106 5 : ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10107 5 : NT_STATUS_OBJECT_PATH_NOT_FOUND);
10108 : } else {
10109 0 : printf("* chkpath on a non existent component should fail\n");
10110 0 : ret = False;
10111 : }
10112 :
10113 5 : torture_deltree(cli, "\\chkpath.dir");
10114 :
10115 5 : if (!torture_close_connection(cli)) {
10116 0 : return False;
10117 : }
10118 :
10119 5 : return ret;
10120 : }
10121 :
10122 0 : static bool run_eatest(int dummy)
10123 : {
10124 0 : static struct cli_state *cli;
10125 0 : const char *fname = "\\eatest.txt";
10126 0 : bool correct = True;
10127 0 : uint16_t fnum;
10128 0 : size_t i, num_eas;
10129 0 : struct ea_struct *ea_list = NULL;
10130 0 : TALLOC_CTX *mem_ctx = talloc_init("eatest");
10131 0 : NTSTATUS status;
10132 :
10133 0 : printf("starting eatest\n");
10134 :
10135 0 : if (!torture_open_connection(&cli, 0)) {
10136 0 : talloc_destroy(mem_ctx);
10137 0 : return False;
10138 : }
10139 :
10140 0 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10141 :
10142 0 : status = cli_ntcreate(cli, fname, 0,
10143 : FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10144 : FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10145 : 0x4044, 0, &fnum, NULL);
10146 0 : if (!NT_STATUS_IS_OK(status)) {
10147 0 : printf("open failed - %s\n", nt_errstr(status));
10148 0 : talloc_destroy(mem_ctx);
10149 0 : return False;
10150 : }
10151 :
10152 0 : for (i = 0; i < 10; i++) {
10153 0 : fstring ea_name, ea_val;
10154 :
10155 0 : slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10156 0 : memset(ea_val, (char)i+1, i+1);
10157 0 : status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10158 0 : if (!NT_STATUS_IS_OK(status)) {
10159 0 : printf("ea_set of name %s failed - %s\n", ea_name,
10160 : nt_errstr(status));
10161 0 : talloc_destroy(mem_ctx);
10162 0 : return False;
10163 : }
10164 : }
10165 :
10166 0 : cli_close(cli, fnum);
10167 0 : for (i = 0; i < 10; i++) {
10168 0 : fstring ea_name, ea_val;
10169 :
10170 0 : slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10171 0 : memset(ea_val, (char)i+1, i+1);
10172 0 : status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10173 0 : if (!NT_STATUS_IS_OK(status)) {
10174 0 : printf("ea_set of name %s failed - %s\n", ea_name,
10175 : nt_errstr(status));
10176 0 : talloc_destroy(mem_ctx);
10177 0 : return False;
10178 : }
10179 : }
10180 :
10181 0 : status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10182 0 : if (!NT_STATUS_IS_OK(status)) {
10183 0 : printf("ea_get list failed - %s\n", nt_errstr(status));
10184 0 : correct = False;
10185 : }
10186 :
10187 0 : printf("num_eas = %d\n", (int)num_eas);
10188 :
10189 0 : if (num_eas != 20) {
10190 0 : printf("Should be 20 EA's stored... failing.\n");
10191 0 : correct = False;
10192 : }
10193 :
10194 0 : for (i = 0; i < num_eas; i++) {
10195 0 : printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10196 0 : dump_data(0, ea_list[i].value.data,
10197 0 : ea_list[i].value.length);
10198 : }
10199 :
10200 : /* Setting EA's to zero length deletes them. Test this */
10201 0 : printf("Now deleting all EA's - case independent....\n");
10202 :
10203 : #if 1
10204 0 : cli_set_ea_path(cli, fname, "", "", 0);
10205 : #else
10206 : for (i = 0; i < 20; i++) {
10207 : fstring ea_name;
10208 : slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10209 : status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10210 : if (!NT_STATUS_IS_OK(status)) {
10211 : printf("ea_set of name %s failed - %s\n", ea_name,
10212 : nt_errstr(status));
10213 : talloc_destroy(mem_ctx);
10214 : return False;
10215 : }
10216 : }
10217 : #endif
10218 :
10219 0 : status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10220 0 : if (!NT_STATUS_IS_OK(status)) {
10221 0 : printf("ea_get list failed - %s\n", nt_errstr(status));
10222 0 : correct = False;
10223 : }
10224 :
10225 0 : printf("num_eas = %d\n", (int)num_eas);
10226 0 : for (i = 0; i < num_eas; i++) {
10227 0 : printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10228 0 : dump_data(0, ea_list[i].value.data,
10229 0 : ea_list[i].value.length);
10230 : }
10231 :
10232 0 : if (num_eas != 0) {
10233 0 : printf("deleting EA's failed.\n");
10234 0 : correct = False;
10235 : }
10236 :
10237 : /* Try and delete a non existent EA. */
10238 0 : status = cli_set_ea_path(cli, fname, "foo", "", 0);
10239 0 : if (!NT_STATUS_IS_OK(status)) {
10240 0 : printf("deleting non-existent EA 'foo' should succeed. %s\n",
10241 : nt_errstr(status));
10242 0 : correct = False;
10243 : }
10244 :
10245 0 : talloc_destroy(mem_ctx);
10246 0 : if (!torture_close_connection(cli)) {
10247 0 : correct = False;
10248 : }
10249 :
10250 0 : return correct;
10251 : }
10252 :
10253 0 : static bool run_dirtest1(int dummy)
10254 : {
10255 0 : int i;
10256 0 : static struct cli_state *cli;
10257 0 : uint16_t fnum;
10258 0 : int num_seen;
10259 0 : bool correct = True;
10260 :
10261 0 : printf("starting directory test\n");
10262 :
10263 0 : if (!torture_open_connection(&cli, 0)) {
10264 0 : return False;
10265 : }
10266 :
10267 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
10268 :
10269 0 : cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10270 0 : cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10271 0 : cli_rmdir(cli, "\\LISTDIR");
10272 0 : cli_mkdir(cli, "\\LISTDIR");
10273 :
10274 : /* Create 1000 files and 1000 directories. */
10275 0 : for (i=0;i<1000;i++) {
10276 0 : fstring fname;
10277 0 : slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10278 0 : if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10279 : FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10280 : 0, 0, &fnum, NULL))) {
10281 0 : fprintf(stderr,"Failed to open %s\n", fname);
10282 0 : return False;
10283 : }
10284 0 : cli_close(cli, fnum);
10285 : }
10286 0 : for (i=0;i<1000;i++) {
10287 0 : fstring fname;
10288 0 : slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10289 0 : if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10290 0 : fprintf(stderr,"Failed to open %s\n", fname);
10291 0 : return False;
10292 : }
10293 : }
10294 :
10295 : /* Now ensure that doing an old list sees both files and directories. */
10296 0 : num_seen = 0;
10297 0 : cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10298 0 : printf("num_seen = %d\n", num_seen );
10299 : /* We should see 100 files + 1000 directories + . and .. */
10300 0 : if (num_seen != 2002)
10301 0 : correct = False;
10302 :
10303 : /* Ensure if we have the "must have" bits we only see the
10304 : * relevant entries.
10305 : */
10306 0 : num_seen = 0;
10307 0 : cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10308 0 : printf("num_seen = %d\n", num_seen );
10309 0 : if (num_seen != 1002)
10310 0 : correct = False;
10311 :
10312 0 : num_seen = 0;
10313 0 : cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10314 0 : printf("num_seen = %d\n", num_seen );
10315 0 : if (num_seen != 1000)
10316 0 : correct = False;
10317 :
10318 : /* Delete everything. */
10319 0 : cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10320 0 : cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10321 0 : cli_rmdir(cli, "\\LISTDIR");
10322 :
10323 : #if 0
10324 : printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10325 : printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10326 : printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10327 : #endif
10328 :
10329 0 : if (!torture_close_connection(cli)) {
10330 0 : correct = False;
10331 : }
10332 :
10333 0 : printf("finished dirtest1\n");
10334 :
10335 0 : return correct;
10336 : }
10337 :
10338 0 : static bool run_error_map_extract(int dummy) {
10339 :
10340 0 : static struct cli_state *c_dos;
10341 0 : static struct cli_state *c_nt;
10342 0 : NTSTATUS status;
10343 :
10344 0 : uint32_t error;
10345 :
10346 0 : uint32_t errnum;
10347 0 : uint8_t errclass;
10348 :
10349 0 : NTSTATUS nt_status;
10350 :
10351 0 : fstring user;
10352 :
10353 : /* NT-Error connection */
10354 :
10355 0 : disable_spnego = true;
10356 0 : if (!(c_nt = open_nbt_connection())) {
10357 0 : disable_spnego = false;
10358 0 : return False;
10359 : }
10360 0 : disable_spnego = false;
10361 :
10362 0 : status = smbXcli_negprot(c_nt->conn,
10363 0 : c_nt->timeout,
10364 : PROTOCOL_CORE,
10365 : PROTOCOL_NT1,
10366 : NULL,
10367 : NULL,
10368 : NULL);
10369 :
10370 0 : if (!NT_STATUS_IS_OK(status)) {
10371 0 : printf("%s rejected the NT-error negprot (%s)\n", host,
10372 : nt_errstr(status));
10373 0 : cli_shutdown(c_nt);
10374 0 : return False;
10375 : }
10376 :
10377 0 : status = cli_session_setup_anon(c_nt);
10378 0 : if (!NT_STATUS_IS_OK(status)) {
10379 0 : printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10380 0 : return False;
10381 : }
10382 :
10383 : /* DOS-Error connection */
10384 :
10385 0 : disable_spnego = true;
10386 0 : force_dos_errors = true;
10387 0 : if (!(c_dos = open_nbt_connection())) {
10388 0 : disable_spnego = false;
10389 0 : force_dos_errors = false;
10390 0 : return False;
10391 : }
10392 0 : disable_spnego = false;
10393 0 : force_dos_errors = false;
10394 :
10395 0 : status = smbXcli_negprot(c_dos->conn,
10396 0 : c_dos->timeout,
10397 : PROTOCOL_CORE,
10398 : PROTOCOL_NT1,
10399 : NULL,
10400 : NULL,
10401 : NULL);
10402 0 : if (!NT_STATUS_IS_OK(status)) {
10403 0 : printf("%s rejected the DOS-error negprot (%s)\n", host,
10404 : nt_errstr(status));
10405 0 : cli_shutdown(c_dos);
10406 0 : return False;
10407 : }
10408 :
10409 0 : status = cli_session_setup_anon(c_dos);
10410 0 : if (!NT_STATUS_IS_OK(status)) {
10411 0 : printf("%s rejected the DOS-error initial session setup (%s)\n",
10412 : host, nt_errstr(status));
10413 0 : return False;
10414 : }
10415 :
10416 0 : c_nt->map_dos_errors = false;
10417 0 : c_dos->map_dos_errors = false;
10418 :
10419 0 : for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10420 0 : struct cli_credentials *user_creds = NULL;
10421 :
10422 0 : fstr_sprintf(user, "%X", error);
10423 :
10424 0 : user_creds = cli_session_creds_init(talloc_tos(),
10425 : user,
10426 : workgroup,
10427 : NULL, /* realm */
10428 : password,
10429 : false, /* use_kerberos */
10430 : false, /* fallback_after_kerberos */
10431 : false, /* use_ccache */
10432 : false); /* password_is_nt_hash */
10433 0 : if (user_creds == NULL) {
10434 0 : printf("cli_session_creds_init(%s) failed\n", user);
10435 0 : return false;
10436 : }
10437 :
10438 0 : status = cli_session_setup_creds(c_nt, user_creds);
10439 0 : if (NT_STATUS_IS_OK(status)) {
10440 0 : printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10441 : }
10442 :
10443 : /* Case #1: 32-bit NT errors */
10444 0 : if (!NT_STATUS_IS_DOS(status)) {
10445 0 : nt_status = status;
10446 : } else {
10447 0 : printf("/** Dos error on NT connection! (%s) */\n",
10448 : nt_errstr(status));
10449 0 : nt_status = NT_STATUS(0xc0000000);
10450 : }
10451 :
10452 0 : status = cli_session_setup_creds(c_dos, user_creds);
10453 0 : if (NT_STATUS_IS_OK(status)) {
10454 0 : printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10455 : }
10456 :
10457 : /* Case #1: 32-bit NT errors */
10458 0 : if (NT_STATUS_IS_DOS(status)) {
10459 0 : printf("/** NT error on DOS connection! (%s) */\n",
10460 : nt_errstr(status));
10461 0 : errnum = errclass = 0;
10462 : } else {
10463 0 : errclass = NT_STATUS_DOS_CLASS(status);
10464 0 : errnum = NT_STATUS_DOS_CODE(status);
10465 : }
10466 :
10467 0 : if (NT_STATUS_V(nt_status) != error) {
10468 0 : printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10469 0 : get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
10470 0 : get_nt_error_c_code(talloc_tos(), nt_status));
10471 : }
10472 :
10473 0 : printf("\t{%s,\t%s,\t%s},\n",
10474 : smb_dos_err_class(errclass),
10475 : smb_dos_err_name(errclass, errnum),
10476 0 : get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10477 :
10478 0 : TALLOC_FREE(user_creds);
10479 : }
10480 0 : return True;
10481 : }
10482 :
10483 0 : static bool run_sesssetup_bench(int dummy)
10484 : {
10485 0 : static struct cli_state *c;
10486 0 : const char *fname = "\\file.dat";
10487 0 : uint16_t fnum;
10488 0 : NTSTATUS status;
10489 0 : int i;
10490 :
10491 0 : if (!torture_open_connection(&c, 0)) {
10492 0 : return false;
10493 : }
10494 :
10495 0 : status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10496 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10497 : FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10498 0 : if (!NT_STATUS_IS_OK(status)) {
10499 0 : d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10500 0 : return false;
10501 : }
10502 :
10503 0 : for (i=0; i<torture_numops; i++) {
10504 0 : status = cli_session_setup_creds(c, torture_creds);
10505 0 : if (!NT_STATUS_IS_OK(status)) {
10506 0 : d_printf("(%s) cli_session_setup_creds failed: %s\n",
10507 : __location__, nt_errstr(status));
10508 0 : return false;
10509 : }
10510 :
10511 0 : d_printf("\r%d ", (int)cli_state_get_uid(c));
10512 :
10513 0 : status = cli_ulogoff(c);
10514 0 : if (!NT_STATUS_IS_OK(status)) {
10515 0 : d_printf("(%s) cli_ulogoff failed: %s\n",
10516 : __location__, nt_errstr(status));
10517 0 : return false;
10518 : }
10519 : }
10520 :
10521 0 : return true;
10522 : }
10523 :
10524 9 : static bool subst_test(const char *str, const char *user, const char *domain,
10525 : uid_t uid, gid_t gid, const char *expected)
10526 : {
10527 9 : char *subst;
10528 9 : bool result = true;
10529 :
10530 9 : subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10531 :
10532 9 : if (strcmp(subst, expected) != 0) {
10533 0 : printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10534 : "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10535 : expected);
10536 0 : result = false;
10537 : }
10538 :
10539 9 : TALLOC_FREE(subst);
10540 9 : return result;
10541 : }
10542 :
10543 5 : static void chain1_open_completion(struct tevent_req *req)
10544 : {
10545 0 : uint16_t fnum;
10546 0 : NTSTATUS status;
10547 5 : status = cli_openx_recv(req, &fnum);
10548 5 : TALLOC_FREE(req);
10549 :
10550 5 : d_printf("cli_openx_recv returned %s: %d\n",
10551 : nt_errstr(status),
10552 5 : NT_STATUS_IS_OK(status) ? fnum : -1);
10553 5 : }
10554 :
10555 5 : static void chain1_write_completion(struct tevent_req *req)
10556 : {
10557 0 : size_t written;
10558 0 : NTSTATUS status;
10559 5 : status = cli_write_andx_recv(req, &written);
10560 5 : TALLOC_FREE(req);
10561 :
10562 5 : d_printf("cli_write_andx_recv returned %s: %d\n",
10563 : nt_errstr(status),
10564 5 : NT_STATUS_IS_OK(status) ? (int)written : -1);
10565 5 : }
10566 :
10567 5 : static void chain1_close_completion(struct tevent_req *req)
10568 : {
10569 0 : NTSTATUS status;
10570 5 : bool *done = (bool *)tevent_req_callback_data_void(req);
10571 :
10572 5 : status = cli_close_recv(req);
10573 5 : *done = true;
10574 :
10575 5 : TALLOC_FREE(req);
10576 :
10577 5 : d_printf("cli_close returned %s\n", nt_errstr(status));
10578 5 : }
10579 :
10580 5 : static bool run_chain1(int dummy)
10581 : {
10582 0 : struct cli_state *cli1;
10583 5 : struct tevent_context *evt = samba_tevent_context_init(NULL);
10584 0 : struct tevent_req *reqs[3], *smbreqs[3];
10585 5 : bool done = false;
10586 5 : const char *str = "foobar";
10587 5 : const char *fname = "\\test_chain";
10588 0 : NTSTATUS status;
10589 :
10590 5 : printf("starting chain1 test\n");
10591 5 : if (!torture_open_connection(&cli1, 0)) {
10592 0 : return False;
10593 : }
10594 :
10595 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
10596 :
10597 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10598 :
10599 5 : reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10600 : O_CREAT|O_RDWR, 0, &smbreqs[0]);
10601 5 : if (reqs[0] == NULL) return false;
10602 5 : tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10603 :
10604 :
10605 5 : reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10606 5 : (const uint8_t *)str, 0, strlen(str)+1,
10607 : smbreqs, 1, &smbreqs[1]);
10608 5 : if (reqs[1] == NULL) return false;
10609 5 : tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10610 :
10611 5 : reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10612 5 : if (reqs[2] == NULL) return false;
10613 5 : tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10614 :
10615 5 : status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10616 5 : if (!NT_STATUS_IS_OK(status)) {
10617 0 : return false;
10618 : }
10619 :
10620 35 : while (!done) {
10621 30 : tevent_loop_once(evt);
10622 : }
10623 :
10624 5 : torture_close_connection(cli1);
10625 5 : return True;
10626 : }
10627 :
10628 5 : static void chain2_sesssetup_completion(struct tevent_req *req)
10629 : {
10630 0 : NTSTATUS status;
10631 5 : status = cli_session_setup_guest_recv(req);
10632 5 : d_printf("sesssetup returned %s\n", nt_errstr(status));
10633 5 : }
10634 :
10635 5 : static void chain2_tcon_completion(struct tevent_req *req)
10636 : {
10637 5 : bool *done = (bool *)tevent_req_callback_data_void(req);
10638 0 : NTSTATUS status;
10639 5 : status = cli_tcon_andx_recv(req);
10640 5 : d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10641 5 : *done = true;
10642 5 : }
10643 :
10644 5 : static bool run_chain2(int dummy)
10645 : {
10646 0 : struct cli_state *cli1;
10647 5 : struct tevent_context *evt = samba_tevent_context_init(NULL);
10648 0 : struct tevent_req *reqs[2], *smbreqs[2];
10649 5 : bool done = false;
10650 0 : NTSTATUS status;
10651 5 : int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10652 :
10653 5 : printf("starting chain2 test\n");
10654 5 : status = cli_start_connection(talloc_tos(),
10655 : &cli1,
10656 : lp_netbios_name(),
10657 : host,
10658 : NULL,
10659 : port_to_use,
10660 : SMB_SIGNING_DEFAULT,
10661 : flags);
10662 5 : if (!NT_STATUS_IS_OK(status)) {
10663 0 : return False;
10664 : }
10665 :
10666 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
10667 :
10668 5 : reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10669 : &smbreqs[0]);
10670 5 : if (reqs[0] == NULL) return false;
10671 5 : tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10672 :
10673 5 : reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10674 : "?????", NULL, 0, &smbreqs[1]);
10675 5 : if (reqs[1] == NULL) return false;
10676 5 : tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10677 :
10678 5 : status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10679 5 : if (!NT_STATUS_IS_OK(status)) {
10680 0 : return false;
10681 : }
10682 :
10683 30 : while (!done) {
10684 25 : tevent_loop_once(evt);
10685 : }
10686 :
10687 5 : torture_close_connection(cli1);
10688 5 : return True;
10689 : }
10690 :
10691 :
10692 : struct torture_createdel_state {
10693 : struct tevent_context *ev;
10694 : struct cli_state *cli;
10695 : };
10696 :
10697 : static void torture_createdel_created(struct tevent_req *subreq);
10698 : static void torture_createdel_closed(struct tevent_req *subreq);
10699 :
10700 0 : static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10701 : struct tevent_context *ev,
10702 : struct cli_state *cli,
10703 : const char *name)
10704 : {
10705 0 : struct tevent_req *req, *subreq;
10706 0 : struct torture_createdel_state *state;
10707 :
10708 0 : req = tevent_req_create(mem_ctx, &state,
10709 : struct torture_createdel_state);
10710 0 : if (req == NULL) {
10711 0 : return NULL;
10712 : }
10713 0 : state->ev = ev;
10714 0 : state->cli = cli;
10715 :
10716 0 : subreq = cli_ntcreate_send(
10717 : state, ev, cli, name, 0,
10718 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10719 : FILE_ATTRIBUTE_NORMAL,
10720 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10721 : FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10722 : SMB2_IMPERSONATION_IMPERSONATION, 0);
10723 :
10724 0 : if (tevent_req_nomem(subreq, req)) {
10725 0 : return tevent_req_post(req, ev);
10726 : }
10727 0 : tevent_req_set_callback(subreq, torture_createdel_created, req);
10728 0 : return req;
10729 : }
10730 :
10731 0 : static void torture_createdel_created(struct tevent_req *subreq)
10732 : {
10733 0 : struct tevent_req *req = tevent_req_callback_data(
10734 : subreq, struct tevent_req);
10735 0 : struct torture_createdel_state *state = tevent_req_data(
10736 : req, struct torture_createdel_state);
10737 0 : NTSTATUS status;
10738 0 : uint16_t fnum;
10739 :
10740 0 : status = cli_ntcreate_recv(subreq, &fnum, NULL);
10741 0 : TALLOC_FREE(subreq);
10742 0 : if (tevent_req_nterror(req, status)) {
10743 0 : DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10744 : nt_errstr(status)));
10745 0 : return;
10746 : }
10747 :
10748 0 : subreq = cli_close_send(state, state->ev, state->cli, fnum, 0);
10749 0 : if (tevent_req_nomem(subreq, req)) {
10750 0 : return;
10751 : }
10752 0 : tevent_req_set_callback(subreq, torture_createdel_closed, req);
10753 : }
10754 :
10755 0 : static void torture_createdel_closed(struct tevent_req *subreq)
10756 : {
10757 0 : struct tevent_req *req = tevent_req_callback_data(
10758 : subreq, struct tevent_req);
10759 0 : NTSTATUS status;
10760 :
10761 0 : status = cli_close_recv(subreq);
10762 0 : if (tevent_req_nterror(req, status)) {
10763 0 : DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10764 0 : return;
10765 : }
10766 0 : tevent_req_done(req);
10767 : }
10768 :
10769 0 : static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10770 : {
10771 0 : return tevent_req_simple_recv_ntstatus(req);
10772 : }
10773 :
10774 : struct torture_createdels_state {
10775 : struct tevent_context *ev;
10776 : struct cli_state *cli;
10777 : const char *base_name;
10778 : int sent;
10779 : int received;
10780 : int num_files;
10781 : struct tevent_req **reqs;
10782 : };
10783 :
10784 : static void torture_createdels_done(struct tevent_req *subreq);
10785 :
10786 0 : static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10787 : struct tevent_context *ev,
10788 : struct cli_state *cli,
10789 : const char *base_name,
10790 : int num_parallel,
10791 : int num_files)
10792 : {
10793 0 : struct tevent_req *req;
10794 0 : struct torture_createdels_state *state;
10795 0 : int i;
10796 :
10797 0 : req = tevent_req_create(mem_ctx, &state,
10798 : struct torture_createdels_state);
10799 0 : if (req == NULL) {
10800 0 : return NULL;
10801 : }
10802 0 : state->ev = ev;
10803 0 : state->cli = cli;
10804 0 : state->base_name = talloc_strdup(state, base_name);
10805 0 : if (tevent_req_nomem(state->base_name, req)) {
10806 0 : return tevent_req_post(req, ev);
10807 : }
10808 0 : state->num_files = MAX(num_parallel, num_files);
10809 0 : state->sent = 0;
10810 0 : state->received = 0;
10811 :
10812 0 : state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10813 0 : if (tevent_req_nomem(state->reqs, req)) {
10814 0 : return tevent_req_post(req, ev);
10815 : }
10816 :
10817 0 : for (i=0; i<num_parallel; i++) {
10818 0 : char *name;
10819 :
10820 0 : name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10821 0 : state->sent);
10822 0 : if (tevent_req_nomem(name, req)) {
10823 0 : return tevent_req_post(req, ev);
10824 : }
10825 0 : state->reqs[i] = torture_createdel_send(
10826 0 : state->reqs, state->ev, state->cli, name);
10827 0 : if (tevent_req_nomem(state->reqs[i], req)) {
10828 0 : return tevent_req_post(req, ev);
10829 : }
10830 0 : name = talloc_move(state->reqs[i], &name);
10831 0 : tevent_req_set_callback(state->reqs[i],
10832 : torture_createdels_done, req);
10833 0 : state->sent += 1;
10834 : }
10835 0 : return req;
10836 : }
10837 :
10838 0 : static void torture_createdels_done(struct tevent_req *subreq)
10839 : {
10840 0 : struct tevent_req *req = tevent_req_callback_data(
10841 : subreq, struct tevent_req);
10842 0 : struct torture_createdels_state *state = tevent_req_data(
10843 : req, struct torture_createdels_state);
10844 0 : size_t i, num_parallel = talloc_array_length(state->reqs);
10845 0 : NTSTATUS status;
10846 0 : char *name;
10847 :
10848 0 : status = torture_createdel_recv(subreq);
10849 0 : if (!NT_STATUS_IS_OK(status)){
10850 0 : DEBUG(10, ("torture_createdel_recv returned %s\n",
10851 : nt_errstr(status)));
10852 0 : TALLOC_FREE(subreq);
10853 0 : tevent_req_nterror(req, status);
10854 0 : return;
10855 : }
10856 :
10857 0 : for (i=0; i<num_parallel; i++) {
10858 0 : if (subreq == state->reqs[i]) {
10859 0 : break;
10860 : }
10861 : }
10862 0 : if (i == num_parallel) {
10863 0 : DEBUG(10, ("received something we did not send\n"));
10864 0 : tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10865 0 : return;
10866 : }
10867 0 : TALLOC_FREE(state->reqs[i]);
10868 :
10869 0 : if (state->sent >= state->num_files) {
10870 0 : tevent_req_done(req);
10871 0 : return;
10872 : }
10873 :
10874 0 : name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10875 : state->sent);
10876 0 : if (tevent_req_nomem(name, req)) {
10877 0 : return;
10878 : }
10879 0 : state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10880 : state->cli, name);
10881 0 : if (tevent_req_nomem(state->reqs[i], req)) {
10882 0 : return;
10883 : }
10884 0 : name = talloc_move(state->reqs[i], &name);
10885 0 : tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10886 0 : state->sent += 1;
10887 : }
10888 :
10889 0 : static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10890 : {
10891 0 : return tevent_req_simple_recv_ntstatus(req);
10892 : }
10893 :
10894 : struct swallow_notify_state {
10895 : struct tevent_context *ev;
10896 : struct cli_state *cli;
10897 : uint16_t fnum;
10898 : uint32_t completion_filter;
10899 : bool recursive;
10900 : bool (*fn)(uint32_t action, const char *name, void *priv);
10901 : void *priv;
10902 : };
10903 :
10904 : static void swallow_notify_done(struct tevent_req *subreq);
10905 :
10906 0 : static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10907 : struct tevent_context *ev,
10908 : struct cli_state *cli,
10909 : uint16_t fnum,
10910 : uint32_t completion_filter,
10911 : bool recursive,
10912 : bool (*fn)(uint32_t action,
10913 : const char *name,
10914 : void *priv),
10915 : void *priv)
10916 : {
10917 0 : struct tevent_req *req, *subreq;
10918 0 : struct swallow_notify_state *state;
10919 :
10920 0 : req = tevent_req_create(mem_ctx, &state,
10921 : struct swallow_notify_state);
10922 0 : if (req == NULL) {
10923 0 : return NULL;
10924 : }
10925 0 : state->ev = ev;
10926 0 : state->cli = cli;
10927 0 : state->fnum = fnum;
10928 0 : state->completion_filter = completion_filter;
10929 0 : state->recursive = recursive;
10930 0 : state->fn = fn;
10931 0 : state->priv = priv;
10932 :
10933 0 : subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10934 0 : 0xffff, state->completion_filter,
10935 0 : state->recursive);
10936 0 : if (tevent_req_nomem(subreq, req)) {
10937 0 : return tevent_req_post(req, ev);
10938 : }
10939 0 : tevent_req_set_callback(subreq, swallow_notify_done, req);
10940 0 : return req;
10941 : }
10942 :
10943 0 : static void swallow_notify_done(struct tevent_req *subreq)
10944 : {
10945 0 : struct tevent_req *req = tevent_req_callback_data(
10946 : subreq, struct tevent_req);
10947 0 : struct swallow_notify_state *state = tevent_req_data(
10948 : req, struct swallow_notify_state);
10949 0 : NTSTATUS status;
10950 0 : uint32_t i, num_changes;
10951 0 : struct notify_change *changes;
10952 :
10953 0 : status = cli_notify_recv(subreq, state, &num_changes, &changes);
10954 0 : TALLOC_FREE(subreq);
10955 0 : if (!NT_STATUS_IS_OK(status)) {
10956 0 : DEBUG(10, ("cli_notify_recv returned %s\n",
10957 : nt_errstr(status)));
10958 0 : tevent_req_nterror(req, status);
10959 0 : return;
10960 : }
10961 :
10962 0 : for (i=0; i<num_changes; i++) {
10963 0 : state->fn(changes[i].action, changes[i].name, state->priv);
10964 : }
10965 0 : TALLOC_FREE(changes);
10966 :
10967 0 : subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10968 : 0xffff, state->completion_filter,
10969 0 : state->recursive);
10970 0 : if (tevent_req_nomem(subreq, req)) {
10971 0 : return;
10972 : }
10973 0 : tevent_req_set_callback(subreq, swallow_notify_done, req);
10974 : }
10975 :
10976 0 : static bool print_notifies(uint32_t action, const char *name, void *priv)
10977 : {
10978 0 : if (DEBUGLEVEL > 5) {
10979 0 : d_printf("%d %s\n", (int)action, name);
10980 : }
10981 0 : return true;
10982 : }
10983 :
10984 0 : static void notify_bench_done(struct tevent_req *req)
10985 : {
10986 0 : int *num_finished = (int *)tevent_req_callback_data_void(req);
10987 0 : *num_finished += 1;
10988 0 : }
10989 :
10990 0 : static bool run_notify_bench(int dummy)
10991 : {
10992 0 : const char *dname = "\\notify-bench";
10993 0 : struct tevent_context *ev;
10994 0 : NTSTATUS status;
10995 0 : uint16_t dnum;
10996 0 : struct tevent_req *req1;
10997 0 : struct tevent_req *req2 = NULL;
10998 0 : int i, num_unc_names;
10999 0 : int num_finished = 0;
11000 :
11001 0 : printf("starting notify-bench test\n");
11002 :
11003 0 : if (use_multishare_conn) {
11004 0 : char **unc_list;
11005 0 : unc_list = file_lines_load(multishare_conn_fname,
11006 : &num_unc_names, 0, NULL);
11007 0 : if (!unc_list || num_unc_names <= 0) {
11008 0 : d_printf("Failed to load unc names list from '%s'\n",
11009 : multishare_conn_fname);
11010 0 : return false;
11011 : }
11012 0 : TALLOC_FREE(unc_list);
11013 : } else {
11014 0 : num_unc_names = 1;
11015 : }
11016 :
11017 0 : ev = samba_tevent_context_init(talloc_tos());
11018 0 : if (ev == NULL) {
11019 0 : d_printf("tevent_context_init failed\n");
11020 0 : return false;
11021 : }
11022 :
11023 0 : for (i=0; i<num_unc_names; i++) {
11024 0 : struct cli_state *cli;
11025 0 : char *base_fname;
11026 :
11027 0 : base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
11028 : dname, i);
11029 0 : if (base_fname == NULL) {
11030 0 : return false;
11031 : }
11032 :
11033 0 : if (!torture_open_connection(&cli, i)) {
11034 0 : return false;
11035 : }
11036 :
11037 0 : status = cli_ntcreate(cli, dname, 0,
11038 : MAXIMUM_ALLOWED_ACCESS,
11039 : 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
11040 : FILE_SHARE_DELETE,
11041 : FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
11042 : &dnum, NULL);
11043 :
11044 0 : if (!NT_STATUS_IS_OK(status)) {
11045 0 : d_printf("Could not create %s: %s\n", dname,
11046 : nt_errstr(status));
11047 0 : return false;
11048 : }
11049 :
11050 0 : req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
11051 : FILE_NOTIFY_CHANGE_FILE_NAME |
11052 : FILE_NOTIFY_CHANGE_DIR_NAME |
11053 : FILE_NOTIFY_CHANGE_ATTRIBUTES |
11054 : FILE_NOTIFY_CHANGE_LAST_WRITE,
11055 : false, print_notifies, NULL);
11056 0 : if (req1 == NULL) {
11057 0 : d_printf("Could not create notify request\n");
11058 0 : return false;
11059 : }
11060 :
11061 0 : req2 = torture_createdels_send(talloc_tos(), ev, cli,
11062 : base_fname, 10, torture_numops);
11063 0 : if (req2 == NULL) {
11064 0 : d_printf("Could not create createdels request\n");
11065 0 : return false;
11066 : }
11067 0 : TALLOC_FREE(base_fname);
11068 :
11069 0 : tevent_req_set_callback(req2, notify_bench_done,
11070 : &num_finished);
11071 : }
11072 :
11073 0 : while (num_finished < num_unc_names) {
11074 0 : int ret;
11075 0 : ret = tevent_loop_once(ev);
11076 0 : if (ret != 0) {
11077 0 : d_printf("tevent_loop_once failed\n");
11078 0 : return false;
11079 : }
11080 : }
11081 :
11082 0 : if (!tevent_req_poll(req2, ev)) {
11083 0 : d_printf("tevent_req_poll failed\n");
11084 : }
11085 :
11086 0 : status = torture_createdels_recv(req2);
11087 0 : d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
11088 :
11089 0 : return true;
11090 : }
11091 :
11092 0 : static bool run_mangle1(int dummy)
11093 : {
11094 0 : struct cli_state *cli;
11095 0 : const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
11096 0 : uint16_t fnum;
11097 0 : fstring alt_name;
11098 0 : NTSTATUS status;
11099 :
11100 0 : printf("starting mangle1 test\n");
11101 0 : if (!torture_open_connection(&cli, 0)) {
11102 0 : return False;
11103 : }
11104 :
11105 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11106 :
11107 0 : status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11108 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11109 : 0, 0, &fnum, NULL);
11110 0 : if (!NT_STATUS_IS_OK(status)) {
11111 0 : d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11112 0 : return false;
11113 : }
11114 0 : cli_close(cli, fnum);
11115 :
11116 0 : status = cli_qpathinfo_alt_name(cli, fname, alt_name);
11117 0 : if (!NT_STATUS_IS_OK(status)) {
11118 0 : d_printf("cli_qpathinfo_alt_name failed: %s\n",
11119 : nt_errstr(status));
11120 0 : return false;
11121 : }
11122 0 : d_printf("alt_name: %s\n", alt_name);
11123 :
11124 0 : status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
11125 0 : if (!NT_STATUS_IS_OK(status)) {
11126 0 : d_printf("cli_openx(%s) failed: %s\n", alt_name,
11127 : nt_errstr(status));
11128 0 : return false;
11129 : }
11130 0 : cli_close(cli, fnum);
11131 :
11132 0 : status = cli_qpathinfo1(cli, alt_name, NULL, NULL, NULL, NULL, NULL);
11133 0 : if (!NT_STATUS_IS_OK(status)) {
11134 0 : d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
11135 : nt_errstr(status));
11136 0 : return false;
11137 : }
11138 :
11139 0 : return true;
11140 : }
11141 :
11142 2 : static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
11143 : const char *mask,
11144 : void *state)
11145 : {
11146 2 : if (f->short_name == NULL) {
11147 2 : return NT_STATUS_OK;
11148 : }
11149 :
11150 0 : if (strlen(f->short_name) == 0) {
11151 0 : return NT_STATUS_OK;
11152 : }
11153 :
11154 0 : printf("unexpected shortname: %s\n", f->short_name);
11155 :
11156 0 : return NT_STATUS_OBJECT_NAME_INVALID;
11157 : }
11158 :
11159 2 : static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11160 : const char *mask,
11161 : void *state)
11162 : {
11163 2 : char *name = state;
11164 :
11165 2 : printf("name: %s\n", f->name);
11166 2 : fstrcpy(name, f->name);
11167 2 : return NT_STATUS_OK;
11168 : }
11169 :
11170 2 : static bool run_mangle_illegal(int dummy)
11171 : {
11172 2 : struct cli_state *cli = NULL;
11173 2 : struct cli_state *cli_posix = NULL;
11174 2 : const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11175 2 : const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11176 2 : char *mangled_path = NULL;
11177 0 : uint16_t fnum;
11178 0 : fstring name;
11179 0 : fstring alt_name;
11180 0 : NTSTATUS status;
11181 :
11182 2 : printf("starting mangle-illegal test\n");
11183 :
11184 2 : if (!torture_open_connection(&cli, 0)) {
11185 0 : return False;
11186 : }
11187 :
11188 2 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11189 :
11190 2 : if (!torture_open_connection(&cli_posix, 0)) {
11191 0 : return false;
11192 : }
11193 :
11194 2 : smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11195 :
11196 2 : status = torture_setup_unix_extensions(cli_posix);
11197 2 : if (!NT_STATUS_IS_OK(status)) {
11198 0 : return false;
11199 : }
11200 :
11201 2 : cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11202 2 : status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11203 2 : if (!NT_STATUS_IS_OK(status)) {
11204 0 : printf("mkdir1 failed : %s\n", nt_errstr(status));
11205 0 : return False;
11206 : }
11207 :
11208 : /*
11209 : * Create a file with illegal NTFS characters and test that we
11210 : * get a usable mangled name
11211 : */
11212 :
11213 2 : cli_setatr(cli_posix, illegal_fname, 0, 0);
11214 2 : cli_posix_unlink(cli_posix, illegal_fname);
11215 :
11216 2 : status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11217 : 0600, &fnum);
11218 2 : if (!NT_STATUS_IS_OK(status)) {
11219 0 : printf("POSIX create of %s failed (%s)\n",
11220 : illegal_fname, nt_errstr(status));
11221 0 : return false;
11222 : }
11223 :
11224 2 : status = cli_close(cli_posix, fnum);
11225 2 : if (!NT_STATUS_IS_OK(status)) {
11226 0 : printf("close failed (%s)\n", nt_errstr(status));
11227 0 : return false;
11228 : }
11229 :
11230 2 : status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11231 2 : if (!NT_STATUS_IS_OK(status)) {
11232 0 : d_printf("cli_list failed: %s\n", nt_errstr(status));
11233 0 : return false;
11234 : }
11235 :
11236 2 : mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11237 2 : if (mangled_path == NULL) {
11238 0 : return false;
11239 : }
11240 :
11241 2 : status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11242 2 : if (!NT_STATUS_IS_OK(status)) {
11243 0 : d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11244 0 : TALLOC_FREE(mangled_path);
11245 0 : return false;
11246 : }
11247 2 : TALLOC_FREE(mangled_path);
11248 2 : cli_close(cli, fnum);
11249 :
11250 2 : cli_setatr(cli_posix, illegal_fname, 0, 0);
11251 2 : cli_posix_unlink(cli_posix, illegal_fname);
11252 :
11253 : /*
11254 : * Create a file with a long name and check that we got *no* short name.
11255 : */
11256 :
11257 2 : status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11258 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11259 : 0, 0, &fnum, NULL);
11260 2 : if (!NT_STATUS_IS_OK(status)) {
11261 0 : d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11262 0 : return false;
11263 : }
11264 2 : cli_close(cli, fnum);
11265 :
11266 2 : status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11267 2 : if (!NT_STATUS_IS_OK(status)) {
11268 0 : d_printf("cli_list failed\n");
11269 0 : return false;
11270 : }
11271 :
11272 2 : cli_unlink(cli, fname, 0);
11273 2 : cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11274 :
11275 2 : if (!torture_close_connection(cli_posix)) {
11276 0 : return false;
11277 : }
11278 :
11279 2 : if (!torture_close_connection(cli)) {
11280 0 : return false;
11281 : }
11282 :
11283 2 : return true;
11284 : }
11285 :
11286 0 : static size_t null_source(uint8_t *buf, size_t n, void *priv)
11287 : {
11288 0 : size_t *to_pull = (size_t *)priv;
11289 0 : size_t thistime = *to_pull;
11290 :
11291 0 : thistime = MIN(thistime, n);
11292 0 : if (thistime == 0) {
11293 0 : return 0;
11294 : }
11295 :
11296 0 : memset(buf, 0, thistime);
11297 0 : *to_pull -= thistime;
11298 0 : return thistime;
11299 : }
11300 :
11301 0 : static bool run_windows_write(int dummy)
11302 : {
11303 0 : struct cli_state *cli1;
11304 0 : uint16_t fnum;
11305 0 : int i;
11306 0 : bool ret = false;
11307 0 : const char *fname = "\\writetest.txt";
11308 0 : struct timeval start_time;
11309 0 : double seconds;
11310 0 : double kbytes;
11311 0 : NTSTATUS status;
11312 :
11313 0 : printf("starting windows_write test\n");
11314 0 : if (!torture_open_connection(&cli1, 0)) {
11315 0 : return False;
11316 : }
11317 :
11318 0 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11319 0 : if (!NT_STATUS_IS_OK(status)) {
11320 0 : printf("open failed (%s)\n", nt_errstr(status));
11321 0 : return False;
11322 : }
11323 :
11324 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
11325 :
11326 0 : start_time = timeval_current();
11327 :
11328 0 : for (i=0; i<torture_numops; i++) {
11329 0 : uint8_t c = 0;
11330 0 : off_t start = i * torture_blocksize;
11331 0 : size_t to_pull = torture_blocksize - 1;
11332 :
11333 0 : status = cli_writeall(cli1, fnum, 0, &c,
11334 0 : start + torture_blocksize - 1, 1, NULL);
11335 0 : if (!NT_STATUS_IS_OK(status)) {
11336 0 : printf("cli_write failed: %s\n", nt_errstr(status));
11337 0 : goto fail;
11338 : }
11339 :
11340 0 : status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11341 : null_source, &to_pull);
11342 0 : if (!NT_STATUS_IS_OK(status)) {
11343 0 : printf("cli_push returned: %s\n", nt_errstr(status));
11344 0 : goto fail;
11345 : }
11346 : }
11347 :
11348 0 : seconds = timeval_elapsed(&start_time);
11349 0 : kbytes = (double)torture_blocksize * torture_numops;
11350 0 : kbytes /= 1024;
11351 :
11352 0 : printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11353 0 : (double)seconds, (int)(kbytes/seconds));
11354 :
11355 0 : ret = true;
11356 0 : fail:
11357 0 : cli_close(cli1, fnum);
11358 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11359 0 : torture_close_connection(cli1);
11360 0 : return ret;
11361 : }
11362 :
11363 64 : static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11364 : {
11365 64 : size_t max_pdu = 0x1FFFF;
11366 :
11367 64 : if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11368 32 : max_pdu = 0xFFFFFF;
11369 : }
11370 :
11371 64 : if (smb1cli_conn_signing_is_active(cli->conn)) {
11372 32 : max_pdu = 0x1FFFF;
11373 : }
11374 :
11375 64 : if (smb1cli_conn_encryption_on(cli->conn)) {
11376 16 : max_pdu = CLI_BUFFER_SIZE;
11377 : }
11378 :
11379 64 : if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11380 8 : len_requested &= 0xFFFF;
11381 : }
11382 :
11383 64 : return MIN(len_requested,
11384 : max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11385 : }
11386 :
11387 64 : static bool check_read_call(struct cli_state *cli,
11388 : uint16_t fnum,
11389 : uint8_t *buf,
11390 : size_t len_requested)
11391 : {
11392 0 : NTSTATUS status;
11393 64 : struct tevent_req *subreq = NULL;
11394 64 : ssize_t len_read = 0;
11395 64 : size_t len_expected = 0;
11396 64 : struct tevent_context *ev = NULL;
11397 :
11398 64 : ev = samba_tevent_context_init(talloc_tos());
11399 64 : if (ev == NULL) {
11400 0 : return false;
11401 : }
11402 :
11403 64 : subreq = cli_read_andx_send(talloc_tos(),
11404 : ev,
11405 : cli,
11406 : fnum,
11407 : 0,
11408 : len_requested);
11409 :
11410 64 : if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11411 0 : return false;
11412 : }
11413 :
11414 64 : status = cli_read_andx_recv(subreq, &len_read, &buf);
11415 64 : if (!NT_STATUS_IS_OK(status)) {
11416 0 : d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11417 0 : return false;
11418 : }
11419 :
11420 64 : TALLOC_FREE(subreq);
11421 64 : TALLOC_FREE(ev);
11422 :
11423 64 : len_expected = calc_expected_return(cli, len_requested);
11424 :
11425 64 : if (len_expected > 0x10000 && len_read == 0x10000) {
11426 : /* Windows servers only return a max of 0x10000,
11427 : doesn't matter if you set CAP_LARGE_READX in
11428 : the client sessionsetupX call or not. */
11429 12 : d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11430 : (unsigned int)len_requested);
11431 52 : } else if (len_read != len_expected) {
11432 0 : d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11433 : (unsigned int)len_requested,
11434 : (unsigned int)len_read,
11435 : (unsigned int)len_expected);
11436 0 : return false;
11437 : } else {
11438 52 : d_printf("Correct read reply.\n");
11439 : }
11440 :
11441 64 : return true;
11442 : }
11443 :
11444 : /* Test large readX variants. */
11445 8 : static bool large_readx_tests(struct cli_state *cli,
11446 : uint16_t fnum,
11447 : uint8_t *buf)
11448 : {
11449 : /* A read of 0xFFFF0001 should *always* return 1 byte. */
11450 8 : if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11451 0 : return false;
11452 : }
11453 : /* A read of 0x10000 should return 0x10000 bytes. */
11454 8 : if (check_read_call(cli, fnum, buf, 0x10000) == false) {
11455 0 : return false;
11456 : }
11457 : /* A read of 0x10000 should return 0x10001 bytes. */
11458 8 : if (check_read_call(cli, fnum, buf, 0x10001) == false) {
11459 0 : return false;
11460 : }
11461 : /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11462 : the requested number of bytes. */
11463 8 : if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11464 0 : return false;
11465 : }
11466 : /* A read of 1MB should return 1MB bytes (on Samba). */
11467 8 : if (check_read_call(cli, fnum, buf, 0x100000) == false) {
11468 0 : return false;
11469 : }
11470 :
11471 8 : if (check_read_call(cli, fnum, buf, 0x20001) == false) {
11472 0 : return false;
11473 : }
11474 8 : if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11475 0 : return false;
11476 : }
11477 8 : if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11478 0 : return false;
11479 : }
11480 8 : return true;
11481 : }
11482 :
11483 5 : static bool run_large_readx(int dummy)
11484 : {
11485 5 : uint8_t *buf = NULL;
11486 5 : struct cli_state *cli1 = NULL;
11487 5 : struct cli_state *cli2 = NULL;
11488 5 : bool correct = false;
11489 5 : const char *fname = "\\large_readx.dat";
11490 0 : NTSTATUS status;
11491 5 : uint16_t fnum1 = UINT16_MAX;
11492 5 : uint32_t normal_caps = 0;
11493 5 : size_t file_size = 20*1024*1024;
11494 5 : TALLOC_CTX *frame = talloc_stackframe();
11495 0 : size_t i;
11496 0 : struct {
11497 : const char *name;
11498 : enum smb_signing_setting signing_setting;
11499 : enum protocol_types protocol;
11500 5 : } runs[] = {
11501 : {
11502 : .name = "NT1",
11503 : .signing_setting = SMB_SIGNING_IF_REQUIRED,
11504 : .protocol = PROTOCOL_NT1,
11505 : },{
11506 : .name = "NT1 - SIGNING_REQUIRED",
11507 : .signing_setting = SMB_SIGNING_REQUIRED,
11508 : .protocol = PROTOCOL_NT1,
11509 : },
11510 : };
11511 :
11512 5 : printf("starting large_readx test\n");
11513 :
11514 5 : if (!torture_open_connection(&cli1, 0)) {
11515 0 : goto out;
11516 : }
11517 :
11518 5 : normal_caps = smb1cli_conn_capabilities(cli1->conn);
11519 :
11520 5 : if (!(normal_caps & CAP_LARGE_READX)) {
11521 0 : d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11522 : (unsigned int)normal_caps);
11523 0 : goto out;
11524 : }
11525 :
11526 : /* Create a file of size 4MB. */
11527 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11528 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11529 : 0, 0, &fnum1, NULL);
11530 :
11531 5 : if (!NT_STATUS_IS_OK(status)) {
11532 0 : d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11533 0 : goto out;
11534 : }
11535 :
11536 : /* Write file_size bytes. */
11537 5 : buf = talloc_zero_array(frame, uint8_t, file_size);
11538 5 : if (buf == NULL) {
11539 0 : goto out;
11540 : }
11541 :
11542 5 : status = cli_writeall(cli1,
11543 : fnum1,
11544 : 0,
11545 : buf,
11546 : 0,
11547 : file_size,
11548 : NULL);
11549 5 : if (!NT_STATUS_IS_OK(status)) {
11550 0 : d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11551 0 : goto out;
11552 : }
11553 :
11554 5 : status = cli_close(cli1, fnum1);
11555 5 : if (!NT_STATUS_IS_OK(status)) {
11556 0 : d_printf("cli_close failed: %s\n", nt_errstr(status));
11557 0 : goto out;
11558 : }
11559 :
11560 5 : fnum1 = UINT16_MAX;
11561 :
11562 15 : for (i=0; i < ARRAY_SIZE(runs); i++) {
11563 10 : enum smb_signing_setting saved_signing_setting = signing_state;
11564 10 : uint16_t fnum2 = -1;
11565 :
11566 10 : if (do_encrypt &&
11567 4 : (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11568 : {
11569 2 : d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11570 2 : continue;
11571 : }
11572 :
11573 8 : d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11574 :
11575 8 : signing_state = runs[i].signing_setting;
11576 8 : cli2 = open_nbt_connection();
11577 8 : signing_state = saved_signing_setting;
11578 8 : if (cli2 == NULL) {
11579 0 : goto out;
11580 : }
11581 :
11582 8 : status = smbXcli_negprot(cli2->conn,
11583 8 : cli2->timeout,
11584 : runs[i].protocol,
11585 : runs[i].protocol,
11586 : NULL,
11587 : NULL,
11588 : NULL);
11589 8 : if (!NT_STATUS_IS_OK(status)) {
11590 0 : goto out;
11591 : }
11592 :
11593 8 : status = cli_session_setup_creds(cli2, torture_creds);
11594 8 : if (!NT_STATUS_IS_OK(status)) {
11595 0 : goto out;
11596 : }
11597 :
11598 8 : status = cli_tree_connect(cli2,
11599 : share,
11600 : "?????",
11601 : password);
11602 8 : if (!NT_STATUS_IS_OK(status)) {
11603 0 : goto out;
11604 : }
11605 :
11606 8 : cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11607 :
11608 8 : normal_caps = smb1cli_conn_capabilities(cli2->conn);
11609 :
11610 8 : if (!(normal_caps & CAP_LARGE_READX)) {
11611 0 : d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11612 : (unsigned int)normal_caps);
11613 0 : goto out;
11614 : }
11615 :
11616 8 : if (do_encrypt) {
11617 2 : if (force_cli_encryption(cli2, share) == false) {
11618 0 : goto out;
11619 : }
11620 6 : } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11621 0 : uint16_t major, minor;
11622 0 : uint32_t caplow, caphigh;
11623 :
11624 4 : status = cli_unix_extensions_version(cli2,
11625 : &major, &minor,
11626 : &caplow, &caphigh);
11627 4 : if (!NT_STATUS_IS_OK(status)) {
11628 0 : goto out;
11629 : }
11630 : }
11631 :
11632 8 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11633 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11634 : 0, 0, &fnum2, NULL);
11635 8 : if (!NT_STATUS_IS_OK(status)) {
11636 0 : d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11637 0 : goto out;
11638 : }
11639 :
11640 : /* All reads must return less than file_size bytes. */
11641 8 : if (!large_readx_tests(cli2, fnum2, buf)) {
11642 0 : goto out;
11643 : }
11644 :
11645 8 : status = cli_close(cli2, fnum2);
11646 8 : if (!NT_STATUS_IS_OK(status)) {
11647 0 : d_printf("cli_close failed: %s\n", nt_errstr(status));
11648 0 : goto out;
11649 : }
11650 8 : fnum2 = -1;
11651 :
11652 8 : if (!torture_close_connection(cli2)) {
11653 0 : goto out;
11654 : }
11655 8 : cli2 = NULL;
11656 : }
11657 :
11658 5 : correct = true;
11659 5 : printf("Success on large_readx test\n");
11660 :
11661 5 : out:
11662 :
11663 5 : if (cli2) {
11664 0 : if (!torture_close_connection(cli2)) {
11665 0 : correct = false;
11666 : }
11667 : }
11668 :
11669 5 : if (cli1) {
11670 5 : if (fnum1 != UINT16_MAX) {
11671 0 : status = cli_close(cli1, fnum1);
11672 0 : if (!NT_STATUS_IS_OK(status)) {
11673 0 : d_printf("cli_close failed: %s\n", nt_errstr(status));
11674 : }
11675 0 : fnum1 = UINT16_MAX;
11676 : }
11677 :
11678 5 : status = cli_unlink(cli1, fname,
11679 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11680 5 : if (!NT_STATUS_IS_OK(status)) {
11681 0 : printf("unlink failed (%s)\n", nt_errstr(status));
11682 : }
11683 :
11684 5 : if (!torture_close_connection(cli1)) {
11685 0 : correct = false;
11686 : }
11687 : }
11688 :
11689 5 : TALLOC_FREE(frame);
11690 :
11691 5 : printf("finished large_readx test\n");
11692 5 : return correct;
11693 : }
11694 :
11695 24 : static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11696 : const char *mask,
11697 : void *private_data)
11698 : {
11699 24 : uint32_t *p_attr = (uint32_t *)private_data;
11700 :
11701 24 : if (strequal(finfo->name, test_filename)) {
11702 4 : *p_attr = finfo->attr;
11703 : }
11704 :
11705 24 : return NT_STATUS_OK;
11706 : }
11707 :
11708 4 : static bool run_msdfs_attribute(int dummy)
11709 : {
11710 0 : static struct cli_state *cli;
11711 4 : bool correct = false;
11712 4 : uint32_t attr = 0;
11713 0 : NTSTATUS status;
11714 :
11715 4 : printf("Starting MSDFS-ATTRIBUTE test\n");
11716 :
11717 4 : if (test_filename == NULL || test_filename[0] == '\0') {
11718 0 : printf("MSDFS-ATTRIBUTE test "
11719 : "needs -f filename-of-msdfs-link\n");
11720 0 : return false;
11721 : }
11722 :
11723 : /*
11724 : * NB. We use torture_open_connection_flags() not
11725 : * torture_open_connection() as the latter forces
11726 : * SMB1.
11727 : */
11728 4 : if (!torture_open_connection_flags(&cli, 0, 0)) {
11729 0 : return false;
11730 : }
11731 :
11732 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11733 :
11734 4 : status = cli_list(cli,
11735 : "*",
11736 : FILE_ATTRIBUTE_DIRECTORY,
11737 : msdfs_attribute_list_fn,
11738 : &attr);
11739 :
11740 4 : if (!NT_STATUS_IS_OK(status)) {
11741 0 : printf("cli_list failed with %s\n",
11742 : nt_errstr(status));
11743 0 : goto out;
11744 : }
11745 4 : if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11746 0 : printf("file %s should have "
11747 : "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11748 : test_filename,
11749 : (unsigned int)attr);
11750 0 : goto out;
11751 : }
11752 :
11753 4 : if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11754 0 : printf("file %s should have "
11755 : "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11756 : test_filename,
11757 : (unsigned int)attr);
11758 0 : goto out;
11759 : }
11760 :
11761 4 : correct = true;
11762 :
11763 4 : out:
11764 :
11765 4 : torture_close_connection(cli);
11766 4 : return correct;
11767 : }
11768 :
11769 0 : static bool run_cli_echo(int dummy)
11770 : {
11771 0 : struct cli_state *cli;
11772 0 : NTSTATUS status;
11773 :
11774 0 : printf("starting cli_echo test\n");
11775 0 : if (!torture_open_connection(&cli, 0)) {
11776 0 : return false;
11777 : }
11778 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11779 :
11780 0 : status = cli_echo(cli, 5, data_blob_const("hello", 5));
11781 :
11782 0 : d_printf("cli_echo returned %s\n", nt_errstr(status));
11783 :
11784 0 : torture_close_connection(cli);
11785 0 : return NT_STATUS_IS_OK(status);
11786 : }
11787 :
11788 14 : static int splice_status(off_t written, void *priv)
11789 : {
11790 14 : return true;
11791 : }
11792 :
11793 7 : static bool run_cli_splice(int dummy)
11794 : {
11795 7 : uint8_t *buf = NULL;
11796 7 : struct cli_state *cli1 = NULL;
11797 7 : bool correct = false;
11798 7 : const char *fname_src = "\\splice_src.dat";
11799 7 : const char *fname_dst = "\\splice_dst.dat";
11800 0 : NTSTATUS status;
11801 7 : uint16_t fnum1 = UINT16_MAX;
11802 7 : uint16_t fnum2 = UINT16_MAX;
11803 7 : size_t file_size = 2*1024*1024;
11804 7 : size_t splice_size = 1*1024*1024 + 713;
11805 0 : uint8_t digest1[16], digest2[16];
11806 7 : off_t written = 0;
11807 7 : size_t nread = 0;
11808 7 : TALLOC_CTX *frame = talloc_stackframe();
11809 :
11810 7 : printf("starting cli_splice test\n");
11811 :
11812 7 : if (!torture_open_connection(&cli1, 0)) {
11813 0 : goto out;
11814 : }
11815 :
11816 7 : cli_unlink(cli1, fname_src,
11817 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11818 7 : cli_unlink(cli1, fname_dst,
11819 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11820 :
11821 : /* Create a file */
11822 7 : status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11823 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11824 : 0, 0, &fnum1, NULL);
11825 :
11826 7 : if (!NT_STATUS_IS_OK(status)) {
11827 0 : d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11828 0 : goto out;
11829 : }
11830 :
11831 : /* Write file_size bytes - must be bigger than splice_size. */
11832 7 : buf = talloc_zero_array(frame, uint8_t, file_size);
11833 7 : if (buf == NULL) {
11834 0 : d_printf("talloc_fail\n");
11835 0 : goto out;
11836 : }
11837 :
11838 : /* Fill it with random numbers. */
11839 7 : generate_random_buffer(buf, file_size);
11840 :
11841 : /* MD5 the first 1MB + 713 bytes. */
11842 7 : gnutls_hash_fast(GNUTLS_DIG_MD5,
11843 : buf,
11844 : splice_size,
11845 : digest1);
11846 :
11847 7 : status = cli_writeall(cli1,
11848 : fnum1,
11849 : 0,
11850 : buf,
11851 : 0,
11852 : file_size,
11853 : NULL);
11854 7 : if (!NT_STATUS_IS_OK(status)) {
11855 0 : d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11856 0 : goto out;
11857 : }
11858 :
11859 7 : status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11860 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11861 : 0, 0, &fnum2, NULL);
11862 :
11863 7 : if (!NT_STATUS_IS_OK(status)) {
11864 0 : d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11865 0 : goto out;
11866 : }
11867 :
11868 : /* Now splice 1MB + 713 bytes. */
11869 7 : status = cli_splice(cli1,
11870 : cli1,
11871 : fnum1,
11872 : fnum2,
11873 : splice_size,
11874 : 0,
11875 : 0,
11876 : &written,
11877 : splice_status,
11878 : NULL);
11879 :
11880 7 : if (!NT_STATUS_IS_OK(status)) {
11881 0 : d_printf("cli_splice failed: %s\n", nt_errstr(status));
11882 0 : goto out;
11883 : }
11884 :
11885 : /* Clear the old buffer. */
11886 7 : memset(buf, '\0', file_size);
11887 :
11888 : /* Read the new file. */
11889 7 : status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11890 7 : if (!NT_STATUS_IS_OK(status)) {
11891 0 : d_printf("cli_read failed: %s\n", nt_errstr(status));
11892 0 : goto out;
11893 : }
11894 7 : if (nread != splice_size) {
11895 0 : d_printf("bad read of 0x%x, should be 0x%x\n",
11896 : (unsigned int)nread,
11897 : (unsigned int)splice_size);
11898 0 : goto out;
11899 : }
11900 :
11901 : /* MD5 the first 1MB + 713 bytes. */
11902 7 : gnutls_hash_fast(GNUTLS_DIG_MD5,
11903 : buf,
11904 : splice_size,
11905 : digest2);
11906 :
11907 : /* Must be the same. */
11908 7 : if (memcmp(digest1, digest2, 16) != 0) {
11909 0 : d_printf("bad MD5 compare\n");
11910 0 : goto out;
11911 : }
11912 :
11913 7 : correct = true;
11914 7 : printf("Success on cli_splice test\n");
11915 :
11916 7 : out:
11917 :
11918 7 : if (cli1) {
11919 7 : if (fnum1 != UINT16_MAX) {
11920 7 : cli_close(cli1, fnum1);
11921 : }
11922 7 : if (fnum2 != UINT16_MAX) {
11923 7 : cli_close(cli1, fnum2);
11924 : }
11925 :
11926 7 : cli_unlink(cli1, fname_src,
11927 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11928 7 : cli_unlink(cli1, fname_dst,
11929 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11930 :
11931 7 : if (!torture_close_connection(cli1)) {
11932 0 : correct = false;
11933 : }
11934 : }
11935 :
11936 7 : TALLOC_FREE(frame);
11937 7 : return correct;
11938 : }
11939 :
11940 4 : static bool run_uid_regression_test(int dummy)
11941 : {
11942 0 : static struct cli_state *cli;
11943 0 : int16_t old_vuid;
11944 0 : int32_t old_cnum;
11945 4 : bool correct = True;
11946 4 : struct smbXcli_tcon *tcon_copy = NULL;
11947 0 : NTSTATUS status;
11948 :
11949 4 : printf("starting uid regression test\n");
11950 :
11951 4 : if (!torture_open_connection(&cli, 0)) {
11952 0 : return False;
11953 : }
11954 :
11955 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11956 :
11957 : /* Ok - now save then logoff our current user. */
11958 4 : old_vuid = cli_state_get_uid(cli);
11959 :
11960 4 : status = cli_ulogoff(cli);
11961 4 : if (!NT_STATUS_IS_OK(status)) {
11962 0 : d_printf("(%s) cli_ulogoff failed: %s\n",
11963 : __location__, nt_errstr(status));
11964 0 : correct = false;
11965 0 : goto out;
11966 : }
11967 :
11968 4 : cli_state_set_uid(cli, old_vuid);
11969 :
11970 : /* Try an operation. */
11971 4 : status = cli_mkdir(cli, "\\uid_reg_test");
11972 4 : if (NT_STATUS_IS_OK(status)) {
11973 0 : d_printf("(%s) cli_mkdir succeeded\n",
11974 : __location__);
11975 0 : correct = false;
11976 0 : goto out;
11977 : } else {
11978 : /* Should be bad uid. */
11979 4 : if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11980 4 : NT_STATUS_USER_SESSION_DELETED)) {
11981 0 : correct = false;
11982 0 : goto out;
11983 : }
11984 : }
11985 :
11986 4 : old_cnum = cli_state_get_tid(cli);
11987 : /*
11988 : * This is an SMB1-only test.
11989 : * Copy the tcon, not "save/restore".
11990 : *
11991 : * In SMB1 the cli_tdis() below frees
11992 : * cli->smb1.tcon so we need a copy
11993 : * of the struct to put back for the
11994 : * second tdis call with invalid vuid.
11995 : *
11996 : * This is a test-only hack. Real client code
11997 : * uses cli_state_save_tcon_share()/cli_state_restore_tcon_share().
11998 : */
11999 4 : tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
12000 4 : if (tcon_copy == NULL) {
12001 0 : correct = false;
12002 0 : goto out;
12003 : }
12004 :
12005 : /* Now try a SMBtdis with the invalid vuid set to zero. */
12006 4 : cli_state_set_uid(cli, 0);
12007 :
12008 : /* This should succeed. */
12009 4 : status = cli_tdis(cli);
12010 :
12011 4 : if (NT_STATUS_IS_OK(status)) {
12012 4 : d_printf("First tdis with invalid vuid should succeed.\n");
12013 : } else {
12014 0 : d_printf("First tdis failed (%s)\n", nt_errstr(status));
12015 0 : correct = false;
12016 0 : cli->smb1.tcon = tcon_copy;
12017 0 : goto out;
12018 : }
12019 :
12020 4 : cli->smb1.tcon = tcon_copy;
12021 4 : cli_state_set_uid(cli, old_vuid);
12022 4 : cli_state_set_tid(cli, old_cnum);
12023 :
12024 : /* This should fail. */
12025 4 : status = cli_tdis(cli);
12026 4 : if (NT_STATUS_IS_OK(status)) {
12027 0 : d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
12028 0 : correct = false;
12029 0 : goto out;
12030 : } else {
12031 : /* Should be bad tid. */
12032 4 : if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
12033 4 : NT_STATUS_NETWORK_NAME_DELETED)) {
12034 0 : correct = false;
12035 0 : goto out;
12036 : }
12037 : }
12038 :
12039 4 : cli_rmdir(cli, "\\uid_reg_test");
12040 :
12041 4 : out:
12042 :
12043 4 : cli_shutdown(cli);
12044 4 : return correct;
12045 : }
12046 :
12047 :
12048 : static const char *illegal_chars = "*\\/?<>|\":";
12049 : static char force_shortname_chars[] = " +,.[];=\177";
12050 :
12051 8 : static NTSTATUS shortname_del_fn(struct file_info *finfo,
12052 : const char *mask, void *state)
12053 : {
12054 8 : struct cli_state *pcli = (struct cli_state *)state;
12055 0 : fstring fname;
12056 8 : NTSTATUS status = NT_STATUS_OK;
12057 :
12058 8 : slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
12059 :
12060 8 : if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
12061 8 : return NT_STATUS_OK;
12062 :
12063 0 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
12064 0 : status = cli_rmdir(pcli, fname);
12065 0 : if (!NT_STATUS_IS_OK(status)) {
12066 0 : printf("del_fn: failed to rmdir %s\n,", fname );
12067 : }
12068 : } else {
12069 0 : status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12070 0 : if (!NT_STATUS_IS_OK(status)) {
12071 0 : printf("del_fn: failed to unlink %s\n,", fname );
12072 : }
12073 : }
12074 0 : return status;
12075 : }
12076 :
12077 : struct sn_state {
12078 : int matched;
12079 : int i;
12080 : bool val;
12081 : };
12082 :
12083 348 : static NTSTATUS shortname_list_fn(struct file_info *finfo,
12084 : const char *name, void *state)
12085 : {
12086 348 : struct sn_state *s = (struct sn_state *)state;
12087 348 : int i = s->i;
12088 :
12089 : #if 0
12090 : printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
12091 : i, finfo->name, finfo->short_name);
12092 : #endif
12093 :
12094 348 : if (strchr(force_shortname_chars, i)) {
12095 36 : if (!finfo->short_name) {
12096 : /* Shortname not created when it should be. */
12097 0 : d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
12098 : __location__, finfo->name, i);
12099 0 : s->val = true;
12100 : }
12101 312 : } else if (finfo->short_name){
12102 : /* Shortname created when it should not be. */
12103 0 : d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
12104 : __location__, finfo->short_name, finfo->name);
12105 0 : s->val = true;
12106 : }
12107 348 : s->matched += 1;
12108 348 : return NT_STATUS_OK;
12109 : }
12110 :
12111 4 : static bool run_shortname_test(int dummy)
12112 : {
12113 0 : static struct cli_state *cli;
12114 4 : bool correct = True;
12115 0 : int i;
12116 0 : struct sn_state s;
12117 0 : char fname[40];
12118 0 : NTSTATUS status;
12119 :
12120 4 : printf("starting shortname test\n");
12121 :
12122 4 : if (!torture_open_connection(&cli, 0)) {
12123 0 : return False;
12124 : }
12125 :
12126 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
12127 :
12128 4 : cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12129 4 : cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12130 4 : cli_rmdir(cli, "\\shortname");
12131 :
12132 4 : status = cli_mkdir(cli, "\\shortname");
12133 4 : if (!NT_STATUS_IS_OK(status)) {
12134 0 : d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
12135 : __location__, nt_errstr(status));
12136 0 : correct = false;
12137 0 : goto out;
12138 : }
12139 :
12140 4 : if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
12141 0 : correct = false;
12142 0 : goto out;
12143 : }
12144 4 : if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
12145 0 : correct = false;
12146 0 : goto out;
12147 : }
12148 :
12149 4 : s.val = false;
12150 :
12151 388 : for (i = 32; i < 128; i++) {
12152 384 : uint16_t fnum = (uint16_t)-1;
12153 :
12154 384 : s.i = i;
12155 :
12156 384 : if (strchr(illegal_chars, i)) {
12157 36 : continue;
12158 : }
12159 348 : fname[15] = i;
12160 :
12161 348 : status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12162 : FILE_SHARE_READ|FILE_SHARE_WRITE,
12163 : FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12164 348 : if (!NT_STATUS_IS_OK(status)) {
12165 0 : d_printf("(%s) cli_nt_create of %s failed: %s\n",
12166 : __location__, fname, nt_errstr(status));
12167 0 : correct = false;
12168 0 : goto out;
12169 : }
12170 348 : cli_close(cli, fnum);
12171 :
12172 348 : s.matched = 0;
12173 348 : status = cli_list(cli, "\\shortname\\test*.*", 0,
12174 : shortname_list_fn, &s);
12175 348 : if (s.matched != 1) {
12176 0 : d_printf("(%s) failed to list %s: %s\n",
12177 : __location__, fname, nt_errstr(status));
12178 0 : correct = false;
12179 0 : goto out;
12180 : }
12181 :
12182 348 : status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12183 348 : if (!NT_STATUS_IS_OK(status)) {
12184 0 : d_printf("(%s) failed to delete %s: %s\n",
12185 : __location__, fname, nt_errstr(status));
12186 0 : correct = false;
12187 0 : goto out;
12188 : }
12189 :
12190 348 : if (s.val) {
12191 0 : correct = false;
12192 0 : goto out;
12193 : }
12194 : }
12195 :
12196 4 : out:
12197 :
12198 4 : cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12199 4 : cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12200 4 : cli_rmdir(cli, "\\shortname");
12201 4 : torture_close_connection(cli);
12202 4 : return correct;
12203 : }
12204 :
12205 : TLDAPRC callback_code;
12206 :
12207 1912 : static void pagedsearch_cb(struct tevent_req *req)
12208 : {
12209 0 : TLDAPRC rc;
12210 0 : struct tldap_message *msg;
12211 0 : char *dn;
12212 :
12213 1912 : rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12214 1912 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12215 0 : d_printf("tldap_search_paged_recv failed: %s\n",
12216 : tldap_rc2string(rc));
12217 0 : callback_code = rc;
12218 0 : return;
12219 : }
12220 1912 : if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12221 32 : TALLOC_FREE(msg);
12222 32 : return;
12223 : }
12224 1880 : if (!tldap_entry_dn(msg, &dn)) {
12225 0 : d_printf("tldap_entry_dn failed\n");
12226 0 : return;
12227 : }
12228 1880 : d_printf("%s\n", dn);
12229 1880 : TALLOC_FREE(msg);
12230 : }
12231 :
12232 : enum tldap_extended_val {
12233 : EXTENDED_ZERO = 0,
12234 : EXTENDED_ONE = 1,
12235 : EXTENDED_NONE = 2,
12236 : };
12237 :
12238 : /*
12239 : * Construct an extended dn control with either no value, 0 or 1
12240 : *
12241 : * No value and 0 are equivalent (non-hyphenated GUID)
12242 : * 1 has the hyphenated GUID
12243 : */
12244 : static struct tldap_control *
12245 24 : tldap_build_extended_control(enum tldap_extended_val val)
12246 : {
12247 0 : struct tldap_control empty_control;
12248 0 : struct asn1_data *data;
12249 :
12250 24 : ZERO_STRUCT(empty_control);
12251 :
12252 24 : if (val != EXTENDED_NONE) {
12253 16 : data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12254 :
12255 16 : if (!data) {
12256 0 : return NULL;
12257 : }
12258 :
12259 16 : if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12260 0 : return NULL;
12261 : }
12262 :
12263 16 : if (!asn1_write_Integer(data, (int)val)) {
12264 0 : return NULL;
12265 : }
12266 :
12267 16 : if (!asn1_pop_tag(data)) {
12268 0 : return NULL;
12269 : }
12270 :
12271 16 : if (!asn1_blob(data, &empty_control.value)) {
12272 0 : return NULL;
12273 : }
12274 : }
12275 :
12276 24 : empty_control.oid = "1.2.840.113556.1.4.529";
12277 24 : empty_control.critical = true;
12278 :
12279 24 : return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12280 :
12281 : }
12282 :
12283 24 : static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12284 : enum tldap_extended_val control_val)
12285 : {
12286 24 : struct tldap_control *control = tldap_build_extended_control(control_val);
12287 24 : char *dn = NULL;
12288 0 : struct tldap_message **msg;
12289 0 : TLDAPRC rc;
12290 :
12291 24 : rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12292 : "(objectClass=*)", NULL, 0, 0,
12293 : control, 1, NULL,
12294 : 0, 0, 0, 0, talloc_tos(), &msg);
12295 24 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12296 0 : d_printf("tldap_search for domain DN failed: %s\n",
12297 : tldap_errstr(talloc_tos(), ld, rc));
12298 0 : return false;
12299 : }
12300 :
12301 24 : if (!tldap_entry_dn(msg[0], &dn)) {
12302 0 : d_printf("tldap_search domain DN fetch failed: %s\n",
12303 : tldap_errstr(talloc_tos(), ld, rc));
12304 0 : return false;
12305 : }
12306 :
12307 24 : d_printf("%s\n", dn);
12308 : {
12309 0 : uint32_t time_low;
12310 0 : uint32_t time_mid, time_hi_and_version;
12311 0 : uint32_t clock_seq[2];
12312 0 : uint32_t node[6];
12313 0 : char next;
12314 :
12315 24 : switch (control_val) {
12316 16 : case EXTENDED_NONE:
12317 : case EXTENDED_ZERO:
12318 : /*
12319 : * When reading GUIDs with hyphens, scanf will treat
12320 : * hyphen as a hex character (and counts as part of the
12321 : * width). This creates leftover GUID string which we
12322 : * check will for with 'next' and closing '>'.
12323 : */
12324 16 : if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12325 : &time_low, &time_mid,
12326 : &time_hi_and_version, &clock_seq[0],
12327 : &clock_seq[1], &node[0], &node[1],
12328 : &node[2], &node[3], &node[4],
12329 : &node[5], &next)) {
12330 : /* This GUID is good */
12331 : } else {
12332 0 : d_printf("GUID format in control (no hyphens) doesn't match output\n");
12333 0 : return false;
12334 : }
12335 :
12336 16 : break;
12337 8 : case EXTENDED_ONE:
12338 8 : if (12 == sscanf(dn,
12339 : "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12340 : &time_low, &time_mid,
12341 : &time_hi_and_version, &clock_seq[0],
12342 : &clock_seq[1], &node[0], &node[1],
12343 : &node[2], &node[3], &node[4],
12344 : &node[5], &next)) {
12345 : /* This GUID is good */
12346 : } else {
12347 0 : d_printf("GUID format in control (with hyphens) doesn't match output\n");
12348 0 : return false;
12349 : }
12350 :
12351 8 : break;
12352 0 : default:
12353 0 : return false;
12354 : }
12355 : }
12356 :
12357 24 : return true;
12358 : }
12359 :
12360 8 : static bool run_tldap(int dummy)
12361 : {
12362 0 : struct tldap_context *ld;
12363 0 : int fd;
12364 0 : TLDAPRC rc;
12365 0 : NTSTATUS status;
12366 0 : struct sockaddr_storage addr;
12367 0 : struct tevent_context *ev;
12368 0 : struct tevent_req *req;
12369 0 : char *basedn;
12370 0 : const char *filter;
12371 8 : struct loadparm_context *lp_ctx = NULL;
12372 8 : int tcp_port = 389;
12373 8 : bool use_tls = false;
12374 8 : bool use_starttls = false;
12375 8 : int wrap_flags = -1;
12376 8 : uint32_t gensec_features = 0;
12377 :
12378 8 : lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
12379 :
12380 8 : wrap_flags = lpcfg_client_ldap_sasl_wrapping(lp_ctx);
12381 :
12382 8 : if (wrap_flags & ADS_AUTH_SASL_LDAPS) {
12383 2 : use_tls = true;
12384 2 : tcp_port = 636;
12385 6 : } else if (wrap_flags & ADS_AUTH_SASL_STARTTLS) {
12386 2 : use_tls = true;
12387 2 : use_starttls = true;
12388 : }
12389 8 : if (wrap_flags & ADS_AUTH_SASL_SEAL) {
12390 2 : gensec_features |= GENSEC_FEATURE_SEAL;
12391 : }
12392 8 : if (wrap_flags & ADS_AUTH_SASL_SIGN) {
12393 2 : gensec_features |= GENSEC_FEATURE_SIGN;
12394 : }
12395 :
12396 8 : if (gensec_features != 0) {
12397 4 : gensec_features |= GENSEC_FEATURE_LDAP_STYLE;
12398 : }
12399 :
12400 8 : if (!resolve_name(host, &addr, 0, false)) {
12401 0 : d_printf("could not find host %s\n", host);
12402 0 : return false;
12403 : }
12404 8 : status = open_socket_out(&addr, tcp_port, 9999, &fd);
12405 8 : if (!NT_STATUS_IS_OK(status)) {
12406 0 : d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12407 0 : return false;
12408 : }
12409 :
12410 8 : ld = tldap_context_create(talloc_tos(), fd);
12411 8 : if (ld == NULL) {
12412 0 : close(fd);
12413 0 : d_printf("tldap_context_create failed\n");
12414 0 : return false;
12415 : }
12416 :
12417 8 : if (use_tls && !tldap_has_tls_tstream(ld)) {
12418 4 : tldap_set_starttls_needed(ld, use_starttls);
12419 :
12420 4 : rc = tldap_tls_connect(ld, lp_ctx, host);
12421 4 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12422 0 : DBG_ERR("tldap_tls_connect(%s) failed: %s\n",
12423 : host, tldap_errstr(talloc_tos(), ld, rc));
12424 0 : return false;
12425 : }
12426 : }
12427 :
12428 8 : rc = tldap_fetch_rootdse(ld);
12429 8 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12430 0 : d_printf("tldap_fetch_rootdse failed: %s\n",
12431 : tldap_errstr(talloc_tos(), ld, rc));
12432 0 : return false;
12433 : }
12434 :
12435 8 : basedn = tldap_talloc_single_attribute(
12436 : tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12437 8 : if (basedn == NULL) {
12438 0 : d_printf("no defaultNamingContext\n");
12439 0 : return false;
12440 : }
12441 8 : d_printf("defaultNamingContext: %s\n", basedn);
12442 :
12443 8 : ev = samba_tevent_context_init(talloc_tos());
12444 8 : if (ev == NULL) {
12445 0 : d_printf("tevent_context_init failed\n");
12446 0 : return false;
12447 : }
12448 :
12449 8 : rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12450 : lp_ctx, gensec_features);
12451 8 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12452 0 : d_printf("tldap_gensec_bind failed\n");
12453 0 : return false;
12454 : }
12455 :
12456 8 : callback_code = TLDAP_SUCCESS;
12457 :
12458 8 : req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12459 : TLDAP_SCOPE_SUB, "(objectclass=*)",
12460 : NULL, 0, 0,
12461 : NULL, 0, NULL, 0, 0, 0, 0, 5);
12462 8 : if (req == NULL) {
12463 0 : d_printf("tldap_search_paged_send failed\n");
12464 0 : return false;
12465 : }
12466 8 : tevent_req_set_callback(req, pagedsearch_cb, NULL);
12467 :
12468 8 : tevent_req_poll(req, ev);
12469 :
12470 8 : TALLOC_FREE(req);
12471 :
12472 8 : rc = callback_code;
12473 :
12474 8 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12475 0 : d_printf("tldap_search with paging failed: %s\n",
12476 : tldap_errstr(talloc_tos(), ld, rc));
12477 0 : return false;
12478 : }
12479 :
12480 : /* test search filters against rootDSE */
12481 8 : filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12482 : "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12483 :
12484 8 : rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12485 : NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12486 : talloc_tos(), NULL);
12487 8 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12488 0 : d_printf("tldap_search with complex filter failed: %s\n",
12489 : tldap_errstr(talloc_tos(), ld, rc));
12490 0 : return false;
12491 : }
12492 :
12493 : /*
12494 : * Tests to check for regression of:
12495 : *
12496 : * https://bugzilla.samba.org/show_bug.cgi?id=14029
12497 : *
12498 : * TLDAP used here to pick apart the original string DN (with GUID)
12499 : */
12500 8 : if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12501 0 : d_printf("tldap_search with extended dn (no val) failed: %s\n",
12502 : tldap_errstr(talloc_tos(), ld, rc));
12503 0 : return false;
12504 : }
12505 8 : if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12506 0 : d_printf("tldap_search with extended dn (0) failed: %s\n",
12507 : tldap_errstr(talloc_tos(), ld, rc));
12508 0 : return false;
12509 : }
12510 8 : if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12511 0 : d_printf("tldap_search with extended dn (1) failed: %s\n",
12512 : tldap_errstr(talloc_tos(), ld, rc));
12513 0 : return false;
12514 : }
12515 :
12516 8 : TALLOC_FREE(ld);
12517 8 : return true;
12518 : }
12519 :
12520 : /* Torture test to ensure no regression of :
12521 : https://bugzilla.samba.org/show_bug.cgi?id=7084
12522 : */
12523 :
12524 4 : static bool run_dir_createtime(int dummy)
12525 : {
12526 0 : struct cli_state *cli;
12527 4 : const char *dname = "\\testdir_createtime";
12528 4 : const char *fname = "\\testdir_createtime\\testfile";
12529 0 : NTSTATUS status;
12530 0 : struct timespec create_time;
12531 0 : struct timespec create_time1;
12532 0 : uint16_t fnum;
12533 4 : bool ret = false;
12534 0 : uint64_t ino;
12535 :
12536 4 : if (!torture_open_connection(&cli, 0)) {
12537 0 : return false;
12538 : }
12539 :
12540 4 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12541 : /* Ensure ino is zero, SMB2 gets a real one. */
12542 0 : ino = 0;
12543 : } else {
12544 : /* Ensure ino is -1, SMB1 never gets a real one. */
12545 4 : ino = (uint64_t)-1;
12546 : }
12547 :
12548 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12549 4 : cli_rmdir(cli, dname);
12550 :
12551 4 : status = cli_mkdir(cli, dname);
12552 4 : if (!NT_STATUS_IS_OK(status)) {
12553 0 : printf("mkdir failed: %s\n", nt_errstr(status));
12554 0 : goto out;
12555 : }
12556 :
12557 4 : status = cli_qpathinfo2(cli,
12558 : dname,
12559 : &create_time,
12560 : NULL,
12561 : NULL,
12562 : NULL,
12563 : NULL,
12564 : NULL,
12565 : &ino,
12566 : NULL);
12567 4 : if (!NT_STATUS_IS_OK(status)) {
12568 0 : printf("cli_qpathinfo2 returned %s\n",
12569 : nt_errstr(status));
12570 0 : goto out;
12571 : }
12572 :
12573 4 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12574 : /* SMB2 should always return an inode. */
12575 0 : if (ino == 0) {
12576 0 : printf("SMB2 bad inode (0)\n");
12577 0 : goto out;
12578 : }
12579 : } else {
12580 : /* SMB1 must always return zero here. */
12581 4 : if (ino != 0) {
12582 0 : printf("SMB1 bad inode (!0)\n");
12583 0 : goto out;
12584 : }
12585 : }
12586 :
12587 : /* Sleep 3 seconds, then create a file. */
12588 4 : sleep(3);
12589 :
12590 4 : status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12591 : DENY_NONE, &fnum);
12592 4 : if (!NT_STATUS_IS_OK(status)) {
12593 0 : printf("cli_openx failed: %s\n", nt_errstr(status));
12594 0 : goto out;
12595 : }
12596 :
12597 4 : status = cli_qpathinfo2(cli,
12598 : dname,
12599 : &create_time1,
12600 : NULL,
12601 : NULL,
12602 : NULL,
12603 : NULL,
12604 : NULL,
12605 : NULL,
12606 : NULL);
12607 4 : if (!NT_STATUS_IS_OK(status)) {
12608 0 : printf("cli_qpathinfo2 (2) returned %s\n",
12609 : nt_errstr(status));
12610 0 : goto out;
12611 : }
12612 :
12613 4 : if (timespec_compare(&create_time1, &create_time)) {
12614 0 : printf("run_dir_createtime: create time was updated (error)\n");
12615 : } else {
12616 4 : printf("run_dir_createtime: create time was not updated (correct)\n");
12617 4 : ret = true;
12618 : }
12619 :
12620 4 : out:
12621 :
12622 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12623 4 : cli_rmdir(cli, dname);
12624 4 : if (!torture_close_connection(cli)) {
12625 0 : ret = false;
12626 : }
12627 4 : return ret;
12628 : }
12629 :
12630 :
12631 4 : static bool run_streamerror(int dummy)
12632 : {
12633 0 : struct cli_state *cli;
12634 4 : const char *dname = "\\testdir_streamerror";
12635 4 : const char *streamname =
12636 : "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12637 0 : NTSTATUS status;
12638 0 : time_t change_time, access_time, write_time;
12639 0 : off_t size;
12640 0 : uint16_t fnum;
12641 0 : uint32_t attr;
12642 4 : bool ret = true;
12643 :
12644 4 : if (!torture_open_connection(&cli, 0)) {
12645 0 : return false;
12646 : }
12647 :
12648 4 : torture_deltree(cli, dname);
12649 :
12650 4 : status = cli_mkdir(cli, dname);
12651 4 : if (!NT_STATUS_IS_OK(status)) {
12652 0 : printf("mkdir failed: %s\n", nt_errstr(status));
12653 0 : return false;
12654 : }
12655 :
12656 4 : status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12657 : &write_time, &size, &attr);
12658 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12659 0 : printf("pathinfo returned %s, expected "
12660 : "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12661 : nt_errstr(status));
12662 0 : ret = false;
12663 : }
12664 :
12665 4 : status = cli_ntcreate(cli, streamname, 0x16,
12666 : FILE_READ_DATA|FILE_READ_EA|
12667 : FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12668 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12669 : FILE_OPEN, 0, 0, &fnum, NULL);
12670 :
12671 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12672 0 : printf("ntcreate returned %s, expected "
12673 : "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12674 : nt_errstr(status));
12675 0 : ret = false;
12676 : }
12677 :
12678 :
12679 4 : cli_rmdir(cli, dname);
12680 4 : return ret;
12681 : }
12682 :
12683 : struct pidtest_state {
12684 : bool success;
12685 : uint16_t vwv[1];
12686 : DATA_BLOB data;
12687 : };
12688 :
12689 : static void pid_echo_done(struct tevent_req *subreq);
12690 :
12691 4 : static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12692 : struct tevent_context *ev,
12693 : struct cli_state *cli)
12694 : {
12695 0 : struct tevent_req *req, *subreq;
12696 0 : struct pidtest_state *state;
12697 :
12698 4 : req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12699 4 : if (req == NULL) {
12700 0 : return NULL;
12701 : }
12702 :
12703 4 : SSVAL(state->vwv, 0, 1);
12704 4 : state->data = data_blob_const("hello", 5);
12705 :
12706 4 : subreq = smb1cli_req_send(state,
12707 : ev,
12708 : cli->conn,
12709 : SMBecho,
12710 : 0, 0, /* *_flags */
12711 : 0, 0, /* *_flags2 */
12712 4 : cli->timeout,
12713 : 0xDEADBEEF, /* pid */
12714 : NULL, /* tcon */
12715 : NULL, /* session */
12716 4 : ARRAY_SIZE(state->vwv), state->vwv,
12717 4 : state->data.length, state->data.data);
12718 :
12719 4 : if (tevent_req_nomem(subreq, req)) {
12720 0 : return tevent_req_post(req, ev);
12721 : }
12722 4 : tevent_req_set_callback(subreq, pid_echo_done, req);
12723 4 : return req;
12724 : }
12725 :
12726 4 : static void pid_echo_done(struct tevent_req *subreq)
12727 : {
12728 4 : struct tevent_req *req = tevent_req_callback_data(
12729 : subreq, struct tevent_req);
12730 4 : struct pidtest_state *state = tevent_req_data(
12731 : req, struct pidtest_state);
12732 0 : NTSTATUS status;
12733 0 : uint32_t num_bytes;
12734 4 : uint8_t *bytes = NULL;
12735 4 : struct iovec *recv_iov = NULL;
12736 4 : uint8_t *phdr = NULL;
12737 4 : uint16_t pidlow = 0;
12738 4 : uint16_t pidhigh = 0;
12739 4 : struct smb1cli_req_expected_response expected[] = {
12740 : {
12741 : .status = NT_STATUS_OK,
12742 : .wct = 1,
12743 : },
12744 : };
12745 :
12746 4 : status = smb1cli_req_recv(subreq, state,
12747 : &recv_iov,
12748 : &phdr,
12749 : NULL, /* pwct */
12750 : NULL, /* pvwv */
12751 : NULL, /* pvwv_offset */
12752 : &num_bytes,
12753 : &bytes,
12754 : NULL, /* pbytes_offset */
12755 : NULL, /* pinbuf */
12756 : expected, ARRAY_SIZE(expected));
12757 :
12758 4 : TALLOC_FREE(subreq);
12759 :
12760 4 : if (!NT_STATUS_IS_OK(status)) {
12761 0 : tevent_req_nterror(req, status);
12762 0 : return;
12763 : }
12764 :
12765 4 : if (num_bytes != state->data.length) {
12766 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12767 0 : return;
12768 : }
12769 :
12770 4 : if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12771 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12772 0 : return;
12773 : }
12774 :
12775 : /* Check pid low/high == DEADBEEF */
12776 4 : pidlow = SVAL(phdr, HDR_PID);
12777 4 : if (pidlow != 0xBEEF){
12778 0 : printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12779 : (unsigned int)pidlow);
12780 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12781 0 : return;
12782 : }
12783 4 : pidhigh = SVAL(phdr, HDR_PIDHIGH);
12784 4 : if (pidhigh != 0xDEAD){
12785 0 : printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12786 : (unsigned int)pidhigh);
12787 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12788 0 : return;
12789 : }
12790 :
12791 4 : tevent_req_done(req);
12792 : }
12793 :
12794 4 : static NTSTATUS pid_echo_recv(struct tevent_req *req)
12795 : {
12796 4 : return tevent_req_simple_recv_ntstatus(req);
12797 : }
12798 :
12799 4 : static bool run_pidhigh(int dummy)
12800 : {
12801 4 : bool success = false;
12802 4 : struct cli_state *cli = NULL;
12803 0 : NTSTATUS status;
12804 4 : struct tevent_context *ev = NULL;
12805 4 : struct tevent_req *req = NULL;
12806 4 : TALLOC_CTX *frame = talloc_stackframe();
12807 :
12808 4 : printf("starting pid high test\n");
12809 4 : if (!torture_open_connection(&cli, 0)) {
12810 0 : return false;
12811 : }
12812 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
12813 :
12814 4 : ev = samba_tevent_context_init(frame);
12815 4 : if (ev == NULL) {
12816 0 : goto fail;
12817 : }
12818 :
12819 4 : req = pid_echo_send(frame, ev, cli);
12820 4 : if (req == NULL) {
12821 0 : goto fail;
12822 : }
12823 :
12824 4 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12825 0 : goto fail;
12826 : }
12827 :
12828 4 : status = pid_echo_recv(req);
12829 4 : if (NT_STATUS_IS_OK(status)) {
12830 4 : printf("pid high test ok\n");
12831 4 : success = true;
12832 : }
12833 :
12834 0 : fail:
12835 :
12836 4 : TALLOC_FREE(frame);
12837 4 : torture_close_connection(cli);
12838 4 : return success;
12839 : }
12840 :
12841 : /*
12842 : Test Windows open on a bad POSIX symlink.
12843 : */
12844 4 : static bool run_symlink_open_test(int dummy)
12845 : {
12846 0 : static struct cli_state *cli;
12847 4 : const char *fname = "non_existant_file";
12848 4 : const char *sname = "dangling_symlink";
12849 4 : uint16_t fnum = (uint16_t)-1;
12850 4 : bool correct = false;
12851 0 : NTSTATUS status;
12852 4 : TALLOC_CTX *frame = NULL;
12853 :
12854 4 : frame = talloc_stackframe();
12855 :
12856 4 : printf("Starting Windows bad symlink open test\n");
12857 :
12858 4 : if (!torture_open_connection(&cli, 0)) {
12859 0 : TALLOC_FREE(frame);
12860 0 : return false;
12861 : }
12862 :
12863 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
12864 :
12865 4 : status = torture_setup_unix_extensions(cli);
12866 4 : if (!NT_STATUS_IS_OK(status)) {
12867 0 : TALLOC_FREE(frame);
12868 0 : return false;
12869 : }
12870 :
12871 : /* Ensure nothing exists. */
12872 4 : cli_setatr(cli, fname, 0, 0);
12873 4 : cli_posix_unlink(cli, fname);
12874 4 : cli_setatr(cli, sname, 0, 0);
12875 4 : cli_posix_unlink(cli, sname);
12876 :
12877 : /* Create a symlink pointing nowhere. */
12878 4 : status = cli_posix_symlink(cli, fname, sname);
12879 4 : if (!NT_STATUS_IS_OK(status)) {
12880 0 : printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12881 : sname,
12882 : fname,
12883 : nt_errstr(status));
12884 0 : goto out;
12885 : }
12886 :
12887 : /* Now ensure that a Windows open doesn't hang. */
12888 4 : status = cli_ntcreate(cli,
12889 : sname,
12890 : 0,
12891 : FILE_READ_DATA|FILE_WRITE_DATA,
12892 : 0,
12893 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12894 : FILE_OPEN_IF,
12895 : 0x0,
12896 : 0x0,
12897 : &fnum,
12898 : NULL);
12899 :
12900 : /*
12901 : * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12902 : * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12903 : * we use O_NOFOLLOW on the server or not.
12904 : */
12905 4 : if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12906 0 : NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12907 : {
12908 4 : correct = true;
12909 : } else {
12910 0 : printf("cli_ntcreate of %s returned %s - should return"
12911 : " either (%s) or (%s)\n",
12912 : sname,
12913 : nt_errstr(status),
12914 0 : nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12915 0 : nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12916 0 : goto out;
12917 : }
12918 :
12919 4 : correct = true;
12920 :
12921 4 : out:
12922 :
12923 4 : if (fnum != (uint16_t)-1) {
12924 0 : cli_close(cli, fnum);
12925 0 : fnum = (uint16_t)-1;
12926 : }
12927 :
12928 4 : cli_setatr(cli, sname, 0, 0);
12929 4 : cli_posix_unlink(cli, sname);
12930 4 : cli_setatr(cli, fname, 0, 0);
12931 4 : cli_posix_unlink(cli, fname);
12932 :
12933 4 : if (!torture_close_connection(cli)) {
12934 0 : correct = false;
12935 : }
12936 :
12937 4 : TALLOC_FREE(frame);
12938 4 : return correct;
12939 : }
12940 :
12941 16 : static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12942 : const char *name,
12943 : void *state)
12944 : {
12945 16 : char **mangled_name_return = (char **)state;
12946 16 : bool is_mangled = strchr(finfo->name, '~');
12947 :
12948 16 : if (is_mangled) {
12949 8 : *mangled_name_return = talloc_strdup(NULL, finfo->name);
12950 8 : if (*mangled_name_return == NULL) {
12951 0 : return NT_STATUS_NO_MEMORY;
12952 : }
12953 : }
12954 16 : return NT_STATUS_OK;
12955 : }
12956 :
12957 4 : static bool run_smb1_wild_mangle_unlink_test(int dummy)
12958 : {
12959 0 : static struct cli_state *cli_posix = NULL;
12960 0 : static struct cli_state *cli = NULL;
12961 4 : uint16_t fnum = (uint16_t)-1;
12962 4 : bool correct = false;
12963 4 : const char *dname = "smb1_wild_mangle_unlink";
12964 4 : const char *aname = "smb1_wild_mangle_unlink/a";
12965 4 : const char *star_name = "smb1_wild_mangle_unlink/*";
12966 4 : char *windows_unlink_name = NULL;
12967 4 : char *mangled_name = NULL;
12968 0 : NTSTATUS status;
12969 :
12970 4 : printf("Starting SMB1 wild mangle unlink test\n");
12971 :
12972 : /* Open a Windows connection. */
12973 4 : if (!torture_open_connection(&cli, 0)) {
12974 0 : return false;
12975 : }
12976 :
12977 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
12978 :
12979 : /* Open a POSIX connection. */
12980 4 : if (!torture_open_connection(&cli_posix, 0)) {
12981 0 : goto out;
12982 : }
12983 :
12984 4 : smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12985 :
12986 4 : status = torture_setup_unix_extensions(cli_posix);
12987 4 : if (!NT_STATUS_IS_OK(status)) {
12988 0 : printf("server doesn't support POSIX\n");
12989 0 : goto out;
12990 : }
12991 :
12992 : /* Start fresh. */
12993 4 : torture_deltree(cli, dname);
12994 :
12995 : /*
12996 : * Create two files - 'a' and '*'.
12997 : * We need POSIX extensions for this as '*'
12998 : * is not a valid Windows name.
12999 : */
13000 :
13001 4 : status = cli_mkdir(cli, dname);
13002 4 : if (!NT_STATUS_IS_OK(status)) {
13003 0 : printf("cli_mkdir of %s returned %s\n",
13004 : dname,
13005 : nt_errstr(status));
13006 0 : goto out;
13007 : }
13008 :
13009 4 : status = cli_posix_open(cli_posix,
13010 : aname,
13011 : O_RDWR|O_CREAT|O_EXCL,
13012 : 0660,
13013 : &fnum);
13014 4 : if (!NT_STATUS_IS_OK(status)) {
13015 0 : printf("cli_posix_open (create) of %s returned %s\n",
13016 : aname,
13017 : nt_errstr(status));
13018 0 : goto out;
13019 : }
13020 4 : status = cli_close(cli_posix, fnum);
13021 4 : if (!NT_STATUS_IS_OK(status)) {
13022 0 : goto out;
13023 : }
13024 4 : status = cli_posix_open(cli_posix,
13025 : star_name,
13026 : O_RDWR|O_CREAT|O_EXCL,
13027 : 0660,
13028 : &fnum);
13029 4 : if (!NT_STATUS_IS_OK(status)) {
13030 0 : printf("cli_posix_open (create) of %s returned %s\n",
13031 : star_name,
13032 : nt_errstr(status));
13033 0 : goto out;
13034 : }
13035 4 : status = cli_close(cli_posix, fnum);
13036 4 : if (!NT_STATUS_IS_OK(status)) {
13037 0 : goto out;
13038 : }
13039 :
13040 4 : status = cli_list(cli,
13041 : star_name,
13042 : 0,
13043 : smb1_wild_mangle_list_fn,
13044 : &mangled_name);
13045 4 : if (!NT_STATUS_IS_OK(status)) {
13046 0 : printf("cli_list of %s returned %s\n",
13047 : star_name,
13048 : nt_errstr(status));
13049 0 : goto out;
13050 : }
13051 :
13052 4 : if (mangled_name == NULL) {
13053 0 : goto out;
13054 : }
13055 :
13056 4 : printf("mangled_name = %s\n",
13057 : mangled_name);
13058 :
13059 : /*
13060 : * Try a Windows unlink with the mangled name.
13061 : * This should *NOT* unlink the 'a' name.
13062 : */
13063 :
13064 4 : windows_unlink_name = talloc_asprintf(cli_posix,
13065 : "%s\\%s",
13066 : dname,
13067 : mangled_name);
13068 :
13069 4 : status = cli_unlink(cli, windows_unlink_name, 0);
13070 4 : if (!NT_STATUS_IS_OK(status)) {
13071 0 : printf("cli_unlink of %s returned %s\n",
13072 : windows_unlink_name,
13073 : nt_errstr(status));
13074 0 : goto out;
13075 : }
13076 :
13077 : /* Does 'a' still exist ? */
13078 4 : status = cli_posix_open(cli_posix,
13079 : aname,
13080 : O_RDONLY,
13081 : 0,
13082 : &fnum);
13083 4 : if (!NT_STATUS_IS_OK(status)) {
13084 0 : printf("cli_posix_open O_RNONLY of %s returned %s\n",
13085 : aname,
13086 : nt_errstr(status));
13087 0 : goto out;
13088 : }
13089 :
13090 4 : status = cli_close(cli_posix, fnum);
13091 4 : if (!NT_STATUS_IS_OK(status)) {
13092 0 : goto out;
13093 : }
13094 :
13095 4 : correct = true;
13096 :
13097 4 : out:
13098 :
13099 4 : TALLOC_FREE(windows_unlink_name);
13100 4 : TALLOC_FREE(mangled_name);
13101 :
13102 4 : if (cli != NULL) {
13103 4 : torture_deltree(cli, dname);
13104 4 : torture_close_connection(cli);
13105 : }
13106 :
13107 4 : if (cli_posix != NULL) {
13108 4 : torture_close_connection(cli_posix);
13109 : }
13110 :
13111 4 : return correct;
13112 : }
13113 :
13114 4 : static bool run_smb1_wild_mangle_rename_test(int dummy)
13115 : {
13116 0 : static struct cli_state *cli_posix = NULL;
13117 0 : static struct cli_state *cli = NULL;
13118 4 : uint16_t fnum = (uint16_t)-1;
13119 4 : bool correct = false;
13120 4 : const char *dname = "smb1_wild_mangle_rename";
13121 4 : const char *fooname = "smb1_wild_mangle_rename/foo";
13122 4 : const char *foostar_name = "smb1_wild_mangle_rename/fo*";
13123 4 : const char *wild_name = "smb1_wild_mangle_rename/*";
13124 4 : char *windows_rename_src = NULL;
13125 4 : const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
13126 4 : char *mangled_name = NULL;
13127 0 : NTSTATUS status;
13128 :
13129 4 : printf("Starting SMB1 wild mangle rename test\n");
13130 :
13131 4 : if (!torture_open_connection(&cli_posix, 0)) {
13132 0 : return false;
13133 : }
13134 :
13135 4 : smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
13136 :
13137 4 : status = torture_setup_unix_extensions(cli_posix);
13138 4 : if (!NT_STATUS_IS_OK(status)) {
13139 0 : printf("server doesn't support POSIX\n");
13140 0 : return false;
13141 : }
13142 :
13143 : /* Open a Windows connection. */
13144 4 : if (!torture_open_connection(&cli, 0)) {
13145 0 : goto out;
13146 : }
13147 :
13148 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
13149 :
13150 : /* Ensure we start from fresh. */
13151 4 : torture_deltree(cli, dname);
13152 :
13153 : /*
13154 : * Create two files - 'foo' and 'fo*'.
13155 : * We need POSIX extensions for this as 'fo*'
13156 : * is not a valid Windows name.
13157 : */
13158 :
13159 4 : status = cli_posix_mkdir(cli_posix, dname, 0770);
13160 4 : if (!NT_STATUS_IS_OK(status)) {
13161 0 : printf("cli_posix_mkdir of %s returned %s\n",
13162 : dname,
13163 : nt_errstr(status));
13164 0 : goto out;
13165 : }
13166 :
13167 4 : status = cli_posix_open(cli_posix,
13168 : fooname,
13169 : O_RDWR|O_CREAT|O_EXCL,
13170 : 0660,
13171 : &fnum);
13172 4 : if (!NT_STATUS_IS_OK(status)) {
13173 0 : printf("cli_posix_open (create) of %s returned %s\n",
13174 : fooname,
13175 : nt_errstr(status));
13176 0 : goto out;
13177 : }
13178 4 : status = cli_close(cli_posix, fnum);
13179 4 : if (!NT_STATUS_IS_OK(status)) {
13180 0 : goto out;
13181 : }
13182 4 : status = cli_posix_open(cli_posix,
13183 : foostar_name,
13184 : O_RDWR|O_CREAT|O_EXCL,
13185 : 0660,
13186 : &fnum);
13187 4 : if (!NT_STATUS_IS_OK(status)) {
13188 0 : printf("cli_posix_open (create) of %s returned %s\n",
13189 : foostar_name,
13190 : nt_errstr(status));
13191 0 : goto out;
13192 : }
13193 4 : status = cli_close(cli_posix, fnum);
13194 4 : if (!NT_STATUS_IS_OK(status)) {
13195 0 : goto out;
13196 : }
13197 :
13198 : /*
13199 : * Get the mangled name. We can re-use the
13200 : * previous smb1_wild_mangle_list_fn for this.
13201 : */
13202 :
13203 4 : status = cli_list(cli,
13204 : wild_name,
13205 : 0,
13206 : smb1_wild_mangle_list_fn,
13207 : &mangled_name);
13208 4 : if (!NT_STATUS_IS_OK(status)) {
13209 0 : printf("cli_list of %s returned %s\n",
13210 : wild_name,
13211 : nt_errstr(status));
13212 0 : goto out;
13213 : }
13214 :
13215 4 : if (mangled_name == NULL) {
13216 0 : goto out;
13217 : }
13218 :
13219 4 : printf("mangled_name = %s\n",
13220 : mangled_name);
13221 :
13222 : /*
13223 : * Try a Windows rename with the mangled name.
13224 : * This should *NOT* rename the 'foo' name.
13225 : */
13226 :
13227 4 : windows_rename_src = talloc_asprintf(cli_posix,
13228 : "%s\\%s",
13229 : dname,
13230 : mangled_name);
13231 :
13232 4 : status = cli_rename(cli,
13233 : windows_rename_src,
13234 : windows_rename_dst,
13235 : false);
13236 4 : if (!NT_STATUS_IS_OK(status)) {
13237 0 : printf("cli_rename of %s -> %s returned %s\n",
13238 : windows_rename_src,
13239 : windows_rename_dst,
13240 : nt_errstr(status));
13241 0 : goto out;
13242 : }
13243 :
13244 : /* Does 'foo' still exist ? */
13245 4 : status = cli_posix_open(cli_posix,
13246 : fooname,
13247 : O_RDONLY,
13248 : 0,
13249 : &fnum);
13250 4 : if (!NT_STATUS_IS_OK(status)) {
13251 0 : printf("cli_posix_open O_RNONLY of %s returned %s\n",
13252 : fooname,
13253 : nt_errstr(status));
13254 0 : goto out;
13255 : }
13256 :
13257 4 : status = cli_close(cli_posix, fnum);
13258 4 : if (!NT_STATUS_IS_OK(status)) {
13259 0 : goto out;
13260 : }
13261 :
13262 4 : correct = true;
13263 :
13264 4 : out:
13265 :
13266 4 : TALLOC_FREE(mangled_name);
13267 4 : TALLOC_FREE(windows_rename_src);
13268 :
13269 4 : if (cli != NULL) {
13270 4 : torture_deltree(cli, dname);
13271 4 : torture_close_connection(cli);
13272 : }
13273 :
13274 4 : torture_close_connection(cli_posix);
13275 :
13276 4 : return correct;
13277 : }
13278 :
13279 : /*
13280 : * Only testing minimal time strings, as the others
13281 : * need (locale-dependent) guessing at what strftime does and
13282 : * even may differ in builds.
13283 : */
13284 1 : static bool timesubst_test(void)
13285 : {
13286 1 : TALLOC_CTX *ctx = NULL;
13287 : /* Sa 23. Dez 04:33:20 CET 2017 */
13288 1 : const struct timeval tv = { 1514000000, 123 };
13289 1 : const char* expect_minimal = "20171223_033320";
13290 1 : const char* expect_minus = "20171223_033320_000123";
13291 1 : char *s;
13292 1 : char *env_tz, *orig_tz = NULL;
13293 1 : bool result = true;
13294 :
13295 1 : ctx = talloc_new(NULL);
13296 :
13297 1 : env_tz = getenv("TZ");
13298 1 : if(env_tz) {
13299 1 : orig_tz = talloc_strdup(ctx, env_tz);
13300 : }
13301 1 : setenv("TZ", "UTC", 1);
13302 :
13303 1 : s = minimal_timeval_string(ctx, &tv, false);
13304 :
13305 1 : if(!s || strcmp(s, expect_minimal)) {
13306 0 : printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13307 : "[%s]\n", s ? s : "<nil>", expect_minimal);
13308 0 : result = false;
13309 : }
13310 1 : TALLOC_FREE(s);
13311 1 : s = minimal_timeval_string(ctx, &tv, true);
13312 1 : if(!s || strcmp(s, expect_minus)) {
13313 0 : printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13314 : "[%s]\n", s ? s : "<nil>", expect_minus);
13315 0 : result = false;
13316 : }
13317 1 : TALLOC_FREE(s);
13318 :
13319 1 : if(orig_tz) {
13320 1 : setenv("TZ", orig_tz, 1);
13321 : }
13322 :
13323 1 : TALLOC_FREE(ctx);
13324 1 : return result;
13325 : }
13326 :
13327 1 : static bool run_local_substitute(int dummy)
13328 : {
13329 1 : bool ok = true;
13330 :
13331 1 : ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13332 1 : ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13333 1 : ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13334 1 : ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13335 1 : ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13336 1 : ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13337 1 : ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13338 1 : ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13339 1 : ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13340 : /* Substitution depends on current time, so better test the underlying
13341 : formatting function. At least covers %t. */
13342 1 : ok &= timesubst_test();
13343 :
13344 : /* Different captialization rules in sub_basic... */
13345 :
13346 1 : ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13347 1 : "blaDOM") == 0);
13348 :
13349 1 : return ok;
13350 : }
13351 :
13352 1 : static bool run_local_base64(int dummy)
13353 : {
13354 1 : int i;
13355 1 : bool ret = true;
13356 :
13357 2000 : for (i=1; i<2000; i++) {
13358 1999 : DATA_BLOB blob1, blob2;
13359 1999 : char *b64;
13360 :
13361 1999 : blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13362 1999 : blob1.length = i;
13363 1999 : generate_random_buffer(blob1.data, blob1.length);
13364 :
13365 1999 : b64 = base64_encode_data_blob(talloc_tos(), blob1);
13366 1999 : if (b64 == NULL) {
13367 0 : d_fprintf(stderr, "base64_encode_data_blob failed "
13368 : "for %d bytes\n", i);
13369 0 : ret = false;
13370 : }
13371 1999 : blob2 = base64_decode_data_blob(b64);
13372 1999 : TALLOC_FREE(b64);
13373 :
13374 1999 : if (data_blob_cmp(&blob1, &blob2)) {
13375 0 : d_fprintf(stderr, "data_blob_cmp failed for %d "
13376 : "bytes\n", i);
13377 0 : ret = false;
13378 : }
13379 1999 : TALLOC_FREE(blob1.data);
13380 1999 : data_blob_free(&blob2);
13381 : }
13382 1 : return ret;
13383 : }
13384 :
13385 1000000 : static void parse_fn(const struct gencache_timeout *t,
13386 : DATA_BLOB blob,
13387 : void *private_data)
13388 : {
13389 1000000 : return;
13390 : }
13391 :
13392 1 : static bool run_local_gencache(int dummy)
13393 : {
13394 1 : char *val;
13395 1 : time_t tm;
13396 1 : DATA_BLOB blob;
13397 1 : char v;
13398 1 : struct memcache *mem;
13399 1 : int i;
13400 :
13401 1 : mem = memcache_init(NULL, 0);
13402 1 : if (mem == NULL) {
13403 0 : d_printf("%s: memcache_init failed\n", __location__);
13404 0 : return false;
13405 : }
13406 1 : memcache_set_global(mem);
13407 :
13408 1 : if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13409 0 : d_printf("%s: gencache_set() failed\n", __location__);
13410 0 : return False;
13411 : }
13412 :
13413 1 : if (!gencache_get("foo", NULL, NULL, NULL)) {
13414 0 : d_printf("%s: gencache_get() failed\n", __location__);
13415 0 : return False;
13416 : }
13417 :
13418 1000001 : for (i=0; i<1000000; i++) {
13419 1000000 : gencache_parse("foo", parse_fn, NULL);
13420 : }
13421 :
13422 1 : if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13423 0 : d_printf("%s: gencache_get() failed\n", __location__);
13424 0 : return False;
13425 : }
13426 1 : TALLOC_FREE(val);
13427 :
13428 1 : if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13429 0 : d_printf("%s: gencache_get() failed\n", __location__);
13430 0 : return False;
13431 : }
13432 :
13433 1 : if (strcmp(val, "bar") != 0) {
13434 0 : d_printf("%s: gencache_get() returned %s, expected %s\n",
13435 : __location__, val, "bar");
13436 0 : TALLOC_FREE(val);
13437 0 : return False;
13438 : }
13439 :
13440 1 : TALLOC_FREE(val);
13441 :
13442 1 : if (!gencache_del("foo")) {
13443 0 : d_printf("%s: gencache_del() failed\n", __location__);
13444 0 : return False;
13445 : }
13446 1 : if (gencache_del("foo")) {
13447 0 : d_printf("%s: second gencache_del() succeeded\n",
13448 : __location__);
13449 0 : return False;
13450 : }
13451 :
13452 1 : if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13453 0 : d_printf("%s: gencache_get() on deleted entry "
13454 : "succeeded\n", __location__);
13455 0 : return False;
13456 : }
13457 :
13458 1 : blob = data_blob_string_const_null("bar");
13459 1 : tm = time(NULL) + 60;
13460 :
13461 1 : if (!gencache_set_data_blob("foo", blob, tm)) {
13462 0 : d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13463 0 : return False;
13464 : }
13465 :
13466 1 : if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13467 0 : d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13468 0 : return False;
13469 : }
13470 :
13471 1 : if (strcmp((const char *)blob.data, "bar") != 0) {
13472 0 : d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13473 0 : __location__, (const char *)blob.data, "bar");
13474 0 : data_blob_free(&blob);
13475 0 : return False;
13476 : }
13477 :
13478 1 : data_blob_free(&blob);
13479 :
13480 1 : if (!gencache_del("foo")) {
13481 0 : d_printf("%s: gencache_del() failed\n", __location__);
13482 0 : return False;
13483 : }
13484 1 : if (gencache_del("foo")) {
13485 0 : d_printf("%s: second gencache_del() succeeded\n",
13486 : __location__);
13487 0 : return False;
13488 : }
13489 :
13490 1 : if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13491 0 : d_printf("%s: gencache_get_data_blob() on deleted entry "
13492 : "succeeded\n", __location__);
13493 0 : return False;
13494 : }
13495 :
13496 1 : v = 1;
13497 1 : blob.data = (uint8_t *)&v;
13498 1 : blob.length = sizeof(v);
13499 :
13500 1 : if (!gencache_set_data_blob("blob", blob, tm)) {
13501 0 : d_printf("%s: gencache_set_data_blob() failed\n",
13502 : __location__);
13503 0 : return false;
13504 : }
13505 1 : if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13506 0 : d_printf("%s: gencache_get succeeded\n", __location__);
13507 0 : return false;
13508 : }
13509 :
13510 0 : return True;
13511 : }
13512 :
13513 1 : static bool rbt_testflags(struct db_context *db, const char *key,
13514 : const char *value)
13515 : {
13516 1 : bool ret = false;
13517 1 : NTSTATUS status;
13518 1 : struct db_record *rec;
13519 :
13520 1 : rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13521 1 : if (rec == NULL) {
13522 0 : d_fprintf(stderr, "fetch_locked failed\n");
13523 0 : goto done;
13524 : }
13525 :
13526 1 : status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13527 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13528 0 : d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13529 : nt_errstr(status));
13530 0 : goto done;
13531 : }
13532 :
13533 1 : status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13534 : TDB_INSERT);
13535 1 : if (!NT_STATUS_IS_OK(status)) {
13536 0 : d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13537 : nt_errstr(status));
13538 0 : goto done;
13539 : }
13540 :
13541 1 : status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13542 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13543 0 : d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13544 : nt_errstr(status));
13545 0 : goto done;
13546 : }
13547 :
13548 1 : status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13549 1 : if (!NT_STATUS_IS_OK(status)) {
13550 0 : d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13551 : nt_errstr(status));
13552 0 : goto done;
13553 : }
13554 :
13555 0 : ret = true;
13556 1 : done:
13557 1 : TALLOC_FREE(rec);
13558 1 : return ret;
13559 : }
13560 :
13561 1998 : static bool rbt_testval(struct db_context *db, const char *key,
13562 : const char *value)
13563 : {
13564 1998 : struct db_record *rec;
13565 1998 : TDB_DATA data = string_tdb_data(value);
13566 1998 : bool ret = false;
13567 1998 : NTSTATUS status;
13568 1998 : TDB_DATA dbvalue;
13569 :
13570 1998 : rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13571 1998 : if (rec == NULL) {
13572 0 : d_fprintf(stderr, "fetch_locked failed\n");
13573 0 : goto done;
13574 : }
13575 1998 : status = dbwrap_record_store(rec, data, 0);
13576 1998 : if (!NT_STATUS_IS_OK(status)) {
13577 0 : d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13578 0 : goto done;
13579 : }
13580 1998 : TALLOC_FREE(rec);
13581 :
13582 1998 : rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13583 1998 : if (rec == NULL) {
13584 0 : d_fprintf(stderr, "second fetch_locked failed\n");
13585 0 : goto done;
13586 : }
13587 :
13588 1998 : dbvalue = dbwrap_record_get_value(rec);
13589 1998 : if ((dbvalue.dsize != data.dsize)
13590 1998 : || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13591 0 : d_fprintf(stderr, "Got wrong data back\n");
13592 0 : goto done;
13593 : }
13594 :
13595 0 : ret = true;
13596 1998 : done:
13597 1998 : TALLOC_FREE(rec);
13598 1998 : return ret;
13599 : }
13600 :
13601 1000 : static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13602 : {
13603 1000 : int *count2 = (int *)private_data;
13604 1000 : (*count2)++;
13605 1000 : return 0;
13606 : }
13607 :
13608 1000 : static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13609 : {
13610 1000 : int *count2 = (int *)private_data;
13611 1000 : (*count2)++;
13612 1000 : dbwrap_record_delete(rec);
13613 1000 : return 0;
13614 : }
13615 :
13616 1 : static bool run_local_rbtree(int dummy)
13617 : {
13618 1 : struct db_context *db;
13619 1 : bool ret = false;
13620 1 : int i;
13621 1 : NTSTATUS status;
13622 1 : int count = 0;
13623 1 : int count2 = 0;
13624 :
13625 1 : db = db_open_rbt(NULL);
13626 :
13627 1 : if (db == NULL) {
13628 0 : d_fprintf(stderr, "db_open_rbt failed\n");
13629 0 : return false;
13630 : }
13631 :
13632 1 : if (!rbt_testflags(db, "firstkey", "firstval")) {
13633 0 : goto done;
13634 : }
13635 :
13636 1000 : for (i = 0; i < 999; i++) {
13637 999 : char key[sizeof("key-9223372036854775807-1234")];
13638 999 : char value[sizeof("value-9223372036854775807-1234")];
13639 :
13640 999 : snprintf(key, sizeof(key), "key%ld-%d", random(), i);
13641 999 : snprintf(value, sizeof(value) ,"value%ld-%d", random(), i);
13642 :
13643 999 : if (!rbt_testval(db, key, value)) {
13644 0 : goto done;
13645 : }
13646 :
13647 999 : snprintf(value, sizeof(value) ,"value%ld-%d", random(), i + 1);
13648 :
13649 999 : if (!rbt_testval(db, key, value)) {
13650 0 : goto done;
13651 : }
13652 : }
13653 :
13654 1 : ret = true;
13655 1 : count = 0; count2 = 0;
13656 1 : status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13657 : &count2, &count);
13658 1 : printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13659 1 : if ((count != count2) || (count != 1000)) {
13660 0 : ret = false;
13661 : }
13662 1 : count = 0; count2 = 0;
13663 1 : status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13664 : &count2, &count);
13665 1 : printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13666 1 : if ((count != count2) || (count != 1000)) {
13667 0 : ret = false;
13668 : }
13669 1 : count = 0; count2 = 0;
13670 1 : status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13671 : &count2, &count);
13672 1 : printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13673 1 : if ((count != count2) || (count != 0)) {
13674 0 : ret = false;
13675 : }
13676 :
13677 1 : done:
13678 1 : TALLOC_FREE(db);
13679 1 : return ret;
13680 : }
13681 :
13682 :
13683 : /*
13684 : local test for character set functions
13685 :
13686 : This is a very simple test for the functionality in convert_string_error()
13687 : */
13688 1 : static bool run_local_convert_string(int dummy)
13689 : {
13690 1 : TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13691 1 : const char *test_strings[2] = { "March", "M\303\244rz" };
13692 1 : char dst[7];
13693 1 : int i;
13694 :
13695 3 : for (i=0; i<2; i++) {
13696 2 : const char *str = test_strings[i];
13697 2 : int len = strlen(str);
13698 2 : size_t converted_size;
13699 2 : bool ret;
13700 :
13701 2 : memset(dst, 'X', sizeof(dst));
13702 :
13703 : /* first try with real source length */
13704 2 : ret = convert_string_error(CH_UNIX, CH_UTF8,
13705 : str, len,
13706 : dst, sizeof(dst),
13707 : &converted_size);
13708 2 : if (ret != true) {
13709 0 : d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13710 0 : goto failed;
13711 : }
13712 :
13713 2 : if (converted_size != len) {
13714 0 : d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13715 : str, len, (int)converted_size);
13716 0 : goto failed;
13717 : }
13718 :
13719 2 : if (strncmp(str, dst, converted_size) != 0) {
13720 0 : d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13721 0 : goto failed;
13722 : }
13723 :
13724 2 : if (strlen(str) != converted_size) {
13725 0 : d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13726 0 : (int)strlen(str), (int)converted_size);
13727 0 : goto failed;
13728 : }
13729 :
13730 2 : if (dst[converted_size] != 'X') {
13731 0 : d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13732 0 : goto failed;
13733 : }
13734 :
13735 : /* now with srclen==-1, this causes the nul to be
13736 : * converted too */
13737 2 : ret = convert_string_error(CH_UNIX, CH_UTF8,
13738 : str, -1,
13739 : dst, sizeof(dst),
13740 : &converted_size);
13741 2 : if (ret != true) {
13742 0 : d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13743 0 : goto failed;
13744 : }
13745 :
13746 2 : if (converted_size != len+1) {
13747 0 : d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13748 : str, len, (int)converted_size);
13749 0 : goto failed;
13750 : }
13751 :
13752 2 : if (strncmp(str, dst, converted_size) != 0) {
13753 0 : d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13754 0 : goto failed;
13755 : }
13756 :
13757 2 : if (len+1 != converted_size) {
13758 0 : d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13759 : len+1, (int)converted_size);
13760 0 : goto failed;
13761 : }
13762 :
13763 2 : if (dst[converted_size] != 'X') {
13764 0 : d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13765 0 : goto failed;
13766 : }
13767 :
13768 : }
13769 :
13770 :
13771 1 : TALLOC_FREE(tmp_ctx);
13772 0 : return true;
13773 0 : failed:
13774 0 : TALLOC_FREE(tmp_ctx);
13775 0 : return false;
13776 : }
13777 :
13778 1 : static bool run_local_string_to_sid(int dummy) {
13779 1 : struct dom_sid sid;
13780 :
13781 1 : if (string_to_sid(&sid, "S--1-5-32-545")) {
13782 0 : printf("allowing S--1-5-32-545\n");
13783 0 : return false;
13784 : }
13785 1 : if (string_to_sid(&sid, "S-1-5-32-+545")) {
13786 0 : printf("allowing S-1-5-32-+545\n");
13787 0 : return false;
13788 : }
13789 1 : 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")) {
13790 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");
13791 0 : return false;
13792 : }
13793 1 : if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13794 0 : printf("allowing S-1-5-32-545-abc\n");
13795 0 : return false;
13796 : }
13797 1 : if (string_to_sid(&sid, "S-300-5-32-545")) {
13798 0 : printf("allowing S-300-5-32-545\n");
13799 0 : return false;
13800 : }
13801 1 : if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13802 0 : printf("allowing S-1-0xfffffffffffffe-32-545\n");
13803 0 : return false;
13804 : }
13805 1 : if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13806 0 : printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13807 0 : return false;
13808 : }
13809 1 : if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13810 0 : printf("could not parse S-1-0xfffffffffffe-32-545\n");
13811 0 : return false;
13812 : }
13813 1 : if (!string_to_sid(&sid, "S-1-5-32-545")) {
13814 0 : printf("could not parse S-1-5-32-545\n");
13815 0 : return false;
13816 : }
13817 1 : if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13818 0 : struct dom_sid_buf buf;
13819 0 : printf("mis-parsed S-1-5-32-545 as %s\n",
13820 : dom_sid_str_buf(&sid, &buf));
13821 0 : return false;
13822 : }
13823 0 : return true;
13824 : }
13825 :
13826 3 : static bool sid_to_string_test(const char *expected) {
13827 3 : char *str;
13828 3 : bool res = true;
13829 3 : struct dom_sid sid;
13830 :
13831 3 : if (!string_to_sid(&sid, expected)) {
13832 0 : printf("could not parse %s\n", expected);
13833 0 : return false;
13834 : }
13835 :
13836 3 : str = dom_sid_string(NULL, &sid);
13837 3 : if (strcmp(str, expected)) {
13838 0 : printf("Comparison failed (%s != %s)\n", str, expected);
13839 0 : res = false;
13840 : }
13841 3 : TALLOC_FREE(str);
13842 3 : return res;
13843 : }
13844 :
13845 1 : static bool run_local_sid_to_string(int dummy) {
13846 1 : if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13847 0 : return false;
13848 1 : if (!sid_to_string_test("S-1-545"))
13849 0 : return false;
13850 1 : if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13851 0 : return false;
13852 0 : return true;
13853 : }
13854 :
13855 1 : static bool run_local_binary_to_sid(int dummy) {
13856 1 : ssize_t ret;
13857 1 : struct dom_sid *sid = talloc(NULL, struct dom_sid);
13858 1 : static const uint8_t good_binary_sid[] = {
13859 : 0x1, /* revision number */
13860 : 15, /* num auths */
13861 : 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13862 : 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13863 : 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13864 : 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13865 : 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13866 : 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13867 : 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13868 : 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13869 : 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13870 : 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13871 : 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13872 : 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13873 : 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13874 : 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13875 : 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13876 : 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13877 : };
13878 :
13879 1 : static const uint8_t long_binary_sid[] = {
13880 : 0x1, /* revision number */
13881 : 15, /* num auths */
13882 : 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13883 : 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13884 : 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13885 : 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13886 : 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13887 : 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13888 : 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13889 : 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13890 : 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13891 : 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13892 : 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13893 : 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13894 : 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13895 : 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13896 : 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13897 : 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13898 : 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13899 : 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13900 : 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13901 : };
13902 :
13903 1 : static const uint8_t long_binary_sid2[] = {
13904 : 0x1, /* revision number */
13905 : 32, /* num auths */
13906 : 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13907 : 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13908 : 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13909 : 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13910 : 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13911 : 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13912 : 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13913 : 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13914 : 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13915 : 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13916 : 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13917 : 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13918 : 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13919 : 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13920 : 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13921 : 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13922 : 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13923 : 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13924 : 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13925 : 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13926 : 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13927 : 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13928 : 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13929 : 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13930 : 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13931 : 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13932 : 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13933 : 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13934 : 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13935 : 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13936 : 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13937 : 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13938 : 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13939 : };
13940 :
13941 1 : ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13942 1 : if (ret == -1) {
13943 0 : return false;
13944 : }
13945 1 : ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13946 1 : if (ret != -1) {
13947 0 : return false;
13948 : }
13949 1 : ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13950 1 : if (ret != -1) {
13951 0 : return false;
13952 : }
13953 0 : return true;
13954 : }
13955 :
13956 : /* Split a path name into filename and stream name components. Canonicalise
13957 : * such that an implicit $DATA token is always explicit.
13958 : *
13959 : * The "specification" of this function can be found in the
13960 : * run_local_stream_name() function in torture.c, I've tried those
13961 : * combinations against a W2k3 server.
13962 : */
13963 :
13964 8 : static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13965 : char **pbase, char **pstream)
13966 : {
13967 8 : char *base = NULL;
13968 8 : char *stream = NULL;
13969 8 : char *sname; /* stream name */
13970 8 : const char *stype; /* stream type */
13971 :
13972 8 : DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13973 :
13974 8 : sname = strchr_m(fname, ':');
13975 :
13976 8 : if (sname == NULL) {
13977 1 : if (pbase != NULL) {
13978 1 : base = talloc_strdup(mem_ctx, fname);
13979 1 : NT_STATUS_HAVE_NO_MEMORY(base);
13980 : }
13981 1 : goto done;
13982 : }
13983 :
13984 7 : if (pbase != NULL) {
13985 7 : base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13986 7 : NT_STATUS_HAVE_NO_MEMORY(base);
13987 : }
13988 :
13989 7 : sname += 1;
13990 :
13991 7 : stype = strchr_m(sname, ':');
13992 :
13993 7 : if (stype == NULL) {
13994 2 : sname = talloc_strdup(mem_ctx, sname);
13995 2 : stype = "$DATA";
13996 : }
13997 : else {
13998 5 : if (strcasecmp_m(stype, ":$DATA") != 0) {
13999 : /*
14000 : * If there is an explicit stream type, so far we only
14001 : * allow $DATA. Is there anything else allowed? -- vl
14002 : */
14003 3 : DEBUG(10, ("[%s] is an invalid stream type\n", stype));
14004 3 : TALLOC_FREE(base);
14005 3 : return NT_STATUS_OBJECT_NAME_INVALID;
14006 : }
14007 2 : sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
14008 2 : stype += 1;
14009 : }
14010 :
14011 4 : if (sname == NULL) {
14012 0 : TALLOC_FREE(base);
14013 0 : return NT_STATUS_NO_MEMORY;
14014 : }
14015 :
14016 4 : if (sname[0] == '\0') {
14017 : /*
14018 : * no stream name, so no stream
14019 : */
14020 1 : goto done;
14021 : }
14022 :
14023 3 : if (pstream != NULL) {
14024 3 : stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
14025 3 : if (stream == NULL) {
14026 0 : TALLOC_FREE(sname);
14027 0 : TALLOC_FREE(base);
14028 0 : return NT_STATUS_NO_MEMORY;
14029 : }
14030 : /*
14031 : * upper-case the type field
14032 : */
14033 3 : (void)strupper_m(strchr_m(stream, ':')+1);
14034 : }
14035 :
14036 0 : done:
14037 5 : if (pbase != NULL) {
14038 5 : *pbase = base;
14039 : }
14040 5 : if (pstream != NULL) {
14041 5 : *pstream = stream;
14042 : }
14043 5 : return NT_STATUS_OK;
14044 : }
14045 :
14046 8 : static bool test_stream_name(const char *fname, const char *expected_base,
14047 : const char *expected_stream,
14048 : NTSTATUS expected_status)
14049 : {
14050 8 : NTSTATUS status;
14051 8 : char *base = NULL;
14052 8 : char *stream = NULL;
14053 :
14054 8 : status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
14055 8 : if (!NT_STATUS_EQUAL(status, expected_status)) {
14056 0 : goto error;
14057 : }
14058 :
14059 8 : if (!NT_STATUS_IS_OK(status)) {
14060 0 : return true;
14061 : }
14062 :
14063 5 : if (base == NULL) goto error;
14064 :
14065 5 : if (strcmp(expected_base, base) != 0) goto error;
14066 :
14067 5 : if ((expected_stream != NULL) && (stream == NULL)) goto error;
14068 5 : if ((expected_stream == NULL) && (stream != NULL)) goto error;
14069 :
14070 5 : if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
14071 0 : goto error;
14072 :
14073 5 : TALLOC_FREE(base);
14074 5 : TALLOC_FREE(stream);
14075 0 : return true;
14076 :
14077 0 : error:
14078 0 : d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
14079 : fname, expected_base ? expected_base : "<NULL>",
14080 : expected_stream ? expected_stream : "<NULL>",
14081 : nt_errstr(expected_status));
14082 0 : d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
14083 0 : base ? base : "<NULL>", stream ? stream : "<NULL>",
14084 : nt_errstr(status));
14085 0 : TALLOC_FREE(base);
14086 0 : TALLOC_FREE(stream);
14087 0 : return false;
14088 : }
14089 :
14090 1 : static bool run_local_stream_name(int dummy)
14091 : {
14092 1 : bool ret = true;
14093 :
14094 2 : ret &= test_stream_name(
14095 1 : "bla", "bla", NULL, NT_STATUS_OK);
14096 2 : ret &= test_stream_name(
14097 1 : "bla::$DATA", "bla", NULL, NT_STATUS_OK);
14098 2 : ret &= test_stream_name(
14099 1 : "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14100 2 : ret &= test_stream_name(
14101 1 : "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
14102 2 : ret &= test_stream_name(
14103 1 : "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14104 2 : ret &= test_stream_name(
14105 1 : "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
14106 2 : ret &= test_stream_name(
14107 1 : "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
14108 2 : ret &= test_stream_name(
14109 1 : "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
14110 :
14111 1 : return ret;
14112 : }
14113 :
14114 2 : static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
14115 : {
14116 2 : if (a.length != b.length) {
14117 0 : printf("a.length=%d != b.length=%d\n",
14118 0 : (int)a.length, (int)b.length);
14119 0 : return false;
14120 : }
14121 2 : if (memcmp(a.data, b.data, a.length) != 0) {
14122 0 : printf("a.data and b.data differ\n");
14123 0 : return false;
14124 : }
14125 0 : return true;
14126 : }
14127 :
14128 1 : static bool run_local_memcache(int dummy)
14129 : {
14130 1 : struct memcache *cache;
14131 1 : DATA_BLOB k1, k2, k3, k4, k5;
14132 1 : DATA_BLOB d1, d3;
14133 1 : DATA_BLOB v1, v3;
14134 :
14135 1 : TALLOC_CTX *mem_ctx;
14136 1 : char *ptr1 = NULL;
14137 1 : char *ptr2 = NULL;
14138 1 : char *ptr3 = NULL;
14139 :
14140 1 : char *str1, *str2;
14141 1 : size_t size1, size2;
14142 1 : bool ret = false;
14143 :
14144 1 : mem_ctx = talloc_init("foo");
14145 1 : if (mem_ctx == NULL) {
14146 0 : return false;
14147 : }
14148 :
14149 : /* STAT_CACHE TESTS */
14150 :
14151 1 : cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14152 :
14153 1 : if (cache == NULL) {
14154 0 : printf("memcache_init failed\n");
14155 0 : return false;
14156 : }
14157 :
14158 1 : d1 = data_blob_const("d1", 2);
14159 1 : d3 = data_blob_const("d3", 2);
14160 :
14161 1 : k1 = data_blob_const("d1", 2);
14162 1 : k2 = data_blob_const("d2", 2);
14163 1 : k3 = data_blob_const("d3", 2);
14164 1 : k4 = data_blob_const("d4", 2);
14165 1 : k5 = data_blob_const("d5", 2);
14166 :
14167 1 : memcache_add(cache, STAT_CACHE, k1, d1);
14168 :
14169 1 : if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
14170 0 : printf("could not find k1\n");
14171 0 : return false;
14172 : }
14173 1 : if (!data_blob_equal(d1, v1)) {
14174 0 : return false;
14175 : }
14176 :
14177 1 : memcache_add(cache, STAT_CACHE, k1, d3);
14178 :
14179 1 : if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
14180 0 : printf("could not find replaced k1\n");
14181 0 : return false;
14182 : }
14183 1 : if (!data_blob_equal(d3, v3)) {
14184 0 : return false;
14185 : }
14186 :
14187 1 : TALLOC_FREE(cache);
14188 :
14189 : /* GETWD_CACHE TESTS */
14190 1 : str1 = talloc_strdup(mem_ctx, "string1");
14191 1 : if (str1 == NULL) {
14192 0 : return false;
14193 : }
14194 1 : ptr2 = str1; /* Keep an alias for comparison. */
14195 :
14196 1 : str2 = talloc_strdup(mem_ctx, "string2");
14197 1 : if (str2 == NULL) {
14198 0 : return false;
14199 : }
14200 :
14201 1 : cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14202 1 : if (cache == NULL) {
14203 0 : printf("memcache_init failed\n");
14204 0 : return false;
14205 : }
14206 :
14207 1 : memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14208 : /* str1 == NULL now. */
14209 1 : ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14210 1 : if (ptr1 == NULL) {
14211 0 : printf("could not find k2\n");
14212 0 : return false;
14213 : }
14214 1 : if (ptr1 != ptr2) {
14215 0 : printf("fetch of k2 got wrong string\n");
14216 0 : return false;
14217 : }
14218 :
14219 : /* Add a blob to ensure k2 gets purged. */
14220 1 : d3 = data_blob_talloc_zero(mem_ctx, 180);
14221 1 : memcache_add(cache, STAT_CACHE, k3, d3);
14222 :
14223 1 : ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14224 1 : if (ptr2 != NULL) {
14225 0 : printf("Did find k2, should have been purged\n");
14226 0 : return false;
14227 : }
14228 :
14229 : /*
14230 : * Test that talloc size also is accounted in memcache and
14231 : * causes purge of other object.
14232 : */
14233 :
14234 1 : str1 = talloc_zero_size(mem_ctx, 100);
14235 1 : str2 = talloc_zero_size(mem_ctx, 100);
14236 :
14237 1 : memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14238 1 : memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14239 :
14240 1 : ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14241 1 : if (ptr3 != NULL) {
14242 0 : printf("Did find k4, should have been purged\n");
14243 0 : return false;
14244 : }
14245 :
14246 : /*
14247 : * Test that adding a duplicate non-talloced
14248 : * key/value on top of a talloced key/value takes account
14249 : * of the talloc_freed value size.
14250 : */
14251 1 : TALLOC_FREE(cache);
14252 1 : TALLOC_FREE(mem_ctx);
14253 :
14254 1 : mem_ctx = talloc_init("key_replace");
14255 1 : if (mem_ctx == NULL) {
14256 0 : return false;
14257 : }
14258 :
14259 1 : cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14260 1 : if (cache == NULL) {
14261 0 : return false;
14262 : }
14263 :
14264 : /*
14265 : * Add a 100 byte talloced string. This will
14266 : * store a (4 or 8 byte) pointer and record the
14267 : * total talloced size.
14268 : */
14269 1 : str1 = talloc_zero_size(mem_ctx, 100);
14270 1 : memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14271 : /*
14272 : * Now overwrite with a small talloced
14273 : * value. This should fit in the existing size
14274 : * and the total talloced size should be removed
14275 : * from the cache size.
14276 : */
14277 1 : str1 = talloc_zero_size(mem_ctx, 2);
14278 1 : memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14279 : /*
14280 : * Now store a 20 byte string. If the
14281 : * total talloced size wasn't accounted for
14282 : * and removed in the overwrite, then this
14283 : * will evict k4.
14284 : */
14285 1 : str2 = talloc_zero_size(mem_ctx, 20);
14286 1 : memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14287 :
14288 1 : ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14289 1 : if (ptr3 == NULL) {
14290 0 : printf("Did not find k4, should not have been purged\n");
14291 0 : return false;
14292 : }
14293 :
14294 1 : TALLOC_FREE(cache);
14295 1 : TALLOC_FREE(mem_ctx);
14296 :
14297 1 : mem_ctx = talloc_init("foo");
14298 1 : if (mem_ctx == NULL) {
14299 0 : return false;
14300 : }
14301 :
14302 1 : cache = memcache_init(NULL, 0);
14303 1 : if (cache == NULL) {
14304 0 : return false;
14305 : }
14306 :
14307 1 : str1 = talloc_strdup(mem_ctx, "string1");
14308 1 : if (str1 == NULL) {
14309 0 : return false;
14310 : }
14311 1 : str2 = talloc_strdup(mem_ctx, "string2");
14312 1 : if (str2 == NULL) {
14313 0 : return false;
14314 : }
14315 1 : memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14316 : data_blob_string_const("torture"), &str1);
14317 1 : size1 = talloc_total_size(cache);
14318 :
14319 1 : memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14320 : data_blob_string_const("torture"), &str2);
14321 1 : size2 = talloc_total_size(cache);
14322 :
14323 1 : printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14324 :
14325 1 : if (size2 > size1) {
14326 0 : printf("memcache leaks memory!\n");
14327 0 : goto fail;
14328 : }
14329 :
14330 0 : ret = true;
14331 1 : fail:
14332 1 : TALLOC_FREE(cache);
14333 1 : return ret;
14334 : }
14335 :
14336 200 : static void wbclient_done(struct tevent_req *req)
14337 : {
14338 0 : wbcErr wbc_err;
14339 0 : struct winbindd_response *wb_resp;
14340 200 : int *i = (int *)tevent_req_callback_data_void(req);
14341 :
14342 200 : wbc_err = wb_trans_recv(req, req, &wb_resp);
14343 200 : TALLOC_FREE(req);
14344 200 : *i += 1;
14345 200 : d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14346 200 : }
14347 :
14348 2 : static bool run_wbclient_multi_ping(int dummy)
14349 : {
14350 0 : struct tevent_context *ev;
14351 0 : struct wb_context **wb_ctx;
14352 0 : struct winbindd_request wb_req;
14353 2 : bool result = false;
14354 0 : int i, j;
14355 :
14356 2 : BlockSignals(True, SIGPIPE);
14357 :
14358 2 : ev = tevent_context_init(talloc_tos());
14359 2 : if (ev == NULL) {
14360 0 : goto fail;
14361 : }
14362 :
14363 2 : wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14364 2 : if (wb_ctx == NULL) {
14365 0 : goto fail;
14366 : }
14367 :
14368 2 : ZERO_STRUCT(wb_req);
14369 2 : wb_req.cmd = WINBINDD_PING;
14370 :
14371 2 : d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14372 :
14373 4 : for (i=0; i<torture_nprocs; i++) {
14374 2 : wb_ctx[i] = wb_context_init(ev, NULL);
14375 2 : if (wb_ctx[i] == NULL) {
14376 0 : goto fail;
14377 : }
14378 202 : for (j=0; j<torture_numops; j++) {
14379 0 : struct tevent_req *req;
14380 200 : req = wb_trans_send(ev, ev, wb_ctx[i],
14381 200 : (j % 2) == 0, &wb_req);
14382 200 : if (req == NULL) {
14383 0 : goto fail;
14384 : }
14385 200 : tevent_req_set_callback(req, wbclient_done, &i);
14386 : }
14387 : }
14388 :
14389 2 : i = 0;
14390 :
14391 818 : while (i < torture_nprocs * torture_numops) {
14392 816 : tevent_loop_once(ev);
14393 : }
14394 :
14395 2 : result = true;
14396 2 : fail:
14397 2 : TALLOC_FREE(ev);
14398 2 : return result;
14399 : }
14400 :
14401 0 : static bool dbtrans_inc(struct db_context *db)
14402 : {
14403 0 : struct db_record *rec;
14404 0 : uint32_t val;
14405 0 : bool ret = false;
14406 0 : NTSTATUS status;
14407 0 : TDB_DATA value;
14408 :
14409 0 : rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14410 0 : if (rec == NULL) {
14411 0 : printf(__location__ "fetch_lock failed\n");
14412 0 : return false;
14413 : }
14414 :
14415 0 : value = dbwrap_record_get_value(rec);
14416 :
14417 0 : if (value.dsize != sizeof(uint32_t)) {
14418 0 : printf(__location__ "value.dsize = %d\n",
14419 0 : (int)value.dsize);
14420 0 : goto fail;
14421 : }
14422 :
14423 0 : memcpy(&val, value.dptr, sizeof(val));
14424 0 : val += 1;
14425 :
14426 0 : status = dbwrap_record_store(
14427 : rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14428 0 : if (!NT_STATUS_IS_OK(status)) {
14429 0 : printf(__location__ "store failed: %s\n",
14430 : nt_errstr(status));
14431 0 : goto fail;
14432 : }
14433 :
14434 0 : ret = true;
14435 0 : fail:
14436 0 : TALLOC_FREE(rec);
14437 0 : return ret;
14438 : }
14439 :
14440 0 : static bool run_local_dbtrans(int dummy)
14441 : {
14442 0 : struct db_context *db;
14443 0 : struct db_record *rec;
14444 0 : NTSTATUS status;
14445 0 : uint32_t initial;
14446 0 : int res;
14447 0 : TDB_DATA value;
14448 :
14449 0 : db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14450 : O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14451 : DBWRAP_FLAG_NONE);
14452 0 : if (db == NULL) {
14453 0 : printf("Could not open transtest.db\n");
14454 0 : return false;
14455 : }
14456 :
14457 0 : res = dbwrap_transaction_start(db);
14458 0 : if (res != 0) {
14459 0 : printf(__location__ "transaction_start failed\n");
14460 0 : return false;
14461 : }
14462 :
14463 0 : rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14464 0 : if (rec == NULL) {
14465 0 : printf(__location__ "fetch_lock failed\n");
14466 0 : return false;
14467 : }
14468 :
14469 0 : value = dbwrap_record_get_value(rec);
14470 :
14471 0 : if (value.dptr == NULL) {
14472 0 : initial = 0;
14473 0 : status = dbwrap_record_store(
14474 : rec, make_tdb_data((uint8_t *)&initial,
14475 : sizeof(initial)),
14476 : 0);
14477 0 : if (!NT_STATUS_IS_OK(status)) {
14478 0 : printf(__location__ "store returned %s\n",
14479 : nt_errstr(status));
14480 0 : return false;
14481 : }
14482 : }
14483 :
14484 0 : TALLOC_FREE(rec);
14485 :
14486 0 : res = dbwrap_transaction_commit(db);
14487 0 : if (res != 0) {
14488 0 : printf(__location__ "transaction_commit failed\n");
14489 0 : return false;
14490 : }
14491 :
14492 0 : while (true) {
14493 0 : uint32_t val, val2;
14494 0 : int i;
14495 :
14496 0 : res = dbwrap_transaction_start(db);
14497 0 : if (res != 0) {
14498 0 : printf(__location__ "transaction_start failed\n");
14499 0 : break;
14500 : }
14501 :
14502 0 : status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14503 0 : if (!NT_STATUS_IS_OK(status)) {
14504 0 : printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14505 : nt_errstr(status));
14506 0 : break;
14507 : }
14508 :
14509 0 : for (i=0; i<10; i++) {
14510 0 : if (!dbtrans_inc(db)) {
14511 0 : return false;
14512 : }
14513 : }
14514 :
14515 0 : status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14516 0 : if (!NT_STATUS_IS_OK(status)) {
14517 0 : printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14518 : nt_errstr(status));
14519 0 : break;
14520 : }
14521 :
14522 0 : if (val2 != val + 10) {
14523 0 : printf(__location__ "val=%d, val2=%d\n",
14524 : (int)val, (int)val2);
14525 0 : break;
14526 : }
14527 :
14528 0 : printf("val2=%d\r", val2);
14529 :
14530 0 : res = dbwrap_transaction_commit(db);
14531 0 : if (res != 0) {
14532 0 : printf(__location__ "transaction_commit failed\n");
14533 0 : break;
14534 : }
14535 : }
14536 :
14537 0 : TALLOC_FREE(db);
14538 0 : return true;
14539 : }
14540 :
14541 : /*
14542 : * Just a dummy test to be run under a debugger. There's no real way
14543 : * to inspect the tevent_poll specific function from outside of
14544 : * tevent_poll.c.
14545 : */
14546 :
14547 1 : static bool run_local_tevent_poll(int dummy)
14548 : {
14549 1 : struct tevent_context *ev;
14550 1 : struct tevent_fd *fd1, *fd2;
14551 1 : bool result = false;
14552 :
14553 1 : ev = tevent_context_init_byname(NULL, "poll");
14554 1 : if (ev == NULL) {
14555 0 : d_fprintf(stderr, "tevent_context_init_byname failed\n");
14556 0 : goto fail;
14557 : }
14558 :
14559 1 : fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14560 1 : if (fd1 == NULL) {
14561 0 : d_fprintf(stderr, "tevent_add_fd failed\n");
14562 0 : goto fail;
14563 : }
14564 1 : fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14565 1 : if (fd2 == NULL) {
14566 0 : d_fprintf(stderr, "tevent_add_fd failed\n");
14567 0 : goto fail;
14568 : }
14569 1 : TALLOC_FREE(fd2);
14570 :
14571 1 : fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14572 1 : if (fd2 == NULL) {
14573 0 : d_fprintf(stderr, "tevent_add_fd failed\n");
14574 0 : goto fail;
14575 : }
14576 :
14577 0 : result = true;
14578 1 : fail:
14579 1 : TALLOC_FREE(ev);
14580 1 : return result;
14581 : }
14582 :
14583 1 : static bool run_local_hex_encode_buf(int dummy)
14584 : {
14585 1 : char buf[17];
14586 1 : uint8_t src[8];
14587 1 : size_t i;
14588 :
14589 9 : for (i=0; i<sizeof(src); i++) {
14590 8 : src[i] = i;
14591 : }
14592 1 : hex_encode_buf(buf, src, sizeof(src));
14593 1 : if (strcmp(buf, "0001020304050607") != 0) {
14594 0 : return false;
14595 : }
14596 1 : hex_encode_buf(buf, NULL, 0);
14597 1 : if (buf[0] != '\0') {
14598 0 : return false;
14599 : }
14600 0 : return true;
14601 : }
14602 :
14603 : static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14604 : "0.0.0.0",
14605 : "::0",
14606 : "1.2.3.1",
14607 : "0.0.0.0",
14608 : "0.0.0.0",
14609 : "1.2.3.2",
14610 : "1.2.3.3",
14611 : "1.2.3.4",
14612 : "1.2.3.5",
14613 : "::0",
14614 : "1.2.3.6",
14615 : "1.2.3.7",
14616 : "::0",
14617 : "::0",
14618 : "::0",
14619 : "1.2.3.8",
14620 : "1.2.3.9",
14621 : "1.2.3.10",
14622 : "1.2.3.11",
14623 : "1.2.3.12",
14624 : "1.2.3.13",
14625 : "1001:1111:1111:1000:0:1111:1111:1111",
14626 : "1.2.3.1",
14627 : "1.2.3.2",
14628 : "1.2.3.3",
14629 : "1.2.3.12",
14630 : "::0",
14631 : "::0"
14632 : };
14633 :
14634 : static const char *remove_duplicate_addrs2_test_strings_result[] = {
14635 : "1.2.3.1",
14636 : "1.2.3.2",
14637 : "1.2.3.3",
14638 : "1.2.3.4",
14639 : "1.2.3.5",
14640 : "1.2.3.6",
14641 : "1.2.3.7",
14642 : "1.2.3.8",
14643 : "1.2.3.9",
14644 : "1.2.3.10",
14645 : "1.2.3.11",
14646 : "1.2.3.12",
14647 : "1.2.3.13",
14648 : "1001:1111:1111:1000:0:1111:1111:1111"
14649 : };
14650 :
14651 1 : static bool run_local_remove_duplicate_addrs2(int dummy)
14652 : {
14653 1 : struct samba_sockaddr test_vector[28];
14654 1 : size_t count, i;
14655 :
14656 : /* Construct the sockaddr_storage test vector. */
14657 29 : for (i = 0; i < 28; i++) {
14658 28 : struct addrinfo hints;
14659 28 : struct addrinfo *res = NULL;
14660 28 : int ret;
14661 :
14662 28 : memset(&hints, '\0', sizeof(hints));
14663 28 : hints.ai_flags = AI_NUMERICHOST;
14664 28 : ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14665 : NULL,
14666 : &hints,
14667 : &res);
14668 28 : if (ret) {
14669 0 : fprintf(stderr, "getaddrinfo failed on [%s]\n",
14670 : remove_duplicate_addrs2_test_strings_vector[i]);
14671 0 : return false;
14672 : }
14673 28 : memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14674 28 : memcpy(&test_vector[i].u.ss,
14675 28 : res->ai_addr,
14676 28 : res->ai_addrlen);
14677 28 : freeaddrinfo(res);
14678 : }
14679 :
14680 1 : count = remove_duplicate_addrs2(test_vector, i);
14681 :
14682 1 : if (count != 14) {
14683 0 : fprintf(stderr, "count wrong (%zu) should be 14\n",
14684 : count);
14685 0 : return false;
14686 : }
14687 :
14688 15 : for (i = 0; i < count; i++) {
14689 14 : char addr[INET6_ADDRSTRLEN];
14690 :
14691 14 : print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14692 :
14693 14 : if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14694 0 : fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14695 : i,
14696 : addr,
14697 : remove_duplicate_addrs2_test_strings_result[i]);
14698 0 : return false;
14699 : }
14700 : }
14701 :
14702 1 : printf("run_local_remove_duplicate_addrs2: success\n");
14703 1 : return true;
14704 : }
14705 :
14706 0 : static bool run_local_tdb_opener(int dummy)
14707 : {
14708 0 : TDB_CONTEXT *t;
14709 0 : unsigned v = 0;
14710 :
14711 0 : while (1) {
14712 0 : t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14713 : O_RDWR|O_CREAT, 0755);
14714 0 : if (t == NULL) {
14715 0 : perror("tdb_open failed");
14716 0 : return false;
14717 : }
14718 0 : tdb_close(t);
14719 :
14720 0 : v += 1;
14721 0 : printf("\r%u", v);
14722 : }
14723 : return true;
14724 : }
14725 :
14726 0 : static bool run_local_tdb_writer(int dummy)
14727 : {
14728 0 : TDB_CONTEXT *t;
14729 0 : unsigned v = 0;
14730 0 : TDB_DATA val;
14731 :
14732 0 : t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14733 0 : if (t == 0) {
14734 0 : perror("tdb_open failed");
14735 0 : return 1;
14736 : }
14737 :
14738 0 : val.dptr = (uint8_t *)&v;
14739 0 : val.dsize = sizeof(v);
14740 :
14741 0 : while (1) {
14742 0 : TDB_DATA data;
14743 0 : int ret;
14744 :
14745 0 : ret = tdb_store(t, val, val, 0);
14746 0 : if (ret != 0) {
14747 0 : printf("%s\n", tdb_errorstr(t));
14748 : }
14749 0 : v += 1;
14750 0 : printf("\r%u", v);
14751 :
14752 0 : data = tdb_fetch(t, val);
14753 0 : if (data.dptr != NULL) {
14754 0 : SAFE_FREE(data.dptr);
14755 : }
14756 : }
14757 : return true;
14758 : }
14759 :
14760 1 : static bool run_local_canonicalize_path(int dummy)
14761 : {
14762 1 : const char *src[] = {
14763 : "/foo/..",
14764 : "/..",
14765 : "/foo/bar/../baz",
14766 : "/foo/././",
14767 : "/../foo",
14768 : ".././././",
14769 : ".././././../../../boo",
14770 : "./..",
14771 : "/",
14772 : "/../../",
14773 : "/foo/../",
14774 : "/./././",
14775 : "/./././.",
14776 : "/.../././.",
14777 : "/./././.foo",
14778 : "/./././.foo.",
14779 : "/./././foo.",
14780 : "/foo/bar/..",
14781 : "/foo/bar/../baz/",
14782 : "////////////////",
14783 : "/////////./././././.",
14784 : "/./.././../.boo/../baz",
14785 : "/a/component/path",
14786 : "/a/component/path/",
14787 : "/a/component/path/..",
14788 : "/a/component/../path/",
14789 : "///a/./././///component/../////path/",
14790 : NULL
14791 : };
14792 1 : const char *dst[] = {
14793 : "/",
14794 : "/",
14795 : "/foo/baz",
14796 : "/foo",
14797 : "/foo",
14798 : "/",
14799 : "/boo",
14800 : "/",
14801 : "/",
14802 : "/",
14803 : "/",
14804 : "/",
14805 : "/",
14806 : "/...",
14807 : "/.foo",
14808 : "/.foo.",
14809 : "/foo.",
14810 : "/foo",
14811 : "/foo/baz",
14812 : "/",
14813 : "/",
14814 : "/baz",
14815 : "/a/component/path",
14816 : "/a/component/path",
14817 : "/a/component",
14818 : "/a/path",
14819 : "/a/path",
14820 : NULL
14821 : };
14822 1 : unsigned int i;
14823 :
14824 28 : for (i = 0; src[i] != NULL; i++) {
14825 27 : char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14826 27 : if (d == NULL) {
14827 0 : perror("talloc fail\n");
14828 0 : return false;
14829 : }
14830 27 : if (strcmp(d, dst[i]) != 0) {
14831 0 : d_fprintf(stderr,
14832 : "canonicalize mismatch %s -> %s != %s",
14833 : src[i], d, dst[i]);
14834 0 : return false;
14835 : }
14836 27 : talloc_free(d);
14837 : }
14838 0 : return true;
14839 : }
14840 : struct session_setup_nt1_truncated_state {
14841 : uint16_t vwv[13];
14842 : uint8_t bytes[20];
14843 : };
14844 :
14845 : static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq);
14846 :
14847 2 : static struct tevent_req *smb1_session_setup_nt1_truncated_send(
14848 : TALLOC_CTX *mem_ctx,
14849 : struct tevent_context *ev,
14850 : struct smbXcli_conn *conn)
14851 : {
14852 2 : uint16_t *vwv = NULL;
14853 2 : uint8_t *bytes = NULL;
14854 2 : const char *pass = "12345678";
14855 2 : const char *uname = "z";
14856 2 : struct session_setup_nt1_truncated_state *state = NULL;
14857 2 : struct tevent_req *req = NULL;
14858 2 : struct tevent_req *subreq = NULL;
14859 :
14860 2 : req = tevent_req_create(mem_ctx,
14861 : &state,
14862 : struct session_setup_nt1_truncated_state);
14863 2 : if (req == NULL) {
14864 0 : return NULL;
14865 : }
14866 2 : vwv = &state->vwv[0];
14867 2 : bytes = &state->bytes[0];
14868 :
14869 2 : SCVAL(vwv+0, 0, 0xff);
14870 2 : SCVAL(vwv+0, 1, 0);
14871 2 : SSVAL(vwv+1, 0, 0);
14872 2 : SSVAL(vwv+2, 0, 8192);
14873 2 : SSVAL(vwv+3, 0, 2);
14874 2 : SSVAL(vwv+4, 0, 1);
14875 2 : SIVAL(vwv+5, 0, 0);
14876 2 : SSVAL(vwv+7, 0, strlen(pass)); /* OEMPasswordLen */
14877 2 : SSVAL(vwv+8, 0, 0); /* UnicodePasswordLen */
14878 2 : SSVAL(vwv+9, 0, 0); /* reserved */
14879 2 : SSVAL(vwv+10, 0, 0); /* reserved */
14880 2 : SIVAL(vwv+11, 0, CAP_STATUS32);
14881 :
14882 2 : memcpy(bytes, pass, strlen(pass));
14883 2 : bytes += strlen(pass);
14884 2 : memcpy(bytes, uname, strlen(uname)+1);
14885 :
14886 2 : subreq = smb1cli_req_send(state, ev, conn,
14887 : SMBsesssetupX,
14888 : 0, /* additional_flags */
14889 : 0, /* clear_flags */
14890 : 0, /* additional_flags2 */
14891 : 0, /* clear_flags2 */
14892 : 10000, /* timeout_msec */
14893 2 : getpid(),
14894 : NULL, /* tcon */
14895 : NULL, /* session */
14896 : 13, /* wct */
14897 2 : state->vwv,
14898 2 : strlen(pass), /* Truncate length at password. */
14899 2 : state->bytes);
14900 2 : if (tevent_req_nomem(subreq, req)) {
14901 0 : return tevent_req_post(req, ev);
14902 : }
14903 2 : tevent_req_set_callback(subreq,
14904 : smb1_session_setup_nt1_truncated_done,
14905 : req);
14906 2 : return req;
14907 : }
14908 :
14909 2 : static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq)
14910 : {
14911 0 : struct tevent_req *req =
14912 2 : tevent_req_callback_data(subreq,
14913 : struct tevent_req);
14914 0 : struct session_setup_nt1_truncated_state *state =
14915 2 : tevent_req_data(req,
14916 : struct session_setup_nt1_truncated_state);
14917 0 : NTSTATUS status;
14918 2 : struct smb1cli_req_expected_response expected[] = {
14919 : {
14920 : .status = NT_STATUS_OK,
14921 : .wct = 3,
14922 : },
14923 : };
14924 :
14925 2 : status = smb1cli_req_recv(subreq, state,
14926 : NULL,
14927 : NULL,
14928 : NULL,
14929 : NULL,
14930 : NULL, /* pvwv_offset */
14931 : NULL,
14932 : NULL,
14933 : NULL, /* pbytes_offset */
14934 : NULL,
14935 : expected, ARRAY_SIZE(expected));
14936 2 : TALLOC_FREE(subreq);
14937 2 : if (tevent_req_nterror(req, status)) {
14938 0 : return;
14939 : }
14940 2 : tevent_req_done(req);
14941 : }
14942 :
14943 2 : static NTSTATUS smb1_session_setup_nt1_truncated_recv(struct tevent_req *req)
14944 : {
14945 2 : return tevent_req_simple_recv_ntstatus(req);
14946 : }
14947 :
14948 2 : static bool run_smb1_truncated_sesssetup(int dummy)
14949 : {
14950 0 : struct tevent_context *ev;
14951 0 : struct tevent_req *req;
14952 0 : struct smbXcli_conn *conn;
14953 0 : struct sockaddr_storage ss;
14954 0 : NTSTATUS status;
14955 0 : int fd;
14956 0 : bool ok;
14957 :
14958 2 : printf("Starting send truncated SMB1 sesssetup.\n");
14959 :
14960 2 : ok = resolve_name(host, &ss, 0x20, true);
14961 2 : if (!ok) {
14962 0 : d_fprintf(stderr, "Could not resolve name %s\n", host);
14963 0 : return false;
14964 : }
14965 :
14966 2 : status = open_socket_out(&ss, 445, 10000, &fd);
14967 2 : if (!NT_STATUS_IS_OK(status)) {
14968 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
14969 : nt_errstr(status));
14970 0 : return false;
14971 : }
14972 :
14973 2 : conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14974 : NULL, 0, NULL);
14975 2 : if (conn == NULL) {
14976 0 : d_fprintf(stderr, "smbXcli_conn_create failed\n");
14977 0 : return false;
14978 : }
14979 :
14980 2 : status = smbXcli_negprot(conn,
14981 : 0,
14982 : PROTOCOL_NT1,
14983 : PROTOCOL_NT1,
14984 : NULL,
14985 : NULL,
14986 : NULL);
14987 2 : if (!NT_STATUS_IS_OK(status)) {
14988 0 : d_fprintf(stderr, "smbXcli_negprot failed!\n");
14989 0 : return false;
14990 : }
14991 :
14992 2 : ev = samba_tevent_context_init(talloc_tos());
14993 2 : if (ev == NULL) {
14994 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
14995 0 : return false;
14996 : }
14997 :
14998 2 : req = smb1_session_setup_nt1_truncated_send(ev, ev, conn);
14999 2 : if (req == NULL) {
15000 0 : d_fprintf(stderr, "smb1_session_setup_nt1_truncated_send failed\n");
15001 0 : return false;
15002 : }
15003 :
15004 2 : ok = tevent_req_poll_ntstatus(req, ev, &status);
15005 2 : if (!ok) {
15006 0 : d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
15007 : nt_errstr(status));
15008 0 : return false;
15009 : }
15010 :
15011 2 : status = smb1_session_setup_nt1_truncated_recv(req);
15012 2 : if (!NT_STATUS_IS_OK(status)) {
15013 0 : d_fprintf(stderr, "smb1_session_setup_nt1_truncated_recv returned "
15014 : "%s, expected NT_STATUS_OK\n",
15015 : nt_errstr(status));
15016 0 : return false;
15017 : }
15018 :
15019 2 : TALLOC_FREE(conn);
15020 2 : return true;
15021 : }
15022 :
15023 : struct smb1_negotiate_exit_state {
15024 : int dummy;
15025 : };
15026 :
15027 : static void smb1_negotiate_exit_done(struct tevent_req *subreq);
15028 :
15029 4 : static struct tevent_req *smb1_negotiate_exit_send(
15030 : TALLOC_CTX *mem_ctx,
15031 : struct tevent_context *ev,
15032 : struct smbXcli_conn *conn)
15033 : {
15034 4 : struct smb1_negotiate_exit_state *state = NULL;
15035 4 : struct tevent_req *req = NULL;
15036 4 : struct tevent_req *subreq = NULL;
15037 :
15038 4 : req = tevent_req_create(mem_ctx,
15039 : &state,
15040 : struct smb1_negotiate_exit_state);
15041 4 : if (req == NULL) {
15042 0 : return NULL;
15043 : }
15044 4 : subreq = smb1cli_req_send(state, ev, conn,
15045 : SMBexit,
15046 : 0, /* additional_flags */
15047 : 0, /* clear_flags */
15048 : 0, /* additional_flags2 */
15049 : 0, /* clear_flags2 */
15050 : 10000, /* timeout_msec */
15051 4 : getpid(),
15052 : NULL, /* tcon */
15053 : NULL, /* session */
15054 : 0, /* wct */
15055 : NULL,
15056 : 0,
15057 : NULL);
15058 4 : if (tevent_req_nomem(subreq, req)) {
15059 0 : return tevent_req_post(req, ev);
15060 : }
15061 4 : tevent_req_set_callback(subreq,
15062 : smb1_negotiate_exit_done,
15063 : req);
15064 4 : return req;
15065 : }
15066 :
15067 4 : static void smb1_negotiate_exit_done(struct tevent_req *subreq)
15068 : {
15069 0 : struct tevent_req *req =
15070 4 : tevent_req_callback_data(subreq,
15071 : struct tevent_req);
15072 0 : struct smb1_negotiate_exit_state *state =
15073 4 : tevent_req_data(req,
15074 : struct smb1_negotiate_exit_state);
15075 0 : NTSTATUS status;
15076 4 : struct smb1cli_req_expected_response expected[] = {
15077 : {
15078 : .status = NT_STATUS_OK,
15079 : .wct = 0,
15080 : },
15081 : };
15082 :
15083 4 : status = smb1cli_req_recv(subreq, state,
15084 : NULL,
15085 : NULL,
15086 : NULL,
15087 : NULL,
15088 : NULL, /* pvwv_offset */
15089 : NULL,
15090 : NULL,
15091 : NULL, /* pbytes_offset */
15092 : NULL,
15093 : expected, ARRAY_SIZE(expected));
15094 4 : TALLOC_FREE(subreq);
15095 4 : if (tevent_req_nterror(req, status)) {
15096 4 : return;
15097 : }
15098 0 : tevent_req_done(req);
15099 : }
15100 :
15101 4 : static NTSTATUS smb1_negotiate_exit_recv(struct tevent_req *req)
15102 : {
15103 4 : return tevent_req_simple_recv_ntstatus(req);
15104 : }
15105 :
15106 4 : static bool do_smb1_exit(TALLOC_CTX *mem_ctx,
15107 : struct tevent_context *ev,
15108 : struct smbXcli_conn *conn)
15109 : {
15110 0 : struct tevent_req *req;
15111 0 : bool ok;
15112 0 : NTSTATUS status;
15113 4 : NTSTATUS expected_status = NT_STATUS_DOS(ERRSRV, ERRinvnid);;
15114 :
15115 4 : req = smb1_negotiate_exit_send(ev, ev, conn);
15116 4 : if (req == NULL) {
15117 0 : d_fprintf(stderr, "smb1_negotiate_exit_send failed\n");
15118 0 : return false;
15119 : }
15120 :
15121 4 : ok = tevent_req_poll_ntstatus(req, ev, &status);
15122 4 : if (!ok) {
15123 0 : d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
15124 : nt_errstr(status));
15125 0 : return false;
15126 : }
15127 :
15128 4 : status = smb1_negotiate_exit_recv(req);
15129 4 : if (!NT_STATUS_EQUAL(status, expected_status)) {
15130 0 : d_fprintf(stderr, "smb1_negotiate_exit_recv returned "
15131 : "%s, expected ERRSRV, ERRinvnid\n",
15132 : nt_errstr(status));
15133 0 : return false;
15134 : }
15135 4 : return true;
15136 : }
15137 :
15138 2 : static bool run_smb1_negotiate_exit(int dummy)
15139 : {
15140 0 : struct tevent_context *ev;
15141 0 : struct smbXcli_conn *conn;
15142 0 : struct sockaddr_storage ss;
15143 0 : NTSTATUS status;
15144 0 : int fd;
15145 0 : bool ok;
15146 :
15147 2 : printf("Starting send SMB1 negotiate+exit.\n");
15148 :
15149 2 : ok = resolve_name(host, &ss, 0x20, true);
15150 2 : if (!ok) {
15151 0 : d_fprintf(stderr, "Could not resolve name %s\n", host);
15152 0 : return false;
15153 : }
15154 :
15155 2 : status = open_socket_out(&ss, 445, 10000, &fd);
15156 2 : if (!NT_STATUS_IS_OK(status)) {
15157 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
15158 : nt_errstr(status));
15159 0 : return false;
15160 : }
15161 :
15162 2 : conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15163 : NULL, 0, NULL);
15164 2 : if (conn == NULL) {
15165 0 : d_fprintf(stderr, "smbXcli_conn_create failed\n");
15166 0 : return false;
15167 : }
15168 :
15169 2 : status = smbXcli_negprot(conn,
15170 : 0,
15171 : PROTOCOL_NT1,
15172 : PROTOCOL_NT1,
15173 : NULL,
15174 : NULL,
15175 : NULL);
15176 2 : if (!NT_STATUS_IS_OK(status)) {
15177 0 : d_fprintf(stderr, "smbXcli_negprot failed!\n");
15178 0 : return false;
15179 : }
15180 :
15181 2 : ev = samba_tevent_context_init(talloc_tos());
15182 2 : if (ev == NULL) {
15183 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
15184 0 : return false;
15185 : }
15186 :
15187 : /*
15188 : * Call do_smb1_exit twice to catch a server crash, the
15189 : * server sends the first return code then crashes.
15190 : */
15191 2 : ok = do_smb1_exit(ev, ev, conn);
15192 2 : if (!ok) {
15193 0 : d_fprintf(stderr, "do_smb1_exit (1) failed\n");
15194 0 : return false;
15195 : }
15196 2 : ok = do_smb1_exit(ev, ev, conn);
15197 2 : if (!ok) {
15198 0 : d_fprintf(stderr, "do_smb1_exit (2) failed\n");
15199 0 : return false;
15200 : }
15201 :
15202 2 : TALLOC_FREE(conn);
15203 2 : return true;
15204 : }
15205 :
15206 2 : static bool run_smb1_negotiate_tcon(int dummy)
15207 : {
15208 2 : struct cli_state *cli = NULL;
15209 2 : uint16_t cnum = 0;
15210 2 : uint16_t max_xmit = 0;
15211 0 : NTSTATUS status;
15212 :
15213 2 : printf("Starting send SMB1 negotiate+tcon.\n");
15214 2 : cli = open_nbt_connection();
15215 2 : if (cli == NULL) {
15216 0 : d_fprintf(stderr, "open_nbt_connection failed!\n");
15217 0 : return false;
15218 : }
15219 2 : smbXcli_conn_set_sockopt(cli->conn, sockops);
15220 :
15221 2 : status = smbXcli_negprot(cli->conn,
15222 : 0,
15223 : PROTOCOL_NT1,
15224 : PROTOCOL_NT1,
15225 : NULL,
15226 : NULL,
15227 : NULL);
15228 2 : if (!NT_STATUS_IS_OK(status)) {
15229 0 : d_fprintf(stderr, "smbXcli_negprot failed %s!\n",
15230 : nt_errstr(status));
15231 0 : return false;
15232 : }
15233 2 : status = cli_raw_tcon(cli,
15234 : share,
15235 : "",
15236 : "?????",
15237 : &max_xmit,
15238 : &cnum);
15239 2 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
15240 0 : d_fprintf(stderr, "cli_raw_tcon failed - got %s "
15241 : "(should get NT_STATUS_ACCESS_DENIED)!\n",
15242 : nt_errstr(status));
15243 0 : return false;
15244 : }
15245 2 : return true;
15246 : }
15247 :
15248 0 : static bool run_ign_bad_negprot(int dummy)
15249 : {
15250 0 : struct tevent_context *ev;
15251 0 : struct tevent_req *req;
15252 0 : struct smbXcli_conn *conn;
15253 0 : struct sockaddr_storage ss;
15254 0 : NTSTATUS status;
15255 0 : int fd;
15256 0 : bool ok;
15257 :
15258 0 : printf("starting ignore bad negprot\n");
15259 :
15260 0 : ok = resolve_name(host, &ss, 0x20, true);
15261 0 : if (!ok) {
15262 0 : d_fprintf(stderr, "Could not resolve name %s\n", host);
15263 0 : return false;
15264 : }
15265 :
15266 0 : status = open_socket_out(&ss, 445, 10000, &fd);
15267 0 : if (!NT_STATUS_IS_OK(status)) {
15268 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
15269 : nt_errstr(status));
15270 0 : return false;
15271 : }
15272 :
15273 0 : conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15274 : NULL, 0, NULL);
15275 0 : if (conn == NULL) {
15276 0 : d_fprintf(stderr, "smbXcli_conn_create failed\n");
15277 0 : return false;
15278 : }
15279 :
15280 0 : status = smbXcli_negprot(conn,
15281 : 0,
15282 : PROTOCOL_CORE,
15283 : PROTOCOL_CORE,
15284 : NULL,
15285 : NULL,
15286 : NULL);
15287 0 : if (NT_STATUS_IS_OK(status)) {
15288 0 : d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
15289 0 : return false;
15290 : }
15291 :
15292 0 : ev = samba_tevent_context_init(talloc_tos());
15293 0 : if (ev == NULL) {
15294 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
15295 0 : return false;
15296 : }
15297 :
15298 0 : req = smb1cli_session_setup_nt1_send(
15299 0 : ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
15300 : data_blob_null, data_blob_null, 0x40,
15301 : "Windows 2000 2195", "Windows 2000 5.0");
15302 0 : if (req == NULL) {
15303 0 : d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
15304 0 : return false;
15305 : }
15306 :
15307 0 : ok = tevent_req_poll_ntstatus(req, ev, &status);
15308 0 : if (!ok) {
15309 0 : d_fprintf(stderr, "tevent_req_poll failed\n");
15310 0 : return false;
15311 : }
15312 :
15313 0 : status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
15314 : NULL, NULL);
15315 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
15316 0 : d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
15317 : "%s, expected NT_STATUS_CONNECTION_RESET\n",
15318 : nt_errstr(status));
15319 0 : return false;
15320 : }
15321 :
15322 0 : TALLOC_FREE(conn);
15323 :
15324 0 : printf("starting ignore bad negprot\n");
15325 :
15326 0 : return true;
15327 : }
15328 :
15329 :
15330 16 : static double create_procs(bool (*fn)(int), bool *result)
15331 : {
15332 0 : int i, status;
15333 0 : volatile pid_t *child_status;
15334 0 : volatile bool *child_status_out;
15335 0 : int synccount;
15336 16 : int tries = 8;
15337 0 : struct timeval start;
15338 :
15339 16 : synccount = 0;
15340 :
15341 16 : child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
15342 16 : if (!child_status) {
15343 0 : printf("Failed to setup shared memory\n");
15344 0 : return -1;
15345 : }
15346 :
15347 16 : child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
15348 16 : if (!child_status_out) {
15349 0 : printf("Failed to setup result status shared memory\n");
15350 0 : return -1;
15351 : }
15352 :
15353 32 : for (i = 0; i < torture_nprocs; i++) {
15354 16 : child_status[i] = 0;
15355 16 : child_status_out[i] = True;
15356 : }
15357 :
15358 16 : start = timeval_current();
15359 :
15360 32 : for (i=0;i<torture_nprocs;i++) {
15361 16 : procnum = i;
15362 16 : if (fork() == 0) {
15363 0 : pid_t mypid = getpid();
15364 0 : sys_srandom(((int)mypid) ^ ((int)time(NULL)));
15365 :
15366 0 : slprintf(myname,sizeof(myname),"CLIENT%d", i);
15367 :
15368 0 : while (1) {
15369 0 : if (torture_open_connection(¤t_cli, i)) break;
15370 0 : if (tries-- == 0) {
15371 0 : printf("pid %d failed to start\n", (int)getpid());
15372 0 : _exit(1);
15373 : }
15374 0 : smb_msleep(10);
15375 : }
15376 :
15377 0 : child_status[i] = getpid();
15378 :
15379 0 : while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
15380 :
15381 0 : child_status_out[i] = fn(i);
15382 0 : _exit(0);
15383 : }
15384 : }
15385 :
15386 0 : do {
15387 75 : synccount = 0;
15388 150 : for (i=0;i<torture_nprocs;i++) {
15389 75 : if (child_status[i]) synccount++;
15390 : }
15391 75 : if (synccount == torture_nprocs) break;
15392 59 : smb_msleep(10);
15393 59 : } while (timeval_elapsed(&start) < 30);
15394 :
15395 16 : if (synccount != torture_nprocs) {
15396 0 : printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
15397 0 : *result = False;
15398 0 : return timeval_elapsed(&start);
15399 : }
15400 :
15401 : /* start the client load */
15402 16 : start = timeval_current();
15403 :
15404 32 : for (i=0;i<torture_nprocs;i++) {
15405 16 : child_status[i] = 0;
15406 : }
15407 :
15408 16 : printf("%d clients started\n", torture_nprocs);
15409 :
15410 32 : for (i=0;i<torture_nprocs;i++) {
15411 16 : while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
15412 : }
15413 :
15414 16 : printf("\n");
15415 :
15416 32 : for (i=0;i<torture_nprocs;i++) {
15417 16 : if (!child_status_out[i]) {
15418 2 : *result = False;
15419 : }
15420 : }
15421 16 : return timeval_elapsed(&start);
15422 : }
15423 :
15424 : #define FLAG_MULTIPROC 1
15425 :
15426 : static struct {
15427 : const char *name;
15428 : bool (*fn)(int);
15429 : unsigned flags;
15430 : } torture_ops[] = {
15431 : {
15432 : .name = "FDPASS",
15433 : .fn = run_fdpasstest,
15434 : },
15435 : {
15436 : .name = "LOCK1",
15437 : .fn = run_locktest1,
15438 : },
15439 : {
15440 : .name = "LOCK2",
15441 : .fn = run_locktest2,
15442 : },
15443 : {
15444 : .name = "LOCK3",
15445 : .fn = run_locktest3,
15446 : },
15447 : {
15448 : .name = "LOCK4",
15449 : .fn = run_locktest4,
15450 : },
15451 : {
15452 : .name = "LOCK5",
15453 : .fn = run_locktest5,
15454 : },
15455 : {
15456 : .name = "LOCK6",
15457 : .fn = run_locktest6,
15458 : },
15459 : {
15460 : .name = "LOCK7",
15461 : .fn = run_locktest7,
15462 : },
15463 : {
15464 : .name = "LOCK8",
15465 : .fn = run_locktest8,
15466 : },
15467 : {
15468 : .name = "LOCK9A",
15469 : .fn = run_locktest9a,
15470 : },
15471 : {
15472 : .name = "LOCK9B",
15473 : .fn = run_locktest9b,
15474 : },
15475 : {
15476 : .name = "LOCK10",
15477 : .fn = run_locktest10,
15478 : },
15479 : {
15480 : .name = "LOCK11",
15481 : .fn = run_locktest11,
15482 : },
15483 : {
15484 : .name = "LOCK12",
15485 : .fn = run_locktest12,
15486 : },
15487 : {
15488 : .name = "LOCK13",
15489 : .fn = run_locktest13,
15490 : },
15491 : {
15492 : .name = "UNLINK",
15493 : .fn = run_unlinktest,
15494 : },
15495 : {
15496 : .name = "BROWSE",
15497 : .fn = run_browsetest,
15498 : },
15499 : {
15500 : .name = "ATTR",
15501 : .fn = run_attrtest,
15502 : },
15503 : {
15504 : .name = "TRANS2",
15505 : .fn = run_trans2test,
15506 : },
15507 : {
15508 : .name = "MAXFID",
15509 : .fn = run_maxfidtest,
15510 : .flags = FLAG_MULTIPROC,
15511 : },
15512 : {
15513 : .name = "TORTURE",
15514 : .fn = run_torture,
15515 : .flags = FLAG_MULTIPROC,
15516 : },
15517 : {
15518 : .name = "RANDOMIPC",
15519 : .fn = run_randomipc,
15520 : },
15521 : {
15522 : .name = "NEGNOWAIT",
15523 : .fn = run_negprot_nowait,
15524 : },
15525 : {
15526 : .name = "NBENCH",
15527 : .fn = run_nbench,
15528 : },
15529 : {
15530 : .name = "NBENCH2",
15531 : .fn = run_nbench2,
15532 : },
15533 : {
15534 : .name = "OPLOCK1",
15535 : .fn = run_oplock1,
15536 : },
15537 : {
15538 : .name = "OPLOCK2",
15539 : .fn = run_oplock2,
15540 : },
15541 : {
15542 : .name = "OPLOCK4",
15543 : .fn = run_oplock4,
15544 : },
15545 : #ifdef HAVE_KERNEL_OPLOCKS_LINUX
15546 : {
15547 : .name = "OPLOCK5",
15548 : .fn = run_oplock5,
15549 : },
15550 : #endif
15551 : {
15552 : .name = "DIR",
15553 : .fn = run_dirtest,
15554 : },
15555 : {
15556 : .name = "DIR1",
15557 : .fn = run_dirtest1,
15558 : },
15559 : {
15560 : .name = "DIR-CREATETIME",
15561 : .fn = run_dir_createtime,
15562 : },
15563 : {
15564 : .name = "DENY1",
15565 : .fn = torture_denytest1,
15566 : },
15567 : {
15568 : .name = "DENY2",
15569 : .fn = torture_denytest2,
15570 : },
15571 : {
15572 : .name = "TCON",
15573 : .fn = run_tcon_test,
15574 : },
15575 : {
15576 : .name = "TCONDEV",
15577 : .fn = run_tcon_devtype_test,
15578 : },
15579 : {
15580 : .name = "RW1",
15581 : .fn = run_readwritetest,
15582 : },
15583 : {
15584 : .name = "RW2",
15585 : .fn = run_readwritemulti,
15586 : .flags = FLAG_MULTIPROC
15587 : },
15588 : {
15589 : .name = "RW3",
15590 : .fn = run_readwritelarge,
15591 : },
15592 : {
15593 : .name = "RW-SIGNING",
15594 : .fn = run_readwritelarge_signtest,
15595 : },
15596 : {
15597 : .name = "OPEN",
15598 : .fn = run_opentest,
15599 : },
15600 : {
15601 : .name = "POSIX",
15602 : .fn = run_simple_posix_open_test,
15603 : },
15604 : {
15605 : .name = "POSIX-APPEND",
15606 : .fn = run_posix_append,
15607 : },
15608 : {
15609 : .name = "POSIX-SYMLINK-ACL",
15610 : .fn = run_acl_symlink_test,
15611 : },
15612 : {
15613 : .name = "POSIX-SYMLINK-EA",
15614 : .fn = run_ea_symlink_test,
15615 : },
15616 : {
15617 : .name = "POSIX-STREAM-DELETE",
15618 : .fn = run_posix_stream_delete,
15619 : },
15620 : {
15621 : .name = "POSIX-OFD-LOCK",
15622 : .fn = run_posix_ofd_lock_test,
15623 : },
15624 : {
15625 : .name = "POSIX-BLOCKING-LOCK",
15626 : .fn = run_posix_blocking_lock,
15627 : },
15628 : {
15629 : .name = "POSIX-MKDIR",
15630 : .fn = run_posix_mkdir_test,
15631 : },
15632 : {
15633 : .name = "POSIX-ACL-OPLOCK",
15634 : .fn = run_posix_acl_oplock_test,
15635 : },
15636 : {
15637 : .name = "POSIX-ACL-SHAREROOT",
15638 : .fn = run_posix_acl_shareroot_test,
15639 : },
15640 : {
15641 : .name = "POSIX-LS-WILDCARD",
15642 : .fn = run_posix_ls_wildcard_test,
15643 : },
15644 : {
15645 : .name = "POSIX-LS-SINGLE",
15646 : .fn = run_posix_ls_single_test,
15647 : },
15648 : {
15649 : .name = "POSIX-READLINK",
15650 : .fn = run_posix_readlink_test,
15651 : },
15652 : {
15653 : .name = "POSIX-STAT",
15654 : .fn = run_posix_stat_test,
15655 : },
15656 : {
15657 : .name = "POSIX-SYMLINK-PARENT",
15658 : .fn = run_posix_symlink_parent_test,
15659 : },
15660 : {
15661 : .name = "POSIX-SYMLINK-CHMOD",
15662 : .fn = run_posix_symlink_chmod_test,
15663 : },
15664 : {
15665 : .name = "POSIX-SYMLINK-RENAME",
15666 : .fn = run_posix_symlink_rename_test,
15667 : },
15668 : {
15669 : .name = "POSIX-DIR-DEFAULT-ACL",
15670 : .fn = run_posix_dir_default_acl_test,
15671 : },
15672 : {
15673 : .name = "POSIX-SYMLINK-GETPATHINFO",
15674 : .fn = run_posix_symlink_getpathinfo_test,
15675 : },
15676 : {
15677 : .name = "POSIX-SYMLINK-SETPATHINFO",
15678 : .fn = run_posix_symlink_setpathinfo_test,
15679 : },
15680 : {
15681 : .name = "WINDOWS-BAD-SYMLINK",
15682 : .fn = run_symlink_open_test,
15683 : },
15684 : {
15685 : .name = "SMB1-WILD-MANGLE-UNLINK",
15686 : .fn = run_smb1_wild_mangle_unlink_test,
15687 : },
15688 : {
15689 : .name = "SMB1-WILD-MANGLE-RENAME",
15690 : .fn = run_smb1_wild_mangle_rename_test,
15691 : },
15692 : {
15693 : .name = "CASE-INSENSITIVE-CREATE",
15694 : .fn = run_case_insensitive_create,
15695 : },
15696 : {
15697 : .name = "ASYNC-ECHO",
15698 : .fn = run_async_echo,
15699 : },
15700 : {
15701 : .name = "UID-REGRESSION-TEST",
15702 : .fn = run_uid_regression_test,
15703 : },
15704 : {
15705 : .name = "SHORTNAME-TEST",
15706 : .fn = run_shortname_test,
15707 : },
15708 : {
15709 : .name = "ADDRCHANGE",
15710 : .fn = run_addrchange,
15711 : },
15712 : #if 1
15713 : {
15714 : .name = "OPENATTR",
15715 : .fn = run_openattrtest,
15716 : },
15717 : #endif
15718 : {
15719 : .name = "XCOPY",
15720 : .fn = run_xcopy,
15721 : },
15722 : {
15723 : .name = "RENAME",
15724 : .fn = run_rename,
15725 : },
15726 : {
15727 : .name = "RENAME-ACCESS",
15728 : .fn = run_rename_access,
15729 : },
15730 : {
15731 : .name = "OWNER-RIGHTS",
15732 : .fn = run_owner_rights,
15733 : },
15734 : {
15735 : .name = "DELETE",
15736 : .fn = run_deletetest,
15737 : },
15738 : {
15739 : .name = "DELETE-STREAM",
15740 : .fn = run_delete_stream,
15741 : },
15742 : {
15743 : .name = "DELETE-PRINT",
15744 : .fn = run_delete_print_test,
15745 : },
15746 : {
15747 : .name = "DELETE-LN",
15748 : .fn = run_deletetest_ln,
15749 : },
15750 : {
15751 : .name = "PROPERTIES",
15752 : .fn = run_properties,
15753 : },
15754 : {
15755 : .name = "MANGLE",
15756 : .fn = torture_mangle,
15757 : },
15758 : {
15759 : .name = "MANGLE1",
15760 : .fn = run_mangle1,
15761 : },
15762 : {
15763 : .name = "MANGLE-ILLEGAL",
15764 : .fn = run_mangle_illegal,
15765 : },
15766 : {
15767 : .name = "W2K",
15768 : .fn = run_w2ktest,
15769 : },
15770 : {
15771 : .name = "TRANS2SCAN",
15772 : .fn = torture_trans2_scan,
15773 : },
15774 : {
15775 : .name = "NTTRANSSCAN",
15776 : .fn = torture_nttrans_scan,
15777 : },
15778 : {
15779 : .name = "UTABLE",
15780 : .fn = torture_utable,
15781 : },
15782 : {
15783 : .name = "CASETABLE",
15784 : .fn = torture_casetable,
15785 : },
15786 : {
15787 : .name = "ERRMAPEXTRACT",
15788 : .fn = run_error_map_extract,
15789 : },
15790 : {
15791 : .name = "PIPE_NUMBER",
15792 : .fn = run_pipe_number,
15793 : },
15794 : {
15795 : .name = "TCON2",
15796 : .fn = run_tcon2_test,
15797 : },
15798 : {
15799 : .name = "IOCTL",
15800 : .fn = torture_ioctl_test,
15801 : },
15802 : {
15803 : .name = "CHKPATH",
15804 : .fn = torture_chkpath_test,
15805 : },
15806 : {
15807 : .name = "FDSESS",
15808 : .fn = run_fdsesstest,
15809 : },
15810 : {
15811 : .name = "EATEST",
15812 : .fn = run_eatest,
15813 : },
15814 : {
15815 : .name = "SESSSETUP_BENCH",
15816 : .fn = run_sesssetup_bench,
15817 : },
15818 : {
15819 : .name = "CHAIN1",
15820 : .fn = run_chain1,
15821 : },
15822 : {
15823 : .name = "CHAIN2",
15824 : .fn = run_chain2,
15825 : },
15826 : {
15827 : .name = "CHAIN3",
15828 : .fn = run_chain3,
15829 : },
15830 : {
15831 : .name = "WINDOWS-WRITE",
15832 : .fn = run_windows_write,
15833 : },
15834 : {
15835 : .name = "LARGE_READX",
15836 : .fn = run_large_readx,
15837 : },
15838 : {
15839 : .name = "MSDFS-ATTRIBUTE",
15840 : .fn = run_msdfs_attribute,
15841 : },
15842 : {
15843 : .name = "NTTRANS-CREATE",
15844 : .fn = run_nttrans_create,
15845 : },
15846 : {
15847 : .name = "NTTRANS-FSCTL",
15848 : .fn = run_nttrans_fsctl,
15849 : },
15850 : {
15851 : .name = "CLI_ECHO",
15852 : .fn = run_cli_echo,
15853 : },
15854 : {
15855 : .name = "CLI_SPLICE",
15856 : .fn = run_cli_splice,
15857 : },
15858 : {
15859 : .name = "TLDAP",
15860 : .fn = run_tldap,
15861 : },
15862 : {
15863 : .name = "STREAMERROR",
15864 : .fn = run_streamerror,
15865 : },
15866 : {
15867 : .name = "NOTIFY-BENCH",
15868 : .fn = run_notify_bench,
15869 : },
15870 : {
15871 : .name = "NOTIFY-BENCH2",
15872 : .fn = run_notify_bench2,
15873 : },
15874 : {
15875 : .name = "NOTIFY-BENCH3",
15876 : .fn = run_notify_bench3,
15877 : },
15878 : {
15879 : .name = "BAD-NBT-SESSION",
15880 : .fn = run_bad_nbt_session,
15881 : },
15882 : {
15883 : .name = "IGN-BAD-NEGPROT",
15884 : .fn = run_ign_bad_negprot,
15885 : },
15886 : {
15887 : .name = "SMB-ANY-CONNECT",
15888 : .fn = run_smb_any_connect,
15889 : },
15890 : {
15891 : .name = "NOTIFY-ONLINE",
15892 : .fn = run_notify_online,
15893 : },
15894 : {
15895 : .name = "SMB2-BASIC",
15896 : .fn = run_smb2_basic,
15897 : },
15898 : {
15899 : .name = "SMB2-NEGPROT",
15900 : .fn = run_smb2_negprot,
15901 : },
15902 : {
15903 : .name = "SMB2-ANONYMOUS",
15904 : .fn = run_smb2_anonymous,
15905 : },
15906 : {
15907 : .name = "SMB2-SESSION-RECONNECT",
15908 : .fn = run_smb2_session_reconnect,
15909 : },
15910 : {
15911 : .name = "SMB2-TCON-DEPENDENCE",
15912 : .fn = run_smb2_tcon_dependence,
15913 : },
15914 : {
15915 : .name = "SMB2-MULTI-CHANNEL",
15916 : .fn = run_smb2_multi_channel,
15917 : },
15918 : {
15919 : .name = "SMB2-SESSION-REAUTH",
15920 : .fn = run_smb2_session_reauth,
15921 : },
15922 : {
15923 : .name = "SMB2-FTRUNCATE",
15924 : .fn = run_smb2_ftruncate,
15925 : },
15926 : {
15927 : .name = "SMB2-DIR-FSYNC",
15928 : .fn = run_smb2_dir_fsync,
15929 : },
15930 : {
15931 : .name = "SMB2-PATH-SLASH",
15932 : .fn = run_smb2_path_slash,
15933 : },
15934 : {
15935 : .name = "SMB1-SYSTEM-SECURITY",
15936 : .fn = run_smb1_system_security,
15937 : },
15938 : {
15939 : .name = "SMB2-SACL",
15940 : .fn = run_smb2_sacl,
15941 : },
15942 : {
15943 : .name = "SMB2-QUOTA1",
15944 : .fn = run_smb2_quota1,
15945 : },
15946 : {
15947 : .name = "SMB2-INVALID-PIPENAME",
15948 : .fn = run_smb2_invalid_pipename,
15949 : },
15950 : {
15951 : .name = "SMB2-STREAM-ACL",
15952 : .fn = run_smb2_stream_acl,
15953 : },
15954 : {
15955 : .name = "SMB2-LIST-DIR-ASYNC",
15956 : .fn = run_list_dir_async_test,
15957 : },
15958 : {
15959 : .name = "SMB2-DEL-ON-CLOSE-NONEMPTY",
15960 : .fn = run_delete_on_close_non_empty,
15961 : },
15962 : {
15963 : .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15964 : .fn = run_delete_on_close_nonwrite_delete_yes_test,
15965 : },
15966 : {
15967 : .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15968 : .fn = run_delete_on_close_nonwrite_delete_no_test,
15969 : },
15970 : {
15971 : .name = "SMB2-DFS-PATHS",
15972 : .fn = run_smb2_dfs_paths,
15973 : },
15974 : {
15975 : .name = "SMB2-NON-DFS-SHARE",
15976 : .fn = run_smb2_non_dfs_share,
15977 : },
15978 : {
15979 : .name = "SMB2-DFS-SHARE-NON-DFS-PATH",
15980 : .fn = run_smb2_dfs_share_non_dfs_path,
15981 : },
15982 : {
15983 : .name = "SMB2-DFS-FILENAME-LEADING-BACKSLASH",
15984 : .fn = run_smb2_dfs_filename_leading_backslash,
15985 : },
15986 : {
15987 : .name = "SMB2-PIPE-READ-ASYNC-DISCONNECT",
15988 : .fn = run_smb2_pipe_read_async_disconnect,
15989 : },
15990 : {
15991 : .name = "SMB1-TRUNCATED-SESSSETUP",
15992 : .fn = run_smb1_truncated_sesssetup,
15993 : },
15994 : {
15995 : .name = "SMB1-NEGOTIATE-EXIT",
15996 : .fn = run_smb1_negotiate_exit,
15997 : },
15998 : {
15999 : .name = "SMB1-NEGOTIATE-TCON",
16000 : .fn = run_smb1_negotiate_tcon,
16001 : },
16002 : {
16003 : .name = "SMB1-DFS-PATHS",
16004 : .fn = run_smb1_dfs_paths,
16005 : },
16006 : {
16007 : .name = "SMB1-DFS-SEARCH-PATHS",
16008 : .fn = run_smb1_dfs_search_paths,
16009 : },
16010 : {
16011 : .name = "SMB1-DFS-OPERATIONS",
16012 : .fn = run_smb1_dfs_operations,
16013 : },
16014 : {
16015 : .name = "SMB1-DFS-BADPATH",
16016 : .fn = run_smb1_dfs_check_badpath,
16017 : },
16018 : {
16019 : .name = "CLEANUP1",
16020 : .fn = run_cleanup1,
16021 : },
16022 : {
16023 : .name = "CLEANUP2",
16024 : .fn = run_cleanup2,
16025 : },
16026 : {
16027 : .name = "CLEANUP4",
16028 : .fn = run_cleanup4,
16029 : },
16030 : {
16031 : .name = "OPLOCK-CANCEL",
16032 : .fn = run_oplock_cancel,
16033 : },
16034 : {
16035 : .name = "PIDHIGH",
16036 : .fn = run_pidhigh,
16037 : },
16038 : {
16039 : .name = "LOCAL-SUBSTITUTE",
16040 : .fn = run_local_substitute,
16041 : },
16042 : {
16043 : .name = "LOCAL-GENCACHE",
16044 : .fn = run_local_gencache,
16045 : },
16046 : {
16047 : .name = "LOCAL-DBWRAP-WATCH1",
16048 : .fn = run_dbwrap_watch1,
16049 : },
16050 : {
16051 : .name = "LOCAL-DBWRAP-WATCH2",
16052 : .fn = run_dbwrap_watch2,
16053 : },
16054 : {
16055 : .name = "LOCAL-DBWRAP-WATCH3",
16056 : .fn = run_dbwrap_watch3,
16057 : },
16058 : {
16059 : .name = "LOCAL-DBWRAP-WATCH4",
16060 : .fn = run_dbwrap_watch4,
16061 : },
16062 : {
16063 : .name = "LOCAL-DBWRAP-DO-LOCKED1",
16064 : .fn = run_dbwrap_do_locked1,
16065 : },
16066 : {
16067 : .name = "LOCAL-MESSAGING-READ1",
16068 : .fn = run_messaging_read1,
16069 : },
16070 : {
16071 : .name = "LOCAL-MESSAGING-READ2",
16072 : .fn = run_messaging_read2,
16073 : },
16074 : {
16075 : .name = "LOCAL-MESSAGING-READ3",
16076 : .fn = run_messaging_read3,
16077 : },
16078 : {
16079 : .name = "LOCAL-MESSAGING-READ4",
16080 : .fn = run_messaging_read4,
16081 : },
16082 : {
16083 : .name = "LOCAL-MESSAGING-FDPASS1",
16084 : .fn = run_messaging_fdpass1,
16085 : },
16086 : {
16087 : .name = "LOCAL-MESSAGING-FDPASS2",
16088 : .fn = run_messaging_fdpass2,
16089 : },
16090 : {
16091 : .name = "LOCAL-MESSAGING-FDPASS2a",
16092 : .fn = run_messaging_fdpass2a,
16093 : },
16094 : {
16095 : .name = "LOCAL-MESSAGING-FDPASS2b",
16096 : .fn = run_messaging_fdpass2b,
16097 : },
16098 : {
16099 : .name = "LOCAL-MESSAGING-SEND-ALL",
16100 : .fn = run_messaging_send_all,
16101 : },
16102 : {
16103 : .name = "LOCAL-BASE64",
16104 : .fn = run_local_base64,
16105 : },
16106 : {
16107 : .name = "LOCAL-RBTREE",
16108 : .fn = run_local_rbtree,
16109 : },
16110 : {
16111 : .name = "LOCAL-MEMCACHE",
16112 : .fn = run_local_memcache,
16113 : },
16114 : {
16115 : .name = "LOCAL-STREAM-NAME",
16116 : .fn = run_local_stream_name,
16117 : },
16118 : {
16119 : .name = "LOCAL-STR-MATCH-MSWILD",
16120 : .fn = run_str_match_mswild,
16121 : },
16122 : {
16123 : .name = "LOCAL-STR-MATCH-REGEX-SUB1",
16124 : .fn = run_str_match_regex_sub1,
16125 : },
16126 : {
16127 : .name = "WBCLIENT-MULTI-PING",
16128 : .fn = run_wbclient_multi_ping,
16129 : },
16130 : {
16131 : .name = "LOCAL-string_to_sid",
16132 : .fn = run_local_string_to_sid,
16133 : },
16134 : {
16135 : .name = "LOCAL-sid_to_string",
16136 : .fn = run_local_sid_to_string,
16137 : },
16138 : {
16139 : .name = "LOCAL-binary_to_sid",
16140 : .fn = run_local_binary_to_sid,
16141 : },
16142 : {
16143 : .name = "LOCAL-DBTRANS",
16144 : .fn = run_local_dbtrans,
16145 : },
16146 : {
16147 : .name = "LOCAL-TEVENT-POLL",
16148 : .fn = run_local_tevent_poll,
16149 : },
16150 : {
16151 : .name = "LOCAL-CONVERT-STRING",
16152 : .fn = run_local_convert_string,
16153 : },
16154 : {
16155 : .name = "LOCAL-CONV-AUTH-INFO",
16156 : .fn = run_local_conv_auth_info,
16157 : },
16158 : {
16159 : .name = "LOCAL-hex_encode_buf",
16160 : .fn = run_local_hex_encode_buf,
16161 : },
16162 : {
16163 : .name = "LOCAL-IDMAP-TDB-COMMON",
16164 : .fn = run_idmap_tdb_common_test,
16165 : },
16166 : {
16167 : .name = "LOCAL-remove_duplicate_addrs2",
16168 : .fn = run_local_remove_duplicate_addrs2,
16169 : },
16170 : {
16171 : .name = "local-tdb-opener",
16172 : .fn = run_local_tdb_opener,
16173 : },
16174 : {
16175 : .name = "local-tdb-writer",
16176 : .fn = run_local_tdb_writer,
16177 : },
16178 : {
16179 : .name = "LOCAL-DBWRAP-CTDB1",
16180 : .fn = run_local_dbwrap_ctdb1,
16181 : },
16182 : {
16183 : .name = "LOCAL-BENCH-PTHREADPOOL",
16184 : .fn = run_bench_pthreadpool,
16185 : },
16186 : {
16187 : .name = "LOCAL-PTHREADPOOL-TEVENT",
16188 : .fn = run_pthreadpool_tevent,
16189 : },
16190 : {
16191 : .name = "LOCAL-G-LOCK1",
16192 : .fn = run_g_lock1,
16193 : },
16194 : {
16195 : .name = "LOCAL-G-LOCK2",
16196 : .fn = run_g_lock2,
16197 : },
16198 : {
16199 : .name = "LOCAL-G-LOCK3",
16200 : .fn = run_g_lock3,
16201 : },
16202 : {
16203 : .name = "LOCAL-G-LOCK4",
16204 : .fn = run_g_lock4,
16205 : },
16206 : {
16207 : .name = "LOCAL-G-LOCK4A",
16208 : .fn = run_g_lock4a,
16209 : },
16210 : {
16211 : .name = "LOCAL-G-LOCK5",
16212 : .fn = run_g_lock5,
16213 : },
16214 : {
16215 : .name = "LOCAL-G-LOCK6",
16216 : .fn = run_g_lock6,
16217 : },
16218 : {
16219 : .name = "LOCAL-G-LOCK7",
16220 : .fn = run_g_lock7,
16221 : },
16222 : {
16223 : .name = "LOCAL-G-LOCK8",
16224 : .fn = run_g_lock8,
16225 : },
16226 : {
16227 : .name = "LOCAL-G-LOCK-PING-PONG",
16228 : .fn = run_g_lock_ping_pong,
16229 : },
16230 : {
16231 : .name = "LOCAL-CANONICALIZE-PATH",
16232 : .fn = run_local_canonicalize_path,
16233 : },
16234 : {
16235 : .name = "LOCAL-NAMEMAP-CACHE1",
16236 : .fn = run_local_namemap_cache1,
16237 : },
16238 : {
16239 : .name = "LOCAL-IDMAP-CACHE1",
16240 : .fn = run_local_idmap_cache1,
16241 : },
16242 : {
16243 : .name = "qpathinfo-bufsize",
16244 : .fn = run_qpathinfo_bufsize,
16245 : },
16246 : {
16247 : .name = "hide-new-files-timeout",
16248 : .fn = run_hidenewfiles,
16249 : },
16250 : {
16251 : .name = "hide-new-files-timeout-showdirs",
16252 : .fn = run_hidenewfiles_showdirs,
16253 : },
16254 : #ifdef CLUSTER_SUPPORT
16255 : {
16256 : .name = "ctdbd-conn1",
16257 : .fn = run_ctdbd_conn1,
16258 : },
16259 : #endif
16260 : {
16261 : .name = "readdir-timestamp",
16262 : .fn = run_readdir_timestamp,
16263 : },
16264 : {
16265 : .name = "rpc-scale",
16266 : .fn = run_rpc_scale,
16267 : },
16268 : {
16269 : .name = "LOCAL-TDB-VALIDATE",
16270 : .fn = run_tdb_validate,
16271 : },
16272 : {
16273 : .name = NULL,
16274 : },
16275 : };
16276 :
16277 : /****************************************************************************
16278 : run a specified test or "ALL"
16279 : ****************************************************************************/
16280 552 : static bool run_test(const char *name)
16281 : {
16282 552 : bool ret = True;
16283 552 : bool result = True;
16284 552 : bool found = False;
16285 45 : int i;
16286 45 : double t;
16287 552 : if (strequal(name,"ALL")) {
16288 0 : for (i=0;torture_ops[i].name;i++) {
16289 0 : run_test(torture_ops[i].name);
16290 : }
16291 0 : found = True;
16292 : }
16293 :
16294 114995 : for (i=0;torture_ops[i].name;i++) {
16295 114439 : fstr_sprintf(randomfname, "\\XX%x",
16296 114439 : (unsigned)random());
16297 :
16298 114439 : if (strequal(name, torture_ops[i].name)) {
16299 552 : found = True;
16300 552 : printf("Running %s\n", name);
16301 552 : if (torture_ops[i].flags & FLAG_MULTIPROC) {
16302 16 : t = create_procs(torture_ops[i].fn, &result);
16303 16 : if (!result) {
16304 2 : ret = False;
16305 2 : printf("TEST %s FAILED!\n", name);
16306 : }
16307 : } else {
16308 45 : struct timeval start;
16309 536 : start = timeval_current();
16310 536 : if (!torture_ops[i].fn(0)) {
16311 14 : ret = False;
16312 14 : printf("TEST %s FAILED!\n", name);
16313 : }
16314 540 : t = timeval_elapsed(&start);
16315 : }
16316 10001 : printf("%s took %g secs\n\n", name, t);
16317 : }
16318 : }
16319 :
16320 556 : if (!found) {
16321 0 : printf("Did not find a test named %s\n", name);
16322 0 : ret = False;
16323 : }
16324 :
16325 556 : return ret;
16326 : }
16327 :
16328 :
16329 0 : static void usage(void)
16330 : {
16331 0 : int i;
16332 :
16333 0 : printf("WARNING samba4 test suite is much more complete nowadays.\n");
16334 0 : printf("Please use samba4 torture.\n\n");
16335 :
16336 0 : printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
16337 :
16338 0 : printf("\t-d debuglevel\n");
16339 0 : printf("\t-U user%%pass\n");
16340 0 : printf("\t-k use kerberos\n");
16341 0 : printf("\t-N numprocs\n");
16342 0 : printf("\t-n my_netbios_name\n");
16343 0 : printf("\t-W workgroup\n");
16344 0 : printf("\t-o num_operations\n");
16345 0 : printf("\t-O socket_options\n");
16346 0 : printf("\t-m maximum protocol\n");
16347 0 : printf("\t-L use oplocks\n");
16348 0 : printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
16349 0 : printf("\t-A showall\n");
16350 0 : printf("\t-p port\n");
16351 0 : printf("\t-s seed\n");
16352 0 : printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
16353 0 : printf("\t-f filename filename to test\n");
16354 0 : printf("\t-e encrypt\n");
16355 0 : printf("\t-T 'OPTION=VALUE' smb.conf option line\n");
16356 0 : printf("\n\n");
16357 :
16358 0 : printf("tests are:");
16359 0 : for (i=0;torture_ops[i].name;i++) {
16360 0 : printf(" %s", torture_ops[i].name);
16361 : }
16362 0 : printf("\n");
16363 :
16364 0 : printf("default test is ALL\n");
16365 :
16366 0 : exit(1);
16367 : }
16368 :
16369 : /****************************************************************************
16370 : main program
16371 : ****************************************************************************/
16372 552 : int main(int argc,char *argv[])
16373 : {
16374 45 : int opt, i;
16375 45 : char *p;
16376 552 : int gotuser = 0;
16377 552 : int gotpass = 0;
16378 552 : bool correct = True;
16379 552 : TALLOC_CTX *frame = talloc_stackframe();
16380 552 : int seed = time(NULL);
16381 552 : struct loadparm_context *lp_ctx = NULL;
16382 :
16383 : #ifdef HAVE_SETBUFFER
16384 552 : setbuffer(stdout, NULL, 0);
16385 : #endif
16386 :
16387 552 : setup_logging("smbtorture", DEBUG_STDOUT);
16388 :
16389 552 : smb_init_locale();
16390 552 : fault_setup();
16391 :
16392 552 : lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
16393 552 : if (lp_ctx == NULL) {
16394 0 : fprintf(stderr,
16395 : "Failed to initialise the global parameter structure.\n");
16396 0 : return 1;
16397 : }
16398 :
16399 552 : if (is_default_dyn_CONFIGFILE()) {
16400 552 : if(getenv("SMB_CONF_PATH")) {
16401 552 : set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
16402 : }
16403 : }
16404 552 : lp_load_global(get_dyn_CONFIGFILE());
16405 552 : load_interfaces();
16406 :
16407 552 : if (argc < 2) {
16408 0 : usage();
16409 : }
16410 :
16411 11131 : for(p = argv[1]; *p; p++)
16412 10579 : if(*p == '\\')
16413 0 : *p = '/';
16414 :
16415 552 : if (strncmp(argv[1], "//", 2)) {
16416 0 : usage();
16417 : }
16418 :
16419 552 : fstrcpy(host, &argv[1][2]);
16420 552 : p = strchr_m(&host[2],'/');
16421 552 : if (!p) {
16422 0 : usage();
16423 : }
16424 552 : *p = 0;
16425 552 : fstrcpy(share, p+1);
16426 :
16427 552 : fstrcpy(myname, get_myname(talloc_tos()));
16428 552 : if (!*myname) {
16429 0 : fprintf(stderr, "Failed to get my hostname.\n");
16430 0 : return 1;
16431 : }
16432 :
16433 552 : if (*username == 0 && getenv("LOGNAME")) {
16434 0 : fstrcpy(username,getenv("LOGNAME"));
16435 : }
16436 :
16437 552 : argc--;
16438 552 : argv++;
16439 :
16440 552 : fstrcpy(workgroup, lp_workgroup());
16441 :
16442 1755 : while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:T:"))
16443 1800 : != EOF) {
16444 1248 : switch (opt) {
16445 0 : case 'p':
16446 0 : port_to_use = atoi(optarg);
16447 0 : break;
16448 0 : case 's':
16449 0 : seed = atoi(optarg);
16450 0 : break;
16451 0 : case 'W':
16452 0 : fstrcpy(workgroup,optarg);
16453 0 : break;
16454 33 : case 'm':
16455 33 : lpcfg_set_cmdline(lp_ctx, "client max protocol", optarg);
16456 33 : break;
16457 0 : case 'N':
16458 0 : torture_nprocs = atoi(optarg);
16459 0 : break;
16460 0 : case 'o':
16461 0 : torture_numops = atoi(optarg);
16462 0 : break;
16463 0 : case 'd':
16464 0 : lpcfg_set_cmdline(lp_ctx, "log level", optarg);
16465 0 : break;
16466 0 : case 'O':
16467 0 : sockops = optarg;
16468 0 : break;
16469 0 : case 'L':
16470 0 : use_oplocks = True;
16471 0 : break;
16472 469 : case 'l':
16473 469 : local_path = optarg;
16474 469 : break;
16475 0 : case 'A':
16476 0 : torture_showall = True;
16477 0 : break;
16478 0 : case 'n':
16479 0 : fstrcpy(myname, optarg);
16480 0 : break;
16481 0 : case 'c':
16482 0 : client_txt = optarg;
16483 0 : break;
16484 182 : case 'e':
16485 182 : do_encrypt = true;
16486 182 : break;
16487 0 : case 'k':
16488 : #ifdef HAVE_KRB5
16489 0 : use_kerberos = True;
16490 : #else
16491 : d_printf("No kerberos support compiled in\n");
16492 : exit(1);
16493 : #endif
16494 0 : break;
16495 552 : case 'U':
16496 552 : gotuser = 1;
16497 552 : fstrcpy(username,optarg);
16498 552 : p = strchr_m(username,'%');
16499 552 : if (p) {
16500 552 : *p = 0;
16501 552 : fstrcpy(password, p+1);
16502 552 : gotpass = 1;
16503 : }
16504 507 : break;
16505 0 : case 'b':
16506 0 : fstrcpy(multishare_conn_fname, optarg);
16507 0 : use_multishare_conn = True;
16508 0 : break;
16509 0 : case 'B':
16510 0 : torture_blocksize = atoi(optarg);
16511 0 : break;
16512 4 : case 'f':
16513 4 : test_filename = SMB_STRDUP(optarg);
16514 4 : break;
16515 8 : case 'T':
16516 8 : lpcfg_set_option(lp_ctx, optarg);
16517 8 : break;
16518 0 : default:
16519 0 : printf("Unknown option %c (%d)\n", (char)opt, opt);
16520 0 : usage();
16521 : }
16522 : }
16523 :
16524 552 : d_printf("using seed %d\n", seed);
16525 :
16526 552 : srandom(seed);
16527 :
16528 552 : if(use_kerberos && !gotuser) gotpass = True;
16529 :
16530 552 : while (!gotpass) {
16531 0 : char pwd[256] = {0};
16532 0 : int rc;
16533 :
16534 0 : rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
16535 0 : if (rc == 0) {
16536 0 : fstrcpy(password, pwd);
16537 0 : gotpass = 1;
16538 : }
16539 : }
16540 :
16541 552 : printf("host=%s share=%s user=%s myname=%s\n",
16542 : host, share, username, myname);
16543 :
16544 552 : torture_creds = cli_session_creds_init(frame,
16545 : username,
16546 : workgroup,
16547 : NULL, /* realm */
16548 : password,
16549 : use_kerberos,
16550 : false, /* fallback_after_kerberos */
16551 : false, /* use_ccache */
16552 : false); /* password_is_nt_hash */
16553 552 : if (torture_creds == NULL) {
16554 0 : d_printf("cli_session_creds_init() failed.\n");
16555 0 : exit(1);
16556 : }
16557 :
16558 552 : if (argc == optind) {
16559 0 : correct = run_test("ALL");
16560 : } else {
16561 1108 : for (i=optind;i<argc;i++) {
16562 552 : if (!run_test(argv[i])) {
16563 16 : correct = False;
16564 : }
16565 : }
16566 : }
16567 :
16568 556 : TALLOC_FREE(frame);
16569 :
16570 556 : if (correct) {
16571 491 : return(0);
16572 : } else {
16573 16 : return(1);
16574 : }
16575 : }
|