Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : SMB torture tester
4 : Copyright (C) Andrew Tridgell 1997-1998
5 : Copyright (C) Jeremy Allison 2009
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "includes.h"
22 : #include "system/shmem.h"
23 : #include "libsmb/namequery.h"
24 : #include "wbc_async.h"
25 : #include "torture/proto.h"
26 : #include "libcli/security/security.h"
27 : #include "tldap.h"
28 : #include "tldap_util.h"
29 : #include "tldap_gensec_bind.h"
30 : #include "../librpc/gen_ndr/svcctl.h"
31 : #include "../lib/util/memcache.h"
32 : #include "nsswitch/winbind_client.h"
33 : #include "dbwrap/dbwrap.h"
34 : #include "dbwrap/dbwrap_open.h"
35 : #include "dbwrap/dbwrap_rbt.h"
36 : #include "async_smb.h"
37 : #include "libsmb/libsmb.h"
38 : #include "libsmb/clirap.h"
39 : #include "trans2.h"
40 : #include "libsmb/nmblib.h"
41 : #include "../lib/util/tevent_ntstatus.h"
42 : #include "util_tdb.h"
43 : #include "../libcli/smb/read_smb.h"
44 : #include "../libcli/smb/smbXcli_base.h"
45 : #include "lib/util/sys_rw_data.h"
46 : #include "lib/util/base64.h"
47 : #include "lib/util/time.h"
48 : #include "lib/gencache.h"
49 : #include "lib/util/sys_rw.h"
50 : #include "lib/util/asn1.h"
51 : #include "lib/util/util_file.h"
52 : #include "lib/param/param.h"
53 : #include "auth/gensec/gensec.h"
54 : #include "lib/util/string_wrappers.h"
55 : #include "source3/lib/substitute.h"
56 :
57 : #include <gnutls/gnutls.h>
58 : #include <gnutls/crypto.h>
59 :
60 : extern char *optarg;
61 : extern int optind;
62 :
63 : fstring host, workgroup, share, password, username, myname;
64 : struct cli_credentials *torture_creds;
65 : static const char *sockops="TCP_NODELAY";
66 : int torture_nprocs=1;
67 : static int port_to_use=0;
68 : int torture_numops=100;
69 : int torture_blocksize=1024*1024;
70 : static int procnum; /* records process count number when forking */
71 : static struct cli_state *current_cli;
72 : static fstring randomfname;
73 : static bool use_oplocks;
74 : static bool use_level_II_oplocks;
75 : static const char *client_txt = "client_oplocks.txt";
76 : static bool disable_spnego;
77 : static bool use_kerberos;
78 : static bool force_dos_errors;
79 : static fstring multishare_conn_fname;
80 : static bool use_multishare_conn = False;
81 : static bool do_encrypt;
82 : static const char *local_path = NULL;
83 : static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
84 : char *test_filename;
85 :
86 : bool torture_showall = False;
87 :
88 : static double create_procs(bool (*fn)(int), bool *result);
89 :
90 : /********************************************************************
91 : Ensure a connection is encrypted.
92 : ********************************************************************/
93 :
94 200 : static bool force_cli_encryption(struct cli_state *c,
95 : const char *sharename)
96 : {
97 0 : uint16_t major, minor;
98 0 : uint32_t caplow, caphigh;
99 0 : NTSTATUS status;
100 :
101 200 : if (!SERVER_HAS_UNIX_CIFS(c)) {
102 0 : d_printf("Encryption required and "
103 : "server that doesn't support "
104 : "UNIX extensions - failing connect\n");
105 0 : return false;
106 : }
107 :
108 200 : status = cli_unix_extensions_version(c, &major, &minor, &caplow,
109 : &caphigh);
110 200 : if (!NT_STATUS_IS_OK(status)) {
111 0 : d_printf("Encryption required and "
112 : "can't get UNIX CIFS extensions "
113 : "version from server: %s\n", nt_errstr(status));
114 0 : return false;
115 : }
116 :
117 200 : if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
118 0 : d_printf("Encryption required and "
119 : "share %s doesn't support "
120 : "encryption.\n", sharename);
121 0 : return false;
122 : }
123 :
124 200 : status = cli_smb1_setup_encryption(c, torture_creds);
125 200 : if (!NT_STATUS_IS_OK(status)) {
126 0 : d_printf("Encryption required and "
127 : "setup failed with error %s.\n",
128 : nt_errstr(status));
129 0 : return false;
130 : }
131 :
132 200 : return true;
133 : }
134 :
135 :
136 100 : static struct cli_state *open_nbt_connection(void)
137 : {
138 0 : struct cli_state *c;
139 0 : NTSTATUS status;
140 100 : int flags = 0;
141 :
142 100 : if (disable_spnego) {
143 0 : flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
144 : }
145 :
146 100 : if (use_oplocks) {
147 0 : flags |= CLI_FULL_CONNECTION_OPLOCKS;
148 : }
149 :
150 100 : if (use_level_II_oplocks) {
151 0 : flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
152 : }
153 :
154 100 : if (force_dos_errors) {
155 0 : flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
156 : }
157 :
158 100 : status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
159 : signing_state, flags, &c);
160 100 : if (!NT_STATUS_IS_OK(status)) {
161 0 : printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
162 0 : return NULL;
163 : }
164 :
165 100 : cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
166 :
167 100 : return c;
168 : }
169 :
170 : /****************************************************************************
171 : Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
172 : ****************************************************************************/
173 :
174 4 : static bool cli_bad_session_request(int fd,
175 : struct nmb_name *calling, struct nmb_name *called)
176 : {
177 0 : TALLOC_CTX *frame;
178 0 : uint8_t len_buf[4];
179 0 : struct iovec iov[3];
180 0 : ssize_t len;
181 0 : uint8_t *inbuf;
182 0 : int err;
183 4 : bool ret = false;
184 0 : uint8_t message_type;
185 0 : uint8_t error;
186 0 : struct tevent_context *ev;
187 0 : struct tevent_req *req;
188 :
189 4 : frame = talloc_stackframe();
190 :
191 4 : iov[0].iov_base = len_buf;
192 4 : iov[0].iov_len = sizeof(len_buf);
193 :
194 : /* put in the destination name */
195 :
196 4 : iov[1].iov_base = name_mangle(talloc_tos(), called->name,
197 4 : called->name_type);
198 4 : if (iov[1].iov_base == NULL) {
199 0 : goto fail;
200 : }
201 4 : iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
202 4 : talloc_get_size(iov[1].iov_base));
203 :
204 : /* and my name */
205 :
206 4 : iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
207 4 : calling->name_type);
208 4 : if (iov[2].iov_base == NULL) {
209 0 : goto fail;
210 : }
211 4 : iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
212 4 : talloc_get_size(iov[2].iov_base));
213 :
214 : /* Deliberately corrupt the name len (first byte) */
215 4 : *((uint8_t *)iov[2].iov_base) = 100;
216 :
217 : /* send a session request (RFC 1002) */
218 : /* setup the packet length
219 : * Remove four bytes from the length count, since the length
220 : * field in the NBT Session Service header counts the number
221 : * of bytes which follow. The cli_send_smb() function knows
222 : * about this and accounts for those four bytes.
223 : * CRH.
224 : */
225 :
226 4 : _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
227 4 : SCVAL(len_buf,0,0x81);
228 :
229 4 : len = write_data_iov(fd, iov, 3);
230 4 : if (len == -1) {
231 0 : goto fail;
232 : }
233 :
234 4 : ev = samba_tevent_context_init(frame);
235 4 : if (ev == NULL) {
236 0 : goto fail;
237 : }
238 4 : req = read_smb_send(frame, ev, fd);
239 4 : if (req == NULL) {
240 0 : goto fail;
241 : }
242 4 : if (!tevent_req_poll(req, ev)) {
243 0 : goto fail;
244 : }
245 4 : len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
246 4 : if (len == -1) {
247 0 : errno = err;
248 0 : goto fail;
249 : }
250 4 : TALLOC_FREE(ev);
251 :
252 4 : message_type = CVAL(inbuf, 0);
253 4 : if (message_type != 0x83) {
254 0 : d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
255 : message_type);
256 0 : goto fail;
257 : }
258 :
259 4 : if (smb_len(inbuf) != 1) {
260 0 : d_fprintf(stderr, "Expected smb_len 1, got %d\n",
261 0 : (int)smb_len(inbuf));
262 0 : goto fail;
263 : }
264 :
265 4 : error = CVAL(inbuf, 4);
266 4 : if (error != 0x82) {
267 0 : d_fprintf(stderr, "Expected error 0x82, got %d\n",
268 : (int)error);
269 0 : goto fail;
270 : }
271 :
272 4 : ret = true;
273 4 : fail:
274 4 : TALLOC_FREE(frame);
275 4 : return ret;
276 : }
277 :
278 : /* Insert a NULL at the first separator of the given path and return a pointer
279 : * to the remainder of the string.
280 : */
281 : static char *
282 0 : terminate_path_at_separator(char * path)
283 : {
284 0 : char * p;
285 :
286 0 : if (!path) {
287 0 : return NULL;
288 : }
289 :
290 0 : if ((p = strchr_m(path, '/'))) {
291 0 : *p = '\0';
292 0 : return p + 1;
293 : }
294 :
295 0 : if ((p = strchr_m(path, '\\'))) {
296 0 : *p = '\0';
297 0 : return p + 1;
298 : }
299 :
300 : /* No separator. */
301 0 : return NULL;
302 : }
303 :
304 : /*
305 : parse a //server/share type UNC name
306 : */
307 0 : bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
308 : char **hostname, char **sharename)
309 : {
310 0 : char *p;
311 :
312 0 : *hostname = *sharename = NULL;
313 :
314 0 : if (strncmp(unc_name, "\\\\", 2) &&
315 0 : strncmp(unc_name, "//", 2)) {
316 0 : return False;
317 : }
318 :
319 0 : *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
320 0 : p = terminate_path_at_separator(*hostname);
321 :
322 0 : if (p && *p) {
323 0 : *sharename = talloc_strdup(mem_ctx, p);
324 0 : terminate_path_at_separator(*sharename);
325 : }
326 :
327 0 : if (*hostname && *sharename) {
328 0 : return True;
329 : }
330 :
331 0 : TALLOC_FREE(*hostname);
332 0 : TALLOC_FREE(*sharename);
333 0 : return False;
334 : }
335 :
336 497 : static bool torture_open_connection_share(struct cli_state **c,
337 : const char *hostname,
338 : const char *sharename,
339 : int flags)
340 : {
341 0 : NTSTATUS status;
342 :
343 497 : status = cli_full_connection_creds(c,
344 : myname,
345 : hostname,
346 : NULL, /* dest_ss */
347 : port_to_use,
348 : sharename,
349 : "?????",
350 : torture_creds,
351 : flags);
352 497 : if (!NT_STATUS_IS_OK(status)) {
353 2 : printf("failed to open share connection: //%s/%s port:%d - %s\n",
354 : hostname, sharename, port_to_use, nt_errstr(status));
355 2 : return False;
356 : }
357 :
358 495 : cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
359 :
360 495 : if (do_encrypt) {
361 198 : return force_cli_encryption(*c,
362 : sharename);
363 : }
364 297 : return True;
365 : }
366 :
367 497 : bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
368 : {
369 497 : char **unc_list = NULL;
370 497 : int num_unc_names = 0;
371 0 : bool result;
372 :
373 497 : if (use_multishare_conn==True) {
374 0 : char *h, *s;
375 0 : unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
376 0 : if (!unc_list || num_unc_names <= 0) {
377 0 : printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
378 0 : exit(1);
379 : }
380 :
381 0 : if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
382 : NULL, &h, &s)) {
383 0 : printf("Failed to parse UNC name %s\n",
384 0 : unc_list[conn_index % num_unc_names]);
385 0 : TALLOC_FREE(unc_list);
386 0 : exit(1);
387 : }
388 :
389 0 : result = torture_open_connection_share(c, h, s, flags);
390 :
391 : /* h, s were copied earlier */
392 0 : TALLOC_FREE(unc_list);
393 0 : return result;
394 : }
395 :
396 497 : return torture_open_connection_share(c, host, share, flags);
397 : }
398 :
399 485 : bool torture_open_connection(struct cli_state **c, int conn_index)
400 : {
401 485 : int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
402 :
403 485 : if (use_oplocks) {
404 8 : flags |= CLI_FULL_CONNECTION_OPLOCKS;
405 : }
406 485 : if (use_level_II_oplocks) {
407 8 : flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
408 : }
409 :
410 485 : return torture_open_connection_flags(c, conn_index, flags);
411 : }
412 :
413 90 : bool torture_init_connection(struct cli_state **pcli)
414 : {
415 0 : struct cli_state *cli;
416 :
417 90 : cli = open_nbt_connection();
418 90 : if (cli == NULL) {
419 0 : return false;
420 : }
421 :
422 90 : *pcli = cli;
423 90 : return true;
424 : }
425 :
426 5 : bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
427 : {
428 5 : uint16_t old_vuid = cli_state_get_uid(cli);
429 0 : NTSTATUS status;
430 0 : bool ret;
431 :
432 5 : cli_state_set_uid(cli, 0);
433 5 : status = cli_session_setup_creds(cli, torture_creds);
434 5 : ret = NT_STATUS_IS_OK(status);
435 5 : *new_vuid = cli_state_get_uid(cli);
436 5 : cli_state_set_uid(cli, old_vuid);
437 5 : return ret;
438 : }
439 :
440 :
441 421 : bool torture_close_connection(struct cli_state *c)
442 : {
443 421 : bool ret = True;
444 0 : NTSTATUS status;
445 :
446 421 : status = cli_tdis(c);
447 421 : if (!NT_STATUS_IS_OK(status)) {
448 5 : printf("tdis failed (%s)\n", nt_errstr(status));
449 5 : ret = False;
450 : }
451 :
452 421 : cli_shutdown(c);
453 :
454 421 : return ret;
455 : }
456 :
457 48 : void torture_conn_set_sockopt(struct cli_state *cli)
458 : {
459 48 : smbXcli_conn_set_sockopt(cli->conn, sockops);
460 48 : }
461 :
462 58 : static NTSTATUS torture_delete_fn(struct file_info *finfo,
463 : const char *pattern,
464 : void *state)
465 : {
466 0 : NTSTATUS status;
467 58 : char *filename = NULL;
468 58 : char *dirname = NULL;
469 58 : char *p = NULL;
470 58 : TALLOC_CTX *frame = talloc_stackframe();
471 58 : struct cli_state *cli = (struct cli_state *)state;
472 :
473 58 : if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
474 36 : TALLOC_FREE(frame);
475 36 : return NT_STATUS_OK;
476 : }
477 :
478 22 : dirname = talloc_strdup(frame, pattern);
479 22 : if (dirname == NULL) {
480 0 : TALLOC_FREE(frame);
481 0 : return NT_STATUS_NO_MEMORY;
482 : }
483 22 : p = strrchr_m(dirname, '\\');
484 22 : if (p != NULL) {
485 : /* Remove the terminating '\' */
486 22 : *p = '\0';
487 : }
488 22 : if (dirname[0] != '\0') {
489 22 : filename = talloc_asprintf(frame,
490 : "%s\\%s",
491 : dirname,
492 : finfo->name);
493 : } else {
494 0 : filename = talloc_asprintf(frame,
495 : "%s",
496 : finfo->name);
497 : }
498 22 : if (filename == NULL) {
499 0 : TALLOC_FREE(frame);
500 0 : return NT_STATUS_NO_MEMORY;
501 : }
502 22 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
503 5 : char *subdirname = talloc_asprintf(frame,
504 : "%s\\*",
505 : filename);
506 5 : if (subdirname == NULL) {
507 0 : TALLOC_FREE(frame);
508 0 : return NT_STATUS_NO_MEMORY;
509 : }
510 5 : status = cli_list(cli,
511 : subdirname,
512 : FILE_ATTRIBUTE_DIRECTORY |
513 : FILE_ATTRIBUTE_HIDDEN |
514 : FILE_ATTRIBUTE_SYSTEM,
515 : torture_delete_fn,
516 : cli);
517 5 : if (!NT_STATUS_IS_OK(status)) {
518 0 : printf("torture_delete_fn: cli_list "
519 : "of %s failed (%s)\n",
520 : subdirname,
521 : nt_errstr(status));
522 0 : TALLOC_FREE(frame);
523 0 : return status;
524 : }
525 5 : status = cli_rmdir(cli, filename);
526 : } else {
527 17 : status = cli_unlink(cli,
528 : filename,
529 : FILE_ATTRIBUTE_SYSTEM |
530 : FILE_ATTRIBUTE_HIDDEN);
531 : }
532 22 : if (!NT_STATUS_IS_OK(status)) {
533 0 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
534 0 : printf("torture_delete_fn: cli_rmdir"
535 : " of %s failed (%s)\n",
536 : filename,
537 : nt_errstr(status));
538 : } else {
539 0 : printf("torture_delete_fn: cli_unlink"
540 : " of %s failed (%s)\n",
541 : filename,
542 : nt_errstr(status));
543 : }
544 : }
545 22 : TALLOC_FREE(frame);
546 22 : return status;
547 : }
548 :
549 30 : void torture_deltree(struct cli_state *cli, const char *dname)
550 : {
551 30 : char *mask = NULL;
552 0 : NTSTATUS status;
553 :
554 : /* It might be a file */
555 30 : (void)cli_unlink(cli,
556 : dname,
557 : FILE_ATTRIBUTE_SYSTEM |
558 : FILE_ATTRIBUTE_HIDDEN);
559 :
560 30 : mask = talloc_asprintf(cli,
561 : "%s\\*",
562 : dname);
563 30 : if (mask == NULL) {
564 0 : printf("torture_deltree: talloc_asprintf failed\n");
565 0 : return;
566 : }
567 :
568 30 : status = cli_list(cli,
569 : mask,
570 : FILE_ATTRIBUTE_DIRECTORY |
571 : FILE_ATTRIBUTE_HIDDEN|
572 : FILE_ATTRIBUTE_SYSTEM,
573 : torture_delete_fn,
574 : cli);
575 30 : if (!NT_STATUS_IS_OK(status)) {
576 17 : printf("torture_deltree: cli_list of %s failed (%s)\n",
577 : mask,
578 : nt_errstr(status));
579 : }
580 30 : TALLOC_FREE(mask);
581 30 : status = cli_rmdir(cli, dname);
582 30 : if (!NT_STATUS_IS_OK(status)) {
583 17 : printf("torture_deltree: cli_rmdir of %s failed (%s)\n",
584 : dname,
585 : nt_errstr(status));
586 : }
587 : }
588 :
589 : /* check if the server produced the expected dos or nt error code */
590 53 : static bool check_both_error(int line, NTSTATUS status,
591 : uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
592 : {
593 53 : if (NT_STATUS_IS_DOS(status)) {
594 0 : uint8_t cclass;
595 0 : uint32_t num;
596 :
597 : /* Check DOS error */
598 0 : cclass = NT_STATUS_DOS_CLASS(status);
599 0 : num = NT_STATUS_DOS_CODE(status);
600 :
601 0 : if (eclass != cclass || ecode != num) {
602 0 : printf("unexpected error code class=%d code=%d\n",
603 : (int)cclass, (int)num);
604 0 : printf(" expected %d/%d %s (line=%d)\n",
605 : (int)eclass, (int)ecode, nt_errstr(nterr), line);
606 0 : return false;
607 : }
608 : } else {
609 : /* Check NT error */
610 53 : if (!NT_STATUS_EQUAL(nterr, status)) {
611 0 : printf("unexpected error code %s\n",
612 : nt_errstr(status));
613 0 : printf(" expected %s (line=%d)\n",
614 : nt_errstr(nterr), line);
615 0 : return false;
616 : }
617 : }
618 :
619 53 : return true;
620 : }
621 :
622 :
623 : /* check if the server produced the expected error code */
624 38 : static bool check_error(int line, NTSTATUS status,
625 : uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
626 : {
627 38 : if (NT_STATUS_IS_DOS(status)) {
628 0 : uint8_t cclass;
629 0 : uint32_t num;
630 :
631 : /* Check DOS error */
632 :
633 0 : cclass = NT_STATUS_DOS_CLASS(status);
634 0 : num = NT_STATUS_DOS_CODE(status);
635 :
636 0 : if (eclass != cclass || ecode != num) {
637 0 : printf("unexpected error code class=%d code=%d\n",
638 : (int)cclass, (int)num);
639 0 : printf(" expected %d/%d %s (line=%d)\n",
640 : (int)eclass, (int)ecode, nt_errstr(nterr),
641 : line);
642 0 : return False;
643 : }
644 :
645 : } else {
646 : /* Check NT error */
647 :
648 38 : if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
649 1 : printf("unexpected error code %s\n",
650 : nt_errstr(status));
651 1 : printf(" expected %s (line=%d)\n", nt_errstr(nterr),
652 : line);
653 1 : return False;
654 : }
655 : }
656 :
657 37 : return True;
658 : }
659 :
660 9 : NTSTATUS cli_qpathinfo1(struct cli_state *cli,
661 : const char *fname,
662 : time_t *change_time,
663 : time_t *access_time,
664 : time_t *write_time,
665 : off_t *size,
666 : uint32_t *pattr)
667 : {
668 9 : int timezone = smb1cli_conn_server_time_zone(cli->conn);
669 9 : time_t (*date_fn)(const void *buf, int serverzone) = NULL;
670 9 : uint8_t *rdata = NULL;
671 0 : uint32_t num_rdata;
672 0 : NTSTATUS status;
673 :
674 9 : status = cli_qpathinfo(talloc_tos(),
675 : cli,
676 : fname,
677 : SMB_INFO_STANDARD,
678 : 22,
679 : CLI_BUFFER_SIZE,
680 : &rdata,
681 : &num_rdata);
682 9 : if (!NT_STATUS_IS_OK(status)) {
683 4 : return status;
684 : }
685 5 : if (cli->win95) {
686 0 : date_fn = make_unix_date;
687 : } else {
688 5 : date_fn = make_unix_date2;
689 : }
690 :
691 5 : if (change_time) {
692 5 : *change_time = date_fn(rdata + 0, timezone);
693 : }
694 5 : if (access_time) {
695 5 : *access_time = date_fn(rdata + 4, timezone);
696 : }
697 5 : if (write_time) {
698 5 : *write_time = date_fn(rdata + 8, timezone);
699 : }
700 5 : if (size) {
701 5 : *size = PULL_LE_U32(rdata, 12);
702 : }
703 5 : if (pattr) {
704 0 : *pattr = PULL_LE_U16(rdata, l1_attrFile);
705 : }
706 5 : return NT_STATUS_OK;
707 : }
708 :
709 0 : static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
710 : {
711 0 : NTSTATUS status;
712 :
713 0 : status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
714 :
715 0 : while (!NT_STATUS_IS_OK(status)) {
716 0 : if (!check_both_error(__LINE__, status, ERRDOS,
717 0 : ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
718 0 : return false;
719 : }
720 :
721 0 : status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
722 : }
723 :
724 0 : return true;
725 : }
726 :
727 :
728 0 : static bool rw_torture(struct cli_state *c)
729 : {
730 0 : const char *lockfname = "\\torture.lck";
731 0 : fstring fname;
732 0 : uint16_t fnum;
733 0 : uint16_t fnum2;
734 0 : pid_t pid2, pid = getpid();
735 0 : int i, j;
736 0 : char buf[1024];
737 0 : bool correct = True;
738 0 : size_t nread = 0;
739 0 : NTSTATUS status;
740 :
741 0 : memset(buf, '\0', sizeof(buf));
742 :
743 0 : status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
744 : DENY_NONE, &fnum2);
745 0 : if (!NT_STATUS_IS_OK(status)) {
746 0 : status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
747 : }
748 0 : if (!NT_STATUS_IS_OK(status)) {
749 0 : printf("open of %s failed (%s)\n",
750 : lockfname, nt_errstr(status));
751 0 : return False;
752 : }
753 :
754 0 : for (i=0;i<torture_numops;i++) {
755 0 : unsigned n = (unsigned)sys_random()%10;
756 :
757 0 : if (i % 10 == 0) {
758 0 : printf("%d\r", i); fflush(stdout);
759 : }
760 0 : slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
761 :
762 0 : if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
763 0 : return False;
764 : }
765 :
766 0 : status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
767 : DENY_ALL, &fnum);
768 0 : if (!NT_STATUS_IS_OK(status)) {
769 0 : printf("open failed (%s)\n", nt_errstr(status));
770 0 : correct = False;
771 0 : break;
772 : }
773 :
774 0 : status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
775 : sizeof(pid), NULL);
776 0 : if (!NT_STATUS_IS_OK(status)) {
777 0 : printf("write failed (%s)\n", nt_errstr(status));
778 0 : correct = False;
779 : }
780 :
781 0 : for (j=0;j<50;j++) {
782 0 : status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
783 0 : sizeof(pid)+(j*sizeof(buf)),
784 : sizeof(buf), NULL);
785 0 : if (!NT_STATUS_IS_OK(status)) {
786 0 : printf("write failed (%s)\n",
787 : nt_errstr(status));
788 0 : correct = False;
789 : }
790 : }
791 :
792 0 : pid2 = 0;
793 :
794 0 : status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
795 : &nread);
796 0 : if (!NT_STATUS_IS_OK(status)) {
797 0 : printf("read failed (%s)\n", nt_errstr(status));
798 0 : correct = false;
799 0 : } else if (nread != sizeof(pid)) {
800 0 : printf("read/write compare failed: "
801 : "recv %ld req %ld\n", (unsigned long)nread,
802 : (unsigned long)sizeof(pid));
803 0 : correct = false;
804 : }
805 :
806 0 : if (pid2 != pid) {
807 0 : printf("data corruption!\n");
808 0 : correct = False;
809 : }
810 :
811 0 : status = cli_close(c, fnum);
812 0 : if (!NT_STATUS_IS_OK(status)) {
813 0 : printf("close failed (%s)\n", nt_errstr(status));
814 0 : correct = False;
815 : }
816 :
817 0 : status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
818 0 : if (!NT_STATUS_IS_OK(status)) {
819 0 : printf("unlink failed (%s)\n", nt_errstr(status));
820 0 : correct = False;
821 : }
822 :
823 0 : status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
824 0 : if (!NT_STATUS_IS_OK(status)) {
825 0 : printf("unlock failed (%s)\n", nt_errstr(status));
826 0 : correct = False;
827 : }
828 : }
829 :
830 0 : cli_close(c, fnum2);
831 0 : cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
832 :
833 0 : printf("%d\n", i);
834 :
835 0 : return correct;
836 : }
837 :
838 0 : static bool run_torture(int dummy)
839 : {
840 0 : struct cli_state *cli;
841 0 : bool ret;
842 :
843 0 : cli = current_cli;
844 :
845 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
846 :
847 0 : ret = rw_torture(cli);
848 :
849 0 : if (!torture_close_connection(cli)) {
850 0 : ret = False;
851 : }
852 :
853 0 : return ret;
854 : }
855 :
856 0 : static bool rw_torture3(struct cli_state *c, char *lockfname)
857 : {
858 0 : uint16_t fnum = (uint16_t)-1;
859 0 : unsigned int i = 0;
860 0 : char buf[131072];
861 0 : char buf_rd[131072];
862 0 : unsigned count;
863 0 : unsigned countprev = 0;
864 0 : size_t sent = 0;
865 0 : bool correct = True;
866 0 : NTSTATUS status = NT_STATUS_OK;
867 :
868 0 : srandom(1);
869 0 : for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
870 : {
871 0 : SIVAL(buf, i, sys_random());
872 : }
873 :
874 0 : if (procnum == 0)
875 : {
876 0 : status = cli_unlink(
877 : c, lockfname,
878 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
879 0 : if (!NT_STATUS_IS_OK(status)) {
880 0 : printf("unlink failed (%s) (normal, this file should "
881 : "not exist)\n", nt_errstr(status));
882 : }
883 :
884 0 : status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
885 : DENY_NONE, &fnum);
886 0 : if (!NT_STATUS_IS_OK(status)) {
887 0 : printf("first open read/write of %s failed (%s)\n",
888 : lockfname, nt_errstr(status));
889 0 : return False;
890 : }
891 : }
892 : else
893 : {
894 0 : for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
895 : {
896 0 : status = cli_openx(c, lockfname, O_RDONLY,
897 : DENY_NONE, &fnum);
898 0 : if (NT_STATUS_IS_OK(status)) {
899 0 : break;
900 : }
901 0 : smb_msleep(10);
902 : }
903 0 : if (!NT_STATUS_IS_OK(status)) {
904 0 : printf("second open read-only of %s failed (%s)\n",
905 : lockfname, nt_errstr(status));
906 0 : return False;
907 : }
908 : }
909 :
910 0 : i = 0;
911 0 : for (count = 0; count < sizeof(buf); count += sent)
912 : {
913 0 : if (count >= countprev) {
914 0 : printf("%d %8d\r", i, count);
915 0 : fflush(stdout);
916 0 : i++;
917 0 : countprev += (sizeof(buf) / 20);
918 : }
919 :
920 0 : if (procnum == 0)
921 : {
922 0 : sent = ((unsigned)sys_random()%(20))+ 1;
923 0 : if (sent > sizeof(buf) - count)
924 : {
925 0 : sent = sizeof(buf) - count;
926 : }
927 :
928 0 : status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
929 : count, sent, NULL);
930 0 : if (!NT_STATUS_IS_OK(status)) {
931 0 : printf("write failed (%s)\n",
932 : nt_errstr(status));
933 0 : correct = False;
934 : }
935 : }
936 : else
937 : {
938 0 : status = cli_read(c, fnum, buf_rd+count, count,
939 : sizeof(buf)-count, &sent);
940 0 : if(!NT_STATUS_IS_OK(status)) {
941 0 : printf("read failed offset:%d size:%ld (%s)\n",
942 : count, (unsigned long)sizeof(buf)-count,
943 : nt_errstr(status));
944 0 : correct = False;
945 0 : sent = 0;
946 0 : } else if (sent > 0) {
947 0 : if (memcmp(buf_rd+count, buf+count, sent) != 0)
948 : {
949 0 : printf("read/write compare failed\n");
950 0 : printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
951 0 : correct = False;
952 0 : break;
953 : }
954 : }
955 : }
956 :
957 : }
958 :
959 0 : status = cli_close(c, fnum);
960 0 : if (!NT_STATUS_IS_OK(status)) {
961 0 : printf("close failed (%s)\n", nt_errstr(status));
962 0 : correct = False;
963 : }
964 :
965 0 : return correct;
966 : }
967 :
968 18 : static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
969 : {
970 18 : const char *lockfname = "\\torture2.lck";
971 0 : uint16_t fnum1;
972 0 : uint16_t fnum2;
973 0 : int i;
974 0 : char buf[131072];
975 0 : char buf_rd[131072];
976 18 : bool correct = True;
977 0 : size_t bytes_read;
978 0 : NTSTATUS status;
979 :
980 18 : status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
981 18 : if (!NT_STATUS_IS_OK(status)) {
982 18 : printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
983 : }
984 :
985 18 : status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
986 : DENY_NONE, &fnum1);
987 18 : if (!NT_STATUS_IS_OK(status)) {
988 0 : printf("first open read/write of %s failed (%s)\n",
989 : lockfname, nt_errstr(status));
990 0 : return False;
991 : }
992 :
993 18 : status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
994 18 : if (!NT_STATUS_IS_OK(status)) {
995 0 : printf("second open read-only of %s failed (%s)\n",
996 : lockfname, nt_errstr(status));
997 0 : cli_close(c1, fnum1);
998 0 : return False;
999 : }
1000 :
1001 1818 : for (i = 0; i < torture_numops; i++)
1002 : {
1003 1800 : size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
1004 1800 : if (i % 10 == 0) {
1005 180 : printf("%d\r", i); fflush(stdout);
1006 : }
1007 :
1008 1800 : generate_random_buffer((unsigned char *)buf, buf_size);
1009 :
1010 1800 : status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
1011 : buf_size, NULL);
1012 1800 : if (!NT_STATUS_IS_OK(status)) {
1013 0 : printf("write failed (%s)\n", nt_errstr(status));
1014 0 : correct = False;
1015 0 : break;
1016 : }
1017 :
1018 1800 : status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
1019 1800 : if(!NT_STATUS_IS_OK(status)) {
1020 0 : printf("read failed (%s)\n", nt_errstr(status));
1021 0 : correct = false;
1022 0 : break;
1023 1800 : } else if (bytes_read != buf_size) {
1024 0 : printf("read failed\n");
1025 0 : printf("read %ld, expected %ld\n",
1026 : (unsigned long)bytes_read,
1027 : (unsigned long)buf_size);
1028 0 : correct = False;
1029 0 : break;
1030 : }
1031 :
1032 1800 : if (memcmp(buf_rd, buf, buf_size) != 0)
1033 : {
1034 0 : printf("read/write compare failed\n");
1035 0 : correct = False;
1036 0 : break;
1037 : }
1038 : }
1039 :
1040 18 : status = cli_close(c2, fnum2);
1041 18 : if (!NT_STATUS_IS_OK(status)) {
1042 0 : printf("close failed (%s)\n", nt_errstr(status));
1043 0 : correct = False;
1044 : }
1045 :
1046 18 : status = cli_close(c1, fnum1);
1047 18 : if (!NT_STATUS_IS_OK(status)) {
1048 0 : printf("close failed (%s)\n", nt_errstr(status));
1049 0 : correct = False;
1050 : }
1051 :
1052 18 : status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1053 18 : if (!NT_STATUS_IS_OK(status)) {
1054 0 : printf("unlink failed (%s)\n", nt_errstr(status));
1055 0 : correct = False;
1056 : }
1057 :
1058 18 : return correct;
1059 : }
1060 :
1061 9 : static bool run_readwritetest(int dummy)
1062 : {
1063 0 : struct cli_state *cli1, *cli2;
1064 9 : bool test1, test2 = False;
1065 :
1066 9 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1067 0 : return False;
1068 : }
1069 9 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
1070 9 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
1071 :
1072 9 : printf("starting readwritetest\n");
1073 :
1074 9 : test1 = rw_torture2(cli1, cli2);
1075 9 : printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
1076 :
1077 9 : if (test1) {
1078 9 : test2 = rw_torture2(cli1, cli1);
1079 9 : printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
1080 : }
1081 :
1082 9 : if (!torture_close_connection(cli1)) {
1083 0 : test1 = False;
1084 : }
1085 :
1086 9 : if (!torture_close_connection(cli2)) {
1087 0 : test2 = False;
1088 : }
1089 :
1090 9 : return (test1 && test2);
1091 : }
1092 :
1093 0 : static bool run_readwritemulti(int dummy)
1094 : {
1095 0 : struct cli_state *cli;
1096 0 : bool test;
1097 :
1098 0 : cli = current_cli;
1099 :
1100 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1101 :
1102 0 : printf("run_readwritemulti: fname %s\n", randomfname);
1103 0 : test = rw_torture3(cli, randomfname);
1104 :
1105 0 : if (!torture_close_connection(cli)) {
1106 0 : test = False;
1107 : }
1108 :
1109 0 : return test;
1110 : }
1111 :
1112 14 : static bool run_readwritelarge_internal(void)
1113 : {
1114 0 : static struct cli_state *cli1;
1115 0 : uint16_t fnum1;
1116 14 : const char *lockfname = "\\large.dat";
1117 0 : off_t fsize;
1118 0 : char buf[126*1024];
1119 14 : bool correct = True;
1120 0 : NTSTATUS status;
1121 :
1122 14 : if (!torture_open_connection(&cli1, 0)) {
1123 0 : return False;
1124 : }
1125 14 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
1126 14 : memset(buf,'\0',sizeof(buf));
1127 :
1128 14 : printf("starting readwritelarge_internal\n");
1129 :
1130 14 : cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1131 :
1132 14 : status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1133 : DENY_NONE, &fnum1);
1134 14 : if (!NT_STATUS_IS_OK(status)) {
1135 0 : printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1136 0 : return False;
1137 : }
1138 :
1139 14 : cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1140 :
1141 14 : status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1142 : NULL, NULL, NULL);
1143 14 : if (!NT_STATUS_IS_OK(status)) {
1144 0 : printf("qfileinfo failed (%s)\n", nt_errstr(status));
1145 0 : correct = False;
1146 : }
1147 :
1148 14 : if (fsize == sizeof(buf))
1149 14 : printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1150 : (unsigned long)fsize);
1151 : else {
1152 0 : printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1153 : (unsigned long)fsize);
1154 0 : correct = False;
1155 : }
1156 :
1157 14 : status = cli_close(cli1, fnum1);
1158 14 : if (!NT_STATUS_IS_OK(status)) {
1159 0 : printf("close failed (%s)\n", nt_errstr(status));
1160 0 : correct = False;
1161 : }
1162 :
1163 14 : status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1164 14 : if (!NT_STATUS_IS_OK(status)) {
1165 0 : printf("unlink failed (%s)\n", nt_errstr(status));
1166 0 : correct = False;
1167 : }
1168 :
1169 14 : status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1170 : DENY_NONE, &fnum1);
1171 14 : if (!NT_STATUS_IS_OK(status)) {
1172 0 : printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1173 0 : return False;
1174 : }
1175 :
1176 14 : cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1177 :
1178 14 : status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1179 : NULL, NULL, NULL);
1180 14 : if (!NT_STATUS_IS_OK(status)) {
1181 0 : printf("qfileinfo failed (%s)\n", nt_errstr(status));
1182 0 : correct = False;
1183 : }
1184 :
1185 14 : if (fsize == sizeof(buf))
1186 14 : printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1187 : (unsigned long)fsize);
1188 : else {
1189 0 : printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1190 : (unsigned long)fsize);
1191 0 : correct = False;
1192 : }
1193 :
1194 14 : status = cli_close(cli1, fnum1);
1195 14 : if (!NT_STATUS_IS_OK(status)) {
1196 0 : printf("close failed (%s)\n", nt_errstr(status));
1197 0 : correct = False;
1198 : }
1199 :
1200 14 : if (!torture_close_connection(cli1)) {
1201 0 : correct = False;
1202 : }
1203 14 : return correct;
1204 : }
1205 :
1206 9 : static bool run_readwritelarge(int dummy)
1207 : {
1208 9 : return run_readwritelarge_internal();
1209 : }
1210 :
1211 5 : static bool run_readwritelarge_signtest(int dummy)
1212 : {
1213 0 : bool ret;
1214 5 : signing_state = SMB_SIGNING_REQUIRED;
1215 5 : ret = run_readwritelarge_internal();
1216 5 : signing_state = SMB_SIGNING_DEFAULT;
1217 5 : return ret;
1218 : }
1219 :
1220 : int line_count = 0;
1221 : int nbio_id;
1222 :
1223 : #define ival(s) strtol(s, NULL, 0)
1224 :
1225 : /* run a test that simulates an approximate netbench client load */
1226 0 : static bool run_netbench(int client)
1227 : {
1228 0 : struct cli_state *cli;
1229 0 : int i;
1230 0 : char line[1024];
1231 0 : char cname[20];
1232 0 : FILE *f;
1233 0 : const char *params[20];
1234 0 : bool correct = True;
1235 :
1236 0 : cli = current_cli;
1237 :
1238 0 : nbio_id = client;
1239 :
1240 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1241 :
1242 0 : nb_setup(cli);
1243 :
1244 0 : slprintf(cname,sizeof(cname)-1, "client%d", client);
1245 :
1246 0 : f = fopen(client_txt, "r");
1247 :
1248 0 : if (!f) {
1249 0 : perror(client_txt);
1250 0 : return False;
1251 : }
1252 :
1253 0 : while (fgets(line, sizeof(line)-1, f)) {
1254 0 : char *saveptr;
1255 0 : line_count++;
1256 :
1257 0 : line[strlen(line)-1] = 0;
1258 :
1259 : /* printf("[%d] %s\n", line_count, line); */
1260 :
1261 0 : all_string_sub(line,"client1", cname, sizeof(line));
1262 :
1263 : /* parse the command parameters */
1264 0 : params[0] = strtok_r(line, " ", &saveptr);
1265 0 : i = 0;
1266 0 : while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1267 :
1268 0 : params[i] = "";
1269 :
1270 0 : if (i < 2) continue;
1271 :
1272 0 : if (!strncmp(params[0],"SMB", 3)) {
1273 0 : printf("ERROR: You are using a dbench 1 load file\n");
1274 0 : exit(1);
1275 : }
1276 :
1277 0 : if (!strcmp(params[0],"NTCreateX")) {
1278 0 : nb_createx(params[1], ival(params[2]), ival(params[3]),
1279 0 : ival(params[4]));
1280 0 : } else if (!strcmp(params[0],"Close")) {
1281 0 : nb_close(ival(params[1]));
1282 0 : } else if (!strcmp(params[0],"Rename")) {
1283 0 : nb_rename(params[1], params[2]);
1284 0 : } else if (!strcmp(params[0],"Unlink")) {
1285 0 : nb_unlink(params[1]);
1286 0 : } else if (!strcmp(params[0],"Deltree")) {
1287 0 : nb_deltree(params[1]);
1288 0 : } else if (!strcmp(params[0],"Rmdir")) {
1289 0 : nb_rmdir(params[1]);
1290 0 : } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1291 0 : nb_qpathinfo(params[1]);
1292 0 : } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1293 0 : nb_qfileinfo(ival(params[1]));
1294 0 : } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1295 0 : nb_qfsinfo(ival(params[1]));
1296 0 : } else if (!strcmp(params[0],"FIND_FIRST")) {
1297 0 : nb_findfirst(params[1]);
1298 0 : } else if (!strcmp(params[0],"WriteX")) {
1299 0 : nb_writex(ival(params[1]),
1300 0 : ival(params[2]), ival(params[3]), ival(params[4]));
1301 0 : } else if (!strcmp(params[0],"ReadX")) {
1302 0 : nb_readx(ival(params[1]),
1303 0 : ival(params[2]), ival(params[3]), ival(params[4]));
1304 0 : } else if (!strcmp(params[0],"Flush")) {
1305 0 : nb_flush(ival(params[1]));
1306 : } else {
1307 0 : printf("Unknown operation %s\n", params[0]);
1308 0 : exit(1);
1309 : }
1310 : }
1311 0 : fclose(f);
1312 :
1313 0 : nb_cleanup();
1314 :
1315 0 : if (!torture_close_connection(cli)) {
1316 0 : correct = False;
1317 : }
1318 :
1319 0 : return correct;
1320 : }
1321 :
1322 :
1323 : /* run a test that simulates an approximate netbench client load */
1324 0 : static bool run_nbench(int dummy)
1325 : {
1326 0 : double t;
1327 0 : bool correct = True;
1328 :
1329 0 : nbio_shmem(torture_nprocs);
1330 :
1331 0 : nbio_id = -1;
1332 :
1333 0 : signal(SIGALRM, nb_alarm);
1334 0 : alarm(1);
1335 0 : t = create_procs(run_netbench, &correct);
1336 0 : alarm(0);
1337 :
1338 0 : printf("\nThroughput %g MB/sec\n",
1339 0 : 1.0e-6 * nbio_total() / t);
1340 0 : return correct;
1341 : }
1342 :
1343 :
1344 : /*
1345 : This test checks for two things:
1346 :
1347 : 1) correct support for retaining locks over a close (ie. the server
1348 : must not use posix semantics)
1349 : 2) support for lock timeouts
1350 : */
1351 5 : static bool run_locktest1(int dummy)
1352 : {
1353 0 : struct cli_state *cli1, *cli2;
1354 5 : const char *fname = "\\lockt1.lck";
1355 0 : uint16_t fnum1, fnum2, fnum3;
1356 0 : time_t t1, t2;
1357 0 : unsigned lock_timeout;
1358 0 : NTSTATUS status;
1359 :
1360 5 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1361 0 : return False;
1362 : }
1363 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
1364 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
1365 :
1366 5 : printf("starting locktest1\n");
1367 :
1368 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1369 :
1370 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1371 : &fnum1);
1372 5 : if (!NT_STATUS_IS_OK(status)) {
1373 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1374 0 : return False;
1375 : }
1376 :
1377 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1378 5 : if (!NT_STATUS_IS_OK(status)) {
1379 0 : printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1380 0 : return False;
1381 : }
1382 :
1383 5 : status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1384 5 : if (!NT_STATUS_IS_OK(status)) {
1385 0 : printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1386 0 : return False;
1387 : }
1388 :
1389 5 : status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1390 5 : if (!NT_STATUS_IS_OK(status)) {
1391 0 : printf("lock1 failed (%s)\n", nt_errstr(status));
1392 0 : return false;
1393 : }
1394 :
1395 5 : status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1396 5 : if (NT_STATUS_IS_OK(status)) {
1397 0 : printf("lock2 succeeded! This is a locking bug\n");
1398 0 : return false;
1399 : } else {
1400 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1401 5 : NT_STATUS_LOCK_NOT_GRANTED)) {
1402 0 : return false;
1403 : }
1404 : }
1405 :
1406 5 : lock_timeout = (1 + (random() % 20));
1407 5 : printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1408 5 : t1 = time(NULL);
1409 5 : status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1410 5 : if (NT_STATUS_IS_OK(status)) {
1411 0 : printf("lock3 succeeded! This is a locking bug\n");
1412 0 : return false;
1413 : } else {
1414 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1415 5 : NT_STATUS_FILE_LOCK_CONFLICT)) {
1416 0 : return false;
1417 : }
1418 : }
1419 5 : t2 = time(NULL);
1420 :
1421 5 : if (ABS(t2 - t1) < lock_timeout-1) {
1422 0 : printf("error: This server appears not to support timed lock requests\n");
1423 : }
1424 :
1425 5 : printf("server slept for %u seconds for a %u second timeout\n",
1426 : (unsigned int)(t2-t1), lock_timeout);
1427 :
1428 5 : status = cli_close(cli1, fnum2);
1429 5 : if (!NT_STATUS_IS_OK(status)) {
1430 0 : printf("close1 failed (%s)\n", nt_errstr(status));
1431 0 : return False;
1432 : }
1433 :
1434 5 : status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1435 5 : if (NT_STATUS_IS_OK(status)) {
1436 0 : printf("lock4 succeeded! This is a locking bug\n");
1437 0 : return false;
1438 : } else {
1439 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1440 5 : NT_STATUS_FILE_LOCK_CONFLICT)) {
1441 0 : return false;
1442 : }
1443 : }
1444 :
1445 5 : status = cli_close(cli1, fnum1);
1446 5 : if (!NT_STATUS_IS_OK(status)) {
1447 0 : printf("close2 failed (%s)\n", nt_errstr(status));
1448 0 : return False;
1449 : }
1450 :
1451 5 : status = cli_close(cli2, fnum3);
1452 5 : if (!NT_STATUS_IS_OK(status)) {
1453 0 : printf("close3 failed (%s)\n", nt_errstr(status));
1454 0 : return False;
1455 : }
1456 :
1457 5 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1458 5 : if (!NT_STATUS_IS_OK(status)) {
1459 0 : printf("unlink failed (%s)\n", nt_errstr(status));
1460 0 : return False;
1461 : }
1462 :
1463 :
1464 5 : if (!torture_close_connection(cli1)) {
1465 0 : return False;
1466 : }
1467 :
1468 5 : if (!torture_close_connection(cli2)) {
1469 0 : return False;
1470 : }
1471 :
1472 5 : printf("Passed locktest1\n");
1473 5 : return True;
1474 : }
1475 :
1476 : /*
1477 : this checks to see if a secondary tconx can use open files from an
1478 : earlier tconx
1479 : */
1480 5 : static bool run_tcon_test(int dummy)
1481 : {
1482 0 : static struct cli_state *cli;
1483 5 : const char *fname = "\\tcontest.tmp";
1484 0 : uint16_t fnum1;
1485 0 : uint32_t cnum1, cnum2, cnum3;
1486 5 : struct smbXcli_tcon *orig_tcon = NULL;
1487 5 : char *orig_share = NULL;
1488 0 : uint16_t vuid1, vuid2;
1489 0 : char buf[4];
1490 5 : bool ret = True;
1491 0 : NTSTATUS status;
1492 :
1493 5 : memset(buf, '\0', sizeof(buf));
1494 :
1495 5 : if (!torture_open_connection(&cli, 0)) {
1496 0 : return False;
1497 : }
1498 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1499 :
1500 5 : printf("starting tcontest\n");
1501 :
1502 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1503 :
1504 5 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1505 5 : if (!NT_STATUS_IS_OK(status)) {
1506 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1507 0 : return False;
1508 : }
1509 :
1510 5 : cnum1 = cli_state_get_tid(cli);
1511 5 : vuid1 = cli_state_get_uid(cli);
1512 :
1513 5 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1514 5 : if (!NT_STATUS_IS_OK(status)) {
1515 0 : printf("initial write failed (%s)", nt_errstr(status));
1516 0 : return False;
1517 : }
1518 :
1519 5 : cli_state_save_tcon_share(cli, &orig_tcon, &orig_share);
1520 :
1521 5 : status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1522 5 : if (!NT_STATUS_IS_OK(status)) {
1523 0 : printf("%s refused 2nd tree connect (%s)\n", host,
1524 : nt_errstr(status));
1525 0 : cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1526 0 : cli_shutdown(cli);
1527 0 : return False;
1528 : }
1529 :
1530 5 : cnum2 = cli_state_get_tid(cli);
1531 5 : cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1532 5 : vuid2 = cli_state_get_uid(cli) + 1;
1533 :
1534 : /* try a write with the wrong tid */
1535 5 : cli_state_set_tid(cli, cnum2);
1536 :
1537 5 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1538 5 : if (NT_STATUS_IS_OK(status)) {
1539 0 : printf("* server allows write with wrong TID\n");
1540 0 : ret = False;
1541 : } else {
1542 5 : printf("server fails write with wrong TID : %s\n",
1543 : nt_errstr(status));
1544 : }
1545 :
1546 :
1547 : /* try a write with an invalid tid */
1548 5 : cli_state_set_tid(cli, cnum3);
1549 :
1550 5 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1551 5 : if (NT_STATUS_IS_OK(status)) {
1552 0 : printf("* server allows write with invalid TID\n");
1553 0 : ret = False;
1554 : } else {
1555 5 : printf("server fails write with invalid TID : %s\n",
1556 : nt_errstr(status));
1557 : }
1558 :
1559 : /* try a write with an invalid vuid */
1560 5 : cli_state_set_uid(cli, vuid2);
1561 5 : cli_state_set_tid(cli, cnum1);
1562 :
1563 5 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1564 5 : if (NT_STATUS_IS_OK(status)) {
1565 0 : printf("* server allows write with invalid VUID\n");
1566 0 : ret = False;
1567 : } else {
1568 5 : printf("server fails write with invalid VUID : %s\n",
1569 : nt_errstr(status));
1570 : }
1571 :
1572 5 : cli_state_set_tid(cli, cnum1);
1573 5 : cli_state_set_uid(cli, vuid1);
1574 :
1575 5 : status = cli_close(cli, fnum1);
1576 5 : if (!NT_STATUS_IS_OK(status)) {
1577 0 : printf("close failed (%s)\n", nt_errstr(status));
1578 0 : cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1579 0 : cli_shutdown(cli);
1580 0 : return False;
1581 : }
1582 :
1583 5 : cli_state_set_tid(cli, cnum2);
1584 :
1585 5 : status = cli_tdis(cli);
1586 5 : if (!NT_STATUS_IS_OK(status)) {
1587 0 : printf("secondary tdis 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_restore_tcon_share(cli, orig_tcon, orig_share);
1594 :
1595 5 : cli_state_set_tid(cli, cnum1);
1596 :
1597 5 : if (!torture_close_connection(cli)) {
1598 0 : return False;
1599 : }
1600 :
1601 5 : return ret;
1602 : }
1603 :
1604 :
1605 : /*
1606 : checks for old style tcon support
1607 : */
1608 5 : static bool run_tcon2_test(int dummy)
1609 : {
1610 0 : static struct cli_state *cli;
1611 0 : uint16_t cnum, max_xmit;
1612 0 : char *service;
1613 0 : NTSTATUS status;
1614 :
1615 5 : if (!torture_open_connection(&cli, 0)) {
1616 0 : return False;
1617 : }
1618 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1619 :
1620 5 : printf("starting tcon2 test\n");
1621 :
1622 5 : if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1623 0 : return false;
1624 : }
1625 :
1626 5 : status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1627 :
1628 5 : SAFE_FREE(service);
1629 :
1630 5 : if (!NT_STATUS_IS_OK(status)) {
1631 5 : printf("tcon2 failed : %s\n", nt_errstr(status));
1632 : } else {
1633 0 : printf("tcon OK : max_xmit=%d cnum=%d\n",
1634 : (int)max_xmit, (int)cnum);
1635 : }
1636 :
1637 5 : if (!torture_close_connection(cli)) {
1638 0 : return False;
1639 : }
1640 :
1641 5 : printf("Passed tcon2 test\n");
1642 5 : return True;
1643 : }
1644 :
1645 50 : static bool tcon_devtest(struct cli_state *cli,
1646 : const char *myshare, const char *devtype,
1647 : const char *return_devtype,
1648 : NTSTATUS expected_error)
1649 : {
1650 0 : NTSTATUS status;
1651 0 : bool ret;
1652 :
1653 50 : status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1654 :
1655 50 : if (NT_STATUS_IS_OK(expected_error)) {
1656 20 : if (NT_STATUS_IS_OK(status)) {
1657 40 : if (return_devtype != NULL &&
1658 20 : strequal(cli->dev, return_devtype)) {
1659 20 : ret = True;
1660 : } else {
1661 0 : printf("tconX to share %s with type %s "
1662 : "succeeded but returned the wrong "
1663 : "device type (got [%s] but should have got [%s])\n",
1664 : myshare, devtype, cli->dev, return_devtype);
1665 0 : ret = False;
1666 : }
1667 : } else {
1668 0 : printf("tconX to share %s with type %s "
1669 : "should have succeeded but failed\n",
1670 : myshare, devtype);
1671 0 : ret = False;
1672 : }
1673 20 : cli_tdis(cli);
1674 : } else {
1675 30 : if (NT_STATUS_IS_OK(status)) {
1676 0 : printf("tconx to share %s with type %s "
1677 : "should have failed but succeeded\n",
1678 : myshare, devtype);
1679 0 : ret = False;
1680 : } else {
1681 30 : if (NT_STATUS_EQUAL(status, expected_error)) {
1682 30 : ret = True;
1683 : } else {
1684 0 : printf("Returned unexpected error\n");
1685 0 : ret = False;
1686 : }
1687 : }
1688 : }
1689 50 : return ret;
1690 : }
1691 :
1692 : /*
1693 : checks for correct tconX support
1694 : */
1695 5 : static bool run_tcon_devtype_test(int dummy)
1696 : {
1697 0 : static struct cli_state *cli1 = NULL;
1698 5 : int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1699 0 : NTSTATUS status;
1700 5 : bool ret = True;
1701 :
1702 5 : status = cli_full_connection_creds(&cli1,
1703 : myname,
1704 : host,
1705 : NULL, /* dest_ss */
1706 : port_to_use,
1707 : NULL, /* service */
1708 : NULL, /* service_type */
1709 : torture_creds,
1710 : flags);
1711 :
1712 5 : if (!NT_STATUS_IS_OK(status)) {
1713 0 : printf("could not open connection\n");
1714 0 : return False;
1715 : }
1716 :
1717 5 : if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1718 0 : ret = False;
1719 :
1720 5 : if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1721 0 : ret = False;
1722 :
1723 5 : if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1724 0 : ret = False;
1725 :
1726 5 : if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1727 0 : ret = False;
1728 :
1729 5 : if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1730 0 : ret = False;
1731 :
1732 5 : if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1733 0 : ret = False;
1734 :
1735 5 : if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1736 0 : ret = False;
1737 :
1738 5 : if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1739 0 : ret = False;
1740 :
1741 5 : if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1742 0 : ret = False;
1743 :
1744 5 : if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1745 0 : ret = False;
1746 :
1747 5 : cli_shutdown(cli1);
1748 :
1749 5 : if (ret)
1750 5 : printf("Passed tcondevtest\n");
1751 :
1752 5 : return ret;
1753 : }
1754 :
1755 :
1756 : /*
1757 : This test checks that
1758 :
1759 : 1) the server supports multiple locking contexts on the one SMB
1760 : connection, distinguished by PID.
1761 :
1762 : 2) the server correctly fails overlapping locks made by the same PID (this
1763 : goes against POSIX behaviour, which is why it is tricky to implement)
1764 :
1765 : 3) the server denies unlock requests by an incorrect client PID
1766 : */
1767 5 : static bool run_locktest2(int dummy)
1768 : {
1769 0 : static struct cli_state *cli;
1770 5 : const char *fname = "\\lockt2.lck";
1771 0 : uint16_t fnum1, fnum2, fnum3;
1772 5 : bool correct = True;
1773 0 : NTSTATUS status;
1774 :
1775 5 : if (!torture_open_connection(&cli, 0)) {
1776 0 : return False;
1777 : }
1778 :
1779 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1780 :
1781 5 : printf("starting locktest2\n");
1782 :
1783 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1784 :
1785 5 : cli_setpid(cli, 1);
1786 :
1787 5 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1788 5 : if (!NT_STATUS_IS_OK(status)) {
1789 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1790 0 : return False;
1791 : }
1792 :
1793 5 : status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1794 5 : if (!NT_STATUS_IS_OK(status)) {
1795 0 : printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1796 0 : return False;
1797 : }
1798 :
1799 5 : cli_setpid(cli, 2);
1800 :
1801 5 : status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1802 5 : if (!NT_STATUS_IS_OK(status)) {
1803 0 : printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1804 0 : return False;
1805 : }
1806 :
1807 5 : cli_setpid(cli, 1);
1808 :
1809 5 : status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1810 5 : if (!NT_STATUS_IS_OK(status)) {
1811 0 : printf("lock1 failed (%s)\n", nt_errstr(status));
1812 0 : return false;
1813 : }
1814 :
1815 5 : status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1816 5 : if (NT_STATUS_IS_OK(status)) {
1817 0 : printf("WRITE lock1 succeeded! This is a locking bug\n");
1818 0 : correct = false;
1819 : } else {
1820 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1821 5 : NT_STATUS_LOCK_NOT_GRANTED)) {
1822 0 : return false;
1823 : }
1824 : }
1825 :
1826 5 : status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1827 5 : if (NT_STATUS_IS_OK(status)) {
1828 0 : printf("WRITE lock2 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, READ_LOCK);
1838 5 : if (NT_STATUS_IS_OK(status)) {
1839 0 : printf("READ 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_FILE_LOCK_CONFLICT)) {
1844 0 : return false;
1845 : }
1846 : }
1847 :
1848 5 : status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1849 5 : if (!NT_STATUS_IS_OK(status)) {
1850 0 : printf("lock at 100 failed (%s)\n", nt_errstr(status));
1851 : }
1852 5 : cli_setpid(cli, 2);
1853 5 : if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1854 0 : printf("unlock at 100 succeeded! This is a locking bug\n");
1855 0 : correct = False;
1856 : }
1857 :
1858 5 : status = cli_unlock(cli, fnum1, 0, 4);
1859 5 : if (NT_STATUS_IS_OK(status)) {
1860 0 : printf("unlock1 succeeded! This is a locking bug\n");
1861 0 : correct = false;
1862 : } else {
1863 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1864 5 : NT_STATUS_RANGE_NOT_LOCKED)) {
1865 0 : return false;
1866 : }
1867 : }
1868 :
1869 5 : status = cli_unlock(cli, fnum1, 0, 8);
1870 5 : if (NT_STATUS_IS_OK(status)) {
1871 0 : printf("unlock2 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_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1881 5 : if (NT_STATUS_IS_OK(status)) {
1882 0 : printf("lock3 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_LOCK_NOT_GRANTED)) {
1887 0 : return false;
1888 : }
1889 : }
1890 :
1891 5 : cli_setpid(cli, 1);
1892 :
1893 5 : status = cli_close(cli, fnum1);
1894 5 : if (!NT_STATUS_IS_OK(status)) {
1895 0 : printf("close1 failed (%s)\n", nt_errstr(status));
1896 0 : return False;
1897 : }
1898 :
1899 5 : status = cli_close(cli, fnum2);
1900 5 : if (!NT_STATUS_IS_OK(status)) {
1901 0 : printf("close2 failed (%s)\n", nt_errstr(status));
1902 0 : return False;
1903 : }
1904 :
1905 5 : status = cli_close(cli, fnum3);
1906 5 : if (!NT_STATUS_IS_OK(status)) {
1907 0 : printf("close3 failed (%s)\n", nt_errstr(status));
1908 0 : return False;
1909 : }
1910 :
1911 5 : if (!torture_close_connection(cli)) {
1912 0 : correct = False;
1913 : }
1914 :
1915 5 : printf("locktest2 finished\n");
1916 :
1917 5 : return correct;
1918 : }
1919 :
1920 :
1921 : /*
1922 : This test checks that
1923 :
1924 : 1) the server supports the full offset range in lock requests
1925 : */
1926 5 : static bool run_locktest3(int dummy)
1927 : {
1928 0 : static struct cli_state *cli1, *cli2;
1929 5 : const char *fname = "\\lockt3.lck";
1930 0 : uint16_t fnum1, fnum2;
1931 0 : int i;
1932 0 : uint32_t offset;
1933 5 : bool correct = True;
1934 0 : NTSTATUS status;
1935 :
1936 : #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1937 :
1938 5 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1939 0 : return False;
1940 : }
1941 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
1942 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
1943 :
1944 5 : printf("starting locktest3\n");
1945 :
1946 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1947 :
1948 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1949 : &fnum1);
1950 5 : if (!NT_STATUS_IS_OK(status)) {
1951 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1952 0 : return False;
1953 : }
1954 :
1955 5 : status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1956 5 : if (!NT_STATUS_IS_OK(status)) {
1957 0 : printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1958 0 : return False;
1959 : }
1960 :
1961 505 : for (offset=i=0;i<torture_numops;i++) {
1962 500 : NEXT_OFFSET;
1963 :
1964 500 : status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1965 500 : if (!NT_STATUS_IS_OK(status)) {
1966 0 : printf("lock1 %d failed (%s)\n",
1967 : i,
1968 : nt_errstr(status));
1969 0 : return False;
1970 : }
1971 :
1972 500 : status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1973 500 : if (!NT_STATUS_IS_OK(status)) {
1974 0 : printf("lock2 %d failed (%s)\n",
1975 : i,
1976 : nt_errstr(status));
1977 0 : return False;
1978 : }
1979 : }
1980 :
1981 505 : for (offset=i=0;i<torture_numops;i++) {
1982 500 : NEXT_OFFSET;
1983 :
1984 500 : status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1985 500 : if (NT_STATUS_IS_OK(status)) {
1986 0 : printf("error: lock1 %d succeeded!\n", i);
1987 0 : return False;
1988 : }
1989 :
1990 500 : status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1991 500 : if (NT_STATUS_IS_OK(status)) {
1992 0 : printf("error: lock2 %d succeeded!\n", i);
1993 0 : return False;
1994 : }
1995 :
1996 500 : status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1997 500 : if (NT_STATUS_IS_OK(status)) {
1998 0 : printf("error: lock3 %d succeeded!\n", i);
1999 0 : return False;
2000 : }
2001 :
2002 500 : status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
2003 500 : if (NT_STATUS_IS_OK(status)) {
2004 0 : printf("error: lock4 %d succeeded!\n", i);
2005 0 : return False;
2006 : }
2007 : }
2008 :
2009 505 : for (offset=i=0;i<torture_numops;i++) {
2010 500 : NEXT_OFFSET;
2011 :
2012 500 : status = cli_unlock(cli1, fnum1, offset-1, 1);
2013 500 : if (!NT_STATUS_IS_OK(status)) {
2014 0 : printf("unlock1 %d failed (%s)\n",
2015 : i,
2016 : nt_errstr(status));
2017 0 : return False;
2018 : }
2019 :
2020 500 : status = cli_unlock(cli2, fnum2, offset-2, 1);
2021 500 : if (!NT_STATUS_IS_OK(status)) {
2022 0 : printf("unlock2 %d failed (%s)\n",
2023 : i,
2024 : nt_errstr(status));
2025 0 : return False;
2026 : }
2027 : }
2028 :
2029 5 : status = cli_close(cli1, fnum1);
2030 5 : if (!NT_STATUS_IS_OK(status)) {
2031 0 : printf("close1 failed (%s)\n", nt_errstr(status));
2032 0 : return False;
2033 : }
2034 :
2035 5 : status = cli_close(cli2, fnum2);
2036 5 : if (!NT_STATUS_IS_OK(status)) {
2037 0 : printf("close2 failed (%s)\n", nt_errstr(status));
2038 0 : return False;
2039 : }
2040 :
2041 5 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2042 5 : if (!NT_STATUS_IS_OK(status)) {
2043 0 : printf("unlink failed (%s)\n", nt_errstr(status));
2044 0 : return False;
2045 : }
2046 :
2047 5 : if (!torture_close_connection(cli1)) {
2048 0 : correct = False;
2049 : }
2050 :
2051 5 : if (!torture_close_connection(cli2)) {
2052 0 : correct = False;
2053 : }
2054 :
2055 5 : printf("finished locktest3\n");
2056 :
2057 5 : return correct;
2058 : }
2059 :
2060 40 : static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
2061 : char *buf, off_t offset, size_t size,
2062 : size_t *nread, size_t expect)
2063 : {
2064 0 : NTSTATUS status;
2065 0 : size_t l_nread;
2066 :
2067 40 : status = cli_read(cli, fnum, buf, offset, size, &l_nread);
2068 :
2069 40 : if(!NT_STATUS_IS_OK(status)) {
2070 20 : return false;
2071 20 : } else if (l_nread != expect) {
2072 0 : return false;
2073 : }
2074 :
2075 20 : if (nread) {
2076 0 : *nread = l_nread;
2077 : }
2078 :
2079 20 : return true;
2080 : }
2081 :
2082 : #define EXPECTED(ret, v) if ((ret) != (v)) { \
2083 : printf("** "); correct = False; \
2084 : }
2085 :
2086 : /*
2087 : looks at overlapping locks
2088 : */
2089 5 : static bool run_locktest4(int dummy)
2090 : {
2091 0 : static struct cli_state *cli1, *cli2;
2092 5 : const char *fname = "\\lockt4.lck";
2093 0 : uint16_t fnum1, fnum2, f;
2094 0 : bool ret;
2095 0 : char buf[1000];
2096 5 : bool correct = True;
2097 0 : NTSTATUS status;
2098 :
2099 5 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2100 0 : return False;
2101 : }
2102 :
2103 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2104 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
2105 :
2106 5 : printf("starting locktest4\n");
2107 :
2108 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2109 :
2110 5 : cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2111 5 : cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2112 :
2113 5 : memset(buf, 0, sizeof(buf));
2114 :
2115 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2116 : NULL);
2117 5 : if (!NT_STATUS_IS_OK(status)) {
2118 0 : printf("Failed to create file: %s\n", nt_errstr(status));
2119 0 : correct = False;
2120 0 : goto fail;
2121 : }
2122 :
2123 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2124 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
2125 5 : EXPECTED(ret, False);
2126 5 : printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2127 :
2128 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2129 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2130 5 : EXPECTED(ret, True);
2131 5 : printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2132 :
2133 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2134 5 : NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2135 5 : EXPECTED(ret, False);
2136 5 : printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2137 :
2138 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2139 5 : NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2140 5 : EXPECTED(ret, True);
2141 5 : printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2142 :
2143 5 : ret = (cli_setpid(cli1, 1),
2144 10 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2145 5 : (cli_setpid(cli1, 2),
2146 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2147 5 : EXPECTED(ret, False);
2148 5 : printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2149 :
2150 5 : ret = (cli_setpid(cli1, 1),
2151 10 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2152 5 : (cli_setpid(cli1, 2),
2153 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2154 5 : EXPECTED(ret, True);
2155 5 : printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2156 :
2157 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2158 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2159 5 : EXPECTED(ret, True);
2160 5 : printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2161 :
2162 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2163 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2164 5 : EXPECTED(ret, False);
2165 5 : printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2166 :
2167 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2168 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2169 5 : EXPECTED(ret, False);
2170 5 : printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2171 :
2172 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2173 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2174 5 : EXPECTED(ret, True);
2175 5 : printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2176 :
2177 5 : ret = (cli_setpid(cli1, 1),
2178 10 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2179 5 : (cli_setpid(cli1, 2),
2180 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2181 5 : EXPECTED(ret, False);
2182 5 : printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2183 :
2184 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2185 10 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2186 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2187 5 : EXPECTED(ret, False);
2188 5 : printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2189 :
2190 :
2191 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2192 5 : test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2193 5 : EXPECTED(ret, False);
2194 5 : printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2195 :
2196 5 : status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2197 5 : ret = NT_STATUS_IS_OK(status);
2198 5 : if (ret) {
2199 5 : status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2200 : NULL);
2201 5 : ret = NT_STATUS_IS_OK(status);
2202 : }
2203 5 : EXPECTED(ret, False);
2204 5 : printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2205 :
2206 :
2207 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2208 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2209 15 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2210 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2211 5 : EXPECTED(ret, True);
2212 5 : printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2213 :
2214 :
2215 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2216 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2217 10 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2218 5 : test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2219 5 : !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2220 10 : 150, 4, NULL))) &&
2221 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2222 5 : EXPECTED(ret, True);
2223 5 : printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2224 :
2225 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2226 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2227 5 : NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2228 10 : 160, 4, NULL)) &&
2229 5 : test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2230 5 : EXPECTED(ret, True);
2231 5 : printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2232 :
2233 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2234 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2235 5 : NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2236 10 : 170, 4, NULL)) &&
2237 5 : test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2238 5 : EXPECTED(ret, True);
2239 5 : printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2240 :
2241 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2242 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2243 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2244 5 : !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2245 10 : 190, 4, NULL)) &&
2246 5 : test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2247 5 : EXPECTED(ret, True);
2248 5 : printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2249 :
2250 5 : cli_close(cli1, fnum1);
2251 5 : cli_close(cli2, fnum2);
2252 5 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2253 5 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2254 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2255 5 : NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2256 5 : NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2257 15 : NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2258 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2259 5 : cli_close(cli1, f);
2260 5 : cli_close(cli1, fnum1);
2261 5 : EXPECTED(ret, True);
2262 5 : printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2263 :
2264 5 : fail:
2265 5 : cli_close(cli1, fnum1);
2266 5 : cli_close(cli2, fnum2);
2267 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2268 5 : torture_close_connection(cli1);
2269 5 : torture_close_connection(cli2);
2270 :
2271 5 : printf("finished locktest4\n");
2272 5 : return correct;
2273 : }
2274 :
2275 : /*
2276 : looks at lock upgrade/downgrade.
2277 : */
2278 5 : static bool run_locktest5(int dummy)
2279 : {
2280 0 : static struct cli_state *cli1, *cli2;
2281 5 : const char *fname = "\\lockt5.lck";
2282 0 : uint16_t fnum1, fnum2, fnum3;
2283 0 : bool ret;
2284 0 : char buf[1000];
2285 5 : bool correct = True;
2286 0 : NTSTATUS status;
2287 :
2288 5 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2289 0 : return False;
2290 : }
2291 :
2292 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2293 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
2294 :
2295 5 : printf("starting locktest5\n");
2296 :
2297 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2298 :
2299 5 : cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2300 5 : cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2301 5 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2302 :
2303 5 : memset(buf, 0, sizeof(buf));
2304 :
2305 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2306 : NULL);
2307 5 : if (!NT_STATUS_IS_OK(status)) {
2308 0 : printf("Failed to create file: %s\n", nt_errstr(status));
2309 0 : correct = False;
2310 0 : goto fail;
2311 : }
2312 :
2313 : /* Check for NT bug... */
2314 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2315 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2316 5 : cli_close(cli1, fnum1);
2317 5 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2318 5 : status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2319 5 : ret = NT_STATUS_IS_OK(status);
2320 5 : EXPECTED(ret, True);
2321 5 : printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2322 5 : cli_close(cli1, fnum1);
2323 5 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2324 5 : cli_unlock(cli1, fnum3, 0, 1);
2325 :
2326 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2327 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2328 5 : EXPECTED(ret, True);
2329 5 : printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2330 :
2331 5 : status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2332 5 : ret = NT_STATUS_IS_OK(status);
2333 5 : EXPECTED(ret, False);
2334 :
2335 5 : printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2336 :
2337 : /* Unlock the process 2 lock. */
2338 5 : cli_unlock(cli2, fnum2, 0, 4);
2339 :
2340 5 : status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2341 5 : ret = NT_STATUS_IS_OK(status);
2342 5 : EXPECTED(ret, False);
2343 :
2344 5 : printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2345 :
2346 : /* Unlock the process 1 fnum3 lock. */
2347 5 : cli_unlock(cli1, fnum3, 0, 4);
2348 :
2349 : /* Stack 2 more locks here. */
2350 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2351 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2352 :
2353 5 : EXPECTED(ret, True);
2354 5 : printf("the same process %s stack read locks\n", ret?"can":"cannot");
2355 :
2356 : /* Unlock the first process lock, then check this was the WRITE lock that was
2357 : removed. */
2358 :
2359 10 : ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2360 5 : NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2361 :
2362 5 : EXPECTED(ret, True);
2363 5 : printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2364 :
2365 : /* Unlock the process 2 lock. */
2366 5 : cli_unlock(cli2, fnum2, 0, 4);
2367 :
2368 : /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2369 :
2370 5 : ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2371 10 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2372 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2373 :
2374 5 : EXPECTED(ret, True);
2375 5 : printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2376 :
2377 : /* Ensure the next unlock fails. */
2378 5 : ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2379 5 : EXPECTED(ret, False);
2380 5 : printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2381 :
2382 : /* Ensure connection 2 can get a write lock. */
2383 5 : status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2384 5 : ret = NT_STATUS_IS_OK(status);
2385 5 : EXPECTED(ret, True);
2386 :
2387 5 : printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2388 :
2389 :
2390 5 : fail:
2391 5 : cli_close(cli1, fnum1);
2392 5 : cli_close(cli2, fnum2);
2393 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2394 5 : if (!torture_close_connection(cli1)) {
2395 0 : correct = False;
2396 : }
2397 5 : if (!torture_close_connection(cli2)) {
2398 0 : correct = False;
2399 : }
2400 :
2401 5 : printf("finished locktest5\n");
2402 :
2403 5 : return correct;
2404 : }
2405 :
2406 : /*
2407 : tries the unusual lockingX locktype bits
2408 : */
2409 5 : static bool run_locktest6(int dummy)
2410 : {
2411 0 : static struct cli_state *cli;
2412 5 : const char *fname[1] = { "\\lock6.txt" };
2413 0 : int i;
2414 0 : uint16_t fnum;
2415 0 : NTSTATUS status;
2416 :
2417 5 : if (!torture_open_connection(&cli, 0)) {
2418 0 : return False;
2419 : }
2420 :
2421 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
2422 :
2423 5 : printf("starting locktest6\n");
2424 :
2425 10 : for (i=0;i<1;i++) {
2426 5 : printf("Testing %s\n", fname[i]);
2427 :
2428 5 : cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2429 :
2430 5 : cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2431 5 : status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2432 5 : cli_close(cli, fnum);
2433 5 : printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2434 :
2435 5 : cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2436 5 : status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2437 5 : cli_close(cli, fnum);
2438 5 : printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2439 :
2440 5 : cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2441 : }
2442 :
2443 5 : torture_close_connection(cli);
2444 :
2445 5 : printf("finished locktest6\n");
2446 5 : return True;
2447 : }
2448 :
2449 5 : static bool run_locktest7(int dummy)
2450 : {
2451 0 : struct cli_state *cli1;
2452 5 : const char *fname = "\\lockt7.lck";
2453 0 : uint16_t fnum1;
2454 0 : char buf[200];
2455 5 : bool correct = False;
2456 0 : size_t nread;
2457 0 : NTSTATUS status;
2458 :
2459 5 : if (!torture_open_connection(&cli1, 0)) {
2460 0 : return False;
2461 : }
2462 :
2463 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2464 :
2465 5 : printf("starting locktest7\n");
2466 :
2467 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2468 :
2469 5 : cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2470 :
2471 5 : memset(buf, 0, sizeof(buf));
2472 :
2473 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2474 : NULL);
2475 5 : if (!NT_STATUS_IS_OK(status)) {
2476 0 : printf("Failed to create file: %s\n", nt_errstr(status));
2477 0 : goto fail;
2478 : }
2479 :
2480 5 : cli_setpid(cli1, 1);
2481 :
2482 5 : status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2483 5 : if (!NT_STATUS_IS_OK(status)) {
2484 0 : printf("Unable to apply read lock on range 130:4, "
2485 : "error was %s\n", nt_errstr(status));
2486 0 : goto fail;
2487 : } else {
2488 5 : printf("pid1 successfully locked range 130:4 for READ\n");
2489 : }
2490 :
2491 5 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2492 5 : if (!NT_STATUS_IS_OK(status)) {
2493 0 : printf("pid1 unable to read the range 130:4, error was %s\n",
2494 : nt_errstr(status));
2495 0 : goto fail;
2496 5 : } else if (nread != 4) {
2497 0 : printf("pid1 unable to read the range 130:4, "
2498 : "recv %ld req %d\n", (unsigned long)nread, 4);
2499 0 : goto fail;
2500 : } else {
2501 5 : printf("pid1 successfully read the range 130:4\n");
2502 : }
2503 :
2504 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2505 5 : if (!NT_STATUS_IS_OK(status)) {
2506 5 : printf("pid1 unable to write to the range 130:4, error was "
2507 : "%s\n", nt_errstr(status));
2508 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2509 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2510 0 : goto fail;
2511 : }
2512 : } else {
2513 0 : printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2514 0 : goto fail;
2515 : }
2516 :
2517 5 : cli_setpid(cli1, 2);
2518 :
2519 5 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2520 5 : if (!NT_STATUS_IS_OK(status)) {
2521 0 : printf("pid2 unable to read the range 130:4, error was %s\n",
2522 : nt_errstr(status));
2523 0 : goto fail;
2524 5 : } else if (nread != 4) {
2525 0 : printf("pid2 unable to read the range 130:4, "
2526 : "recv %ld req %d\n", (unsigned long)nread, 4);
2527 0 : goto fail;
2528 : } else {
2529 5 : printf("pid2 successfully read the range 130:4\n");
2530 : }
2531 :
2532 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2533 5 : if (!NT_STATUS_IS_OK(status)) {
2534 5 : printf("pid2 unable to write to the range 130:4, error was "
2535 : "%s\n", nt_errstr(status));
2536 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2537 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2538 0 : goto fail;
2539 : }
2540 : } else {
2541 0 : printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2542 0 : goto fail;
2543 : }
2544 :
2545 5 : cli_setpid(cli1, 1);
2546 5 : cli_unlock(cli1, fnum1, 130, 4);
2547 :
2548 5 : status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2549 5 : if (!NT_STATUS_IS_OK(status)) {
2550 0 : printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2551 0 : goto fail;
2552 : } else {
2553 5 : printf("pid1 successfully locked range 130:4 for WRITE\n");
2554 : }
2555 :
2556 5 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2557 5 : if (!NT_STATUS_IS_OK(status)) {
2558 0 : printf("pid1 unable to read the range 130:4, error was %s\n",
2559 : nt_errstr(status));
2560 0 : goto fail;
2561 5 : } else if (nread != 4) {
2562 0 : printf("pid1 unable to read the range 130:4, "
2563 : "recv %ld req %d\n", (unsigned long)nread, 4);
2564 0 : goto fail;
2565 : } else {
2566 5 : printf("pid1 successfully read the range 130:4\n");
2567 : }
2568 :
2569 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2570 5 : if (!NT_STATUS_IS_OK(status)) {
2571 0 : printf("pid1 unable to write to the range 130:4, error was "
2572 : "%s\n", nt_errstr(status));
2573 0 : goto fail;
2574 : } else {
2575 5 : printf("pid1 successfully wrote to the range 130:4\n");
2576 : }
2577 :
2578 5 : cli_setpid(cli1, 2);
2579 :
2580 5 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2581 5 : if (!NT_STATUS_IS_OK(status)) {
2582 5 : printf("pid2 unable to read the range 130:4, error was "
2583 : "%s\n", nt_errstr(status));
2584 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2585 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2586 0 : goto fail;
2587 : }
2588 : } else {
2589 0 : printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2590 : (unsigned long)nread);
2591 0 : goto fail;
2592 : }
2593 :
2594 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2595 5 : if (!NT_STATUS_IS_OK(status)) {
2596 5 : printf("pid2 unable to write to the range 130:4, error was "
2597 : "%s\n", nt_errstr(status));
2598 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2599 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2600 0 : goto fail;
2601 : }
2602 : } else {
2603 0 : printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2604 0 : goto fail;
2605 : }
2606 :
2607 5 : cli_unlock(cli1, fnum1, 130, 0);
2608 5 : correct = True;
2609 :
2610 5 : fail:
2611 5 : cli_close(cli1, fnum1);
2612 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2613 5 : torture_close_connection(cli1);
2614 :
2615 5 : printf("finished locktest7\n");
2616 5 : return correct;
2617 : }
2618 :
2619 : /*
2620 : * This demonstrates a problem with our use of GPFS share modes: A file
2621 : * descriptor sitting in the pending close queue holding a GPFS share mode
2622 : * blocks opening a file another time. Happens with Word 2007 temp files.
2623 : * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2624 : * open is denied with NT_STATUS_SHARING_VIOLATION.
2625 : */
2626 :
2627 0 : static bool run_locktest8(int dummy)
2628 : {
2629 0 : struct cli_state *cli1;
2630 0 : const char *fname = "\\lockt8.lck";
2631 0 : uint16_t fnum1, fnum2;
2632 0 : char buf[200];
2633 0 : bool correct = False;
2634 0 : NTSTATUS status;
2635 :
2636 0 : if (!torture_open_connection(&cli1, 0)) {
2637 0 : return False;
2638 : }
2639 :
2640 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2641 :
2642 0 : printf("starting locktest8\n");
2643 :
2644 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2645 :
2646 0 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2647 : &fnum1);
2648 0 : if (!NT_STATUS_IS_OK(status)) {
2649 0 : d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2650 0 : return false;
2651 : }
2652 :
2653 0 : memset(buf, 0, sizeof(buf));
2654 :
2655 0 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2656 0 : if (!NT_STATUS_IS_OK(status)) {
2657 0 : d_fprintf(stderr, "cli_openx second time returned %s\n",
2658 : nt_errstr(status));
2659 0 : goto fail;
2660 : }
2661 :
2662 0 : status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2663 0 : if (!NT_STATUS_IS_OK(status)) {
2664 0 : printf("Unable to apply read lock on range 1:1, error was "
2665 : "%s\n", nt_errstr(status));
2666 0 : goto fail;
2667 : }
2668 :
2669 0 : status = cli_close(cli1, fnum1);
2670 0 : if (!NT_STATUS_IS_OK(status)) {
2671 0 : d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2672 0 : goto fail;
2673 : }
2674 :
2675 0 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2676 0 : if (!NT_STATUS_IS_OK(status)) {
2677 0 : d_fprintf(stderr, "cli_openx third time returned %s\n",
2678 : nt_errstr(status));
2679 0 : goto fail;
2680 : }
2681 :
2682 0 : correct = true;
2683 :
2684 0 : fail:
2685 0 : cli_close(cli1, fnum1);
2686 0 : cli_close(cli1, fnum2);
2687 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2688 0 : torture_close_connection(cli1);
2689 :
2690 0 : printf("finished locktest8\n");
2691 0 : return correct;
2692 : }
2693 :
2694 : /*
2695 : * This test is designed to be run in conjunction with
2696 : * external NFS or POSIX locks taken in the filesystem.
2697 : * It checks that the smbd server will block until the
2698 : * lock is released and then acquire it. JRA.
2699 : */
2700 :
2701 : static bool got_alarm;
2702 : static struct cli_state *alarm_cli;
2703 :
2704 0 : static void alarm_handler(int dummy)
2705 : {
2706 0 : got_alarm = True;
2707 0 : }
2708 :
2709 0 : static void alarm_handler_parent(int dummy)
2710 : {
2711 0 : smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2712 0 : }
2713 :
2714 8 : static void do_local_lock(const char *fname, int read_fd, int write_fd)
2715 : {
2716 0 : int fd;
2717 8 : char c = '\0';
2718 0 : struct flock lock;
2719 8 : const char *local_pathname = NULL;
2720 0 : int ret;
2721 :
2722 8 : local_pathname = talloc_asprintf(talloc_tos(),
2723 : "%s/%s", local_path, fname);
2724 8 : if (!local_pathname) {
2725 0 : printf("child: alloc fail\n");
2726 0 : exit(1);
2727 : }
2728 :
2729 8 : unlink(local_pathname);
2730 8 : fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2731 8 : if (fd == -1) {
2732 0 : printf("child: open of %s failed %s.\n",
2733 0 : local_pathname, strerror(errno));
2734 0 : exit(1);
2735 : }
2736 :
2737 : /* Now take a fcntl lock. */
2738 8 : lock.l_type = F_WRLCK;
2739 8 : lock.l_whence = SEEK_SET;
2740 8 : lock.l_start = 0;
2741 8 : lock.l_len = 4;
2742 8 : lock.l_pid = getpid();
2743 :
2744 8 : ret = fcntl(fd,F_SETLK,&lock);
2745 8 : if (ret == -1) {
2746 0 : printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2747 0 : local_pathname, strerror(errno));
2748 0 : exit(1);
2749 : } else {
2750 8 : printf("child: got lock 0:4 on file %s.\n",
2751 : local_pathname );
2752 8 : fflush(stdout);
2753 : }
2754 :
2755 8 : CatchSignal(SIGALRM, alarm_handler);
2756 8 : alarm(5);
2757 : /* Signal the parent. */
2758 8 : if (write(write_fd, &c, 1) != 1) {
2759 0 : printf("child: start signal fail %s.\n",
2760 0 : strerror(errno));
2761 0 : exit(1);
2762 : }
2763 8 : alarm(0);
2764 :
2765 8 : alarm(10);
2766 : /* Wait for the parent to be ready. */
2767 8 : if (read(read_fd, &c, 1) != 1) {
2768 0 : printf("child: reply signal fail %s.\n",
2769 0 : strerror(errno));
2770 0 : exit(1);
2771 : }
2772 8 : alarm(0);
2773 :
2774 8 : sleep(5);
2775 8 : close(fd);
2776 8 : printf("child: released lock 0:4 on file %s.\n",
2777 : local_pathname );
2778 8 : fflush(stdout);
2779 8 : exit(0);
2780 : }
2781 :
2782 8 : static bool _run_locktest9X(const char *fname, int timeout)
2783 : {
2784 0 : struct cli_state *cli1;
2785 8 : char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2786 0 : uint16_t fnum;
2787 8 : bool correct = False;
2788 0 : int pipe_in[2], pipe_out[2];
2789 0 : pid_t child_pid;
2790 8 : char c = '\0';
2791 0 : int ret;
2792 0 : struct timeval start;
2793 0 : double seconds;
2794 0 : NTSTATUS status;
2795 :
2796 8 : printf("starting locktest9X: %s\n", fname);
2797 :
2798 8 : if (local_path == NULL) {
2799 0 : d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2800 0 : return false;
2801 : }
2802 :
2803 8 : if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2804 0 : return false;
2805 : }
2806 :
2807 8 : child_pid = fork();
2808 16 : if (child_pid == -1) {
2809 0 : return false;
2810 : }
2811 :
2812 16 : if (child_pid == 0) {
2813 : /* Child. */
2814 8 : do_local_lock(fname, pipe_out[0], pipe_in[1]);
2815 0 : exit(0);
2816 : }
2817 :
2818 8 : close(pipe_out[0]);
2819 8 : close(pipe_in[1]);
2820 8 : pipe_out[0] = -1;
2821 8 : pipe_in[1] = -1;
2822 :
2823 : /* Parent. */
2824 8 : ret = read(pipe_in[0], &c, 1);
2825 8 : if (ret != 1) {
2826 0 : d_fprintf(stderr, "failed to read start signal from child. %s\n",
2827 0 : strerror(errno));
2828 0 : return false;
2829 : }
2830 :
2831 8 : if (!torture_open_connection(&cli1, 0)) {
2832 0 : return false;
2833 : }
2834 :
2835 8 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2836 :
2837 8 : status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2838 : &fnum);
2839 8 : if (!NT_STATUS_IS_OK(status)) {
2840 0 : d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2841 0 : return false;
2842 : }
2843 :
2844 : /* Ensure the child has the lock. */
2845 8 : status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2846 8 : if (NT_STATUS_IS_OK(status)) {
2847 0 : d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2848 0 : goto fail;
2849 : } else {
2850 8 : d_printf("Child has the lock.\n");
2851 : }
2852 :
2853 : /* Tell the child to wait 5 seconds then exit. */
2854 8 : ret = write(pipe_out[1], &c, 1);
2855 8 : if (ret != 1) {
2856 0 : d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2857 0 : strerror(errno));
2858 0 : goto fail;
2859 : }
2860 :
2861 : /* Wait 20 seconds for the lock. */
2862 8 : alarm_cli = cli1;
2863 8 : CatchSignal(SIGALRM, alarm_handler_parent);
2864 8 : alarm(20);
2865 :
2866 8 : start = timeval_current();
2867 :
2868 8 : status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2869 8 : if (!NT_STATUS_IS_OK(status)) {
2870 0 : d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2871 : "%s\n", nt_errstr(status));
2872 0 : goto fail_nofd;
2873 : }
2874 8 : alarm(0);
2875 :
2876 8 : seconds = timeval_elapsed(&start);
2877 :
2878 8 : printf("Parent got the lock after %.2f seconds.\n",
2879 : seconds);
2880 :
2881 8 : status = cli_close(cli1, fnum);
2882 8 : if (!NT_STATUS_IS_OK(status)) {
2883 0 : d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2884 0 : goto fail;
2885 : }
2886 :
2887 8 : correct = true;
2888 :
2889 8 : fail:
2890 8 : cli_close(cli1, fnum);
2891 8 : torture_close_connection(cli1);
2892 :
2893 8 : fail_nofd:
2894 :
2895 8 : printf("finished locktest9X: %s\n", fname);
2896 8 : return correct;
2897 : }
2898 :
2899 4 : static bool run_locktest9a(int dummy)
2900 : {
2901 4 : return _run_locktest9X("lock9a.dat", -1);
2902 : }
2903 :
2904 4 : static bool run_locktest9b(int dummy)
2905 : {
2906 4 : return _run_locktest9X("lock9b.dat", 10000);
2907 : }
2908 :
2909 : struct locktest10_state {
2910 : bool ok;
2911 : bool done;
2912 : };
2913 :
2914 : static void locktest10_lockingx_done(struct tevent_req *subreq);
2915 : static void locktest10_read_andx_done(struct tevent_req *subreq);
2916 :
2917 5 : static bool run_locktest10(int dummy)
2918 : {
2919 5 : struct tevent_context *ev = NULL;
2920 5 : struct cli_state *cli1 = NULL;
2921 5 : struct cli_state *cli2 = NULL;
2922 5 : struct smb1_lock_element lck = { 0 };
2923 5 : struct tevent_req *reqs[2] = { NULL };
2924 5 : struct tevent_req *smbreqs[2] = { NULL };
2925 5 : const char fname[] = "\\lockt10.lck";
2926 0 : uint16_t fnum1, fnum2;
2927 5 : bool ret = false;
2928 0 : bool ok;
2929 5 : uint8_t data = 1;
2930 5 : struct locktest10_state state = { .ok = true };
2931 0 : NTSTATUS status;
2932 :
2933 5 : printf("starting locktest10\n");
2934 :
2935 5 : ev = samba_tevent_context_init(NULL);
2936 5 : if (ev == NULL) {
2937 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
2938 0 : goto done;
2939 : }
2940 :
2941 5 : ok = torture_open_connection(&cli1, 0);
2942 5 : if (!ok) {
2943 0 : goto done;
2944 : }
2945 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2946 :
2947 5 : ok = torture_open_connection(&cli2, 1);
2948 5 : if (!ok) {
2949 0 : goto done;
2950 : }
2951 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
2952 :
2953 5 : status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2954 5 : if (!NT_STATUS_IS_OK(status)) {
2955 0 : d_fprintf(stderr,
2956 : "cli_openx failed: %s\n",
2957 : nt_errstr(status));
2958 0 : goto done;
2959 : }
2960 :
2961 5 : status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2962 5 : if (!NT_STATUS_IS_OK(status)) {
2963 0 : d_fprintf(stderr,
2964 : "cli_writeall failed: %s\n",
2965 : nt_errstr(status));
2966 0 : goto done;
2967 : }
2968 :
2969 5 : status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2970 5 : if (!NT_STATUS_IS_OK(status)) {
2971 0 : d_fprintf(stderr,
2972 : "cli_openx failed: %s\n",
2973 : nt_errstr(status));
2974 0 : goto done;
2975 : }
2976 :
2977 5 : status = cli_locktype(
2978 : cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2979 5 : if (!NT_STATUS_IS_OK(status)) {
2980 0 : d_fprintf(stderr,
2981 : "cli_locktype failed: %s\n",
2982 : nt_errstr(status));
2983 0 : goto done;
2984 : }
2985 :
2986 5 : lck = (struct smb1_lock_element) {
2987 5 : .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2988 : };
2989 :
2990 5 : reqs[0] = cli_lockingx_create(
2991 : ev, /* mem_ctx */
2992 : ev, /* tevent_context */
2993 : cli1, /* cli */
2994 : fnum1, /* fnum */
2995 : LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
2996 : 0, /* newoplocklevel */
2997 : 1, /* timeout */
2998 : 0, /* num_unlocks */
2999 : NULL, /* unlocks */
3000 : 1, /* num_locks */
3001 : &lck, /* locks */
3002 : &smbreqs[0]); /* psmbreq */
3003 5 : if (reqs[0] == NULL) {
3004 0 : d_fprintf(stderr, "cli_lockingx_create failed\n");
3005 0 : goto done;
3006 : }
3007 5 : tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
3008 :
3009 5 : reqs[1] = cli_read_andx_create(
3010 : ev, /* mem_ctx */
3011 : ev, /* ev */
3012 : cli1, /* cli */
3013 : fnum1, /* fnum */
3014 : 0, /* offset */
3015 : 1, /* size */
3016 : &smbreqs[1]); /* psmbreq */
3017 5 : if (reqs[1] == NULL) {
3018 0 : d_fprintf(stderr, "cli_read_andx_create failed\n");
3019 0 : goto done;
3020 : }
3021 5 : tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
3022 :
3023 5 : status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
3024 5 : if (!NT_STATUS_IS_OK(status)) {
3025 0 : d_fprintf(stderr,
3026 : "smb1cli_req_chain_submit failed: %s\n",
3027 : nt_errstr(status));
3028 0 : goto done;
3029 : }
3030 :
3031 30 : while (!state.done) {
3032 25 : tevent_loop_once(ev);
3033 : }
3034 :
3035 5 : torture_close_connection(cli1);
3036 :
3037 5 : if (state.ok) {
3038 5 : ret = true;
3039 : }
3040 0 : done:
3041 5 : return ret;
3042 : }
3043 :
3044 5 : static void locktest10_lockingx_done(struct tevent_req *subreq)
3045 : {
3046 5 : struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3047 0 : NTSTATUS status;
3048 :
3049 5 : status = cli_lockingx_recv(subreq);
3050 5 : TALLOC_FREE(subreq);
3051 :
3052 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3053 0 : d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3054 0 : state->ok = false;
3055 : }
3056 5 : }
3057 :
3058 5 : static void locktest10_read_andx_done(struct tevent_req *subreq)
3059 : {
3060 5 : struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3061 5 : ssize_t received = -1;
3062 5 : uint8_t *rcvbuf = NULL;
3063 0 : NTSTATUS status;
3064 :
3065 5 : status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3066 :
3067 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
3068 0 : d_printf("cli_read_andx returned %s\n", nt_errstr(status));
3069 0 : state->ok = false;
3070 : }
3071 :
3072 5 : state->done = true;
3073 5 : TALLOC_FREE(subreq);
3074 5 : }
3075 :
3076 5 : static bool run_locktest11(int dummy)
3077 : {
3078 0 : struct cli_state *cli1;
3079 5 : const char *fname = "\\lockt11.lck";
3080 0 : NTSTATUS status;
3081 0 : uint16_t fnum;
3082 5 : bool ret = false;
3083 :
3084 5 : if (!torture_open_connection(&cli1, 0)) {
3085 0 : return false;
3086 : }
3087 :
3088 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
3089 :
3090 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3091 :
3092 5 : status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
3093 5 : if (!NT_STATUS_IS_OK(status)) {
3094 0 : d_fprintf(stderr,
3095 : "cli_openx returned %s\n",
3096 : nt_errstr(status));
3097 0 : return false;
3098 : }
3099 :
3100 : /*
3101 : * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3102 : * returns NT_STATUS_OK
3103 : */
3104 :
3105 5 : status = cli_lockingx(
3106 : cli1, /* cli */
3107 : fnum, /* fnum */
3108 : LOCKING_ANDX_CANCEL_LOCK, /* typeoflock */
3109 : 0, /* newoplocklevel */
3110 : 0, /* timeout */
3111 : 0, /* num_unlocks */
3112 : NULL, /* unlocks */
3113 : 0, /* num_locks */
3114 : NULL); /* locks */
3115 :
3116 5 : if (!NT_STATUS_IS_OK(status)) {
3117 1 : d_printf("cli_lockingX returned %s\n", nt_errstr(status));
3118 1 : goto fail;
3119 : }
3120 :
3121 4 : ret = true;
3122 5 : fail:
3123 5 : cli_close(cli1, fnum);
3124 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3125 :
3126 5 : return ret;
3127 : }
3128 :
3129 : struct deferred_close_state {
3130 : struct tevent_context *ev;
3131 : struct cli_state *cli;
3132 : uint16_t fnum;
3133 : };
3134 :
3135 : static void deferred_close_waited(struct tevent_req *subreq);
3136 : static void deferred_close_done(struct tevent_req *subreq);
3137 :
3138 5 : static struct tevent_req *deferred_close_send(
3139 : TALLOC_CTX *mem_ctx,
3140 : struct tevent_context *ev,
3141 : int wait_secs,
3142 : struct cli_state *cli,
3143 : uint16_t fnum)
3144 : {
3145 5 : struct tevent_req *req = NULL, *subreq = NULL;
3146 5 : struct deferred_close_state *state = NULL;
3147 5 : struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
3148 :
3149 5 : req = tevent_req_create(
3150 : mem_ctx, &state, struct deferred_close_state);
3151 5 : if (req == NULL) {
3152 0 : return NULL;
3153 : }
3154 5 : state->ev = ev;
3155 5 : state->cli = cli;
3156 5 : state->fnum = fnum;
3157 :
3158 5 : subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
3159 5 : if (tevent_req_nomem(subreq, req)) {
3160 0 : return tevent_req_post(req, ev);
3161 : }
3162 5 : tevent_req_set_callback(subreq, deferred_close_waited, req);
3163 5 : return req;
3164 : }
3165 :
3166 5 : static void deferred_close_waited(struct tevent_req *subreq)
3167 : {
3168 5 : struct tevent_req *req = tevent_req_callback_data(
3169 : subreq, struct tevent_req);
3170 5 : struct deferred_close_state *state = tevent_req_data(
3171 : req, struct deferred_close_state);
3172 0 : bool ok;
3173 :
3174 5 : ok = tevent_wakeup_recv(subreq);
3175 5 : TALLOC_FREE(subreq);
3176 5 : if (!ok) {
3177 0 : tevent_req_oom(req);
3178 0 : return;
3179 : }
3180 :
3181 5 : subreq = cli_close_send(state, state->ev, state->cli, state->fnum, 0);
3182 5 : if (tevent_req_nomem(subreq, req)) {
3183 0 : return;
3184 : }
3185 5 : tevent_req_set_callback(subreq, deferred_close_done, req);
3186 : }
3187 :
3188 5 : static void deferred_close_done(struct tevent_req *subreq)
3189 : {
3190 5 : NTSTATUS status = cli_close_recv(subreq);
3191 5 : tevent_req_simple_finish_ntstatus(subreq, status);
3192 5 : }
3193 :
3194 5 : static NTSTATUS deferred_close_recv(struct tevent_req *req)
3195 : {
3196 5 : return tevent_req_simple_recv_ntstatus(req);
3197 : }
3198 :
3199 : struct lockread_state {
3200 : struct smb1_lock_element lck;
3201 : struct tevent_req *reqs[2];
3202 : struct tevent_req *smbreqs[2];
3203 : NTSTATUS lock_status;
3204 : NTSTATUS read_status;
3205 : uint8_t *readbuf;
3206 : };
3207 :
3208 : static void lockread_lockingx_done(struct tevent_req *subreq);
3209 : static void lockread_read_andx_done(struct tevent_req *subreq);
3210 :
3211 5 : static struct tevent_req *lockread_send(
3212 : TALLOC_CTX *mem_ctx,
3213 : struct tevent_context *ev,
3214 : struct cli_state *cli,
3215 : uint16_t fnum)
3216 : {
3217 5 : struct tevent_req *req = NULL;
3218 5 : struct lockread_state *state = NULL;
3219 0 : NTSTATUS status;
3220 :
3221 5 : req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3222 5 : if (req == NULL) {
3223 0 : return NULL;
3224 : }
3225 :
3226 10 : state->lck = (struct smb1_lock_element) {
3227 5 : .pid = cli_getpid(cli), .offset = 0, .length = 1,
3228 : };
3229 :
3230 10 : state->reqs[0] = cli_lockingx_create(
3231 : ev, /* mem_ctx */
3232 : ev, /* tevent_context */
3233 : cli, /* cli */
3234 : fnum, /* fnum */
3235 : LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3236 : 0, /* newoplocklevel */
3237 : 10000, /* timeout */
3238 : 0, /* num_unlocks */
3239 : NULL, /* unlocks */
3240 : 1, /* num_locks */
3241 5 : &state->lck, /* locks */
3242 5 : &state->smbreqs[0]); /* psmbreq */
3243 5 : if (tevent_req_nomem(state->reqs[0], req)) {
3244 0 : return tevent_req_post(req, ev);
3245 : }
3246 5 : tevent_req_set_callback(
3247 : state->reqs[0], lockread_lockingx_done, req);
3248 :
3249 10 : state->reqs[1] = cli_read_andx_create(
3250 : ev, /* mem_ctx */
3251 : ev, /* ev */
3252 : cli, /* cli */
3253 : fnum, /* fnum */
3254 : 0, /* offset */
3255 : 1, /* size */
3256 5 : &state->smbreqs[1]); /* psmbreq */
3257 5 : if (tevent_req_nomem(state->reqs[1], req)) {
3258 0 : return tevent_req_post(req, ev);
3259 : }
3260 5 : tevent_req_set_callback(
3261 : state->reqs[1], lockread_read_andx_done, req);
3262 :
3263 5 : status = smb1cli_req_chain_submit(state->smbreqs, 2);
3264 5 : if (tevent_req_nterror(req, status)) {
3265 0 : return tevent_req_post(req, ev);
3266 : }
3267 5 : return req;
3268 : }
3269 :
3270 5 : static void lockread_lockingx_done(struct tevent_req *subreq)
3271 : {
3272 5 : struct tevent_req *req = tevent_req_callback_data(
3273 : subreq, struct tevent_req);
3274 5 : struct lockread_state *state = tevent_req_data(
3275 : req, struct lockread_state);
3276 5 : state->lock_status = cli_lockingx_recv(subreq);
3277 5 : TALLOC_FREE(subreq);
3278 5 : d_fprintf(stderr,
3279 : "lockingx returned %s\n",
3280 : nt_errstr(state->lock_status));
3281 5 : }
3282 :
3283 5 : static void lockread_read_andx_done(struct tevent_req *subreq)
3284 : {
3285 5 : struct tevent_req *req = tevent_req_callback_data(
3286 : subreq, struct tevent_req);
3287 5 : struct lockread_state *state = tevent_req_data(
3288 : req, struct lockread_state);
3289 5 : ssize_t received = -1;
3290 5 : uint8_t *rcvbuf = NULL;
3291 :
3292 5 : state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3293 :
3294 5 : d_fprintf(stderr,
3295 : "read returned %s\n",
3296 : nt_errstr(state->read_status));
3297 :
3298 5 : if (!NT_STATUS_IS_OK(state->read_status)) {
3299 4 : TALLOC_FREE(subreq);
3300 4 : tevent_req_done(req);
3301 4 : return;
3302 : }
3303 :
3304 1 : if (received > 0) {
3305 1 : state->readbuf = talloc_memdup(state, rcvbuf, received);
3306 1 : TALLOC_FREE(subreq);
3307 1 : if (tevent_req_nomem(state->readbuf, req)) {
3308 0 : return;
3309 : }
3310 : }
3311 1 : TALLOC_FREE(subreq);
3312 1 : tevent_req_done(req);
3313 : }
3314 :
3315 5 : static NTSTATUS lockread_recv(
3316 : struct tevent_req *req,
3317 : NTSTATUS *lock_status,
3318 : NTSTATUS *read_status,
3319 : TALLOC_CTX *mem_ctx,
3320 : uint8_t **read_buf)
3321 : {
3322 5 : struct lockread_state *state = tevent_req_data(
3323 : req, struct lockread_state);
3324 0 : NTSTATUS status;
3325 :
3326 5 : if (tevent_req_is_nterror(req, &status)) {
3327 0 : return status;
3328 : }
3329 :
3330 5 : *lock_status = state->lock_status;
3331 5 : *read_status = state->read_status;
3332 5 : if (state->readbuf != NULL) {
3333 1 : *read_buf = talloc_move(mem_ctx, &state->readbuf);
3334 : } else {
3335 4 : *read_buf = NULL;
3336 : }
3337 :
3338 5 : return NT_STATUS_OK;
3339 : }
3340 :
3341 : struct lock12_state {
3342 : uint8_t dummy;
3343 : };
3344 :
3345 : static void lock12_closed(struct tevent_req *subreq);
3346 : static void lock12_read(struct tevent_req *subreq);
3347 :
3348 5 : static struct tevent_req *lock12_send(
3349 : TALLOC_CTX *mem_ctx,
3350 : struct tevent_context *ev,
3351 : struct cli_state *cli,
3352 : uint16_t fnum1,
3353 : uint16_t fnum2)
3354 : {
3355 5 : struct tevent_req *req = NULL, *subreq = NULL;
3356 5 : struct lock12_state *state = NULL;
3357 :
3358 5 : req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3359 5 : if (req == NULL) {
3360 0 : return NULL;
3361 : }
3362 :
3363 5 : subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3364 5 : if (tevent_req_nomem(subreq, req)) {
3365 0 : return tevent_req_post(req, ev);
3366 : }
3367 5 : tevent_req_set_callback(subreq, lock12_closed, req);
3368 :
3369 5 : subreq = lockread_send(state, ev, cli, fnum2);
3370 5 : if (tevent_req_nomem(subreq, req)) {
3371 0 : return tevent_req_post(req, ev);
3372 : }
3373 5 : tevent_req_set_callback(subreq, lock12_read, req);
3374 :
3375 5 : return req;
3376 : }
3377 :
3378 5 : static void lock12_closed(struct tevent_req *subreq)
3379 : {
3380 5 : struct tevent_req *req = tevent_req_callback_data(
3381 : subreq, struct tevent_req);
3382 0 : NTSTATUS status;
3383 :
3384 5 : status = deferred_close_recv(subreq);
3385 5 : TALLOC_FREE(subreq);
3386 5 : DBG_DEBUG("close returned %s\n", nt_errstr(status));
3387 5 : if (tevent_req_nterror(req, status)) {
3388 0 : return;
3389 : }
3390 : }
3391 :
3392 5 : static void lock12_read(struct tevent_req *subreq)
3393 : {
3394 5 : struct tevent_req *req = tevent_req_callback_data(
3395 : subreq, struct tevent_req);
3396 5 : struct lock12_state *state = tevent_req_data(
3397 : req, struct lock12_state);
3398 0 : NTSTATUS status, lock_status, read_status;
3399 5 : uint8_t *buf = NULL;
3400 :
3401 5 : status = lockread_recv(
3402 : subreq, &lock_status, &read_status, state, &buf);
3403 5 : TALLOC_FREE(subreq);
3404 10 : if (tevent_req_nterror(req, status) ||
3405 10 : tevent_req_nterror(req, lock_status) ||
3406 5 : tevent_req_nterror(req, read_status)) {
3407 4 : return;
3408 : }
3409 1 : tevent_req_done(req);
3410 : }
3411 :
3412 5 : static NTSTATUS lock12_recv(struct tevent_req *req)
3413 :
3414 : {
3415 0 : NTSTATUS status;
3416 :
3417 5 : if (tevent_req_is_nterror(req, &status)) {
3418 4 : return status;
3419 : }
3420 1 : return NT_STATUS_OK;
3421 : }
3422 :
3423 5 : static bool run_locktest12(int dummy)
3424 : {
3425 5 : struct tevent_context *ev = NULL;
3426 5 : struct tevent_req *req = NULL;
3427 5 : struct cli_state *cli = NULL;
3428 5 : const char fname[] = "\\lockt12.lck";
3429 0 : uint16_t fnum1, fnum2;
3430 5 : bool ret = false;
3431 0 : bool ok;
3432 5 : uint8_t data = 1;
3433 0 : NTSTATUS status;
3434 :
3435 5 : printf("starting locktest12\n");
3436 :
3437 5 : ev = samba_tevent_context_init(NULL);
3438 5 : if (ev == NULL) {
3439 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
3440 0 : goto done;
3441 : }
3442 :
3443 5 : ok = torture_open_connection(&cli, 0);
3444 5 : if (!ok) {
3445 0 : goto done;
3446 : }
3447 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3448 :
3449 5 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3450 5 : if (!NT_STATUS_IS_OK(status)) {
3451 0 : d_fprintf(stderr,
3452 : "cli_openx failed: %s\n",
3453 : nt_errstr(status));
3454 0 : goto done;
3455 : }
3456 :
3457 5 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3458 5 : if (!NT_STATUS_IS_OK(status)) {
3459 0 : d_fprintf(stderr,
3460 : "cli_openx failed: %s\n",
3461 : nt_errstr(status));
3462 0 : goto done;
3463 : }
3464 :
3465 5 : status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3466 5 : if (!NT_STATUS_IS_OK(status)) {
3467 0 : d_fprintf(stderr,
3468 : "cli_writeall failed: %s\n",
3469 : nt_errstr(status));
3470 0 : goto done;
3471 : }
3472 :
3473 5 : status = cli_locktype(
3474 : cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3475 5 : if (!NT_STATUS_IS_OK(status)) {
3476 0 : d_fprintf(stderr,
3477 : "cli_locktype failed: %s\n",
3478 : nt_errstr(status));
3479 0 : goto done;
3480 : }
3481 :
3482 5 : req = lock12_send(ev, ev, cli, fnum1, fnum2);
3483 5 : if (req == NULL) {
3484 0 : d_fprintf(stderr, "lock12_send failed\n");
3485 0 : goto done;
3486 : }
3487 :
3488 5 : ok = tevent_req_poll_ntstatus(req, ev, &status);
3489 5 : if (!ok) {
3490 0 : d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3491 0 : goto done;
3492 : }
3493 :
3494 5 : if (!NT_STATUS_IS_OK(status)) {
3495 0 : d_fprintf(stderr,
3496 : "tevent_req_poll_ntstatus returned %s\n",
3497 : nt_errstr(status));
3498 0 : goto done;
3499 : }
3500 :
3501 5 : status = lock12_recv(req);
3502 5 : if (!NT_STATUS_IS_OK(status)) {
3503 4 : d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3504 4 : goto done;
3505 : }
3506 :
3507 1 : ret = true;
3508 5 : done:
3509 5 : if (cli != NULL) {
3510 5 : torture_close_connection(cli);
3511 : }
3512 5 : return ret;
3513 : }
3514 :
3515 : struct lock_ntcancel_state {
3516 : struct timeval start;
3517 : struct smb1_lock_element lck;
3518 : struct tevent_req *subreq;
3519 : };
3520 :
3521 : static void lock_ntcancel_waited(struct tevent_req *subreq);
3522 : static void lock_ntcancel_done(struct tevent_req *subreq);
3523 :
3524 5 : static struct tevent_req *lock_ntcancel_send(
3525 : TALLOC_CTX *mem_ctx,
3526 : struct tevent_context *ev,
3527 : struct cli_state *cli,
3528 : uint16_t fnum)
3529 : {
3530 5 : struct tevent_req *req = NULL, *subreq = NULL;
3531 5 : struct lock_ntcancel_state *state = NULL;
3532 :
3533 5 : req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3534 5 : if (req == NULL) {
3535 0 : return NULL;
3536 : }
3537 10 : state->lck = (struct smb1_lock_element) {
3538 5 : .pid = cli_getpid(cli), .offset = 0, .length = 1,
3539 : };
3540 5 : state->start = timeval_current();
3541 :
3542 10 : state->subreq = cli_lockingx_send(
3543 : state, /* mem_ctx */
3544 : ev, /* tevent_context */
3545 : cli, /* cli */
3546 : fnum, /* fnum */
3547 : LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3548 : 0, /* newoplocklevel */
3549 : 10000, /* timeout */
3550 : 0, /* num_unlocks */
3551 : NULL, /* unlocks */
3552 : 1, /* num_locks */
3553 5 : &state->lck); /* locks */
3554 5 : if (tevent_req_nomem(state->subreq, req)) {
3555 0 : return tevent_req_post(req, ev);
3556 : }
3557 5 : tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3558 :
3559 5 : subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3560 5 : if (tevent_req_nomem(subreq, req)) {
3561 0 : return tevent_req_post(req, ev);
3562 : }
3563 5 : tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3564 5 : return req;
3565 : }
3566 :
3567 5 : static void lock_ntcancel_waited(struct tevent_req *subreq)
3568 : {
3569 5 : struct tevent_req *req = tevent_req_callback_data(
3570 : subreq, struct tevent_req);
3571 5 : struct lock_ntcancel_state *state = tevent_req_data(
3572 : req, struct lock_ntcancel_state);
3573 0 : bool ok;
3574 :
3575 5 : ok = tevent_wakeup_recv(subreq);
3576 5 : TALLOC_FREE(subreq);
3577 5 : if (!ok) {
3578 0 : tevent_req_oom(req);
3579 0 : return;
3580 : }
3581 :
3582 5 : ok = tevent_req_cancel(state->subreq);
3583 5 : if (!ok) {
3584 0 : d_fprintf(stderr, "Could not cancel subreq\n");
3585 0 : tevent_req_oom(req);
3586 0 : return;
3587 : }
3588 : }
3589 :
3590 5 : static void lock_ntcancel_done(struct tevent_req *subreq)
3591 : {
3592 5 : struct tevent_req *req = tevent_req_callback_data(
3593 : subreq, struct tevent_req);
3594 5 : struct lock_ntcancel_state *state = tevent_req_data(
3595 : req, struct lock_ntcancel_state);
3596 0 : NTSTATUS status;
3597 0 : double elapsed;
3598 :
3599 5 : status = cli_lockingx_recv(subreq);
3600 5 : TALLOC_FREE(subreq);
3601 :
3602 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3603 0 : d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3604 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3605 0 : return;
3606 : }
3607 :
3608 5 : elapsed = timeval_elapsed(&state->start);
3609 :
3610 5 : if (elapsed > 3) {
3611 0 : d_printf("cli_lockingx was too slow, cancel did not work\n");
3612 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3613 0 : return;
3614 : }
3615 :
3616 5 : tevent_req_done(req);
3617 : }
3618 :
3619 5 : static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3620 : {
3621 5 : return tevent_req_simple_recv_ntstatus(req);
3622 : }
3623 :
3624 5 : static bool run_locktest13(int dummy)
3625 : {
3626 5 : struct tevent_context *ev = NULL;
3627 5 : struct tevent_req *req = NULL;
3628 5 : struct cli_state *cli = NULL;
3629 5 : const char fname[] = "\\lockt13.lck";
3630 0 : uint16_t fnum1, fnum2;
3631 5 : bool ret = false;
3632 0 : bool ok;
3633 5 : uint8_t data = 1;
3634 0 : NTSTATUS status;
3635 :
3636 5 : printf("starting locktest13\n");
3637 :
3638 5 : ev = samba_tevent_context_init(NULL);
3639 5 : if (ev == NULL) {
3640 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
3641 0 : goto done;
3642 : }
3643 :
3644 5 : ok = torture_open_connection(&cli, 0);
3645 5 : if (!ok) {
3646 0 : goto done;
3647 : }
3648 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3649 :
3650 5 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3651 5 : if (!NT_STATUS_IS_OK(status)) {
3652 0 : d_fprintf(stderr,
3653 : "cli_openx failed: %s\n",
3654 : nt_errstr(status));
3655 0 : goto done;
3656 : }
3657 :
3658 5 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3659 5 : if (!NT_STATUS_IS_OK(status)) {
3660 0 : d_fprintf(stderr,
3661 : "cli_openx failed: %s\n",
3662 : nt_errstr(status));
3663 0 : goto done;
3664 : }
3665 :
3666 5 : status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3667 5 : if (!NT_STATUS_IS_OK(status)) {
3668 0 : d_fprintf(stderr,
3669 : "cli_writeall failed: %s\n",
3670 : nt_errstr(status));
3671 0 : goto done;
3672 : }
3673 :
3674 5 : status = cli_locktype(
3675 : cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3676 5 : if (!NT_STATUS_IS_OK(status)) {
3677 0 : d_fprintf(stderr,
3678 : "cli_locktype failed: %s\n",
3679 : nt_errstr(status));
3680 0 : goto done;
3681 : }
3682 :
3683 5 : req = lock_ntcancel_send(ev, ev, cli, fnum2);
3684 5 : if (req == NULL) {
3685 0 : d_fprintf(stderr, "lock_ntcancel_send failed\n");
3686 0 : goto done;
3687 : }
3688 :
3689 5 : ok = tevent_req_poll_ntstatus(req, ev, &status);
3690 5 : if (!ok) {
3691 0 : d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3692 0 : goto done;
3693 : }
3694 :
3695 5 : if (!NT_STATUS_IS_OK(status)) {
3696 0 : d_fprintf(stderr,
3697 : "tevent_req_poll_ntstatus returned %s\n",
3698 : nt_errstr(status));
3699 0 : goto done;
3700 : }
3701 :
3702 5 : status = lock_ntcancel_recv(req);
3703 5 : if (!NT_STATUS_IS_OK(status)) {
3704 0 : d_fprintf(stderr,
3705 : "lock_ntcancel returned %s\n",
3706 : nt_errstr(status));
3707 0 : goto done;
3708 : }
3709 :
3710 5 : ret = true;
3711 5 : done:
3712 5 : if (cli != NULL) {
3713 5 : torture_close_connection(cli);
3714 : }
3715 5 : return ret;
3716 : }
3717 :
3718 : /*
3719 : test whether fnums and tids open on one VC are available on another (a major
3720 : security hole)
3721 : */
3722 5 : static bool run_fdpasstest(int dummy)
3723 : {
3724 0 : struct cli_state *cli1, *cli2;
3725 5 : const char *fname = "\\fdpass.tst";
3726 0 : uint16_t fnum1;
3727 0 : char buf[1024];
3728 0 : NTSTATUS status;
3729 :
3730 5 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3731 0 : return False;
3732 : }
3733 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
3734 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
3735 :
3736 5 : printf("starting fdpasstest\n");
3737 :
3738 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3739 :
3740 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3741 : &fnum1);
3742 5 : if (!NT_STATUS_IS_OK(status)) {
3743 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3744 0 : return False;
3745 : }
3746 :
3747 5 : status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3748 : 13, NULL);
3749 5 : if (!NT_STATUS_IS_OK(status)) {
3750 0 : printf("write failed (%s)\n", nt_errstr(status));
3751 0 : return False;
3752 : }
3753 :
3754 5 : cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3755 5 : cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3756 5 : cli_setpid(cli2, cli_getpid(cli1));
3757 :
3758 5 : if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3759 0 : printf("read succeeded! nasty security hole [%s]\n", buf);
3760 0 : return false;
3761 : }
3762 :
3763 5 : cli_close(cli1, fnum1);
3764 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3765 :
3766 5 : torture_close_connection(cli1);
3767 5 : torture_close_connection(cli2);
3768 :
3769 5 : printf("finished fdpasstest\n");
3770 5 : return True;
3771 : }
3772 :
3773 5 : static bool run_fdsesstest(int dummy)
3774 : {
3775 0 : struct cli_state *cli;
3776 0 : uint16_t new_vuid;
3777 0 : uint16_t saved_vuid;
3778 0 : uint32_t new_cnum;
3779 0 : uint32_t saved_cnum;
3780 5 : const char *fname = "\\fdsess.tst";
3781 5 : const char *fname1 = "\\fdsess1.tst";
3782 0 : uint16_t fnum1;
3783 0 : uint16_t fnum2;
3784 0 : char buf[1024];
3785 5 : bool ret = True;
3786 0 : NTSTATUS status;
3787 :
3788 5 : if (!torture_open_connection(&cli, 0))
3789 0 : return False;
3790 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3791 :
3792 5 : if (!torture_cli_session_setup2(cli, &new_vuid))
3793 0 : return False;
3794 :
3795 5 : saved_cnum = cli_state_get_tid(cli);
3796 5 : if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3797 0 : return False;
3798 5 : new_cnum = cli_state_get_tid(cli);
3799 5 : cli_state_set_tid(cli, saved_cnum);
3800 :
3801 5 : printf("starting fdsesstest\n");
3802 :
3803 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3804 5 : cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3805 :
3806 5 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3807 5 : if (!NT_STATUS_IS_OK(status)) {
3808 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3809 0 : return False;
3810 : }
3811 :
3812 5 : status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3813 : NULL);
3814 5 : if (!NT_STATUS_IS_OK(status)) {
3815 0 : printf("write failed (%s)\n", nt_errstr(status));
3816 0 : return False;
3817 : }
3818 :
3819 5 : saved_vuid = cli_state_get_uid(cli);
3820 5 : cli_state_set_uid(cli, new_vuid);
3821 :
3822 5 : if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3823 0 : printf("read succeeded with different vuid! "
3824 : "nasty security hole [%s]\n", buf);
3825 0 : ret = false;
3826 : }
3827 : /* Try to open a file with different vuid, samba cnum. */
3828 5 : if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3829 5 : printf("create with different vuid, same cnum succeeded.\n");
3830 5 : cli_close(cli, fnum2);
3831 5 : cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3832 : } else {
3833 0 : printf("create with different vuid, same cnum failed.\n");
3834 0 : printf("This will cause problems with service clients.\n");
3835 0 : ret = False;
3836 : }
3837 :
3838 5 : cli_state_set_uid(cli, saved_vuid);
3839 :
3840 : /* Try with same vuid, different cnum. */
3841 5 : cli_state_set_tid(cli, new_cnum);
3842 :
3843 5 : if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3844 0 : printf("read succeeded with different cnum![%s]\n", buf);
3845 0 : ret = false;
3846 : }
3847 :
3848 5 : cli_state_set_tid(cli, saved_cnum);
3849 5 : cli_close(cli, fnum1);
3850 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3851 :
3852 5 : torture_close_connection(cli);
3853 :
3854 5 : printf("finished fdsesstest\n");
3855 5 : return ret;
3856 : }
3857 :
3858 : /*
3859 : This test checks that
3860 :
3861 : 1) the server does not allow an unlink on a file that is open
3862 : */
3863 5 : static bool run_unlinktest(int dummy)
3864 : {
3865 0 : struct cli_state *cli;
3866 5 : const char *fname = "\\unlink.tst";
3867 0 : uint16_t fnum;
3868 5 : bool correct = True;
3869 0 : NTSTATUS status;
3870 :
3871 5 : if (!torture_open_connection(&cli, 0)) {
3872 0 : return False;
3873 : }
3874 :
3875 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3876 :
3877 5 : printf("starting unlink test\n");
3878 :
3879 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3880 :
3881 5 : cli_setpid(cli, 1);
3882 :
3883 5 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3884 5 : if (!NT_STATUS_IS_OK(status)) {
3885 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3886 0 : return False;
3887 : }
3888 :
3889 5 : status = cli_unlink(cli, fname,
3890 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3891 5 : if (NT_STATUS_IS_OK(status)) {
3892 0 : printf("error: server allowed unlink on an open file\n");
3893 0 : correct = False;
3894 : } else {
3895 5 : correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3896 5 : NT_STATUS_SHARING_VIOLATION);
3897 : }
3898 :
3899 5 : cli_close(cli, fnum);
3900 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3901 :
3902 5 : if (!torture_close_connection(cli)) {
3903 0 : correct = False;
3904 : }
3905 :
3906 5 : printf("unlink test finished\n");
3907 :
3908 5 : return correct;
3909 : }
3910 :
3911 :
3912 : /*
3913 : test how many open files this server supports on the one socket
3914 : */
3915 0 : static bool run_maxfidtest(int dummy)
3916 : {
3917 0 : struct cli_state *cli;
3918 0 : fstring fname;
3919 0 : uint16_t fnums[0x11000];
3920 0 : int i;
3921 0 : int retries=4;
3922 0 : bool correct = True;
3923 0 : NTSTATUS status;
3924 :
3925 0 : cli = current_cli;
3926 :
3927 0 : if (retries <= 0) {
3928 0 : printf("failed to connect\n");
3929 0 : return False;
3930 : }
3931 :
3932 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3933 :
3934 0 : for (i=0; i<0x11000; i++) {
3935 0 : slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3936 0 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3937 : &fnums[i]);
3938 0 : if (!NT_STATUS_IS_OK(status)) {
3939 0 : printf("open of %s failed (%s)\n",
3940 : fname, nt_errstr(status));
3941 0 : printf("maximum fnum is %d\n", i);
3942 0 : break;
3943 : }
3944 0 : printf("%6d\r", i);
3945 : }
3946 0 : printf("%6d\n", i);
3947 0 : i--;
3948 :
3949 0 : printf("cleaning up\n");
3950 0 : for (;i>=0;i--) {
3951 0 : slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3952 0 : cli_close(cli, fnums[i]);
3953 :
3954 0 : status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3955 0 : if (!NT_STATUS_IS_OK(status)) {
3956 0 : printf("unlink of %s failed (%s)\n",
3957 : fname, nt_errstr(status));
3958 0 : correct = False;
3959 : }
3960 0 : printf("%6d\r", i);
3961 : }
3962 0 : printf("%6d\n", 0);
3963 :
3964 0 : printf("maxfid test finished\n");
3965 0 : if (!torture_close_connection(cli)) {
3966 0 : correct = False;
3967 : }
3968 0 : return correct;
3969 : }
3970 :
3971 : /* generate a random buffer */
3972 0 : static void rand_buf(char *buf, int len)
3973 : {
3974 0 : while (len--) {
3975 0 : *buf = (char)sys_random();
3976 0 : buf++;
3977 : }
3978 0 : }
3979 :
3980 : /* send smb negprot commands, not reading the response */
3981 0 : static bool run_negprot_nowait(int dummy)
3982 : {
3983 0 : struct tevent_context *ev;
3984 0 : int i;
3985 0 : struct cli_state *cli;
3986 0 : bool correct = True;
3987 :
3988 0 : printf("starting negprot nowait test\n");
3989 :
3990 0 : ev = samba_tevent_context_init(talloc_tos());
3991 0 : if (ev == NULL) {
3992 0 : return false;
3993 : }
3994 :
3995 0 : if (!(cli = open_nbt_connection())) {
3996 0 : TALLOC_FREE(ev);
3997 0 : return False;
3998 : }
3999 :
4000 0 : for (i=0;i<50000;i++) {
4001 0 : struct tevent_req *req;
4002 :
4003 0 : req = smbXcli_negprot_send(
4004 : ev,
4005 : ev,
4006 : cli->conn,
4007 0 : cli->timeout,
4008 : PROTOCOL_CORE,
4009 : PROTOCOL_NT1,
4010 : 0,
4011 : NULL);
4012 0 : if (req == NULL) {
4013 0 : TALLOC_FREE(ev);
4014 0 : return false;
4015 : }
4016 0 : if (!tevent_req_poll(req, ev)) {
4017 0 : d_fprintf(stderr, "tevent_req_poll failed: %s\n",
4018 0 : strerror(errno));
4019 0 : TALLOC_FREE(ev);
4020 0 : return false;
4021 : }
4022 0 : TALLOC_FREE(req);
4023 : }
4024 :
4025 0 : if (torture_close_connection(cli)) {
4026 0 : correct = False;
4027 : }
4028 :
4029 0 : printf("finished negprot nowait test\n");
4030 :
4031 0 : return correct;
4032 : }
4033 :
4034 : /* send smb negprot commands, not reading the response */
4035 4 : static bool run_bad_nbt_session(int dummy)
4036 : {
4037 0 : struct nmb_name called, calling;
4038 0 : struct sockaddr_storage ss;
4039 0 : NTSTATUS status;
4040 0 : int fd;
4041 0 : bool ret;
4042 :
4043 4 : printf("starting bad nbt session test\n");
4044 :
4045 4 : make_nmb_name(&calling, myname, 0x0);
4046 4 : make_nmb_name(&called , host, 0x20);
4047 :
4048 4 : if (!resolve_name(host, &ss, 0x20, true)) {
4049 0 : d_fprintf(stderr, "Could not resolve name %s\n", host);
4050 0 : return false;
4051 : }
4052 :
4053 4 : status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4054 4 : if (!NT_STATUS_IS_OK(status)) {
4055 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
4056 : nt_errstr(status));
4057 0 : return false;
4058 : }
4059 :
4060 4 : ret = cli_bad_session_request(fd, &calling, &called);
4061 4 : close(fd);
4062 4 : if (!ret) {
4063 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
4064 : nt_errstr(status));
4065 0 : return false;
4066 : }
4067 :
4068 4 : printf("finished bad nbt session test\n");
4069 4 : return true;
4070 : }
4071 :
4072 : /* send random IPC commands */
4073 0 : static bool run_randomipc(int dummy)
4074 : {
4075 0 : char *rparam = NULL;
4076 0 : char *rdata = NULL;
4077 0 : unsigned int rdrcnt,rprcnt;
4078 0 : char param[1024];
4079 0 : int api, param_len, i;
4080 0 : struct cli_state *cli;
4081 0 : bool correct = True;
4082 0 : int count = 50000;
4083 :
4084 0 : printf("starting random ipc test\n");
4085 :
4086 0 : if (!torture_open_connection(&cli, 0)) {
4087 0 : return False;
4088 : }
4089 :
4090 0 : for (i=0;i<count;i++) {
4091 0 : api = sys_random() % 500;
4092 0 : param_len = (sys_random() % 64);
4093 :
4094 0 : rand_buf(param, param_len);
4095 :
4096 0 : SSVAL(param,0,api);
4097 :
4098 0 : cli_api(cli,
4099 : param, param_len, 8,
4100 : NULL, 0, CLI_BUFFER_SIZE,
4101 : &rparam, &rprcnt,
4102 : &rdata, &rdrcnt);
4103 0 : if (i % 100 == 0) {
4104 0 : printf("%d/%d\r", i,count);
4105 : }
4106 : }
4107 0 : printf("%d/%d\n", i, count);
4108 :
4109 0 : if (!torture_close_connection(cli)) {
4110 0 : correct = False;
4111 : }
4112 :
4113 0 : SAFE_FREE(rparam);
4114 0 : SAFE_FREE(rdata);
4115 :
4116 0 : printf("finished random ipc test\n");
4117 :
4118 0 : return correct;
4119 : }
4120 :
4121 :
4122 :
4123 8 : static void browse_callback(const char *sname, uint32_t stype,
4124 : const char *comment, void *state)
4125 : {
4126 8 : printf("\t%20.20s %08x %s\n", sname, stype, comment);
4127 8 : }
4128 :
4129 :
4130 :
4131 : /*
4132 : This test checks the browse list code
4133 :
4134 : */
4135 5 : static bool run_browsetest(int dummy)
4136 : {
4137 0 : static struct cli_state *cli;
4138 5 : bool correct = True;
4139 :
4140 5 : printf("starting browse test\n");
4141 :
4142 5 : if (!torture_open_connection(&cli, 0)) {
4143 0 : return False;
4144 : }
4145 :
4146 5 : printf("domain list:\n");
4147 5 : cli_NetServerEnum(cli, cli->server_domain,
4148 : SV_TYPE_DOMAIN_ENUM,
4149 : browse_callback, NULL);
4150 :
4151 5 : printf("machine list:\n");
4152 5 : cli_NetServerEnum(cli, cli->server_domain,
4153 : SV_TYPE_ALL,
4154 : browse_callback, NULL);
4155 :
4156 5 : if (!torture_close_connection(cli)) {
4157 0 : correct = False;
4158 : }
4159 :
4160 5 : printf("browse test finished\n");
4161 :
4162 5 : return correct;
4163 :
4164 : }
4165 :
4166 20 : static bool check_attributes(struct cli_state *cli,
4167 : const char *fname,
4168 : uint32_t expected_attrs)
4169 : {
4170 20 : uint32_t attrs = 0;
4171 20 : NTSTATUS status = cli_getatr(cli,
4172 : fname,
4173 : &attrs,
4174 : NULL,
4175 : NULL);
4176 20 : if (!NT_STATUS_IS_OK(status)) {
4177 0 : printf("cli_getatr failed with %s\n",
4178 : nt_errstr(status));
4179 0 : return false;
4180 : }
4181 20 : if (attrs != expected_attrs) {
4182 0 : printf("Attributes incorrect 0x%x, should be 0x%x\n",
4183 : (unsigned int)attrs,
4184 : (unsigned int)expected_attrs);
4185 0 : return false;
4186 : }
4187 20 : return true;
4188 : }
4189 :
4190 : /*
4191 : This checks how the getatr calls works
4192 : */
4193 5 : static bool run_attrtest(int dummy)
4194 : {
4195 0 : struct cli_state *cli;
4196 0 : uint16_t fnum;
4197 0 : time_t t, t2;
4198 5 : const char *fname = "\\attrib123456789.tst";
4199 5 : bool correct = True;
4200 0 : NTSTATUS status;
4201 :
4202 5 : printf("starting attrib test\n");
4203 :
4204 5 : if (!torture_open_connection(&cli, 0)) {
4205 0 : return False;
4206 : }
4207 :
4208 : /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4209 5 : status = cli_unlink(cli, fname, 0x20000);
4210 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4211 0 : correct = false;
4212 0 : goto out;
4213 : }
4214 :
4215 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4216 5 : cli_openx(cli, fname,
4217 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4218 5 : cli_close(cli, fnum);
4219 :
4220 5 : status = cli_getatr(cli, fname, NULL, NULL, &t);
4221 5 : if (!NT_STATUS_IS_OK(status)) {
4222 0 : printf("getatr failed (%s)\n", nt_errstr(status));
4223 0 : correct = False;
4224 : }
4225 :
4226 5 : if (labs(t - time(NULL)) > 60*60*24*10) {
4227 0 : printf("ERROR: SMBgetatr bug. time is %s",
4228 : ctime(&t));
4229 0 : t = time(NULL);
4230 0 : correct = True;
4231 : }
4232 :
4233 5 : t2 = t-60*60*24; /* 1 day ago */
4234 :
4235 : /* Ensure we can't set with out-of-range (unknown) attribute. */
4236 5 : status = cli_setatr(cli, fname, 0x20000, t2);
4237 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4238 0 : correct = false;
4239 0 : goto out;
4240 : }
4241 :
4242 5 : status = cli_setatr(cli, fname, 0, t2);
4243 5 : if (!NT_STATUS_IS_OK(status)) {
4244 0 : printf("setatr failed (%s)\n", nt_errstr(status));
4245 0 : correct = True;
4246 : }
4247 :
4248 5 : status = cli_getatr(cli, fname, NULL, NULL, &t);
4249 5 : if (!NT_STATUS_IS_OK(status)) {
4250 0 : printf("getatr failed (%s)\n", nt_errstr(status));
4251 0 : correct = True;
4252 : }
4253 :
4254 5 : if (t != t2) {
4255 0 : printf("ERROR: getatr/setatr bug. times are\n%s",
4256 : ctime(&t));
4257 0 : printf("%s", ctime(&t2));
4258 0 : correct = True;
4259 : }
4260 :
4261 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4262 :
4263 : /* Check cli_setpathinfo_ext() */
4264 : /* Re-create the file. */
4265 5 : status = cli_openx(cli, fname,
4266 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4267 5 : if (!NT_STATUS_IS_OK(status)) {
4268 0 : printf("Failed to recreate %s (%s)\n",
4269 : fname, nt_errstr(status));
4270 0 : correct = false;
4271 : }
4272 5 : cli_close(cli, fnum);
4273 :
4274 5 : status = cli_setpathinfo_ext(
4275 : cli,
4276 : fname,
4277 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4278 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4279 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4280 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4281 : FILE_ATTRIBUTE_SYSTEM |
4282 : FILE_ATTRIBUTE_HIDDEN |
4283 : FILE_ATTRIBUTE_READONLY);
4284 5 : if (!NT_STATUS_IS_OK(status)) {
4285 0 : printf("cli_setpathinfo_ext failed with %s\n",
4286 : nt_errstr(status));
4287 0 : correct = false;
4288 : }
4289 :
4290 : /* Check attributes are correct. */
4291 5 : correct = check_attributes(cli,
4292 : fname,
4293 : FILE_ATTRIBUTE_SYSTEM |
4294 : FILE_ATTRIBUTE_HIDDEN |
4295 : FILE_ATTRIBUTE_READONLY);
4296 5 : if (correct == false) {
4297 0 : goto out;
4298 : }
4299 :
4300 : /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4301 5 : status = cli_setpathinfo_ext(
4302 : cli,
4303 : fname,
4304 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4305 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4306 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4307 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4308 : FILE_ATTRIBUTE_NORMAL);
4309 5 : if (!NT_STATUS_IS_OK(status)) {
4310 0 : printf("cli_setpathinfo_ext failed with %s\n",
4311 : nt_errstr(status));
4312 0 : correct = false;
4313 : }
4314 :
4315 : /* Check attributes are correct. */
4316 5 : correct = check_attributes(cli,
4317 : fname,
4318 : FILE_ATTRIBUTE_SYSTEM |
4319 : FILE_ATTRIBUTE_HIDDEN |
4320 : FILE_ATTRIBUTE_READONLY);
4321 5 : if (correct == false) {
4322 0 : goto out;
4323 : }
4324 :
4325 : /* Setting to (uint16_t)-1 should also be ignored. */
4326 5 : status = cli_setpathinfo_ext(
4327 : cli,
4328 : fname,
4329 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4330 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4331 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4332 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4333 : (uint32_t)-1);
4334 5 : if (!NT_STATUS_IS_OK(status)) {
4335 0 : printf("cli_setpathinfo_ext failed with %s\n",
4336 : nt_errstr(status));
4337 0 : correct = false;
4338 : }
4339 :
4340 : /* Check attributes are correct. */
4341 5 : correct = check_attributes(cli,
4342 : fname,
4343 : FILE_ATTRIBUTE_SYSTEM |
4344 : FILE_ATTRIBUTE_HIDDEN |
4345 : FILE_ATTRIBUTE_READONLY);
4346 5 : if (correct == false) {
4347 0 : goto out;
4348 : }
4349 :
4350 : /* Setting to 0 should clear them all. */
4351 5 : status = cli_setpathinfo_ext(
4352 : cli,
4353 : fname,
4354 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4355 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4356 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4357 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4358 : 0);
4359 5 : if (!NT_STATUS_IS_OK(status)) {
4360 0 : printf("cli_setpathinfo_ext failed with %s\n",
4361 : nt_errstr(status));
4362 0 : correct = false;
4363 : }
4364 :
4365 : /* Check attributes are correct. */
4366 5 : correct = check_attributes(cli,
4367 : fname,
4368 : FILE_ATTRIBUTE_NORMAL);
4369 5 : if (correct == false) {
4370 0 : goto out;
4371 : }
4372 :
4373 5 : out:
4374 :
4375 5 : cli_unlink(cli,
4376 : fname,
4377 : FILE_ATTRIBUTE_SYSTEM |
4378 : FILE_ATTRIBUTE_HIDDEN|
4379 : FILE_ATTRIBUTE_READONLY);
4380 :
4381 5 : if (!torture_close_connection(cli)) {
4382 0 : correct = False;
4383 : }
4384 :
4385 5 : printf("attrib test finished\n");
4386 :
4387 5 : return correct;
4388 : }
4389 :
4390 5 : static NTSTATUS cli_qfilename(
4391 : struct cli_state *cli,
4392 : uint16_t fnum,
4393 : TALLOC_CTX *mem_ctx,
4394 : char **_name)
4395 : {
4396 0 : uint16_t recv_flags2;
4397 0 : uint8_t *rdata;
4398 0 : uint32_t num_rdata;
4399 0 : NTSTATUS status;
4400 5 : char *name = NULL;
4401 0 : uint32_t namelen;
4402 :
4403 5 : status = cli_qfileinfo(talloc_tos(), cli, fnum,
4404 : SMB_QUERY_FILE_NAME_INFO,
4405 : 4, CLI_BUFFER_SIZE, &recv_flags2,
4406 : &rdata, &num_rdata);
4407 5 : if (!NT_STATUS_IS_OK(status)) {
4408 0 : return status;
4409 : }
4410 :
4411 5 : namelen = IVAL(rdata, 0);
4412 5 : if (namelen > (num_rdata - 4)) {
4413 0 : TALLOC_FREE(rdata);
4414 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
4415 : }
4416 :
4417 5 : pull_string_talloc(mem_ctx,
4418 : (const char *)rdata,
4419 : recv_flags2,
4420 : &name,
4421 5 : rdata + 4,
4422 : namelen,
4423 : STR_UNICODE);
4424 5 : if (name == NULL) {
4425 0 : status = map_nt_error_from_unix(errno);
4426 0 : TALLOC_FREE(rdata);
4427 0 : return status;
4428 : }
4429 :
4430 5 : *_name = name;
4431 5 : TALLOC_FREE(rdata);
4432 5 : return NT_STATUS_OK;
4433 : }
4434 :
4435 : /*
4436 : This checks a couple of trans2 calls
4437 : */
4438 5 : static bool run_trans2test(int dummy)
4439 : {
4440 0 : struct cli_state *cli;
4441 0 : uint16_t fnum;
4442 0 : off_t size;
4443 0 : time_t c_time, a_time, m_time;
4444 0 : struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4445 5 : const char *fname = "\\trans2.tst";
4446 5 : const char *dname = "\\trans2";
4447 5 : const char *fname2 = "\\trans2\\trans2.tst";
4448 5 : char *pname = NULL;
4449 5 : bool correct = True;
4450 0 : NTSTATUS status;
4451 0 : uint32_t fs_attr;
4452 0 : uint64_t ino;
4453 :
4454 5 : printf("starting trans2 test\n");
4455 :
4456 5 : if (!torture_open_connection(&cli, 0)) {
4457 0 : return False;
4458 : }
4459 :
4460 5 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4461 : /* Ensure ino is zero, SMB2 gets a real one. */
4462 0 : ino = 0;
4463 : } else {
4464 : /* Ensure ino is -1, SMB1 never gets a real one. */
4465 5 : ino = (uint64_t)-1;
4466 : }
4467 :
4468 5 : status = cli_get_fs_attr_info(cli, &fs_attr);
4469 5 : if (!NT_STATUS_IS_OK(status)) {
4470 0 : printf("ERROR: cli_get_fs_attr_info returned %s\n",
4471 : nt_errstr(status));
4472 0 : correct = false;
4473 : }
4474 :
4475 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4476 5 : cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4477 5 : status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4478 : &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4479 5 : if (!NT_STATUS_IS_OK(status)) {
4480 0 : printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4481 0 : correct = False;
4482 : }
4483 :
4484 5 : status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4485 5 : if (!NT_STATUS_IS_OK(status)) {
4486 0 : printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4487 0 : correct = False;
4488 : }
4489 5 : else if (strcmp(pname, fname)) {
4490 0 : printf("qfilename gave different name? [%s] [%s]\n",
4491 : fname, pname);
4492 0 : correct = False;
4493 : }
4494 :
4495 5 : cli_close(cli, fnum);
4496 :
4497 5 : sleep(2);
4498 :
4499 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4500 5 : status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4501 : &fnum);
4502 5 : if (!NT_STATUS_IS_OK(status)) {
4503 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4504 0 : return False;
4505 : }
4506 5 : cli_close(cli, fnum);
4507 :
4508 5 : status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4509 : NULL);
4510 5 : if (!NT_STATUS_IS_OK(status)) {
4511 0 : printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4512 0 : correct = False;
4513 : } else {
4514 5 : time_t t = time(NULL);
4515 :
4516 5 : if (c_time != m_time) {
4517 0 : printf("create time=%s", ctime(&c_time));
4518 0 : printf("modify time=%s", ctime(&m_time));
4519 0 : printf("This system appears to have sticky create times\n");
4520 : }
4521 5 : if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4522 0 : printf("access time=%s", ctime(&a_time));
4523 0 : printf("This system appears to set a midnight access time\n");
4524 0 : correct = False;
4525 : }
4526 :
4527 5 : if (labs(m_time - t) > 60*60*24*7) {
4528 0 : printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4529 0 : correct = False;
4530 : }
4531 : }
4532 :
4533 :
4534 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4535 5 : cli_openx(cli, fname,
4536 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4537 5 : cli_close(cli, fnum);
4538 5 : status = cli_qpathinfo2(cli,
4539 : fname,
4540 : &c_time_ts,
4541 : &a_time_ts,
4542 : &w_time_ts,
4543 : &m_time_ts,
4544 : &size,
4545 : NULL,
4546 : &ino,
4547 : NULL);
4548 5 : if (!NT_STATUS_IS_OK(status)) {
4549 0 : printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4550 0 : correct = False;
4551 : } else {
4552 5 : if (w_time_ts.tv_sec < 60*60*24*2) {
4553 0 : printf("write time=%s", ctime(&w_time_ts.tv_sec));
4554 0 : printf("This system appears to set a initial 0 write time\n");
4555 0 : correct = False;
4556 : }
4557 5 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4558 : /* SMB2 should always return an inode. */
4559 0 : if (ino == 0) {
4560 0 : printf("SMB2 bad inode (0)\n");
4561 0 : correct = false;
4562 : }
4563 : } else {
4564 : /* SMB1 must always return zero here. */
4565 5 : if (ino != 0) {
4566 0 : printf("SMB1 bad inode (!0)\n");
4567 0 : correct = false;
4568 : }
4569 : }
4570 : }
4571 :
4572 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4573 :
4574 :
4575 : /* check if the server updates the directory modification time
4576 : when creating a new file */
4577 5 : status = cli_mkdir(cli, dname);
4578 5 : if (!NT_STATUS_IS_OK(status)) {
4579 0 : printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4580 0 : correct = False;
4581 : }
4582 5 : sleep(3);
4583 5 : status = cli_qpathinfo2(cli,
4584 : "\\trans2\\",
4585 : &c_time_ts,
4586 : &a_time_ts,
4587 : &w_time_ts,
4588 : &m_time_ts,
4589 : &size,
4590 : NULL,
4591 : NULL,
4592 : NULL);
4593 5 : if (!NT_STATUS_IS_OK(status)) {
4594 0 : printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4595 0 : correct = False;
4596 : }
4597 :
4598 5 : cli_openx(cli, fname2,
4599 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4600 5 : cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4601 5 : cli_close(cli, fnum);
4602 5 : status = cli_qpathinfo2(cli,
4603 : "\\trans2\\",
4604 : &c_time_ts,
4605 : &a_time_ts,
4606 : &w_time_ts,
4607 : &m_time2_ts,
4608 : &size,
4609 : NULL,
4610 : NULL,
4611 : NULL);
4612 5 : if (!NT_STATUS_IS_OK(status)) {
4613 0 : printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4614 0 : correct = False;
4615 : } else {
4616 5 : if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4617 : == 0) {
4618 0 : printf("This system does not update directory modification times\n");
4619 0 : correct = False;
4620 : }
4621 : }
4622 5 : cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4623 5 : cli_rmdir(cli, dname);
4624 :
4625 5 : if (!torture_close_connection(cli)) {
4626 0 : correct = False;
4627 : }
4628 :
4629 5 : printf("trans2 test finished\n");
4630 :
4631 5 : return correct;
4632 : }
4633 :
4634 : /*
4635 : This checks new W2K calls.
4636 : */
4637 :
4638 180 : static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4639 : {
4640 180 : uint8_t *buf = NULL;
4641 0 : uint32_t len;
4642 0 : NTSTATUS status;
4643 :
4644 180 : status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4645 : CLI_BUFFER_SIZE, NULL, &buf, &len);
4646 180 : if (!NT_STATUS_IS_OK(status)) {
4647 180 : printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4648 : nt_errstr(status));
4649 : } else {
4650 0 : printf("qfileinfo: level %d, len = %u\n", level, len);
4651 0 : dump_data(0, (uint8_t *)buf, len);
4652 0 : printf("\n");
4653 : }
4654 180 : TALLOC_FREE(buf);
4655 180 : return status;
4656 : }
4657 :
4658 5 : static bool run_w2ktest(int dummy)
4659 : {
4660 0 : struct cli_state *cli;
4661 0 : uint16_t fnum;
4662 5 : const char *fname = "\\w2ktest\\w2k.tst";
4663 0 : int level;
4664 5 : bool correct = True;
4665 :
4666 5 : printf("starting w2k test\n");
4667 :
4668 5 : if (!torture_open_connection(&cli, 0)) {
4669 0 : return False;
4670 : }
4671 :
4672 5 : cli_openx(cli, fname,
4673 : O_RDWR | O_CREAT , DENY_NONE, &fnum);
4674 :
4675 185 : for (level = 1004; level < 1040; level++) {
4676 180 : new_trans(cli, fnum, level);
4677 : }
4678 :
4679 5 : cli_close(cli, fnum);
4680 :
4681 5 : if (!torture_close_connection(cli)) {
4682 0 : correct = False;
4683 : }
4684 :
4685 5 : printf("w2k test finished\n");
4686 :
4687 5 : return correct;
4688 : }
4689 :
4690 :
4691 : /*
4692 : this is a harness for some oplock tests
4693 : */
4694 5 : static bool run_oplock1(int dummy)
4695 : {
4696 0 : struct cli_state *cli1;
4697 5 : const char *fname = "\\lockt1.lck";
4698 0 : uint16_t fnum1;
4699 5 : bool correct = True;
4700 0 : NTSTATUS status;
4701 :
4702 5 : printf("starting oplock test 1\n");
4703 :
4704 5 : if (!torture_open_connection(&cli1, 0)) {
4705 0 : return False;
4706 : }
4707 :
4708 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4709 :
4710 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
4711 :
4712 5 : cli1->use_oplocks = True;
4713 :
4714 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4715 : &fnum1);
4716 5 : if (!NT_STATUS_IS_OK(status)) {
4717 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4718 0 : return False;
4719 : }
4720 :
4721 5 : cli1->use_oplocks = False;
4722 :
4723 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4724 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4725 :
4726 5 : status = cli_close(cli1, fnum1);
4727 5 : if (!NT_STATUS_IS_OK(status)) {
4728 0 : printf("close2 failed (%s)\n", nt_errstr(status));
4729 0 : return False;
4730 : }
4731 :
4732 5 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4733 5 : if (!NT_STATUS_IS_OK(status)) {
4734 0 : printf("unlink failed (%s)\n", nt_errstr(status));
4735 0 : return False;
4736 : }
4737 :
4738 5 : if (!torture_close_connection(cli1)) {
4739 0 : correct = False;
4740 : }
4741 :
4742 5 : printf("finished oplock test 1\n");
4743 :
4744 5 : return correct;
4745 : }
4746 :
4747 4 : static bool run_oplock2(int dummy)
4748 : {
4749 0 : struct cli_state *cli1, *cli2;
4750 4 : const char *fname = "\\lockt2.lck";
4751 0 : uint16_t fnum1, fnum2;
4752 4 : int saved_use_oplocks = use_oplocks;
4753 0 : char buf[4];
4754 4 : bool correct = True;
4755 0 : volatile bool *shared_correct;
4756 0 : size_t nread;
4757 0 : NTSTATUS status;
4758 :
4759 4 : shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4760 4 : *shared_correct = True;
4761 :
4762 4 : use_level_II_oplocks = True;
4763 4 : use_oplocks = True;
4764 :
4765 4 : printf("starting oplock test 2\n");
4766 :
4767 4 : if (!torture_open_connection(&cli1, 0)) {
4768 0 : use_level_II_oplocks = False;
4769 0 : use_oplocks = saved_use_oplocks;
4770 0 : return False;
4771 : }
4772 :
4773 4 : if (!torture_open_connection(&cli2, 1)) {
4774 0 : use_level_II_oplocks = False;
4775 0 : use_oplocks = saved_use_oplocks;
4776 0 : return False;
4777 : }
4778 :
4779 4 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4780 :
4781 4 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
4782 4 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
4783 :
4784 4 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4785 : &fnum1);
4786 4 : if (!NT_STATUS_IS_OK(status)) {
4787 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4788 0 : return False;
4789 : }
4790 :
4791 : /* Don't need the globals any more. */
4792 4 : use_level_II_oplocks = False;
4793 4 : use_oplocks = saved_use_oplocks;
4794 :
4795 4 : if (fork() == 0) {
4796 : /* Child code */
4797 4 : status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4798 4 : if (!NT_STATUS_IS_OK(status)) {
4799 0 : printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4800 0 : *shared_correct = False;
4801 0 : exit(0);
4802 : }
4803 :
4804 4 : sleep(2);
4805 :
4806 4 : status = cli_close(cli2, fnum2);
4807 4 : if (!NT_STATUS_IS_OK(status)) {
4808 0 : printf("close2 failed (%s)\n", nt_errstr(status));
4809 0 : *shared_correct = False;
4810 : }
4811 :
4812 4 : exit(0);
4813 : }
4814 :
4815 4 : sleep(2);
4816 :
4817 : /* Ensure cli1 processes the break. Empty file should always return 0
4818 : * bytes. */
4819 4 : status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4820 4 : if (!NT_STATUS_IS_OK(status)) {
4821 0 : printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4822 0 : correct = false;
4823 4 : } else if (nread != 0) {
4824 0 : printf("read on empty fnum1 failed. recv %ld expected %d\n",
4825 : (unsigned long)nread, 0);
4826 0 : correct = false;
4827 : }
4828 :
4829 : /* Should now be at level II. */
4830 : /* Test if sending a write locks causes a break to none. */
4831 4 : status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4832 4 : if (!NT_STATUS_IS_OK(status)) {
4833 0 : printf("lock failed (%s)\n", nt_errstr(status));
4834 0 : correct = False;
4835 : }
4836 :
4837 4 : cli_unlock(cli1, fnum1, 0, 4);
4838 :
4839 4 : sleep(2);
4840 :
4841 4 : status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4842 4 : if (!NT_STATUS_IS_OK(status)) {
4843 0 : printf("lock failed (%s)\n", nt_errstr(status));
4844 0 : correct = False;
4845 : }
4846 :
4847 4 : cli_unlock(cli1, fnum1, 0, 4);
4848 :
4849 4 : sleep(2);
4850 :
4851 4 : cli_read(cli1, fnum1, buf, 0, 4, NULL);
4852 :
4853 4 : status = cli_close(cli1, fnum1);
4854 4 : if (!NT_STATUS_IS_OK(status)) {
4855 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4856 0 : correct = False;
4857 : }
4858 :
4859 4 : sleep(4);
4860 :
4861 4 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4862 4 : if (!NT_STATUS_IS_OK(status)) {
4863 0 : printf("unlink failed (%s)\n", nt_errstr(status));
4864 0 : correct = False;
4865 : }
4866 :
4867 4 : if (!torture_close_connection(cli1)) {
4868 0 : correct = False;
4869 : }
4870 :
4871 4 : if (!*shared_correct) {
4872 0 : correct = False;
4873 : }
4874 :
4875 4 : printf("finished oplock test 2\n");
4876 :
4877 4 : return correct;
4878 : }
4879 :
4880 : struct oplock4_state {
4881 : struct tevent_context *ev;
4882 : struct cli_state *cli;
4883 : bool *got_break;
4884 : uint16_t *fnum2;
4885 : };
4886 :
4887 : static void oplock4_got_break(struct tevent_req *req);
4888 : static void oplock4_got_open(struct tevent_req *req);
4889 :
4890 5 : static bool run_oplock4(int dummy)
4891 : {
4892 0 : struct tevent_context *ev;
4893 0 : struct cli_state *cli1, *cli2;
4894 0 : struct tevent_req *oplock_req, *open_req;
4895 5 : const char *fname = "\\lockt4.lck";
4896 5 : const char *fname_ln = "\\lockt4_ln.lck";
4897 0 : uint16_t fnum1, fnum2;
4898 5 : int saved_use_oplocks = use_oplocks;
4899 0 : NTSTATUS status;
4900 5 : bool correct = true;
4901 :
4902 0 : bool got_break;
4903 :
4904 0 : struct oplock4_state *state;
4905 :
4906 5 : printf("starting oplock test 4\n");
4907 :
4908 5 : if (!torture_open_connection(&cli1, 0)) {
4909 0 : use_level_II_oplocks = false;
4910 0 : use_oplocks = saved_use_oplocks;
4911 0 : return false;
4912 : }
4913 :
4914 5 : if (!torture_open_connection(&cli2, 1)) {
4915 0 : use_level_II_oplocks = false;
4916 0 : use_oplocks = saved_use_oplocks;
4917 0 : return false;
4918 : }
4919 :
4920 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4921 5 : cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4922 :
4923 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
4924 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
4925 :
4926 : /* Create the file. */
4927 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4928 : &fnum1);
4929 5 : if (!NT_STATUS_IS_OK(status)) {
4930 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4931 0 : return false;
4932 : }
4933 :
4934 5 : status = cli_close(cli1, fnum1);
4935 5 : if (!NT_STATUS_IS_OK(status)) {
4936 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4937 0 : return false;
4938 : }
4939 :
4940 : /* Now create a hardlink. */
4941 5 : status = cli_hardlink(cli1, fname, fname_ln);
4942 5 : if (!NT_STATUS_IS_OK(status)) {
4943 0 : printf("nt hardlink failed (%s)\n", nt_errstr(status));
4944 0 : return false;
4945 : }
4946 :
4947 : /* Prove that opening hardlinks cause deny modes to conflict. */
4948 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4949 5 : if (!NT_STATUS_IS_OK(status)) {
4950 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4951 0 : return false;
4952 : }
4953 :
4954 5 : status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4955 5 : if (NT_STATUS_IS_OK(status)) {
4956 0 : printf("open of %s succeeded - should fail with sharing violation.\n",
4957 : fname_ln);
4958 0 : return false;
4959 : }
4960 :
4961 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4962 0 : printf("open of %s should fail with sharing violation. Got %s\n",
4963 : fname_ln, nt_errstr(status));
4964 0 : return false;
4965 : }
4966 :
4967 5 : status = cli_close(cli1, fnum1);
4968 5 : if (!NT_STATUS_IS_OK(status)) {
4969 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4970 0 : return false;
4971 : }
4972 :
4973 5 : cli1->use_oplocks = true;
4974 5 : cli2->use_oplocks = true;
4975 :
4976 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4977 5 : if (!NT_STATUS_IS_OK(status)) {
4978 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4979 0 : return false;
4980 : }
4981 :
4982 5 : ev = samba_tevent_context_init(talloc_tos());
4983 5 : if (ev == NULL) {
4984 0 : printf("tevent_context_init failed\n");
4985 0 : return false;
4986 : }
4987 :
4988 5 : state = talloc(ev, struct oplock4_state);
4989 5 : if (state == NULL) {
4990 0 : printf("talloc failed\n");
4991 0 : return false;
4992 : }
4993 5 : state->ev = ev;
4994 5 : state->cli = cli1;
4995 5 : state->got_break = &got_break;
4996 5 : state->fnum2 = &fnum2;
4997 :
4998 5 : oplock_req = cli_smb_oplock_break_waiter_send(
4999 : talloc_tos(), ev, cli1);
5000 5 : if (oplock_req == NULL) {
5001 0 : printf("cli_smb_oplock_break_waiter_send failed\n");
5002 0 : return false;
5003 : }
5004 5 : tevent_req_set_callback(oplock_req, oplock4_got_break, state);
5005 :
5006 5 : open_req = cli_openx_send(
5007 : talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
5008 5 : if (open_req == NULL) {
5009 0 : printf("cli_openx_send failed\n");
5010 0 : return false;
5011 : }
5012 5 : tevent_req_set_callback(open_req, oplock4_got_open, state);
5013 :
5014 5 : got_break = false;
5015 5 : fnum2 = 0xffff;
5016 :
5017 40 : while (!got_break || fnum2 == 0xffff) {
5018 0 : int ret;
5019 35 : ret = tevent_loop_once(ev);
5020 35 : if (ret == -1) {
5021 0 : printf("tevent_loop_once failed: %s\n",
5022 0 : strerror(errno));
5023 0 : return false;
5024 : }
5025 : }
5026 :
5027 5 : status = cli_close(cli2, fnum2);
5028 5 : if (!NT_STATUS_IS_OK(status)) {
5029 0 : printf("close2 failed (%s)\n", nt_errstr(status));
5030 0 : correct = false;
5031 : }
5032 :
5033 5 : status = cli_close(cli1, fnum1);
5034 5 : if (!NT_STATUS_IS_OK(status)) {
5035 0 : printf("close1 failed (%s)\n", nt_errstr(status));
5036 0 : correct = false;
5037 : }
5038 :
5039 5 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5040 5 : if (!NT_STATUS_IS_OK(status)) {
5041 0 : printf("unlink failed (%s)\n", nt_errstr(status));
5042 0 : correct = false;
5043 : }
5044 :
5045 5 : status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5046 5 : if (!NT_STATUS_IS_OK(status)) {
5047 0 : printf("unlink failed (%s)\n", nt_errstr(status));
5048 0 : correct = false;
5049 : }
5050 :
5051 5 : if (!torture_close_connection(cli1)) {
5052 0 : correct = false;
5053 : }
5054 :
5055 5 : if (!got_break) {
5056 0 : correct = false;
5057 : }
5058 :
5059 5 : printf("finished oplock test 4\n");
5060 :
5061 5 : return correct;
5062 : }
5063 :
5064 5 : static void oplock4_got_break(struct tevent_req *req)
5065 : {
5066 5 : struct oplock4_state *state = tevent_req_callback_data(
5067 : req, struct oplock4_state);
5068 0 : uint16_t fnum;
5069 0 : uint8_t level;
5070 0 : NTSTATUS status;
5071 :
5072 5 : status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
5073 5 : TALLOC_FREE(req);
5074 5 : if (!NT_STATUS_IS_OK(status)) {
5075 0 : printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5076 : nt_errstr(status));
5077 0 : return;
5078 : }
5079 5 : *state->got_break = true;
5080 :
5081 5 : req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5082 : NO_OPLOCK);
5083 5 : if (req == NULL) {
5084 0 : printf("cli_oplock_ack_send failed\n");
5085 0 : return;
5086 : }
5087 : }
5088 :
5089 5 : static void oplock4_got_open(struct tevent_req *req)
5090 : {
5091 5 : struct oplock4_state *state = tevent_req_callback_data(
5092 : req, struct oplock4_state);
5093 0 : NTSTATUS status;
5094 :
5095 5 : status = cli_openx_recv(req, state->fnum2);
5096 5 : if (!NT_STATUS_IS_OK(status)) {
5097 0 : printf("cli_openx_recv returned %s\n", nt_errstr(status));
5098 0 : *state->fnum2 = 0xffff;
5099 : }
5100 5 : }
5101 :
5102 : #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5103 :
5104 : struct oplock5_state {
5105 : int pipe_down_fd;
5106 : };
5107 :
5108 : /*
5109 : * Async open the file that has a kernel oplock, do an echo to get
5110 : * that 100% across, close the file to signal to the child fd that the
5111 : * oplock can be dropped, wait for the open reply.
5112 : */
5113 :
5114 : static void oplock5_opened(struct tevent_req *subreq);
5115 : static void oplock5_pong(struct tevent_req *subreq);
5116 : static void oplock5_timedout(struct tevent_req *subreq);
5117 :
5118 1 : static struct tevent_req *oplock5_send(
5119 : TALLOC_CTX *mem_ctx,
5120 : struct tevent_context *ev,
5121 : struct cli_state *cli,
5122 : const char *fname,
5123 : int pipe_down_fd)
5124 : {
5125 1 : struct tevent_req *req = NULL, *subreq = NULL;
5126 1 : struct oplock5_state *state = NULL;
5127 0 : static uint8_t data = 0;
5128 :
5129 1 : req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5130 1 : if (req == NULL) {
5131 0 : return NULL;
5132 : }
5133 1 : state->pipe_down_fd = pipe_down_fd;
5134 :
5135 1 : subreq = cli_ntcreate_send(
5136 : state,
5137 : ev,
5138 : cli,
5139 : fname,
5140 : 0, /* CreatFlags */
5141 : SEC_FILE_READ_DATA, /* DesiredAccess */
5142 : FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
5143 : FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5144 : FILE_OPEN, /* CreateDisposition */
5145 : FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5146 : 0, /* Impersonation */
5147 : 0); /* SecurityFlags */
5148 1 : if (tevent_req_nomem(subreq, req)) {
5149 0 : return tevent_req_post(req, ev);
5150 : }
5151 1 : tevent_req_set_callback(subreq, oplock5_opened, req);
5152 :
5153 1 : subreq = cli_echo_send(
5154 : state,
5155 : ev,
5156 : cli,
5157 : 1,
5158 1 : (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5159 1 : if (tevent_req_nomem(subreq, req)) {
5160 0 : return tevent_req_post(req, ev);
5161 : }
5162 1 : tevent_req_set_callback(subreq, oplock5_pong, req);
5163 :
5164 1 : subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5165 1 : if (tevent_req_nomem(subreq, req)) {
5166 0 : return tevent_req_post(req, ev);
5167 : }
5168 1 : tevent_req_set_callback(subreq, oplock5_timedout, req);
5169 :
5170 1 : return req;
5171 : }
5172 :
5173 1 : static void oplock5_opened(struct tevent_req *subreq)
5174 : {
5175 1 : struct tevent_req *req = tevent_req_callback_data(
5176 : subreq, struct tevent_req);
5177 0 : NTSTATUS status;
5178 0 : uint16_t fnum;
5179 :
5180 1 : status = cli_ntcreate_recv(subreq, &fnum, NULL);
5181 1 : TALLOC_FREE(subreq);
5182 1 : if (tevent_req_nterror(req, status)) {
5183 0 : return;
5184 : }
5185 1 : tevent_req_done(req);
5186 : }
5187 :
5188 1 : static void oplock5_pong(struct tevent_req *subreq)
5189 : {
5190 1 : struct tevent_req *req = tevent_req_callback_data(
5191 : subreq, struct tevent_req);
5192 1 : struct oplock5_state *state = tevent_req_data(
5193 : req, struct oplock5_state);
5194 0 : NTSTATUS status;
5195 :
5196 1 : status = cli_echo_recv(subreq);
5197 1 : TALLOC_FREE(subreq);
5198 1 : if (tevent_req_nterror(req, status)) {
5199 0 : return;
5200 : }
5201 :
5202 1 : close(state->pipe_down_fd);
5203 : }
5204 :
5205 0 : static void oplock5_timedout(struct tevent_req *subreq)
5206 : {
5207 0 : struct tevent_req *req = tevent_req_callback_data(
5208 : subreq, struct tevent_req);
5209 0 : bool ok;
5210 :
5211 0 : ok = tevent_wakeup_recv(subreq);
5212 0 : TALLOC_FREE(subreq);
5213 0 : if (!ok) {
5214 0 : tevent_req_oom(req);
5215 0 : return;
5216 : }
5217 0 : tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5218 : }
5219 :
5220 1 : static NTSTATUS oplock5_recv(struct tevent_req *req)
5221 : {
5222 1 : return tevent_req_simple_recv_ntstatus(req);
5223 : }
5224 :
5225 1 : static bool run_oplock5(int dummy)
5226 : {
5227 1 : struct tevent_context *ev = NULL;
5228 1 : struct tevent_req *req = NULL;
5229 1 : struct cli_state *cli = NULL;
5230 1 : const char *fname = "oplock5.txt";
5231 0 : int pipe_down[2], pipe_up[2];
5232 0 : pid_t child_pid;
5233 1 : uint8_t c = '\0';
5234 0 : NTSTATUS status;
5235 0 : int ret;
5236 0 : bool ok;
5237 :
5238 1 : printf("starting oplock5\n");
5239 :
5240 1 : if (local_path == NULL) {
5241 0 : d_fprintf(stderr, "oplock5 must be given a local path via "
5242 : "-l <localpath>\n");
5243 0 : return false;
5244 : }
5245 :
5246 1 : ret = pipe(pipe_down);
5247 1 : if (ret == -1) {
5248 0 : d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5249 0 : return false;
5250 : }
5251 1 : ret = pipe(pipe_up);
5252 1 : if (ret == -1) {
5253 0 : d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5254 0 : return false;
5255 : }
5256 :
5257 1 : child_pid = fork();
5258 2 : if (child_pid == -1) {
5259 0 : d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5260 0 : return false;
5261 : }
5262 :
5263 2 : if (child_pid == 0) {
5264 1 : char *local_file = NULL;
5265 0 : int fd;
5266 :
5267 1 : close(pipe_down[1]);
5268 1 : close(pipe_up[0]);
5269 :
5270 1 : local_file = talloc_asprintf(
5271 1 : talloc_tos(), "%s/%s", local_path, fname);
5272 1 : if (local_file == 0) {
5273 0 : c = 1;
5274 0 : goto do_write;
5275 : }
5276 1 : fd = open(local_file, O_RDWR|O_CREAT, 0644);
5277 1 : if (fd == -1) {
5278 0 : d_fprintf(stderr,
5279 : "open(%s) in child failed: %s\n",
5280 : local_file,
5281 0 : strerror(errno));
5282 0 : c = 2;
5283 0 : goto do_write;
5284 : }
5285 :
5286 1 : signal(SIGIO, SIG_IGN);
5287 :
5288 1 : ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5289 1 : if (ret == -1) {
5290 0 : d_fprintf(stderr,
5291 : "SETLEASE in child failed: %s\n",
5292 0 : strerror(errno));
5293 0 : c = 3;
5294 0 : goto do_write;
5295 : }
5296 :
5297 1 : do_write:
5298 1 : ret = sys_write(pipe_up[1], &c, sizeof(c));
5299 1 : if (ret == -1) {
5300 0 : d_fprintf(stderr,
5301 : "sys_write failed: %s\n",
5302 0 : strerror(errno));
5303 0 : exit(4);
5304 : }
5305 1 : ret = sys_read(pipe_down[0], &c, sizeof(c));
5306 1 : if (ret == -1) {
5307 0 : d_fprintf(stderr,
5308 : "sys_read failed: %s\n",
5309 0 : strerror(errno));
5310 0 : exit(5);
5311 : }
5312 1 : exit(0);
5313 : }
5314 :
5315 1 : close(pipe_up[1]);
5316 1 : close(pipe_down[0]);
5317 :
5318 1 : ret = sys_read(pipe_up[0], &c, sizeof(c));
5319 1 : if (ret != 1) {
5320 0 : d_fprintf(stderr,
5321 : "sys_read failed: %s\n",
5322 0 : strerror(errno));
5323 0 : return false;
5324 : }
5325 1 : if (c != 0) {
5326 0 : d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5327 0 : return false;
5328 : }
5329 :
5330 1 : ok = torture_open_connection(&cli, 0);
5331 1 : if (!ok) {
5332 0 : d_fprintf(stderr, "torture_open_connection failed\n");
5333 0 : return false;
5334 : }
5335 :
5336 1 : ev = samba_tevent_context_init(talloc_tos());
5337 1 : if (ev == NULL) {
5338 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
5339 0 : return false;
5340 : }
5341 :
5342 1 : req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5343 1 : if (req == NULL) {
5344 0 : d_fprintf(stderr, "oplock5_send failed\n");
5345 0 : return false;
5346 : }
5347 :
5348 1 : ok = tevent_req_poll_ntstatus(req, ev, &status);
5349 1 : if (!ok) {
5350 0 : d_fprintf(stderr,
5351 : "tevent_req_poll_ntstatus failed: %s\n",
5352 : nt_errstr(status));
5353 0 : return false;
5354 : }
5355 :
5356 1 : status = oplock5_recv(req);
5357 1 : TALLOC_FREE(req);
5358 1 : if (!NT_STATUS_IS_OK(status)) {
5359 0 : d_fprintf(stderr,
5360 : "oplock5 failed: %s\n",
5361 : nt_errstr(status));
5362 0 : return false;
5363 : }
5364 :
5365 1 : return true;
5366 : }
5367 :
5368 : #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5369 :
5370 : /*
5371 : Test delete on close semantics.
5372 : */
5373 5 : static bool run_deletetest(int dummy)
5374 : {
5375 5 : struct cli_state *cli1 = NULL;
5376 5 : struct cli_state *cli2 = NULL;
5377 5 : const char *fname = "\\delete.file";
5378 5 : uint16_t fnum1 = (uint16_t)-1;
5379 5 : uint16_t fnum2 = (uint16_t)-1;
5380 5 : bool correct = false;
5381 0 : NTSTATUS status;
5382 :
5383 5 : printf("starting delete test\n");
5384 :
5385 5 : if (!torture_open_connection(&cli1, 0)) {
5386 0 : return False;
5387 : }
5388 :
5389 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
5390 :
5391 : /* Test 1 - this should delete the file on close. */
5392 :
5393 5 : cli_setatr(cli1, fname, 0, 0);
5394 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5395 :
5396 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5397 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5398 : FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5399 5 : if (!NT_STATUS_IS_OK(status)) {
5400 0 : printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5401 0 : goto fail;
5402 : }
5403 :
5404 5 : status = cli_close(cli1, fnum1);
5405 5 : if (!NT_STATUS_IS_OK(status)) {
5406 0 : printf("[1] close failed (%s)\n", nt_errstr(status));
5407 0 : goto fail;
5408 : }
5409 :
5410 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5411 5 : if (NT_STATUS_IS_OK(status)) {
5412 0 : printf("[1] open of %s succeeded (should fail)\n", fname);
5413 0 : goto fail;
5414 : }
5415 :
5416 5 : printf("first delete on close test succeeded.\n");
5417 :
5418 : /* Test 2 - this should delete the file on close. */
5419 :
5420 5 : cli_setatr(cli1, fname, 0, 0);
5421 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5422 :
5423 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5424 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5425 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5426 5 : if (!NT_STATUS_IS_OK(status)) {
5427 0 : printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5428 0 : goto fail;
5429 : }
5430 :
5431 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5432 5 : if (!NT_STATUS_IS_OK(status)) {
5433 0 : printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5434 0 : goto fail;
5435 : }
5436 :
5437 5 : status = cli_close(cli1, fnum1);
5438 5 : if (!NT_STATUS_IS_OK(status)) {
5439 0 : printf("[2] close failed (%s)\n", nt_errstr(status));
5440 0 : goto fail;
5441 : }
5442 :
5443 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5444 5 : if (NT_STATUS_IS_OK(status)) {
5445 0 : printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5446 0 : status = cli_close(cli1, fnum1);
5447 0 : if (!NT_STATUS_IS_OK(status)) {
5448 0 : printf("[2] close failed (%s)\n", nt_errstr(status));
5449 : }
5450 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5451 0 : goto fail;
5452 : }
5453 :
5454 5 : printf("second delete on close test succeeded.\n");
5455 :
5456 : /* Test 3 - ... */
5457 5 : cli_setatr(cli1, fname, 0, 0);
5458 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5459 :
5460 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5461 : FILE_ATTRIBUTE_NORMAL,
5462 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5463 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5464 5 : if (!NT_STATUS_IS_OK(status)) {
5465 0 : printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5466 0 : goto fail;
5467 : }
5468 :
5469 : /* This should fail with a sharing violation - open for delete is only compatible
5470 : with SHARE_DELETE. */
5471 :
5472 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5473 : FILE_ATTRIBUTE_NORMAL,
5474 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5475 : FILE_OPEN, 0, 0, &fnum2, NULL);
5476 5 : if (NT_STATUS_IS_OK(status)) {
5477 0 : printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
5478 0 : goto fail;
5479 : }
5480 :
5481 : /* This should succeed. */
5482 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5483 : FILE_ATTRIBUTE_NORMAL,
5484 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5485 : FILE_OPEN, 0, 0, &fnum2, NULL);
5486 5 : if (!NT_STATUS_IS_OK(status)) {
5487 0 : printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5488 0 : goto fail;
5489 : }
5490 :
5491 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5492 5 : if (!NT_STATUS_IS_OK(status)) {
5493 0 : printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5494 0 : goto fail;
5495 : }
5496 :
5497 5 : status = cli_close(cli1, fnum1);
5498 5 : if (!NT_STATUS_IS_OK(status)) {
5499 0 : printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5500 0 : goto fail;
5501 : }
5502 :
5503 5 : status = cli_close(cli1, fnum2);
5504 5 : if (!NT_STATUS_IS_OK(status)) {
5505 0 : printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5506 0 : goto fail;
5507 : }
5508 :
5509 : /* This should fail - file should no longer be there. */
5510 :
5511 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5512 5 : if (NT_STATUS_IS_OK(status)) {
5513 0 : printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5514 0 : status = cli_close(cli1, fnum1);
5515 0 : if (!NT_STATUS_IS_OK(status)) {
5516 0 : printf("[3] close failed (%s)\n", nt_errstr(status));
5517 : }
5518 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5519 0 : goto fail;
5520 : }
5521 :
5522 5 : printf("third delete on close test succeeded.\n");
5523 :
5524 : /* Test 4 ... */
5525 5 : cli_setatr(cli1, fname, 0, 0);
5526 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5527 :
5528 5 : status = cli_ntcreate(cli1, fname, 0,
5529 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5530 : FILE_ATTRIBUTE_NORMAL,
5531 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5532 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5533 5 : if (!NT_STATUS_IS_OK(status)) {
5534 0 : printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5535 0 : goto fail;
5536 : }
5537 :
5538 : /* This should succeed. */
5539 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5540 : FILE_ATTRIBUTE_NORMAL,
5541 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5542 : FILE_OPEN, 0, 0, &fnum2, NULL);
5543 5 : if (!NT_STATUS_IS_OK(status)) {
5544 0 : printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5545 0 : goto fail;
5546 : }
5547 :
5548 5 : status = cli_close(cli1, fnum2);
5549 5 : if (!NT_STATUS_IS_OK(status)) {
5550 0 : printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5551 0 : goto fail;
5552 : }
5553 :
5554 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5555 5 : if (!NT_STATUS_IS_OK(status)) {
5556 0 : printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5557 0 : goto fail;
5558 : }
5559 :
5560 : /* This should fail - no more opens once delete on close set. */
5561 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5562 : FILE_ATTRIBUTE_NORMAL,
5563 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5564 : FILE_OPEN, 0, 0, &fnum2, NULL);
5565 5 : if (NT_STATUS_IS_OK(status)) {
5566 0 : printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
5567 0 : goto fail;
5568 : }
5569 :
5570 5 : status = cli_close(cli1, fnum1);
5571 5 : if (!NT_STATUS_IS_OK(status)) {
5572 0 : printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5573 0 : goto fail;
5574 : }
5575 :
5576 5 : printf("fourth delete on close test succeeded.\n");
5577 :
5578 : /* Test 5 ... */
5579 5 : cli_setatr(cli1, fname, 0, 0);
5580 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5581 :
5582 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5583 5 : if (!NT_STATUS_IS_OK(status)) {
5584 0 : printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5585 0 : goto fail;
5586 : }
5587 :
5588 : /* This should fail - only allowed on NT opens with DELETE access. */
5589 :
5590 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5591 5 : if (NT_STATUS_IS_OK(status)) {
5592 0 : printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5593 0 : goto fail;
5594 : }
5595 :
5596 5 : status = cli_close(cli1, fnum1);
5597 5 : if (!NT_STATUS_IS_OK(status)) {
5598 0 : printf("[5] close failed (%s)\n", nt_errstr(status));
5599 0 : goto fail;
5600 : }
5601 :
5602 5 : printf("fifth delete on close test succeeded.\n");
5603 :
5604 : /* Test 6 ... */
5605 5 : cli_setatr(cli1, fname, 0, 0);
5606 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5607 :
5608 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5609 : FILE_ATTRIBUTE_NORMAL,
5610 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5611 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5612 5 : if (!NT_STATUS_IS_OK(status)) {
5613 0 : printf("[6] open of %s failed (%s)\n", fname,
5614 : nt_errstr(status));
5615 0 : goto fail;
5616 : }
5617 :
5618 : /* This should fail - only allowed on NT opens with DELETE access. */
5619 :
5620 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5621 5 : if (NT_STATUS_IS_OK(status)) {
5622 0 : printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5623 0 : goto fail;
5624 : }
5625 :
5626 5 : status = cli_close(cli1, fnum1);
5627 5 : if (!NT_STATUS_IS_OK(status)) {
5628 0 : printf("[6] close failed (%s)\n", nt_errstr(status));
5629 0 : goto fail;
5630 : }
5631 :
5632 5 : printf("sixth delete on close test succeeded.\n");
5633 :
5634 : /* Test 7 ... */
5635 5 : cli_setatr(cli1, fname, 0, 0);
5636 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5637 :
5638 5 : status = cli_ntcreate(cli1, fname, 0,
5639 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5640 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5641 : 0, 0, &fnum1, NULL);
5642 5 : if (!NT_STATUS_IS_OK(status)) {
5643 0 : printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5644 0 : goto fail;
5645 : }
5646 :
5647 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5648 5 : if (!NT_STATUS_IS_OK(status)) {
5649 0 : printf("[7] setting delete_on_close on file failed !\n");
5650 0 : goto fail;
5651 : }
5652 :
5653 5 : status = cli_nt_delete_on_close(cli1, fnum1, false);
5654 5 : if (!NT_STATUS_IS_OK(status)) {
5655 0 : printf("[7] unsetting delete_on_close on file failed !\n");
5656 0 : goto fail;
5657 : }
5658 :
5659 5 : status = cli_close(cli1, fnum1);
5660 5 : if (!NT_STATUS_IS_OK(status)) {
5661 0 : printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5662 0 : goto fail;
5663 : }
5664 :
5665 : /* This next open should succeed - we reset the flag. */
5666 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5667 5 : if (!NT_STATUS_IS_OK(status)) {
5668 0 : printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5669 0 : goto fail;
5670 : }
5671 :
5672 5 : status = cli_close(cli1, fnum1);
5673 5 : if (!NT_STATUS_IS_OK(status)) {
5674 0 : printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5675 0 : goto fail;
5676 : }
5677 :
5678 5 : printf("seventh delete on close test succeeded.\n");
5679 :
5680 : /* Test 8 ... */
5681 5 : cli_setatr(cli1, fname, 0, 0);
5682 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5683 :
5684 5 : if (!torture_open_connection(&cli2, 1)) {
5685 0 : printf("[8] failed to open second connection.\n");
5686 0 : goto fail;
5687 : }
5688 :
5689 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
5690 :
5691 5 : status = cli_ntcreate(cli1, fname, 0,
5692 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5693 : FILE_ATTRIBUTE_NORMAL,
5694 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5695 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5696 5 : if (!NT_STATUS_IS_OK(status)) {
5697 0 : printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5698 0 : goto fail;
5699 : }
5700 :
5701 5 : status = cli_ntcreate(cli2, fname, 0,
5702 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5703 : FILE_ATTRIBUTE_NORMAL,
5704 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5705 : FILE_OPEN, 0, 0, &fnum2, NULL);
5706 5 : if (!NT_STATUS_IS_OK(status)) {
5707 0 : printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5708 0 : goto fail;
5709 : }
5710 :
5711 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5712 5 : if (!NT_STATUS_IS_OK(status)) {
5713 0 : printf("[8] setting delete_on_close on file failed !\n");
5714 0 : goto fail;
5715 : }
5716 :
5717 5 : status = cli_close(cli1, fnum1);
5718 5 : if (!NT_STATUS_IS_OK(status)) {
5719 0 : printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5720 0 : goto fail;
5721 : }
5722 :
5723 5 : status = cli_close(cli2, fnum2);
5724 5 : if (!NT_STATUS_IS_OK(status)) {
5725 0 : printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5726 0 : goto fail;
5727 : }
5728 :
5729 : /* This should fail.. */
5730 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5731 5 : if (NT_STATUS_IS_OK(status)) {
5732 0 : printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5733 0 : goto fail;
5734 : }
5735 :
5736 5 : printf("eighth delete on close test succeeded.\n");
5737 :
5738 : /* Test 9 ... */
5739 :
5740 : /* This should fail - we need to set DELETE_ACCESS. */
5741 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5742 : FILE_ATTRIBUTE_NORMAL,
5743 : FILE_SHARE_NONE,
5744 : FILE_OVERWRITE_IF,
5745 : FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5746 5 : if (NT_STATUS_IS_OK(status)) {
5747 0 : printf("[9] open of %s succeeded should have failed!\n", fname);
5748 0 : goto fail;
5749 : }
5750 :
5751 5 : printf("ninth delete on close test succeeded.\n");
5752 :
5753 : /* Test 10 ... */
5754 :
5755 5 : status = cli_ntcreate(cli1, fname, 0,
5756 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5757 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5758 : FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5759 : 0, &fnum1, NULL);
5760 5 : if (!NT_STATUS_IS_OK(status)) {
5761 0 : printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5762 0 : goto fail;
5763 : }
5764 :
5765 : /* This should delete the file. */
5766 5 : status = cli_close(cli1, fnum1);
5767 5 : if (!NT_STATUS_IS_OK(status)) {
5768 0 : printf("[10] close failed (%s)\n", nt_errstr(status));
5769 0 : goto fail;
5770 : }
5771 :
5772 : /* This should fail.. */
5773 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5774 5 : if (NT_STATUS_IS_OK(status)) {
5775 0 : printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5776 0 : goto fail;
5777 : }
5778 :
5779 5 : printf("tenth delete on close test succeeded.\n");
5780 :
5781 : /* Test 11 ... */
5782 :
5783 5 : cli_setatr(cli1, fname, 0, 0);
5784 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5785 :
5786 : /* Can we open a read-only file with delete access? */
5787 :
5788 : /* Create a readonly file. */
5789 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5790 : FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5791 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5792 5 : if (!NT_STATUS_IS_OK(status)) {
5793 0 : printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5794 0 : goto fail;
5795 : }
5796 :
5797 5 : status = cli_close(cli1, fnum1);
5798 5 : if (!NT_STATUS_IS_OK(status)) {
5799 0 : printf("[11] close failed (%s)\n", nt_errstr(status));
5800 0 : goto fail;
5801 : }
5802 :
5803 : /* Now try open for delete access. */
5804 5 : status = cli_ntcreate(cli1, fname, 0,
5805 : FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5806 : 0,
5807 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5808 : FILE_OPEN, 0, 0, &fnum1, NULL);
5809 5 : if (!NT_STATUS_IS_OK(status)) {
5810 0 : printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5811 0 : goto fail;
5812 : }
5813 :
5814 5 : cli_close(cli1, fnum1);
5815 :
5816 5 : printf("eleventh delete on close test succeeded.\n");
5817 :
5818 : /*
5819 : * Test 12
5820 : * like test 4 but with initial delete on close
5821 : */
5822 :
5823 5 : cli_setatr(cli1, fname, 0, 0);
5824 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5825 :
5826 5 : status = cli_ntcreate(cli1, fname, 0,
5827 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5828 : FILE_ATTRIBUTE_NORMAL,
5829 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5830 : FILE_OVERWRITE_IF,
5831 : FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5832 5 : if (!NT_STATUS_IS_OK(status)) {
5833 0 : printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5834 0 : goto fail;
5835 : }
5836 :
5837 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5838 : FILE_ATTRIBUTE_NORMAL,
5839 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5840 : FILE_OPEN, 0, 0, &fnum2, NULL);
5841 5 : if (!NT_STATUS_IS_OK(status)) {
5842 0 : printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5843 0 : goto fail;
5844 : }
5845 :
5846 5 : status = cli_close(cli1, fnum2);
5847 5 : if (!NT_STATUS_IS_OK(status)) {
5848 0 : printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5849 0 : goto fail;
5850 : }
5851 :
5852 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5853 5 : if (!NT_STATUS_IS_OK(status)) {
5854 0 : printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5855 0 : goto fail;
5856 : }
5857 :
5858 : /* This should fail - no more opens once delete on close set. */
5859 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5860 : FILE_ATTRIBUTE_NORMAL,
5861 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5862 : FILE_OPEN, 0, 0, &fnum2, NULL);
5863 5 : if (NT_STATUS_IS_OK(status)) {
5864 0 : printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5865 0 : goto fail;
5866 : }
5867 :
5868 5 : status = cli_nt_delete_on_close(cli1, fnum1, false);
5869 5 : if (!NT_STATUS_IS_OK(status)) {
5870 0 : printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5871 0 : goto fail;
5872 : }
5873 :
5874 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5875 : FILE_ATTRIBUTE_NORMAL,
5876 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5877 : FILE_OPEN, 0, 0, &fnum2, NULL);
5878 5 : if (!NT_STATUS_IS_OK(status)) {
5879 0 : printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5880 0 : goto fail;
5881 : }
5882 :
5883 5 : status = cli_close(cli1, fnum2);
5884 5 : if (!NT_STATUS_IS_OK(status)) {
5885 0 : printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5886 0 : goto fail;
5887 : }
5888 :
5889 5 : status = cli_close(cli1, fnum1);
5890 5 : if (!NT_STATUS_IS_OK(status)) {
5891 0 : printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5892 0 : goto fail;
5893 : }
5894 :
5895 : /*
5896 : * setting delete on close on the handle does
5897 : * not unset the initial delete on close...
5898 : */
5899 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5900 : FILE_ATTRIBUTE_NORMAL,
5901 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5902 : FILE_OPEN, 0, 0, &fnum2, NULL);
5903 5 : if (NT_STATUS_IS_OK(status)) {
5904 0 : printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5905 0 : goto fail;
5906 5 : } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5907 0 : printf("ntcreate returned %s, expected "
5908 : "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5909 : nt_errstr(status));
5910 0 : goto fail;
5911 : }
5912 :
5913 5 : printf("twelfth delete on close test succeeded.\n");
5914 :
5915 :
5916 5 : printf("finished delete test\n");
5917 :
5918 5 : correct = true;
5919 :
5920 5 : fail:
5921 : /* FIXME: This will crash if we aborted before cli2 got
5922 : * initialized, because these functions don't handle
5923 : * uninitialized connections. */
5924 :
5925 5 : if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5926 5 : if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5927 5 : cli_setatr(cli1, fname, 0, 0);
5928 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5929 :
5930 5 : if (cli1 && !torture_close_connection(cli1)) {
5931 0 : correct = False;
5932 : }
5933 5 : if (cli2 && !torture_close_connection(cli2)) {
5934 0 : correct = False;
5935 : }
5936 5 : return correct;
5937 : }
5938 :
5939 : struct delete_stream_state {
5940 : bool closed;
5941 : };
5942 :
5943 : static void delete_stream_unlinked(struct tevent_req *subreq);
5944 : static void delete_stream_closed(struct tevent_req *subreq);
5945 :
5946 5 : static struct tevent_req *delete_stream_send(
5947 : TALLOC_CTX *mem_ctx,
5948 : struct tevent_context *ev,
5949 : struct cli_state *cli,
5950 : const char *base_fname,
5951 : uint16_t stream_fnum)
5952 : {
5953 5 : struct tevent_req *req = NULL, *subreq = NULL;
5954 5 : struct delete_stream_state *state = NULL;
5955 :
5956 5 : req = tevent_req_create(
5957 : mem_ctx, &state, struct delete_stream_state);
5958 5 : if (req == NULL) {
5959 0 : return NULL;
5960 : }
5961 :
5962 5 : subreq = cli_unlink_send(
5963 : state,
5964 : ev,
5965 : cli,
5966 : base_fname,
5967 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5968 5 : if (tevent_req_nomem(subreq, req)) {
5969 0 : return tevent_req_post(req, ev);
5970 : }
5971 5 : tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5972 :
5973 5 : subreq = cli_close_send(state, ev, cli, stream_fnum, 0);
5974 5 : if (tevent_req_nomem(subreq, req)) {
5975 0 : return tevent_req_post(req, ev);
5976 : }
5977 5 : tevent_req_set_callback(subreq, delete_stream_closed, req);
5978 :
5979 5 : return req;
5980 : }
5981 :
5982 5 : static void delete_stream_unlinked(struct tevent_req *subreq)
5983 : {
5984 5 : struct tevent_req *req = tevent_req_callback_data(
5985 : subreq, struct tevent_req);
5986 5 : struct delete_stream_state *state = tevent_req_data(
5987 : req, struct delete_stream_state);
5988 0 : NTSTATUS status;
5989 :
5990 5 : status = cli_unlink_recv(subreq);
5991 5 : TALLOC_FREE(subreq);
5992 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5993 0 : printf("cli_unlink returned %s\n",
5994 : nt_errstr(status));
5995 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5996 0 : return;
5997 : }
5998 5 : if (!state->closed) {
5999 : /* close reply should have come in first */
6000 0 : printf("Not closed\n");
6001 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6002 0 : return;
6003 : }
6004 5 : tevent_req_done(req);
6005 : }
6006 :
6007 5 : static void delete_stream_closed(struct tevent_req *subreq)
6008 : {
6009 5 : struct tevent_req *req = tevent_req_callback_data(
6010 : subreq, struct tevent_req);
6011 5 : struct delete_stream_state *state = tevent_req_data(
6012 : req, struct delete_stream_state);
6013 0 : NTSTATUS status;
6014 :
6015 5 : status = cli_close_recv(subreq);
6016 5 : TALLOC_FREE(subreq);
6017 5 : if (tevent_req_nterror(req, status)) {
6018 0 : return;
6019 : }
6020 : /* also waiting for the unlink to come back */
6021 5 : state->closed = true;
6022 : }
6023 :
6024 5 : static NTSTATUS delete_stream_recv(struct tevent_req *req)
6025 : {
6026 5 : return tevent_req_simple_recv_ntstatus(req);
6027 : }
6028 :
6029 5 : static bool run_delete_stream(int dummy)
6030 : {
6031 5 : struct tevent_context *ev = NULL;
6032 5 : struct tevent_req *req = NULL;
6033 5 : struct cli_state *cli = NULL;
6034 5 : const char fname[] = "delete_stream";
6035 5 : const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
6036 0 : uint16_t fnum1, fnum2;
6037 0 : NTSTATUS status;
6038 0 : bool ok;
6039 :
6040 5 : printf("Starting stream delete test\n");
6041 :
6042 5 : ok = torture_open_connection(&cli, 0);
6043 5 : if (!ok) {
6044 0 : return false;
6045 : }
6046 :
6047 5 : cli_setatr(cli, fname, 0, 0);
6048 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6049 :
6050 : /* Create the file. */
6051 5 : status = cli_ntcreate(
6052 : cli,
6053 : fname,
6054 : 0,
6055 : READ_CONTROL_ACCESS,
6056 : 0,
6057 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6058 : FILE_CREATE,
6059 : 0x0,
6060 : 0x0,
6061 : &fnum1,
6062 : NULL);
6063 5 : if (!NT_STATUS_IS_OK(status)) {
6064 0 : d_fprintf(stderr,
6065 : "cli_ntcreate of %s failed (%s)\n",
6066 : fname,
6067 : nt_errstr(status));
6068 0 : return false;
6069 : }
6070 5 : status = cli_close(cli, fnum1);
6071 5 : if (!NT_STATUS_IS_OK(status)) {
6072 0 : d_fprintf(stderr,
6073 : "cli_close of %s failed (%s)\n",
6074 : fname,
6075 : nt_errstr(status));
6076 0 : return false;
6077 : }
6078 :
6079 : /* Now create the stream. */
6080 5 : status = cli_ntcreate(
6081 : cli,
6082 : fname_stream,
6083 : 0,
6084 : FILE_WRITE_DATA,
6085 : 0,
6086 : FILE_SHARE_READ|FILE_SHARE_WRITE,
6087 : FILE_CREATE,
6088 : 0x0,
6089 : 0x0,
6090 : &fnum1,
6091 : NULL);
6092 :
6093 5 : if (!NT_STATUS_IS_OK(status)) {
6094 0 : d_fprintf(stderr,
6095 : "cli_ntcreate of %s failed (%s)\n",
6096 : fname_stream,
6097 : nt_errstr(status));
6098 0 : return false;
6099 : }
6100 :
6101 : /* open it a second time */
6102 :
6103 5 : status = cli_ntcreate(
6104 : cli,
6105 : fname_stream,
6106 : 0,
6107 : FILE_WRITE_DATA,
6108 : 0,
6109 : FILE_SHARE_READ|FILE_SHARE_WRITE,
6110 : FILE_OPEN,
6111 : 0x0,
6112 : 0x0,
6113 : &fnum2,
6114 : NULL);
6115 :
6116 5 : if (!NT_STATUS_IS_OK(status)) {
6117 0 : d_fprintf(stderr,
6118 : "2nd cli_ntcreate of %s failed (%s)\n",
6119 : fname_stream,
6120 : nt_errstr(status));
6121 0 : return false;
6122 : }
6123 :
6124 5 : ev = samba_tevent_context_init(talloc_tos());
6125 5 : if (ev == NULL) {
6126 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
6127 0 : return false;
6128 : }
6129 :
6130 5 : req = delete_stream_send(ev, ev, cli, fname, fnum1);
6131 5 : if (req == NULL) {
6132 0 : d_fprintf(stderr, "delete_stream_send failed\n");
6133 0 : return false;
6134 : }
6135 :
6136 5 : ok = tevent_req_poll_ntstatus(req, ev, &status);
6137 5 : if (!ok) {
6138 0 : d_fprintf(stderr,
6139 : "tevent_req_poll_ntstatus failed: %s\n",
6140 : nt_errstr(status));
6141 0 : return false;
6142 : }
6143 :
6144 5 : status = delete_stream_recv(req);
6145 5 : TALLOC_FREE(req);
6146 5 : if (!NT_STATUS_IS_OK(status)) {
6147 0 : d_fprintf(stderr,
6148 : "delete_stream failed: %s\n",
6149 : nt_errstr(status));
6150 0 : return false;
6151 : }
6152 :
6153 5 : status = cli_close(cli, fnum2);
6154 5 : if (!NT_STATUS_IS_OK(status)) {
6155 0 : d_fprintf(stderr,
6156 : "close failed: %s\n",
6157 : nt_errstr(status));
6158 0 : return false;
6159 : }
6160 :
6161 5 : status = cli_unlink(
6162 : cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6163 5 : if (!NT_STATUS_IS_OK(status)) {
6164 0 : d_fprintf(stderr,
6165 : "unlink failed: %s\n",
6166 : nt_errstr(status));
6167 0 : return false;
6168 : }
6169 :
6170 5 : return true;
6171 : }
6172 :
6173 : /*
6174 : Exercise delete on close semantics - use on the PRINT1 share in torture
6175 : testing.
6176 : */
6177 2 : static bool run_delete_print_test(int dummy)
6178 : {
6179 2 : struct cli_state *cli1 = NULL;
6180 2 : const char *fname = "print_delete.file";
6181 2 : uint16_t fnum1 = (uint16_t)-1;
6182 2 : bool correct = false;
6183 2 : const char *buf = "print file data\n";
6184 0 : NTSTATUS status;
6185 :
6186 2 : printf("starting print delete test\n");
6187 :
6188 2 : if (!torture_open_connection(&cli1, 0)) {
6189 0 : return false;
6190 : }
6191 :
6192 2 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
6193 :
6194 2 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6195 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6196 : 0, 0, &fnum1, NULL);
6197 2 : if (!NT_STATUS_IS_OK(status)) {
6198 0 : printf("open of %s failed (%s)\n",
6199 : fname,
6200 : nt_errstr(status));
6201 0 : goto fail;
6202 : }
6203 :
6204 2 : status = cli_writeall(cli1,
6205 : fnum1,
6206 : 0,
6207 : (const uint8_t *)buf,
6208 : 0, /* offset */
6209 : strlen(buf), /* size */
6210 : NULL);
6211 2 : if (!NT_STATUS_IS_OK(status)) {
6212 0 : printf("writing print file data failed (%s)\n",
6213 : nt_errstr(status));
6214 0 : goto fail;
6215 : }
6216 :
6217 2 : status = cli_nt_delete_on_close(cli1, fnum1, true);
6218 2 : if (!NT_STATUS_IS_OK(status)) {
6219 0 : printf("setting delete_on_close failed (%s)\n",
6220 : nt_errstr(status));
6221 0 : goto fail;
6222 : }
6223 :
6224 2 : status = cli_close(cli1, fnum1);
6225 2 : if (!NT_STATUS_IS_OK(status)) {
6226 0 : printf("close failed (%s)\n", nt_errstr(status));
6227 0 : goto fail;
6228 : }
6229 :
6230 2 : printf("finished print delete test\n");
6231 :
6232 2 : correct = true;
6233 :
6234 2 : fail:
6235 :
6236 2 : if (fnum1 != (uint16_t)-1) {
6237 2 : cli_close(cli1, fnum1);
6238 : }
6239 :
6240 2 : if (cli1 && !torture_close_connection(cli1)) {
6241 0 : correct = false;
6242 : }
6243 2 : return correct;
6244 : }
6245 :
6246 4 : static bool run_deletetest_ln(int dummy)
6247 : {
6248 0 : struct cli_state *cli;
6249 4 : const char *fname = "\\delete1";
6250 4 : const char *fname_ln = "\\delete1_ln";
6251 0 : uint16_t fnum;
6252 0 : uint16_t fnum1;
6253 0 : NTSTATUS status;
6254 4 : bool correct = true;
6255 0 : time_t t;
6256 :
6257 4 : printf("starting deletetest-ln\n");
6258 :
6259 4 : if (!torture_open_connection(&cli, 0)) {
6260 0 : return false;
6261 : }
6262 :
6263 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6264 4 : cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6265 :
6266 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6267 :
6268 : /* Create the file. */
6269 4 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6270 4 : if (!NT_STATUS_IS_OK(status)) {
6271 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6272 0 : return false;
6273 : }
6274 :
6275 4 : status = cli_close(cli, fnum);
6276 4 : if (!NT_STATUS_IS_OK(status)) {
6277 0 : printf("close1 failed (%s)\n", nt_errstr(status));
6278 0 : return false;
6279 : }
6280 :
6281 : /* Now create a hardlink. */
6282 4 : status = cli_hardlink(cli, fname, fname_ln);
6283 4 : if (!NT_STATUS_IS_OK(status)) {
6284 0 : printf("nt hardlink failed (%s)\n", nt_errstr(status));
6285 0 : return false;
6286 : }
6287 :
6288 : /* Open the original file. */
6289 4 : status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6290 : FILE_ATTRIBUTE_NORMAL,
6291 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6292 : FILE_OPEN_IF, 0, 0, &fnum, NULL);
6293 4 : if (!NT_STATUS_IS_OK(status)) {
6294 0 : printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6295 0 : return false;
6296 : }
6297 :
6298 : /* Unlink the hard link path. */
6299 4 : status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6300 : FILE_ATTRIBUTE_NORMAL,
6301 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6302 : FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6303 4 : if (!NT_STATUS_IS_OK(status)) {
6304 0 : printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6305 0 : return false;
6306 : }
6307 4 : status = cli_nt_delete_on_close(cli, fnum1, true);
6308 4 : if (!NT_STATUS_IS_OK(status)) {
6309 0 : d_printf("(%s) failed to set delete_on_close %s: %s\n",
6310 : __location__, fname_ln, nt_errstr(status));
6311 0 : return false;
6312 : }
6313 :
6314 4 : status = cli_close(cli, fnum1);
6315 4 : if (!NT_STATUS_IS_OK(status)) {
6316 0 : printf("close %s failed (%s)\n",
6317 : fname_ln, nt_errstr(status));
6318 0 : return false;
6319 : }
6320 :
6321 4 : status = cli_close(cli, fnum);
6322 4 : if (!NT_STATUS_IS_OK(status)) {
6323 0 : printf("close %s failed (%s)\n",
6324 : fname, nt_errstr(status));
6325 0 : return false;
6326 : }
6327 :
6328 : /* Ensure the original file is still there. */
6329 4 : status = cli_getatr(cli, fname, NULL, NULL, &t);
6330 4 : if (!NT_STATUS_IS_OK(status)) {
6331 0 : printf("%s getatr on file %s failed (%s)\n",
6332 : __location__,
6333 : fname,
6334 : nt_errstr(status));
6335 0 : correct = False;
6336 : }
6337 :
6338 : /* Ensure the link path is gone. */
6339 4 : status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6340 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6341 0 : printf("%s, getatr for file %s returned wrong error code %s "
6342 : "- should have been deleted\n",
6343 : __location__,
6344 : fname_ln, nt_errstr(status));
6345 0 : correct = False;
6346 : }
6347 :
6348 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6349 4 : cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6350 :
6351 4 : if (!torture_close_connection(cli)) {
6352 0 : correct = false;
6353 : }
6354 :
6355 4 : printf("finished deletetest-ln\n");
6356 :
6357 4 : return correct;
6358 : }
6359 :
6360 : /*
6361 : print out server properties
6362 : */
6363 5 : static bool run_properties(int dummy)
6364 : {
6365 0 : struct cli_state *cli;
6366 5 : bool correct = True;
6367 :
6368 5 : printf("starting properties test\n");
6369 :
6370 5 : ZERO_STRUCT(cli);
6371 :
6372 5 : if (!torture_open_connection(&cli, 0)) {
6373 0 : return False;
6374 : }
6375 :
6376 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6377 :
6378 5 : d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6379 :
6380 5 : if (!torture_close_connection(cli)) {
6381 0 : correct = False;
6382 : }
6383 :
6384 5 : return correct;
6385 : }
6386 :
6387 :
6388 :
6389 : /* FIRST_DESIRED_ACCESS 0xf019f */
6390 : #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6391 : FILE_READ_EA| /* 0xf */ \
6392 : FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
6393 : FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
6394 : DELETE_ACCESS|READ_CONTROL_ACCESS|\
6395 : WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
6396 : /* SECOND_DESIRED_ACCESS 0xe0080 */
6397 : #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6398 : READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6399 : WRITE_OWNER_ACCESS /* 0xe0000 */
6400 :
6401 : #if 0
6402 : #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6403 : READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6404 : FILE_READ_DATA|\
6405 : WRITE_OWNER_ACCESS /* */
6406 : #endif
6407 :
6408 : /*
6409 : Test ntcreate calls made by xcopy
6410 : */
6411 5 : static bool run_xcopy(int dummy)
6412 : {
6413 0 : static struct cli_state *cli1;
6414 5 : const char *fname = "\\test.txt";
6415 5 : bool correct = True;
6416 0 : uint16_t fnum1, fnum2;
6417 0 : NTSTATUS status;
6418 :
6419 5 : printf("starting xcopy test\n");
6420 :
6421 5 : if (!torture_open_connection(&cli1, 0)) {
6422 0 : return False;
6423 : }
6424 :
6425 5 : status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6426 : FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6427 : FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6428 5 : if (!NT_STATUS_IS_OK(status)) {
6429 0 : printf("First open failed - %s\n", nt_errstr(status));
6430 0 : return False;
6431 : }
6432 :
6433 5 : status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6434 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6435 : FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6436 5 : if (!NT_STATUS_IS_OK(status)) {
6437 0 : printf("second open failed - %s\n", nt_errstr(status));
6438 0 : return False;
6439 : }
6440 :
6441 5 : if (!torture_close_connection(cli1)) {
6442 0 : correct = False;
6443 : }
6444 :
6445 5 : return correct;
6446 : }
6447 :
6448 : /*
6449 : Test rename on files open with share delete and no share delete.
6450 : */
6451 5 : static bool run_rename(int dummy)
6452 : {
6453 0 : static struct cli_state *cli1;
6454 5 : const char *fname = "\\test.txt";
6455 5 : const char *fname1 = "\\test1.txt";
6456 5 : bool correct = True;
6457 0 : uint16_t fnum1;
6458 0 : uint32_t attr;
6459 0 : NTSTATUS status;
6460 :
6461 5 : printf("starting rename test\n");
6462 :
6463 5 : if (!torture_open_connection(&cli1, 0)) {
6464 0 : return False;
6465 : }
6466 :
6467 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6468 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6469 :
6470 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6471 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6472 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6473 5 : if (!NT_STATUS_IS_OK(status)) {
6474 0 : printf("First open failed - %s\n", nt_errstr(status));
6475 0 : return False;
6476 : }
6477 :
6478 5 : status = cli_rename(cli1, fname, fname1, false);
6479 5 : if (!NT_STATUS_IS_OK(status)) {
6480 5 : printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6481 : } else {
6482 0 : printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6483 0 : correct = False;
6484 : }
6485 :
6486 5 : status = cli_close(cli1, fnum1);
6487 5 : if (!NT_STATUS_IS_OK(status)) {
6488 0 : printf("close - 1 failed (%s)\n", nt_errstr(status));
6489 0 : return False;
6490 : }
6491 :
6492 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6493 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6494 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6495 : #if 0
6496 : FILE_SHARE_DELETE|FILE_SHARE_NONE,
6497 : #else
6498 : FILE_SHARE_DELETE|FILE_SHARE_READ,
6499 : #endif
6500 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6501 5 : if (!NT_STATUS_IS_OK(status)) {
6502 0 : printf("Second open failed - %s\n", nt_errstr(status));
6503 0 : return False;
6504 : }
6505 :
6506 5 : status = cli_rename(cli1, fname, fname1, false);
6507 5 : if (!NT_STATUS_IS_OK(status)) {
6508 0 : printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6509 0 : correct = False;
6510 : } else {
6511 5 : printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6512 : }
6513 :
6514 5 : status = cli_close(cli1, fnum1);
6515 5 : if (!NT_STATUS_IS_OK(status)) {
6516 0 : printf("close - 2 failed (%s)\n", nt_errstr(status));
6517 0 : return False;
6518 : }
6519 :
6520 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6521 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6522 :
6523 5 : status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6524 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6525 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6526 5 : if (!NT_STATUS_IS_OK(status)) {
6527 0 : printf("Third open failed - %s\n", nt_errstr(status));
6528 0 : return False;
6529 : }
6530 :
6531 :
6532 5 : status = cli_rename(cli1, fname, fname1, false);
6533 5 : if (!NT_STATUS_IS_OK(status)) {
6534 0 : printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6535 0 : correct = False;
6536 : } else {
6537 5 : printf("Third rename succeeded (SHARE_NONE)\n");
6538 : }
6539 :
6540 5 : status = cli_close(cli1, fnum1);
6541 5 : if (!NT_STATUS_IS_OK(status)) {
6542 0 : printf("close - 3 failed (%s)\n", nt_errstr(status));
6543 0 : return False;
6544 : }
6545 :
6546 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6547 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6548 :
6549 : /*----*/
6550 :
6551 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6552 : FILE_ATTRIBUTE_NORMAL,
6553 : FILE_SHARE_READ | FILE_SHARE_WRITE,
6554 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6555 5 : if (!NT_STATUS_IS_OK(status)) {
6556 0 : printf("Fourth open failed - %s\n", nt_errstr(status));
6557 0 : return False;
6558 : }
6559 :
6560 5 : status = cli_rename(cli1, fname, fname1, false);
6561 5 : if (!NT_STATUS_IS_OK(status)) {
6562 5 : printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6563 : } else {
6564 0 : printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6565 0 : correct = False;
6566 : }
6567 :
6568 5 : status = cli_close(cli1, fnum1);
6569 5 : if (!NT_STATUS_IS_OK(status)) {
6570 0 : printf("close - 4 failed (%s)\n", nt_errstr(status));
6571 0 : return False;
6572 : }
6573 :
6574 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6575 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6576 :
6577 : /*--*/
6578 :
6579 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6580 : FILE_ATTRIBUTE_NORMAL,
6581 : FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6582 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6583 5 : if (!NT_STATUS_IS_OK(status)) {
6584 0 : printf("Fifth open failed - %s\n", nt_errstr(status));
6585 0 : return False;
6586 : }
6587 :
6588 5 : status = cli_rename(cli1, fname, fname1, false);
6589 5 : if (!NT_STATUS_IS_OK(status)) {
6590 0 : printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6591 0 : correct = False;
6592 : } else {
6593 5 : printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6594 : }
6595 :
6596 : /*--*/
6597 5 : status = cli_close(cli1, fnum1);
6598 5 : if (!NT_STATUS_IS_OK(status)) {
6599 0 : printf("close - 5 failed (%s)\n", nt_errstr(status));
6600 0 : return False;
6601 : }
6602 :
6603 : /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6604 5 : status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6605 5 : if (!NT_STATUS_IS_OK(status)) {
6606 0 : printf("getatr on file %s failed - %s ! \n",
6607 : fname1, nt_errstr(status));
6608 0 : correct = False;
6609 : } else {
6610 5 : if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6611 0 : printf("Renamed file %s has wrong attr 0x%x "
6612 : "(should be 0x%x)\n",
6613 : fname1,
6614 : attr,
6615 : (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6616 0 : correct = False;
6617 : } else {
6618 5 : printf("Renamed file %s has archive bit set\n", fname1);
6619 : }
6620 : }
6621 :
6622 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6623 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6624 :
6625 5 : if (!torture_close_connection(cli1)) {
6626 0 : correct = False;
6627 : }
6628 :
6629 5 : return correct;
6630 : }
6631 :
6632 : /*
6633 : Test rename into a directory with an ACL denying it.
6634 : */
6635 4 : static bool run_rename_access(int dummy)
6636 : {
6637 0 : static struct cli_state *cli = NULL;
6638 0 : static struct cli_state *posix_cli = NULL;
6639 4 : const char *src = "test.txt";
6640 4 : const char *dname = "dir";
6641 4 : const char *dst = "dir\\test.txt";
6642 4 : const char *dsrc = "test.dir";
6643 4 : const char *ddst = "dir\\test.dir";
6644 4 : uint16_t fnum = (uint16_t)-1;
6645 4 : struct security_descriptor *sd = NULL;
6646 4 : struct security_descriptor *newsd = NULL;
6647 0 : NTSTATUS status;
6648 4 : TALLOC_CTX *frame = NULL;
6649 :
6650 4 : frame = talloc_stackframe();
6651 4 : printf("starting rename access test\n");
6652 :
6653 : /* Windows connection. */
6654 4 : if (!torture_open_connection(&cli, 0)) {
6655 0 : goto fail;
6656 : }
6657 :
6658 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6659 :
6660 : /* Posix connection. */
6661 4 : if (!torture_open_connection(&posix_cli, 0)) {
6662 0 : goto fail;
6663 : }
6664 :
6665 4 : smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6666 :
6667 4 : status = torture_setup_unix_extensions(posix_cli);
6668 4 : if (!NT_STATUS_IS_OK(status)) {
6669 0 : goto fail;
6670 : }
6671 :
6672 : /* Start with a clean slate. */
6673 4 : cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6674 4 : cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6675 4 : cli_rmdir(cli, dsrc);
6676 4 : cli_rmdir(cli, ddst);
6677 4 : cli_rmdir(cli, dname);
6678 :
6679 : /*
6680 : * Setup the destination directory with a DENY ACE to
6681 : * prevent new files within it.
6682 : */
6683 4 : status = cli_ntcreate(cli,
6684 : dname,
6685 : 0,
6686 : FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6687 : WRITE_DAC_ACCESS|FILE_READ_DATA|
6688 : WRITE_OWNER_ACCESS,
6689 : FILE_ATTRIBUTE_DIRECTORY,
6690 : FILE_SHARE_READ|FILE_SHARE_WRITE,
6691 : FILE_CREATE,
6692 : FILE_DIRECTORY_FILE,
6693 : 0,
6694 : &fnum,
6695 : NULL);
6696 4 : if (!NT_STATUS_IS_OK(status)) {
6697 0 : printf("Create of %s - %s\n", dname, nt_errstr(status));
6698 0 : goto fail;
6699 : }
6700 :
6701 4 : status = cli_query_secdesc(cli,
6702 : fnum,
6703 : frame,
6704 : &sd);
6705 4 : if (!NT_STATUS_IS_OK(status)) {
6706 0 : printf("cli_query_secdesc failed for %s (%s)\n",
6707 : dname, nt_errstr(status));
6708 0 : goto fail;
6709 : }
6710 :
6711 4 : newsd = security_descriptor_dacl_create(frame,
6712 : 0,
6713 : NULL,
6714 : NULL,
6715 : SID_WORLD,
6716 : SEC_ACE_TYPE_ACCESS_DENIED,
6717 : SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6718 : 0,
6719 : NULL);
6720 4 : if (newsd == NULL) {
6721 0 : goto fail;
6722 : }
6723 8 : sd->dacl = security_acl_concatenate(frame,
6724 4 : newsd->dacl,
6725 4 : sd->dacl);
6726 4 : if (sd->dacl == NULL) {
6727 0 : goto fail;
6728 : }
6729 4 : status = cli_set_secdesc(cli, fnum, sd);
6730 4 : if (!NT_STATUS_IS_OK(status)) {
6731 0 : printf("cli_set_secdesc failed for %s (%s)\n",
6732 : dname, nt_errstr(status));
6733 0 : goto fail;
6734 : }
6735 4 : status = cli_close(cli, fnum);
6736 4 : if (!NT_STATUS_IS_OK(status)) {
6737 0 : printf("close failed for %s (%s)\n",
6738 : dname, nt_errstr(status));
6739 0 : goto fail;
6740 : }
6741 : /* Now go around the back and chmod to 777 via POSIX. */
6742 4 : status = cli_posix_chmod(posix_cli, dname, 0777);
6743 4 : if (!NT_STATUS_IS_OK(status)) {
6744 0 : printf("cli_posix_chmod failed for %s (%s)\n",
6745 : dname, nt_errstr(status));
6746 0 : goto fail;
6747 : }
6748 :
6749 : /* Check we can't create a file within dname via Windows. */
6750 4 : status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6751 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6752 0 : cli_close(posix_cli, fnum);
6753 0 : printf("Create of %s should be ACCESS denied, was %s\n",
6754 : dst, nt_errstr(status));
6755 0 : goto fail;
6756 : }
6757 :
6758 : /* Make the sample file/directory. */
6759 4 : status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6760 4 : if (!NT_STATUS_IS_OK(status)) {
6761 0 : printf("open of %s failed (%s)\n", src, nt_errstr(status));
6762 0 : goto fail;
6763 : }
6764 4 : status = cli_close(cli, fnum);
6765 4 : if (!NT_STATUS_IS_OK(status)) {
6766 0 : printf("cli_close failed (%s)\n", nt_errstr(status));
6767 0 : goto fail;
6768 : }
6769 :
6770 4 : status = cli_mkdir(cli, dsrc);
6771 4 : if (!NT_STATUS_IS_OK(status)) {
6772 0 : printf("cli_mkdir of %s failed (%s)\n",
6773 : dsrc, nt_errstr(status));
6774 0 : goto fail;
6775 : }
6776 :
6777 : /*
6778 : * OK - renames of the new file and directory into the
6779 : * dst directory should fail.
6780 : */
6781 :
6782 4 : status = cli_rename(cli, src, dst, false);
6783 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6784 0 : printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6785 : src, dst, nt_errstr(status));
6786 0 : goto fail;
6787 : }
6788 4 : status = cli_rename(cli, dsrc, ddst, false);
6789 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6790 0 : printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6791 : src, dst, nt_errstr(status));
6792 0 : goto fail;
6793 : }
6794 :
6795 4 : TALLOC_FREE(frame);
6796 4 : return true;
6797 :
6798 0 : fail:
6799 :
6800 0 : if (posix_cli) {
6801 0 : torture_close_connection(posix_cli);
6802 : }
6803 :
6804 0 : if (cli) {
6805 0 : if (fnum != (uint16_t)-1) {
6806 0 : cli_close(cli, fnum);
6807 : }
6808 0 : cli_unlink(cli, src,
6809 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6810 0 : cli_unlink(cli, dst,
6811 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6812 0 : cli_rmdir(cli, dsrc);
6813 0 : cli_rmdir(cli, ddst);
6814 0 : cli_rmdir(cli, dname);
6815 :
6816 0 : torture_close_connection(cli);
6817 : }
6818 :
6819 0 : TALLOC_FREE(frame);
6820 0 : return false;
6821 : }
6822 :
6823 : /*
6824 : Test owner rights ACE.
6825 : */
6826 4 : static bool run_owner_rights(int dummy)
6827 : {
6828 0 : static struct cli_state *cli = NULL;
6829 4 : const char *fname = "owner_rights.txt";
6830 4 : uint16_t fnum = (uint16_t)-1;
6831 4 : struct security_descriptor *sd = NULL;
6832 4 : struct security_descriptor *newsd = NULL;
6833 0 : NTSTATUS status;
6834 4 : TALLOC_CTX *frame = NULL;
6835 :
6836 4 : frame = talloc_stackframe();
6837 4 : printf("starting owner rights test\n");
6838 :
6839 : /* Windows connection. */
6840 4 : if (!torture_open_connection(&cli, 0)) {
6841 0 : goto fail;
6842 : }
6843 :
6844 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6845 :
6846 : /* Start with a clean slate. */
6847 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6848 :
6849 : /* Create the test file. */
6850 : /* Now try and open for read and write-dac. */
6851 4 : status = cli_ntcreate(cli,
6852 : fname,
6853 : 0,
6854 : GENERIC_ALL_ACCESS,
6855 : FILE_ATTRIBUTE_NORMAL,
6856 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6857 : FILE_SHARE_DELETE,
6858 : FILE_CREATE,
6859 : 0,
6860 : 0,
6861 : &fnum,
6862 : NULL);
6863 4 : if (!NT_STATUS_IS_OK(status)) {
6864 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
6865 0 : goto fail;
6866 : }
6867 :
6868 : /* Get the original SD. */
6869 4 : status = cli_query_secdesc(cli,
6870 : fnum,
6871 : frame,
6872 : &sd);
6873 4 : if (!NT_STATUS_IS_OK(status)) {
6874 0 : printf("cli_query_secdesc failed for %s (%s)\n",
6875 : fname, nt_errstr(status));
6876 0 : goto fail;
6877 : }
6878 :
6879 : /*
6880 : * Add an "owner-rights" ACE denying WRITE_DATA,
6881 : * and an "owner-rights" ACE allowing READ_DATA.
6882 : */
6883 :
6884 4 : newsd = security_descriptor_dacl_create(frame,
6885 : 0,
6886 : NULL,
6887 : NULL,
6888 : SID_OWNER_RIGHTS,
6889 : SEC_ACE_TYPE_ACCESS_DENIED,
6890 : FILE_WRITE_DATA,
6891 : 0,
6892 : SID_OWNER_RIGHTS,
6893 : SEC_ACE_TYPE_ACCESS_ALLOWED,
6894 : FILE_READ_DATA,
6895 : 0,
6896 : NULL);
6897 4 : if (newsd == NULL) {
6898 0 : goto fail;
6899 : }
6900 8 : sd->dacl = security_acl_concatenate(frame,
6901 4 : newsd->dacl,
6902 4 : sd->dacl);
6903 4 : if (sd->dacl == NULL) {
6904 0 : goto fail;
6905 : }
6906 4 : status = cli_set_secdesc(cli, fnum, sd);
6907 4 : if (!NT_STATUS_IS_OK(status)) {
6908 0 : printf("cli_set_secdesc failed for %s (%s)\n",
6909 : fname, nt_errstr(status));
6910 0 : goto fail;
6911 : }
6912 4 : status = cli_close(cli, fnum);
6913 4 : if (!NT_STATUS_IS_OK(status)) {
6914 0 : printf("close failed for %s (%s)\n",
6915 : fname, nt_errstr(status));
6916 0 : goto fail;
6917 : }
6918 4 : fnum = (uint16_t)-1;
6919 :
6920 : /* Try and open for FILE_WRITE_DATA */
6921 4 : status = cli_ntcreate(cli,
6922 : fname,
6923 : 0,
6924 : FILE_WRITE_DATA,
6925 : FILE_ATTRIBUTE_NORMAL,
6926 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6927 : FILE_SHARE_DELETE,
6928 : FILE_OPEN,
6929 : 0,
6930 : 0,
6931 : &fnum,
6932 : NULL);
6933 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6934 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
6935 0 : goto fail;
6936 : }
6937 :
6938 : /* Now try and open for FILE_READ_DATA */
6939 4 : status = cli_ntcreate(cli,
6940 : fname,
6941 : 0,
6942 : FILE_READ_DATA,
6943 : FILE_ATTRIBUTE_NORMAL,
6944 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6945 : FILE_SHARE_DELETE,
6946 : FILE_OPEN,
6947 : 0,
6948 : 0,
6949 : &fnum,
6950 : NULL);
6951 4 : if (!NT_STATUS_IS_OK(status)) {
6952 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
6953 0 : goto fail;
6954 : }
6955 :
6956 4 : status = cli_close(cli, fnum);
6957 4 : if (!NT_STATUS_IS_OK(status)) {
6958 0 : printf("close failed for %s (%s)\n",
6959 : fname, nt_errstr(status));
6960 0 : goto fail;
6961 : }
6962 :
6963 : /* Restore clean slate. */
6964 4 : TALLOC_FREE(sd);
6965 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6966 :
6967 : /* Create the test file. */
6968 4 : status = cli_ntcreate(cli,
6969 : fname,
6970 : 0,
6971 : GENERIC_ALL_ACCESS,
6972 : FILE_ATTRIBUTE_NORMAL,
6973 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6974 : FILE_SHARE_DELETE,
6975 : FILE_CREATE,
6976 : 0,
6977 : 0,
6978 : &fnum,
6979 : NULL);
6980 4 : if (!NT_STATUS_IS_OK(status)) {
6981 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
6982 0 : goto fail;
6983 : }
6984 :
6985 : /* Get the original SD. */
6986 4 : status = cli_query_secdesc(cli,
6987 : fnum,
6988 : frame,
6989 : &sd);
6990 4 : if (!NT_STATUS_IS_OK(status)) {
6991 0 : printf("cli_query_secdesc failed for %s (%s)\n",
6992 : fname, nt_errstr(status));
6993 0 : goto fail;
6994 : }
6995 :
6996 : /*
6997 : * Add an "owner-rights ACE denying WRITE_DATA,
6998 : * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6999 : */
7000 :
7001 4 : newsd = security_descriptor_dacl_create(frame,
7002 : 0,
7003 : NULL,
7004 : NULL,
7005 : SID_OWNER_RIGHTS,
7006 : SEC_ACE_TYPE_ACCESS_DENIED,
7007 : FILE_WRITE_DATA,
7008 : 0,
7009 : SID_OWNER_RIGHTS,
7010 : SEC_ACE_TYPE_ACCESS_ALLOWED,
7011 : FILE_READ_DATA|FILE_WRITE_DATA,
7012 : 0,
7013 : NULL);
7014 4 : if (newsd == NULL) {
7015 0 : goto fail;
7016 : }
7017 8 : sd->dacl = security_acl_concatenate(frame,
7018 4 : newsd->dacl,
7019 4 : sd->dacl);
7020 4 : if (sd->dacl == NULL) {
7021 0 : goto fail;
7022 : }
7023 4 : status = cli_set_secdesc(cli, fnum, sd);
7024 4 : if (!NT_STATUS_IS_OK(status)) {
7025 0 : printf("cli_set_secdesc failed for %s (%s)\n",
7026 : fname, nt_errstr(status));
7027 0 : goto fail;
7028 : }
7029 4 : status = cli_close(cli, fnum);
7030 4 : if (!NT_STATUS_IS_OK(status)) {
7031 0 : printf("close failed for %s (%s)\n",
7032 : fname, nt_errstr(status));
7033 0 : goto fail;
7034 : }
7035 4 : fnum = (uint16_t)-1;
7036 :
7037 : /* Try and open for FILE_WRITE_DATA */
7038 4 : status = cli_ntcreate(cli,
7039 : fname,
7040 : 0,
7041 : FILE_WRITE_DATA,
7042 : FILE_ATTRIBUTE_NORMAL,
7043 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7044 : FILE_SHARE_DELETE,
7045 : FILE_OPEN,
7046 : 0,
7047 : 0,
7048 : &fnum,
7049 : NULL);
7050 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7051 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
7052 0 : goto fail;
7053 : }
7054 :
7055 : /* Now try and open for FILE_READ_DATA */
7056 4 : status = cli_ntcreate(cli,
7057 : fname,
7058 : 0,
7059 : FILE_READ_DATA,
7060 : FILE_ATTRIBUTE_NORMAL,
7061 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7062 : FILE_SHARE_DELETE,
7063 : FILE_OPEN,
7064 : 0,
7065 : 0,
7066 : &fnum,
7067 : NULL);
7068 4 : if (!NT_STATUS_IS_OK(status)) {
7069 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
7070 0 : goto fail;
7071 : }
7072 :
7073 4 : status = cli_close(cli, fnum);
7074 4 : if (!NT_STATUS_IS_OK(status)) {
7075 0 : printf("close failed for %s (%s)\n",
7076 : fname, nt_errstr(status));
7077 0 : goto fail;
7078 : }
7079 :
7080 : /* Restore clean slate. */
7081 4 : TALLOC_FREE(sd);
7082 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7083 :
7084 :
7085 : /* Create the test file. */
7086 4 : status = cli_ntcreate(cli,
7087 : fname,
7088 : 0,
7089 : GENERIC_ALL_ACCESS,
7090 : FILE_ATTRIBUTE_NORMAL,
7091 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7092 : FILE_SHARE_DELETE,
7093 : FILE_CREATE,
7094 : 0,
7095 : 0,
7096 : &fnum,
7097 : NULL);
7098 4 : if (!NT_STATUS_IS_OK(status)) {
7099 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
7100 0 : goto fail;
7101 : }
7102 :
7103 : /* Get the original SD. */
7104 4 : status = cli_query_secdesc(cli,
7105 : fnum,
7106 : frame,
7107 : &sd);
7108 4 : if (!NT_STATUS_IS_OK(status)) {
7109 0 : printf("cli_query_secdesc failed for %s (%s)\n",
7110 : fname, nt_errstr(status));
7111 0 : goto fail;
7112 : }
7113 :
7114 : /*
7115 : * Add an "authenticated users" ACE allowing READ_DATA,
7116 : * add an "owner-rights" denying READ_DATA,
7117 : * and an "authenticated users" ACE allowing WRITE_DATA.
7118 : */
7119 :
7120 4 : newsd = security_descriptor_dacl_create(frame,
7121 : 0,
7122 : NULL,
7123 : NULL,
7124 : SID_NT_AUTHENTICATED_USERS,
7125 : SEC_ACE_TYPE_ACCESS_ALLOWED,
7126 : FILE_READ_DATA,
7127 : 0,
7128 : SID_OWNER_RIGHTS,
7129 : SEC_ACE_TYPE_ACCESS_DENIED,
7130 : FILE_READ_DATA,
7131 : 0,
7132 : SID_NT_AUTHENTICATED_USERS,
7133 : SEC_ACE_TYPE_ACCESS_ALLOWED,
7134 : FILE_WRITE_DATA,
7135 : 0,
7136 : NULL);
7137 4 : if (newsd == NULL) {
7138 0 : printf("newsd == NULL\n");
7139 0 : goto fail;
7140 : }
7141 8 : sd->dacl = security_acl_concatenate(frame,
7142 4 : newsd->dacl,
7143 4 : sd->dacl);
7144 4 : if (sd->dacl == NULL) {
7145 0 : printf("sd->dacl == NULL\n");
7146 0 : goto fail;
7147 : }
7148 4 : status = cli_set_secdesc(cli, fnum, sd);
7149 4 : if (!NT_STATUS_IS_OK(status)) {
7150 0 : printf("cli_set_secdesc failed for %s (%s)\n",
7151 : fname, nt_errstr(status));
7152 0 : goto fail;
7153 : }
7154 4 : status = cli_close(cli, fnum);
7155 4 : if (!NT_STATUS_IS_OK(status)) {
7156 0 : printf("close failed for %s (%s)\n",
7157 : fname, nt_errstr(status));
7158 0 : goto fail;
7159 : }
7160 4 : fnum = (uint16_t)-1;
7161 :
7162 : /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7163 4 : status = cli_ntcreate(cli,
7164 : fname,
7165 : 0,
7166 : FILE_READ_DATA|FILE_WRITE_DATA,
7167 : FILE_ATTRIBUTE_NORMAL,
7168 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7169 : FILE_SHARE_DELETE,
7170 : FILE_OPEN,
7171 : 0,
7172 : 0,
7173 : &fnum,
7174 : NULL);
7175 4 : if (!NT_STATUS_IS_OK(status)) {
7176 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
7177 0 : goto fail;
7178 : }
7179 :
7180 4 : status = cli_close(cli, fnum);
7181 4 : if (!NT_STATUS_IS_OK(status)) {
7182 0 : printf("close failed for %s (%s)\n",
7183 : fname, nt_errstr(status));
7184 0 : goto fail;
7185 : }
7186 :
7187 4 : cli_unlink(cli, fname,
7188 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7189 :
7190 4 : TALLOC_FREE(frame);
7191 4 : return true;
7192 :
7193 0 : fail:
7194 :
7195 0 : if (cli) {
7196 0 : if (fnum != (uint16_t)-1) {
7197 0 : cli_close(cli, fnum);
7198 : }
7199 0 : cli_unlink(cli, fname,
7200 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7201 0 : torture_close_connection(cli);
7202 : }
7203 :
7204 0 : TALLOC_FREE(frame);
7205 0 : return false;
7206 : }
7207 :
7208 : /*
7209 : * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7210 : * Note this test only works with a user with SeSecurityPrivilege set.
7211 : *
7212 : * NB. This is also tested in samba3.base.createx_access
7213 : * but this makes it very explicit what we're looking for.
7214 : */
7215 2 : static bool run_smb1_system_security(int dummy)
7216 : {
7217 0 : static struct cli_state *cli = NULL;
7218 2 : const char *fname = "system_security.txt";
7219 2 : uint16_t fnum = (uint16_t)-1;
7220 0 : NTSTATUS status;
7221 2 : TALLOC_CTX *frame = NULL;
7222 :
7223 2 : frame = talloc_stackframe();
7224 2 : printf("starting smb1 system security test\n");
7225 :
7226 : /* SMB1 connection - torture_open_connection() forces this. */
7227 2 : if (!torture_open_connection(&cli, 0)) {
7228 0 : goto fail;
7229 : }
7230 :
7231 2 : smbXcli_conn_set_sockopt(cli->conn, sockops);
7232 :
7233 : /* Start with a clean slate. */
7234 2 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7235 :
7236 : /* Create the test file. */
7237 2 : status = cli_ntcreate(cli,
7238 : fname,
7239 : 0,
7240 : GENERIC_ALL_ACCESS,
7241 : FILE_ATTRIBUTE_NORMAL,
7242 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7243 : FILE_SHARE_DELETE,
7244 : FILE_CREATE,
7245 : 0,
7246 : 0,
7247 : &fnum,
7248 : NULL);
7249 2 : if (!NT_STATUS_IS_OK(status)) {
7250 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
7251 0 : goto fail;
7252 : }
7253 :
7254 2 : status = cli_close(cli, fnum);
7255 :
7256 : /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7257 : /*
7258 : * On SMB1 this succeeds - SMB2 it fails,
7259 : * see the SMB2-SACL test.
7260 : */
7261 2 : status = cli_ntcreate(cli,
7262 : fname,
7263 : 0,
7264 : SEC_FLAG_SYSTEM_SECURITY,
7265 : FILE_ATTRIBUTE_NORMAL,
7266 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7267 : FILE_SHARE_DELETE,
7268 : FILE_OPEN,
7269 : 0,
7270 : 0,
7271 : &fnum,
7272 : NULL);
7273 2 : if (!NT_STATUS_IS_OK(status)) {
7274 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
7275 0 : goto fail;
7276 : }
7277 :
7278 2 : status = cli_close(cli, fnum);
7279 :
7280 2 : cli_unlink(cli, fname,
7281 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7282 :
7283 2 : torture_close_connection(cli);
7284 2 : TALLOC_FREE(frame);
7285 2 : return true;
7286 :
7287 0 : fail:
7288 :
7289 0 : if (cli) {
7290 0 : if (fnum != (uint16_t)-1) {
7291 0 : cli_close(cli, fnum);
7292 : }
7293 0 : cli_unlink(cli, fname,
7294 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7295 0 : torture_close_connection(cli);
7296 : }
7297 :
7298 0 : TALLOC_FREE(frame);
7299 0 : return false;
7300 : }
7301 :
7302 0 : static bool run_pipe_number(int dummy)
7303 : {
7304 0 : struct cli_state *cli1;
7305 0 : const char *pipe_name = "\\SPOOLSS";
7306 0 : uint16_t fnum;
7307 0 : int num_pipes = 0;
7308 0 : NTSTATUS status;
7309 :
7310 0 : printf("starting pipenumber test\n");
7311 0 : if (!torture_open_connection(&cli1, 0)) {
7312 0 : return False;
7313 : }
7314 :
7315 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
7316 0 : while(1) {
7317 0 : status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7318 : FILE_ATTRIBUTE_NORMAL,
7319 : FILE_SHARE_READ|FILE_SHARE_WRITE,
7320 : FILE_OPEN_IF, 0, 0, &fnum, NULL);
7321 0 : if (!NT_STATUS_IS_OK(status)) {
7322 0 : printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7323 0 : break;
7324 : }
7325 0 : num_pipes++;
7326 0 : printf("\r%6d", num_pipes);
7327 : }
7328 :
7329 0 : printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7330 0 : torture_close_connection(cli1);
7331 0 : return True;
7332 : }
7333 :
7334 : /*
7335 : Test open mode returns on read-only files.
7336 : */
7337 5 : static bool run_opentest(int dummy)
7338 : {
7339 0 : static struct cli_state *cli1;
7340 0 : static struct cli_state *cli2;
7341 5 : const char *fname = "\\readonly.file";
7342 0 : uint16_t fnum1, fnum2;
7343 0 : char buf[20];
7344 0 : off_t fsize;
7345 5 : bool correct = True;
7346 0 : char *tmp_path;
7347 0 : NTSTATUS status;
7348 :
7349 5 : printf("starting open test\n");
7350 :
7351 5 : if (!torture_open_connection(&cli1, 0)) {
7352 0 : return False;
7353 : }
7354 :
7355 5 : cli_setatr(cli1, fname, 0, 0);
7356 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7357 :
7358 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
7359 :
7360 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7361 5 : if (!NT_STATUS_IS_OK(status)) {
7362 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7363 0 : return False;
7364 : }
7365 :
7366 5 : status = cli_close(cli1, fnum1);
7367 5 : if (!NT_STATUS_IS_OK(status)) {
7368 0 : printf("close2 failed (%s)\n", nt_errstr(status));
7369 0 : return False;
7370 : }
7371 :
7372 5 : status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7373 5 : if (!NT_STATUS_IS_OK(status)) {
7374 0 : printf("cli_setatr failed (%s)\n", nt_errstr(status));
7375 0 : return False;
7376 : }
7377 :
7378 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7379 5 : if (!NT_STATUS_IS_OK(status)) {
7380 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7381 0 : return False;
7382 : }
7383 :
7384 : /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7385 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7386 :
7387 5 : if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7388 5 : NT_STATUS_ACCESS_DENIED)) {
7389 4 : printf("correct error code ERRDOS/ERRnoaccess returned\n");
7390 : }
7391 :
7392 5 : printf("finished open test 1\n");
7393 :
7394 5 : cli_close(cli1, fnum1);
7395 :
7396 : /* Now try not readonly and ensure ERRbadshare is returned. */
7397 :
7398 5 : cli_setatr(cli1, fname, 0, 0);
7399 :
7400 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7401 5 : if (!NT_STATUS_IS_OK(status)) {
7402 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7403 0 : return False;
7404 : }
7405 :
7406 : /* This will fail - but the error should be ERRshare. */
7407 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7408 :
7409 5 : if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7410 5 : NT_STATUS_SHARING_VIOLATION)) {
7411 5 : printf("correct error code ERRDOS/ERRbadshare returned\n");
7412 : }
7413 :
7414 5 : status = cli_close(cli1, fnum1);
7415 5 : if (!NT_STATUS_IS_OK(status)) {
7416 0 : printf("close2 failed (%s)\n", nt_errstr(status));
7417 0 : return False;
7418 : }
7419 :
7420 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7421 :
7422 5 : printf("finished open test 2\n");
7423 :
7424 : /* Test truncate open disposition on file opened for read. */
7425 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7426 5 : if (!NT_STATUS_IS_OK(status)) {
7427 0 : printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7428 0 : return False;
7429 : }
7430 :
7431 : /* write 20 bytes. */
7432 :
7433 5 : memset(buf, '\0', 20);
7434 :
7435 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7436 5 : if (!NT_STATUS_IS_OK(status)) {
7437 0 : printf("write failed (%s)\n", nt_errstr(status));
7438 0 : correct = False;
7439 : }
7440 :
7441 5 : status = cli_close(cli1, fnum1);
7442 5 : if (!NT_STATUS_IS_OK(status)) {
7443 0 : printf("(3) close1 failed (%s)\n", nt_errstr(status));
7444 0 : return False;
7445 : }
7446 :
7447 : /* Ensure size == 20. */
7448 5 : status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7449 5 : if (!NT_STATUS_IS_OK(status)) {
7450 0 : printf("(3) getatr failed (%s)\n", nt_errstr(status));
7451 0 : return False;
7452 : }
7453 :
7454 5 : if (fsize != 20) {
7455 0 : printf("(3) file size != 20\n");
7456 0 : return False;
7457 : }
7458 :
7459 : /* Now test if we can truncate a file opened for readonly. */
7460 5 : status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7461 5 : if (!NT_STATUS_IS_OK(status)) {
7462 0 : printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7463 0 : return False;
7464 : }
7465 :
7466 5 : status = cli_close(cli1, fnum1);
7467 5 : if (!NT_STATUS_IS_OK(status)) {
7468 0 : printf("close2 failed (%s)\n", nt_errstr(status));
7469 0 : return False;
7470 : }
7471 :
7472 : /* Ensure size == 0. */
7473 5 : status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7474 5 : if (!NT_STATUS_IS_OK(status)) {
7475 0 : printf("(3) getatr failed (%s)\n", nt_errstr(status));
7476 0 : return False;
7477 : }
7478 :
7479 5 : if (fsize != 0) {
7480 0 : printf("(3) file size != 0\n");
7481 0 : return False;
7482 : }
7483 5 : printf("finished open test 3\n");
7484 :
7485 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7486 :
7487 5 : printf("Do ctemp tests\n");
7488 5 : status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7489 5 : if (!NT_STATUS_IS_OK(status)) {
7490 0 : printf("ctemp failed (%s)\n", nt_errstr(status));
7491 0 : return False;
7492 : }
7493 :
7494 5 : printf("ctemp gave path %s\n", tmp_path);
7495 5 : status = cli_close(cli1, fnum1);
7496 5 : if (!NT_STATUS_IS_OK(status)) {
7497 0 : printf("close of temp failed (%s)\n", nt_errstr(status));
7498 : }
7499 :
7500 5 : status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7501 5 : if (!NT_STATUS_IS_OK(status)) {
7502 0 : printf("unlink of temp failed (%s)\n", nt_errstr(status));
7503 : }
7504 :
7505 : /* Test the non-io opens... */
7506 :
7507 5 : if (!torture_open_connection(&cli2, 1)) {
7508 0 : return False;
7509 : }
7510 :
7511 5 : cli_setatr(cli2, fname, 0, 0);
7512 5 : cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7513 :
7514 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
7515 :
7516 5 : printf("TEST #1 testing 2 non-io opens (no delete)\n");
7517 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7518 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7519 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7520 5 : if (!NT_STATUS_IS_OK(status)) {
7521 0 : printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7522 0 : return False;
7523 : }
7524 :
7525 5 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7526 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7527 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7528 5 : if (!NT_STATUS_IS_OK(status)) {
7529 0 : printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7530 0 : return False;
7531 : }
7532 :
7533 5 : status = cli_close(cli1, fnum1);
7534 5 : if (!NT_STATUS_IS_OK(status)) {
7535 0 : printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7536 0 : return False;
7537 : }
7538 :
7539 5 : status = cli_close(cli2, fnum2);
7540 5 : if (!NT_STATUS_IS_OK(status)) {
7541 0 : printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7542 0 : return False;
7543 : }
7544 :
7545 5 : printf("non-io open test #1 passed.\n");
7546 :
7547 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7548 :
7549 5 : printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7550 :
7551 5 : status = cli_ntcreate(cli1, fname, 0,
7552 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7553 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7554 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7555 5 : if (!NT_STATUS_IS_OK(status)) {
7556 0 : printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7557 0 : return False;
7558 : }
7559 :
7560 5 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7561 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7562 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7563 5 : if (!NT_STATUS_IS_OK(status)) {
7564 0 : printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7565 0 : return False;
7566 : }
7567 :
7568 5 : status = cli_close(cli1, fnum1);
7569 5 : if (!NT_STATUS_IS_OK(status)) {
7570 0 : printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7571 0 : return False;
7572 : }
7573 :
7574 5 : status = cli_close(cli2, fnum2);
7575 5 : if (!NT_STATUS_IS_OK(status)) {
7576 0 : printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7577 0 : return False;
7578 : }
7579 :
7580 5 : printf("non-io open test #2 passed.\n");
7581 :
7582 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7583 :
7584 5 : printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7585 :
7586 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7587 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7588 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7589 5 : if (!NT_STATUS_IS_OK(status)) {
7590 0 : printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7591 0 : return False;
7592 : }
7593 :
7594 5 : status = cli_ntcreate(cli2, fname, 0,
7595 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7596 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7597 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7598 5 : if (!NT_STATUS_IS_OK(status)) {
7599 0 : printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7600 0 : return False;
7601 : }
7602 :
7603 5 : status = cli_close(cli1, fnum1);
7604 5 : if (!NT_STATUS_IS_OK(status)) {
7605 0 : printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7606 0 : return False;
7607 : }
7608 :
7609 5 : status = cli_close(cli2, fnum2);
7610 5 : if (!NT_STATUS_IS_OK(status)) {
7611 0 : printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7612 0 : return False;
7613 : }
7614 :
7615 5 : printf("non-io open test #3 passed.\n");
7616 :
7617 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7618 :
7619 5 : printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7620 :
7621 5 : status = cli_ntcreate(cli1, fname, 0,
7622 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7623 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7624 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7625 5 : if (!NT_STATUS_IS_OK(status)) {
7626 0 : printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7627 0 : return False;
7628 : }
7629 :
7630 5 : status = cli_ntcreate(cli2, fname, 0,
7631 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7632 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7633 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7634 5 : if (NT_STATUS_IS_OK(status)) {
7635 0 : printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7636 0 : return False;
7637 : }
7638 :
7639 5 : printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7640 :
7641 5 : status = cli_close(cli1, fnum1);
7642 5 : if (!NT_STATUS_IS_OK(status)) {
7643 0 : printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7644 0 : return False;
7645 : }
7646 :
7647 5 : printf("non-io open test #4 passed.\n");
7648 :
7649 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7650 :
7651 5 : printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7652 :
7653 5 : status = cli_ntcreate(cli1, fname, 0,
7654 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7655 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7656 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7657 5 : if (!NT_STATUS_IS_OK(status)) {
7658 0 : printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7659 0 : return False;
7660 : }
7661 :
7662 5 : status = cli_ntcreate(cli2, fname, 0,
7663 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7664 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7665 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7666 5 : if (!NT_STATUS_IS_OK(status)) {
7667 0 : printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7668 0 : return False;
7669 : }
7670 :
7671 5 : status = cli_close(cli1, fnum1);
7672 5 : if (!NT_STATUS_IS_OK(status)) {
7673 0 : printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7674 0 : return False;
7675 : }
7676 :
7677 5 : status = cli_close(cli2, fnum2);
7678 5 : if (!NT_STATUS_IS_OK(status)) {
7679 0 : printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7680 0 : return False;
7681 : }
7682 :
7683 5 : printf("non-io open test #5 passed.\n");
7684 :
7685 5 : printf("TEST #6 testing 1 non-io open, one io open\n");
7686 :
7687 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7688 :
7689 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7690 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7691 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7692 5 : if (!NT_STATUS_IS_OK(status)) {
7693 0 : printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7694 0 : return False;
7695 : }
7696 :
7697 5 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7698 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7699 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7700 5 : if (!NT_STATUS_IS_OK(status)) {
7701 0 : printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7702 0 : return False;
7703 : }
7704 :
7705 5 : status = cli_close(cli1, fnum1);
7706 5 : if (!NT_STATUS_IS_OK(status)) {
7707 0 : printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7708 0 : return False;
7709 : }
7710 :
7711 5 : status = cli_close(cli2, fnum2);
7712 5 : if (!NT_STATUS_IS_OK(status)) {
7713 0 : printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7714 0 : return False;
7715 : }
7716 :
7717 5 : printf("non-io open test #6 passed.\n");
7718 :
7719 5 : printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7720 :
7721 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7722 :
7723 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7724 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7725 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7726 5 : if (!NT_STATUS_IS_OK(status)) {
7727 0 : printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7728 0 : return False;
7729 : }
7730 :
7731 5 : status = cli_ntcreate(cli2, fname, 0,
7732 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7733 : FILE_ATTRIBUTE_NORMAL,
7734 : FILE_SHARE_READ|FILE_SHARE_DELETE,
7735 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7736 5 : if (NT_STATUS_IS_OK(status)) {
7737 0 : printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7738 0 : return False;
7739 : }
7740 :
7741 5 : printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7742 :
7743 5 : status = cli_close(cli1, fnum1);
7744 5 : if (!NT_STATUS_IS_OK(status)) {
7745 0 : printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7746 0 : return False;
7747 : }
7748 :
7749 5 : printf("non-io open test #7 passed.\n");
7750 :
7751 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7752 :
7753 5 : printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7754 5 : status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7755 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7756 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7757 5 : if (!NT_STATUS_IS_OK(status)) {
7758 0 : printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7759 0 : correct = false;
7760 0 : goto out;
7761 : }
7762 :
7763 : /* Write to ensure we have to update the file time. */
7764 5 : status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7765 : NULL);
7766 5 : if (!NT_STATUS_IS_OK(status)) {
7767 0 : printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7768 0 : correct = false;
7769 0 : goto out;
7770 : }
7771 :
7772 5 : status = cli_close(cli1, fnum1);
7773 5 : if (!NT_STATUS_IS_OK(status)) {
7774 0 : printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7775 0 : correct = false;
7776 : }
7777 :
7778 5 : out:
7779 :
7780 5 : if (!torture_close_connection(cli1)) {
7781 0 : correct = False;
7782 : }
7783 5 : if (!torture_close_connection(cli2)) {
7784 0 : correct = False;
7785 : }
7786 :
7787 5 : return correct;
7788 : }
7789 :
7790 102 : NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7791 : {
7792 0 : uint16_t major, minor;
7793 0 : uint32_t caplow, caphigh;
7794 0 : NTSTATUS status;
7795 :
7796 102 : if (!SERVER_HAS_UNIX_CIFS(cli)) {
7797 0 : printf("Server doesn't support UNIX CIFS extensions.\n");
7798 0 : return NT_STATUS_NOT_SUPPORTED;
7799 : }
7800 :
7801 102 : status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7802 : &caphigh);
7803 102 : if (!NT_STATUS_IS_OK(status)) {
7804 0 : printf("Server didn't return UNIX CIFS extensions: %s\n",
7805 : nt_errstr(status));
7806 0 : return status;
7807 : }
7808 :
7809 102 : status = cli_set_unix_extensions_capabilities(cli, major, minor,
7810 : caplow, caphigh);
7811 102 : if (!NT_STATUS_IS_OK(status)) {
7812 0 : printf("Server doesn't support setting UNIX CIFS extensions: "
7813 : "%s.\n", nt_errstr(status));
7814 0 : return status;
7815 : }
7816 :
7817 102 : return NT_STATUS_OK;
7818 : }
7819 :
7820 : /*
7821 : Test POSIX open /mkdir calls.
7822 : */
7823 4 : static bool run_simple_posix_open_test(int dummy)
7824 : {
7825 0 : static struct cli_state *cli1;
7826 4 : const char *fname = "posix:file";
7827 4 : const char *hname = "posix:hlink";
7828 4 : const char *sname = "posix:symlink";
7829 4 : const char *dname = "posix:dir";
7830 0 : char buf[10];
7831 4 : char *target = NULL;
7832 4 : uint16_t fnum1 = (uint16_t)-1;
7833 0 : SMB_STRUCT_STAT sbuf;
7834 4 : bool correct = false;
7835 0 : NTSTATUS status;
7836 0 : size_t nread;
7837 4 : const char *fname_windows = "windows_file";
7838 4 : uint16_t fnum2 = (uint16_t)-1;
7839 0 : bool ok;
7840 :
7841 4 : printf("Starting simple POSIX open test\n");
7842 :
7843 4 : if (!torture_open_connection(&cli1, 0)) {
7844 0 : return false;
7845 : }
7846 :
7847 4 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
7848 :
7849 4 : status = torture_setup_unix_extensions(cli1);
7850 4 : if (!NT_STATUS_IS_OK(status)) {
7851 0 : return false;
7852 : }
7853 :
7854 4 : cli_setatr(cli1, fname, 0, 0);
7855 4 : cli_posix_unlink(cli1, fname);
7856 4 : cli_setatr(cli1, dname, 0, 0);
7857 4 : cli_posix_rmdir(cli1, dname);
7858 4 : cli_setatr(cli1, hname, 0, 0);
7859 4 : cli_posix_unlink(cli1, hname);
7860 4 : cli_setatr(cli1, sname, 0, 0);
7861 4 : cli_posix_unlink(cli1, sname);
7862 4 : cli_setatr(cli1, fname_windows, 0, 0);
7863 4 : cli_posix_unlink(cli1, fname_windows);
7864 :
7865 : /* Create a directory. */
7866 4 : status = cli_posix_mkdir(cli1, dname, 0777);
7867 4 : if (!NT_STATUS_IS_OK(status)) {
7868 0 : printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7869 0 : goto out;
7870 : }
7871 :
7872 4 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7873 : 0600, &fnum1);
7874 4 : if (!NT_STATUS_IS_OK(status)) {
7875 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7876 0 : goto out;
7877 : }
7878 :
7879 : /* Test ftruncate - set file size. */
7880 4 : status = cli_ftruncate(cli1, fnum1, 1000);
7881 4 : if (!NT_STATUS_IS_OK(status)) {
7882 0 : printf("ftruncate failed (%s)\n", nt_errstr(status));
7883 0 : goto out;
7884 : }
7885 :
7886 : /* Ensure st_size == 1000 */
7887 4 : status = cli_posix_stat(cli1, fname, &sbuf);
7888 4 : if (!NT_STATUS_IS_OK(status)) {
7889 0 : printf("stat failed (%s)\n", nt_errstr(status));
7890 0 : goto out;
7891 : }
7892 :
7893 4 : if (sbuf.st_ex_size != 1000) {
7894 0 : printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7895 0 : goto out;
7896 : }
7897 :
7898 : /* Ensure st_mode == 0600 */
7899 4 : if ((sbuf.st_ex_mode & 07777) != 0600) {
7900 0 : printf("posix_open - bad permissions 0%o != 0600\n",
7901 0 : (unsigned int)(sbuf.st_ex_mode & 07777));
7902 0 : goto out;
7903 : }
7904 :
7905 : /* Test ftruncate - set file size back to zero. */
7906 4 : status = cli_ftruncate(cli1, fnum1, 0);
7907 4 : if (!NT_STATUS_IS_OK(status)) {
7908 0 : printf("ftruncate failed (%s)\n", nt_errstr(status));
7909 0 : goto out;
7910 : }
7911 :
7912 4 : status = cli_close(cli1, fnum1);
7913 4 : if (!NT_STATUS_IS_OK(status)) {
7914 0 : printf("close failed (%s)\n", nt_errstr(status));
7915 0 : goto out;
7916 : }
7917 :
7918 : /* Now open the file again for read only. */
7919 4 : status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7920 4 : if (!NT_STATUS_IS_OK(status)) {
7921 0 : printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7922 0 : goto out;
7923 : }
7924 :
7925 : /* Now unlink while open. */
7926 4 : status = cli_posix_unlink(cli1, fname);
7927 4 : if (!NT_STATUS_IS_OK(status)) {
7928 0 : printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7929 0 : goto out;
7930 : }
7931 :
7932 4 : status = cli_close(cli1, fnum1);
7933 4 : if (!NT_STATUS_IS_OK(status)) {
7934 0 : printf("close(2) failed (%s)\n", nt_errstr(status));
7935 0 : goto out;
7936 : }
7937 :
7938 : /* Ensure the file has gone. */
7939 4 : status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7940 4 : if (NT_STATUS_IS_OK(status)) {
7941 0 : printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7942 0 : goto out;
7943 : }
7944 :
7945 : /* Create again to test open with O_TRUNC. */
7946 4 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7947 4 : if (!NT_STATUS_IS_OK(status)) {
7948 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7949 0 : goto out;
7950 : }
7951 :
7952 : /* Test ftruncate - set file size. */
7953 4 : status = cli_ftruncate(cli1, fnum1, 1000);
7954 4 : if (!NT_STATUS_IS_OK(status)) {
7955 0 : printf("ftruncate failed (%s)\n", nt_errstr(status));
7956 0 : goto out;
7957 : }
7958 :
7959 : /* Ensure st_size == 1000 */
7960 4 : status = cli_posix_stat(cli1, fname, &sbuf);
7961 4 : if (!NT_STATUS_IS_OK(status)) {
7962 0 : printf("stat failed (%s)\n", nt_errstr(status));
7963 0 : goto out;
7964 : }
7965 :
7966 4 : if (sbuf.st_ex_size != 1000) {
7967 0 : printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7968 0 : goto out;
7969 : }
7970 :
7971 4 : status = cli_close(cli1, fnum1);
7972 4 : if (!NT_STATUS_IS_OK(status)) {
7973 0 : printf("close(2) failed (%s)\n", nt_errstr(status));
7974 0 : goto out;
7975 : }
7976 :
7977 : /* Re-open with O_TRUNC. */
7978 4 : status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7979 4 : if (!NT_STATUS_IS_OK(status)) {
7980 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7981 0 : goto out;
7982 : }
7983 :
7984 : /* Ensure st_size == 0 */
7985 4 : status = cli_posix_stat(cli1, fname, &sbuf);
7986 4 : if (!NT_STATUS_IS_OK(status)) {
7987 0 : printf("stat failed (%s)\n", nt_errstr(status));
7988 0 : goto out;
7989 : }
7990 :
7991 4 : if (sbuf.st_ex_size != 0) {
7992 0 : printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7993 0 : goto out;
7994 : }
7995 :
7996 4 : status = cli_close(cli1, fnum1);
7997 4 : if (!NT_STATUS_IS_OK(status)) {
7998 0 : printf("close failed (%s)\n", nt_errstr(status));
7999 0 : goto out;
8000 : }
8001 :
8002 4 : status = cli_posix_unlink(cli1, fname);
8003 4 : if (!NT_STATUS_IS_OK(status)) {
8004 0 : printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
8005 0 : goto out;
8006 : }
8007 :
8008 4 : status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
8009 4 : if (!NT_STATUS_IS_OK(status)) {
8010 0 : printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
8011 : dname, nt_errstr(status));
8012 0 : goto out;
8013 : }
8014 :
8015 4 : cli_close(cli1, fnum1);
8016 :
8017 : /* What happens when we try and POSIX open a directory for write ? */
8018 4 : status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
8019 4 : if (NT_STATUS_IS_OK(status)) {
8020 0 : printf("POSIX open of directory %s succeeded, "
8021 : "should have failed.\n",
8022 : dname);
8023 0 : goto out;
8024 : } else {
8025 4 : if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
8026 4 : NT_STATUS_FILE_IS_A_DIRECTORY)) {
8027 0 : goto out;
8028 : }
8029 : }
8030 :
8031 : /* Create the file. */
8032 4 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8033 : 0600, &fnum1);
8034 4 : if (!NT_STATUS_IS_OK(status)) {
8035 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
8036 0 : goto out;
8037 : }
8038 :
8039 : /* Write some data into it. */
8040 4 : status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
8041 : NULL);
8042 4 : if (!NT_STATUS_IS_OK(status)) {
8043 0 : printf("cli_write failed: %s\n", nt_errstr(status));
8044 0 : goto out;
8045 : }
8046 :
8047 4 : cli_close(cli1, fnum1);
8048 :
8049 : /* Now create a hardlink. */
8050 4 : status = cli_posix_hardlink(cli1, fname, hname);
8051 4 : if (!NT_STATUS_IS_OK(status)) {
8052 0 : printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
8053 0 : goto out;
8054 : }
8055 :
8056 : /* Now create a symlink. */
8057 4 : status = cli_posix_symlink(cli1, fname, sname);
8058 4 : if (!NT_STATUS_IS_OK(status)) {
8059 0 : printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
8060 0 : goto out;
8061 : }
8062 :
8063 : /* Open the hardlink for read. */
8064 4 : status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
8065 4 : if (!NT_STATUS_IS_OK(status)) {
8066 0 : printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
8067 0 : goto out;
8068 : }
8069 :
8070 4 : status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
8071 4 : if (!NT_STATUS_IS_OK(status)) {
8072 0 : printf("POSIX read of %s failed (%s)\n", hname,
8073 : nt_errstr(status));
8074 0 : goto out;
8075 4 : } else if (nread != 10) {
8076 0 : printf("POSIX read of %s failed. Received %ld, expected %d\n",
8077 : hname, (unsigned long)nread, 10);
8078 0 : goto out;
8079 : }
8080 :
8081 4 : if (memcmp(buf, "TEST DATA\n", 10)) {
8082 0 : printf("invalid data read from hardlink\n");
8083 0 : goto out;
8084 : }
8085 :
8086 : /* Do a POSIX lock/unlock. */
8087 4 : status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8088 4 : if (!NT_STATUS_IS_OK(status)) {
8089 0 : printf("POSIX lock failed %s\n", nt_errstr(status));
8090 0 : goto out;
8091 : }
8092 :
8093 : /* Punch a hole in the locked area. */
8094 4 : status = cli_posix_unlock(cli1, fnum1, 10, 80);
8095 4 : if (!NT_STATUS_IS_OK(status)) {
8096 0 : printf("POSIX unlock failed %s\n", nt_errstr(status));
8097 0 : goto out;
8098 : }
8099 :
8100 4 : cli_close(cli1, fnum1);
8101 :
8102 : /* Open the symlink for read - this should fail. A POSIX
8103 : client should not be doing opens on a symlink. */
8104 4 : status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8105 4 : if (NT_STATUS_IS_OK(status)) {
8106 0 : printf("POSIX open of %s succeeded (should have failed)\n", sname);
8107 0 : goto out;
8108 : }
8109 4 : ok = check_both_error(
8110 : __LINE__, status, ERRDOS, ERRbadpath,
8111 4 : NT_STATUS_OBJECT_NAME_NOT_FOUND);
8112 4 : if (!ok) {
8113 0 : printf("POSIX open of %s should have failed "
8114 : "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8115 : "failed with %s instead.\n",
8116 : sname, nt_errstr(status));
8117 0 : goto out;
8118 : }
8119 :
8120 4 : status = cli_readlink(cli1, sname, talloc_tos(), &target, NULL, NULL);
8121 4 : if (!NT_STATUS_IS_OK(status)) {
8122 0 : printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8123 0 : goto out;
8124 : }
8125 :
8126 4 : if (strcmp(target, fname) != 0) {
8127 0 : printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8128 : sname, fname, target);
8129 0 : goto out;
8130 : }
8131 :
8132 4 : status = cli_posix_rmdir(cli1, dname);
8133 4 : if (!NT_STATUS_IS_OK(status)) {
8134 0 : printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8135 0 : goto out;
8136 : }
8137 :
8138 : /* Check directory opens with a specific permission. */
8139 4 : status = cli_posix_mkdir(cli1, dname, 0700);
8140 4 : if (!NT_STATUS_IS_OK(status)) {
8141 0 : printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8142 0 : goto out;
8143 : }
8144 :
8145 : /* Ensure st_mode == 0700 */
8146 4 : status = cli_posix_stat(cli1, dname, &sbuf);
8147 4 : if (!NT_STATUS_IS_OK(status)) {
8148 0 : printf("stat failed (%s)\n", nt_errstr(status));
8149 0 : goto out;
8150 : }
8151 :
8152 4 : if ((sbuf.st_ex_mode & 07777) != 0700) {
8153 0 : printf("posix_mkdir - bad permissions 0%o != 0700\n",
8154 0 : (unsigned int)(sbuf.st_ex_mode & 07777));
8155 0 : goto out;
8156 : }
8157 :
8158 : /*
8159 : * Now create a Windows file, and attempt a POSIX unlink.
8160 : * This should fail with a sharing violation but due to:
8161 : *
8162 : * [Bug 9571] Unlink after open causes smbd to panic
8163 : *
8164 : * ensure we've fixed the lock ordering violation.
8165 : */
8166 :
8167 4 : status = cli_ntcreate(cli1, fname_windows, 0,
8168 : FILE_READ_DATA|FILE_WRITE_DATA, 0,
8169 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8170 : FILE_CREATE,
8171 : 0x0, 0x0, &fnum2, NULL);
8172 4 : if (!NT_STATUS_IS_OK(status)) {
8173 0 : printf("Windows create of %s failed (%s)\n", fname_windows,
8174 : nt_errstr(status));
8175 0 : goto out;
8176 : }
8177 :
8178 : /* Now try posix_unlink. */
8179 4 : status = cli_posix_unlink(cli1, fname_windows);
8180 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8181 0 : printf("POSIX unlink of %s should fail "
8182 : "with NT_STATUS_SHARING_VIOLATION "
8183 : "got %s instead !\n",
8184 : fname_windows,
8185 : nt_errstr(status));
8186 0 : goto out;
8187 : }
8188 :
8189 4 : cli_close(cli1, fnum2);
8190 :
8191 4 : printf("Simple POSIX open test passed\n");
8192 4 : correct = true;
8193 :
8194 4 : out:
8195 :
8196 4 : if (fnum1 != (uint16_t)-1) {
8197 4 : cli_close(cli1, fnum1);
8198 4 : fnum1 = (uint16_t)-1;
8199 : }
8200 :
8201 4 : if (fnum2 != (uint16_t)-1) {
8202 4 : cli_close(cli1, fnum2);
8203 4 : fnum2 = (uint16_t)-1;
8204 : }
8205 :
8206 4 : cli_setatr(cli1, sname, 0, 0);
8207 4 : cli_posix_unlink(cli1, sname);
8208 4 : cli_setatr(cli1, hname, 0, 0);
8209 4 : cli_posix_unlink(cli1, hname);
8210 4 : cli_setatr(cli1, fname, 0, 0);
8211 4 : cli_posix_unlink(cli1, fname);
8212 4 : cli_setatr(cli1, dname, 0, 0);
8213 4 : cli_posix_rmdir(cli1, dname);
8214 4 : cli_setatr(cli1, fname_windows, 0, 0);
8215 4 : cli_posix_unlink(cli1, fname_windows);
8216 :
8217 4 : if (!torture_close_connection(cli1)) {
8218 0 : correct = false;
8219 : }
8220 :
8221 4 : return correct;
8222 : }
8223 :
8224 : /*
8225 : Test POSIX and Windows ACLs are rejected on symlinks.
8226 : */
8227 4 : static bool run_acl_symlink_test(int dummy)
8228 : {
8229 0 : static struct cli_state *cli;
8230 4 : const char *fname = "posix_file";
8231 4 : const char *sname = "posix_symlink";
8232 4 : uint16_t fnum = (uint16_t)-1;
8233 4 : bool correct = false;
8234 0 : NTSTATUS status;
8235 4 : char *posix_acl = NULL;
8236 4 : size_t posix_acl_len = 0;
8237 4 : char *posix_acl_sym = NULL;
8238 4 : size_t posix_acl_len_sym = 0;
8239 4 : struct security_descriptor *sd = NULL;
8240 4 : TALLOC_CTX *frame = NULL;
8241 :
8242 4 : frame = talloc_stackframe();
8243 :
8244 4 : printf("Starting acl symlink test\n");
8245 :
8246 4 : if (!torture_open_connection(&cli, 0)) {
8247 0 : TALLOC_FREE(frame);
8248 0 : return false;
8249 : }
8250 :
8251 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
8252 :
8253 4 : status = torture_setup_unix_extensions(cli);
8254 4 : if (!NT_STATUS_IS_OK(status)) {
8255 0 : TALLOC_FREE(frame);
8256 0 : return false;
8257 : }
8258 :
8259 4 : cli_setatr(cli, fname, 0, 0);
8260 4 : cli_posix_unlink(cli, fname);
8261 4 : cli_setatr(cli, sname, 0, 0);
8262 4 : cli_posix_unlink(cli, sname);
8263 :
8264 4 : status = cli_ntcreate(cli,
8265 : fname,
8266 : 0,
8267 : READ_CONTROL_ACCESS,
8268 : 0,
8269 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8270 : FILE_CREATE,
8271 : 0x0,
8272 : 0x0,
8273 : &fnum,
8274 : NULL);
8275 :
8276 4 : if (!NT_STATUS_IS_OK(status)) {
8277 0 : printf("cli_ntcreate of %s failed (%s)\n",
8278 : fname,
8279 : nt_errstr(status));
8280 0 : goto out;
8281 : }
8282 :
8283 : /* Get the Windows ACL on the file. */
8284 4 : status = cli_query_secdesc(cli,
8285 : fnum,
8286 : frame,
8287 : &sd);
8288 4 : if (!NT_STATUS_IS_OK(status)) {
8289 0 : printf("cli_query_secdesc failed (%s)\n",
8290 : nt_errstr(status));
8291 0 : goto out;
8292 : }
8293 :
8294 : /* Get the POSIX ACL on the file. */
8295 4 : status = cli_posix_getacl(cli,
8296 : fname,
8297 : frame,
8298 : &posix_acl_len,
8299 : &posix_acl);
8300 :
8301 4 : if (!NT_STATUS_IS_OK(status)) {
8302 0 : printf("cli_posix_getacl failed (%s)\n",
8303 : nt_errstr(status));
8304 0 : goto out;
8305 : }
8306 :
8307 4 : status = cli_close(cli, fnum);
8308 4 : if (!NT_STATUS_IS_OK(status)) {
8309 0 : printf("close failed (%s)\n", nt_errstr(status));
8310 0 : goto out;
8311 : }
8312 4 : fnum = (uint16_t)-1;
8313 :
8314 : /* Now create a symlink. */
8315 4 : status = cli_posix_symlink(cli, fname, sname);
8316 4 : if (!NT_STATUS_IS_OK(status)) {
8317 0 : printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8318 : sname,
8319 : fname,
8320 : nt_errstr(status));
8321 0 : goto out;
8322 : }
8323 :
8324 : /* Open a handle on the symlink for SD set/get should fail. */
8325 4 : status = cli_ntcreate(cli,
8326 : sname,
8327 : 0,
8328 : READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8329 : 0,
8330 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8331 : FILE_OPEN,
8332 : 0x0,
8333 : 0x0,
8334 : &fnum,
8335 : NULL);
8336 :
8337 4 : if (NT_STATUS_IS_OK(status)) {
8338 0 : printf("Symlink open for getsd/setsd of %s "
8339 : "succeeded (should fail)\n",
8340 : sname);
8341 0 : goto out;
8342 : }
8343 :
8344 : /* Try a stat-open on the symlink, should also fail. */
8345 4 : status = cli_ntcreate(cli,
8346 : sname,
8347 : 0,
8348 : FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8349 : 0,
8350 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8351 : FILE_OPEN,
8352 : 0x0,
8353 : 0x0,
8354 : &fnum,
8355 : NULL);
8356 :
8357 4 : if (NT_STATUS_IS_OK(status)) {
8358 0 : printf("Stat-open of symlink succeeded (should fail)\n");
8359 0 : goto out;
8360 : }
8361 :
8362 : /* Get the POSIX ACL on the symlink pathname. Should fail. */
8363 4 : status = cli_posix_getacl(cli,
8364 : sname,
8365 : frame,
8366 : &posix_acl_len_sym,
8367 : &posix_acl_sym);
8368 :
8369 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8370 0 : printf("cli_posix_getacl on a symlink gave %s. "
8371 : "Should be NT_STATUS_ACCESS_DENIED.\n",
8372 : nt_errstr(status));
8373 0 : goto out;
8374 : }
8375 :
8376 : /* Set the POSIX ACL on the symlink pathname. Should fail. */
8377 4 : status = cli_posix_setacl(cli,
8378 : sname,
8379 : posix_acl,
8380 : posix_acl_len);
8381 :
8382 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8383 0 : printf("cli_posix_setacl on a symlink gave %s. "
8384 : "Should be NT_STATUS_ACCESS_DENIED.\n",
8385 : nt_errstr(status));
8386 0 : goto out;
8387 : }
8388 :
8389 4 : printf("ACL symlink test passed\n");
8390 4 : correct = true;
8391 :
8392 4 : out:
8393 :
8394 4 : if (fnum != (uint16_t)-1) {
8395 0 : cli_close(cli, fnum);
8396 0 : fnum = (uint16_t)-1;
8397 : }
8398 :
8399 4 : cli_setatr(cli, sname, 0, 0);
8400 4 : cli_posix_unlink(cli, sname);
8401 4 : cli_setatr(cli, fname, 0, 0);
8402 4 : cli_posix_unlink(cli, fname);
8403 :
8404 4 : if (!torture_close_connection(cli)) {
8405 0 : correct = false;
8406 : }
8407 :
8408 4 : TALLOC_FREE(frame);
8409 4 : return correct;
8410 : }
8411 :
8412 : /*
8413 : Test POSIX can delete a file containing streams.
8414 : */
8415 4 : static bool run_posix_stream_delete(int dummy)
8416 : {
8417 4 : struct cli_state *cli1 = NULL;
8418 4 : struct cli_state *cli2 = NULL;
8419 4 : const char *fname = "streamfile";
8420 4 : const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8421 4 : uint16_t fnum1 = (uint16_t)-1;
8422 4 : bool correct = false;
8423 0 : NTSTATUS status;
8424 4 : TALLOC_CTX *frame = NULL;
8425 :
8426 4 : frame = talloc_stackframe();
8427 :
8428 4 : printf("Starting POSIX stream delete test\n");
8429 :
8430 4 : if (!torture_open_connection(&cli1, 0) ||
8431 4 : !torture_open_connection(&cli2, 1)) {
8432 0 : TALLOC_FREE(frame);
8433 0 : return false;
8434 : }
8435 :
8436 4 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
8437 4 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
8438 :
8439 4 : status = torture_setup_unix_extensions(cli2);
8440 4 : if (!NT_STATUS_IS_OK(status)) {
8441 0 : goto out;
8442 : }
8443 :
8444 4 : cli_setatr(cli1, fname, 0, 0);
8445 4 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8446 :
8447 : /* Create the file. */
8448 4 : status = cli_ntcreate(cli1,
8449 : fname,
8450 : 0,
8451 : READ_CONTROL_ACCESS,
8452 : 0,
8453 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8454 : FILE_CREATE,
8455 : 0x0,
8456 : 0x0,
8457 : &fnum1,
8458 : NULL);
8459 :
8460 4 : if (!NT_STATUS_IS_OK(status)) {
8461 0 : printf("cli_ntcreate of %s failed (%s)\n",
8462 : fname,
8463 : nt_errstr(status));
8464 0 : goto out;
8465 : }
8466 :
8467 4 : status = cli_close(cli1, fnum1);
8468 4 : if (!NT_STATUS_IS_OK(status)) {
8469 0 : printf("cli_close of %s failed (%s)\n",
8470 : fname,
8471 : nt_errstr(status));
8472 0 : goto out;
8473 : }
8474 4 : fnum1 = (uint16_t)-1;
8475 :
8476 : /* Now create the stream. */
8477 4 : status = cli_ntcreate(cli1,
8478 : stream_fname,
8479 : 0,
8480 : FILE_WRITE_DATA,
8481 : 0,
8482 : FILE_SHARE_READ|FILE_SHARE_WRITE,
8483 : FILE_CREATE,
8484 : 0x0,
8485 : 0x0,
8486 : &fnum1,
8487 : NULL);
8488 :
8489 4 : if (!NT_STATUS_IS_OK(status)) {
8490 0 : printf("cli_ntcreate of %s failed (%s)\n",
8491 : stream_fname,
8492 : nt_errstr(status));
8493 0 : goto out;
8494 : }
8495 :
8496 : /* Leave the stream handle open... */
8497 :
8498 : /* POSIX unlink should fail. */
8499 4 : status = cli_posix_unlink(cli2, fname);
8500 4 : if (NT_STATUS_IS_OK(status)) {
8501 0 : printf("cli_posix_unlink of %s succeeded, should have failed\n",
8502 : fname);
8503 0 : goto out;
8504 : }
8505 :
8506 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8507 0 : printf("cli_posix_unlink of %s failed with (%s) "
8508 : "should have been NT_STATUS_SHARING_VIOLATION\n",
8509 : fname,
8510 : nt_errstr(status));
8511 0 : goto out;
8512 : }
8513 :
8514 : /* Close the stream handle. */
8515 4 : status = cli_close(cli1, fnum1);
8516 4 : if (!NT_STATUS_IS_OK(status)) {
8517 0 : printf("cli_close of %s failed (%s)\n",
8518 : stream_fname,
8519 : nt_errstr(status));
8520 0 : goto out;
8521 : }
8522 4 : fnum1 = (uint16_t)-1;
8523 :
8524 : /* POSIX unlink after stream handle closed should succeed. */
8525 4 : status = cli_posix_unlink(cli2, fname);
8526 4 : if (!NT_STATUS_IS_OK(status)) {
8527 0 : printf("cli_posix_unlink of %s failed (%s)\n",
8528 : fname,
8529 : nt_errstr(status));
8530 0 : goto out;
8531 : }
8532 :
8533 4 : printf("POSIX stream delete test passed\n");
8534 4 : correct = true;
8535 :
8536 4 : out:
8537 :
8538 4 : if (fnum1 != (uint16_t)-1) {
8539 0 : cli_close(cli1, fnum1);
8540 0 : fnum1 = (uint16_t)-1;
8541 : }
8542 :
8543 4 : cli_setatr(cli1, fname, 0, 0);
8544 4 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8545 :
8546 4 : if (!torture_close_connection(cli1)) {
8547 0 : correct = false;
8548 : }
8549 4 : if (!torture_close_connection(cli2)) {
8550 0 : correct = false;
8551 : }
8552 :
8553 4 : TALLOC_FREE(frame);
8554 4 : return correct;
8555 : }
8556 :
8557 : /*
8558 : Test setting EA's are rejected on symlinks.
8559 : */
8560 4 : static bool run_ea_symlink_test(int dummy)
8561 : {
8562 0 : static struct cli_state *cli;
8563 4 : const char *fname = "posix_file_ea";
8564 4 : const char *sname = "posix_symlink_ea";
8565 4 : const char *ea_name = "testea_name";
8566 4 : const char *ea_value = "testea_value";
8567 4 : uint16_t fnum = (uint16_t)-1;
8568 4 : bool correct = false;
8569 0 : NTSTATUS status;
8570 0 : size_t i, num_eas;
8571 4 : struct ea_struct *eas = NULL;
8572 4 : TALLOC_CTX *frame = NULL;
8573 :
8574 4 : frame = talloc_stackframe();
8575 :
8576 4 : printf("Starting EA symlink test\n");
8577 :
8578 4 : if (!torture_open_connection(&cli, 0)) {
8579 0 : TALLOC_FREE(frame);
8580 0 : return false;
8581 : }
8582 :
8583 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
8584 :
8585 4 : status = torture_setup_unix_extensions(cli);
8586 4 : if (!NT_STATUS_IS_OK(status)) {
8587 0 : TALLOC_FREE(frame);
8588 0 : return false;
8589 : }
8590 :
8591 4 : cli_setatr(cli, fname, 0, 0);
8592 4 : cli_posix_unlink(cli, fname);
8593 4 : cli_setatr(cli, sname, 0, 0);
8594 4 : cli_posix_unlink(cli, sname);
8595 :
8596 4 : status = cli_ntcreate(cli,
8597 : fname,
8598 : 0,
8599 : READ_CONTROL_ACCESS,
8600 : 0,
8601 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8602 : FILE_CREATE,
8603 : 0x0,
8604 : 0x0,
8605 : &fnum,
8606 : NULL);
8607 :
8608 4 : if (!NT_STATUS_IS_OK(status)) {
8609 0 : printf("cli_ntcreate of %s failed (%s)\n",
8610 : fname,
8611 : nt_errstr(status));
8612 0 : goto out;
8613 : }
8614 :
8615 4 : status = cli_close(cli, fnum);
8616 4 : if (!NT_STATUS_IS_OK(status)) {
8617 0 : printf("close failed (%s)\n",
8618 : nt_errstr(status));
8619 0 : goto out;
8620 : }
8621 4 : fnum = (uint16_t)-1;
8622 :
8623 : /* Set an EA on the path. */
8624 4 : status = cli_set_ea_path(cli,
8625 : fname,
8626 : ea_name,
8627 : ea_value,
8628 4 : strlen(ea_value)+1);
8629 :
8630 4 : if (!NT_STATUS_IS_OK(status)) {
8631 0 : printf("cli_set_ea_path failed (%s)\n",
8632 : nt_errstr(status));
8633 0 : goto out;
8634 : }
8635 :
8636 : /* Now create a symlink. */
8637 4 : status = cli_posix_symlink(cli, fname, sname);
8638 4 : if (!NT_STATUS_IS_OK(status)) {
8639 0 : printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8640 : sname,
8641 : fname,
8642 : nt_errstr(status));
8643 0 : goto out;
8644 : }
8645 :
8646 : /* Get the EA list on the path. Should return value set. */
8647 4 : status = cli_get_ea_list_path(cli,
8648 : fname,
8649 : frame,
8650 : &num_eas,
8651 : &eas);
8652 :
8653 4 : if (!NT_STATUS_IS_OK(status)) {
8654 0 : printf("cli_get_ea_list_path failed (%s)\n",
8655 : nt_errstr(status));
8656 0 : goto out;
8657 : }
8658 :
8659 : /* Ensure the EA we set is there. */
8660 4 : for (i=0; i<num_eas; i++) {
8661 4 : if (strcmp(eas[i].name, ea_name) == 0 &&
8662 4 : eas[i].value.length == strlen(ea_value)+1 &&
8663 4 : memcmp(eas[i].value.data,
8664 : ea_value,
8665 4 : eas[i].value.length) == 0) {
8666 4 : break;
8667 : }
8668 : }
8669 :
8670 4 : if (i == num_eas) {
8671 0 : printf("Didn't find EA on pathname %s\n",
8672 : fname);
8673 0 : goto out;
8674 : }
8675 :
8676 4 : num_eas = 0;
8677 4 : TALLOC_FREE(eas);
8678 :
8679 : /* Get the EA list on the symlink. Should return empty list. */
8680 4 : status = cli_get_ea_list_path(cli,
8681 : sname,
8682 : frame,
8683 : &num_eas,
8684 : &eas);
8685 :
8686 4 : if (!NT_STATUS_IS_OK(status)) {
8687 0 : printf("cli_get_ea_list_path failed (%s)\n",
8688 : nt_errstr(status));
8689 0 : goto out;
8690 : }
8691 :
8692 4 : if (num_eas != 0) {
8693 0 : printf("cli_get_ea_list_path failed (%s)\n",
8694 : nt_errstr(status));
8695 0 : goto out;
8696 : }
8697 :
8698 : /* Set an EA on the symlink. Should fail. */
8699 4 : status = cli_set_ea_path(cli,
8700 : sname,
8701 : ea_name,
8702 : ea_value,
8703 4 : strlen(ea_value)+1);
8704 :
8705 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8706 0 : printf("cli_set_ea_path on a symlink gave %s. "
8707 : "Should be NT_STATUS_ACCESS_DENIED.\n",
8708 : nt_errstr(status));
8709 0 : goto out;
8710 : }
8711 :
8712 4 : printf("EA symlink test passed\n");
8713 4 : correct = true;
8714 :
8715 4 : out:
8716 :
8717 4 : if (fnum != (uint16_t)-1) {
8718 0 : cli_close(cli, fnum);
8719 0 : fnum = (uint16_t)-1;
8720 : }
8721 :
8722 4 : cli_setatr(cli, sname, 0, 0);
8723 4 : cli_posix_unlink(cli, sname);
8724 4 : cli_setatr(cli, fname, 0, 0);
8725 4 : cli_posix_unlink(cli, fname);
8726 :
8727 4 : if (!torture_close_connection(cli)) {
8728 0 : correct = false;
8729 : }
8730 :
8731 4 : TALLOC_FREE(frame);
8732 4 : return correct;
8733 : }
8734 :
8735 : /*
8736 : Test POSIX locks are OFD-locks.
8737 : */
8738 4 : static bool run_posix_ofd_lock_test(int dummy)
8739 : {
8740 0 : static struct cli_state *cli;
8741 4 : const char *fname = "posix_file";
8742 4 : uint16_t fnum1 = (uint16_t)-1;
8743 4 : uint16_t fnum2 = (uint16_t)-1;
8744 4 : bool correct = false;
8745 0 : NTSTATUS status;
8746 4 : TALLOC_CTX *frame = NULL;
8747 :
8748 4 : frame = talloc_stackframe();
8749 :
8750 4 : printf("Starting POSIX ofd-lock test\n");
8751 :
8752 4 : if (!torture_open_connection(&cli, 0)) {
8753 0 : TALLOC_FREE(frame);
8754 0 : return false;
8755 : }
8756 :
8757 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
8758 :
8759 4 : status = torture_setup_unix_extensions(cli);
8760 4 : if (!NT_STATUS_IS_OK(status)) {
8761 0 : TALLOC_FREE(frame);
8762 0 : return false;
8763 : }
8764 :
8765 4 : cli_setatr(cli, fname, 0, 0);
8766 4 : cli_posix_unlink(cli, fname);
8767 :
8768 : /* Open the file twice. */
8769 4 : status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8770 : 0600, &fnum1);
8771 4 : if (!NT_STATUS_IS_OK(status)) {
8772 0 : printf("First POSIX open of %s failed\n", fname);
8773 0 : goto out;
8774 : }
8775 :
8776 4 : status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8777 4 : if (!NT_STATUS_IS_OK(status)) {
8778 0 : printf("First POSIX open of %s failed\n", fname);
8779 0 : goto out;
8780 : }
8781 :
8782 : /* Set a 0-50 lock on fnum1. */
8783 4 : status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8784 4 : if (!NT_STATUS_IS_OK(status)) {
8785 0 : printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8786 0 : goto out;
8787 : }
8788 :
8789 : /* Set a 60-100 lock on fnum2. */
8790 4 : status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8791 4 : if (!NT_STATUS_IS_OK(status)) {
8792 0 : printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8793 0 : goto out;
8794 : }
8795 :
8796 : /* close fnum1 - 0-50 lock should go away. */
8797 4 : status = cli_close(cli, fnum1);
8798 4 : if (!NT_STATUS_IS_OK(status)) {
8799 0 : printf("close failed (%s)\n",
8800 : nt_errstr(status));
8801 0 : goto out;
8802 : }
8803 4 : fnum1 = (uint16_t)-1;
8804 :
8805 : /* Change the lock context. */
8806 4 : cli_setpid(cli, cli_getpid(cli) + 1);
8807 :
8808 : /* Re-open fnum1. */
8809 4 : status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8810 4 : if (!NT_STATUS_IS_OK(status)) {
8811 0 : printf("Third POSIX open of %s failed\n", fname);
8812 0 : goto out;
8813 : }
8814 :
8815 : /* 60-100 lock should still be there. */
8816 4 : status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8817 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8818 0 : printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8819 0 : goto out;
8820 : }
8821 :
8822 : /* 0-50 lock should be gone. */
8823 4 : status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8824 4 : if (!NT_STATUS_IS_OK(status)) {
8825 0 : printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8826 0 : goto out;
8827 : }
8828 :
8829 4 : printf("POSIX OFD lock test passed\n");
8830 4 : correct = true;
8831 :
8832 4 : out:
8833 :
8834 4 : if (fnum1 != (uint16_t)-1) {
8835 4 : cli_close(cli, fnum1);
8836 4 : fnum1 = (uint16_t)-1;
8837 : }
8838 4 : if (fnum2 != (uint16_t)-1) {
8839 4 : cli_close(cli, fnum2);
8840 4 : fnum2 = (uint16_t)-1;
8841 : }
8842 :
8843 4 : cli_setatr(cli, fname, 0, 0);
8844 4 : cli_posix_unlink(cli, fname);
8845 :
8846 4 : if (!torture_close_connection(cli)) {
8847 0 : correct = false;
8848 : }
8849 :
8850 4 : TALLOC_FREE(frame);
8851 4 : return correct;
8852 : }
8853 :
8854 : struct posix_blocking_state {
8855 : struct tevent_context *ev;
8856 : struct cli_state *cli1;
8857 : uint16_t fnum1;
8858 : struct cli_state *cli2;
8859 : uint16_t fnum2;
8860 : bool gotblocked;
8861 : bool gotecho;
8862 : };
8863 :
8864 : static void posix_blocking_locked(struct tevent_req *subreq);
8865 : static void posix_blocking_gotblocked(struct tevent_req *subreq);
8866 : static void posix_blocking_gotecho(struct tevent_req *subreq);
8867 : static void posix_blocking_unlocked(struct tevent_req *subreq);
8868 :
8869 4 : static struct tevent_req *posix_blocking_send(
8870 : TALLOC_CTX *mem_ctx,
8871 : struct tevent_context *ev,
8872 : struct cli_state *cli1,
8873 : uint16_t fnum1,
8874 : struct cli_state *cli2,
8875 : uint16_t fnum2)
8876 : {
8877 4 : struct tevent_req *req = NULL, *subreq = NULL;
8878 4 : struct posix_blocking_state *state = NULL;
8879 :
8880 4 : req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8881 4 : if (req == NULL) {
8882 0 : return NULL;
8883 : }
8884 4 : state->ev = ev;
8885 4 : state->cli1 = cli1;
8886 4 : state->fnum1 = fnum1;
8887 4 : state->cli2 = cli2;
8888 4 : state->fnum2 = fnum2;
8889 :
8890 4 : subreq = cli_posix_lock_send(
8891 : state,
8892 4 : state->ev,
8893 4 : state->cli1,
8894 4 : state->fnum1,
8895 : 0,
8896 : 1,
8897 : false,
8898 : WRITE_LOCK);
8899 4 : if (tevent_req_nomem(subreq, req)) {
8900 0 : return tevent_req_post(req, ev);
8901 : }
8902 4 : tevent_req_set_callback(subreq, posix_blocking_locked, req);
8903 4 : return req;
8904 : }
8905 :
8906 4 : static void posix_blocking_locked(struct tevent_req *subreq)
8907 : {
8908 4 : struct tevent_req *req = tevent_req_callback_data(
8909 : subreq, struct tevent_req);
8910 4 : struct posix_blocking_state *state = tevent_req_data(
8911 : req, struct posix_blocking_state);
8912 0 : NTSTATUS status;
8913 :
8914 4 : status = cli_posix_lock_recv(subreq);
8915 4 : TALLOC_FREE(subreq);
8916 4 : if (tevent_req_nterror(req, status)) {
8917 0 : return;
8918 : }
8919 :
8920 4 : subreq = cli_posix_lock_send(
8921 : state,
8922 : state->ev,
8923 : state->cli2,
8924 4 : state->fnum2,
8925 : 0,
8926 : 1,
8927 : true,
8928 : WRITE_LOCK);
8929 4 : if (tevent_req_nomem(subreq, req)) {
8930 0 : return;
8931 : }
8932 4 : tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8933 :
8934 : /* Make sure the blocking request is delivered */
8935 4 : subreq = cli_echo_send(
8936 : state,
8937 : state->ev,
8938 : state->cli2,
8939 : 1,
8940 4 : (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8941 4 : if (tevent_req_nomem(subreq, req)) {
8942 0 : return;
8943 : }
8944 4 : tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8945 : }
8946 :
8947 4 : static void posix_blocking_gotblocked(struct tevent_req *subreq)
8948 : {
8949 4 : struct tevent_req *req = tevent_req_callback_data(
8950 : subreq, struct tevent_req);
8951 4 : struct posix_blocking_state *state = tevent_req_data(
8952 : req, struct posix_blocking_state);
8953 0 : NTSTATUS status;
8954 :
8955 4 : status = cli_posix_lock_recv(subreq);
8956 4 : TALLOC_FREE(subreq);
8957 4 : if (tevent_req_nterror(req, status)) {
8958 0 : return;
8959 : }
8960 4 : if (!state->gotecho) {
8961 0 : printf("blocked req got through before echo\n");
8962 0 : tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8963 0 : return;
8964 : }
8965 4 : tevent_req_done(req);
8966 : }
8967 :
8968 4 : static void posix_blocking_gotecho(struct tevent_req *subreq)
8969 : {
8970 4 : struct tevent_req *req = tevent_req_callback_data(
8971 : subreq, struct tevent_req);
8972 4 : struct posix_blocking_state *state = tevent_req_data(
8973 : req, struct posix_blocking_state);
8974 0 : NTSTATUS status;
8975 :
8976 4 : status = cli_echo_recv(subreq);
8977 4 : TALLOC_FREE(subreq);
8978 4 : if (tevent_req_nterror(req, status)) {
8979 0 : return;
8980 : }
8981 4 : if (state->gotblocked) {
8982 0 : printf("blocked req got through before echo\n");
8983 0 : tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8984 0 : return;
8985 : }
8986 4 : state->gotecho = true;
8987 :
8988 4 : subreq = cli_posix_lock_send(
8989 : state,
8990 : state->ev,
8991 : state->cli1,
8992 4 : state->fnum1,
8993 : 0,
8994 : 1,
8995 : false,
8996 : UNLOCK_LOCK);
8997 4 : if (tevent_req_nomem(subreq, req)) {
8998 0 : return;
8999 : }
9000 4 : tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
9001 : }
9002 :
9003 4 : static void posix_blocking_unlocked(struct tevent_req *subreq)
9004 : {
9005 4 : struct tevent_req *req = tevent_req_callback_data(
9006 : subreq, struct tevent_req);
9007 0 : NTSTATUS status;
9008 :
9009 4 : status = cli_posix_lock_recv(subreq);
9010 4 : TALLOC_FREE(subreq);
9011 4 : if (tevent_req_nterror(req, status)) {
9012 0 : return;
9013 : }
9014 : /* tevent_req_done in posix_blocking_gotlocked */
9015 : }
9016 :
9017 4 : static NTSTATUS posix_blocking_recv(struct tevent_req *req)
9018 : {
9019 4 : return tevent_req_simple_recv_ntstatus(req);
9020 : }
9021 :
9022 4 : static bool run_posix_blocking_lock(int dummy)
9023 : {
9024 4 : struct tevent_context *ev = NULL;
9025 4 : struct cli_state *cli1 = NULL, *cli2 = NULL;
9026 4 : const char *fname = "posix_blocking";
9027 4 : uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
9028 4 : struct tevent_req *req = NULL;
9029 0 : NTSTATUS status;
9030 4 : bool ret = false;
9031 0 : bool ok;
9032 :
9033 4 : printf("Starting posix blocking lock test\n");
9034 :
9035 4 : ev = samba_tevent_context_init(NULL);
9036 4 : if (ev == NULL) {
9037 0 : return false;
9038 : }
9039 :
9040 4 : ok = torture_open_connection(&cli1, 0);
9041 4 : if (!ok) {
9042 0 : goto fail;
9043 : }
9044 4 : ok = torture_open_connection(&cli2, 0);
9045 4 : if (!ok) {
9046 0 : goto fail;
9047 : }
9048 :
9049 4 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
9050 :
9051 4 : status = torture_setup_unix_extensions(cli1);
9052 4 : if (!NT_STATUS_IS_OK(status)) {
9053 0 : return false;
9054 : }
9055 :
9056 4 : status = torture_setup_unix_extensions(cli2);
9057 4 : if (!NT_STATUS_IS_OK(status)) {
9058 0 : return false;
9059 : }
9060 :
9061 4 : cli_setatr(cli1, fname, 0, 0);
9062 4 : cli_posix_unlink(cli1, fname);
9063 :
9064 4 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
9065 : 0600, &fnum1);
9066 4 : if (!NT_STATUS_IS_OK(status)) {
9067 0 : printf("First POSIX open of %s failed: %s\n",
9068 : fname,
9069 : nt_errstr(status));
9070 0 : goto fail;
9071 : }
9072 :
9073 4 : status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
9074 4 : if (!NT_STATUS_IS_OK(status)) {
9075 0 : printf("Second POSIX open of %s failed: %s\n",
9076 : fname,
9077 : nt_errstr(status));
9078 0 : goto fail;
9079 : }
9080 :
9081 4 : req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9082 4 : if (req == NULL) {
9083 0 : printf("cli_posix_blocking failed\n");
9084 0 : goto fail;
9085 : }
9086 :
9087 4 : ok = tevent_req_poll_ntstatus(req, ev, &status);
9088 4 : if (!ok) {
9089 0 : printf("tevent_req_poll_ntstatus failed: %s\n",
9090 : nt_errstr(status));
9091 0 : goto fail;
9092 : }
9093 4 : status = posix_blocking_recv(req);
9094 4 : TALLOC_FREE(req);
9095 4 : if (!NT_STATUS_IS_OK(status)) {
9096 0 : printf("posix_blocking_recv returned %s\n",
9097 : nt_errstr(status));
9098 0 : goto fail;
9099 : }
9100 :
9101 4 : ret = true;
9102 4 : fail:
9103 :
9104 4 : if (fnum1 != UINT16_MAX) {
9105 4 : cli_close(cli1, fnum1);
9106 4 : fnum1 = UINT16_MAX;
9107 : }
9108 4 : if (fnum2 != UINT16_MAX) {
9109 4 : cli_close(cli2, fnum2);
9110 4 : fnum2 = UINT16_MAX;
9111 : }
9112 :
9113 4 : if (cli1 != NULL) {
9114 4 : cli_setatr(cli1, fname, 0, 0);
9115 4 : cli_posix_unlink(cli1, fname);
9116 : }
9117 :
9118 4 : ok = true;
9119 :
9120 4 : if (cli1 != NULL) {
9121 4 : ok &= torture_close_connection(cli1);
9122 4 : cli1 = NULL;
9123 : }
9124 4 : if (cli2 != NULL) {
9125 4 : ok &= torture_close_connection(cli2);
9126 4 : cli2 = NULL;
9127 : }
9128 :
9129 4 : if (!ok) {
9130 0 : ret = false;
9131 : }
9132 4 : TALLOC_FREE(ev);
9133 4 : return ret;
9134 : }
9135 :
9136 : /*
9137 : Test POSIX mkdir is case-sensitive.
9138 : */
9139 4 : static bool run_posix_mkdir_test(int dummy)
9140 : {
9141 0 : static struct cli_state *cli;
9142 4 : const char *fname_foo = "POSIX_foo";
9143 4 : const char *fname_foo_Foo = "POSIX_foo/Foo";
9144 4 : const char *fname_foo_foo = "POSIX_foo/foo";
9145 4 : const char *fname_Foo = "POSIX_Foo";
9146 4 : const char *fname_Foo_Foo = "POSIX_Foo/Foo";
9147 4 : const char *fname_Foo_foo = "POSIX_Foo/foo";
9148 4 : bool correct = false;
9149 0 : NTSTATUS status;
9150 4 : TALLOC_CTX *frame = NULL;
9151 4 : uint16_t fnum = (uint16_t)-1;
9152 :
9153 4 : frame = talloc_stackframe();
9154 :
9155 4 : printf("Starting POSIX mkdir test\n");
9156 :
9157 4 : if (!torture_open_connection(&cli, 0)) {
9158 0 : TALLOC_FREE(frame);
9159 0 : return false;
9160 : }
9161 :
9162 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
9163 :
9164 4 : status = torture_setup_unix_extensions(cli);
9165 4 : if (!NT_STATUS_IS_OK(status)) {
9166 0 : TALLOC_FREE(frame);
9167 0 : return false;
9168 : }
9169 :
9170 4 : cli_posix_rmdir(cli, fname_foo_foo);
9171 4 : cli_posix_rmdir(cli, fname_foo_Foo);
9172 4 : cli_posix_rmdir(cli, fname_foo);
9173 :
9174 4 : cli_posix_rmdir(cli, fname_Foo_foo);
9175 4 : cli_posix_rmdir(cli, fname_Foo_Foo);
9176 4 : cli_posix_rmdir(cli, fname_Foo);
9177 :
9178 : /*
9179 : * Create a file POSIX_foo then try
9180 : * and use it in a directory path by
9181 : * doing mkdir POSIX_foo/bar.
9182 : * The mkdir should fail with
9183 : * NT_STATUS_OBJECT_PATH_NOT_FOUND
9184 : */
9185 :
9186 4 : status = cli_posix_open(cli,
9187 : fname_foo,
9188 : O_RDWR|O_CREAT,
9189 : 0666,
9190 : &fnum);
9191 4 : if (!NT_STATUS_IS_OK(status)) {
9192 0 : printf("cli_posix_open of %s failed error %s\n",
9193 : fname_foo,
9194 : nt_errstr(status));
9195 0 : goto out;
9196 : }
9197 :
9198 4 : status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9199 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9200 0 : printf("cli_posix_mkdir of %s should fail with "
9201 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9202 : "%s instead\n",
9203 : fname_foo_foo,
9204 : nt_errstr(status));
9205 0 : goto out;
9206 : }
9207 :
9208 4 : status = cli_close(cli, fnum);
9209 4 : if (!NT_STATUS_IS_OK(status)) {
9210 0 : printf("cli_close failed %s\n", nt_errstr(status));
9211 0 : goto out;
9212 : }
9213 4 : fnum = (uint16_t)-1;
9214 :
9215 4 : status = cli_posix_unlink(cli, fname_foo);
9216 4 : if (!NT_STATUS_IS_OK(status)) {
9217 0 : printf("cli_posix_unlink of %s failed error %s\n",
9218 : fname_foo,
9219 : nt_errstr(status));
9220 0 : goto out;
9221 : }
9222 :
9223 : /*
9224 : * Now we've deleted everything, posix_mkdir, posix_rmdir,
9225 : * posix_open, posix_unlink, on
9226 : * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9227 : * not silently create POSIX_foo/foo.
9228 : */
9229 :
9230 4 : status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9231 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9232 0 : printf("cli_posix_mkdir of %s should fail with "
9233 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9234 : "%s instead\n",
9235 : fname_foo_foo,
9236 : nt_errstr(status));
9237 0 : goto out;
9238 : }
9239 :
9240 4 : status = cli_posix_rmdir(cli, fname_foo_foo);
9241 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9242 0 : printf("cli_posix_rmdir of %s should fail with "
9243 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9244 : "%s instead\n",
9245 : fname_foo_foo,
9246 : nt_errstr(status));
9247 0 : goto out;
9248 : }
9249 :
9250 4 : status = cli_posix_open(cli,
9251 : fname_foo_foo,
9252 : O_RDWR|O_CREAT,
9253 : 0666,
9254 : &fnum);
9255 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9256 0 : printf("cli_posix_open of %s should fail with "
9257 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9258 : "%s instead\n",
9259 : fname_foo_foo,
9260 : nt_errstr(status));
9261 0 : goto out;
9262 : }
9263 :
9264 4 : status = cli_posix_unlink(cli, fname_foo_foo);
9265 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9266 0 : printf("cli_posix_unlink of %s should fail with "
9267 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9268 : "%s instead\n",
9269 : fname_foo_foo,
9270 : nt_errstr(status));
9271 0 : goto out;
9272 : }
9273 :
9274 4 : status = cli_posix_mkdir(cli, fname_foo, 0777);
9275 4 : if (!NT_STATUS_IS_OK(status)) {
9276 0 : printf("cli_posix_mkdir of %s failed\n", fname_foo);
9277 0 : goto out;
9278 : }
9279 :
9280 4 : status = cli_posix_mkdir(cli, fname_Foo, 0777);
9281 4 : if (!NT_STATUS_IS_OK(status)) {
9282 0 : printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9283 0 : goto out;
9284 : }
9285 :
9286 4 : status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9287 4 : if (!NT_STATUS_IS_OK(status)) {
9288 0 : printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9289 0 : goto out;
9290 : }
9291 :
9292 4 : status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9293 4 : if (!NT_STATUS_IS_OK(status)) {
9294 0 : printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9295 0 : goto out;
9296 : }
9297 :
9298 4 : status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9299 4 : if (!NT_STATUS_IS_OK(status)) {
9300 0 : printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9301 0 : goto out;
9302 : }
9303 :
9304 4 : status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9305 4 : if (!NT_STATUS_IS_OK(status)) {
9306 0 : printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9307 0 : goto out;
9308 : }
9309 :
9310 4 : printf("POSIX mkdir test passed\n");
9311 4 : correct = true;
9312 :
9313 4 : out:
9314 :
9315 4 : if (fnum != (uint16_t)-1) {
9316 0 : cli_close(cli, fnum);
9317 0 : fnum = (uint16_t)-1;
9318 : }
9319 :
9320 4 : cli_posix_rmdir(cli, fname_foo_foo);
9321 4 : cli_posix_rmdir(cli, fname_foo_Foo);
9322 4 : cli_posix_rmdir(cli, fname_foo);
9323 :
9324 4 : cli_posix_rmdir(cli, fname_Foo_foo);
9325 4 : cli_posix_rmdir(cli, fname_Foo_Foo);
9326 4 : cli_posix_rmdir(cli, fname_Foo);
9327 :
9328 4 : if (!torture_close_connection(cli)) {
9329 0 : correct = false;
9330 : }
9331 :
9332 4 : TALLOC_FREE(frame);
9333 4 : return correct;
9334 : }
9335 :
9336 : struct posix_acl_oplock_state {
9337 : struct tevent_context *ev;
9338 : struct cli_state *cli;
9339 : bool *got_break;
9340 : bool *acl_ret;
9341 : NTSTATUS status;
9342 : };
9343 :
9344 4 : static void posix_acl_oplock_got_break(struct tevent_req *req)
9345 : {
9346 4 : struct posix_acl_oplock_state *state = tevent_req_callback_data(
9347 : req, struct posix_acl_oplock_state);
9348 0 : uint16_t fnum;
9349 0 : uint8_t level;
9350 0 : NTSTATUS status;
9351 :
9352 4 : status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9353 4 : TALLOC_FREE(req);
9354 4 : if (!NT_STATUS_IS_OK(status)) {
9355 0 : printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9356 : nt_errstr(status));
9357 0 : return;
9358 : }
9359 4 : *state->got_break = true;
9360 :
9361 4 : req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9362 : NO_OPLOCK);
9363 4 : if (req == NULL) {
9364 0 : printf("cli_oplock_ack_send failed\n");
9365 0 : return;
9366 : }
9367 : }
9368 :
9369 4 : static void posix_acl_oplock_got_acl(struct tevent_req *req)
9370 : {
9371 4 : struct posix_acl_oplock_state *state = tevent_req_callback_data(
9372 : req, struct posix_acl_oplock_state);
9373 4 : size_t ret_size = 0;
9374 4 : char *ret_data = NULL;
9375 :
9376 4 : state->status = cli_posix_getacl_recv(req,
9377 : state,
9378 : &ret_size,
9379 : &ret_data);
9380 :
9381 4 : if (!NT_STATUS_IS_OK(state->status)) {
9382 0 : printf("cli_posix_getacl_recv returned %s\n",
9383 : nt_errstr(state->status));
9384 : }
9385 4 : *state->acl_ret = true;
9386 4 : }
9387 :
9388 4 : static bool run_posix_acl_oplock_test(int dummy)
9389 : {
9390 0 : struct tevent_context *ev;
9391 0 : struct cli_state *cli1, *cli2;
9392 0 : struct tevent_req *oplock_req, *getacl_req;
9393 4 : const char *fname = "posix_acl_oplock";
9394 0 : uint16_t fnum;
9395 4 : int saved_use_oplocks = use_oplocks;
9396 0 : NTSTATUS status;
9397 4 : bool correct = true;
9398 4 : bool got_break = false;
9399 4 : bool acl_ret = false;
9400 :
9401 0 : struct posix_acl_oplock_state *state;
9402 :
9403 4 : printf("starting posix_acl_oplock test\n");
9404 :
9405 4 : if (!torture_open_connection(&cli1, 0)) {
9406 0 : use_level_II_oplocks = false;
9407 0 : use_oplocks = saved_use_oplocks;
9408 0 : return false;
9409 : }
9410 :
9411 4 : if (!torture_open_connection(&cli2, 1)) {
9412 0 : use_level_II_oplocks = false;
9413 0 : use_oplocks = saved_use_oplocks;
9414 0 : return false;
9415 : }
9416 :
9417 : /* Setup posix on cli2 only. */
9418 4 : status = torture_setup_unix_extensions(cli2);
9419 4 : if (!NT_STATUS_IS_OK(status)) {
9420 0 : return false;
9421 : }
9422 :
9423 4 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
9424 4 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
9425 :
9426 4 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9427 :
9428 : /* Create the file on the Windows connection. */
9429 4 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9430 : &fnum);
9431 4 : if (!NT_STATUS_IS_OK(status)) {
9432 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9433 0 : return false;
9434 : }
9435 :
9436 4 : status = cli_close(cli1, fnum);
9437 4 : if (!NT_STATUS_IS_OK(status)) {
9438 0 : printf("close1 failed (%s)\n", nt_errstr(status));
9439 0 : return false;
9440 : }
9441 :
9442 4 : cli1->use_oplocks = true;
9443 :
9444 : /* Open with oplock. */
9445 4 : status = cli_ntcreate(cli1,
9446 : fname,
9447 : 0,
9448 : FILE_READ_DATA,
9449 : FILE_ATTRIBUTE_NORMAL,
9450 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9451 : FILE_OPEN,
9452 : 0,
9453 : 0,
9454 : &fnum,
9455 : NULL);
9456 :
9457 4 : if (!NT_STATUS_IS_OK(status)) {
9458 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9459 0 : return false;
9460 : }
9461 :
9462 4 : ev = samba_tevent_context_init(talloc_tos());
9463 4 : if (ev == NULL) {
9464 0 : printf("tevent_context_init failed\n");
9465 0 : return false;
9466 : }
9467 :
9468 4 : state = talloc_zero(ev, struct posix_acl_oplock_state);
9469 4 : if (state == NULL) {
9470 0 : printf("talloc failed\n");
9471 0 : return false;
9472 : }
9473 4 : state->ev = ev;
9474 4 : state->cli = cli1;
9475 4 : state->got_break = &got_break;
9476 4 : state->acl_ret = &acl_ret;
9477 :
9478 4 : oplock_req = cli_smb_oplock_break_waiter_send(
9479 : talloc_tos(), ev, cli1);
9480 4 : if (oplock_req == NULL) {
9481 0 : printf("cli_smb_oplock_break_waiter_send failed\n");
9482 0 : return false;
9483 : }
9484 4 : tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9485 :
9486 : /* Get ACL on POSIX connection - should break oplock. */
9487 4 : getacl_req = cli_posix_getacl_send(talloc_tos(),
9488 : ev,
9489 : cli2,
9490 : fname);
9491 4 : if (getacl_req == NULL) {
9492 0 : printf("cli_posix_getacl_send failed\n");
9493 0 : return false;
9494 : }
9495 4 : tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9496 :
9497 36 : while (!got_break || !acl_ret) {
9498 0 : int ret;
9499 32 : ret = tevent_loop_once(ev);
9500 32 : if (ret == -1) {
9501 0 : printf("tevent_loop_once failed: %s\n",
9502 0 : strerror(errno));
9503 0 : return false;
9504 : }
9505 : }
9506 :
9507 4 : if (!NT_STATUS_IS_OK(state->status)) {
9508 0 : printf("getacl failed (%s)\n", nt_errstr(state->status));
9509 0 : correct = false;
9510 : }
9511 :
9512 4 : status = cli_close(cli1, fnum);
9513 4 : if (!NT_STATUS_IS_OK(status)) {
9514 0 : printf("close2 failed (%s)\n", nt_errstr(status));
9515 0 : correct = false;
9516 : }
9517 :
9518 4 : status = cli_unlink(cli1,
9519 : fname,
9520 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9521 4 : if (!NT_STATUS_IS_OK(status)) {
9522 0 : printf("unlink failed (%s)\n", nt_errstr(status));
9523 0 : correct = false;
9524 : }
9525 :
9526 4 : if (!torture_close_connection(cli1)) {
9527 0 : correct = false;
9528 : }
9529 4 : if (!torture_close_connection(cli2)) {
9530 0 : correct = false;
9531 : }
9532 :
9533 4 : if (!got_break) {
9534 0 : correct = false;
9535 : }
9536 :
9537 4 : printf("finished posix acl oplock test\n");
9538 :
9539 4 : return correct;
9540 : }
9541 :
9542 4 : static bool run_posix_acl_shareroot_test(int dummy)
9543 : {
9544 0 : struct cli_state *cli;
9545 0 : NTSTATUS status;
9546 4 : bool correct = false;
9547 4 : char *posix_acl = NULL;
9548 4 : size_t posix_acl_len = 0;
9549 4 : uint16_t num_file_acls = 0;
9550 4 : uint16_t num_dir_acls = 0;
9551 0 : uint16_t i;
9552 4 : uint32_t expected_size = 0;
9553 4 : bool got_user = false;
9554 4 : bool got_group = false;
9555 4 : bool got_other = false;
9556 4 : TALLOC_CTX *frame = NULL;
9557 :
9558 4 : frame = talloc_stackframe();
9559 :
9560 4 : printf("starting posix_acl_shareroot test\n");
9561 :
9562 4 : if (!torture_open_connection(&cli, 0)) {
9563 0 : TALLOC_FREE(frame);
9564 0 : return false;
9565 : }
9566 :
9567 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
9568 :
9569 4 : status = torture_setup_unix_extensions(cli);
9570 4 : if (!NT_STATUS_IS_OK(status)) {
9571 0 : printf("Failed to setup unix extensions\n");
9572 0 : goto out;
9573 : }
9574 :
9575 : /* Get the POSIX ACL on the root of the share. */
9576 4 : status = cli_posix_getacl(cli,
9577 : ".",
9578 : frame,
9579 : &posix_acl_len,
9580 : &posix_acl);
9581 :
9582 4 : if (!NT_STATUS_IS_OK(status)) {
9583 0 : printf("cli_posix_getacl of '.' failed (%s)\n",
9584 : nt_errstr(status));
9585 0 : goto out;
9586 : }
9587 :
9588 4 : if (posix_acl_len < 6 ||
9589 4 : SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9590 0 : printf("getfacl ., unknown POSIX acl version %u.\n",
9591 0 : (unsigned int)CVAL(posix_acl,0) );
9592 0 : goto out;
9593 : }
9594 :
9595 4 : num_file_acls = SVAL(posix_acl,2);
9596 4 : num_dir_acls = SVAL(posix_acl,4);
9597 4 : expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9598 4 : SMB_POSIX_ACL_ENTRY_SIZE*
9599 4 : (num_file_acls+num_dir_acls);
9600 :
9601 4 : if (posix_acl_len != expected_size) {
9602 0 : printf("incorrect POSIX acl buffer size "
9603 : "(should be %u, was %u).\n",
9604 : (unsigned int)expected_size,
9605 : (unsigned int)posix_acl_len);
9606 0 : goto out;
9607 : }
9608 :
9609 : /*
9610 : * We don't need to know what the ACL's are
9611 : * we just need to know we have at least 3
9612 : * file entries (u,g,o).
9613 : */
9614 :
9615 16 : for (i = 0; i < num_file_acls; i++) {
9616 12 : unsigned char tagtype =
9617 12 : CVAL(posix_acl,
9618 : SMB_POSIX_ACL_HEADER_SIZE+
9619 : (i*SMB_POSIX_ACL_ENTRY_SIZE));
9620 :
9621 12 : switch(tagtype) {
9622 4 : case SMB_POSIX_ACL_USER_OBJ:
9623 4 : got_user = true;
9624 4 : break;
9625 4 : case SMB_POSIX_ACL_GROUP_OBJ:
9626 4 : got_group = true;
9627 4 : break;
9628 4 : case SMB_POSIX_ACL_OTHER:
9629 4 : got_other = true;
9630 4 : break;
9631 0 : default:
9632 0 : break;
9633 : }
9634 : }
9635 :
9636 4 : if (!got_user) {
9637 0 : printf("Missing user entry\n");
9638 0 : goto out;
9639 : }
9640 :
9641 4 : if (!got_group) {
9642 0 : printf("Missing group entry\n");
9643 0 : goto out;
9644 : }
9645 :
9646 4 : if (!got_other) {
9647 0 : printf("Missing other entry\n");
9648 0 : goto out;
9649 : }
9650 :
9651 4 : correct = true;
9652 :
9653 4 : out:
9654 :
9655 4 : if (!torture_close_connection(cli)) {
9656 0 : correct = false;
9657 : }
9658 :
9659 4 : printf("finished posix acl shareroot test\n");
9660 4 : TALLOC_FREE(frame);
9661 :
9662 4 : return correct;
9663 : }
9664 :
9665 : static uint32_t open_attrs_table[] = {
9666 : FILE_ATTRIBUTE_NORMAL,
9667 : FILE_ATTRIBUTE_ARCHIVE,
9668 : FILE_ATTRIBUTE_READONLY,
9669 : FILE_ATTRIBUTE_HIDDEN,
9670 : FILE_ATTRIBUTE_SYSTEM,
9671 :
9672 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9673 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9674 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9675 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9676 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9677 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9678 :
9679 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9680 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9681 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9682 : FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9683 : };
9684 :
9685 : struct trunc_open_results {
9686 : unsigned int num;
9687 : uint32_t init_attr;
9688 : uint32_t trunc_attr;
9689 : uint32_t result_attr;
9690 : };
9691 :
9692 : static struct trunc_open_results attr_results[] = {
9693 : { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9694 : { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9695 : { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9696 : { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9697 : { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9698 : { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9699 : { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9700 : { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9701 : { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9702 : { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9703 : { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9704 : { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9705 : { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9706 : { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9707 : { 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 },
9708 : { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9709 : { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9710 : { 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 },
9711 : { 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 },
9712 : { 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 },
9713 : { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9714 : { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9715 : { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9716 : { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9717 : { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9718 : { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9719 : };
9720 :
9721 0 : static bool run_openattrtest(int dummy)
9722 : {
9723 0 : static struct cli_state *cli1;
9724 0 : const char *fname = "\\openattr.file";
9725 0 : uint16_t fnum1;
9726 0 : bool correct = True;
9727 0 : uint32_t attr;
9728 0 : unsigned int i, j, k, l;
9729 0 : NTSTATUS status;
9730 :
9731 0 : printf("starting open attr test\n");
9732 :
9733 0 : if (!torture_open_connection(&cli1, 0)) {
9734 0 : return False;
9735 : }
9736 :
9737 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
9738 :
9739 0 : for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9740 0 : cli_setatr(cli1, fname, 0, 0);
9741 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9742 :
9743 0 : status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9744 : open_attrs_table[i], FILE_SHARE_NONE,
9745 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9746 0 : if (!NT_STATUS_IS_OK(status)) {
9747 0 : printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9748 0 : return False;
9749 : }
9750 :
9751 0 : status = cli_close(cli1, fnum1);
9752 0 : if (!NT_STATUS_IS_OK(status)) {
9753 0 : printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9754 0 : return False;
9755 : }
9756 :
9757 0 : for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9758 0 : status = cli_ntcreate(cli1, fname, 0,
9759 : FILE_READ_DATA|FILE_WRITE_DATA,
9760 : open_attrs_table[j],
9761 : FILE_SHARE_NONE, FILE_OVERWRITE,
9762 : 0, 0, &fnum1, NULL);
9763 0 : if (!NT_STATUS_IS_OK(status)) {
9764 0 : for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9765 0 : if (attr_results[l].num == k) {
9766 0 : printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9767 : k, open_attrs_table[i],
9768 : open_attrs_table[j],
9769 : fname, NT_STATUS_V(status), nt_errstr(status));
9770 0 : correct = False;
9771 : }
9772 : }
9773 :
9774 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9775 0 : printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9776 : k, open_attrs_table[i], open_attrs_table[j],
9777 : nt_errstr(status));
9778 0 : correct = False;
9779 : }
9780 : #if 0
9781 : printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9782 : #endif
9783 0 : k++;
9784 0 : continue;
9785 : }
9786 :
9787 0 : status = cli_close(cli1, fnum1);
9788 0 : if (!NT_STATUS_IS_OK(status)) {
9789 0 : printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9790 0 : return False;
9791 : }
9792 :
9793 0 : status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9794 0 : if (!NT_STATUS_IS_OK(status)) {
9795 0 : printf("getatr(2) failed (%s)\n", nt_errstr(status));
9796 0 : return False;
9797 : }
9798 :
9799 : #if 0
9800 : printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9801 : k, open_attrs_table[i], open_attrs_table[j], attr );
9802 : #endif
9803 :
9804 0 : for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9805 0 : if (attr_results[l].num == k) {
9806 0 : if (attr != attr_results[l].result_attr ||
9807 0 : open_attrs_table[i] != attr_results[l].init_attr ||
9808 0 : open_attrs_table[j] != attr_results[l].trunc_attr) {
9809 0 : printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9810 : open_attrs_table[i],
9811 : open_attrs_table[j],
9812 : (unsigned int)attr,
9813 : attr_results[l].result_attr);
9814 0 : correct = False;
9815 : }
9816 0 : break;
9817 : }
9818 : }
9819 0 : k++;
9820 : }
9821 : }
9822 :
9823 0 : cli_setatr(cli1, fname, 0, 0);
9824 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9825 :
9826 0 : printf("open attr test %s.\n", correct ? "passed" : "failed");
9827 :
9828 0 : if (!torture_close_connection(cli1)) {
9829 0 : correct = False;
9830 : }
9831 0 : return correct;
9832 : }
9833 :
9834 0 : static NTSTATUS list_fn(struct file_info *finfo,
9835 : const char *name, void *state)
9836 : {
9837 0 : int *matched = (int *)state;
9838 0 : if (matched != NULL) {
9839 0 : *matched += 1;
9840 : }
9841 0 : return NT_STATUS_OK;
9842 : }
9843 :
9844 : /*
9845 : test directory listing speed
9846 : */
9847 5 : static bool run_dirtest(int dummy)
9848 : {
9849 0 : int i;
9850 0 : static struct cli_state *cli;
9851 0 : uint16_t fnum;
9852 0 : struct timeval core_start;
9853 5 : bool correct = True;
9854 0 : int matched;
9855 :
9856 5 : printf("starting directory test\n");
9857 :
9858 5 : if (!torture_open_connection(&cli, 0)) {
9859 0 : return False;
9860 : }
9861 :
9862 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
9863 :
9864 5 : srandom(0);
9865 505 : for (i=0;i<torture_numops;i++) {
9866 0 : fstring fname;
9867 500 : slprintf(fname, sizeof(fname), "\\%x", (int)random());
9868 500 : if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9869 0 : fprintf(stderr,"Failed to open %s\n", fname);
9870 0 : return False;
9871 : }
9872 500 : cli_close(cli, fnum);
9873 : }
9874 :
9875 5 : core_start = timeval_current();
9876 :
9877 5 : matched = 0;
9878 5 : cli_list(cli, "a*.*", 0, list_fn, &matched);
9879 5 : printf("Matched %d\n", matched);
9880 :
9881 5 : matched = 0;
9882 5 : cli_list(cli, "b*.*", 0, list_fn, &matched);
9883 5 : printf("Matched %d\n", matched);
9884 :
9885 5 : matched = 0;
9886 5 : cli_list(cli, "xyzabc", 0, list_fn, &matched);
9887 5 : printf("Matched %d\n", matched);
9888 :
9889 5 : printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9890 :
9891 5 : srandom(0);
9892 505 : for (i=0;i<torture_numops;i++) {
9893 0 : fstring fname;
9894 500 : slprintf(fname, sizeof(fname), "\\%x", (int)random());
9895 500 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9896 : }
9897 :
9898 5 : if (!torture_close_connection(cli)) {
9899 0 : correct = False;
9900 : }
9901 :
9902 5 : printf("finished dirtest\n");
9903 :
9904 5 : return correct;
9905 : }
9906 :
9907 0 : static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9908 : void *state)
9909 : {
9910 0 : struct cli_state *pcli = (struct cli_state *)state;
9911 0 : fstring fname;
9912 0 : slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9913 :
9914 0 : if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9915 0 : return NT_STATUS_OK;
9916 :
9917 0 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9918 0 : if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9919 0 : printf("del_fn: failed to rmdir %s\n,", fname );
9920 : } else {
9921 0 : if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9922 0 : printf("del_fn: failed to unlink %s\n,", fname );
9923 : }
9924 0 : return NT_STATUS_OK;
9925 : }
9926 :
9927 :
9928 : /*
9929 : send a raw ioctl - used by the torture code
9930 : */
9931 327690 : static NTSTATUS cli_raw_ioctl(struct cli_state *cli,
9932 : uint16_t fnum,
9933 : uint32_t code,
9934 : DATA_BLOB *blob)
9935 : {
9936 0 : uint16_t vwv[3];
9937 0 : NTSTATUS status;
9938 :
9939 327690 : PUSH_LE_U16(vwv + 0, 0, fnum);
9940 327690 : PUSH_LE_U16(vwv + 1, 0, code >> 16);
9941 327690 : PUSH_LE_U16(vwv + 2, 0, (code & 0xFFFF));
9942 :
9943 327690 : status = cli_smb(talloc_tos(),
9944 : cli,
9945 : SMBioctl,
9946 : 0,
9947 : 3,
9948 : vwv,
9949 : 0,
9950 : NULL,
9951 : NULL,
9952 : 0,
9953 : NULL,
9954 : NULL,
9955 : NULL,
9956 : NULL);
9957 327690 : if (!NT_STATUS_IS_OK(status)) {
9958 327682 : return status;
9959 : }
9960 8 : *blob = data_blob_null;
9961 8 : return NT_STATUS_OK;
9962 : }
9963 :
9964 : /*
9965 : sees what IOCTLs are supported
9966 : */
9967 5 : bool torture_ioctl_test(int dummy)
9968 : {
9969 0 : static struct cli_state *cli;
9970 0 : uint16_t device, function;
9971 0 : uint16_t fnum;
9972 5 : const char *fname = "\\ioctl.dat";
9973 0 : DATA_BLOB blob;
9974 0 : NTSTATUS status;
9975 :
9976 5 : if (!torture_open_connection(&cli, 0)) {
9977 0 : return False;
9978 : }
9979 :
9980 5 : printf("starting ioctl test\n");
9981 :
9982 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9983 :
9984 5 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9985 5 : if (!NT_STATUS_IS_OK(status)) {
9986 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9987 0 : return False;
9988 : }
9989 :
9990 5 : status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9991 5 : printf("ioctl device info: %s\n", nt_errstr(status));
9992 :
9993 5 : status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9994 5 : printf("ioctl job info: %s\n", nt_errstr(status));
9995 :
9996 1285 : for (device=0;device<0x100;device++) {
9997 1280 : printf("ioctl test with device = 0x%x\n", device);
9998 328960 : for (function=0;function<0x100;function++) {
9999 327680 : uint32_t code = (device<<16) | function;
10000 :
10001 327680 : status = cli_raw_ioctl(cli, fnum, code, &blob);
10002 :
10003 327680 : if (NT_STATUS_IS_OK(status)) {
10004 4 : printf("ioctl 0x%x OK : %d bytes\n", (int)code,
10005 4 : (int)blob.length);
10006 4 : data_blob_free(&blob);
10007 : }
10008 : }
10009 : }
10010 :
10011 5 : if (!torture_close_connection(cli)) {
10012 0 : return False;
10013 : }
10014 :
10015 5 : return True;
10016 : }
10017 :
10018 :
10019 : /*
10020 : tries variants of chkpath
10021 : */
10022 5 : bool torture_chkpath_test(int dummy)
10023 : {
10024 0 : static struct cli_state *cli;
10025 0 : uint16_t fnum;
10026 0 : bool ret;
10027 0 : NTSTATUS status;
10028 :
10029 5 : if (!torture_open_connection(&cli, 0)) {
10030 0 : return False;
10031 : }
10032 :
10033 5 : printf("starting chkpath test\n");
10034 :
10035 : /* cleanup from an old run */
10036 5 : torture_deltree(cli, "\\chkpath.dir");
10037 :
10038 5 : status = cli_mkdir(cli, "\\chkpath.dir");
10039 5 : if (!NT_STATUS_IS_OK(status)) {
10040 0 : printf("mkdir1 failed : %s\n", nt_errstr(status));
10041 0 : return False;
10042 : }
10043 :
10044 5 : status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
10045 5 : if (!NT_STATUS_IS_OK(status)) {
10046 0 : printf("mkdir2 failed : %s\n", nt_errstr(status));
10047 0 : return False;
10048 : }
10049 :
10050 5 : status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
10051 : DENY_NONE, &fnum);
10052 5 : if (!NT_STATUS_IS_OK(status)) {
10053 0 : printf("open1 failed (%s)\n", nt_errstr(status));
10054 0 : return False;
10055 : }
10056 5 : cli_close(cli, fnum);
10057 :
10058 5 : status = cli_chkpath(cli, "\\chkpath.dir");
10059 5 : if (!NT_STATUS_IS_OK(status)) {
10060 0 : printf("chkpath1 failed: %s\n", nt_errstr(status));
10061 0 : ret = False;
10062 : }
10063 :
10064 5 : status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
10065 5 : if (!NT_STATUS_IS_OK(status)) {
10066 0 : printf("chkpath2 failed: %s\n", nt_errstr(status));
10067 0 : ret = False;
10068 : }
10069 :
10070 5 : status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
10071 5 : if (!NT_STATUS_IS_OK(status)) {
10072 5 : ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10073 5 : NT_STATUS_NOT_A_DIRECTORY);
10074 : } else {
10075 0 : printf("* chkpath on a file should fail\n");
10076 0 : ret = False;
10077 : }
10078 :
10079 5 : status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
10080 5 : if (!NT_STATUS_IS_OK(status)) {
10081 5 : ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
10082 5 : NT_STATUS_OBJECT_NAME_NOT_FOUND);
10083 : } else {
10084 0 : printf("* chkpath on a non existent file should fail\n");
10085 0 : ret = False;
10086 : }
10087 :
10088 5 : status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
10089 5 : if (!NT_STATUS_IS_OK(status)) {
10090 5 : ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10091 5 : NT_STATUS_OBJECT_PATH_NOT_FOUND);
10092 : } else {
10093 0 : printf("* chkpath on a non existent component should fail\n");
10094 0 : ret = False;
10095 : }
10096 :
10097 5 : torture_deltree(cli, "\\chkpath.dir");
10098 :
10099 5 : if (!torture_close_connection(cli)) {
10100 0 : return False;
10101 : }
10102 :
10103 5 : return ret;
10104 : }
10105 :
10106 0 : static bool run_eatest(int dummy)
10107 : {
10108 0 : static struct cli_state *cli;
10109 0 : const char *fname = "\\eatest.txt";
10110 0 : bool correct = True;
10111 0 : uint16_t fnum;
10112 0 : size_t i, num_eas;
10113 0 : struct ea_struct *ea_list = NULL;
10114 0 : TALLOC_CTX *mem_ctx = talloc_init("eatest");
10115 0 : NTSTATUS status;
10116 :
10117 0 : printf("starting eatest\n");
10118 :
10119 0 : if (!torture_open_connection(&cli, 0)) {
10120 0 : talloc_destroy(mem_ctx);
10121 0 : return False;
10122 : }
10123 :
10124 0 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10125 :
10126 0 : status = cli_ntcreate(cli, fname, 0,
10127 : FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10128 : FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10129 : 0x4044, 0, &fnum, NULL);
10130 0 : if (!NT_STATUS_IS_OK(status)) {
10131 0 : printf("open failed - %s\n", nt_errstr(status));
10132 0 : talloc_destroy(mem_ctx);
10133 0 : return False;
10134 : }
10135 :
10136 0 : for (i = 0; i < 10; i++) {
10137 0 : fstring ea_name, ea_val;
10138 :
10139 0 : slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10140 0 : memset(ea_val, (char)i+1, i+1);
10141 0 : status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10142 0 : if (!NT_STATUS_IS_OK(status)) {
10143 0 : printf("ea_set of name %s failed - %s\n", ea_name,
10144 : nt_errstr(status));
10145 0 : talloc_destroy(mem_ctx);
10146 0 : return False;
10147 : }
10148 : }
10149 :
10150 0 : cli_close(cli, fnum);
10151 0 : for (i = 0; i < 10; i++) {
10152 0 : fstring ea_name, ea_val;
10153 :
10154 0 : slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10155 0 : memset(ea_val, (char)i+1, i+1);
10156 0 : status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10157 0 : if (!NT_STATUS_IS_OK(status)) {
10158 0 : printf("ea_set of name %s failed - %s\n", ea_name,
10159 : nt_errstr(status));
10160 0 : talloc_destroy(mem_ctx);
10161 0 : return False;
10162 : }
10163 : }
10164 :
10165 0 : status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10166 0 : if (!NT_STATUS_IS_OK(status)) {
10167 0 : printf("ea_get list failed - %s\n", nt_errstr(status));
10168 0 : correct = False;
10169 : }
10170 :
10171 0 : printf("num_eas = %d\n", (int)num_eas);
10172 :
10173 0 : if (num_eas != 20) {
10174 0 : printf("Should be 20 EA's stored... failing.\n");
10175 0 : correct = False;
10176 : }
10177 :
10178 0 : for (i = 0; i < num_eas; i++) {
10179 0 : printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10180 0 : dump_data(0, ea_list[i].value.data,
10181 0 : ea_list[i].value.length);
10182 : }
10183 :
10184 : /* Setting EA's to zero length deletes them. Test this */
10185 0 : printf("Now deleting all EA's - case independent....\n");
10186 :
10187 : #if 1
10188 0 : cli_set_ea_path(cli, fname, "", "", 0);
10189 : #else
10190 : for (i = 0; i < 20; i++) {
10191 : fstring ea_name;
10192 : slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10193 : status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10194 : if (!NT_STATUS_IS_OK(status)) {
10195 : printf("ea_set of name %s failed - %s\n", ea_name,
10196 : nt_errstr(status));
10197 : talloc_destroy(mem_ctx);
10198 : return False;
10199 : }
10200 : }
10201 : #endif
10202 :
10203 0 : status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10204 0 : if (!NT_STATUS_IS_OK(status)) {
10205 0 : printf("ea_get list failed - %s\n", nt_errstr(status));
10206 0 : correct = False;
10207 : }
10208 :
10209 0 : printf("num_eas = %d\n", (int)num_eas);
10210 0 : for (i = 0; i < num_eas; i++) {
10211 0 : printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10212 0 : dump_data(0, ea_list[i].value.data,
10213 0 : ea_list[i].value.length);
10214 : }
10215 :
10216 0 : if (num_eas != 0) {
10217 0 : printf("deleting EA's failed.\n");
10218 0 : correct = False;
10219 : }
10220 :
10221 : /* Try and delete a non existent EA. */
10222 0 : status = cli_set_ea_path(cli, fname, "foo", "", 0);
10223 0 : if (!NT_STATUS_IS_OK(status)) {
10224 0 : printf("deleting non-existent EA 'foo' should succeed. %s\n",
10225 : nt_errstr(status));
10226 0 : correct = False;
10227 : }
10228 :
10229 0 : talloc_destroy(mem_ctx);
10230 0 : if (!torture_close_connection(cli)) {
10231 0 : correct = False;
10232 : }
10233 :
10234 0 : return correct;
10235 : }
10236 :
10237 0 : static bool run_dirtest1(int dummy)
10238 : {
10239 0 : int i;
10240 0 : static struct cli_state *cli;
10241 0 : uint16_t fnum;
10242 0 : int num_seen;
10243 0 : bool correct = True;
10244 :
10245 0 : printf("starting directory test\n");
10246 :
10247 0 : if (!torture_open_connection(&cli, 0)) {
10248 0 : return False;
10249 : }
10250 :
10251 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
10252 :
10253 0 : cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10254 0 : cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10255 0 : cli_rmdir(cli, "\\LISTDIR");
10256 0 : cli_mkdir(cli, "\\LISTDIR");
10257 :
10258 : /* Create 1000 files and 1000 directories. */
10259 0 : for (i=0;i<1000;i++) {
10260 0 : fstring fname;
10261 0 : slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10262 0 : if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10263 : FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10264 : 0, 0, &fnum, NULL))) {
10265 0 : fprintf(stderr,"Failed to open %s\n", fname);
10266 0 : return False;
10267 : }
10268 0 : cli_close(cli, fnum);
10269 : }
10270 0 : for (i=0;i<1000;i++) {
10271 0 : fstring fname;
10272 0 : slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10273 0 : if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10274 0 : fprintf(stderr,"Failed to open %s\n", fname);
10275 0 : return False;
10276 : }
10277 : }
10278 :
10279 : /* Now ensure that doing an old list sees both files and directories. */
10280 0 : num_seen = 0;
10281 0 : cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10282 0 : printf("num_seen = %d\n", num_seen );
10283 : /* We should see 100 files + 1000 directories + . and .. */
10284 0 : if (num_seen != 2002)
10285 0 : correct = False;
10286 :
10287 : /* Ensure if we have the "must have" bits we only see the
10288 : * relevant entries.
10289 : */
10290 0 : num_seen = 0;
10291 0 : cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10292 0 : printf("num_seen = %d\n", num_seen );
10293 0 : if (num_seen != 1002)
10294 0 : correct = False;
10295 :
10296 0 : num_seen = 0;
10297 0 : cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10298 0 : printf("num_seen = %d\n", num_seen );
10299 0 : if (num_seen != 1000)
10300 0 : correct = False;
10301 :
10302 : /* Delete everything. */
10303 0 : cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10304 0 : cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10305 0 : cli_rmdir(cli, "\\LISTDIR");
10306 :
10307 : #if 0
10308 : printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10309 : printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10310 : printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10311 : #endif
10312 :
10313 0 : if (!torture_close_connection(cli)) {
10314 0 : correct = False;
10315 : }
10316 :
10317 0 : printf("finished dirtest1\n");
10318 :
10319 0 : return correct;
10320 : }
10321 :
10322 0 : static bool run_error_map_extract(int dummy) {
10323 :
10324 0 : static struct cli_state *c_dos;
10325 0 : static struct cli_state *c_nt;
10326 0 : NTSTATUS status;
10327 :
10328 0 : uint32_t error;
10329 :
10330 0 : uint32_t errnum;
10331 0 : uint8_t errclass;
10332 :
10333 0 : NTSTATUS nt_status;
10334 :
10335 0 : fstring user;
10336 :
10337 : /* NT-Error connection */
10338 :
10339 0 : disable_spnego = true;
10340 0 : if (!(c_nt = open_nbt_connection())) {
10341 0 : disable_spnego = false;
10342 0 : return False;
10343 : }
10344 0 : disable_spnego = false;
10345 :
10346 0 : status = smbXcli_negprot(c_nt->conn,
10347 0 : c_nt->timeout,
10348 : PROTOCOL_CORE,
10349 : PROTOCOL_NT1,
10350 : NULL,
10351 : NULL,
10352 : NULL);
10353 :
10354 0 : if (!NT_STATUS_IS_OK(status)) {
10355 0 : printf("%s rejected the NT-error negprot (%s)\n", host,
10356 : nt_errstr(status));
10357 0 : cli_shutdown(c_nt);
10358 0 : return False;
10359 : }
10360 :
10361 0 : status = cli_session_setup_anon(c_nt);
10362 0 : if (!NT_STATUS_IS_OK(status)) {
10363 0 : printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10364 0 : return False;
10365 : }
10366 :
10367 : /* DOS-Error connection */
10368 :
10369 0 : disable_spnego = true;
10370 0 : force_dos_errors = true;
10371 0 : if (!(c_dos = open_nbt_connection())) {
10372 0 : disable_spnego = false;
10373 0 : force_dos_errors = false;
10374 0 : return False;
10375 : }
10376 0 : disable_spnego = false;
10377 0 : force_dos_errors = false;
10378 :
10379 0 : status = smbXcli_negprot(c_dos->conn,
10380 0 : c_dos->timeout,
10381 : PROTOCOL_CORE,
10382 : PROTOCOL_NT1,
10383 : NULL,
10384 : NULL,
10385 : NULL);
10386 0 : if (!NT_STATUS_IS_OK(status)) {
10387 0 : printf("%s rejected the DOS-error negprot (%s)\n", host,
10388 : nt_errstr(status));
10389 0 : cli_shutdown(c_dos);
10390 0 : return False;
10391 : }
10392 :
10393 0 : status = cli_session_setup_anon(c_dos);
10394 0 : if (!NT_STATUS_IS_OK(status)) {
10395 0 : printf("%s rejected the DOS-error initial session setup (%s)\n",
10396 : host, nt_errstr(status));
10397 0 : return False;
10398 : }
10399 :
10400 0 : c_nt->map_dos_errors = false;
10401 0 : c_dos->map_dos_errors = false;
10402 :
10403 0 : for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10404 0 : struct cli_credentials *user_creds = NULL;
10405 :
10406 0 : fstr_sprintf(user, "%X", error);
10407 :
10408 0 : user_creds = cli_session_creds_init(talloc_tos(),
10409 : user,
10410 : workgroup,
10411 : NULL, /* realm */
10412 : password,
10413 : false, /* use_kerberos */
10414 : false, /* fallback_after_kerberos */
10415 : false, /* use_ccache */
10416 : false); /* password_is_nt_hash */
10417 0 : if (user_creds == NULL) {
10418 0 : printf("cli_session_creds_init(%s) failed\n", user);
10419 0 : return false;
10420 : }
10421 :
10422 0 : status = cli_session_setup_creds(c_nt, user_creds);
10423 0 : if (NT_STATUS_IS_OK(status)) {
10424 0 : printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10425 : }
10426 :
10427 : /* Case #1: 32-bit NT errors */
10428 0 : if (!NT_STATUS_IS_DOS(status)) {
10429 0 : nt_status = status;
10430 : } else {
10431 0 : printf("/** Dos error on NT connection! (%s) */\n",
10432 : nt_errstr(status));
10433 0 : nt_status = NT_STATUS(0xc0000000);
10434 : }
10435 :
10436 0 : status = cli_session_setup_creds(c_dos, user_creds);
10437 0 : if (NT_STATUS_IS_OK(status)) {
10438 0 : printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10439 : }
10440 :
10441 : /* Case #1: 32-bit NT errors */
10442 0 : if (NT_STATUS_IS_DOS(status)) {
10443 0 : printf("/** NT error on DOS connection! (%s) */\n",
10444 : nt_errstr(status));
10445 0 : errnum = errclass = 0;
10446 : } else {
10447 0 : errclass = NT_STATUS_DOS_CLASS(status);
10448 0 : errnum = NT_STATUS_DOS_CODE(status);
10449 : }
10450 :
10451 0 : if (NT_STATUS_V(nt_status) != error) {
10452 0 : printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10453 0 : get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
10454 0 : get_nt_error_c_code(talloc_tos(), nt_status));
10455 : }
10456 :
10457 0 : printf("\t{%s,\t%s,\t%s},\n",
10458 : smb_dos_err_class(errclass),
10459 : smb_dos_err_name(errclass, errnum),
10460 0 : get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10461 :
10462 0 : TALLOC_FREE(user_creds);
10463 : }
10464 0 : return True;
10465 : }
10466 :
10467 0 : static bool run_sesssetup_bench(int dummy)
10468 : {
10469 0 : static struct cli_state *c;
10470 0 : const char *fname = "\\file.dat";
10471 0 : uint16_t fnum;
10472 0 : NTSTATUS status;
10473 0 : int i;
10474 :
10475 0 : if (!torture_open_connection(&c, 0)) {
10476 0 : return false;
10477 : }
10478 :
10479 0 : status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10480 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10481 : FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10482 0 : if (!NT_STATUS_IS_OK(status)) {
10483 0 : d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10484 0 : return false;
10485 : }
10486 :
10487 0 : for (i=0; i<torture_numops; i++) {
10488 0 : status = cli_session_setup_creds(c, torture_creds);
10489 0 : if (!NT_STATUS_IS_OK(status)) {
10490 0 : d_printf("(%s) cli_session_setup_creds failed: %s\n",
10491 : __location__, nt_errstr(status));
10492 0 : return false;
10493 : }
10494 :
10495 0 : d_printf("\r%d ", (int)cli_state_get_uid(c));
10496 :
10497 0 : status = cli_ulogoff(c);
10498 0 : if (!NT_STATUS_IS_OK(status)) {
10499 0 : d_printf("(%s) cli_ulogoff failed: %s\n",
10500 : __location__, nt_errstr(status));
10501 0 : return false;
10502 : }
10503 : }
10504 :
10505 0 : return true;
10506 : }
10507 :
10508 9 : static bool subst_test(const char *str, const char *user, const char *domain,
10509 : uid_t uid, gid_t gid, const char *expected)
10510 : {
10511 9 : char *subst;
10512 9 : bool result = true;
10513 :
10514 9 : subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10515 :
10516 9 : if (strcmp(subst, expected) != 0) {
10517 0 : printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10518 : "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10519 : expected);
10520 0 : result = false;
10521 : }
10522 :
10523 9 : TALLOC_FREE(subst);
10524 9 : return result;
10525 : }
10526 :
10527 5 : static void chain1_open_completion(struct tevent_req *req)
10528 : {
10529 0 : uint16_t fnum;
10530 0 : NTSTATUS status;
10531 5 : status = cli_openx_recv(req, &fnum);
10532 5 : TALLOC_FREE(req);
10533 :
10534 5 : d_printf("cli_openx_recv returned %s: %d\n",
10535 : nt_errstr(status),
10536 5 : NT_STATUS_IS_OK(status) ? fnum : -1);
10537 5 : }
10538 :
10539 5 : static void chain1_write_completion(struct tevent_req *req)
10540 : {
10541 0 : size_t written;
10542 0 : NTSTATUS status;
10543 5 : status = cli_write_andx_recv(req, &written);
10544 5 : TALLOC_FREE(req);
10545 :
10546 5 : d_printf("cli_write_andx_recv returned %s: %d\n",
10547 : nt_errstr(status),
10548 5 : NT_STATUS_IS_OK(status) ? (int)written : -1);
10549 5 : }
10550 :
10551 5 : static void chain1_close_completion(struct tevent_req *req)
10552 : {
10553 0 : NTSTATUS status;
10554 5 : bool *done = (bool *)tevent_req_callback_data_void(req);
10555 :
10556 5 : status = cli_close_recv(req);
10557 5 : *done = true;
10558 :
10559 5 : TALLOC_FREE(req);
10560 :
10561 5 : d_printf("cli_close returned %s\n", nt_errstr(status));
10562 5 : }
10563 :
10564 5 : static bool run_chain1(int dummy)
10565 : {
10566 0 : struct cli_state *cli1;
10567 5 : struct tevent_context *evt = samba_tevent_context_init(NULL);
10568 0 : struct tevent_req *reqs[3], *smbreqs[3];
10569 5 : bool done = false;
10570 5 : const char *str = "foobar";
10571 5 : const char *fname = "\\test_chain";
10572 0 : NTSTATUS status;
10573 :
10574 5 : printf("starting chain1 test\n");
10575 5 : if (!torture_open_connection(&cli1, 0)) {
10576 0 : return False;
10577 : }
10578 :
10579 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
10580 :
10581 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10582 :
10583 5 : reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10584 : O_CREAT|O_RDWR, 0, &smbreqs[0]);
10585 5 : if (reqs[0] == NULL) return false;
10586 5 : tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10587 :
10588 :
10589 5 : reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10590 5 : (const uint8_t *)str, 0, strlen(str)+1,
10591 : smbreqs, 1, &smbreqs[1]);
10592 5 : if (reqs[1] == NULL) return false;
10593 5 : tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10594 :
10595 5 : reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10596 5 : if (reqs[2] == NULL) return false;
10597 5 : tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10598 :
10599 5 : status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10600 5 : if (!NT_STATUS_IS_OK(status)) {
10601 0 : return false;
10602 : }
10603 :
10604 35 : while (!done) {
10605 30 : tevent_loop_once(evt);
10606 : }
10607 :
10608 5 : torture_close_connection(cli1);
10609 5 : return True;
10610 : }
10611 :
10612 5 : static void chain2_sesssetup_completion(struct tevent_req *req)
10613 : {
10614 0 : NTSTATUS status;
10615 5 : status = cli_session_setup_guest_recv(req);
10616 5 : d_printf("sesssetup returned %s\n", nt_errstr(status));
10617 5 : }
10618 :
10619 5 : static void chain2_tcon_completion(struct tevent_req *req)
10620 : {
10621 5 : bool *done = (bool *)tevent_req_callback_data_void(req);
10622 0 : NTSTATUS status;
10623 5 : status = cli_tcon_andx_recv(req);
10624 5 : d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10625 5 : *done = true;
10626 5 : }
10627 :
10628 5 : static bool run_chain2(int dummy)
10629 : {
10630 0 : struct cli_state *cli1;
10631 5 : struct tevent_context *evt = samba_tevent_context_init(NULL);
10632 0 : struct tevent_req *reqs[2], *smbreqs[2];
10633 5 : bool done = false;
10634 0 : NTSTATUS status;
10635 5 : int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10636 :
10637 5 : printf("starting chain2 test\n");
10638 5 : status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10639 : port_to_use, SMB_SIGNING_DEFAULT, flags);
10640 5 : if (!NT_STATUS_IS_OK(status)) {
10641 0 : return False;
10642 : }
10643 :
10644 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
10645 :
10646 5 : reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10647 : &smbreqs[0]);
10648 5 : if (reqs[0] == NULL) return false;
10649 5 : tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10650 :
10651 5 : reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10652 : "?????", NULL, 0, &smbreqs[1]);
10653 5 : if (reqs[1] == NULL) return false;
10654 5 : tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10655 :
10656 5 : status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10657 5 : if (!NT_STATUS_IS_OK(status)) {
10658 0 : return false;
10659 : }
10660 :
10661 30 : while (!done) {
10662 25 : tevent_loop_once(evt);
10663 : }
10664 :
10665 5 : torture_close_connection(cli1);
10666 5 : return True;
10667 : }
10668 :
10669 :
10670 : struct torture_createdel_state {
10671 : struct tevent_context *ev;
10672 : struct cli_state *cli;
10673 : };
10674 :
10675 : static void torture_createdel_created(struct tevent_req *subreq);
10676 : static void torture_createdel_closed(struct tevent_req *subreq);
10677 :
10678 0 : static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10679 : struct tevent_context *ev,
10680 : struct cli_state *cli,
10681 : const char *name)
10682 : {
10683 0 : struct tevent_req *req, *subreq;
10684 0 : struct torture_createdel_state *state;
10685 :
10686 0 : req = tevent_req_create(mem_ctx, &state,
10687 : struct torture_createdel_state);
10688 0 : if (req == NULL) {
10689 0 : return NULL;
10690 : }
10691 0 : state->ev = ev;
10692 0 : state->cli = cli;
10693 :
10694 0 : subreq = cli_ntcreate_send(
10695 : state, ev, cli, name, 0,
10696 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10697 : FILE_ATTRIBUTE_NORMAL,
10698 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10699 : FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10700 : SMB2_IMPERSONATION_IMPERSONATION, 0);
10701 :
10702 0 : if (tevent_req_nomem(subreq, req)) {
10703 0 : return tevent_req_post(req, ev);
10704 : }
10705 0 : tevent_req_set_callback(subreq, torture_createdel_created, req);
10706 0 : return req;
10707 : }
10708 :
10709 0 : static void torture_createdel_created(struct tevent_req *subreq)
10710 : {
10711 0 : struct tevent_req *req = tevent_req_callback_data(
10712 : subreq, struct tevent_req);
10713 0 : struct torture_createdel_state *state = tevent_req_data(
10714 : req, struct torture_createdel_state);
10715 0 : NTSTATUS status;
10716 0 : uint16_t fnum;
10717 :
10718 0 : status = cli_ntcreate_recv(subreq, &fnum, NULL);
10719 0 : TALLOC_FREE(subreq);
10720 0 : if (tevent_req_nterror(req, status)) {
10721 0 : DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10722 : nt_errstr(status)));
10723 0 : return;
10724 : }
10725 :
10726 0 : subreq = cli_close_send(state, state->ev, state->cli, fnum, 0);
10727 0 : if (tevent_req_nomem(subreq, req)) {
10728 0 : return;
10729 : }
10730 0 : tevent_req_set_callback(subreq, torture_createdel_closed, req);
10731 : }
10732 :
10733 0 : static void torture_createdel_closed(struct tevent_req *subreq)
10734 : {
10735 0 : struct tevent_req *req = tevent_req_callback_data(
10736 : subreq, struct tevent_req);
10737 0 : NTSTATUS status;
10738 :
10739 0 : status = cli_close_recv(subreq);
10740 0 : if (tevent_req_nterror(req, status)) {
10741 0 : DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10742 0 : return;
10743 : }
10744 0 : tevent_req_done(req);
10745 : }
10746 :
10747 0 : static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10748 : {
10749 0 : return tevent_req_simple_recv_ntstatus(req);
10750 : }
10751 :
10752 : struct torture_createdels_state {
10753 : struct tevent_context *ev;
10754 : struct cli_state *cli;
10755 : const char *base_name;
10756 : int sent;
10757 : int received;
10758 : int num_files;
10759 : struct tevent_req **reqs;
10760 : };
10761 :
10762 : static void torture_createdels_done(struct tevent_req *subreq);
10763 :
10764 0 : static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10765 : struct tevent_context *ev,
10766 : struct cli_state *cli,
10767 : const char *base_name,
10768 : int num_parallel,
10769 : int num_files)
10770 : {
10771 0 : struct tevent_req *req;
10772 0 : struct torture_createdels_state *state;
10773 0 : int i;
10774 :
10775 0 : req = tevent_req_create(mem_ctx, &state,
10776 : struct torture_createdels_state);
10777 0 : if (req == NULL) {
10778 0 : return NULL;
10779 : }
10780 0 : state->ev = ev;
10781 0 : state->cli = cli;
10782 0 : state->base_name = talloc_strdup(state, base_name);
10783 0 : if (tevent_req_nomem(state->base_name, req)) {
10784 0 : return tevent_req_post(req, ev);
10785 : }
10786 0 : state->num_files = MAX(num_parallel, num_files);
10787 0 : state->sent = 0;
10788 0 : state->received = 0;
10789 :
10790 0 : state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10791 0 : if (tevent_req_nomem(state->reqs, req)) {
10792 0 : return tevent_req_post(req, ev);
10793 : }
10794 :
10795 0 : for (i=0; i<num_parallel; i++) {
10796 0 : char *name;
10797 :
10798 0 : name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10799 0 : state->sent);
10800 0 : if (tevent_req_nomem(name, req)) {
10801 0 : return tevent_req_post(req, ev);
10802 : }
10803 0 : state->reqs[i] = torture_createdel_send(
10804 0 : state->reqs, state->ev, state->cli, name);
10805 0 : if (tevent_req_nomem(state->reqs[i], req)) {
10806 0 : return tevent_req_post(req, ev);
10807 : }
10808 0 : name = talloc_move(state->reqs[i], &name);
10809 0 : tevent_req_set_callback(state->reqs[i],
10810 : torture_createdels_done, req);
10811 0 : state->sent += 1;
10812 : }
10813 0 : return req;
10814 : }
10815 :
10816 0 : static void torture_createdels_done(struct tevent_req *subreq)
10817 : {
10818 0 : struct tevent_req *req = tevent_req_callback_data(
10819 : subreq, struct tevent_req);
10820 0 : struct torture_createdels_state *state = tevent_req_data(
10821 : req, struct torture_createdels_state);
10822 0 : size_t i, num_parallel = talloc_array_length(state->reqs);
10823 0 : NTSTATUS status;
10824 0 : char *name;
10825 :
10826 0 : status = torture_createdel_recv(subreq);
10827 0 : if (!NT_STATUS_IS_OK(status)){
10828 0 : DEBUG(10, ("torture_createdel_recv returned %s\n",
10829 : nt_errstr(status)));
10830 0 : TALLOC_FREE(subreq);
10831 0 : tevent_req_nterror(req, status);
10832 0 : return;
10833 : }
10834 :
10835 0 : for (i=0; i<num_parallel; i++) {
10836 0 : if (subreq == state->reqs[i]) {
10837 0 : break;
10838 : }
10839 : }
10840 0 : if (i == num_parallel) {
10841 0 : DEBUG(10, ("received something we did not send\n"));
10842 0 : tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10843 0 : return;
10844 : }
10845 0 : TALLOC_FREE(state->reqs[i]);
10846 :
10847 0 : if (state->sent >= state->num_files) {
10848 0 : tevent_req_done(req);
10849 0 : return;
10850 : }
10851 :
10852 0 : name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10853 : state->sent);
10854 0 : if (tevent_req_nomem(name, req)) {
10855 0 : return;
10856 : }
10857 0 : state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10858 : state->cli, name);
10859 0 : if (tevent_req_nomem(state->reqs[i], req)) {
10860 0 : return;
10861 : }
10862 0 : name = talloc_move(state->reqs[i], &name);
10863 0 : tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10864 0 : state->sent += 1;
10865 : }
10866 :
10867 0 : static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10868 : {
10869 0 : return tevent_req_simple_recv_ntstatus(req);
10870 : }
10871 :
10872 : struct swallow_notify_state {
10873 : struct tevent_context *ev;
10874 : struct cli_state *cli;
10875 : uint16_t fnum;
10876 : uint32_t completion_filter;
10877 : bool recursive;
10878 : bool (*fn)(uint32_t action, const char *name, void *priv);
10879 : void *priv;
10880 : };
10881 :
10882 : static void swallow_notify_done(struct tevent_req *subreq);
10883 :
10884 0 : static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10885 : struct tevent_context *ev,
10886 : struct cli_state *cli,
10887 : uint16_t fnum,
10888 : uint32_t completion_filter,
10889 : bool recursive,
10890 : bool (*fn)(uint32_t action,
10891 : const char *name,
10892 : void *priv),
10893 : void *priv)
10894 : {
10895 0 : struct tevent_req *req, *subreq;
10896 0 : struct swallow_notify_state *state;
10897 :
10898 0 : req = tevent_req_create(mem_ctx, &state,
10899 : struct swallow_notify_state);
10900 0 : if (req == NULL) {
10901 0 : return NULL;
10902 : }
10903 0 : state->ev = ev;
10904 0 : state->cli = cli;
10905 0 : state->fnum = fnum;
10906 0 : state->completion_filter = completion_filter;
10907 0 : state->recursive = recursive;
10908 0 : state->fn = fn;
10909 0 : state->priv = priv;
10910 :
10911 0 : subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10912 0 : 0xffff, state->completion_filter,
10913 0 : state->recursive);
10914 0 : if (tevent_req_nomem(subreq, req)) {
10915 0 : return tevent_req_post(req, ev);
10916 : }
10917 0 : tevent_req_set_callback(subreq, swallow_notify_done, req);
10918 0 : return req;
10919 : }
10920 :
10921 0 : static void swallow_notify_done(struct tevent_req *subreq)
10922 : {
10923 0 : struct tevent_req *req = tevent_req_callback_data(
10924 : subreq, struct tevent_req);
10925 0 : struct swallow_notify_state *state = tevent_req_data(
10926 : req, struct swallow_notify_state);
10927 0 : NTSTATUS status;
10928 0 : uint32_t i, num_changes;
10929 0 : struct notify_change *changes;
10930 :
10931 0 : status = cli_notify_recv(subreq, state, &num_changes, &changes);
10932 0 : TALLOC_FREE(subreq);
10933 0 : if (!NT_STATUS_IS_OK(status)) {
10934 0 : DEBUG(10, ("cli_notify_recv returned %s\n",
10935 : nt_errstr(status)));
10936 0 : tevent_req_nterror(req, status);
10937 0 : return;
10938 : }
10939 :
10940 0 : for (i=0; i<num_changes; i++) {
10941 0 : state->fn(changes[i].action, changes[i].name, state->priv);
10942 : }
10943 0 : TALLOC_FREE(changes);
10944 :
10945 0 : subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10946 : 0xffff, state->completion_filter,
10947 0 : state->recursive);
10948 0 : if (tevent_req_nomem(subreq, req)) {
10949 0 : return;
10950 : }
10951 0 : tevent_req_set_callback(subreq, swallow_notify_done, req);
10952 : }
10953 :
10954 0 : static bool print_notifies(uint32_t action, const char *name, void *priv)
10955 : {
10956 0 : if (DEBUGLEVEL > 5) {
10957 0 : d_printf("%d %s\n", (int)action, name);
10958 : }
10959 0 : return true;
10960 : }
10961 :
10962 0 : static void notify_bench_done(struct tevent_req *req)
10963 : {
10964 0 : int *num_finished = (int *)tevent_req_callback_data_void(req);
10965 0 : *num_finished += 1;
10966 0 : }
10967 :
10968 0 : static bool run_notify_bench(int dummy)
10969 : {
10970 0 : const char *dname = "\\notify-bench";
10971 0 : struct tevent_context *ev;
10972 0 : NTSTATUS status;
10973 0 : uint16_t dnum;
10974 0 : struct tevent_req *req1;
10975 0 : struct tevent_req *req2 = NULL;
10976 0 : int i, num_unc_names;
10977 0 : int num_finished = 0;
10978 :
10979 0 : printf("starting notify-bench test\n");
10980 :
10981 0 : if (use_multishare_conn) {
10982 0 : char **unc_list;
10983 0 : unc_list = file_lines_load(multishare_conn_fname,
10984 : &num_unc_names, 0, NULL);
10985 0 : if (!unc_list || num_unc_names <= 0) {
10986 0 : d_printf("Failed to load unc names list from '%s'\n",
10987 : multishare_conn_fname);
10988 0 : return false;
10989 : }
10990 0 : TALLOC_FREE(unc_list);
10991 : } else {
10992 0 : num_unc_names = 1;
10993 : }
10994 :
10995 0 : ev = samba_tevent_context_init(talloc_tos());
10996 0 : if (ev == NULL) {
10997 0 : d_printf("tevent_context_init failed\n");
10998 0 : return false;
10999 : }
11000 :
11001 0 : for (i=0; i<num_unc_names; i++) {
11002 0 : struct cli_state *cli;
11003 0 : char *base_fname;
11004 :
11005 0 : base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
11006 : dname, i);
11007 0 : if (base_fname == NULL) {
11008 0 : return false;
11009 : }
11010 :
11011 0 : if (!torture_open_connection(&cli, i)) {
11012 0 : return false;
11013 : }
11014 :
11015 0 : status = cli_ntcreate(cli, dname, 0,
11016 : MAXIMUM_ALLOWED_ACCESS,
11017 : 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
11018 : FILE_SHARE_DELETE,
11019 : FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
11020 : &dnum, NULL);
11021 :
11022 0 : if (!NT_STATUS_IS_OK(status)) {
11023 0 : d_printf("Could not create %s: %s\n", dname,
11024 : nt_errstr(status));
11025 0 : return false;
11026 : }
11027 :
11028 0 : req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
11029 : FILE_NOTIFY_CHANGE_FILE_NAME |
11030 : FILE_NOTIFY_CHANGE_DIR_NAME |
11031 : FILE_NOTIFY_CHANGE_ATTRIBUTES |
11032 : FILE_NOTIFY_CHANGE_LAST_WRITE,
11033 : false, print_notifies, NULL);
11034 0 : if (req1 == NULL) {
11035 0 : d_printf("Could not create notify request\n");
11036 0 : return false;
11037 : }
11038 :
11039 0 : req2 = torture_createdels_send(talloc_tos(), ev, cli,
11040 : base_fname, 10, torture_numops);
11041 0 : if (req2 == NULL) {
11042 0 : d_printf("Could not create createdels request\n");
11043 0 : return false;
11044 : }
11045 0 : TALLOC_FREE(base_fname);
11046 :
11047 0 : tevent_req_set_callback(req2, notify_bench_done,
11048 : &num_finished);
11049 : }
11050 :
11051 0 : while (num_finished < num_unc_names) {
11052 0 : int ret;
11053 0 : ret = tevent_loop_once(ev);
11054 0 : if (ret != 0) {
11055 0 : d_printf("tevent_loop_once failed\n");
11056 0 : return false;
11057 : }
11058 : }
11059 :
11060 0 : if (!tevent_req_poll(req2, ev)) {
11061 0 : d_printf("tevent_req_poll failed\n");
11062 : }
11063 :
11064 0 : status = torture_createdels_recv(req2);
11065 0 : d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
11066 :
11067 0 : return true;
11068 : }
11069 :
11070 0 : static bool run_mangle1(int dummy)
11071 : {
11072 0 : struct cli_state *cli;
11073 0 : const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
11074 0 : uint16_t fnum;
11075 0 : fstring alt_name;
11076 0 : NTSTATUS status;
11077 :
11078 0 : printf("starting mangle1 test\n");
11079 0 : if (!torture_open_connection(&cli, 0)) {
11080 0 : return False;
11081 : }
11082 :
11083 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11084 :
11085 0 : status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11086 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11087 : 0, 0, &fnum, NULL);
11088 0 : if (!NT_STATUS_IS_OK(status)) {
11089 0 : d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11090 0 : return false;
11091 : }
11092 0 : cli_close(cli, fnum);
11093 :
11094 0 : status = cli_qpathinfo_alt_name(cli, fname, alt_name);
11095 0 : if (!NT_STATUS_IS_OK(status)) {
11096 0 : d_printf("cli_qpathinfo_alt_name failed: %s\n",
11097 : nt_errstr(status));
11098 0 : return false;
11099 : }
11100 0 : d_printf("alt_name: %s\n", alt_name);
11101 :
11102 0 : status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
11103 0 : if (!NT_STATUS_IS_OK(status)) {
11104 0 : d_printf("cli_openx(%s) failed: %s\n", alt_name,
11105 : nt_errstr(status));
11106 0 : return false;
11107 : }
11108 0 : cli_close(cli, fnum);
11109 :
11110 0 : status = cli_qpathinfo1(cli, alt_name, NULL, NULL, NULL, NULL, NULL);
11111 0 : if (!NT_STATUS_IS_OK(status)) {
11112 0 : d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
11113 : nt_errstr(status));
11114 0 : return false;
11115 : }
11116 :
11117 0 : return true;
11118 : }
11119 :
11120 2 : static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
11121 : const char *mask,
11122 : void *state)
11123 : {
11124 2 : if (f->short_name == NULL) {
11125 2 : return NT_STATUS_OK;
11126 : }
11127 :
11128 0 : if (strlen(f->short_name) == 0) {
11129 0 : return NT_STATUS_OK;
11130 : }
11131 :
11132 0 : printf("unexpected shortname: %s\n", f->short_name);
11133 :
11134 0 : return NT_STATUS_OBJECT_NAME_INVALID;
11135 : }
11136 :
11137 2 : static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11138 : const char *mask,
11139 : void *state)
11140 : {
11141 2 : char *name = state;
11142 :
11143 2 : printf("name: %s\n", f->name);
11144 2 : fstrcpy(name, f->name);
11145 2 : return NT_STATUS_OK;
11146 : }
11147 :
11148 2 : static bool run_mangle_illegal(int dummy)
11149 : {
11150 2 : struct cli_state *cli = NULL;
11151 2 : struct cli_state *cli_posix = NULL;
11152 2 : const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11153 2 : const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11154 2 : char *mangled_path = NULL;
11155 0 : uint16_t fnum;
11156 0 : fstring name;
11157 0 : fstring alt_name;
11158 0 : NTSTATUS status;
11159 :
11160 2 : printf("starting mangle-illegal test\n");
11161 :
11162 2 : if (!torture_open_connection(&cli, 0)) {
11163 0 : return False;
11164 : }
11165 :
11166 2 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11167 :
11168 2 : if (!torture_open_connection(&cli_posix, 0)) {
11169 0 : return false;
11170 : }
11171 :
11172 2 : smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11173 :
11174 2 : status = torture_setup_unix_extensions(cli_posix);
11175 2 : if (!NT_STATUS_IS_OK(status)) {
11176 0 : return false;
11177 : }
11178 :
11179 2 : cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11180 2 : status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11181 2 : if (!NT_STATUS_IS_OK(status)) {
11182 0 : printf("mkdir1 failed : %s\n", nt_errstr(status));
11183 0 : return False;
11184 : }
11185 :
11186 : /*
11187 : * Create a file with illegal NTFS characters and test that we
11188 : * get a usable mangled name
11189 : */
11190 :
11191 2 : cli_setatr(cli_posix, illegal_fname, 0, 0);
11192 2 : cli_posix_unlink(cli_posix, illegal_fname);
11193 :
11194 2 : status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11195 : 0600, &fnum);
11196 2 : if (!NT_STATUS_IS_OK(status)) {
11197 0 : printf("POSIX create of %s failed (%s)\n",
11198 : illegal_fname, nt_errstr(status));
11199 0 : return false;
11200 : }
11201 :
11202 2 : status = cli_close(cli_posix, fnum);
11203 2 : if (!NT_STATUS_IS_OK(status)) {
11204 0 : printf("close failed (%s)\n", nt_errstr(status));
11205 0 : return false;
11206 : }
11207 :
11208 2 : status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11209 2 : if (!NT_STATUS_IS_OK(status)) {
11210 0 : d_printf("cli_list failed: %s\n", nt_errstr(status));
11211 0 : return false;
11212 : }
11213 :
11214 2 : mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11215 2 : if (mangled_path == NULL) {
11216 0 : return false;
11217 : }
11218 :
11219 2 : status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11220 2 : if (!NT_STATUS_IS_OK(status)) {
11221 0 : d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11222 0 : TALLOC_FREE(mangled_path);
11223 0 : return false;
11224 : }
11225 2 : TALLOC_FREE(mangled_path);
11226 2 : cli_close(cli, fnum);
11227 :
11228 2 : cli_setatr(cli_posix, illegal_fname, 0, 0);
11229 2 : cli_posix_unlink(cli_posix, illegal_fname);
11230 :
11231 : /*
11232 : * Create a file with a long name and check that we got *no* short name.
11233 : */
11234 :
11235 2 : status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11236 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11237 : 0, 0, &fnum, NULL);
11238 2 : if (!NT_STATUS_IS_OK(status)) {
11239 0 : d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11240 0 : return false;
11241 : }
11242 2 : cli_close(cli, fnum);
11243 :
11244 2 : status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11245 2 : if (!NT_STATUS_IS_OK(status)) {
11246 0 : d_printf("cli_list failed\n");
11247 0 : return false;
11248 : }
11249 :
11250 2 : cli_unlink(cli, fname, 0);
11251 2 : cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11252 :
11253 2 : if (!torture_close_connection(cli_posix)) {
11254 0 : return false;
11255 : }
11256 :
11257 2 : if (!torture_close_connection(cli)) {
11258 0 : return false;
11259 : }
11260 :
11261 2 : return true;
11262 : }
11263 :
11264 0 : static size_t null_source(uint8_t *buf, size_t n, void *priv)
11265 : {
11266 0 : size_t *to_pull = (size_t *)priv;
11267 0 : size_t thistime = *to_pull;
11268 :
11269 0 : thistime = MIN(thistime, n);
11270 0 : if (thistime == 0) {
11271 0 : return 0;
11272 : }
11273 :
11274 0 : memset(buf, 0, thistime);
11275 0 : *to_pull -= thistime;
11276 0 : return thistime;
11277 : }
11278 :
11279 0 : static bool run_windows_write(int dummy)
11280 : {
11281 0 : struct cli_state *cli1;
11282 0 : uint16_t fnum;
11283 0 : int i;
11284 0 : bool ret = false;
11285 0 : const char *fname = "\\writetest.txt";
11286 0 : struct timeval start_time;
11287 0 : double seconds;
11288 0 : double kbytes;
11289 0 : NTSTATUS status;
11290 :
11291 0 : printf("starting windows_write test\n");
11292 0 : if (!torture_open_connection(&cli1, 0)) {
11293 0 : return False;
11294 : }
11295 :
11296 0 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11297 0 : if (!NT_STATUS_IS_OK(status)) {
11298 0 : printf("open failed (%s)\n", nt_errstr(status));
11299 0 : return False;
11300 : }
11301 :
11302 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
11303 :
11304 0 : start_time = timeval_current();
11305 :
11306 0 : for (i=0; i<torture_numops; i++) {
11307 0 : uint8_t c = 0;
11308 0 : off_t start = i * torture_blocksize;
11309 0 : size_t to_pull = torture_blocksize - 1;
11310 :
11311 0 : status = cli_writeall(cli1, fnum, 0, &c,
11312 0 : start + torture_blocksize - 1, 1, NULL);
11313 0 : if (!NT_STATUS_IS_OK(status)) {
11314 0 : printf("cli_write failed: %s\n", nt_errstr(status));
11315 0 : goto fail;
11316 : }
11317 :
11318 0 : status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11319 : null_source, &to_pull);
11320 0 : if (!NT_STATUS_IS_OK(status)) {
11321 0 : printf("cli_push returned: %s\n", nt_errstr(status));
11322 0 : goto fail;
11323 : }
11324 : }
11325 :
11326 0 : seconds = timeval_elapsed(&start_time);
11327 0 : kbytes = (double)torture_blocksize * torture_numops;
11328 0 : kbytes /= 1024;
11329 :
11330 0 : printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11331 0 : (double)seconds, (int)(kbytes/seconds));
11332 :
11333 0 : ret = true;
11334 0 : fail:
11335 0 : cli_close(cli1, fnum);
11336 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11337 0 : torture_close_connection(cli1);
11338 0 : return ret;
11339 : }
11340 :
11341 64 : static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11342 : {
11343 64 : size_t max_pdu = 0x1FFFF;
11344 :
11345 64 : if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11346 32 : max_pdu = 0xFFFFFF;
11347 : }
11348 :
11349 64 : if (smb1cli_conn_signing_is_active(cli->conn)) {
11350 32 : max_pdu = 0x1FFFF;
11351 : }
11352 :
11353 64 : if (smb1cli_conn_encryption_on(cli->conn)) {
11354 16 : max_pdu = CLI_BUFFER_SIZE;
11355 : }
11356 :
11357 64 : if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11358 8 : len_requested &= 0xFFFF;
11359 : }
11360 :
11361 64 : return MIN(len_requested,
11362 : max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11363 : }
11364 :
11365 64 : static bool check_read_call(struct cli_state *cli,
11366 : uint16_t fnum,
11367 : uint8_t *buf,
11368 : size_t len_requested)
11369 : {
11370 0 : NTSTATUS status;
11371 64 : struct tevent_req *subreq = NULL;
11372 64 : ssize_t len_read = 0;
11373 64 : size_t len_expected = 0;
11374 64 : struct tevent_context *ev = NULL;
11375 :
11376 64 : ev = samba_tevent_context_init(talloc_tos());
11377 64 : if (ev == NULL) {
11378 0 : return false;
11379 : }
11380 :
11381 64 : subreq = cli_read_andx_send(talloc_tos(),
11382 : ev,
11383 : cli,
11384 : fnum,
11385 : 0,
11386 : len_requested);
11387 :
11388 64 : if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11389 0 : return false;
11390 : }
11391 :
11392 64 : status = cli_read_andx_recv(subreq, &len_read, &buf);
11393 64 : if (!NT_STATUS_IS_OK(status)) {
11394 0 : d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11395 0 : return false;
11396 : }
11397 :
11398 64 : TALLOC_FREE(subreq);
11399 64 : TALLOC_FREE(ev);
11400 :
11401 64 : len_expected = calc_expected_return(cli, len_requested);
11402 :
11403 64 : if (len_expected > 0x10000 && len_read == 0x10000) {
11404 : /* Windows servers only return a max of 0x10000,
11405 : doesn't matter if you set CAP_LARGE_READX in
11406 : the client sessionsetupX call or not. */
11407 12 : d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11408 : (unsigned int)len_requested);
11409 52 : } else if (len_read != len_expected) {
11410 0 : d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11411 : (unsigned int)len_requested,
11412 : (unsigned int)len_read,
11413 : (unsigned int)len_expected);
11414 0 : return false;
11415 : } else {
11416 52 : d_printf("Correct read reply.\n");
11417 : }
11418 :
11419 64 : return true;
11420 : }
11421 :
11422 : /* Test large readX variants. */
11423 8 : static bool large_readx_tests(struct cli_state *cli,
11424 : uint16_t fnum,
11425 : uint8_t *buf)
11426 : {
11427 : /* A read of 0xFFFF0001 should *always* return 1 byte. */
11428 8 : if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11429 0 : return false;
11430 : }
11431 : /* A read of 0x10000 should return 0x10000 bytes. */
11432 8 : if (check_read_call(cli, fnum, buf, 0x10000) == false) {
11433 0 : return false;
11434 : }
11435 : /* A read of 0x10000 should return 0x10001 bytes. */
11436 8 : if (check_read_call(cli, fnum, buf, 0x10001) == false) {
11437 0 : return false;
11438 : }
11439 : /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11440 : the requested number of bytes. */
11441 8 : if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11442 0 : return false;
11443 : }
11444 : /* A read of 1MB should return 1MB bytes (on Samba). */
11445 8 : if (check_read_call(cli, fnum, buf, 0x100000) == false) {
11446 0 : return false;
11447 : }
11448 :
11449 8 : if (check_read_call(cli, fnum, buf, 0x20001) == false) {
11450 0 : return false;
11451 : }
11452 8 : if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11453 0 : return false;
11454 : }
11455 8 : if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11456 0 : return false;
11457 : }
11458 8 : return true;
11459 : }
11460 :
11461 5 : static bool run_large_readx(int dummy)
11462 : {
11463 5 : uint8_t *buf = NULL;
11464 5 : struct cli_state *cli1 = NULL;
11465 5 : struct cli_state *cli2 = NULL;
11466 5 : bool correct = false;
11467 5 : const char *fname = "\\large_readx.dat";
11468 0 : NTSTATUS status;
11469 5 : uint16_t fnum1 = UINT16_MAX;
11470 5 : uint32_t normal_caps = 0;
11471 5 : size_t file_size = 20*1024*1024;
11472 5 : TALLOC_CTX *frame = talloc_stackframe();
11473 0 : size_t i;
11474 0 : struct {
11475 : const char *name;
11476 : enum smb_signing_setting signing_setting;
11477 : enum protocol_types protocol;
11478 5 : } runs[] = {
11479 : {
11480 : .name = "NT1",
11481 : .signing_setting = SMB_SIGNING_IF_REQUIRED,
11482 : .protocol = PROTOCOL_NT1,
11483 : },{
11484 : .name = "NT1 - SIGNING_REQUIRED",
11485 : .signing_setting = SMB_SIGNING_REQUIRED,
11486 : .protocol = PROTOCOL_NT1,
11487 : },
11488 : };
11489 :
11490 5 : printf("starting large_readx test\n");
11491 :
11492 5 : if (!torture_open_connection(&cli1, 0)) {
11493 0 : goto out;
11494 : }
11495 :
11496 5 : normal_caps = smb1cli_conn_capabilities(cli1->conn);
11497 :
11498 5 : if (!(normal_caps & CAP_LARGE_READX)) {
11499 0 : d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11500 : (unsigned int)normal_caps);
11501 0 : goto out;
11502 : }
11503 :
11504 : /* Create a file of size 4MB. */
11505 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11506 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11507 : 0, 0, &fnum1, NULL);
11508 :
11509 5 : if (!NT_STATUS_IS_OK(status)) {
11510 0 : d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11511 0 : goto out;
11512 : }
11513 :
11514 : /* Write file_size bytes. */
11515 5 : buf = talloc_zero_array(frame, uint8_t, file_size);
11516 5 : if (buf == NULL) {
11517 0 : goto out;
11518 : }
11519 :
11520 5 : status = cli_writeall(cli1,
11521 : fnum1,
11522 : 0,
11523 : buf,
11524 : 0,
11525 : file_size,
11526 : NULL);
11527 5 : if (!NT_STATUS_IS_OK(status)) {
11528 0 : d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11529 0 : goto out;
11530 : }
11531 :
11532 5 : status = cli_close(cli1, fnum1);
11533 5 : if (!NT_STATUS_IS_OK(status)) {
11534 0 : d_printf("cli_close failed: %s\n", nt_errstr(status));
11535 0 : goto out;
11536 : }
11537 :
11538 5 : fnum1 = UINT16_MAX;
11539 :
11540 15 : for (i=0; i < ARRAY_SIZE(runs); i++) {
11541 10 : enum smb_signing_setting saved_signing_setting = signing_state;
11542 10 : uint16_t fnum2 = -1;
11543 :
11544 10 : if (do_encrypt &&
11545 4 : (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11546 : {
11547 2 : d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11548 2 : continue;
11549 : }
11550 :
11551 8 : d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11552 :
11553 8 : signing_state = runs[i].signing_setting;
11554 8 : cli2 = open_nbt_connection();
11555 8 : signing_state = saved_signing_setting;
11556 8 : if (cli2 == NULL) {
11557 0 : goto out;
11558 : }
11559 :
11560 8 : status = smbXcli_negprot(cli2->conn,
11561 8 : cli2->timeout,
11562 : runs[i].protocol,
11563 : runs[i].protocol,
11564 : NULL,
11565 : NULL,
11566 : NULL);
11567 8 : if (!NT_STATUS_IS_OK(status)) {
11568 0 : goto out;
11569 : }
11570 :
11571 8 : status = cli_session_setup_creds(cli2, torture_creds);
11572 8 : if (!NT_STATUS_IS_OK(status)) {
11573 0 : goto out;
11574 : }
11575 :
11576 8 : status = cli_tree_connect(cli2,
11577 : share,
11578 : "?????",
11579 : password);
11580 8 : if (!NT_STATUS_IS_OK(status)) {
11581 0 : goto out;
11582 : }
11583 :
11584 8 : cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11585 :
11586 8 : normal_caps = smb1cli_conn_capabilities(cli2->conn);
11587 :
11588 8 : if (!(normal_caps & CAP_LARGE_READX)) {
11589 0 : d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11590 : (unsigned int)normal_caps);
11591 0 : goto out;
11592 : }
11593 :
11594 8 : if (do_encrypt) {
11595 2 : if (force_cli_encryption(cli2, share) == false) {
11596 0 : goto out;
11597 : }
11598 6 : } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11599 0 : uint16_t major, minor;
11600 0 : uint32_t caplow, caphigh;
11601 :
11602 4 : status = cli_unix_extensions_version(cli2,
11603 : &major, &minor,
11604 : &caplow, &caphigh);
11605 4 : if (!NT_STATUS_IS_OK(status)) {
11606 0 : goto out;
11607 : }
11608 : }
11609 :
11610 8 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11611 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11612 : 0, 0, &fnum2, NULL);
11613 8 : if (!NT_STATUS_IS_OK(status)) {
11614 0 : d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11615 0 : goto out;
11616 : }
11617 :
11618 : /* All reads must return less than file_size bytes. */
11619 8 : if (!large_readx_tests(cli2, fnum2, buf)) {
11620 0 : goto out;
11621 : }
11622 :
11623 8 : status = cli_close(cli2, fnum2);
11624 8 : if (!NT_STATUS_IS_OK(status)) {
11625 0 : d_printf("cli_close failed: %s\n", nt_errstr(status));
11626 0 : goto out;
11627 : }
11628 8 : fnum2 = -1;
11629 :
11630 8 : if (!torture_close_connection(cli2)) {
11631 0 : goto out;
11632 : }
11633 8 : cli2 = NULL;
11634 : }
11635 :
11636 5 : correct = true;
11637 5 : printf("Success on large_readx test\n");
11638 :
11639 5 : out:
11640 :
11641 5 : if (cli2) {
11642 0 : if (!torture_close_connection(cli2)) {
11643 0 : correct = false;
11644 : }
11645 : }
11646 :
11647 5 : if (cli1) {
11648 5 : if (fnum1 != UINT16_MAX) {
11649 0 : status = cli_close(cli1, fnum1);
11650 0 : if (!NT_STATUS_IS_OK(status)) {
11651 0 : d_printf("cli_close failed: %s\n", nt_errstr(status));
11652 : }
11653 0 : fnum1 = UINT16_MAX;
11654 : }
11655 :
11656 5 : status = cli_unlink(cli1, fname,
11657 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11658 5 : if (!NT_STATUS_IS_OK(status)) {
11659 0 : printf("unlink failed (%s)\n", nt_errstr(status));
11660 : }
11661 :
11662 5 : if (!torture_close_connection(cli1)) {
11663 0 : correct = false;
11664 : }
11665 : }
11666 :
11667 5 : TALLOC_FREE(frame);
11668 :
11669 5 : printf("finished large_readx test\n");
11670 5 : return correct;
11671 : }
11672 :
11673 24 : static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11674 : const char *mask,
11675 : void *private_data)
11676 : {
11677 24 : uint32_t *p_attr = (uint32_t *)private_data;
11678 :
11679 24 : if (strequal(finfo->name, test_filename)) {
11680 4 : *p_attr = finfo->attr;
11681 : }
11682 :
11683 24 : return NT_STATUS_OK;
11684 : }
11685 :
11686 4 : static bool run_msdfs_attribute(int dummy)
11687 : {
11688 0 : static struct cli_state *cli;
11689 4 : bool correct = false;
11690 4 : uint32_t attr = 0;
11691 0 : NTSTATUS status;
11692 :
11693 4 : printf("Starting MSDFS-ATTRIBUTE test\n");
11694 :
11695 4 : if (test_filename == NULL || test_filename[0] == '\0') {
11696 0 : printf("MSDFS-ATTRIBUTE test "
11697 : "needs -f filename-of-msdfs-link\n");
11698 0 : return false;
11699 : }
11700 :
11701 : /*
11702 : * NB. We use torture_open_connection_flags() not
11703 : * torture_open_connection() as the latter forces
11704 : * SMB1.
11705 : */
11706 4 : if (!torture_open_connection_flags(&cli, 0, 0)) {
11707 0 : return false;
11708 : }
11709 :
11710 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11711 :
11712 4 : status = cli_list(cli,
11713 : "*",
11714 : FILE_ATTRIBUTE_DIRECTORY,
11715 : msdfs_attribute_list_fn,
11716 : &attr);
11717 :
11718 4 : if (!NT_STATUS_IS_OK(status)) {
11719 0 : printf("cli_list failed with %s\n",
11720 : nt_errstr(status));
11721 0 : goto out;
11722 : }
11723 4 : if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11724 0 : printf("file %s should have "
11725 : "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11726 : test_filename,
11727 : (unsigned int)attr);
11728 0 : goto out;
11729 : }
11730 :
11731 4 : if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11732 0 : printf("file %s should have "
11733 : "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11734 : test_filename,
11735 : (unsigned int)attr);
11736 0 : goto out;
11737 : }
11738 :
11739 4 : correct = true;
11740 :
11741 4 : out:
11742 :
11743 4 : torture_close_connection(cli);
11744 4 : return correct;
11745 : }
11746 :
11747 0 : static bool run_cli_echo(int dummy)
11748 : {
11749 0 : struct cli_state *cli;
11750 0 : NTSTATUS status;
11751 :
11752 0 : printf("starting cli_echo test\n");
11753 0 : if (!torture_open_connection(&cli, 0)) {
11754 0 : return false;
11755 : }
11756 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11757 :
11758 0 : status = cli_echo(cli, 5, data_blob_const("hello", 5));
11759 :
11760 0 : d_printf("cli_echo returned %s\n", nt_errstr(status));
11761 :
11762 0 : torture_close_connection(cli);
11763 0 : return NT_STATUS_IS_OK(status);
11764 : }
11765 :
11766 14 : static int splice_status(off_t written, void *priv)
11767 : {
11768 14 : return true;
11769 : }
11770 :
11771 7 : static bool run_cli_splice(int dummy)
11772 : {
11773 7 : uint8_t *buf = NULL;
11774 7 : struct cli_state *cli1 = NULL;
11775 7 : bool correct = false;
11776 7 : const char *fname_src = "\\splice_src.dat";
11777 7 : const char *fname_dst = "\\splice_dst.dat";
11778 0 : NTSTATUS status;
11779 7 : uint16_t fnum1 = UINT16_MAX;
11780 7 : uint16_t fnum2 = UINT16_MAX;
11781 7 : size_t file_size = 2*1024*1024;
11782 7 : size_t splice_size = 1*1024*1024 + 713;
11783 0 : uint8_t digest1[16], digest2[16];
11784 7 : off_t written = 0;
11785 7 : size_t nread = 0;
11786 7 : TALLOC_CTX *frame = talloc_stackframe();
11787 :
11788 7 : printf("starting cli_splice test\n");
11789 :
11790 7 : if (!torture_open_connection(&cli1, 0)) {
11791 0 : goto out;
11792 : }
11793 :
11794 7 : cli_unlink(cli1, fname_src,
11795 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11796 7 : cli_unlink(cli1, fname_dst,
11797 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11798 :
11799 : /* Create a file */
11800 7 : status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11801 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11802 : 0, 0, &fnum1, NULL);
11803 :
11804 7 : if (!NT_STATUS_IS_OK(status)) {
11805 0 : d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11806 0 : goto out;
11807 : }
11808 :
11809 : /* Write file_size bytes - must be bigger than splice_size. */
11810 7 : buf = talloc_zero_array(frame, uint8_t, file_size);
11811 7 : if (buf == NULL) {
11812 0 : d_printf("talloc_fail\n");
11813 0 : goto out;
11814 : }
11815 :
11816 : /* Fill it with random numbers. */
11817 7 : generate_random_buffer(buf, file_size);
11818 :
11819 : /* MD5 the first 1MB + 713 bytes. */
11820 7 : gnutls_hash_fast(GNUTLS_DIG_MD5,
11821 : buf,
11822 : splice_size,
11823 : digest1);
11824 :
11825 7 : status = cli_writeall(cli1,
11826 : fnum1,
11827 : 0,
11828 : buf,
11829 : 0,
11830 : file_size,
11831 : NULL);
11832 7 : if (!NT_STATUS_IS_OK(status)) {
11833 0 : d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11834 0 : goto out;
11835 : }
11836 :
11837 7 : status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11838 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11839 : 0, 0, &fnum2, NULL);
11840 :
11841 7 : if (!NT_STATUS_IS_OK(status)) {
11842 0 : d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11843 0 : goto out;
11844 : }
11845 :
11846 : /* Now splice 1MB + 713 bytes. */
11847 7 : status = cli_splice(cli1,
11848 : cli1,
11849 : fnum1,
11850 : fnum2,
11851 : splice_size,
11852 : 0,
11853 : 0,
11854 : &written,
11855 : splice_status,
11856 : NULL);
11857 :
11858 7 : if (!NT_STATUS_IS_OK(status)) {
11859 0 : d_printf("cli_splice failed: %s\n", nt_errstr(status));
11860 0 : goto out;
11861 : }
11862 :
11863 : /* Clear the old buffer. */
11864 7 : memset(buf, '\0', file_size);
11865 :
11866 : /* Read the new file. */
11867 7 : status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11868 7 : if (!NT_STATUS_IS_OK(status)) {
11869 0 : d_printf("cli_read failed: %s\n", nt_errstr(status));
11870 0 : goto out;
11871 : }
11872 7 : if (nread != splice_size) {
11873 0 : d_printf("bad read of 0x%x, should be 0x%x\n",
11874 : (unsigned int)nread,
11875 : (unsigned int)splice_size);
11876 0 : goto out;
11877 : }
11878 :
11879 : /* MD5 the first 1MB + 713 bytes. */
11880 7 : gnutls_hash_fast(GNUTLS_DIG_MD5,
11881 : buf,
11882 : splice_size,
11883 : digest2);
11884 :
11885 : /* Must be the same. */
11886 7 : if (memcmp(digest1, digest2, 16) != 0) {
11887 0 : d_printf("bad MD5 compare\n");
11888 0 : goto out;
11889 : }
11890 :
11891 7 : correct = true;
11892 7 : printf("Success on cli_splice test\n");
11893 :
11894 7 : out:
11895 :
11896 7 : if (cli1) {
11897 7 : if (fnum1 != UINT16_MAX) {
11898 7 : cli_close(cli1, fnum1);
11899 : }
11900 7 : if (fnum2 != UINT16_MAX) {
11901 7 : cli_close(cli1, fnum2);
11902 : }
11903 :
11904 7 : cli_unlink(cli1, fname_src,
11905 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11906 7 : cli_unlink(cli1, fname_dst,
11907 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11908 :
11909 7 : if (!torture_close_connection(cli1)) {
11910 0 : correct = false;
11911 : }
11912 : }
11913 :
11914 7 : TALLOC_FREE(frame);
11915 7 : return correct;
11916 : }
11917 :
11918 4 : static bool run_uid_regression_test(int dummy)
11919 : {
11920 0 : static struct cli_state *cli;
11921 0 : int16_t old_vuid;
11922 0 : int32_t old_cnum;
11923 4 : bool correct = True;
11924 4 : struct smbXcli_tcon *tcon_copy = NULL;
11925 0 : NTSTATUS status;
11926 :
11927 4 : printf("starting uid regression test\n");
11928 :
11929 4 : if (!torture_open_connection(&cli, 0)) {
11930 0 : return False;
11931 : }
11932 :
11933 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11934 :
11935 : /* Ok - now save then logoff our current user. */
11936 4 : old_vuid = cli_state_get_uid(cli);
11937 :
11938 4 : status = cli_ulogoff(cli);
11939 4 : if (!NT_STATUS_IS_OK(status)) {
11940 0 : d_printf("(%s) cli_ulogoff failed: %s\n",
11941 : __location__, nt_errstr(status));
11942 0 : correct = false;
11943 0 : goto out;
11944 : }
11945 :
11946 4 : cli_state_set_uid(cli, old_vuid);
11947 :
11948 : /* Try an operation. */
11949 4 : status = cli_mkdir(cli, "\\uid_reg_test");
11950 4 : if (NT_STATUS_IS_OK(status)) {
11951 0 : d_printf("(%s) cli_mkdir succeeded\n",
11952 : __location__);
11953 0 : correct = false;
11954 0 : goto out;
11955 : } else {
11956 : /* Should be bad uid. */
11957 4 : if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11958 4 : NT_STATUS_USER_SESSION_DELETED)) {
11959 0 : correct = false;
11960 0 : goto out;
11961 : }
11962 : }
11963 :
11964 4 : old_cnum = cli_state_get_tid(cli);
11965 : /*
11966 : * This is an SMB1-only test.
11967 : * Copy the tcon, not "save/restore".
11968 : *
11969 : * In SMB1 the cli_tdis() below frees
11970 : * cli->smb1.tcon so we need a copy
11971 : * of the struct to put back for the
11972 : * second tdis call with invalid vuid.
11973 : *
11974 : * This is a test-only hack. Real client code
11975 : * uses cli_state_save_tcon_share()/cli_state_restore_tcon_share().
11976 : */
11977 4 : tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
11978 4 : if (tcon_copy == NULL) {
11979 0 : correct = false;
11980 0 : goto out;
11981 : }
11982 :
11983 : /* Now try a SMBtdis with the invalid vuid set to zero. */
11984 4 : cli_state_set_uid(cli, 0);
11985 :
11986 : /* This should succeed. */
11987 4 : status = cli_tdis(cli);
11988 :
11989 4 : if (NT_STATUS_IS_OK(status)) {
11990 4 : d_printf("First tdis with invalid vuid should succeed.\n");
11991 : } else {
11992 0 : d_printf("First tdis failed (%s)\n", nt_errstr(status));
11993 0 : correct = false;
11994 0 : cli->smb1.tcon = tcon_copy;
11995 0 : goto out;
11996 : }
11997 :
11998 4 : cli->smb1.tcon = tcon_copy;
11999 4 : cli_state_set_uid(cli, old_vuid);
12000 4 : cli_state_set_tid(cli, old_cnum);
12001 :
12002 : /* This should fail. */
12003 4 : status = cli_tdis(cli);
12004 4 : if (NT_STATUS_IS_OK(status)) {
12005 0 : d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
12006 0 : correct = false;
12007 0 : goto out;
12008 : } else {
12009 : /* Should be bad tid. */
12010 4 : if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
12011 4 : NT_STATUS_NETWORK_NAME_DELETED)) {
12012 0 : correct = false;
12013 0 : goto out;
12014 : }
12015 : }
12016 :
12017 4 : cli_rmdir(cli, "\\uid_reg_test");
12018 :
12019 4 : out:
12020 :
12021 4 : cli_shutdown(cli);
12022 4 : return correct;
12023 : }
12024 :
12025 :
12026 : static const char *illegal_chars = "*\\/?<>|\":";
12027 : static char force_shortname_chars[] = " +,.[];=\177";
12028 :
12029 8 : static NTSTATUS shortname_del_fn(struct file_info *finfo,
12030 : const char *mask, void *state)
12031 : {
12032 8 : struct cli_state *pcli = (struct cli_state *)state;
12033 0 : fstring fname;
12034 8 : NTSTATUS status = NT_STATUS_OK;
12035 :
12036 8 : slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
12037 :
12038 8 : if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
12039 8 : return NT_STATUS_OK;
12040 :
12041 0 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
12042 0 : status = cli_rmdir(pcli, fname);
12043 0 : if (!NT_STATUS_IS_OK(status)) {
12044 0 : printf("del_fn: failed to rmdir %s\n,", fname );
12045 : }
12046 : } else {
12047 0 : status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12048 0 : if (!NT_STATUS_IS_OK(status)) {
12049 0 : printf("del_fn: failed to unlink %s\n,", fname );
12050 : }
12051 : }
12052 0 : return status;
12053 : }
12054 :
12055 : struct sn_state {
12056 : int matched;
12057 : int i;
12058 : bool val;
12059 : };
12060 :
12061 348 : static NTSTATUS shortname_list_fn(struct file_info *finfo,
12062 : const char *name, void *state)
12063 : {
12064 348 : struct sn_state *s = (struct sn_state *)state;
12065 348 : int i = s->i;
12066 :
12067 : #if 0
12068 : printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
12069 : i, finfo->name, finfo->short_name);
12070 : #endif
12071 :
12072 348 : if (strchr(force_shortname_chars, i)) {
12073 36 : if (!finfo->short_name) {
12074 : /* Shortname not created when it should be. */
12075 0 : d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
12076 : __location__, finfo->name, i);
12077 0 : s->val = true;
12078 : }
12079 312 : } else if (finfo->short_name){
12080 : /* Shortname created when it should not be. */
12081 0 : d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
12082 : __location__, finfo->short_name, finfo->name);
12083 0 : s->val = true;
12084 : }
12085 348 : s->matched += 1;
12086 348 : return NT_STATUS_OK;
12087 : }
12088 :
12089 4 : static bool run_shortname_test(int dummy)
12090 : {
12091 0 : static struct cli_state *cli;
12092 4 : bool correct = True;
12093 0 : int i;
12094 0 : struct sn_state s;
12095 0 : char fname[40];
12096 0 : NTSTATUS status;
12097 :
12098 4 : printf("starting shortname test\n");
12099 :
12100 4 : if (!torture_open_connection(&cli, 0)) {
12101 0 : return False;
12102 : }
12103 :
12104 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
12105 :
12106 4 : cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12107 4 : cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12108 4 : cli_rmdir(cli, "\\shortname");
12109 :
12110 4 : status = cli_mkdir(cli, "\\shortname");
12111 4 : if (!NT_STATUS_IS_OK(status)) {
12112 0 : d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
12113 : __location__, nt_errstr(status));
12114 0 : correct = false;
12115 0 : goto out;
12116 : }
12117 :
12118 4 : if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
12119 0 : correct = false;
12120 0 : goto out;
12121 : }
12122 4 : if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
12123 0 : correct = false;
12124 0 : goto out;
12125 : }
12126 :
12127 4 : s.val = false;
12128 :
12129 388 : for (i = 32; i < 128; i++) {
12130 384 : uint16_t fnum = (uint16_t)-1;
12131 :
12132 384 : s.i = i;
12133 :
12134 384 : if (strchr(illegal_chars, i)) {
12135 36 : continue;
12136 : }
12137 348 : fname[15] = i;
12138 :
12139 348 : status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12140 : FILE_SHARE_READ|FILE_SHARE_WRITE,
12141 : FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12142 348 : if (!NT_STATUS_IS_OK(status)) {
12143 0 : d_printf("(%s) cli_nt_create of %s failed: %s\n",
12144 : __location__, fname, nt_errstr(status));
12145 0 : correct = false;
12146 0 : goto out;
12147 : }
12148 348 : cli_close(cli, fnum);
12149 :
12150 348 : s.matched = 0;
12151 348 : status = cli_list(cli, "\\shortname\\test*.*", 0,
12152 : shortname_list_fn, &s);
12153 348 : if (s.matched != 1) {
12154 0 : d_printf("(%s) failed to list %s: %s\n",
12155 : __location__, fname, nt_errstr(status));
12156 0 : correct = false;
12157 0 : goto out;
12158 : }
12159 :
12160 348 : status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12161 348 : if (!NT_STATUS_IS_OK(status)) {
12162 0 : d_printf("(%s) failed to delete %s: %s\n",
12163 : __location__, fname, nt_errstr(status));
12164 0 : correct = false;
12165 0 : goto out;
12166 : }
12167 :
12168 348 : if (s.val) {
12169 0 : correct = false;
12170 0 : goto out;
12171 : }
12172 : }
12173 :
12174 4 : out:
12175 :
12176 4 : cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12177 4 : cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12178 4 : cli_rmdir(cli, "\\shortname");
12179 4 : torture_close_connection(cli);
12180 4 : return correct;
12181 : }
12182 :
12183 : TLDAPRC callback_code;
12184 :
12185 478 : static void pagedsearch_cb(struct tevent_req *req)
12186 : {
12187 0 : TLDAPRC rc;
12188 0 : struct tldap_message *msg;
12189 0 : char *dn;
12190 :
12191 478 : rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12192 478 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12193 0 : d_printf("tldap_search_paged_recv failed: %s\n",
12194 : tldap_rc2string(rc));
12195 0 : callback_code = rc;
12196 0 : return;
12197 : }
12198 478 : if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12199 8 : TALLOC_FREE(msg);
12200 8 : return;
12201 : }
12202 470 : if (!tldap_entry_dn(msg, &dn)) {
12203 0 : d_printf("tldap_entry_dn failed\n");
12204 0 : return;
12205 : }
12206 470 : d_printf("%s\n", dn);
12207 470 : TALLOC_FREE(msg);
12208 : }
12209 :
12210 : enum tldap_extended_val {
12211 : EXTENDED_ZERO = 0,
12212 : EXTENDED_ONE = 1,
12213 : EXTENDED_NONE = 2,
12214 : };
12215 :
12216 : /*
12217 : * Construct an extended dn control with either no value, 0 or 1
12218 : *
12219 : * No value and 0 are equivalent (non-hyphenated GUID)
12220 : * 1 has the hyphenated GUID
12221 : */
12222 : static struct tldap_control *
12223 6 : tldap_build_extended_control(enum tldap_extended_val val)
12224 : {
12225 0 : struct tldap_control empty_control;
12226 0 : struct asn1_data *data;
12227 :
12228 6 : ZERO_STRUCT(empty_control);
12229 :
12230 6 : if (val != EXTENDED_NONE) {
12231 4 : data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12232 :
12233 4 : if (!data) {
12234 0 : return NULL;
12235 : }
12236 :
12237 4 : if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12238 0 : return NULL;
12239 : }
12240 :
12241 4 : if (!asn1_write_Integer(data, (int)val)) {
12242 0 : return NULL;
12243 : }
12244 :
12245 4 : if (!asn1_pop_tag(data)) {
12246 0 : return NULL;
12247 : }
12248 :
12249 4 : if (!asn1_blob(data, &empty_control.value)) {
12250 0 : return NULL;
12251 : }
12252 : }
12253 :
12254 6 : empty_control.oid = "1.2.840.113556.1.4.529";
12255 6 : empty_control.critical = true;
12256 :
12257 6 : return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12258 :
12259 : }
12260 :
12261 6 : static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12262 : enum tldap_extended_val control_val)
12263 : {
12264 6 : struct tldap_control *control = tldap_build_extended_control(control_val);
12265 6 : char *dn = NULL;
12266 0 : struct tldap_message **msg;
12267 0 : TLDAPRC rc;
12268 :
12269 6 : rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12270 : "(objectClass=*)", NULL, 0, 0,
12271 : control, 1, NULL,
12272 : 0, 0, 0, 0, talloc_tos(), &msg);
12273 6 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12274 0 : d_printf("tldap_search for domain DN failed: %s\n",
12275 : tldap_errstr(talloc_tos(), ld, rc));
12276 0 : return false;
12277 : }
12278 :
12279 6 : if (!tldap_entry_dn(msg[0], &dn)) {
12280 0 : d_printf("tldap_search domain DN fetch failed: %s\n",
12281 : tldap_errstr(talloc_tos(), ld, rc));
12282 0 : return false;
12283 : }
12284 :
12285 6 : d_printf("%s\n", dn);
12286 : {
12287 0 : uint32_t time_low;
12288 0 : uint32_t time_mid, time_hi_and_version;
12289 0 : uint32_t clock_seq[2];
12290 0 : uint32_t node[6];
12291 0 : char next;
12292 :
12293 6 : switch (control_val) {
12294 4 : case EXTENDED_NONE:
12295 : case EXTENDED_ZERO:
12296 : /*
12297 : * When reading GUIDs with hyphens, scanf will treat
12298 : * hyphen as a hex character (and counts as part of the
12299 : * width). This creates leftover GUID string which we
12300 : * check will for with 'next' and closing '>'.
12301 : */
12302 4 : if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12303 : &time_low, &time_mid,
12304 : &time_hi_and_version, &clock_seq[0],
12305 : &clock_seq[1], &node[0], &node[1],
12306 : &node[2], &node[3], &node[4],
12307 : &node[5], &next)) {
12308 : /* This GUID is good */
12309 : } else {
12310 0 : d_printf("GUID format in control (no hyphens) doesn't match output\n");
12311 0 : return false;
12312 : }
12313 :
12314 4 : break;
12315 2 : case EXTENDED_ONE:
12316 2 : if (12 == sscanf(dn,
12317 : "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12318 : &time_low, &time_mid,
12319 : &time_hi_and_version, &clock_seq[0],
12320 : &clock_seq[1], &node[0], &node[1],
12321 : &node[2], &node[3], &node[4],
12322 : &node[5], &next)) {
12323 : /* This GUID is good */
12324 : } else {
12325 0 : d_printf("GUID format in control (with hyphens) doesn't match output\n");
12326 0 : return false;
12327 : }
12328 :
12329 2 : break;
12330 0 : default:
12331 0 : return false;
12332 : }
12333 : }
12334 :
12335 6 : return true;
12336 : }
12337 :
12338 2 : static bool run_tldap(int dummy)
12339 : {
12340 0 : struct tldap_context *ld;
12341 0 : int fd;
12342 0 : TLDAPRC rc;
12343 0 : NTSTATUS status;
12344 0 : struct sockaddr_storage addr;
12345 0 : struct tevent_context *ev;
12346 0 : struct tevent_req *req;
12347 0 : char *basedn;
12348 0 : const char *filter;
12349 :
12350 2 : if (!resolve_name(host, &addr, 0, false)) {
12351 0 : d_printf("could not find host %s\n", host);
12352 0 : return false;
12353 : }
12354 2 : status = open_socket_out(&addr, 389, 9999, &fd);
12355 2 : if (!NT_STATUS_IS_OK(status)) {
12356 0 : d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12357 0 : return false;
12358 : }
12359 :
12360 2 : ld = tldap_context_create(talloc_tos(), fd);
12361 2 : if (ld == NULL) {
12362 0 : close(fd);
12363 0 : d_printf("tldap_context_create failed\n");
12364 0 : return false;
12365 : }
12366 :
12367 2 : rc = tldap_fetch_rootdse(ld);
12368 2 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12369 0 : d_printf("tldap_fetch_rootdse failed: %s\n",
12370 : tldap_errstr(talloc_tos(), ld, rc));
12371 0 : return false;
12372 : }
12373 :
12374 2 : basedn = tldap_talloc_single_attribute(
12375 : tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12376 2 : if (basedn == NULL) {
12377 0 : d_printf("no defaultNamingContext\n");
12378 0 : return false;
12379 : }
12380 2 : d_printf("defaultNamingContext: %s\n", basedn);
12381 :
12382 2 : ev = samba_tevent_context_init(talloc_tos());
12383 2 : if (ev == NULL) {
12384 0 : d_printf("tevent_context_init failed\n");
12385 0 : return false;
12386 : }
12387 :
12388 2 : rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12389 : loadparm_init_s3(talloc_tos(),
12390 : loadparm_s3_helpers()),
12391 : GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12392 :
12393 2 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12394 0 : d_printf("tldap_gensec_bind failed\n");
12395 0 : return false;
12396 : }
12397 :
12398 2 : callback_code = TLDAP_SUCCESS;
12399 :
12400 2 : req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12401 : TLDAP_SCOPE_SUB, "(objectclass=*)",
12402 : NULL, 0, 0,
12403 : NULL, 0, NULL, 0, 0, 0, 0, 5);
12404 2 : if (req == NULL) {
12405 0 : d_printf("tldap_search_paged_send failed\n");
12406 0 : return false;
12407 : }
12408 2 : tevent_req_set_callback(req, pagedsearch_cb, NULL);
12409 :
12410 2 : tevent_req_poll(req, ev);
12411 :
12412 2 : TALLOC_FREE(req);
12413 :
12414 2 : rc = callback_code;
12415 :
12416 2 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12417 0 : d_printf("tldap_search with paging failed: %s\n",
12418 : tldap_errstr(talloc_tos(), ld, rc));
12419 0 : return false;
12420 : }
12421 :
12422 : /* test search filters against rootDSE */
12423 2 : filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12424 : "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12425 :
12426 2 : rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12427 : NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12428 : talloc_tos(), NULL);
12429 2 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12430 0 : d_printf("tldap_search with complex filter failed: %s\n",
12431 : tldap_errstr(talloc_tos(), ld, rc));
12432 0 : return false;
12433 : }
12434 :
12435 : /*
12436 : * Tests to check for regression of:
12437 : *
12438 : * https://bugzilla.samba.org/show_bug.cgi?id=14029
12439 : *
12440 : * TLDAP used here to pick apart the original string DN (with GUID)
12441 : */
12442 2 : if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12443 0 : d_printf("tldap_search with extended dn (no val) failed: %s\n",
12444 : tldap_errstr(talloc_tos(), ld, rc));
12445 0 : return false;
12446 : }
12447 2 : if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12448 0 : d_printf("tldap_search with extended dn (0) failed: %s\n",
12449 : tldap_errstr(talloc_tos(), ld, rc));
12450 0 : return false;
12451 : }
12452 2 : if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12453 0 : d_printf("tldap_search with extended dn (1) failed: %s\n",
12454 : tldap_errstr(talloc_tos(), ld, rc));
12455 0 : return false;
12456 : }
12457 :
12458 2 : TALLOC_FREE(ld);
12459 2 : return true;
12460 : }
12461 :
12462 : /* Torture test to ensure no regression of :
12463 : https://bugzilla.samba.org/show_bug.cgi?id=7084
12464 : */
12465 :
12466 4 : static bool run_dir_createtime(int dummy)
12467 : {
12468 0 : struct cli_state *cli;
12469 4 : const char *dname = "\\testdir_createtime";
12470 4 : const char *fname = "\\testdir_createtime\\testfile";
12471 0 : NTSTATUS status;
12472 0 : struct timespec create_time;
12473 0 : struct timespec create_time1;
12474 0 : uint16_t fnum;
12475 4 : bool ret = false;
12476 0 : uint64_t ino;
12477 :
12478 4 : if (!torture_open_connection(&cli, 0)) {
12479 0 : return false;
12480 : }
12481 :
12482 4 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12483 : /* Ensure ino is zero, SMB2 gets a real one. */
12484 0 : ino = 0;
12485 : } else {
12486 : /* Ensure ino is -1, SMB1 never gets a real one. */
12487 4 : ino = (uint64_t)-1;
12488 : }
12489 :
12490 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12491 4 : cli_rmdir(cli, dname);
12492 :
12493 4 : status = cli_mkdir(cli, dname);
12494 4 : if (!NT_STATUS_IS_OK(status)) {
12495 0 : printf("mkdir failed: %s\n", nt_errstr(status));
12496 0 : goto out;
12497 : }
12498 :
12499 4 : status = cli_qpathinfo2(cli,
12500 : dname,
12501 : &create_time,
12502 : NULL,
12503 : NULL,
12504 : NULL,
12505 : NULL,
12506 : NULL,
12507 : &ino,
12508 : NULL);
12509 4 : if (!NT_STATUS_IS_OK(status)) {
12510 0 : printf("cli_qpathinfo2 returned %s\n",
12511 : nt_errstr(status));
12512 0 : goto out;
12513 : }
12514 :
12515 4 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12516 : /* SMB2 should always return an inode. */
12517 0 : if (ino == 0) {
12518 0 : printf("SMB2 bad inode (0)\n");
12519 0 : goto out;
12520 : }
12521 : } else {
12522 : /* SMB1 must always return zero here. */
12523 4 : if (ino != 0) {
12524 0 : printf("SMB1 bad inode (!0)\n");
12525 0 : goto out;
12526 : }
12527 : }
12528 :
12529 : /* Sleep 3 seconds, then create a file. */
12530 4 : sleep(3);
12531 :
12532 4 : status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12533 : DENY_NONE, &fnum);
12534 4 : if (!NT_STATUS_IS_OK(status)) {
12535 0 : printf("cli_openx failed: %s\n", nt_errstr(status));
12536 0 : goto out;
12537 : }
12538 :
12539 4 : status = cli_qpathinfo2(cli,
12540 : dname,
12541 : &create_time1,
12542 : NULL,
12543 : NULL,
12544 : NULL,
12545 : NULL,
12546 : NULL,
12547 : NULL,
12548 : NULL);
12549 4 : if (!NT_STATUS_IS_OK(status)) {
12550 0 : printf("cli_qpathinfo2 (2) returned %s\n",
12551 : nt_errstr(status));
12552 0 : goto out;
12553 : }
12554 :
12555 4 : if (timespec_compare(&create_time1, &create_time)) {
12556 0 : printf("run_dir_createtime: create time was updated (error)\n");
12557 : } else {
12558 4 : printf("run_dir_createtime: create time was not updated (correct)\n");
12559 4 : ret = true;
12560 : }
12561 :
12562 4 : out:
12563 :
12564 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12565 4 : cli_rmdir(cli, dname);
12566 4 : if (!torture_close_connection(cli)) {
12567 0 : ret = false;
12568 : }
12569 4 : return ret;
12570 : }
12571 :
12572 :
12573 4 : static bool run_streamerror(int dummy)
12574 : {
12575 0 : struct cli_state *cli;
12576 4 : const char *dname = "\\testdir_streamerror";
12577 4 : const char *streamname =
12578 : "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12579 0 : NTSTATUS status;
12580 0 : time_t change_time, access_time, write_time;
12581 0 : off_t size;
12582 0 : uint16_t fnum;
12583 0 : uint32_t attr;
12584 4 : bool ret = true;
12585 :
12586 4 : if (!torture_open_connection(&cli, 0)) {
12587 0 : return false;
12588 : }
12589 :
12590 4 : torture_deltree(cli, dname);
12591 :
12592 4 : status = cli_mkdir(cli, dname);
12593 4 : if (!NT_STATUS_IS_OK(status)) {
12594 0 : printf("mkdir failed: %s\n", nt_errstr(status));
12595 0 : return false;
12596 : }
12597 :
12598 4 : status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12599 : &write_time, &size, &attr);
12600 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12601 0 : printf("pathinfo returned %s, expected "
12602 : "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12603 : nt_errstr(status));
12604 0 : ret = false;
12605 : }
12606 :
12607 4 : status = cli_ntcreate(cli, streamname, 0x16,
12608 : FILE_READ_DATA|FILE_READ_EA|
12609 : FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12610 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12611 : FILE_OPEN, 0, 0, &fnum, NULL);
12612 :
12613 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12614 0 : printf("ntcreate returned %s, expected "
12615 : "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12616 : nt_errstr(status));
12617 0 : ret = false;
12618 : }
12619 :
12620 :
12621 4 : cli_rmdir(cli, dname);
12622 4 : return ret;
12623 : }
12624 :
12625 : struct pidtest_state {
12626 : bool success;
12627 : uint16_t vwv[1];
12628 : DATA_BLOB data;
12629 : };
12630 :
12631 : static void pid_echo_done(struct tevent_req *subreq);
12632 :
12633 4 : static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12634 : struct tevent_context *ev,
12635 : struct cli_state *cli)
12636 : {
12637 0 : struct tevent_req *req, *subreq;
12638 0 : struct pidtest_state *state;
12639 :
12640 4 : req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12641 4 : if (req == NULL) {
12642 0 : return NULL;
12643 : }
12644 :
12645 4 : SSVAL(state->vwv, 0, 1);
12646 4 : state->data = data_blob_const("hello", 5);
12647 :
12648 4 : subreq = smb1cli_req_send(state,
12649 : ev,
12650 : cli->conn,
12651 : SMBecho,
12652 : 0, 0, /* *_flags */
12653 : 0, 0, /* *_flags2 */
12654 4 : cli->timeout,
12655 : 0xDEADBEEF, /* pid */
12656 : NULL, /* tcon */
12657 : NULL, /* session */
12658 4 : ARRAY_SIZE(state->vwv), state->vwv,
12659 4 : state->data.length, state->data.data);
12660 :
12661 4 : if (tevent_req_nomem(subreq, req)) {
12662 0 : return tevent_req_post(req, ev);
12663 : }
12664 4 : tevent_req_set_callback(subreq, pid_echo_done, req);
12665 4 : return req;
12666 : }
12667 :
12668 4 : static void pid_echo_done(struct tevent_req *subreq)
12669 : {
12670 4 : struct tevent_req *req = tevent_req_callback_data(
12671 : subreq, struct tevent_req);
12672 4 : struct pidtest_state *state = tevent_req_data(
12673 : req, struct pidtest_state);
12674 0 : NTSTATUS status;
12675 0 : uint32_t num_bytes;
12676 4 : uint8_t *bytes = NULL;
12677 4 : struct iovec *recv_iov = NULL;
12678 4 : uint8_t *phdr = NULL;
12679 4 : uint16_t pidlow = 0;
12680 4 : uint16_t pidhigh = 0;
12681 4 : struct smb1cli_req_expected_response expected[] = {
12682 : {
12683 : .status = NT_STATUS_OK,
12684 : .wct = 1,
12685 : },
12686 : };
12687 :
12688 4 : status = smb1cli_req_recv(subreq, state,
12689 : &recv_iov,
12690 : &phdr,
12691 : NULL, /* pwct */
12692 : NULL, /* pvwv */
12693 : NULL, /* pvwv_offset */
12694 : &num_bytes,
12695 : &bytes,
12696 : NULL, /* pbytes_offset */
12697 : NULL, /* pinbuf */
12698 : expected, ARRAY_SIZE(expected));
12699 :
12700 4 : TALLOC_FREE(subreq);
12701 :
12702 4 : if (!NT_STATUS_IS_OK(status)) {
12703 0 : tevent_req_nterror(req, status);
12704 0 : return;
12705 : }
12706 :
12707 4 : if (num_bytes != state->data.length) {
12708 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12709 0 : return;
12710 : }
12711 :
12712 4 : if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12713 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12714 0 : return;
12715 : }
12716 :
12717 : /* Check pid low/high == DEADBEEF */
12718 4 : pidlow = SVAL(phdr, HDR_PID);
12719 4 : if (pidlow != 0xBEEF){
12720 0 : printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12721 : (unsigned int)pidlow);
12722 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12723 0 : return;
12724 : }
12725 4 : pidhigh = SVAL(phdr, HDR_PIDHIGH);
12726 4 : if (pidhigh != 0xDEAD){
12727 0 : printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12728 : (unsigned int)pidhigh);
12729 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12730 0 : return;
12731 : }
12732 :
12733 4 : tevent_req_done(req);
12734 : }
12735 :
12736 4 : static NTSTATUS pid_echo_recv(struct tevent_req *req)
12737 : {
12738 4 : return tevent_req_simple_recv_ntstatus(req);
12739 : }
12740 :
12741 4 : static bool run_pidhigh(int dummy)
12742 : {
12743 4 : bool success = false;
12744 4 : struct cli_state *cli = NULL;
12745 0 : NTSTATUS status;
12746 4 : struct tevent_context *ev = NULL;
12747 4 : struct tevent_req *req = NULL;
12748 4 : TALLOC_CTX *frame = talloc_stackframe();
12749 :
12750 4 : printf("starting pid high test\n");
12751 4 : if (!torture_open_connection(&cli, 0)) {
12752 0 : return false;
12753 : }
12754 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
12755 :
12756 4 : ev = samba_tevent_context_init(frame);
12757 4 : if (ev == NULL) {
12758 0 : goto fail;
12759 : }
12760 :
12761 4 : req = pid_echo_send(frame, ev, cli);
12762 4 : if (req == NULL) {
12763 0 : goto fail;
12764 : }
12765 :
12766 4 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12767 0 : goto fail;
12768 : }
12769 :
12770 4 : status = pid_echo_recv(req);
12771 4 : if (NT_STATUS_IS_OK(status)) {
12772 4 : printf("pid high test ok\n");
12773 4 : success = true;
12774 : }
12775 :
12776 0 : fail:
12777 :
12778 4 : TALLOC_FREE(frame);
12779 4 : torture_close_connection(cli);
12780 4 : return success;
12781 : }
12782 :
12783 : /*
12784 : Test Windows open on a bad POSIX symlink.
12785 : */
12786 4 : static bool run_symlink_open_test(int dummy)
12787 : {
12788 0 : static struct cli_state *cli;
12789 4 : const char *fname = "non_existant_file";
12790 4 : const char *sname = "dangling_symlink";
12791 4 : uint16_t fnum = (uint16_t)-1;
12792 4 : bool correct = false;
12793 0 : NTSTATUS status;
12794 4 : TALLOC_CTX *frame = NULL;
12795 :
12796 4 : frame = talloc_stackframe();
12797 :
12798 4 : printf("Starting Windows bad symlink open test\n");
12799 :
12800 4 : if (!torture_open_connection(&cli, 0)) {
12801 0 : TALLOC_FREE(frame);
12802 0 : return false;
12803 : }
12804 :
12805 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
12806 :
12807 4 : status = torture_setup_unix_extensions(cli);
12808 4 : if (!NT_STATUS_IS_OK(status)) {
12809 0 : TALLOC_FREE(frame);
12810 0 : return false;
12811 : }
12812 :
12813 : /* Ensure nothing exists. */
12814 4 : cli_setatr(cli, fname, 0, 0);
12815 4 : cli_posix_unlink(cli, fname);
12816 4 : cli_setatr(cli, sname, 0, 0);
12817 4 : cli_posix_unlink(cli, sname);
12818 :
12819 : /* Create a symlink pointing nowhere. */
12820 4 : status = cli_posix_symlink(cli, fname, sname);
12821 4 : if (!NT_STATUS_IS_OK(status)) {
12822 0 : printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12823 : sname,
12824 : fname,
12825 : nt_errstr(status));
12826 0 : goto out;
12827 : }
12828 :
12829 : /* Now ensure that a Windows open doesn't hang. */
12830 4 : status = cli_ntcreate(cli,
12831 : sname,
12832 : 0,
12833 : FILE_READ_DATA|FILE_WRITE_DATA,
12834 : 0,
12835 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12836 : FILE_OPEN_IF,
12837 : 0x0,
12838 : 0x0,
12839 : &fnum,
12840 : NULL);
12841 :
12842 : /*
12843 : * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12844 : * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12845 : * we use O_NOFOLLOW on the server or not.
12846 : */
12847 4 : if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12848 0 : NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12849 : {
12850 4 : correct = true;
12851 : } else {
12852 0 : printf("cli_ntcreate of %s returned %s - should return"
12853 : " either (%s) or (%s)\n",
12854 : sname,
12855 : nt_errstr(status),
12856 0 : nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12857 0 : nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12858 0 : goto out;
12859 : }
12860 :
12861 4 : correct = true;
12862 :
12863 4 : out:
12864 :
12865 4 : if (fnum != (uint16_t)-1) {
12866 0 : cli_close(cli, fnum);
12867 0 : fnum = (uint16_t)-1;
12868 : }
12869 :
12870 4 : cli_setatr(cli, sname, 0, 0);
12871 4 : cli_posix_unlink(cli, sname);
12872 4 : cli_setatr(cli, fname, 0, 0);
12873 4 : cli_posix_unlink(cli, fname);
12874 :
12875 4 : if (!torture_close_connection(cli)) {
12876 0 : correct = false;
12877 : }
12878 :
12879 4 : TALLOC_FREE(frame);
12880 4 : return correct;
12881 : }
12882 :
12883 16 : static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12884 : const char *name,
12885 : void *state)
12886 : {
12887 16 : char **mangled_name_return = (char **)state;
12888 16 : bool is_mangled = strchr(finfo->name, '~');
12889 :
12890 16 : if (is_mangled) {
12891 8 : *mangled_name_return = talloc_strdup(NULL, finfo->name);
12892 8 : if (*mangled_name_return == NULL) {
12893 0 : return NT_STATUS_NO_MEMORY;
12894 : }
12895 : }
12896 16 : return NT_STATUS_OK;
12897 : }
12898 :
12899 4 : static bool run_smb1_wild_mangle_unlink_test(int dummy)
12900 : {
12901 0 : static struct cli_state *cli_posix = NULL;
12902 0 : static struct cli_state *cli = NULL;
12903 4 : uint16_t fnum = (uint16_t)-1;
12904 4 : bool correct = false;
12905 4 : const char *dname = "smb1_wild_mangle_unlink";
12906 4 : const char *aname = "smb1_wild_mangle_unlink/a";
12907 4 : const char *star_name = "smb1_wild_mangle_unlink/*";
12908 4 : char *windows_unlink_name = NULL;
12909 4 : char *mangled_name = NULL;
12910 0 : NTSTATUS status;
12911 :
12912 4 : printf("Starting SMB1 wild mangle unlink test\n");
12913 :
12914 : /* Open a Windows connection. */
12915 4 : if (!torture_open_connection(&cli, 0)) {
12916 0 : return false;
12917 : }
12918 :
12919 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
12920 :
12921 : /* Open a POSIX connection. */
12922 4 : if (!torture_open_connection(&cli_posix, 0)) {
12923 0 : goto out;
12924 : }
12925 :
12926 4 : smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12927 :
12928 4 : status = torture_setup_unix_extensions(cli_posix);
12929 4 : if (!NT_STATUS_IS_OK(status)) {
12930 0 : printf("server doesn't support POSIX\n");
12931 0 : goto out;
12932 : }
12933 :
12934 : /* Start fresh. */
12935 4 : torture_deltree(cli, dname);
12936 :
12937 : /*
12938 : * Create two files - 'a' and '*'.
12939 : * We need POSIX extensions for this as '*'
12940 : * is not a valid Windows name.
12941 : */
12942 :
12943 4 : status = cli_mkdir(cli, dname);
12944 4 : if (!NT_STATUS_IS_OK(status)) {
12945 0 : printf("cli_mkdir of %s returned %s\n",
12946 : dname,
12947 : nt_errstr(status));
12948 0 : goto out;
12949 : }
12950 :
12951 4 : status = cli_posix_open(cli_posix,
12952 : aname,
12953 : O_RDWR|O_CREAT|O_EXCL,
12954 : 0660,
12955 : &fnum);
12956 4 : if (!NT_STATUS_IS_OK(status)) {
12957 0 : printf("cli_posix_open (create) of %s returned %s\n",
12958 : aname,
12959 : nt_errstr(status));
12960 0 : goto out;
12961 : }
12962 4 : status = cli_close(cli_posix, fnum);
12963 4 : if (!NT_STATUS_IS_OK(status)) {
12964 0 : goto out;
12965 : }
12966 4 : status = cli_posix_open(cli_posix,
12967 : star_name,
12968 : O_RDWR|O_CREAT|O_EXCL,
12969 : 0660,
12970 : &fnum);
12971 4 : if (!NT_STATUS_IS_OK(status)) {
12972 0 : printf("cli_posix_open (create) of %s returned %s\n",
12973 : star_name,
12974 : nt_errstr(status));
12975 0 : goto out;
12976 : }
12977 4 : status = cli_close(cli_posix, fnum);
12978 4 : if (!NT_STATUS_IS_OK(status)) {
12979 0 : goto out;
12980 : }
12981 :
12982 4 : status = cli_list(cli,
12983 : star_name,
12984 : 0,
12985 : smb1_wild_mangle_list_fn,
12986 : &mangled_name);
12987 4 : if (!NT_STATUS_IS_OK(status)) {
12988 0 : printf("cli_list of %s returned %s\n",
12989 : star_name,
12990 : nt_errstr(status));
12991 0 : goto out;
12992 : }
12993 :
12994 4 : if (mangled_name == NULL) {
12995 0 : goto out;
12996 : }
12997 :
12998 4 : printf("mangled_name = %s\n",
12999 : mangled_name);
13000 :
13001 : /*
13002 : * Try a Windows unlink with the mangled name.
13003 : * This should *NOT* unlink the 'a' name.
13004 : */
13005 :
13006 4 : windows_unlink_name = talloc_asprintf(cli_posix,
13007 : "%s\\%s",
13008 : dname,
13009 : mangled_name);
13010 :
13011 4 : status = cli_unlink(cli, windows_unlink_name, 0);
13012 4 : if (!NT_STATUS_IS_OK(status)) {
13013 0 : printf("cli_unlink of %s returned %s\n",
13014 : windows_unlink_name,
13015 : nt_errstr(status));
13016 0 : goto out;
13017 : }
13018 :
13019 : /* Does 'a' still exist ? */
13020 4 : status = cli_posix_open(cli_posix,
13021 : aname,
13022 : O_RDONLY,
13023 : 0,
13024 : &fnum);
13025 4 : if (!NT_STATUS_IS_OK(status)) {
13026 0 : printf("cli_posix_open O_RNONLY of %s returned %s\n",
13027 : aname,
13028 : nt_errstr(status));
13029 0 : goto out;
13030 : }
13031 :
13032 4 : status = cli_close(cli_posix, fnum);
13033 4 : if (!NT_STATUS_IS_OK(status)) {
13034 0 : goto out;
13035 : }
13036 :
13037 4 : correct = true;
13038 :
13039 4 : out:
13040 :
13041 4 : TALLOC_FREE(windows_unlink_name);
13042 4 : TALLOC_FREE(mangled_name);
13043 :
13044 4 : if (cli != NULL) {
13045 4 : torture_deltree(cli, dname);
13046 4 : torture_close_connection(cli);
13047 : }
13048 :
13049 4 : if (cli_posix != NULL) {
13050 4 : torture_close_connection(cli_posix);
13051 : }
13052 :
13053 4 : return correct;
13054 : }
13055 :
13056 4 : static bool run_smb1_wild_mangle_rename_test(int dummy)
13057 : {
13058 0 : static struct cli_state *cli_posix = NULL;
13059 0 : static struct cli_state *cli = NULL;
13060 4 : uint16_t fnum = (uint16_t)-1;
13061 4 : bool correct = false;
13062 4 : const char *dname = "smb1_wild_mangle_rename";
13063 4 : const char *fooname = "smb1_wild_mangle_rename/foo";
13064 4 : const char *foostar_name = "smb1_wild_mangle_rename/fo*";
13065 4 : const char *wild_name = "smb1_wild_mangle_rename/*";
13066 4 : char *windows_rename_src = NULL;
13067 4 : const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
13068 4 : char *mangled_name = NULL;
13069 0 : NTSTATUS status;
13070 :
13071 4 : printf("Starting SMB1 wild mangle rename test\n");
13072 :
13073 4 : if (!torture_open_connection(&cli_posix, 0)) {
13074 0 : return false;
13075 : }
13076 :
13077 4 : smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
13078 :
13079 4 : status = torture_setup_unix_extensions(cli_posix);
13080 4 : if (!NT_STATUS_IS_OK(status)) {
13081 0 : printf("server doesn't support POSIX\n");
13082 0 : return false;
13083 : }
13084 :
13085 : /* Open a Windows connection. */
13086 4 : if (!torture_open_connection(&cli, 0)) {
13087 0 : goto out;
13088 : }
13089 :
13090 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
13091 :
13092 : /* Ensure we start from fresh. */
13093 4 : torture_deltree(cli, dname);
13094 :
13095 : /*
13096 : * Create two files - 'foo' and 'fo*'.
13097 : * We need POSIX extensions for this as 'fo*'
13098 : * is not a valid Windows name.
13099 : */
13100 :
13101 4 : status = cli_posix_mkdir(cli_posix, dname, 0770);
13102 4 : if (!NT_STATUS_IS_OK(status)) {
13103 0 : printf("cli_posix_mkdir of %s returned %s\n",
13104 : dname,
13105 : nt_errstr(status));
13106 0 : goto out;
13107 : }
13108 :
13109 4 : status = cli_posix_open(cli_posix,
13110 : fooname,
13111 : O_RDWR|O_CREAT|O_EXCL,
13112 : 0660,
13113 : &fnum);
13114 4 : if (!NT_STATUS_IS_OK(status)) {
13115 0 : printf("cli_posix_open (create) of %s returned %s\n",
13116 : fooname,
13117 : nt_errstr(status));
13118 0 : goto out;
13119 : }
13120 4 : status = cli_close(cli_posix, fnum);
13121 4 : if (!NT_STATUS_IS_OK(status)) {
13122 0 : goto out;
13123 : }
13124 4 : status = cli_posix_open(cli_posix,
13125 : foostar_name,
13126 : O_RDWR|O_CREAT|O_EXCL,
13127 : 0660,
13128 : &fnum);
13129 4 : if (!NT_STATUS_IS_OK(status)) {
13130 0 : printf("cli_posix_open (create) of %s returned %s\n",
13131 : foostar_name,
13132 : nt_errstr(status));
13133 0 : goto out;
13134 : }
13135 4 : status = cli_close(cli_posix, fnum);
13136 4 : if (!NT_STATUS_IS_OK(status)) {
13137 0 : goto out;
13138 : }
13139 :
13140 : /*
13141 : * Get the mangled name. We can re-use the
13142 : * previous smb1_wild_mangle_list_fn for this.
13143 : */
13144 :
13145 4 : status = cli_list(cli,
13146 : wild_name,
13147 : 0,
13148 : smb1_wild_mangle_list_fn,
13149 : &mangled_name);
13150 4 : if (!NT_STATUS_IS_OK(status)) {
13151 0 : printf("cli_list of %s returned %s\n",
13152 : wild_name,
13153 : nt_errstr(status));
13154 0 : goto out;
13155 : }
13156 :
13157 4 : if (mangled_name == NULL) {
13158 0 : goto out;
13159 : }
13160 :
13161 4 : printf("mangled_name = %s\n",
13162 : mangled_name);
13163 :
13164 : /*
13165 : * Try a Windows rename with the mangled name.
13166 : * This should *NOT* rename the 'foo' name.
13167 : */
13168 :
13169 4 : windows_rename_src = talloc_asprintf(cli_posix,
13170 : "%s\\%s",
13171 : dname,
13172 : mangled_name);
13173 :
13174 4 : status = cli_rename(cli,
13175 : windows_rename_src,
13176 : windows_rename_dst,
13177 : false);
13178 4 : if (!NT_STATUS_IS_OK(status)) {
13179 0 : printf("cli_rename of %s -> %s returned %s\n",
13180 : windows_rename_src,
13181 : windows_rename_dst,
13182 : nt_errstr(status));
13183 0 : goto out;
13184 : }
13185 :
13186 : /* Does 'foo' still exist ? */
13187 4 : status = cli_posix_open(cli_posix,
13188 : fooname,
13189 : O_RDONLY,
13190 : 0,
13191 : &fnum);
13192 4 : if (!NT_STATUS_IS_OK(status)) {
13193 0 : printf("cli_posix_open O_RNONLY of %s returned %s\n",
13194 : fooname,
13195 : nt_errstr(status));
13196 0 : goto out;
13197 : }
13198 :
13199 4 : status = cli_close(cli_posix, fnum);
13200 4 : if (!NT_STATUS_IS_OK(status)) {
13201 0 : goto out;
13202 : }
13203 :
13204 4 : correct = true;
13205 :
13206 4 : out:
13207 :
13208 4 : TALLOC_FREE(mangled_name);
13209 4 : TALLOC_FREE(windows_rename_src);
13210 :
13211 4 : if (cli != NULL) {
13212 4 : torture_deltree(cli, dname);
13213 4 : torture_close_connection(cli);
13214 : }
13215 :
13216 4 : torture_close_connection(cli_posix);
13217 :
13218 4 : return correct;
13219 : }
13220 :
13221 : /*
13222 : * Only testing minimal time strings, as the others
13223 : * need (locale-dependent) guessing at what strftime does and
13224 : * even may differ in builds.
13225 : */
13226 1 : static bool timesubst_test(void)
13227 : {
13228 1 : TALLOC_CTX *ctx = NULL;
13229 : /* Sa 23. Dez 04:33:20 CET 2017 */
13230 1 : const struct timeval tv = { 1514000000, 123 };
13231 1 : const char* expect_minimal = "20171223_033320";
13232 1 : const char* expect_minus = "20171223_033320_000123";
13233 1 : char *s;
13234 1 : char *env_tz, *orig_tz = NULL;
13235 1 : bool result = true;
13236 :
13237 1 : ctx = talloc_new(NULL);
13238 :
13239 1 : env_tz = getenv("TZ");
13240 1 : if(env_tz) {
13241 1 : orig_tz = talloc_strdup(ctx, env_tz);
13242 : }
13243 1 : setenv("TZ", "UTC", 1);
13244 :
13245 1 : s = minimal_timeval_string(ctx, &tv, false);
13246 :
13247 1 : if(!s || strcmp(s, expect_minimal)) {
13248 0 : printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13249 : "[%s]\n", s ? s : "<nil>", expect_minimal);
13250 0 : result = false;
13251 : }
13252 1 : TALLOC_FREE(s);
13253 1 : s = minimal_timeval_string(ctx, &tv, true);
13254 1 : if(!s || strcmp(s, expect_minus)) {
13255 0 : printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13256 : "[%s]\n", s ? s : "<nil>", expect_minus);
13257 0 : result = false;
13258 : }
13259 1 : TALLOC_FREE(s);
13260 :
13261 1 : if(orig_tz) {
13262 1 : setenv("TZ", orig_tz, 1);
13263 : }
13264 :
13265 1 : TALLOC_FREE(ctx);
13266 1 : return result;
13267 : }
13268 :
13269 1 : static bool run_local_substitute(int dummy)
13270 : {
13271 1 : bool ok = true;
13272 :
13273 1 : ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13274 1 : ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13275 1 : ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13276 1 : ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13277 1 : ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13278 1 : ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13279 1 : ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13280 1 : ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13281 1 : ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13282 : /* Substitution depends on current time, so better test the underlying
13283 : formatting function. At least covers %t. */
13284 1 : ok &= timesubst_test();
13285 :
13286 : /* Different captialization rules in sub_basic... */
13287 :
13288 1 : ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13289 1 : "blaDOM") == 0);
13290 :
13291 1 : return ok;
13292 : }
13293 :
13294 1 : static bool run_local_base64(int dummy)
13295 : {
13296 1 : int i;
13297 1 : bool ret = true;
13298 :
13299 2000 : for (i=1; i<2000; i++) {
13300 1999 : DATA_BLOB blob1, blob2;
13301 1999 : char *b64;
13302 :
13303 1999 : blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13304 1999 : blob1.length = i;
13305 1999 : generate_random_buffer(blob1.data, blob1.length);
13306 :
13307 1999 : b64 = base64_encode_data_blob(talloc_tos(), blob1);
13308 1999 : if (b64 == NULL) {
13309 0 : d_fprintf(stderr, "base64_encode_data_blob failed "
13310 : "for %d bytes\n", i);
13311 0 : ret = false;
13312 : }
13313 1999 : blob2 = base64_decode_data_blob(b64);
13314 1999 : TALLOC_FREE(b64);
13315 :
13316 1999 : if (data_blob_cmp(&blob1, &blob2)) {
13317 0 : d_fprintf(stderr, "data_blob_cmp failed for %d "
13318 : "bytes\n", i);
13319 0 : ret = false;
13320 : }
13321 1999 : TALLOC_FREE(blob1.data);
13322 1999 : data_blob_free(&blob2);
13323 : }
13324 1 : return ret;
13325 : }
13326 :
13327 1000000 : static void parse_fn(const struct gencache_timeout *t,
13328 : DATA_BLOB blob,
13329 : void *private_data)
13330 : {
13331 1000000 : return;
13332 : }
13333 :
13334 1 : static bool run_local_gencache(int dummy)
13335 : {
13336 1 : char *val;
13337 1 : time_t tm;
13338 1 : DATA_BLOB blob;
13339 1 : char v;
13340 1 : struct memcache *mem;
13341 1 : int i;
13342 :
13343 1 : mem = memcache_init(NULL, 0);
13344 1 : if (mem == NULL) {
13345 0 : d_printf("%s: memcache_init failed\n", __location__);
13346 0 : return false;
13347 : }
13348 1 : memcache_set_global(mem);
13349 :
13350 1 : if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13351 0 : d_printf("%s: gencache_set() failed\n", __location__);
13352 0 : return False;
13353 : }
13354 :
13355 1 : if (!gencache_get("foo", NULL, NULL, NULL)) {
13356 0 : d_printf("%s: gencache_get() failed\n", __location__);
13357 0 : return False;
13358 : }
13359 :
13360 1000001 : for (i=0; i<1000000; i++) {
13361 1000000 : gencache_parse("foo", parse_fn, NULL);
13362 : }
13363 :
13364 1 : if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13365 0 : d_printf("%s: gencache_get() failed\n", __location__);
13366 0 : return False;
13367 : }
13368 1 : TALLOC_FREE(val);
13369 :
13370 1 : if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13371 0 : d_printf("%s: gencache_get() failed\n", __location__);
13372 0 : return False;
13373 : }
13374 :
13375 1 : if (strcmp(val, "bar") != 0) {
13376 0 : d_printf("%s: gencache_get() returned %s, expected %s\n",
13377 : __location__, val, "bar");
13378 0 : TALLOC_FREE(val);
13379 0 : return False;
13380 : }
13381 :
13382 1 : TALLOC_FREE(val);
13383 :
13384 1 : if (!gencache_del("foo")) {
13385 0 : d_printf("%s: gencache_del() failed\n", __location__);
13386 0 : return False;
13387 : }
13388 1 : if (gencache_del("foo")) {
13389 0 : d_printf("%s: second gencache_del() succeeded\n",
13390 : __location__);
13391 0 : return False;
13392 : }
13393 :
13394 1 : if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13395 0 : d_printf("%s: gencache_get() on deleted entry "
13396 : "succeeded\n", __location__);
13397 0 : return False;
13398 : }
13399 :
13400 1 : blob = data_blob_string_const_null("bar");
13401 1 : tm = time(NULL) + 60;
13402 :
13403 1 : if (!gencache_set_data_blob("foo", blob, tm)) {
13404 0 : d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13405 0 : return False;
13406 : }
13407 :
13408 1 : if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13409 0 : d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13410 0 : return False;
13411 : }
13412 :
13413 1 : if (strcmp((const char *)blob.data, "bar") != 0) {
13414 0 : d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13415 0 : __location__, (const char *)blob.data, "bar");
13416 0 : data_blob_free(&blob);
13417 0 : return False;
13418 : }
13419 :
13420 1 : data_blob_free(&blob);
13421 :
13422 1 : if (!gencache_del("foo")) {
13423 0 : d_printf("%s: gencache_del() failed\n", __location__);
13424 0 : return False;
13425 : }
13426 1 : if (gencache_del("foo")) {
13427 0 : d_printf("%s: second gencache_del() succeeded\n",
13428 : __location__);
13429 0 : return False;
13430 : }
13431 :
13432 1 : if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13433 0 : d_printf("%s: gencache_get_data_blob() on deleted entry "
13434 : "succeeded\n", __location__);
13435 0 : return False;
13436 : }
13437 :
13438 1 : v = 1;
13439 1 : blob.data = (uint8_t *)&v;
13440 1 : blob.length = sizeof(v);
13441 :
13442 1 : if (!gencache_set_data_blob("blob", blob, tm)) {
13443 0 : d_printf("%s: gencache_set_data_blob() failed\n",
13444 : __location__);
13445 0 : return false;
13446 : }
13447 1 : if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13448 0 : d_printf("%s: gencache_get succeeded\n", __location__);
13449 0 : return false;
13450 : }
13451 :
13452 0 : return True;
13453 : }
13454 :
13455 1 : static bool rbt_testflags(struct db_context *db, const char *key,
13456 : const char *value)
13457 : {
13458 1 : bool ret = false;
13459 1 : NTSTATUS status;
13460 1 : struct db_record *rec;
13461 :
13462 1 : rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13463 1 : if (rec == NULL) {
13464 0 : d_fprintf(stderr, "fetch_locked failed\n");
13465 0 : goto done;
13466 : }
13467 :
13468 1 : status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13469 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13470 0 : d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13471 : nt_errstr(status));
13472 0 : goto done;
13473 : }
13474 :
13475 1 : status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13476 : TDB_INSERT);
13477 1 : if (!NT_STATUS_IS_OK(status)) {
13478 0 : d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13479 : nt_errstr(status));
13480 0 : goto done;
13481 : }
13482 :
13483 1 : status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13484 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13485 0 : d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13486 : nt_errstr(status));
13487 0 : goto done;
13488 : }
13489 :
13490 1 : status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13491 1 : if (!NT_STATUS_IS_OK(status)) {
13492 0 : d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13493 : nt_errstr(status));
13494 0 : goto done;
13495 : }
13496 :
13497 0 : ret = true;
13498 1 : done:
13499 1 : TALLOC_FREE(rec);
13500 1 : return ret;
13501 : }
13502 :
13503 1998 : static bool rbt_testval(struct db_context *db, const char *key,
13504 : const char *value)
13505 : {
13506 1998 : struct db_record *rec;
13507 1998 : TDB_DATA data = string_tdb_data(value);
13508 1998 : bool ret = false;
13509 1998 : NTSTATUS status;
13510 1998 : TDB_DATA dbvalue;
13511 :
13512 1998 : rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13513 1998 : if (rec == NULL) {
13514 0 : d_fprintf(stderr, "fetch_locked failed\n");
13515 0 : goto done;
13516 : }
13517 1998 : status = dbwrap_record_store(rec, data, 0);
13518 1998 : if (!NT_STATUS_IS_OK(status)) {
13519 0 : d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13520 0 : goto done;
13521 : }
13522 1998 : TALLOC_FREE(rec);
13523 :
13524 1998 : rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13525 1998 : if (rec == NULL) {
13526 0 : d_fprintf(stderr, "second fetch_locked failed\n");
13527 0 : goto done;
13528 : }
13529 :
13530 1998 : dbvalue = dbwrap_record_get_value(rec);
13531 1998 : if ((dbvalue.dsize != data.dsize)
13532 1998 : || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13533 0 : d_fprintf(stderr, "Got wrong data back\n");
13534 0 : goto done;
13535 : }
13536 :
13537 0 : ret = true;
13538 1998 : done:
13539 1998 : TALLOC_FREE(rec);
13540 1998 : return ret;
13541 : }
13542 :
13543 1000 : static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13544 : {
13545 1000 : int *count2 = (int *)private_data;
13546 1000 : (*count2)++;
13547 1000 : return 0;
13548 : }
13549 :
13550 1000 : static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13551 : {
13552 1000 : int *count2 = (int *)private_data;
13553 1000 : (*count2)++;
13554 1000 : dbwrap_record_delete(rec);
13555 1000 : return 0;
13556 : }
13557 :
13558 1 : static bool run_local_rbtree(int dummy)
13559 : {
13560 1 : struct db_context *db;
13561 1 : bool ret = false;
13562 1 : int i;
13563 1 : NTSTATUS status;
13564 1 : int count = 0;
13565 1 : int count2 = 0;
13566 :
13567 1 : db = db_open_rbt(NULL);
13568 :
13569 1 : if (db == NULL) {
13570 0 : d_fprintf(stderr, "db_open_rbt failed\n");
13571 0 : return false;
13572 : }
13573 :
13574 1 : if (!rbt_testflags(db, "firstkey", "firstval")) {
13575 0 : goto done;
13576 : }
13577 :
13578 1000 : for (i = 0; i < 999; i++) {
13579 999 : char key[sizeof("key-9223372036854775807")];
13580 999 : char value[sizeof("value-9223372036854775807")];
13581 :
13582 999 : snprintf(key, sizeof(key), "key%ld", random());
13583 999 : snprintf(value, sizeof(value) ,"value%ld", random());
13584 :
13585 999 : if (!rbt_testval(db, key, value)) {
13586 0 : goto done;
13587 : }
13588 :
13589 999 : snprintf(value, sizeof(value) ,"value%ld", random());
13590 :
13591 999 : if (!rbt_testval(db, key, value)) {
13592 0 : goto done;
13593 : }
13594 : }
13595 :
13596 1 : ret = true;
13597 1 : count = 0; count2 = 0;
13598 1 : status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13599 : &count2, &count);
13600 1 : printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13601 1 : if ((count != count2) || (count != 1000)) {
13602 0 : ret = false;
13603 : }
13604 1 : count = 0; count2 = 0;
13605 1 : status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13606 : &count2, &count);
13607 1 : printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13608 1 : if ((count != count2) || (count != 1000)) {
13609 0 : ret = false;
13610 : }
13611 1 : count = 0; count2 = 0;
13612 1 : status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13613 : &count2, &count);
13614 1 : printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13615 1 : if ((count != count2) || (count != 0)) {
13616 0 : ret = false;
13617 : }
13618 :
13619 1 : done:
13620 1 : TALLOC_FREE(db);
13621 1 : return ret;
13622 : }
13623 :
13624 :
13625 : /*
13626 : local test for character set functions
13627 :
13628 : This is a very simple test for the functionality in convert_string_error()
13629 : */
13630 1 : static bool run_local_convert_string(int dummy)
13631 : {
13632 1 : TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13633 1 : const char *test_strings[2] = { "March", "M\303\244rz" };
13634 1 : char dst[7];
13635 1 : int i;
13636 :
13637 3 : for (i=0; i<2; i++) {
13638 2 : const char *str = test_strings[i];
13639 2 : int len = strlen(str);
13640 2 : size_t converted_size;
13641 2 : bool ret;
13642 :
13643 2 : memset(dst, 'X', sizeof(dst));
13644 :
13645 : /* first try with real source length */
13646 2 : ret = convert_string_error(CH_UNIX, CH_UTF8,
13647 : str, len,
13648 : dst, sizeof(dst),
13649 : &converted_size);
13650 2 : if (ret != true) {
13651 0 : d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13652 0 : goto failed;
13653 : }
13654 :
13655 2 : if (converted_size != len) {
13656 0 : d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13657 : str, len, (int)converted_size);
13658 0 : goto failed;
13659 : }
13660 :
13661 2 : if (strncmp(str, dst, converted_size) != 0) {
13662 0 : d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13663 0 : goto failed;
13664 : }
13665 :
13666 2 : if (strlen(str) != converted_size) {
13667 0 : d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13668 0 : (int)strlen(str), (int)converted_size);
13669 0 : goto failed;
13670 : }
13671 :
13672 2 : if (dst[converted_size] != 'X') {
13673 0 : d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13674 0 : goto failed;
13675 : }
13676 :
13677 : /* now with srclen==-1, this causes the nul to be
13678 : * converted too */
13679 2 : ret = convert_string_error(CH_UNIX, CH_UTF8,
13680 : str, -1,
13681 : dst, sizeof(dst),
13682 : &converted_size);
13683 2 : if (ret != true) {
13684 0 : d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13685 0 : goto failed;
13686 : }
13687 :
13688 2 : if (converted_size != len+1) {
13689 0 : d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13690 : str, len, (int)converted_size);
13691 0 : goto failed;
13692 : }
13693 :
13694 2 : if (strncmp(str, dst, converted_size) != 0) {
13695 0 : d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13696 0 : goto failed;
13697 : }
13698 :
13699 2 : if (len+1 != converted_size) {
13700 0 : d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13701 : len+1, (int)converted_size);
13702 0 : goto failed;
13703 : }
13704 :
13705 2 : if (dst[converted_size] != 'X') {
13706 0 : d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13707 0 : goto failed;
13708 : }
13709 :
13710 : }
13711 :
13712 :
13713 1 : TALLOC_FREE(tmp_ctx);
13714 0 : return true;
13715 0 : failed:
13716 0 : TALLOC_FREE(tmp_ctx);
13717 0 : return false;
13718 : }
13719 :
13720 1 : static bool run_local_string_to_sid(int dummy) {
13721 1 : struct dom_sid sid;
13722 :
13723 1 : if (string_to_sid(&sid, "S--1-5-32-545")) {
13724 0 : printf("allowing S--1-5-32-545\n");
13725 0 : return false;
13726 : }
13727 1 : if (string_to_sid(&sid, "S-1-5-32-+545")) {
13728 0 : printf("allowing S-1-5-32-+545\n");
13729 0 : return false;
13730 : }
13731 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")) {
13732 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");
13733 0 : return false;
13734 : }
13735 1 : if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13736 0 : printf("allowing S-1-5-32-545-abc\n");
13737 0 : return false;
13738 : }
13739 1 : if (string_to_sid(&sid, "S-300-5-32-545")) {
13740 0 : printf("allowing S-300-5-32-545\n");
13741 0 : return false;
13742 : }
13743 1 : if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13744 0 : printf("allowing S-1-0xfffffffffffffe-32-545\n");
13745 0 : return false;
13746 : }
13747 1 : if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13748 0 : printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13749 0 : return false;
13750 : }
13751 1 : if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13752 0 : printf("could not parse S-1-0xfffffffffffe-32-545\n");
13753 0 : return false;
13754 : }
13755 1 : if (!string_to_sid(&sid, "S-1-5-32-545")) {
13756 0 : printf("could not parse S-1-5-32-545\n");
13757 0 : return false;
13758 : }
13759 1 : if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13760 0 : struct dom_sid_buf buf;
13761 0 : printf("mis-parsed S-1-5-32-545 as %s\n",
13762 : dom_sid_str_buf(&sid, &buf));
13763 0 : return false;
13764 : }
13765 0 : return true;
13766 : }
13767 :
13768 3 : static bool sid_to_string_test(const char *expected) {
13769 3 : char *str;
13770 3 : bool res = true;
13771 3 : struct dom_sid sid;
13772 :
13773 3 : if (!string_to_sid(&sid, expected)) {
13774 0 : printf("could not parse %s\n", expected);
13775 0 : return false;
13776 : }
13777 :
13778 3 : str = dom_sid_string(NULL, &sid);
13779 3 : if (strcmp(str, expected)) {
13780 0 : printf("Comparison failed (%s != %s)\n", str, expected);
13781 0 : res = false;
13782 : }
13783 3 : TALLOC_FREE(str);
13784 3 : return res;
13785 : }
13786 :
13787 1 : static bool run_local_sid_to_string(int dummy) {
13788 1 : if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13789 0 : return false;
13790 1 : if (!sid_to_string_test("S-1-545"))
13791 0 : return false;
13792 1 : if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13793 0 : return false;
13794 0 : return true;
13795 : }
13796 :
13797 1 : static bool run_local_binary_to_sid(int dummy) {
13798 1 : ssize_t ret;
13799 1 : struct dom_sid *sid = talloc(NULL, struct dom_sid);
13800 1 : static const uint8_t good_binary_sid[] = {
13801 : 0x1, /* revision number */
13802 : 15, /* num auths */
13803 : 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13804 : 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13805 : 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13806 : 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13807 : 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13808 : 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13809 : 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13810 : 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13811 : 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13812 : 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13813 : 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13814 : 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13815 : 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13816 : 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13817 : 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13818 : 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13819 : };
13820 :
13821 1 : static const uint8_t long_binary_sid[] = {
13822 : 0x1, /* revision number */
13823 : 15, /* num auths */
13824 : 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13825 : 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13826 : 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13827 : 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13828 : 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13829 : 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13830 : 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13831 : 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13832 : 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13833 : 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13834 : 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13835 : 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13836 : 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13837 : 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13838 : 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13839 : 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13840 : 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13841 : 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13842 : 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13843 : };
13844 :
13845 1 : static const uint8_t long_binary_sid2[] = {
13846 : 0x1, /* revision number */
13847 : 32, /* num auths */
13848 : 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13849 : 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13850 : 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13851 : 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13852 : 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13853 : 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13854 : 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13855 : 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13856 : 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13857 : 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13858 : 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13859 : 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13860 : 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13861 : 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13862 : 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13863 : 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13864 : 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13865 : 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13866 : 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13867 : 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13868 : 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13869 : 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13870 : 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13871 : 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13872 : 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13873 : 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13874 : 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13875 : 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13876 : 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13877 : 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13878 : 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13879 : 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13880 : 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13881 : };
13882 :
13883 1 : ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13884 1 : if (ret == -1) {
13885 0 : return false;
13886 : }
13887 1 : ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13888 1 : if (ret != -1) {
13889 0 : return false;
13890 : }
13891 1 : ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13892 1 : if (ret != -1) {
13893 0 : return false;
13894 : }
13895 0 : return true;
13896 : }
13897 :
13898 : /* Split a path name into filename and stream name components. Canonicalise
13899 : * such that an implicit $DATA token is always explicit.
13900 : *
13901 : * The "specification" of this function can be found in the
13902 : * run_local_stream_name() function in torture.c, I've tried those
13903 : * combinations against a W2k3 server.
13904 : */
13905 :
13906 8 : static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13907 : char **pbase, char **pstream)
13908 : {
13909 8 : char *base = NULL;
13910 8 : char *stream = NULL;
13911 8 : char *sname; /* stream name */
13912 8 : const char *stype; /* stream type */
13913 :
13914 8 : DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13915 :
13916 8 : sname = strchr_m(fname, ':');
13917 :
13918 8 : if (sname == NULL) {
13919 1 : if (pbase != NULL) {
13920 1 : base = talloc_strdup(mem_ctx, fname);
13921 1 : NT_STATUS_HAVE_NO_MEMORY(base);
13922 : }
13923 1 : goto done;
13924 : }
13925 :
13926 7 : if (pbase != NULL) {
13927 7 : base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13928 7 : NT_STATUS_HAVE_NO_MEMORY(base);
13929 : }
13930 :
13931 7 : sname += 1;
13932 :
13933 7 : stype = strchr_m(sname, ':');
13934 :
13935 7 : if (stype == NULL) {
13936 2 : sname = talloc_strdup(mem_ctx, sname);
13937 2 : stype = "$DATA";
13938 : }
13939 : else {
13940 5 : if (strcasecmp_m(stype, ":$DATA") != 0) {
13941 : /*
13942 : * If there is an explicit stream type, so far we only
13943 : * allow $DATA. Is there anything else allowed? -- vl
13944 : */
13945 3 : DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13946 3 : TALLOC_FREE(base);
13947 3 : return NT_STATUS_OBJECT_NAME_INVALID;
13948 : }
13949 2 : sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13950 2 : stype += 1;
13951 : }
13952 :
13953 4 : if (sname == NULL) {
13954 0 : TALLOC_FREE(base);
13955 0 : return NT_STATUS_NO_MEMORY;
13956 : }
13957 :
13958 4 : if (sname[0] == '\0') {
13959 : /*
13960 : * no stream name, so no stream
13961 : */
13962 1 : goto done;
13963 : }
13964 :
13965 3 : if (pstream != NULL) {
13966 3 : stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13967 3 : if (stream == NULL) {
13968 0 : TALLOC_FREE(sname);
13969 0 : TALLOC_FREE(base);
13970 0 : return NT_STATUS_NO_MEMORY;
13971 : }
13972 : /*
13973 : * upper-case the type field
13974 : */
13975 3 : (void)strupper_m(strchr_m(stream, ':')+1);
13976 : }
13977 :
13978 0 : done:
13979 5 : if (pbase != NULL) {
13980 5 : *pbase = base;
13981 : }
13982 5 : if (pstream != NULL) {
13983 5 : *pstream = stream;
13984 : }
13985 5 : return NT_STATUS_OK;
13986 : }
13987 :
13988 8 : static bool test_stream_name(const char *fname, const char *expected_base,
13989 : const char *expected_stream,
13990 : NTSTATUS expected_status)
13991 : {
13992 8 : NTSTATUS status;
13993 8 : char *base = NULL;
13994 8 : char *stream = NULL;
13995 :
13996 8 : status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13997 8 : if (!NT_STATUS_EQUAL(status, expected_status)) {
13998 0 : goto error;
13999 : }
14000 :
14001 8 : if (!NT_STATUS_IS_OK(status)) {
14002 0 : return true;
14003 : }
14004 :
14005 5 : if (base == NULL) goto error;
14006 :
14007 5 : if (strcmp(expected_base, base) != 0) goto error;
14008 :
14009 5 : if ((expected_stream != NULL) && (stream == NULL)) goto error;
14010 5 : if ((expected_stream == NULL) && (stream != NULL)) goto error;
14011 :
14012 5 : if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
14013 0 : goto error;
14014 :
14015 5 : TALLOC_FREE(base);
14016 5 : TALLOC_FREE(stream);
14017 0 : return true;
14018 :
14019 0 : error:
14020 0 : d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
14021 : fname, expected_base ? expected_base : "<NULL>",
14022 : expected_stream ? expected_stream : "<NULL>",
14023 : nt_errstr(expected_status));
14024 0 : d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
14025 0 : base ? base : "<NULL>", stream ? stream : "<NULL>",
14026 : nt_errstr(status));
14027 0 : TALLOC_FREE(base);
14028 0 : TALLOC_FREE(stream);
14029 0 : return false;
14030 : }
14031 :
14032 1 : static bool run_local_stream_name(int dummy)
14033 : {
14034 1 : bool ret = true;
14035 :
14036 2 : ret &= test_stream_name(
14037 1 : "bla", "bla", NULL, NT_STATUS_OK);
14038 2 : ret &= test_stream_name(
14039 1 : "bla::$DATA", "bla", NULL, NT_STATUS_OK);
14040 2 : ret &= test_stream_name(
14041 1 : "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14042 2 : ret &= test_stream_name(
14043 1 : "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
14044 2 : ret &= test_stream_name(
14045 1 : "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14046 2 : ret &= test_stream_name(
14047 1 : "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
14048 2 : ret &= test_stream_name(
14049 1 : "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
14050 2 : ret &= test_stream_name(
14051 1 : "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
14052 :
14053 1 : return ret;
14054 : }
14055 :
14056 2 : static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
14057 : {
14058 2 : if (a.length != b.length) {
14059 0 : printf("a.length=%d != b.length=%d\n",
14060 0 : (int)a.length, (int)b.length);
14061 0 : return false;
14062 : }
14063 2 : if (memcmp(a.data, b.data, a.length) != 0) {
14064 0 : printf("a.data and b.data differ\n");
14065 0 : return false;
14066 : }
14067 0 : return true;
14068 : }
14069 :
14070 1 : static bool run_local_memcache(int dummy)
14071 : {
14072 1 : struct memcache *cache;
14073 1 : DATA_BLOB k1, k2, k3, k4, k5;
14074 1 : DATA_BLOB d1, d3;
14075 1 : DATA_BLOB v1, v3;
14076 :
14077 1 : TALLOC_CTX *mem_ctx;
14078 1 : char *ptr1 = NULL;
14079 1 : char *ptr2 = NULL;
14080 1 : char *ptr3 = NULL;
14081 :
14082 1 : char *str1, *str2;
14083 1 : size_t size1, size2;
14084 1 : bool ret = false;
14085 :
14086 1 : mem_ctx = talloc_init("foo");
14087 1 : if (mem_ctx == NULL) {
14088 0 : return false;
14089 : }
14090 :
14091 : /* STAT_CACHE TESTS */
14092 :
14093 1 : cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14094 :
14095 1 : if (cache == NULL) {
14096 0 : printf("memcache_init failed\n");
14097 0 : return false;
14098 : }
14099 :
14100 1 : d1 = data_blob_const("d1", 2);
14101 1 : d3 = data_blob_const("d3", 2);
14102 :
14103 1 : k1 = data_blob_const("d1", 2);
14104 1 : k2 = data_blob_const("d2", 2);
14105 1 : k3 = data_blob_const("d3", 2);
14106 1 : k4 = data_blob_const("d4", 2);
14107 1 : k5 = data_blob_const("d5", 2);
14108 :
14109 1 : memcache_add(cache, STAT_CACHE, k1, d1);
14110 :
14111 1 : if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
14112 0 : printf("could not find k1\n");
14113 0 : return false;
14114 : }
14115 1 : if (!data_blob_equal(d1, v1)) {
14116 0 : return false;
14117 : }
14118 :
14119 1 : memcache_add(cache, STAT_CACHE, k1, d3);
14120 :
14121 1 : if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
14122 0 : printf("could not find replaced k1\n");
14123 0 : return false;
14124 : }
14125 1 : if (!data_blob_equal(d3, v3)) {
14126 0 : return false;
14127 : }
14128 :
14129 1 : TALLOC_FREE(cache);
14130 :
14131 : /* GETWD_CACHE TESTS */
14132 1 : str1 = talloc_strdup(mem_ctx, "string1");
14133 1 : if (str1 == NULL) {
14134 0 : return false;
14135 : }
14136 1 : ptr2 = str1; /* Keep an alias for comparison. */
14137 :
14138 1 : str2 = talloc_strdup(mem_ctx, "string2");
14139 1 : if (str2 == NULL) {
14140 0 : return false;
14141 : }
14142 :
14143 1 : cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14144 1 : if (cache == NULL) {
14145 0 : printf("memcache_init failed\n");
14146 0 : return false;
14147 : }
14148 :
14149 1 : memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14150 : /* str1 == NULL now. */
14151 1 : ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14152 1 : if (ptr1 == NULL) {
14153 0 : printf("could not find k2\n");
14154 0 : return false;
14155 : }
14156 1 : if (ptr1 != ptr2) {
14157 0 : printf("fetch of k2 got wrong string\n");
14158 0 : return false;
14159 : }
14160 :
14161 : /* Add a blob to ensure k2 gets purged. */
14162 1 : d3 = data_blob_talloc_zero(mem_ctx, 180);
14163 1 : memcache_add(cache, STAT_CACHE, k3, d3);
14164 :
14165 1 : ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14166 1 : if (ptr2 != NULL) {
14167 0 : printf("Did find k2, should have been purged\n");
14168 0 : return false;
14169 : }
14170 :
14171 : /*
14172 : * Test that talloc size also is accounted in memcache and
14173 : * causes purge of other object.
14174 : */
14175 :
14176 1 : str1 = talloc_zero_size(mem_ctx, 100);
14177 1 : str2 = talloc_zero_size(mem_ctx, 100);
14178 :
14179 1 : memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14180 1 : memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14181 :
14182 1 : ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14183 1 : if (ptr3 != NULL) {
14184 0 : printf("Did find k4, should have been purged\n");
14185 0 : return false;
14186 : }
14187 :
14188 : /*
14189 : * Test that adding a duplicate non-talloced
14190 : * key/value on top of a talloced key/value takes account
14191 : * of the talloc_freed value size.
14192 : */
14193 1 : TALLOC_FREE(cache);
14194 1 : TALLOC_FREE(mem_ctx);
14195 :
14196 1 : mem_ctx = talloc_init("key_replace");
14197 1 : if (mem_ctx == 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 : return false;
14204 : }
14205 :
14206 : /*
14207 : * Add a 100 byte talloced string. This will
14208 : * store a (4 or 8 byte) pointer and record the
14209 : * total talloced size.
14210 : */
14211 1 : str1 = talloc_zero_size(mem_ctx, 100);
14212 1 : memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14213 : /*
14214 : * Now overwrite with a small talloced
14215 : * value. This should fit in the existing size
14216 : * and the total talloced size should be removed
14217 : * from the cache size.
14218 : */
14219 1 : str1 = talloc_zero_size(mem_ctx, 2);
14220 1 : memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14221 : /*
14222 : * Now store a 20 byte string. If the
14223 : * total talloced size wasn't accounted for
14224 : * and removed in the overwrite, then this
14225 : * will evict k4.
14226 : */
14227 1 : str2 = talloc_zero_size(mem_ctx, 20);
14228 1 : memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14229 :
14230 1 : ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14231 1 : if (ptr3 == NULL) {
14232 0 : printf("Did not find k4, should not have been purged\n");
14233 0 : return false;
14234 : }
14235 :
14236 1 : TALLOC_FREE(cache);
14237 1 : TALLOC_FREE(mem_ctx);
14238 :
14239 1 : mem_ctx = talloc_init("foo");
14240 1 : if (mem_ctx == NULL) {
14241 0 : return false;
14242 : }
14243 :
14244 1 : cache = memcache_init(NULL, 0);
14245 1 : if (cache == NULL) {
14246 0 : return false;
14247 : }
14248 :
14249 1 : str1 = talloc_strdup(mem_ctx, "string1");
14250 1 : if (str1 == NULL) {
14251 0 : return false;
14252 : }
14253 1 : str2 = talloc_strdup(mem_ctx, "string2");
14254 1 : if (str2 == NULL) {
14255 0 : return false;
14256 : }
14257 1 : memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14258 : data_blob_string_const("torture"), &str1);
14259 1 : size1 = talloc_total_size(cache);
14260 :
14261 1 : memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14262 : data_blob_string_const("torture"), &str2);
14263 1 : size2 = talloc_total_size(cache);
14264 :
14265 1 : printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14266 :
14267 1 : if (size2 > size1) {
14268 0 : printf("memcache leaks memory!\n");
14269 0 : goto fail;
14270 : }
14271 :
14272 0 : ret = true;
14273 1 : fail:
14274 1 : TALLOC_FREE(cache);
14275 1 : return ret;
14276 : }
14277 :
14278 200 : static void wbclient_done(struct tevent_req *req)
14279 : {
14280 0 : wbcErr wbc_err;
14281 0 : struct winbindd_response *wb_resp;
14282 200 : int *i = (int *)tevent_req_callback_data_void(req);
14283 :
14284 200 : wbc_err = wb_trans_recv(req, req, &wb_resp);
14285 200 : TALLOC_FREE(req);
14286 200 : *i += 1;
14287 200 : d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14288 200 : }
14289 :
14290 2 : static bool run_wbclient_multi_ping(int dummy)
14291 : {
14292 0 : struct tevent_context *ev;
14293 0 : struct wb_context **wb_ctx;
14294 0 : struct winbindd_request wb_req;
14295 2 : bool result = false;
14296 0 : int i, j;
14297 :
14298 2 : BlockSignals(True, SIGPIPE);
14299 :
14300 2 : ev = tevent_context_init(talloc_tos());
14301 2 : if (ev == NULL) {
14302 0 : goto fail;
14303 : }
14304 :
14305 2 : wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14306 2 : if (wb_ctx == NULL) {
14307 0 : goto fail;
14308 : }
14309 :
14310 2 : ZERO_STRUCT(wb_req);
14311 2 : wb_req.cmd = WINBINDD_PING;
14312 :
14313 2 : d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14314 :
14315 4 : for (i=0; i<torture_nprocs; i++) {
14316 2 : wb_ctx[i] = wb_context_init(ev, NULL);
14317 2 : if (wb_ctx[i] == NULL) {
14318 0 : goto fail;
14319 : }
14320 202 : for (j=0; j<torture_numops; j++) {
14321 0 : struct tevent_req *req;
14322 200 : req = wb_trans_send(ev, ev, wb_ctx[i],
14323 200 : (j % 2) == 0, &wb_req);
14324 200 : if (req == NULL) {
14325 0 : goto fail;
14326 : }
14327 200 : tevent_req_set_callback(req, wbclient_done, &i);
14328 : }
14329 : }
14330 :
14331 2 : i = 0;
14332 :
14333 818 : while (i < torture_nprocs * torture_numops) {
14334 816 : tevent_loop_once(ev);
14335 : }
14336 :
14337 2 : result = true;
14338 2 : fail:
14339 2 : TALLOC_FREE(ev);
14340 2 : return result;
14341 : }
14342 :
14343 0 : static bool dbtrans_inc(struct db_context *db)
14344 : {
14345 0 : struct db_record *rec;
14346 0 : uint32_t val;
14347 0 : bool ret = false;
14348 0 : NTSTATUS status;
14349 0 : TDB_DATA value;
14350 :
14351 0 : rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14352 0 : if (rec == NULL) {
14353 0 : printf(__location__ "fetch_lock failed\n");
14354 0 : return false;
14355 : }
14356 :
14357 0 : value = dbwrap_record_get_value(rec);
14358 :
14359 0 : if (value.dsize != sizeof(uint32_t)) {
14360 0 : printf(__location__ "value.dsize = %d\n",
14361 0 : (int)value.dsize);
14362 0 : goto fail;
14363 : }
14364 :
14365 0 : memcpy(&val, value.dptr, sizeof(val));
14366 0 : val += 1;
14367 :
14368 0 : status = dbwrap_record_store(
14369 : rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14370 0 : if (!NT_STATUS_IS_OK(status)) {
14371 0 : printf(__location__ "store failed: %s\n",
14372 : nt_errstr(status));
14373 0 : goto fail;
14374 : }
14375 :
14376 0 : ret = true;
14377 0 : fail:
14378 0 : TALLOC_FREE(rec);
14379 0 : return ret;
14380 : }
14381 :
14382 0 : static bool run_local_dbtrans(int dummy)
14383 : {
14384 0 : struct db_context *db;
14385 0 : struct db_record *rec;
14386 0 : NTSTATUS status;
14387 0 : uint32_t initial;
14388 0 : int res;
14389 0 : TDB_DATA value;
14390 :
14391 0 : db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14392 : O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14393 : DBWRAP_FLAG_NONE);
14394 0 : if (db == NULL) {
14395 0 : printf("Could not open transtest.db\n");
14396 0 : return false;
14397 : }
14398 :
14399 0 : res = dbwrap_transaction_start(db);
14400 0 : if (res != 0) {
14401 0 : printf(__location__ "transaction_start failed\n");
14402 0 : return false;
14403 : }
14404 :
14405 0 : rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14406 0 : if (rec == NULL) {
14407 0 : printf(__location__ "fetch_lock failed\n");
14408 0 : return false;
14409 : }
14410 :
14411 0 : value = dbwrap_record_get_value(rec);
14412 :
14413 0 : if (value.dptr == NULL) {
14414 0 : initial = 0;
14415 0 : status = dbwrap_record_store(
14416 : rec, make_tdb_data((uint8_t *)&initial,
14417 : sizeof(initial)),
14418 : 0);
14419 0 : if (!NT_STATUS_IS_OK(status)) {
14420 0 : printf(__location__ "store returned %s\n",
14421 : nt_errstr(status));
14422 0 : return false;
14423 : }
14424 : }
14425 :
14426 0 : TALLOC_FREE(rec);
14427 :
14428 0 : res = dbwrap_transaction_commit(db);
14429 0 : if (res != 0) {
14430 0 : printf(__location__ "transaction_commit failed\n");
14431 0 : return false;
14432 : }
14433 :
14434 0 : while (true) {
14435 0 : uint32_t val, val2;
14436 0 : int i;
14437 :
14438 0 : res = dbwrap_transaction_start(db);
14439 0 : if (res != 0) {
14440 0 : printf(__location__ "transaction_start failed\n");
14441 0 : break;
14442 : }
14443 :
14444 0 : status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14445 0 : if (!NT_STATUS_IS_OK(status)) {
14446 0 : printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14447 : nt_errstr(status));
14448 0 : break;
14449 : }
14450 :
14451 0 : for (i=0; i<10; i++) {
14452 0 : if (!dbtrans_inc(db)) {
14453 0 : return false;
14454 : }
14455 : }
14456 :
14457 0 : status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14458 0 : if (!NT_STATUS_IS_OK(status)) {
14459 0 : printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14460 : nt_errstr(status));
14461 0 : break;
14462 : }
14463 :
14464 0 : if (val2 != val + 10) {
14465 0 : printf(__location__ "val=%d, val2=%d\n",
14466 : (int)val, (int)val2);
14467 0 : break;
14468 : }
14469 :
14470 0 : printf("val2=%d\r", val2);
14471 :
14472 0 : res = dbwrap_transaction_commit(db);
14473 0 : if (res != 0) {
14474 0 : printf(__location__ "transaction_commit failed\n");
14475 0 : break;
14476 : }
14477 : }
14478 :
14479 0 : TALLOC_FREE(db);
14480 0 : return true;
14481 : }
14482 :
14483 : /*
14484 : * Just a dummy test to be run under a debugger. There's no real way
14485 : * to inspect the tevent_poll specific function from outside of
14486 : * tevent_poll.c.
14487 : */
14488 :
14489 1 : static bool run_local_tevent_poll(int dummy)
14490 : {
14491 1 : struct tevent_context *ev;
14492 1 : struct tevent_fd *fd1, *fd2;
14493 1 : bool result = false;
14494 :
14495 1 : ev = tevent_context_init_byname(NULL, "poll");
14496 1 : if (ev == NULL) {
14497 0 : d_fprintf(stderr, "tevent_context_init_byname failed\n");
14498 0 : goto fail;
14499 : }
14500 :
14501 1 : fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14502 1 : if (fd1 == NULL) {
14503 0 : d_fprintf(stderr, "tevent_add_fd failed\n");
14504 0 : goto fail;
14505 : }
14506 1 : fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14507 1 : if (fd2 == NULL) {
14508 0 : d_fprintf(stderr, "tevent_add_fd failed\n");
14509 0 : goto fail;
14510 : }
14511 1 : TALLOC_FREE(fd2);
14512 :
14513 1 : fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14514 1 : if (fd2 == NULL) {
14515 0 : d_fprintf(stderr, "tevent_add_fd failed\n");
14516 0 : goto fail;
14517 : }
14518 :
14519 0 : result = true;
14520 1 : fail:
14521 1 : TALLOC_FREE(ev);
14522 1 : return result;
14523 : }
14524 :
14525 1 : static bool run_local_hex_encode_buf(int dummy)
14526 : {
14527 1 : char buf[17];
14528 1 : uint8_t src[8];
14529 1 : size_t i;
14530 :
14531 9 : for (i=0; i<sizeof(src); i++) {
14532 8 : src[i] = i;
14533 : }
14534 1 : hex_encode_buf(buf, src, sizeof(src));
14535 1 : if (strcmp(buf, "0001020304050607") != 0) {
14536 0 : return false;
14537 : }
14538 1 : hex_encode_buf(buf, NULL, 0);
14539 1 : if (buf[0] != '\0') {
14540 0 : return false;
14541 : }
14542 0 : return true;
14543 : }
14544 :
14545 : static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14546 : "0.0.0.0",
14547 : "::0",
14548 : "1.2.3.1",
14549 : "0.0.0.0",
14550 : "0.0.0.0",
14551 : "1.2.3.2",
14552 : "1.2.3.3",
14553 : "1.2.3.4",
14554 : "1.2.3.5",
14555 : "::0",
14556 : "1.2.3.6",
14557 : "1.2.3.7",
14558 : "::0",
14559 : "::0",
14560 : "::0",
14561 : "1.2.3.8",
14562 : "1.2.3.9",
14563 : "1.2.3.10",
14564 : "1.2.3.11",
14565 : "1.2.3.12",
14566 : "1.2.3.13",
14567 : "1001:1111:1111:1000:0:1111:1111:1111",
14568 : "1.2.3.1",
14569 : "1.2.3.2",
14570 : "1.2.3.3",
14571 : "1.2.3.12",
14572 : "::0",
14573 : "::0"
14574 : };
14575 :
14576 : static const char *remove_duplicate_addrs2_test_strings_result[] = {
14577 : "1.2.3.1",
14578 : "1.2.3.2",
14579 : "1.2.3.3",
14580 : "1.2.3.4",
14581 : "1.2.3.5",
14582 : "1.2.3.6",
14583 : "1.2.3.7",
14584 : "1.2.3.8",
14585 : "1.2.3.9",
14586 : "1.2.3.10",
14587 : "1.2.3.11",
14588 : "1.2.3.12",
14589 : "1.2.3.13",
14590 : "1001:1111:1111:1000:0:1111:1111:1111"
14591 : };
14592 :
14593 1 : static bool run_local_remove_duplicate_addrs2(int dummy)
14594 : {
14595 1 : struct samba_sockaddr test_vector[28];
14596 1 : size_t count, i;
14597 :
14598 : /* Construct the sockaddr_storage test vector. */
14599 29 : for (i = 0; i < 28; i++) {
14600 28 : struct addrinfo hints;
14601 28 : struct addrinfo *res = NULL;
14602 28 : int ret;
14603 :
14604 28 : memset(&hints, '\0', sizeof(hints));
14605 28 : hints.ai_flags = AI_NUMERICHOST;
14606 28 : ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14607 : NULL,
14608 : &hints,
14609 : &res);
14610 28 : if (ret) {
14611 0 : fprintf(stderr, "getaddrinfo failed on [%s]\n",
14612 : remove_duplicate_addrs2_test_strings_vector[i]);
14613 0 : return false;
14614 : }
14615 28 : memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14616 28 : memcpy(&test_vector[i].u.ss,
14617 28 : res->ai_addr,
14618 28 : res->ai_addrlen);
14619 28 : freeaddrinfo(res);
14620 : }
14621 :
14622 1 : count = remove_duplicate_addrs2(test_vector, i);
14623 :
14624 1 : if (count != 14) {
14625 0 : fprintf(stderr, "count wrong (%zu) should be 14\n",
14626 : count);
14627 0 : return false;
14628 : }
14629 :
14630 15 : for (i = 0; i < count; i++) {
14631 14 : char addr[INET6_ADDRSTRLEN];
14632 :
14633 14 : print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14634 :
14635 14 : if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14636 0 : fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14637 : i,
14638 : addr,
14639 : remove_duplicate_addrs2_test_strings_result[i]);
14640 0 : return false;
14641 : }
14642 : }
14643 :
14644 1 : printf("run_local_remove_duplicate_addrs2: success\n");
14645 1 : return true;
14646 : }
14647 :
14648 0 : static bool run_local_tdb_opener(int dummy)
14649 : {
14650 0 : TDB_CONTEXT *t;
14651 0 : unsigned v = 0;
14652 :
14653 0 : while (1) {
14654 0 : t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14655 : O_RDWR|O_CREAT, 0755);
14656 0 : if (t == NULL) {
14657 0 : perror("tdb_open failed");
14658 0 : return false;
14659 : }
14660 0 : tdb_close(t);
14661 :
14662 0 : v += 1;
14663 0 : printf("\r%u", v);
14664 : }
14665 : return true;
14666 : }
14667 :
14668 0 : static bool run_local_tdb_writer(int dummy)
14669 : {
14670 0 : TDB_CONTEXT *t;
14671 0 : unsigned v = 0;
14672 0 : TDB_DATA val;
14673 :
14674 0 : t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14675 0 : if (t == 0) {
14676 0 : perror("tdb_open failed");
14677 0 : return 1;
14678 : }
14679 :
14680 0 : val.dptr = (uint8_t *)&v;
14681 0 : val.dsize = sizeof(v);
14682 :
14683 0 : while (1) {
14684 0 : TDB_DATA data;
14685 0 : int ret;
14686 :
14687 0 : ret = tdb_store(t, val, val, 0);
14688 0 : if (ret != 0) {
14689 0 : printf("%s\n", tdb_errorstr(t));
14690 : }
14691 0 : v += 1;
14692 0 : printf("\r%u", v);
14693 :
14694 0 : data = tdb_fetch(t, val);
14695 0 : if (data.dptr != NULL) {
14696 0 : SAFE_FREE(data.dptr);
14697 : }
14698 : }
14699 : return true;
14700 : }
14701 :
14702 1 : static bool run_local_canonicalize_path(int dummy)
14703 : {
14704 1 : const char *src[] = {
14705 : "/foo/..",
14706 : "/..",
14707 : "/foo/bar/../baz",
14708 : "/foo/././",
14709 : "/../foo",
14710 : ".././././",
14711 : ".././././../../../boo",
14712 : "./..",
14713 : "/",
14714 : "/../../",
14715 : "/foo/../",
14716 : "/./././",
14717 : "/./././.",
14718 : "/.../././.",
14719 : "/./././.foo",
14720 : "/./././.foo.",
14721 : "/./././foo.",
14722 : "/foo/bar/..",
14723 : "/foo/bar/../baz/",
14724 : "////////////////",
14725 : "/////////./././././.",
14726 : "/./.././../.boo/../baz",
14727 : "/a/component/path",
14728 : "/a/component/path/",
14729 : "/a/component/path/..",
14730 : "/a/component/../path/",
14731 : "///a/./././///component/../////path/",
14732 : NULL
14733 : };
14734 1 : const char *dst[] = {
14735 : "/",
14736 : "/",
14737 : "/foo/baz",
14738 : "/foo",
14739 : "/foo",
14740 : "/",
14741 : "/boo",
14742 : "/",
14743 : "/",
14744 : "/",
14745 : "/",
14746 : "/",
14747 : "/",
14748 : "/...",
14749 : "/.foo",
14750 : "/.foo.",
14751 : "/foo.",
14752 : "/foo",
14753 : "/foo/baz",
14754 : "/",
14755 : "/",
14756 : "/baz",
14757 : "/a/component/path",
14758 : "/a/component/path",
14759 : "/a/component",
14760 : "/a/path",
14761 : "/a/path",
14762 : NULL
14763 : };
14764 1 : unsigned int i;
14765 :
14766 28 : for (i = 0; src[i] != NULL; i++) {
14767 27 : char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14768 27 : if (d == NULL) {
14769 0 : perror("talloc fail\n");
14770 0 : return false;
14771 : }
14772 27 : if (strcmp(d, dst[i]) != 0) {
14773 0 : d_fprintf(stderr,
14774 : "canonicalize mismatch %s -> %s != %s",
14775 : src[i], d, dst[i]);
14776 0 : return false;
14777 : }
14778 27 : talloc_free(d);
14779 : }
14780 0 : return true;
14781 : }
14782 : struct session_setup_nt1_truncated_state {
14783 : uint16_t vwv[13];
14784 : uint8_t bytes[20];
14785 : };
14786 :
14787 : static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq);
14788 :
14789 2 : static struct tevent_req *smb1_session_setup_nt1_truncated_send(
14790 : TALLOC_CTX *mem_ctx,
14791 : struct tevent_context *ev,
14792 : struct smbXcli_conn *conn)
14793 : {
14794 2 : uint16_t *vwv = NULL;
14795 2 : uint8_t *bytes = NULL;
14796 2 : const char *pass = "12345678";
14797 2 : const char *uname = "z";
14798 2 : struct session_setup_nt1_truncated_state *state = NULL;
14799 2 : struct tevent_req *req = NULL;
14800 2 : struct tevent_req *subreq = NULL;
14801 :
14802 2 : req = tevent_req_create(mem_ctx,
14803 : &state,
14804 : struct session_setup_nt1_truncated_state);
14805 2 : if (req == NULL) {
14806 0 : return NULL;
14807 : }
14808 2 : vwv = &state->vwv[0];
14809 2 : bytes = &state->bytes[0];
14810 :
14811 2 : SCVAL(vwv+0, 0, 0xff);
14812 2 : SCVAL(vwv+0, 1, 0);
14813 2 : SSVAL(vwv+1, 0, 0);
14814 2 : SSVAL(vwv+2, 0, 8192);
14815 2 : SSVAL(vwv+3, 0, 2);
14816 2 : SSVAL(vwv+4, 0, 1);
14817 2 : SIVAL(vwv+5, 0, 0);
14818 2 : SSVAL(vwv+7, 0, strlen(pass)); /* OEMPasswordLen */
14819 2 : SSVAL(vwv+8, 0, 0); /* UnicodePasswordLen */
14820 2 : SSVAL(vwv+9, 0, 0); /* reserved */
14821 2 : SSVAL(vwv+10, 0, 0); /* reserved */
14822 2 : SIVAL(vwv+11, 0, CAP_STATUS32);
14823 :
14824 2 : memcpy(bytes, pass, strlen(pass));
14825 2 : bytes += strlen(pass);
14826 2 : memcpy(bytes, uname, strlen(uname)+1);
14827 :
14828 2 : subreq = smb1cli_req_send(state, ev, conn,
14829 : SMBsesssetupX,
14830 : 0, /* additional_flags */
14831 : 0, /* clear_flags */
14832 : 0, /* additional_flags2 */
14833 : 0, /* clear_flags2 */
14834 : 10000, /* timeout_msec */
14835 2 : getpid(),
14836 : NULL, /* tcon */
14837 : NULL, /* session */
14838 : 13, /* wct */
14839 2 : state->vwv,
14840 2 : strlen(pass), /* Truncate length at password. */
14841 2 : state->bytes);
14842 2 : if (tevent_req_nomem(subreq, req)) {
14843 0 : return tevent_req_post(req, ev);
14844 : }
14845 2 : tevent_req_set_callback(subreq,
14846 : smb1_session_setup_nt1_truncated_done,
14847 : req);
14848 2 : return req;
14849 : }
14850 :
14851 2 : static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq)
14852 : {
14853 0 : struct tevent_req *req =
14854 2 : tevent_req_callback_data(subreq,
14855 : struct tevent_req);
14856 0 : struct session_setup_nt1_truncated_state *state =
14857 2 : tevent_req_data(req,
14858 : struct session_setup_nt1_truncated_state);
14859 0 : NTSTATUS status;
14860 2 : struct smb1cli_req_expected_response expected[] = {
14861 : {
14862 : .status = NT_STATUS_OK,
14863 : .wct = 3,
14864 : },
14865 : };
14866 :
14867 2 : status = smb1cli_req_recv(subreq, state,
14868 : NULL,
14869 : NULL,
14870 : NULL,
14871 : NULL,
14872 : NULL, /* pvwv_offset */
14873 : NULL,
14874 : NULL,
14875 : NULL, /* pbytes_offset */
14876 : NULL,
14877 : expected, ARRAY_SIZE(expected));
14878 2 : TALLOC_FREE(subreq);
14879 2 : if (tevent_req_nterror(req, status)) {
14880 0 : return;
14881 : }
14882 2 : tevent_req_done(req);
14883 : }
14884 :
14885 2 : static NTSTATUS smb1_session_setup_nt1_truncated_recv(struct tevent_req *req)
14886 : {
14887 2 : return tevent_req_simple_recv_ntstatus(req);
14888 : }
14889 :
14890 2 : static bool run_smb1_truncated_sesssetup(int dummy)
14891 : {
14892 0 : struct tevent_context *ev;
14893 0 : struct tevent_req *req;
14894 0 : struct smbXcli_conn *conn;
14895 0 : struct sockaddr_storage ss;
14896 0 : NTSTATUS status;
14897 0 : int fd;
14898 0 : bool ok;
14899 :
14900 2 : printf("Starting send truncated SMB1 sesssetup.\n");
14901 :
14902 2 : ok = resolve_name(host, &ss, 0x20, true);
14903 2 : if (!ok) {
14904 0 : d_fprintf(stderr, "Could not resolve name %s\n", host);
14905 0 : return false;
14906 : }
14907 :
14908 2 : status = open_socket_out(&ss, 445, 10000, &fd);
14909 2 : if (!NT_STATUS_IS_OK(status)) {
14910 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
14911 : nt_errstr(status));
14912 0 : return false;
14913 : }
14914 :
14915 2 : conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14916 : NULL, 0, NULL);
14917 2 : if (conn == NULL) {
14918 0 : d_fprintf(stderr, "smbXcli_conn_create failed\n");
14919 0 : return false;
14920 : }
14921 :
14922 2 : status = smbXcli_negprot(conn,
14923 : 0,
14924 : PROTOCOL_NT1,
14925 : PROTOCOL_NT1,
14926 : NULL,
14927 : NULL,
14928 : NULL);
14929 2 : if (!NT_STATUS_IS_OK(status)) {
14930 0 : d_fprintf(stderr, "smbXcli_negprot failed!\n");
14931 0 : return false;
14932 : }
14933 :
14934 2 : ev = samba_tevent_context_init(talloc_tos());
14935 2 : if (ev == NULL) {
14936 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
14937 0 : return false;
14938 : }
14939 :
14940 2 : req = smb1_session_setup_nt1_truncated_send(ev, ev, conn);
14941 2 : if (req == NULL) {
14942 0 : d_fprintf(stderr, "smb1_session_setup_nt1_truncated_send failed\n");
14943 0 : return false;
14944 : }
14945 :
14946 2 : ok = tevent_req_poll_ntstatus(req, ev, &status);
14947 2 : if (!ok) {
14948 0 : d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
14949 : nt_errstr(status));
14950 0 : return false;
14951 : }
14952 :
14953 2 : status = smb1_session_setup_nt1_truncated_recv(req);
14954 2 : if (!NT_STATUS_IS_OK(status)) {
14955 0 : d_fprintf(stderr, "smb1_session_setup_nt1_truncated_recv returned "
14956 : "%s, expected NT_STATUS_OK\n",
14957 : nt_errstr(status));
14958 0 : return false;
14959 : }
14960 :
14961 2 : TALLOC_FREE(conn);
14962 2 : return true;
14963 : }
14964 :
14965 : struct smb1_negotiate_exit_state {
14966 : int dummy;
14967 : };
14968 :
14969 : static void smb1_negotiate_exit_done(struct tevent_req *subreq);
14970 :
14971 4 : static struct tevent_req *smb1_negotiate_exit_send(
14972 : TALLOC_CTX *mem_ctx,
14973 : struct tevent_context *ev,
14974 : struct smbXcli_conn *conn)
14975 : {
14976 4 : struct smb1_negotiate_exit_state *state = NULL;
14977 4 : struct tevent_req *req = NULL;
14978 4 : struct tevent_req *subreq = NULL;
14979 :
14980 4 : req = tevent_req_create(mem_ctx,
14981 : &state,
14982 : struct smb1_negotiate_exit_state);
14983 4 : if (req == NULL) {
14984 0 : return NULL;
14985 : }
14986 4 : subreq = smb1cli_req_send(state, ev, conn,
14987 : SMBexit,
14988 : 0, /* additional_flags */
14989 : 0, /* clear_flags */
14990 : 0, /* additional_flags2 */
14991 : 0, /* clear_flags2 */
14992 : 10000, /* timeout_msec */
14993 4 : getpid(),
14994 : NULL, /* tcon */
14995 : NULL, /* session */
14996 : 0, /* wct */
14997 : NULL,
14998 : 0,
14999 : NULL);
15000 4 : if (tevent_req_nomem(subreq, req)) {
15001 0 : return tevent_req_post(req, ev);
15002 : }
15003 4 : tevent_req_set_callback(subreq,
15004 : smb1_negotiate_exit_done,
15005 : req);
15006 4 : return req;
15007 : }
15008 :
15009 4 : static void smb1_negotiate_exit_done(struct tevent_req *subreq)
15010 : {
15011 0 : struct tevent_req *req =
15012 4 : tevent_req_callback_data(subreq,
15013 : struct tevent_req);
15014 0 : struct smb1_negotiate_exit_state *state =
15015 4 : tevent_req_data(req,
15016 : struct smb1_negotiate_exit_state);
15017 0 : NTSTATUS status;
15018 4 : struct smb1cli_req_expected_response expected[] = {
15019 : {
15020 : .status = NT_STATUS_OK,
15021 : .wct = 0,
15022 : },
15023 : };
15024 :
15025 4 : status = smb1cli_req_recv(subreq, state,
15026 : NULL,
15027 : NULL,
15028 : NULL,
15029 : NULL,
15030 : NULL, /* pvwv_offset */
15031 : NULL,
15032 : NULL,
15033 : NULL, /* pbytes_offset */
15034 : NULL,
15035 : expected, ARRAY_SIZE(expected));
15036 4 : TALLOC_FREE(subreq);
15037 4 : if (tevent_req_nterror(req, status)) {
15038 4 : return;
15039 : }
15040 0 : tevent_req_done(req);
15041 : }
15042 :
15043 4 : static NTSTATUS smb1_negotiate_exit_recv(struct tevent_req *req)
15044 : {
15045 4 : return tevent_req_simple_recv_ntstatus(req);
15046 : }
15047 :
15048 4 : static bool do_smb1_exit(TALLOC_CTX *mem_ctx,
15049 : struct tevent_context *ev,
15050 : struct smbXcli_conn *conn)
15051 : {
15052 0 : struct tevent_req *req;
15053 0 : bool ok;
15054 0 : NTSTATUS status;
15055 4 : NTSTATUS expected_status = NT_STATUS_DOS(ERRSRV, ERRinvnid);;
15056 :
15057 4 : req = smb1_negotiate_exit_send(ev, ev, conn);
15058 4 : if (req == NULL) {
15059 0 : d_fprintf(stderr, "smb1_negotiate_exit_send failed\n");
15060 0 : return false;
15061 : }
15062 :
15063 4 : ok = tevent_req_poll_ntstatus(req, ev, &status);
15064 4 : if (!ok) {
15065 0 : d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
15066 : nt_errstr(status));
15067 0 : return false;
15068 : }
15069 :
15070 4 : status = smb1_negotiate_exit_recv(req);
15071 4 : if (!NT_STATUS_EQUAL(status, expected_status)) {
15072 0 : d_fprintf(stderr, "smb1_negotiate_exit_recv returned "
15073 : "%s, expected ERRSRV, ERRinvnid\n",
15074 : nt_errstr(status));
15075 0 : return false;
15076 : }
15077 4 : return true;
15078 : }
15079 :
15080 2 : static bool run_smb1_negotiate_exit(int dummy)
15081 : {
15082 0 : struct tevent_context *ev;
15083 0 : struct smbXcli_conn *conn;
15084 0 : struct sockaddr_storage ss;
15085 0 : NTSTATUS status;
15086 0 : int fd;
15087 0 : bool ok;
15088 :
15089 2 : printf("Starting send SMB1 negotiate+exit.\n");
15090 :
15091 2 : ok = resolve_name(host, &ss, 0x20, true);
15092 2 : if (!ok) {
15093 0 : d_fprintf(stderr, "Could not resolve name %s\n", host);
15094 0 : return false;
15095 : }
15096 :
15097 2 : status = open_socket_out(&ss, 445, 10000, &fd);
15098 2 : if (!NT_STATUS_IS_OK(status)) {
15099 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
15100 : nt_errstr(status));
15101 0 : return false;
15102 : }
15103 :
15104 2 : conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15105 : NULL, 0, NULL);
15106 2 : if (conn == NULL) {
15107 0 : d_fprintf(stderr, "smbXcli_conn_create failed\n");
15108 0 : return false;
15109 : }
15110 :
15111 2 : status = smbXcli_negprot(conn,
15112 : 0,
15113 : PROTOCOL_NT1,
15114 : PROTOCOL_NT1,
15115 : NULL,
15116 : NULL,
15117 : NULL);
15118 2 : if (!NT_STATUS_IS_OK(status)) {
15119 0 : d_fprintf(stderr, "smbXcli_negprot failed!\n");
15120 0 : return false;
15121 : }
15122 :
15123 2 : ev = samba_tevent_context_init(talloc_tos());
15124 2 : if (ev == NULL) {
15125 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
15126 0 : return false;
15127 : }
15128 :
15129 : /*
15130 : * Call do_smb1_exit twice to catch a server crash, the
15131 : * server sends the first return code then crashes.
15132 : */
15133 2 : ok = do_smb1_exit(ev, ev, conn);
15134 2 : if (!ok) {
15135 0 : d_fprintf(stderr, "do_smb1_exit (1) failed\n");
15136 0 : return false;
15137 : }
15138 2 : ok = do_smb1_exit(ev, ev, conn);
15139 2 : if (!ok) {
15140 0 : d_fprintf(stderr, "do_smb1_exit (2) failed\n");
15141 0 : return false;
15142 : }
15143 :
15144 2 : TALLOC_FREE(conn);
15145 2 : return true;
15146 : }
15147 :
15148 2 : static bool run_smb1_negotiate_tcon(int dummy)
15149 : {
15150 2 : struct cli_state *cli = NULL;
15151 2 : uint16_t cnum = 0;
15152 2 : uint16_t max_xmit = 0;
15153 0 : NTSTATUS status;
15154 :
15155 2 : printf("Starting send SMB1 negotiate+tcon.\n");
15156 2 : cli = open_nbt_connection();
15157 2 : if (cli == NULL) {
15158 0 : d_fprintf(stderr, "open_nbt_connection failed!\n");
15159 0 : return false;
15160 : }
15161 2 : smbXcli_conn_set_sockopt(cli->conn, sockops);
15162 :
15163 2 : status = smbXcli_negprot(cli->conn,
15164 : 0,
15165 : PROTOCOL_NT1,
15166 : PROTOCOL_NT1,
15167 : NULL,
15168 : NULL,
15169 : NULL);
15170 2 : if (!NT_STATUS_IS_OK(status)) {
15171 0 : d_fprintf(stderr, "smbXcli_negprot failed %s!\n",
15172 : nt_errstr(status));
15173 0 : return false;
15174 : }
15175 2 : status = cli_raw_tcon(cli,
15176 : share,
15177 : "",
15178 : "?????",
15179 : &max_xmit,
15180 : &cnum);
15181 2 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
15182 0 : d_fprintf(stderr, "cli_raw_tcon failed - got %s "
15183 : "(should get NT_STATUS_ACCESS_DENIED)!\n",
15184 : nt_errstr(status));
15185 0 : return false;
15186 : }
15187 2 : return true;
15188 : }
15189 :
15190 0 : static bool run_ign_bad_negprot(int dummy)
15191 : {
15192 0 : struct tevent_context *ev;
15193 0 : struct tevent_req *req;
15194 0 : struct smbXcli_conn *conn;
15195 0 : struct sockaddr_storage ss;
15196 0 : NTSTATUS status;
15197 0 : int fd;
15198 0 : bool ok;
15199 :
15200 0 : printf("starting ignore bad negprot\n");
15201 :
15202 0 : ok = resolve_name(host, &ss, 0x20, true);
15203 0 : if (!ok) {
15204 0 : d_fprintf(stderr, "Could not resolve name %s\n", host);
15205 0 : return false;
15206 : }
15207 :
15208 0 : status = open_socket_out(&ss, 445, 10000, &fd);
15209 0 : if (!NT_STATUS_IS_OK(status)) {
15210 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
15211 : nt_errstr(status));
15212 0 : return false;
15213 : }
15214 :
15215 0 : conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15216 : NULL, 0, NULL);
15217 0 : if (conn == NULL) {
15218 0 : d_fprintf(stderr, "smbXcli_conn_create failed\n");
15219 0 : return false;
15220 : }
15221 :
15222 0 : status = smbXcli_negprot(conn,
15223 : 0,
15224 : PROTOCOL_CORE,
15225 : PROTOCOL_CORE,
15226 : NULL,
15227 : NULL,
15228 : NULL);
15229 0 : if (NT_STATUS_IS_OK(status)) {
15230 0 : d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
15231 0 : return false;
15232 : }
15233 :
15234 0 : ev = samba_tevent_context_init(talloc_tos());
15235 0 : if (ev == NULL) {
15236 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
15237 0 : return false;
15238 : }
15239 :
15240 0 : req = smb1cli_session_setup_nt1_send(
15241 0 : ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
15242 : data_blob_null, data_blob_null, 0x40,
15243 : "Windows 2000 2195", "Windows 2000 5.0");
15244 0 : if (req == NULL) {
15245 0 : d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
15246 0 : return false;
15247 : }
15248 :
15249 0 : ok = tevent_req_poll_ntstatus(req, ev, &status);
15250 0 : if (!ok) {
15251 0 : d_fprintf(stderr, "tevent_req_poll failed\n");
15252 0 : return false;
15253 : }
15254 :
15255 0 : status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
15256 : NULL, NULL);
15257 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
15258 0 : d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
15259 : "%s, expected NT_STATUS_CONNECTION_RESET\n",
15260 : nt_errstr(status));
15261 0 : return false;
15262 : }
15263 :
15264 0 : TALLOC_FREE(conn);
15265 :
15266 0 : printf("starting ignore bad negprot\n");
15267 :
15268 0 : return true;
15269 : }
15270 :
15271 :
15272 16 : static double create_procs(bool (*fn)(int), bool *result)
15273 : {
15274 0 : int i, status;
15275 0 : volatile pid_t *child_status;
15276 0 : volatile bool *child_status_out;
15277 0 : int synccount;
15278 16 : int tries = 8;
15279 0 : struct timeval start;
15280 :
15281 16 : synccount = 0;
15282 :
15283 16 : child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
15284 16 : if (!child_status) {
15285 0 : printf("Failed to setup shared memory\n");
15286 0 : return -1;
15287 : }
15288 :
15289 16 : child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
15290 16 : if (!child_status_out) {
15291 0 : printf("Failed to setup result status shared memory\n");
15292 0 : return -1;
15293 : }
15294 :
15295 32 : for (i = 0; i < torture_nprocs; i++) {
15296 16 : child_status[i] = 0;
15297 16 : child_status_out[i] = True;
15298 : }
15299 :
15300 16 : start = timeval_current();
15301 :
15302 32 : for (i=0;i<torture_nprocs;i++) {
15303 16 : procnum = i;
15304 16 : if (fork() == 0) {
15305 0 : pid_t mypid = getpid();
15306 0 : sys_srandom(((int)mypid) ^ ((int)time(NULL)));
15307 :
15308 0 : slprintf(myname,sizeof(myname),"CLIENT%d", i);
15309 :
15310 0 : while (1) {
15311 0 : if (torture_open_connection(¤t_cli, i)) break;
15312 0 : if (tries-- == 0) {
15313 0 : printf("pid %d failed to start\n", (int)getpid());
15314 0 : _exit(1);
15315 : }
15316 0 : smb_msleep(10);
15317 : }
15318 :
15319 0 : child_status[i] = getpid();
15320 :
15321 0 : while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
15322 :
15323 0 : child_status_out[i] = fn(i);
15324 0 : _exit(0);
15325 : }
15326 : }
15327 :
15328 0 : do {
15329 73 : synccount = 0;
15330 146 : for (i=0;i<torture_nprocs;i++) {
15331 73 : if (child_status[i]) synccount++;
15332 : }
15333 73 : if (synccount == torture_nprocs) break;
15334 57 : smb_msleep(10);
15335 57 : } while (timeval_elapsed(&start) < 30);
15336 :
15337 16 : if (synccount != torture_nprocs) {
15338 0 : printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
15339 0 : *result = False;
15340 0 : return timeval_elapsed(&start);
15341 : }
15342 :
15343 : /* start the client load */
15344 16 : start = timeval_current();
15345 :
15346 32 : for (i=0;i<torture_nprocs;i++) {
15347 16 : child_status[i] = 0;
15348 : }
15349 :
15350 16 : printf("%d clients started\n", torture_nprocs);
15351 :
15352 32 : for (i=0;i<torture_nprocs;i++) {
15353 16 : while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
15354 : }
15355 :
15356 16 : printf("\n");
15357 :
15358 32 : for (i=0;i<torture_nprocs;i++) {
15359 16 : if (!child_status_out[i]) {
15360 2 : *result = False;
15361 : }
15362 : }
15363 16 : return timeval_elapsed(&start);
15364 : }
15365 :
15366 : #define FLAG_MULTIPROC 1
15367 :
15368 : static struct {
15369 : const char *name;
15370 : bool (*fn)(int);
15371 : unsigned flags;
15372 : } torture_ops[] = {
15373 : {
15374 : .name = "FDPASS",
15375 : .fn = run_fdpasstest,
15376 : },
15377 : {
15378 : .name = "LOCK1",
15379 : .fn = run_locktest1,
15380 : },
15381 : {
15382 : .name = "LOCK2",
15383 : .fn = run_locktest2,
15384 : },
15385 : {
15386 : .name = "LOCK3",
15387 : .fn = run_locktest3,
15388 : },
15389 : {
15390 : .name = "LOCK4",
15391 : .fn = run_locktest4,
15392 : },
15393 : {
15394 : .name = "LOCK5",
15395 : .fn = run_locktest5,
15396 : },
15397 : {
15398 : .name = "LOCK6",
15399 : .fn = run_locktest6,
15400 : },
15401 : {
15402 : .name = "LOCK7",
15403 : .fn = run_locktest7,
15404 : },
15405 : {
15406 : .name = "LOCK8",
15407 : .fn = run_locktest8,
15408 : },
15409 : {
15410 : .name = "LOCK9A",
15411 : .fn = run_locktest9a,
15412 : },
15413 : {
15414 : .name = "LOCK9B",
15415 : .fn = run_locktest9b,
15416 : },
15417 : {
15418 : .name = "LOCK10",
15419 : .fn = run_locktest10,
15420 : },
15421 : {
15422 : .name = "LOCK11",
15423 : .fn = run_locktest11,
15424 : },
15425 : {
15426 : .name = "LOCK12",
15427 : .fn = run_locktest12,
15428 : },
15429 : {
15430 : .name = "LOCK13",
15431 : .fn = run_locktest13,
15432 : },
15433 : {
15434 : .name = "UNLINK",
15435 : .fn = run_unlinktest,
15436 : },
15437 : {
15438 : .name = "BROWSE",
15439 : .fn = run_browsetest,
15440 : },
15441 : {
15442 : .name = "ATTR",
15443 : .fn = run_attrtest,
15444 : },
15445 : {
15446 : .name = "TRANS2",
15447 : .fn = run_trans2test,
15448 : },
15449 : {
15450 : .name = "MAXFID",
15451 : .fn = run_maxfidtest,
15452 : .flags = FLAG_MULTIPROC,
15453 : },
15454 : {
15455 : .name = "TORTURE",
15456 : .fn = run_torture,
15457 : .flags = FLAG_MULTIPROC,
15458 : },
15459 : {
15460 : .name = "RANDOMIPC",
15461 : .fn = run_randomipc,
15462 : },
15463 : {
15464 : .name = "NEGNOWAIT",
15465 : .fn = run_negprot_nowait,
15466 : },
15467 : {
15468 : .name = "NBENCH",
15469 : .fn = run_nbench,
15470 : },
15471 : {
15472 : .name = "NBENCH2",
15473 : .fn = run_nbench2,
15474 : },
15475 : {
15476 : .name = "OPLOCK1",
15477 : .fn = run_oplock1,
15478 : },
15479 : {
15480 : .name = "OPLOCK2",
15481 : .fn = run_oplock2,
15482 : },
15483 : {
15484 : .name = "OPLOCK4",
15485 : .fn = run_oplock4,
15486 : },
15487 : #ifdef HAVE_KERNEL_OPLOCKS_LINUX
15488 : {
15489 : .name = "OPLOCK5",
15490 : .fn = run_oplock5,
15491 : },
15492 : #endif
15493 : {
15494 : .name = "DIR",
15495 : .fn = run_dirtest,
15496 : },
15497 : {
15498 : .name = "DIR1",
15499 : .fn = run_dirtest1,
15500 : },
15501 : {
15502 : .name = "DIR-CREATETIME",
15503 : .fn = run_dir_createtime,
15504 : },
15505 : {
15506 : .name = "DENY1",
15507 : .fn = torture_denytest1,
15508 : },
15509 : {
15510 : .name = "DENY2",
15511 : .fn = torture_denytest2,
15512 : },
15513 : {
15514 : .name = "TCON",
15515 : .fn = run_tcon_test,
15516 : },
15517 : {
15518 : .name = "TCONDEV",
15519 : .fn = run_tcon_devtype_test,
15520 : },
15521 : {
15522 : .name = "RW1",
15523 : .fn = run_readwritetest,
15524 : },
15525 : {
15526 : .name = "RW2",
15527 : .fn = run_readwritemulti,
15528 : .flags = FLAG_MULTIPROC
15529 : },
15530 : {
15531 : .name = "RW3",
15532 : .fn = run_readwritelarge,
15533 : },
15534 : {
15535 : .name = "RW-SIGNING",
15536 : .fn = run_readwritelarge_signtest,
15537 : },
15538 : {
15539 : .name = "OPEN",
15540 : .fn = run_opentest,
15541 : },
15542 : {
15543 : .name = "POSIX",
15544 : .fn = run_simple_posix_open_test,
15545 : },
15546 : {
15547 : .name = "POSIX-APPEND",
15548 : .fn = run_posix_append,
15549 : },
15550 : {
15551 : .name = "POSIX-SYMLINK-ACL",
15552 : .fn = run_acl_symlink_test,
15553 : },
15554 : {
15555 : .name = "POSIX-SYMLINK-EA",
15556 : .fn = run_ea_symlink_test,
15557 : },
15558 : {
15559 : .name = "POSIX-STREAM-DELETE",
15560 : .fn = run_posix_stream_delete,
15561 : },
15562 : {
15563 : .name = "POSIX-OFD-LOCK",
15564 : .fn = run_posix_ofd_lock_test,
15565 : },
15566 : {
15567 : .name = "POSIX-BLOCKING-LOCK",
15568 : .fn = run_posix_blocking_lock,
15569 : },
15570 : {
15571 : .name = "POSIX-MKDIR",
15572 : .fn = run_posix_mkdir_test,
15573 : },
15574 : {
15575 : .name = "POSIX-ACL-OPLOCK",
15576 : .fn = run_posix_acl_oplock_test,
15577 : },
15578 : {
15579 : .name = "POSIX-ACL-SHAREROOT",
15580 : .fn = run_posix_acl_shareroot_test,
15581 : },
15582 : {
15583 : .name = "POSIX-LS-WILDCARD",
15584 : .fn = run_posix_ls_wildcard_test,
15585 : },
15586 : {
15587 : .name = "POSIX-LS-SINGLE",
15588 : .fn = run_posix_ls_single_test,
15589 : },
15590 : {
15591 : .name = "POSIX-READLINK",
15592 : .fn = run_posix_readlink_test,
15593 : },
15594 : {
15595 : .name = "POSIX-STAT",
15596 : .fn = run_posix_stat_test,
15597 : },
15598 : {
15599 : .name = "POSIX-SYMLINK-PARENT",
15600 : .fn = run_posix_symlink_parent_test,
15601 : },
15602 : {
15603 : .name = "POSIX-SYMLINK-CHMOD",
15604 : .fn = run_posix_symlink_chmod_test,
15605 : },
15606 : {
15607 : .name = "POSIX-SYMLINK-RENAME",
15608 : .fn = run_posix_symlink_rename_test,
15609 : },
15610 : {
15611 : .name = "POSIX-DIR-DEFAULT-ACL",
15612 : .fn = run_posix_dir_default_acl_test,
15613 : },
15614 : {
15615 : .name = "POSIX-SYMLINK-GETPATHINFO",
15616 : .fn = run_posix_symlink_getpathinfo_test,
15617 : },
15618 : {
15619 : .name = "POSIX-SYMLINK-SETPATHINFO",
15620 : .fn = run_posix_symlink_setpathinfo_test,
15621 : },
15622 : {
15623 : .name = "WINDOWS-BAD-SYMLINK",
15624 : .fn = run_symlink_open_test,
15625 : },
15626 : {
15627 : .name = "SMB1-WILD-MANGLE-UNLINK",
15628 : .fn = run_smb1_wild_mangle_unlink_test,
15629 : },
15630 : {
15631 : .name = "SMB1-WILD-MANGLE-RENAME",
15632 : .fn = run_smb1_wild_mangle_rename_test,
15633 : },
15634 : {
15635 : .name = "CASE-INSENSITIVE-CREATE",
15636 : .fn = run_case_insensitive_create,
15637 : },
15638 : {
15639 : .name = "ASYNC-ECHO",
15640 : .fn = run_async_echo,
15641 : },
15642 : {
15643 : .name = "UID-REGRESSION-TEST",
15644 : .fn = run_uid_regression_test,
15645 : },
15646 : {
15647 : .name = "SHORTNAME-TEST",
15648 : .fn = run_shortname_test,
15649 : },
15650 : {
15651 : .name = "ADDRCHANGE",
15652 : .fn = run_addrchange,
15653 : },
15654 : #if 1
15655 : {
15656 : .name = "OPENATTR",
15657 : .fn = run_openattrtest,
15658 : },
15659 : #endif
15660 : {
15661 : .name = "XCOPY",
15662 : .fn = run_xcopy,
15663 : },
15664 : {
15665 : .name = "RENAME",
15666 : .fn = run_rename,
15667 : },
15668 : {
15669 : .name = "RENAME-ACCESS",
15670 : .fn = run_rename_access,
15671 : },
15672 : {
15673 : .name = "OWNER-RIGHTS",
15674 : .fn = run_owner_rights,
15675 : },
15676 : {
15677 : .name = "DELETE",
15678 : .fn = run_deletetest,
15679 : },
15680 : {
15681 : .name = "DELETE-STREAM",
15682 : .fn = run_delete_stream,
15683 : },
15684 : {
15685 : .name = "DELETE-PRINT",
15686 : .fn = run_delete_print_test,
15687 : },
15688 : {
15689 : .name = "DELETE-LN",
15690 : .fn = run_deletetest_ln,
15691 : },
15692 : {
15693 : .name = "PROPERTIES",
15694 : .fn = run_properties,
15695 : },
15696 : {
15697 : .name = "MANGLE",
15698 : .fn = torture_mangle,
15699 : },
15700 : {
15701 : .name = "MANGLE1",
15702 : .fn = run_mangle1,
15703 : },
15704 : {
15705 : .name = "MANGLE-ILLEGAL",
15706 : .fn = run_mangle_illegal,
15707 : },
15708 : {
15709 : .name = "W2K",
15710 : .fn = run_w2ktest,
15711 : },
15712 : {
15713 : .name = "TRANS2SCAN",
15714 : .fn = torture_trans2_scan,
15715 : },
15716 : {
15717 : .name = "NTTRANSSCAN",
15718 : .fn = torture_nttrans_scan,
15719 : },
15720 : {
15721 : .name = "UTABLE",
15722 : .fn = torture_utable,
15723 : },
15724 : {
15725 : .name = "CASETABLE",
15726 : .fn = torture_casetable,
15727 : },
15728 : {
15729 : .name = "ERRMAPEXTRACT",
15730 : .fn = run_error_map_extract,
15731 : },
15732 : {
15733 : .name = "PIPE_NUMBER",
15734 : .fn = run_pipe_number,
15735 : },
15736 : {
15737 : .name = "TCON2",
15738 : .fn = run_tcon2_test,
15739 : },
15740 : {
15741 : .name = "IOCTL",
15742 : .fn = torture_ioctl_test,
15743 : },
15744 : {
15745 : .name = "CHKPATH",
15746 : .fn = torture_chkpath_test,
15747 : },
15748 : {
15749 : .name = "FDSESS",
15750 : .fn = run_fdsesstest,
15751 : },
15752 : {
15753 : .name = "EATEST",
15754 : .fn = run_eatest,
15755 : },
15756 : {
15757 : .name = "SESSSETUP_BENCH",
15758 : .fn = run_sesssetup_bench,
15759 : },
15760 : {
15761 : .name = "CHAIN1",
15762 : .fn = run_chain1,
15763 : },
15764 : {
15765 : .name = "CHAIN2",
15766 : .fn = run_chain2,
15767 : },
15768 : {
15769 : .name = "CHAIN3",
15770 : .fn = run_chain3,
15771 : },
15772 : {
15773 : .name = "WINDOWS-WRITE",
15774 : .fn = run_windows_write,
15775 : },
15776 : {
15777 : .name = "LARGE_READX",
15778 : .fn = run_large_readx,
15779 : },
15780 : {
15781 : .name = "MSDFS-ATTRIBUTE",
15782 : .fn = run_msdfs_attribute,
15783 : },
15784 : {
15785 : .name = "NTTRANS-CREATE",
15786 : .fn = run_nttrans_create,
15787 : },
15788 : {
15789 : .name = "NTTRANS-FSCTL",
15790 : .fn = run_nttrans_fsctl,
15791 : },
15792 : {
15793 : .name = "CLI_ECHO",
15794 : .fn = run_cli_echo,
15795 : },
15796 : {
15797 : .name = "CLI_SPLICE",
15798 : .fn = run_cli_splice,
15799 : },
15800 : {
15801 : .name = "TLDAP",
15802 : .fn = run_tldap,
15803 : },
15804 : {
15805 : .name = "STREAMERROR",
15806 : .fn = run_streamerror,
15807 : },
15808 : {
15809 : .name = "NOTIFY-BENCH",
15810 : .fn = run_notify_bench,
15811 : },
15812 : {
15813 : .name = "NOTIFY-BENCH2",
15814 : .fn = run_notify_bench2,
15815 : },
15816 : {
15817 : .name = "NOTIFY-BENCH3",
15818 : .fn = run_notify_bench3,
15819 : },
15820 : {
15821 : .name = "BAD-NBT-SESSION",
15822 : .fn = run_bad_nbt_session,
15823 : },
15824 : {
15825 : .name = "IGN-BAD-NEGPROT",
15826 : .fn = run_ign_bad_negprot,
15827 : },
15828 : {
15829 : .name = "SMB-ANY-CONNECT",
15830 : .fn = run_smb_any_connect,
15831 : },
15832 : {
15833 : .name = "NOTIFY-ONLINE",
15834 : .fn = run_notify_online,
15835 : },
15836 : {
15837 : .name = "SMB2-BASIC",
15838 : .fn = run_smb2_basic,
15839 : },
15840 : {
15841 : .name = "SMB2-NEGPROT",
15842 : .fn = run_smb2_negprot,
15843 : },
15844 : {
15845 : .name = "SMB2-ANONYMOUS",
15846 : .fn = run_smb2_anonymous,
15847 : },
15848 : {
15849 : .name = "SMB2-SESSION-RECONNECT",
15850 : .fn = run_smb2_session_reconnect,
15851 : },
15852 : {
15853 : .name = "SMB2-TCON-DEPENDENCE",
15854 : .fn = run_smb2_tcon_dependence,
15855 : },
15856 : {
15857 : .name = "SMB2-MULTI-CHANNEL",
15858 : .fn = run_smb2_multi_channel,
15859 : },
15860 : {
15861 : .name = "SMB2-SESSION-REAUTH",
15862 : .fn = run_smb2_session_reauth,
15863 : },
15864 : {
15865 : .name = "SMB2-FTRUNCATE",
15866 : .fn = run_smb2_ftruncate,
15867 : },
15868 : {
15869 : .name = "SMB2-DIR-FSYNC",
15870 : .fn = run_smb2_dir_fsync,
15871 : },
15872 : {
15873 : .name = "SMB2-PATH-SLASH",
15874 : .fn = run_smb2_path_slash,
15875 : },
15876 : {
15877 : .name = "SMB1-SYSTEM-SECURITY",
15878 : .fn = run_smb1_system_security,
15879 : },
15880 : {
15881 : .name = "SMB2-SACL",
15882 : .fn = run_smb2_sacl,
15883 : },
15884 : {
15885 : .name = "SMB2-QUOTA1",
15886 : .fn = run_smb2_quota1,
15887 : },
15888 : {
15889 : .name = "SMB2-INVALID-PIPENAME",
15890 : .fn = run_smb2_invalid_pipename,
15891 : },
15892 : {
15893 : .name = "SMB2-STREAM-ACL",
15894 : .fn = run_smb2_stream_acl,
15895 : },
15896 : {
15897 : .name = "SMB2-LIST-DIR-ASYNC",
15898 : .fn = run_list_dir_async_test,
15899 : },
15900 : {
15901 : .name = "SMB2-DEL-ON-CLOSE-NONEMPTY",
15902 : .fn = run_delete_on_close_non_empty,
15903 : },
15904 : {
15905 : .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15906 : .fn = run_delete_on_close_nonwrite_delete_yes_test,
15907 : },
15908 : {
15909 : .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15910 : .fn = run_delete_on_close_nonwrite_delete_no_test,
15911 : },
15912 : {
15913 : .name = "SMB2-DFS-PATHS",
15914 : .fn = run_smb2_dfs_paths,
15915 : },
15916 : {
15917 : .name = "SMB2-NON-DFS-SHARE",
15918 : .fn = run_smb2_non_dfs_share,
15919 : },
15920 : {
15921 : .name = "SMB2-DFS-SHARE-NON-DFS-PATH",
15922 : .fn = run_smb2_dfs_share_non_dfs_path,
15923 : },
15924 : {
15925 : .name = "SMB2-DFS-FILENAME-LEADING-BACKSLASH",
15926 : .fn = run_smb2_dfs_filename_leading_backslash,
15927 : },
15928 : {
15929 : .name = "SMB2-PIPE-READ-ASYNC-DISCONNECT",
15930 : .fn = run_smb2_pipe_read_async_disconnect,
15931 : },
15932 : {
15933 : .name = "SMB1-TRUNCATED-SESSSETUP",
15934 : .fn = run_smb1_truncated_sesssetup,
15935 : },
15936 : {
15937 : .name = "SMB1-NEGOTIATE-EXIT",
15938 : .fn = run_smb1_negotiate_exit,
15939 : },
15940 : {
15941 : .name = "SMB1-NEGOTIATE-TCON",
15942 : .fn = run_smb1_negotiate_tcon,
15943 : },
15944 : {
15945 : .name = "SMB1-DFS-PATHS",
15946 : .fn = run_smb1_dfs_paths,
15947 : },
15948 : {
15949 : .name = "SMB1-DFS-SEARCH-PATHS",
15950 : .fn = run_smb1_dfs_search_paths,
15951 : },
15952 : {
15953 : .name = "SMB1-DFS-OPERATIONS",
15954 : .fn = run_smb1_dfs_operations,
15955 : },
15956 : {
15957 : .name = "SMB1-DFS-BADPATH",
15958 : .fn = run_smb1_dfs_check_badpath,
15959 : },
15960 : {
15961 : .name = "CLEANUP1",
15962 : .fn = run_cleanup1,
15963 : },
15964 : {
15965 : .name = "CLEANUP2",
15966 : .fn = run_cleanup2,
15967 : },
15968 : {
15969 : .name = "CLEANUP4",
15970 : .fn = run_cleanup4,
15971 : },
15972 : {
15973 : .name = "OPLOCK-CANCEL",
15974 : .fn = run_oplock_cancel,
15975 : },
15976 : {
15977 : .name = "PIDHIGH",
15978 : .fn = run_pidhigh,
15979 : },
15980 : {
15981 : .name = "LOCAL-SUBSTITUTE",
15982 : .fn = run_local_substitute,
15983 : },
15984 : {
15985 : .name = "LOCAL-GENCACHE",
15986 : .fn = run_local_gencache,
15987 : },
15988 : {
15989 : .name = "LOCAL-DBWRAP-WATCH1",
15990 : .fn = run_dbwrap_watch1,
15991 : },
15992 : {
15993 : .name = "LOCAL-DBWRAP-WATCH2",
15994 : .fn = run_dbwrap_watch2,
15995 : },
15996 : {
15997 : .name = "LOCAL-DBWRAP-WATCH3",
15998 : .fn = run_dbwrap_watch3,
15999 : },
16000 : {
16001 : .name = "LOCAL-DBWRAP-WATCH4",
16002 : .fn = run_dbwrap_watch4,
16003 : },
16004 : {
16005 : .name = "LOCAL-DBWRAP-DO-LOCKED1",
16006 : .fn = run_dbwrap_do_locked1,
16007 : },
16008 : {
16009 : .name = "LOCAL-MESSAGING-READ1",
16010 : .fn = run_messaging_read1,
16011 : },
16012 : {
16013 : .name = "LOCAL-MESSAGING-READ2",
16014 : .fn = run_messaging_read2,
16015 : },
16016 : {
16017 : .name = "LOCAL-MESSAGING-READ3",
16018 : .fn = run_messaging_read3,
16019 : },
16020 : {
16021 : .name = "LOCAL-MESSAGING-READ4",
16022 : .fn = run_messaging_read4,
16023 : },
16024 : {
16025 : .name = "LOCAL-MESSAGING-FDPASS1",
16026 : .fn = run_messaging_fdpass1,
16027 : },
16028 : {
16029 : .name = "LOCAL-MESSAGING-FDPASS2",
16030 : .fn = run_messaging_fdpass2,
16031 : },
16032 : {
16033 : .name = "LOCAL-MESSAGING-FDPASS2a",
16034 : .fn = run_messaging_fdpass2a,
16035 : },
16036 : {
16037 : .name = "LOCAL-MESSAGING-FDPASS2b",
16038 : .fn = run_messaging_fdpass2b,
16039 : },
16040 : {
16041 : .name = "LOCAL-MESSAGING-SEND-ALL",
16042 : .fn = run_messaging_send_all,
16043 : },
16044 : {
16045 : .name = "LOCAL-BASE64",
16046 : .fn = run_local_base64,
16047 : },
16048 : {
16049 : .name = "LOCAL-RBTREE",
16050 : .fn = run_local_rbtree,
16051 : },
16052 : {
16053 : .name = "LOCAL-MEMCACHE",
16054 : .fn = run_local_memcache,
16055 : },
16056 : {
16057 : .name = "LOCAL-STREAM-NAME",
16058 : .fn = run_local_stream_name,
16059 : },
16060 : {
16061 : .name = "LOCAL-STR-MATCH-MSWILD",
16062 : .fn = run_str_match_mswild,
16063 : },
16064 : {
16065 : .name = "LOCAL-STR-MATCH-REGEX-SUB1",
16066 : .fn = run_str_match_regex_sub1,
16067 : },
16068 : {
16069 : .name = "WBCLIENT-MULTI-PING",
16070 : .fn = run_wbclient_multi_ping,
16071 : },
16072 : {
16073 : .name = "LOCAL-string_to_sid",
16074 : .fn = run_local_string_to_sid,
16075 : },
16076 : {
16077 : .name = "LOCAL-sid_to_string",
16078 : .fn = run_local_sid_to_string,
16079 : },
16080 : {
16081 : .name = "LOCAL-binary_to_sid",
16082 : .fn = run_local_binary_to_sid,
16083 : },
16084 : {
16085 : .name = "LOCAL-DBTRANS",
16086 : .fn = run_local_dbtrans,
16087 : },
16088 : {
16089 : .name = "LOCAL-TEVENT-POLL",
16090 : .fn = run_local_tevent_poll,
16091 : },
16092 : {
16093 : .name = "LOCAL-CONVERT-STRING",
16094 : .fn = run_local_convert_string,
16095 : },
16096 : {
16097 : .name = "LOCAL-CONV-AUTH-INFO",
16098 : .fn = run_local_conv_auth_info,
16099 : },
16100 : {
16101 : .name = "LOCAL-hex_encode_buf",
16102 : .fn = run_local_hex_encode_buf,
16103 : },
16104 : {
16105 : .name = "LOCAL-IDMAP-TDB-COMMON",
16106 : .fn = run_idmap_tdb_common_test,
16107 : },
16108 : {
16109 : .name = "LOCAL-remove_duplicate_addrs2",
16110 : .fn = run_local_remove_duplicate_addrs2,
16111 : },
16112 : {
16113 : .name = "local-tdb-opener",
16114 : .fn = run_local_tdb_opener,
16115 : },
16116 : {
16117 : .name = "local-tdb-writer",
16118 : .fn = run_local_tdb_writer,
16119 : },
16120 : {
16121 : .name = "LOCAL-DBWRAP-CTDB1",
16122 : .fn = run_local_dbwrap_ctdb1,
16123 : },
16124 : {
16125 : .name = "LOCAL-BENCH-PTHREADPOOL",
16126 : .fn = run_bench_pthreadpool,
16127 : },
16128 : {
16129 : .name = "LOCAL-PTHREADPOOL-TEVENT",
16130 : .fn = run_pthreadpool_tevent,
16131 : },
16132 : {
16133 : .name = "LOCAL-G-LOCK1",
16134 : .fn = run_g_lock1,
16135 : },
16136 : {
16137 : .name = "LOCAL-G-LOCK2",
16138 : .fn = run_g_lock2,
16139 : },
16140 : {
16141 : .name = "LOCAL-G-LOCK3",
16142 : .fn = run_g_lock3,
16143 : },
16144 : {
16145 : .name = "LOCAL-G-LOCK4",
16146 : .fn = run_g_lock4,
16147 : },
16148 : {
16149 : .name = "LOCAL-G-LOCK4A",
16150 : .fn = run_g_lock4a,
16151 : },
16152 : {
16153 : .name = "LOCAL-G-LOCK5",
16154 : .fn = run_g_lock5,
16155 : },
16156 : {
16157 : .name = "LOCAL-G-LOCK6",
16158 : .fn = run_g_lock6,
16159 : },
16160 : {
16161 : .name = "LOCAL-G-LOCK7",
16162 : .fn = run_g_lock7,
16163 : },
16164 : {
16165 : .name = "LOCAL-G-LOCK8",
16166 : .fn = run_g_lock8,
16167 : },
16168 : {
16169 : .name = "LOCAL-G-LOCK-PING-PONG",
16170 : .fn = run_g_lock_ping_pong,
16171 : },
16172 : {
16173 : .name = "LOCAL-CANONICALIZE-PATH",
16174 : .fn = run_local_canonicalize_path,
16175 : },
16176 : {
16177 : .name = "LOCAL-NAMEMAP-CACHE1",
16178 : .fn = run_local_namemap_cache1,
16179 : },
16180 : {
16181 : .name = "LOCAL-IDMAP-CACHE1",
16182 : .fn = run_local_idmap_cache1,
16183 : },
16184 : {
16185 : .name = "qpathinfo-bufsize",
16186 : .fn = run_qpathinfo_bufsize,
16187 : },
16188 : {
16189 : .name = "hide-new-files-timeout",
16190 : .fn = run_hidenewfiles,
16191 : },
16192 : {
16193 : .name = "hide-new-files-timeout-showdirs",
16194 : .fn = run_hidenewfiles_showdirs,
16195 : },
16196 : #ifdef CLUSTER_SUPPORT
16197 : {
16198 : .name = "ctdbd-conn1",
16199 : .fn = run_ctdbd_conn1,
16200 : },
16201 : #endif
16202 : {
16203 : .name = "readdir-timestamp",
16204 : .fn = run_readdir_timestamp,
16205 : },
16206 : {
16207 : .name = "rpc-scale",
16208 : .fn = run_rpc_scale,
16209 : },
16210 : {
16211 : .name = "LOCAL-TDB-VALIDATE",
16212 : .fn = run_tdb_validate,
16213 : },
16214 : {
16215 : .name = NULL,
16216 : },
16217 : };
16218 :
16219 : /****************************************************************************
16220 : run a specified test or "ALL"
16221 : ****************************************************************************/
16222 546 : static bool run_test(const char *name)
16223 : {
16224 546 : bool ret = True;
16225 546 : bool result = True;
16226 546 : bool found = False;
16227 45 : int i;
16228 45 : double t;
16229 546 : if (strequal(name,"ALL")) {
16230 0 : for (i=0;torture_ops[i].name;i++) {
16231 0 : run_test(torture_ops[i].name);
16232 : }
16233 0 : found = True;
16234 : }
16235 :
16236 113747 : for (i=0;torture_ops[i].name;i++) {
16237 113197 : fstr_sprintf(randomfname, "\\XX%x",
16238 113197 : (unsigned)random());
16239 :
16240 113197 : if (strequal(name, torture_ops[i].name)) {
16241 546 : found = True;
16242 546 : printf("Running %s\n", name);
16243 546 : if (torture_ops[i].flags & FLAG_MULTIPROC) {
16244 16 : t = create_procs(torture_ops[i].fn, &result);
16245 16 : if (!result) {
16246 2 : ret = False;
16247 2 : printf("TEST %s FAILED!\n", name);
16248 : }
16249 : } else {
16250 45 : struct timeval start;
16251 530 : start = timeval_current();
16252 530 : if (!torture_ops[i].fn(0)) {
16253 14 : ret = False;
16254 14 : printf("TEST %s FAILED!\n", name);
16255 : }
16256 534 : t = timeval_elapsed(&start);
16257 : }
16258 9995 : printf("%s took %g secs\n\n", name, t);
16259 : }
16260 : }
16261 :
16262 550 : if (!found) {
16263 0 : printf("Did not find a test named %s\n", name);
16264 0 : ret = False;
16265 : }
16266 :
16267 550 : return ret;
16268 : }
16269 :
16270 :
16271 0 : static void usage(void)
16272 : {
16273 0 : int i;
16274 :
16275 0 : printf("WARNING samba4 test suite is much more complete nowadays.\n");
16276 0 : printf("Please use samba4 torture.\n\n");
16277 :
16278 0 : printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
16279 :
16280 0 : printf("\t-d debuglevel\n");
16281 0 : printf("\t-U user%%pass\n");
16282 0 : printf("\t-k use kerberos\n");
16283 0 : printf("\t-N numprocs\n");
16284 0 : printf("\t-n my_netbios_name\n");
16285 0 : printf("\t-W workgroup\n");
16286 0 : printf("\t-o num_operations\n");
16287 0 : printf("\t-O socket_options\n");
16288 0 : printf("\t-m maximum protocol\n");
16289 0 : printf("\t-L use oplocks\n");
16290 0 : printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
16291 0 : printf("\t-A showall\n");
16292 0 : printf("\t-p port\n");
16293 0 : printf("\t-s seed\n");
16294 0 : printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
16295 0 : printf("\t-f filename filename to test\n");
16296 0 : printf("\t-e encrypt\n");
16297 0 : printf("\n\n");
16298 :
16299 0 : printf("tests are:");
16300 0 : for (i=0;torture_ops[i].name;i++) {
16301 0 : printf(" %s", torture_ops[i].name);
16302 : }
16303 0 : printf("\n");
16304 :
16305 0 : printf("default test is ALL\n");
16306 :
16307 0 : exit(1);
16308 : }
16309 :
16310 : /****************************************************************************
16311 : main program
16312 : ****************************************************************************/
16313 546 : int main(int argc,char *argv[])
16314 : {
16315 45 : int opt, i;
16316 45 : char *p;
16317 546 : int gotuser = 0;
16318 546 : int gotpass = 0;
16319 546 : bool correct = True;
16320 546 : TALLOC_CTX *frame = talloc_stackframe();
16321 546 : int seed = time(NULL);
16322 546 : struct loadparm_context *lp_ctx = NULL;
16323 :
16324 : #ifdef HAVE_SETBUFFER
16325 546 : setbuffer(stdout, NULL, 0);
16326 : #endif
16327 :
16328 546 : setup_logging("smbtorture", DEBUG_STDOUT);
16329 :
16330 546 : smb_init_locale();
16331 546 : fault_setup();
16332 :
16333 546 : lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
16334 546 : if (lp_ctx == NULL) {
16335 0 : fprintf(stderr,
16336 : "Failed to initialise the global parameter structure.\n");
16337 0 : return 1;
16338 : }
16339 :
16340 546 : if (is_default_dyn_CONFIGFILE()) {
16341 546 : if(getenv("SMB_CONF_PATH")) {
16342 546 : set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
16343 : }
16344 : }
16345 546 : lp_load_global(get_dyn_CONFIGFILE());
16346 546 : load_interfaces();
16347 :
16348 546 : if (argc < 2) {
16349 0 : usage();
16350 : }
16351 :
16352 11065 : for(p = argv[1]; *p; p++)
16353 10519 : if(*p == '\\')
16354 0 : *p = '/';
16355 :
16356 546 : if (strncmp(argv[1], "//", 2)) {
16357 0 : usage();
16358 : }
16359 :
16360 546 : fstrcpy(host, &argv[1][2]);
16361 546 : p = strchr_m(&host[2],'/');
16362 546 : if (!p) {
16363 0 : usage();
16364 : }
16365 546 : *p = 0;
16366 546 : fstrcpy(share, p+1);
16367 :
16368 546 : fstrcpy(myname, get_myname(talloc_tos()));
16369 546 : if (!*myname) {
16370 0 : fprintf(stderr, "Failed to get my hostname.\n");
16371 0 : return 1;
16372 : }
16373 :
16374 546 : if (*username == 0 && getenv("LOGNAME")) {
16375 0 : fstrcpy(username,getenv("LOGNAME"));
16376 : }
16377 :
16378 546 : argc--;
16379 546 : argv++;
16380 :
16381 546 : fstrcpy(workgroup, lp_workgroup());
16382 :
16383 1729 : while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
16384 1774 : != EOF) {
16385 1228 : switch (opt) {
16386 0 : case 'p':
16387 0 : port_to_use = atoi(optarg);
16388 0 : break;
16389 0 : case 's':
16390 0 : seed = atoi(optarg);
16391 0 : break;
16392 0 : case 'W':
16393 0 : fstrcpy(workgroup,optarg);
16394 0 : break;
16395 33 : case 'm':
16396 33 : lpcfg_set_cmdline(lp_ctx, "client max protocol", optarg);
16397 33 : break;
16398 0 : case 'N':
16399 0 : torture_nprocs = atoi(optarg);
16400 0 : break;
16401 0 : case 'o':
16402 0 : torture_numops = atoi(optarg);
16403 0 : break;
16404 0 : case 'd':
16405 0 : lpcfg_set_cmdline(lp_ctx, "log level", optarg);
16406 0 : break;
16407 0 : case 'O':
16408 0 : sockops = optarg;
16409 0 : break;
16410 0 : case 'L':
16411 0 : use_oplocks = True;
16412 0 : break;
16413 463 : case 'l':
16414 463 : local_path = optarg;
16415 463 : break;
16416 0 : case 'A':
16417 0 : torture_showall = True;
16418 0 : break;
16419 0 : case 'n':
16420 0 : fstrcpy(myname, optarg);
16421 0 : break;
16422 0 : case 'c':
16423 0 : client_txt = optarg;
16424 0 : break;
16425 182 : case 'e':
16426 182 : do_encrypt = true;
16427 182 : break;
16428 0 : case 'k':
16429 : #ifdef HAVE_KRB5
16430 0 : use_kerberos = True;
16431 : #else
16432 : d_printf("No kerberos support compiled in\n");
16433 : exit(1);
16434 : #endif
16435 0 : break;
16436 546 : case 'U':
16437 546 : gotuser = 1;
16438 546 : fstrcpy(username,optarg);
16439 546 : p = strchr_m(username,'%');
16440 546 : if (p) {
16441 546 : *p = 0;
16442 546 : fstrcpy(password, p+1);
16443 546 : gotpass = 1;
16444 : }
16445 501 : break;
16446 0 : case 'b':
16447 0 : fstrcpy(multishare_conn_fname, optarg);
16448 0 : use_multishare_conn = True;
16449 0 : break;
16450 0 : case 'B':
16451 0 : torture_blocksize = atoi(optarg);
16452 0 : break;
16453 4 : case 'f':
16454 4 : test_filename = SMB_STRDUP(optarg);
16455 4 : break;
16456 0 : default:
16457 0 : printf("Unknown option %c (%d)\n", (char)opt, opt);
16458 0 : usage();
16459 : }
16460 : }
16461 :
16462 546 : d_printf("using seed %d\n", seed);
16463 :
16464 546 : srandom(seed);
16465 :
16466 546 : if(use_kerberos && !gotuser) gotpass = True;
16467 :
16468 546 : while (!gotpass) {
16469 0 : char pwd[256] = {0};
16470 0 : int rc;
16471 :
16472 0 : rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
16473 0 : if (rc == 0) {
16474 0 : fstrcpy(password, pwd);
16475 0 : gotpass = 1;
16476 : }
16477 : }
16478 :
16479 546 : printf("host=%s share=%s user=%s myname=%s\n",
16480 : host, share, username, myname);
16481 :
16482 546 : torture_creds = cli_session_creds_init(frame,
16483 : username,
16484 : workgroup,
16485 : NULL, /* realm */
16486 : password,
16487 : use_kerberos,
16488 : false, /* fallback_after_kerberos */
16489 : false, /* use_ccache */
16490 : false); /* password_is_nt_hash */
16491 546 : if (torture_creds == NULL) {
16492 0 : d_printf("cli_session_creds_init() failed.\n");
16493 0 : exit(1);
16494 : }
16495 :
16496 546 : if (argc == optind) {
16497 0 : correct = run_test("ALL");
16498 : } else {
16499 1096 : for (i=optind;i<argc;i++) {
16500 546 : if (!run_test(argv[i])) {
16501 16 : correct = False;
16502 : }
16503 : }
16504 : }
16505 :
16506 550 : TALLOC_FREE(frame);
16507 :
16508 550 : if (correct) {
16509 485 : return(0);
16510 : } else {
16511 16 : return(1);
16512 : }
16513 : }
|