Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : SMB torture tester
4 : Copyright (C) Andrew Tridgell 1997-1998
5 : Copyright (C) Jeremy Allison 2009
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "includes.h"
22 : #include "system/shmem.h"
23 : #include "libsmb/namequery.h"
24 : #include "wbc_async.h"
25 : #include "torture/proto.h"
26 : #include "libcli/security/security.h"
27 : #include "tldap.h"
28 : #include "tldap_util.h"
29 : #include "tldap_gensec_bind.h"
30 : #include "../librpc/gen_ndr/svcctl.h"
31 : #include "../lib/util/memcache.h"
32 : #include "nsswitch/winbind_client.h"
33 : #include "dbwrap/dbwrap.h"
34 : #include "dbwrap/dbwrap_open.h"
35 : #include "dbwrap/dbwrap_rbt.h"
36 : #include "async_smb.h"
37 : #include "libsmb/libsmb.h"
38 : #include "libsmb/clirap.h"
39 : #include "trans2.h"
40 : #include "libsmb/nmblib.h"
41 : #include "../lib/util/tevent_ntstatus.h"
42 : #include "util_tdb.h"
43 : #include "../libcli/smb/read_smb.h"
44 : #include "../libcli/smb/smbXcli_base.h"
45 : #include "lib/util/sys_rw_data.h"
46 : #include "lib/util/base64.h"
47 : #include "lib/util/time.h"
48 : #include "lib/gencache.h"
49 : #include "lib/util/sys_rw.h"
50 : #include "lib/util/asn1.h"
51 : #include "lib/param/param.h"
52 : #include "auth/gensec/gensec.h"
53 : #include "lib/util/string_wrappers.h"
54 : #include "source3/lib/substitute.h"
55 :
56 : #include <gnutls/gnutls.h>
57 : #include <gnutls/crypto.h>
58 :
59 : extern char *optarg;
60 : extern int optind;
61 :
62 : fstring host, workgroup, share, password, username, myname;
63 : struct cli_credentials *torture_creds;
64 : static const char *sockops="TCP_NODELAY";
65 : int torture_nprocs=1;
66 : static int port_to_use=0;
67 : int torture_numops=100;
68 : int torture_blocksize=1024*1024;
69 : static int procnum; /* records process count number when forking */
70 : static struct cli_state *current_cli;
71 : static fstring randomfname;
72 : static bool use_oplocks;
73 : static bool use_level_II_oplocks;
74 : static const char *client_txt = "client_oplocks.txt";
75 : static bool disable_spnego;
76 : static bool use_kerberos;
77 : static bool force_dos_errors;
78 : static fstring multishare_conn_fname;
79 : static bool use_multishare_conn = False;
80 : static bool do_encrypt;
81 : static const char *local_path = NULL;
82 : static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
83 : char *test_filename;
84 :
85 : bool torture_showall = False;
86 :
87 : static double create_procs(bool (*fn)(int), bool *result);
88 :
89 : /********************************************************************
90 : Ensure a connection is encrypted.
91 : ********************************************************************/
92 :
93 200 : static bool force_cli_encryption(struct cli_state *c,
94 : const char *sharename)
95 : {
96 0 : uint16_t major, minor;
97 0 : uint32_t caplow, caphigh;
98 0 : NTSTATUS status;
99 :
100 200 : if (!SERVER_HAS_UNIX_CIFS(c)) {
101 0 : d_printf("Encryption required and "
102 : "server that doesn't support "
103 : "UNIX extensions - failing connect\n");
104 0 : return false;
105 : }
106 :
107 200 : status = cli_unix_extensions_version(c, &major, &minor, &caplow,
108 : &caphigh);
109 200 : if (!NT_STATUS_IS_OK(status)) {
110 0 : d_printf("Encryption required and "
111 : "can't get UNIX CIFS extensions "
112 : "version from server: %s\n", nt_errstr(status));
113 0 : return false;
114 : }
115 :
116 200 : if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
117 0 : d_printf("Encryption required and "
118 : "share %s doesn't support "
119 : "encryption.\n", sharename);
120 0 : return false;
121 : }
122 :
123 200 : status = cli_smb1_setup_encryption(c, torture_creds);
124 200 : if (!NT_STATUS_IS_OK(status)) {
125 0 : d_printf("Encryption required and "
126 : "setup failed with error %s.\n",
127 : nt_errstr(status));
128 0 : return false;
129 : }
130 :
131 200 : return true;
132 : }
133 :
134 :
135 100 : static struct cli_state *open_nbt_connection(void)
136 : {
137 0 : struct cli_state *c;
138 0 : NTSTATUS status;
139 100 : int flags = 0;
140 :
141 100 : if (disable_spnego) {
142 0 : flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
143 : }
144 :
145 100 : if (use_oplocks) {
146 0 : flags |= CLI_FULL_CONNECTION_OPLOCKS;
147 : }
148 :
149 100 : if (use_level_II_oplocks) {
150 0 : flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
151 : }
152 :
153 100 : if (force_dos_errors) {
154 0 : flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
155 : }
156 :
157 100 : status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
158 : signing_state, flags, &c);
159 100 : if (!NT_STATUS_IS_OK(status)) {
160 0 : printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
161 0 : return NULL;
162 : }
163 :
164 100 : cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
165 :
166 100 : return c;
167 : }
168 :
169 : /****************************************************************************
170 : Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
171 : ****************************************************************************/
172 :
173 4 : static bool cli_bad_session_request(int fd,
174 : struct nmb_name *calling, struct nmb_name *called)
175 : {
176 0 : TALLOC_CTX *frame;
177 0 : uint8_t len_buf[4];
178 0 : struct iovec iov[3];
179 0 : ssize_t len;
180 0 : uint8_t *inbuf;
181 0 : int err;
182 4 : bool ret = false;
183 0 : uint8_t message_type;
184 0 : uint8_t error;
185 0 : struct tevent_context *ev;
186 0 : struct tevent_req *req;
187 :
188 4 : frame = talloc_stackframe();
189 :
190 4 : iov[0].iov_base = len_buf;
191 4 : iov[0].iov_len = sizeof(len_buf);
192 :
193 : /* put in the destination name */
194 :
195 4 : iov[1].iov_base = name_mangle(talloc_tos(), called->name,
196 4 : called->name_type);
197 4 : if (iov[1].iov_base == NULL) {
198 0 : goto fail;
199 : }
200 4 : iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
201 4 : talloc_get_size(iov[1].iov_base));
202 :
203 : /* and my name */
204 :
205 4 : iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
206 4 : calling->name_type);
207 4 : if (iov[2].iov_base == NULL) {
208 0 : goto fail;
209 : }
210 4 : iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
211 4 : talloc_get_size(iov[2].iov_base));
212 :
213 : /* Deliberately corrupt the name len (first byte) */
214 4 : *((uint8_t *)iov[2].iov_base) = 100;
215 :
216 : /* send a session request (RFC 1002) */
217 : /* setup the packet length
218 : * Remove four bytes from the length count, since the length
219 : * field in the NBT Session Service header counts the number
220 : * of bytes which follow. The cli_send_smb() function knows
221 : * about this and accounts for those four bytes.
222 : * CRH.
223 : */
224 :
225 4 : _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
226 4 : SCVAL(len_buf,0,0x81);
227 :
228 4 : len = write_data_iov(fd, iov, 3);
229 4 : if (len == -1) {
230 0 : goto fail;
231 : }
232 :
233 4 : ev = samba_tevent_context_init(frame);
234 4 : if (ev == NULL) {
235 0 : goto fail;
236 : }
237 4 : req = read_smb_send(frame, ev, fd);
238 4 : if (req == NULL) {
239 0 : goto fail;
240 : }
241 4 : if (!tevent_req_poll(req, ev)) {
242 0 : goto fail;
243 : }
244 4 : len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
245 4 : if (len == -1) {
246 0 : errno = err;
247 0 : goto fail;
248 : }
249 4 : TALLOC_FREE(ev);
250 :
251 4 : message_type = CVAL(inbuf, 0);
252 4 : if (message_type != 0x83) {
253 0 : d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
254 : message_type);
255 0 : goto fail;
256 : }
257 :
258 4 : if (smb_len(inbuf) != 1) {
259 0 : d_fprintf(stderr, "Expected smb_len 1, got %d\n",
260 0 : (int)smb_len(inbuf));
261 0 : goto fail;
262 : }
263 :
264 4 : error = CVAL(inbuf, 4);
265 4 : if (error != 0x82) {
266 0 : d_fprintf(stderr, "Expected error 0x82, got %d\n",
267 : (int)error);
268 0 : goto fail;
269 : }
270 :
271 4 : ret = true;
272 4 : fail:
273 4 : TALLOC_FREE(frame);
274 4 : return ret;
275 : }
276 :
277 : /* Insert a NULL at the first separator of the given path and return a pointer
278 : * to the remainder of the string.
279 : */
280 : static char *
281 0 : terminate_path_at_separator(char * path)
282 : {
283 0 : char * p;
284 :
285 0 : if (!path) {
286 0 : return NULL;
287 : }
288 :
289 0 : if ((p = strchr_m(path, '/'))) {
290 0 : *p = '\0';
291 0 : return p + 1;
292 : }
293 :
294 0 : if ((p = strchr_m(path, '\\'))) {
295 0 : *p = '\0';
296 0 : return p + 1;
297 : }
298 :
299 : /* No separator. */
300 0 : return NULL;
301 : }
302 :
303 : /*
304 : parse a //server/share type UNC name
305 : */
306 0 : bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
307 : char **hostname, char **sharename)
308 : {
309 0 : char *p;
310 :
311 0 : *hostname = *sharename = NULL;
312 :
313 0 : if (strncmp(unc_name, "\\\\", 2) &&
314 0 : strncmp(unc_name, "//", 2)) {
315 0 : return False;
316 : }
317 :
318 0 : *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
319 0 : p = terminate_path_at_separator(*hostname);
320 :
321 0 : if (p && *p) {
322 0 : *sharename = talloc_strdup(mem_ctx, p);
323 0 : terminate_path_at_separator(*sharename);
324 : }
325 :
326 0 : if (*hostname && *sharename) {
327 0 : return True;
328 : }
329 :
330 0 : TALLOC_FREE(*hostname);
331 0 : TALLOC_FREE(*sharename);
332 0 : return False;
333 : }
334 :
335 497 : static bool torture_open_connection_share(struct cli_state **c,
336 : const char *hostname,
337 : const char *sharename,
338 : int flags)
339 : {
340 0 : NTSTATUS status;
341 :
342 497 : status = cli_full_connection_creds(c,
343 : myname,
344 : hostname,
345 : NULL, /* dest_ss */
346 : port_to_use,
347 : sharename,
348 : "?????",
349 : torture_creds,
350 : flags);
351 497 : if (!NT_STATUS_IS_OK(status)) {
352 2 : printf("failed to open share connection: //%s/%s port:%d - %s\n",
353 : hostname, sharename, port_to_use, nt_errstr(status));
354 2 : return False;
355 : }
356 :
357 495 : cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
358 :
359 495 : if (do_encrypt) {
360 198 : return force_cli_encryption(*c,
361 : sharename);
362 : }
363 297 : return True;
364 : }
365 :
366 497 : bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
367 : {
368 497 : char **unc_list = NULL;
369 497 : int num_unc_names = 0;
370 0 : bool result;
371 :
372 497 : if (use_multishare_conn==True) {
373 0 : char *h, *s;
374 0 : unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
375 0 : if (!unc_list || num_unc_names <= 0) {
376 0 : printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
377 0 : exit(1);
378 : }
379 :
380 0 : if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
381 : NULL, &h, &s)) {
382 0 : printf("Failed to parse UNC name %s\n",
383 0 : unc_list[conn_index % num_unc_names]);
384 0 : TALLOC_FREE(unc_list);
385 0 : exit(1);
386 : }
387 :
388 0 : result = torture_open_connection_share(c, h, s, flags);
389 :
390 : /* h, s were copied earlier */
391 0 : TALLOC_FREE(unc_list);
392 0 : return result;
393 : }
394 :
395 497 : return torture_open_connection_share(c, host, share, flags);
396 : }
397 :
398 485 : bool torture_open_connection(struct cli_state **c, int conn_index)
399 : {
400 485 : int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
401 :
402 485 : if (use_oplocks) {
403 8 : flags |= CLI_FULL_CONNECTION_OPLOCKS;
404 : }
405 485 : if (use_level_II_oplocks) {
406 8 : flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
407 : }
408 :
409 485 : return torture_open_connection_flags(c, conn_index, flags);
410 : }
411 :
412 90 : bool torture_init_connection(struct cli_state **pcli)
413 : {
414 0 : struct cli_state *cli;
415 :
416 90 : cli = open_nbt_connection();
417 90 : if (cli == NULL) {
418 0 : return false;
419 : }
420 :
421 90 : *pcli = cli;
422 90 : return true;
423 : }
424 :
425 5 : bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
426 : {
427 5 : uint16_t old_vuid = cli_state_get_uid(cli);
428 0 : NTSTATUS status;
429 0 : bool ret;
430 :
431 5 : cli_state_set_uid(cli, 0);
432 5 : status = cli_session_setup_creds(cli, torture_creds);
433 5 : ret = NT_STATUS_IS_OK(status);
434 5 : *new_vuid = cli_state_get_uid(cli);
435 5 : cli_state_set_uid(cli, old_vuid);
436 5 : return ret;
437 : }
438 :
439 :
440 421 : bool torture_close_connection(struct cli_state *c)
441 : {
442 421 : bool ret = True;
443 0 : NTSTATUS status;
444 :
445 421 : status = cli_tdis(c);
446 421 : if (!NT_STATUS_IS_OK(status)) {
447 5 : printf("tdis failed (%s)\n", nt_errstr(status));
448 5 : ret = False;
449 : }
450 :
451 421 : cli_shutdown(c);
452 :
453 421 : return ret;
454 : }
455 :
456 48 : void torture_conn_set_sockopt(struct cli_state *cli)
457 : {
458 48 : smbXcli_conn_set_sockopt(cli->conn, sockops);
459 48 : }
460 :
461 58 : static NTSTATUS torture_delete_fn(struct file_info *finfo,
462 : const char *pattern,
463 : void *state)
464 : {
465 0 : NTSTATUS status;
466 58 : char *filename = NULL;
467 58 : char *dirname = NULL;
468 58 : char *p = NULL;
469 58 : TALLOC_CTX *frame = talloc_stackframe();
470 58 : struct cli_state *cli = (struct cli_state *)state;
471 :
472 58 : if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
473 36 : TALLOC_FREE(frame);
474 36 : return NT_STATUS_OK;
475 : }
476 :
477 22 : dirname = talloc_strdup(frame, pattern);
478 22 : if (dirname == NULL) {
479 0 : TALLOC_FREE(frame);
480 0 : return NT_STATUS_NO_MEMORY;
481 : }
482 22 : p = strrchr_m(dirname, '\\');
483 22 : if (p != NULL) {
484 : /* Remove the terminating '\' */
485 22 : *p = '\0';
486 : }
487 22 : if (dirname[0] != '\0') {
488 22 : filename = talloc_asprintf(frame,
489 : "%s\\%s",
490 : dirname,
491 : finfo->name);
492 : } else {
493 0 : filename = talloc_asprintf(frame,
494 : "%s",
495 : finfo->name);
496 : }
497 22 : if (filename == NULL) {
498 0 : TALLOC_FREE(frame);
499 0 : return NT_STATUS_NO_MEMORY;
500 : }
501 22 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
502 5 : char *subdirname = talloc_asprintf(frame,
503 : "%s\\*",
504 : filename);
505 5 : if (subdirname == NULL) {
506 0 : TALLOC_FREE(frame);
507 0 : return NT_STATUS_NO_MEMORY;
508 : }
509 5 : status = cli_list(cli,
510 : subdirname,
511 : FILE_ATTRIBUTE_DIRECTORY |
512 : FILE_ATTRIBUTE_HIDDEN |
513 : FILE_ATTRIBUTE_SYSTEM,
514 : torture_delete_fn,
515 : cli);
516 5 : if (!NT_STATUS_IS_OK(status)) {
517 0 : printf("torture_delete_fn: cli_list "
518 : "of %s failed (%s)\n",
519 : subdirname,
520 : nt_errstr(status));
521 0 : TALLOC_FREE(frame);
522 0 : return status;
523 : }
524 5 : status = cli_rmdir(cli, filename);
525 : } else {
526 17 : status = cli_unlink(cli,
527 : filename,
528 : FILE_ATTRIBUTE_SYSTEM |
529 : FILE_ATTRIBUTE_HIDDEN);
530 : }
531 22 : if (!NT_STATUS_IS_OK(status)) {
532 0 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
533 0 : printf("torture_delete_fn: cli_rmdir"
534 : " of %s failed (%s)\n",
535 : filename,
536 : nt_errstr(status));
537 : } else {
538 0 : printf("torture_delete_fn: cli_unlink"
539 : " of %s failed (%s)\n",
540 : filename,
541 : nt_errstr(status));
542 : }
543 : }
544 22 : TALLOC_FREE(frame);
545 22 : return status;
546 : }
547 :
548 30 : void torture_deltree(struct cli_state *cli, const char *dname)
549 : {
550 30 : char *mask = NULL;
551 0 : NTSTATUS status;
552 :
553 : /* It might be a file */
554 30 : (void)cli_unlink(cli,
555 : dname,
556 : FILE_ATTRIBUTE_SYSTEM |
557 : FILE_ATTRIBUTE_HIDDEN);
558 :
559 30 : mask = talloc_asprintf(cli,
560 : "%s\\*",
561 : dname);
562 30 : if (mask == NULL) {
563 0 : printf("torture_deltree: talloc_asprintf failed\n");
564 0 : return;
565 : }
566 :
567 30 : status = cli_list(cli,
568 : mask,
569 : FILE_ATTRIBUTE_DIRECTORY |
570 : FILE_ATTRIBUTE_HIDDEN|
571 : FILE_ATTRIBUTE_SYSTEM,
572 : torture_delete_fn,
573 : cli);
574 30 : if (!NT_STATUS_IS_OK(status)) {
575 17 : printf("torture_deltree: cli_list of %s failed (%s)\n",
576 : mask,
577 : nt_errstr(status));
578 : }
579 30 : TALLOC_FREE(mask);
580 30 : status = cli_rmdir(cli, dname);
581 30 : if (!NT_STATUS_IS_OK(status)) {
582 17 : printf("torture_deltree: cli_rmdir of %s failed (%s)\n",
583 : dname,
584 : nt_errstr(status));
585 : }
586 : }
587 :
588 : /* check if the server produced the expected dos or nt error code */
589 53 : static bool check_both_error(int line, NTSTATUS status,
590 : uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
591 : {
592 53 : if (NT_STATUS_IS_DOS(status)) {
593 0 : uint8_t cclass;
594 0 : uint32_t num;
595 :
596 : /* Check DOS error */
597 0 : cclass = NT_STATUS_DOS_CLASS(status);
598 0 : num = NT_STATUS_DOS_CODE(status);
599 :
600 0 : if (eclass != cclass || ecode != num) {
601 0 : printf("unexpected error code class=%d code=%d\n",
602 : (int)cclass, (int)num);
603 0 : printf(" expected %d/%d %s (line=%d)\n",
604 : (int)eclass, (int)ecode, nt_errstr(nterr), line);
605 0 : return false;
606 : }
607 : } else {
608 : /* Check NT error */
609 53 : if (!NT_STATUS_EQUAL(nterr, status)) {
610 0 : printf("unexpected error code %s\n",
611 : nt_errstr(status));
612 0 : printf(" expected %s (line=%d)\n",
613 : nt_errstr(nterr), line);
614 0 : return false;
615 : }
616 : }
617 :
618 53 : return true;
619 : }
620 :
621 :
622 : /* check if the server produced the expected error code */
623 38 : static bool check_error(int line, NTSTATUS status,
624 : uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
625 : {
626 38 : if (NT_STATUS_IS_DOS(status)) {
627 0 : uint8_t cclass;
628 0 : uint32_t num;
629 :
630 : /* Check DOS error */
631 :
632 0 : cclass = NT_STATUS_DOS_CLASS(status);
633 0 : num = NT_STATUS_DOS_CODE(status);
634 :
635 0 : if (eclass != cclass || ecode != num) {
636 0 : printf("unexpected error code class=%d code=%d\n",
637 : (int)cclass, (int)num);
638 0 : printf(" expected %d/%d %s (line=%d)\n",
639 : (int)eclass, (int)ecode, nt_errstr(nterr),
640 : line);
641 0 : return False;
642 : }
643 :
644 : } else {
645 : /* Check NT error */
646 :
647 38 : if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
648 1 : printf("unexpected error code %s\n",
649 : nt_errstr(status));
650 1 : printf(" expected %s (line=%d)\n", nt_errstr(nterr),
651 : line);
652 1 : return False;
653 : }
654 : }
655 :
656 37 : return True;
657 : }
658 :
659 9 : NTSTATUS cli_qpathinfo1(struct cli_state *cli,
660 : const char *fname,
661 : time_t *change_time,
662 : time_t *access_time,
663 : time_t *write_time,
664 : off_t *size,
665 : uint32_t *pattr)
666 : {
667 9 : int timezone = smb1cli_conn_server_time_zone(cli->conn);
668 9 : time_t (*date_fn)(const void *buf, int serverzone) = NULL;
669 9 : uint8_t *rdata = NULL;
670 0 : uint32_t num_rdata;
671 0 : NTSTATUS status;
672 :
673 9 : status = cli_qpathinfo(talloc_tos(),
674 : cli,
675 : fname,
676 : SMB_INFO_STANDARD,
677 : 22,
678 : CLI_BUFFER_SIZE,
679 : &rdata,
680 : &num_rdata);
681 9 : if (!NT_STATUS_IS_OK(status)) {
682 4 : return status;
683 : }
684 5 : if (cli->win95) {
685 0 : date_fn = make_unix_date;
686 : } else {
687 5 : date_fn = make_unix_date2;
688 : }
689 :
690 5 : if (change_time) {
691 5 : *change_time = date_fn(rdata + 0, timezone);
692 : }
693 5 : if (access_time) {
694 5 : *access_time = date_fn(rdata + 4, timezone);
695 : }
696 5 : if (write_time) {
697 5 : *write_time = date_fn(rdata + 8, timezone);
698 : }
699 5 : if (size) {
700 5 : *size = PULL_LE_U32(rdata, 12);
701 : }
702 5 : if (pattr) {
703 0 : *pattr = PULL_LE_U16(rdata, l1_attrFile);
704 : }
705 5 : return NT_STATUS_OK;
706 : }
707 :
708 0 : static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
709 : {
710 0 : NTSTATUS status;
711 :
712 0 : status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
713 :
714 0 : while (!NT_STATUS_IS_OK(status)) {
715 0 : if (!check_both_error(__LINE__, status, ERRDOS,
716 0 : ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
717 0 : return false;
718 : }
719 :
720 0 : status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
721 : }
722 :
723 0 : return true;
724 : }
725 :
726 :
727 0 : static bool rw_torture(struct cli_state *c)
728 : {
729 0 : const char *lockfname = "\\torture.lck";
730 0 : fstring fname;
731 0 : uint16_t fnum;
732 0 : uint16_t fnum2;
733 0 : pid_t pid2, pid = getpid();
734 0 : int i, j;
735 0 : char buf[1024];
736 0 : bool correct = True;
737 0 : size_t nread = 0;
738 0 : NTSTATUS status;
739 :
740 0 : memset(buf, '\0', sizeof(buf));
741 :
742 0 : status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
743 : DENY_NONE, &fnum2);
744 0 : if (!NT_STATUS_IS_OK(status)) {
745 0 : status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
746 : }
747 0 : if (!NT_STATUS_IS_OK(status)) {
748 0 : printf("open of %s failed (%s)\n",
749 : lockfname, nt_errstr(status));
750 0 : return False;
751 : }
752 :
753 0 : for (i=0;i<torture_numops;i++) {
754 0 : unsigned n = (unsigned)sys_random()%10;
755 :
756 0 : if (i % 10 == 0) {
757 0 : printf("%d\r", i); fflush(stdout);
758 : }
759 0 : slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
760 :
761 0 : if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
762 0 : return False;
763 : }
764 :
765 0 : status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
766 : DENY_ALL, &fnum);
767 0 : if (!NT_STATUS_IS_OK(status)) {
768 0 : printf("open failed (%s)\n", nt_errstr(status));
769 0 : correct = False;
770 0 : break;
771 : }
772 :
773 0 : status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
774 : sizeof(pid), NULL);
775 0 : if (!NT_STATUS_IS_OK(status)) {
776 0 : printf("write failed (%s)\n", nt_errstr(status));
777 0 : correct = False;
778 : }
779 :
780 0 : for (j=0;j<50;j++) {
781 0 : status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
782 0 : sizeof(pid)+(j*sizeof(buf)),
783 : sizeof(buf), NULL);
784 0 : if (!NT_STATUS_IS_OK(status)) {
785 0 : printf("write failed (%s)\n",
786 : nt_errstr(status));
787 0 : correct = False;
788 : }
789 : }
790 :
791 0 : pid2 = 0;
792 :
793 0 : status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
794 : &nread);
795 0 : if (!NT_STATUS_IS_OK(status)) {
796 0 : printf("read failed (%s)\n", nt_errstr(status));
797 0 : correct = false;
798 0 : } else if (nread != sizeof(pid)) {
799 0 : printf("read/write compare failed: "
800 : "recv %ld req %ld\n", (unsigned long)nread,
801 : (unsigned long)sizeof(pid));
802 0 : correct = false;
803 : }
804 :
805 0 : if (pid2 != pid) {
806 0 : printf("data corruption!\n");
807 0 : correct = False;
808 : }
809 :
810 0 : status = cli_close(c, fnum);
811 0 : if (!NT_STATUS_IS_OK(status)) {
812 0 : printf("close failed (%s)\n", nt_errstr(status));
813 0 : correct = False;
814 : }
815 :
816 0 : status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
817 0 : if (!NT_STATUS_IS_OK(status)) {
818 0 : printf("unlink failed (%s)\n", nt_errstr(status));
819 0 : correct = False;
820 : }
821 :
822 0 : status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
823 0 : if (!NT_STATUS_IS_OK(status)) {
824 0 : printf("unlock failed (%s)\n", nt_errstr(status));
825 0 : correct = False;
826 : }
827 : }
828 :
829 0 : cli_close(c, fnum2);
830 0 : cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
831 :
832 0 : printf("%d\n", i);
833 :
834 0 : return correct;
835 : }
836 :
837 0 : static bool run_torture(int dummy)
838 : {
839 0 : struct cli_state *cli;
840 0 : bool ret;
841 :
842 0 : cli = current_cli;
843 :
844 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
845 :
846 0 : ret = rw_torture(cli);
847 :
848 0 : if (!torture_close_connection(cli)) {
849 0 : ret = False;
850 : }
851 :
852 0 : return ret;
853 : }
854 :
855 0 : static bool rw_torture3(struct cli_state *c, char *lockfname)
856 : {
857 0 : uint16_t fnum = (uint16_t)-1;
858 0 : unsigned int i = 0;
859 0 : char buf[131072];
860 0 : char buf_rd[131072];
861 0 : unsigned count;
862 0 : unsigned countprev = 0;
863 0 : size_t sent = 0;
864 0 : bool correct = True;
865 0 : NTSTATUS status = NT_STATUS_OK;
866 :
867 0 : srandom(1);
868 0 : for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
869 : {
870 0 : SIVAL(buf, i, sys_random());
871 : }
872 :
873 0 : if (procnum == 0)
874 : {
875 0 : status = cli_unlink(
876 : c, lockfname,
877 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
878 0 : if (!NT_STATUS_IS_OK(status)) {
879 0 : printf("unlink failed (%s) (normal, this file should "
880 : "not exist)\n", nt_errstr(status));
881 : }
882 :
883 0 : status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
884 : DENY_NONE, &fnum);
885 0 : if (!NT_STATUS_IS_OK(status)) {
886 0 : printf("first open read/write of %s failed (%s)\n",
887 : lockfname, nt_errstr(status));
888 0 : return False;
889 : }
890 : }
891 : else
892 : {
893 0 : for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
894 : {
895 0 : status = cli_openx(c, lockfname, O_RDONLY,
896 : DENY_NONE, &fnum);
897 0 : if (NT_STATUS_IS_OK(status)) {
898 0 : break;
899 : }
900 0 : smb_msleep(10);
901 : }
902 0 : if (!NT_STATUS_IS_OK(status)) {
903 0 : printf("second open read-only of %s failed (%s)\n",
904 : lockfname, nt_errstr(status));
905 0 : return False;
906 : }
907 : }
908 :
909 0 : i = 0;
910 0 : for (count = 0; count < sizeof(buf); count += sent)
911 : {
912 0 : if (count >= countprev) {
913 0 : printf("%d %8d\r", i, count);
914 0 : fflush(stdout);
915 0 : i++;
916 0 : countprev += (sizeof(buf) / 20);
917 : }
918 :
919 0 : if (procnum == 0)
920 : {
921 0 : sent = ((unsigned)sys_random()%(20))+ 1;
922 0 : if (sent > sizeof(buf) - count)
923 : {
924 0 : sent = sizeof(buf) - count;
925 : }
926 :
927 0 : status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
928 : count, sent, NULL);
929 0 : if (!NT_STATUS_IS_OK(status)) {
930 0 : printf("write failed (%s)\n",
931 : nt_errstr(status));
932 0 : correct = False;
933 : }
934 : }
935 : else
936 : {
937 0 : status = cli_read(c, fnum, buf_rd+count, count,
938 : sizeof(buf)-count, &sent);
939 0 : if(!NT_STATUS_IS_OK(status)) {
940 0 : printf("read failed offset:%d size:%ld (%s)\n",
941 : count, (unsigned long)sizeof(buf)-count,
942 : nt_errstr(status));
943 0 : correct = False;
944 0 : sent = 0;
945 0 : } else if (sent > 0) {
946 0 : if (memcmp(buf_rd+count, buf+count, sent) != 0)
947 : {
948 0 : printf("read/write compare failed\n");
949 0 : printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
950 0 : correct = False;
951 0 : break;
952 : }
953 : }
954 : }
955 :
956 : }
957 :
958 0 : status = cli_close(c, fnum);
959 0 : if (!NT_STATUS_IS_OK(status)) {
960 0 : printf("close failed (%s)\n", nt_errstr(status));
961 0 : correct = False;
962 : }
963 :
964 0 : return correct;
965 : }
966 :
967 18 : static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
968 : {
969 18 : const char *lockfname = "\\torture2.lck";
970 0 : uint16_t fnum1;
971 0 : uint16_t fnum2;
972 0 : int i;
973 0 : char buf[131072];
974 0 : char buf_rd[131072];
975 18 : bool correct = True;
976 0 : size_t bytes_read;
977 0 : NTSTATUS status;
978 :
979 18 : status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
980 18 : if (!NT_STATUS_IS_OK(status)) {
981 18 : printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
982 : }
983 :
984 18 : status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
985 : DENY_NONE, &fnum1);
986 18 : if (!NT_STATUS_IS_OK(status)) {
987 0 : printf("first open read/write of %s failed (%s)\n",
988 : lockfname, nt_errstr(status));
989 0 : return False;
990 : }
991 :
992 18 : status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
993 18 : if (!NT_STATUS_IS_OK(status)) {
994 0 : printf("second open read-only of %s failed (%s)\n",
995 : lockfname, nt_errstr(status));
996 0 : cli_close(c1, fnum1);
997 0 : return False;
998 : }
999 :
1000 1818 : for (i = 0; i < torture_numops; i++)
1001 : {
1002 1800 : size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
1003 1800 : if (i % 10 == 0) {
1004 180 : printf("%d\r", i); fflush(stdout);
1005 : }
1006 :
1007 1800 : generate_random_buffer((unsigned char *)buf, buf_size);
1008 :
1009 1800 : status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
1010 : buf_size, NULL);
1011 1800 : if (!NT_STATUS_IS_OK(status)) {
1012 0 : printf("write failed (%s)\n", nt_errstr(status));
1013 0 : correct = False;
1014 0 : break;
1015 : }
1016 :
1017 1800 : status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
1018 1800 : if(!NT_STATUS_IS_OK(status)) {
1019 0 : printf("read failed (%s)\n", nt_errstr(status));
1020 0 : correct = false;
1021 0 : break;
1022 1800 : } else if (bytes_read != buf_size) {
1023 0 : printf("read failed\n");
1024 0 : printf("read %ld, expected %ld\n",
1025 : (unsigned long)bytes_read,
1026 : (unsigned long)buf_size);
1027 0 : correct = False;
1028 0 : break;
1029 : }
1030 :
1031 1800 : if (memcmp(buf_rd, buf, buf_size) != 0)
1032 : {
1033 0 : printf("read/write compare failed\n");
1034 0 : correct = False;
1035 0 : break;
1036 : }
1037 : }
1038 :
1039 18 : status = cli_close(c2, fnum2);
1040 18 : if (!NT_STATUS_IS_OK(status)) {
1041 0 : printf("close failed (%s)\n", nt_errstr(status));
1042 0 : correct = False;
1043 : }
1044 :
1045 18 : status = cli_close(c1, fnum1);
1046 18 : if (!NT_STATUS_IS_OK(status)) {
1047 0 : printf("close failed (%s)\n", nt_errstr(status));
1048 0 : correct = False;
1049 : }
1050 :
1051 18 : status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1052 18 : if (!NT_STATUS_IS_OK(status)) {
1053 0 : printf("unlink failed (%s)\n", nt_errstr(status));
1054 0 : correct = False;
1055 : }
1056 :
1057 18 : return correct;
1058 : }
1059 :
1060 9 : static bool run_readwritetest(int dummy)
1061 : {
1062 0 : struct cli_state *cli1, *cli2;
1063 9 : bool test1, test2 = False;
1064 :
1065 9 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1066 0 : return False;
1067 : }
1068 9 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
1069 9 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
1070 :
1071 9 : printf("starting readwritetest\n");
1072 :
1073 9 : test1 = rw_torture2(cli1, cli2);
1074 9 : printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
1075 :
1076 9 : if (test1) {
1077 9 : test2 = rw_torture2(cli1, cli1);
1078 9 : printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
1079 : }
1080 :
1081 9 : if (!torture_close_connection(cli1)) {
1082 0 : test1 = False;
1083 : }
1084 :
1085 9 : if (!torture_close_connection(cli2)) {
1086 0 : test2 = False;
1087 : }
1088 :
1089 9 : return (test1 && test2);
1090 : }
1091 :
1092 0 : static bool run_readwritemulti(int dummy)
1093 : {
1094 0 : struct cli_state *cli;
1095 0 : bool test;
1096 :
1097 0 : cli = current_cli;
1098 :
1099 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1100 :
1101 0 : printf("run_readwritemulti: fname %s\n", randomfname);
1102 0 : test = rw_torture3(cli, randomfname);
1103 :
1104 0 : if (!torture_close_connection(cli)) {
1105 0 : test = False;
1106 : }
1107 :
1108 0 : return test;
1109 : }
1110 :
1111 14 : static bool run_readwritelarge_internal(void)
1112 : {
1113 0 : static struct cli_state *cli1;
1114 0 : uint16_t fnum1;
1115 14 : const char *lockfname = "\\large.dat";
1116 0 : off_t fsize;
1117 0 : char buf[126*1024];
1118 14 : bool correct = True;
1119 0 : NTSTATUS status;
1120 :
1121 14 : if (!torture_open_connection(&cli1, 0)) {
1122 0 : return False;
1123 : }
1124 14 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
1125 14 : memset(buf,'\0',sizeof(buf));
1126 :
1127 14 : printf("starting readwritelarge_internal\n");
1128 :
1129 14 : cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1130 :
1131 14 : status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1132 : DENY_NONE, &fnum1);
1133 14 : if (!NT_STATUS_IS_OK(status)) {
1134 0 : printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1135 0 : return False;
1136 : }
1137 :
1138 14 : cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1139 :
1140 14 : status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1141 : NULL, NULL, NULL);
1142 14 : if (!NT_STATUS_IS_OK(status)) {
1143 0 : printf("qfileinfo failed (%s)\n", nt_errstr(status));
1144 0 : correct = False;
1145 : }
1146 :
1147 14 : if (fsize == sizeof(buf))
1148 14 : printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1149 : (unsigned long)fsize);
1150 : else {
1151 0 : printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1152 : (unsigned long)fsize);
1153 0 : correct = False;
1154 : }
1155 :
1156 14 : status = cli_close(cli1, fnum1);
1157 14 : if (!NT_STATUS_IS_OK(status)) {
1158 0 : printf("close failed (%s)\n", nt_errstr(status));
1159 0 : correct = False;
1160 : }
1161 :
1162 14 : status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1163 14 : if (!NT_STATUS_IS_OK(status)) {
1164 0 : printf("unlink failed (%s)\n", nt_errstr(status));
1165 0 : correct = False;
1166 : }
1167 :
1168 14 : status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1169 : DENY_NONE, &fnum1);
1170 14 : if (!NT_STATUS_IS_OK(status)) {
1171 0 : printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1172 0 : return False;
1173 : }
1174 :
1175 14 : cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1176 :
1177 14 : status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1178 : NULL, NULL, NULL);
1179 14 : if (!NT_STATUS_IS_OK(status)) {
1180 0 : printf("qfileinfo failed (%s)\n", nt_errstr(status));
1181 0 : correct = False;
1182 : }
1183 :
1184 14 : if (fsize == sizeof(buf))
1185 14 : printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1186 : (unsigned long)fsize);
1187 : else {
1188 0 : printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1189 : (unsigned long)fsize);
1190 0 : correct = False;
1191 : }
1192 :
1193 14 : status = cli_close(cli1, fnum1);
1194 14 : if (!NT_STATUS_IS_OK(status)) {
1195 0 : printf("close failed (%s)\n", nt_errstr(status));
1196 0 : correct = False;
1197 : }
1198 :
1199 14 : if (!torture_close_connection(cli1)) {
1200 0 : correct = False;
1201 : }
1202 14 : return correct;
1203 : }
1204 :
1205 9 : static bool run_readwritelarge(int dummy)
1206 : {
1207 9 : return run_readwritelarge_internal();
1208 : }
1209 :
1210 5 : static bool run_readwritelarge_signtest(int dummy)
1211 : {
1212 0 : bool ret;
1213 5 : signing_state = SMB_SIGNING_REQUIRED;
1214 5 : ret = run_readwritelarge_internal();
1215 5 : signing_state = SMB_SIGNING_DEFAULT;
1216 5 : return ret;
1217 : }
1218 :
1219 : int line_count = 0;
1220 : int nbio_id;
1221 :
1222 : #define ival(s) strtol(s, NULL, 0)
1223 :
1224 : /* run a test that simulates an approximate netbench client load */
1225 0 : static bool run_netbench(int client)
1226 : {
1227 0 : struct cli_state *cli;
1228 0 : int i;
1229 0 : char line[1024];
1230 0 : char cname[20];
1231 0 : FILE *f;
1232 0 : const char *params[20];
1233 0 : bool correct = True;
1234 :
1235 0 : cli = current_cli;
1236 :
1237 0 : nbio_id = client;
1238 :
1239 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1240 :
1241 0 : nb_setup(cli);
1242 :
1243 0 : slprintf(cname,sizeof(cname)-1, "client%d", client);
1244 :
1245 0 : f = fopen(client_txt, "r");
1246 :
1247 0 : if (!f) {
1248 0 : perror(client_txt);
1249 0 : return False;
1250 : }
1251 :
1252 0 : while (fgets(line, sizeof(line)-1, f)) {
1253 0 : char *saveptr;
1254 0 : line_count++;
1255 :
1256 0 : line[strlen(line)-1] = 0;
1257 :
1258 : /* printf("[%d] %s\n", line_count, line); */
1259 :
1260 0 : all_string_sub(line,"client1", cname, sizeof(line));
1261 :
1262 : /* parse the command parameters */
1263 0 : params[0] = strtok_r(line, " ", &saveptr);
1264 0 : i = 0;
1265 0 : while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1266 :
1267 0 : params[i] = "";
1268 :
1269 0 : if (i < 2) continue;
1270 :
1271 0 : if (!strncmp(params[0],"SMB", 3)) {
1272 0 : printf("ERROR: You are using a dbench 1 load file\n");
1273 0 : exit(1);
1274 : }
1275 :
1276 0 : if (!strcmp(params[0],"NTCreateX")) {
1277 0 : nb_createx(params[1], ival(params[2]), ival(params[3]),
1278 0 : ival(params[4]));
1279 0 : } else if (!strcmp(params[0],"Close")) {
1280 0 : nb_close(ival(params[1]));
1281 0 : } else if (!strcmp(params[0],"Rename")) {
1282 0 : nb_rename(params[1], params[2]);
1283 0 : } else if (!strcmp(params[0],"Unlink")) {
1284 0 : nb_unlink(params[1]);
1285 0 : } else if (!strcmp(params[0],"Deltree")) {
1286 0 : nb_deltree(params[1]);
1287 0 : } else if (!strcmp(params[0],"Rmdir")) {
1288 0 : nb_rmdir(params[1]);
1289 0 : } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1290 0 : nb_qpathinfo(params[1]);
1291 0 : } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1292 0 : nb_qfileinfo(ival(params[1]));
1293 0 : } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1294 0 : nb_qfsinfo(ival(params[1]));
1295 0 : } else if (!strcmp(params[0],"FIND_FIRST")) {
1296 0 : nb_findfirst(params[1]);
1297 0 : } else if (!strcmp(params[0],"WriteX")) {
1298 0 : nb_writex(ival(params[1]),
1299 0 : ival(params[2]), ival(params[3]), ival(params[4]));
1300 0 : } else if (!strcmp(params[0],"ReadX")) {
1301 0 : nb_readx(ival(params[1]),
1302 0 : ival(params[2]), ival(params[3]), ival(params[4]));
1303 0 : } else if (!strcmp(params[0],"Flush")) {
1304 0 : nb_flush(ival(params[1]));
1305 : } else {
1306 0 : printf("Unknown operation %s\n", params[0]);
1307 0 : exit(1);
1308 : }
1309 : }
1310 0 : fclose(f);
1311 :
1312 0 : nb_cleanup();
1313 :
1314 0 : if (!torture_close_connection(cli)) {
1315 0 : correct = False;
1316 : }
1317 :
1318 0 : return correct;
1319 : }
1320 :
1321 :
1322 : /* run a test that simulates an approximate netbench client load */
1323 0 : static bool run_nbench(int dummy)
1324 : {
1325 0 : double t;
1326 0 : bool correct = True;
1327 :
1328 0 : nbio_shmem(torture_nprocs);
1329 :
1330 0 : nbio_id = -1;
1331 :
1332 0 : signal(SIGALRM, nb_alarm);
1333 0 : alarm(1);
1334 0 : t = create_procs(run_netbench, &correct);
1335 0 : alarm(0);
1336 :
1337 0 : printf("\nThroughput %g MB/sec\n",
1338 0 : 1.0e-6 * nbio_total() / t);
1339 0 : return correct;
1340 : }
1341 :
1342 :
1343 : /*
1344 : This test checks for two things:
1345 :
1346 : 1) correct support for retaining locks over a close (ie. the server
1347 : must not use posix semantics)
1348 : 2) support for lock timeouts
1349 : */
1350 5 : static bool run_locktest1(int dummy)
1351 : {
1352 0 : struct cli_state *cli1, *cli2;
1353 5 : const char *fname = "\\lockt1.lck";
1354 0 : uint16_t fnum1, fnum2, fnum3;
1355 0 : time_t t1, t2;
1356 0 : unsigned lock_timeout;
1357 0 : NTSTATUS status;
1358 :
1359 5 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1360 0 : return False;
1361 : }
1362 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
1363 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
1364 :
1365 5 : printf("starting locktest1\n");
1366 :
1367 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1368 :
1369 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1370 : &fnum1);
1371 5 : if (!NT_STATUS_IS_OK(status)) {
1372 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1373 0 : return False;
1374 : }
1375 :
1376 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1377 5 : if (!NT_STATUS_IS_OK(status)) {
1378 0 : printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1379 0 : return False;
1380 : }
1381 :
1382 5 : status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1383 5 : if (!NT_STATUS_IS_OK(status)) {
1384 0 : printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1385 0 : return False;
1386 : }
1387 :
1388 5 : status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1389 5 : if (!NT_STATUS_IS_OK(status)) {
1390 0 : printf("lock1 failed (%s)\n", nt_errstr(status));
1391 0 : return false;
1392 : }
1393 :
1394 5 : status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1395 5 : if (NT_STATUS_IS_OK(status)) {
1396 0 : printf("lock2 succeeded! This is a locking bug\n");
1397 0 : return false;
1398 : } else {
1399 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1400 5 : NT_STATUS_LOCK_NOT_GRANTED)) {
1401 0 : return false;
1402 : }
1403 : }
1404 :
1405 5 : lock_timeout = (1 + (random() % 20));
1406 5 : printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1407 5 : t1 = time(NULL);
1408 5 : status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1409 5 : if (NT_STATUS_IS_OK(status)) {
1410 0 : printf("lock3 succeeded! This is a locking bug\n");
1411 0 : return false;
1412 : } else {
1413 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1414 5 : NT_STATUS_FILE_LOCK_CONFLICT)) {
1415 0 : return false;
1416 : }
1417 : }
1418 5 : t2 = time(NULL);
1419 :
1420 5 : if (ABS(t2 - t1) < lock_timeout-1) {
1421 0 : printf("error: This server appears not to support timed lock requests\n");
1422 : }
1423 :
1424 5 : printf("server slept for %u seconds for a %u second timeout\n",
1425 : (unsigned int)(t2-t1), lock_timeout);
1426 :
1427 5 : status = cli_close(cli1, fnum2);
1428 5 : if (!NT_STATUS_IS_OK(status)) {
1429 0 : printf("close1 failed (%s)\n", nt_errstr(status));
1430 0 : return False;
1431 : }
1432 :
1433 5 : status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1434 5 : if (NT_STATUS_IS_OK(status)) {
1435 0 : printf("lock4 succeeded! This is a locking bug\n");
1436 0 : return false;
1437 : } else {
1438 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1439 5 : NT_STATUS_FILE_LOCK_CONFLICT)) {
1440 0 : return false;
1441 : }
1442 : }
1443 :
1444 5 : status = cli_close(cli1, fnum1);
1445 5 : if (!NT_STATUS_IS_OK(status)) {
1446 0 : printf("close2 failed (%s)\n", nt_errstr(status));
1447 0 : return False;
1448 : }
1449 :
1450 5 : status = cli_close(cli2, fnum3);
1451 5 : if (!NT_STATUS_IS_OK(status)) {
1452 0 : printf("close3 failed (%s)\n", nt_errstr(status));
1453 0 : return False;
1454 : }
1455 :
1456 5 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1457 5 : if (!NT_STATUS_IS_OK(status)) {
1458 0 : printf("unlink failed (%s)\n", nt_errstr(status));
1459 0 : return False;
1460 : }
1461 :
1462 :
1463 5 : if (!torture_close_connection(cli1)) {
1464 0 : return False;
1465 : }
1466 :
1467 5 : if (!torture_close_connection(cli2)) {
1468 0 : return False;
1469 : }
1470 :
1471 5 : printf("Passed locktest1\n");
1472 5 : return True;
1473 : }
1474 :
1475 : /*
1476 : this checks to see if a secondary tconx can use open files from an
1477 : earlier tconx
1478 : */
1479 5 : static bool run_tcon_test(int dummy)
1480 : {
1481 0 : static struct cli_state *cli;
1482 5 : const char *fname = "\\tcontest.tmp";
1483 0 : uint16_t fnum1;
1484 0 : uint32_t cnum1, cnum2, cnum3;
1485 5 : struct smbXcli_tcon *orig_tcon = NULL;
1486 5 : char *orig_share = NULL;
1487 0 : uint16_t vuid1, vuid2;
1488 0 : char buf[4];
1489 5 : bool ret = True;
1490 0 : NTSTATUS status;
1491 :
1492 5 : memset(buf, '\0', sizeof(buf));
1493 :
1494 5 : if (!torture_open_connection(&cli, 0)) {
1495 0 : return False;
1496 : }
1497 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1498 :
1499 5 : printf("starting tcontest\n");
1500 :
1501 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1502 :
1503 5 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1504 5 : if (!NT_STATUS_IS_OK(status)) {
1505 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1506 0 : return False;
1507 : }
1508 :
1509 5 : cnum1 = cli_state_get_tid(cli);
1510 5 : vuid1 = cli_state_get_uid(cli);
1511 :
1512 5 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1513 5 : if (!NT_STATUS_IS_OK(status)) {
1514 0 : printf("initial write failed (%s)", nt_errstr(status));
1515 0 : return False;
1516 : }
1517 :
1518 5 : cli_state_save_tcon_share(cli, &orig_tcon, &orig_share);
1519 :
1520 5 : status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1521 5 : if (!NT_STATUS_IS_OK(status)) {
1522 0 : printf("%s refused 2nd tree connect (%s)\n", host,
1523 : nt_errstr(status));
1524 0 : cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1525 0 : cli_shutdown(cli);
1526 0 : return False;
1527 : }
1528 :
1529 5 : cnum2 = cli_state_get_tid(cli);
1530 5 : cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1531 5 : vuid2 = cli_state_get_uid(cli) + 1;
1532 :
1533 : /* try a write with the wrong tid */
1534 5 : cli_state_set_tid(cli, cnum2);
1535 :
1536 5 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1537 5 : if (NT_STATUS_IS_OK(status)) {
1538 0 : printf("* server allows write with wrong TID\n");
1539 0 : ret = False;
1540 : } else {
1541 5 : printf("server fails write with wrong TID : %s\n",
1542 : nt_errstr(status));
1543 : }
1544 :
1545 :
1546 : /* try a write with an invalid tid */
1547 5 : cli_state_set_tid(cli, cnum3);
1548 :
1549 5 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1550 5 : if (NT_STATUS_IS_OK(status)) {
1551 0 : printf("* server allows write with invalid TID\n");
1552 0 : ret = False;
1553 : } else {
1554 5 : printf("server fails write with invalid TID : %s\n",
1555 : nt_errstr(status));
1556 : }
1557 :
1558 : /* try a write with an invalid vuid */
1559 5 : cli_state_set_uid(cli, vuid2);
1560 5 : cli_state_set_tid(cli, cnum1);
1561 :
1562 5 : status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1563 5 : if (NT_STATUS_IS_OK(status)) {
1564 0 : printf("* server allows write with invalid VUID\n");
1565 0 : ret = False;
1566 : } else {
1567 5 : printf("server fails write with invalid VUID : %s\n",
1568 : nt_errstr(status));
1569 : }
1570 :
1571 5 : cli_state_set_tid(cli, cnum1);
1572 5 : cli_state_set_uid(cli, vuid1);
1573 :
1574 5 : status = cli_close(cli, fnum1);
1575 5 : if (!NT_STATUS_IS_OK(status)) {
1576 0 : printf("close failed (%s)\n", nt_errstr(status));
1577 0 : cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1578 0 : cli_shutdown(cli);
1579 0 : return False;
1580 : }
1581 :
1582 5 : cli_state_set_tid(cli, cnum2);
1583 :
1584 5 : status = cli_tdis(cli);
1585 5 : if (!NT_STATUS_IS_OK(status)) {
1586 0 : printf("secondary tdis failed (%s)\n", nt_errstr(status));
1587 0 : cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1588 0 : cli_shutdown(cli);
1589 0 : return False;
1590 : }
1591 :
1592 5 : cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1593 :
1594 5 : cli_state_set_tid(cli, cnum1);
1595 :
1596 5 : if (!torture_close_connection(cli)) {
1597 0 : return False;
1598 : }
1599 :
1600 5 : return ret;
1601 : }
1602 :
1603 :
1604 : /*
1605 : checks for old style tcon support
1606 : */
1607 5 : static bool run_tcon2_test(int dummy)
1608 : {
1609 0 : static struct cli_state *cli;
1610 0 : uint16_t cnum, max_xmit;
1611 0 : char *service;
1612 0 : NTSTATUS status;
1613 :
1614 5 : if (!torture_open_connection(&cli, 0)) {
1615 0 : return False;
1616 : }
1617 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1618 :
1619 5 : printf("starting tcon2 test\n");
1620 :
1621 5 : if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1622 0 : return false;
1623 : }
1624 :
1625 5 : status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1626 :
1627 5 : SAFE_FREE(service);
1628 :
1629 5 : if (!NT_STATUS_IS_OK(status)) {
1630 5 : printf("tcon2 failed : %s\n", nt_errstr(status));
1631 : } else {
1632 0 : printf("tcon OK : max_xmit=%d cnum=%d\n",
1633 : (int)max_xmit, (int)cnum);
1634 : }
1635 :
1636 5 : if (!torture_close_connection(cli)) {
1637 0 : return False;
1638 : }
1639 :
1640 5 : printf("Passed tcon2 test\n");
1641 5 : return True;
1642 : }
1643 :
1644 50 : static bool tcon_devtest(struct cli_state *cli,
1645 : const char *myshare, const char *devtype,
1646 : const char *return_devtype,
1647 : NTSTATUS expected_error)
1648 : {
1649 0 : NTSTATUS status;
1650 0 : bool ret;
1651 :
1652 50 : status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1653 :
1654 50 : if (NT_STATUS_IS_OK(expected_error)) {
1655 20 : if (NT_STATUS_IS_OK(status)) {
1656 40 : if (return_devtype != NULL &&
1657 20 : strequal(cli->dev, return_devtype)) {
1658 20 : ret = True;
1659 : } else {
1660 0 : printf("tconX to share %s with type %s "
1661 : "succeeded but returned the wrong "
1662 : "device type (got [%s] but should have got [%s])\n",
1663 : myshare, devtype, cli->dev, return_devtype);
1664 0 : ret = False;
1665 : }
1666 : } else {
1667 0 : printf("tconX to share %s with type %s "
1668 : "should have succeeded but failed\n",
1669 : myshare, devtype);
1670 0 : ret = False;
1671 : }
1672 20 : cli_tdis(cli);
1673 : } else {
1674 30 : if (NT_STATUS_IS_OK(status)) {
1675 0 : printf("tconx to share %s with type %s "
1676 : "should have failed but succeeded\n",
1677 : myshare, devtype);
1678 0 : ret = False;
1679 : } else {
1680 30 : if (NT_STATUS_EQUAL(status, expected_error)) {
1681 30 : ret = True;
1682 : } else {
1683 0 : printf("Returned unexpected error\n");
1684 0 : ret = False;
1685 : }
1686 : }
1687 : }
1688 50 : return ret;
1689 : }
1690 :
1691 : /*
1692 : checks for correct tconX support
1693 : */
1694 5 : static bool run_tcon_devtype_test(int dummy)
1695 : {
1696 0 : static struct cli_state *cli1 = NULL;
1697 5 : int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1698 0 : NTSTATUS status;
1699 5 : bool ret = True;
1700 :
1701 5 : status = cli_full_connection_creds(&cli1,
1702 : myname,
1703 : host,
1704 : NULL, /* dest_ss */
1705 : port_to_use,
1706 : NULL, /* service */
1707 : NULL, /* service_type */
1708 : torture_creds,
1709 : flags);
1710 :
1711 5 : if (!NT_STATUS_IS_OK(status)) {
1712 0 : printf("could not open connection\n");
1713 0 : return False;
1714 : }
1715 :
1716 5 : if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1717 0 : ret = False;
1718 :
1719 5 : if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1720 0 : ret = False;
1721 :
1722 5 : if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1723 0 : ret = False;
1724 :
1725 5 : if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1726 0 : ret = False;
1727 :
1728 5 : if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1729 0 : ret = False;
1730 :
1731 5 : if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1732 0 : ret = False;
1733 :
1734 5 : if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1735 0 : ret = False;
1736 :
1737 5 : if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1738 0 : ret = False;
1739 :
1740 5 : if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1741 0 : ret = False;
1742 :
1743 5 : if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1744 0 : ret = False;
1745 :
1746 5 : cli_shutdown(cli1);
1747 :
1748 5 : if (ret)
1749 5 : printf("Passed tcondevtest\n");
1750 :
1751 5 : return ret;
1752 : }
1753 :
1754 :
1755 : /*
1756 : This test checks that
1757 :
1758 : 1) the server supports multiple locking contexts on the one SMB
1759 : connection, distinguished by PID.
1760 :
1761 : 2) the server correctly fails overlapping locks made by the same PID (this
1762 : goes against POSIX behaviour, which is why it is tricky to implement)
1763 :
1764 : 3) the server denies unlock requests by an incorrect client PID
1765 : */
1766 5 : static bool run_locktest2(int dummy)
1767 : {
1768 0 : static struct cli_state *cli;
1769 5 : const char *fname = "\\lockt2.lck";
1770 0 : uint16_t fnum1, fnum2, fnum3;
1771 5 : bool correct = True;
1772 0 : NTSTATUS status;
1773 :
1774 5 : if (!torture_open_connection(&cli, 0)) {
1775 0 : return False;
1776 : }
1777 :
1778 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
1779 :
1780 5 : printf("starting locktest2\n");
1781 :
1782 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1783 :
1784 5 : cli_setpid(cli, 1);
1785 :
1786 5 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1787 5 : if (!NT_STATUS_IS_OK(status)) {
1788 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1789 0 : return False;
1790 : }
1791 :
1792 5 : status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1793 5 : if (!NT_STATUS_IS_OK(status)) {
1794 0 : printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1795 0 : return False;
1796 : }
1797 :
1798 5 : cli_setpid(cli, 2);
1799 :
1800 5 : status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1801 5 : if (!NT_STATUS_IS_OK(status)) {
1802 0 : printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1803 0 : return False;
1804 : }
1805 :
1806 5 : cli_setpid(cli, 1);
1807 :
1808 5 : status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1809 5 : if (!NT_STATUS_IS_OK(status)) {
1810 0 : printf("lock1 failed (%s)\n", nt_errstr(status));
1811 0 : return false;
1812 : }
1813 :
1814 5 : status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1815 5 : if (NT_STATUS_IS_OK(status)) {
1816 0 : printf("WRITE lock1 succeeded! This is a locking bug\n");
1817 0 : correct = false;
1818 : } else {
1819 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1820 5 : NT_STATUS_LOCK_NOT_GRANTED)) {
1821 0 : return false;
1822 : }
1823 : }
1824 :
1825 5 : status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1826 5 : if (NT_STATUS_IS_OK(status)) {
1827 0 : printf("WRITE lock2 succeeded! This is a locking bug\n");
1828 0 : correct = false;
1829 : } else {
1830 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1831 5 : NT_STATUS_LOCK_NOT_GRANTED)) {
1832 0 : return false;
1833 : }
1834 : }
1835 :
1836 5 : status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1837 5 : if (NT_STATUS_IS_OK(status)) {
1838 0 : printf("READ lock2 succeeded! This is a locking bug\n");
1839 0 : correct = false;
1840 : } else {
1841 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1842 5 : NT_STATUS_FILE_LOCK_CONFLICT)) {
1843 0 : return false;
1844 : }
1845 : }
1846 :
1847 5 : status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1848 5 : if (!NT_STATUS_IS_OK(status)) {
1849 0 : printf("lock at 100 failed (%s)\n", nt_errstr(status));
1850 : }
1851 5 : cli_setpid(cli, 2);
1852 5 : if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1853 0 : printf("unlock at 100 succeeded! This is a locking bug\n");
1854 0 : correct = False;
1855 : }
1856 :
1857 5 : status = cli_unlock(cli, fnum1, 0, 4);
1858 5 : if (NT_STATUS_IS_OK(status)) {
1859 0 : printf("unlock1 succeeded! This is a locking bug\n");
1860 0 : correct = false;
1861 : } else {
1862 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1863 5 : NT_STATUS_RANGE_NOT_LOCKED)) {
1864 0 : return false;
1865 : }
1866 : }
1867 :
1868 5 : status = cli_unlock(cli, fnum1, 0, 8);
1869 5 : if (NT_STATUS_IS_OK(status)) {
1870 0 : printf("unlock2 succeeded! This is a locking bug\n");
1871 0 : correct = false;
1872 : } else {
1873 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1874 5 : NT_STATUS_RANGE_NOT_LOCKED)) {
1875 0 : return false;
1876 : }
1877 : }
1878 :
1879 5 : status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1880 5 : if (NT_STATUS_IS_OK(status)) {
1881 0 : printf("lock3 succeeded! This is a locking bug\n");
1882 0 : correct = false;
1883 : } else {
1884 5 : if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1885 5 : NT_STATUS_LOCK_NOT_GRANTED)) {
1886 0 : return false;
1887 : }
1888 : }
1889 :
1890 5 : cli_setpid(cli, 1);
1891 :
1892 5 : status = cli_close(cli, fnum1);
1893 5 : if (!NT_STATUS_IS_OK(status)) {
1894 0 : printf("close1 failed (%s)\n", nt_errstr(status));
1895 0 : return False;
1896 : }
1897 :
1898 5 : status = cli_close(cli, fnum2);
1899 5 : if (!NT_STATUS_IS_OK(status)) {
1900 0 : printf("close2 failed (%s)\n", nt_errstr(status));
1901 0 : return False;
1902 : }
1903 :
1904 5 : status = cli_close(cli, fnum3);
1905 5 : if (!NT_STATUS_IS_OK(status)) {
1906 0 : printf("close3 failed (%s)\n", nt_errstr(status));
1907 0 : return False;
1908 : }
1909 :
1910 5 : if (!torture_close_connection(cli)) {
1911 0 : correct = False;
1912 : }
1913 :
1914 5 : printf("locktest2 finished\n");
1915 :
1916 5 : return correct;
1917 : }
1918 :
1919 :
1920 : /*
1921 : This test checks that
1922 :
1923 : 1) the server supports the full offset range in lock requests
1924 : */
1925 5 : static bool run_locktest3(int dummy)
1926 : {
1927 0 : static struct cli_state *cli1, *cli2;
1928 5 : const char *fname = "\\lockt3.lck";
1929 0 : uint16_t fnum1, fnum2;
1930 0 : int i;
1931 0 : uint32_t offset;
1932 5 : bool correct = True;
1933 0 : NTSTATUS status;
1934 :
1935 : #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1936 :
1937 5 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1938 0 : return False;
1939 : }
1940 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
1941 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
1942 :
1943 5 : printf("starting locktest3\n");
1944 :
1945 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1946 :
1947 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1948 : &fnum1);
1949 5 : if (!NT_STATUS_IS_OK(status)) {
1950 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1951 0 : return False;
1952 : }
1953 :
1954 5 : status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1955 5 : if (!NT_STATUS_IS_OK(status)) {
1956 0 : printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1957 0 : return False;
1958 : }
1959 :
1960 505 : for (offset=i=0;i<torture_numops;i++) {
1961 500 : NEXT_OFFSET;
1962 :
1963 500 : status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1964 500 : if (!NT_STATUS_IS_OK(status)) {
1965 0 : printf("lock1 %d failed (%s)\n",
1966 : i,
1967 : nt_errstr(status));
1968 0 : return False;
1969 : }
1970 :
1971 500 : status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1972 500 : if (!NT_STATUS_IS_OK(status)) {
1973 0 : printf("lock2 %d failed (%s)\n",
1974 : i,
1975 : nt_errstr(status));
1976 0 : return False;
1977 : }
1978 : }
1979 :
1980 505 : for (offset=i=0;i<torture_numops;i++) {
1981 500 : NEXT_OFFSET;
1982 :
1983 500 : status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1984 500 : if (NT_STATUS_IS_OK(status)) {
1985 0 : printf("error: lock1 %d succeeded!\n", i);
1986 0 : return False;
1987 : }
1988 :
1989 500 : status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1990 500 : if (NT_STATUS_IS_OK(status)) {
1991 0 : printf("error: lock2 %d succeeded!\n", i);
1992 0 : return False;
1993 : }
1994 :
1995 500 : status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1996 500 : if (NT_STATUS_IS_OK(status)) {
1997 0 : printf("error: lock3 %d succeeded!\n", i);
1998 0 : return False;
1999 : }
2000 :
2001 500 : status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
2002 500 : if (NT_STATUS_IS_OK(status)) {
2003 0 : printf("error: lock4 %d succeeded!\n", i);
2004 0 : return False;
2005 : }
2006 : }
2007 :
2008 505 : for (offset=i=0;i<torture_numops;i++) {
2009 500 : NEXT_OFFSET;
2010 :
2011 500 : status = cli_unlock(cli1, fnum1, offset-1, 1);
2012 500 : if (!NT_STATUS_IS_OK(status)) {
2013 0 : printf("unlock1 %d failed (%s)\n",
2014 : i,
2015 : nt_errstr(status));
2016 0 : return False;
2017 : }
2018 :
2019 500 : status = cli_unlock(cli2, fnum2, offset-2, 1);
2020 500 : if (!NT_STATUS_IS_OK(status)) {
2021 0 : printf("unlock2 %d failed (%s)\n",
2022 : i,
2023 : nt_errstr(status));
2024 0 : return False;
2025 : }
2026 : }
2027 :
2028 5 : status = cli_close(cli1, fnum1);
2029 5 : if (!NT_STATUS_IS_OK(status)) {
2030 0 : printf("close1 failed (%s)\n", nt_errstr(status));
2031 0 : return False;
2032 : }
2033 :
2034 5 : status = cli_close(cli2, fnum2);
2035 5 : if (!NT_STATUS_IS_OK(status)) {
2036 0 : printf("close2 failed (%s)\n", nt_errstr(status));
2037 0 : return False;
2038 : }
2039 :
2040 5 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2041 5 : if (!NT_STATUS_IS_OK(status)) {
2042 0 : printf("unlink failed (%s)\n", nt_errstr(status));
2043 0 : return False;
2044 : }
2045 :
2046 5 : if (!torture_close_connection(cli1)) {
2047 0 : correct = False;
2048 : }
2049 :
2050 5 : if (!torture_close_connection(cli2)) {
2051 0 : correct = False;
2052 : }
2053 :
2054 5 : printf("finished locktest3\n");
2055 :
2056 5 : return correct;
2057 : }
2058 :
2059 40 : static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
2060 : char *buf, off_t offset, size_t size,
2061 : size_t *nread, size_t expect)
2062 : {
2063 0 : NTSTATUS status;
2064 0 : size_t l_nread;
2065 :
2066 40 : status = cli_read(cli, fnum, buf, offset, size, &l_nread);
2067 :
2068 40 : if(!NT_STATUS_IS_OK(status)) {
2069 20 : return false;
2070 20 : } else if (l_nread != expect) {
2071 0 : return false;
2072 : }
2073 :
2074 20 : if (nread) {
2075 0 : *nread = l_nread;
2076 : }
2077 :
2078 20 : return true;
2079 : }
2080 :
2081 : #define EXPECTED(ret, v) if ((ret) != (v)) { \
2082 : printf("** "); correct = False; \
2083 : }
2084 :
2085 : /*
2086 : looks at overlapping locks
2087 : */
2088 5 : static bool run_locktest4(int dummy)
2089 : {
2090 0 : static struct cli_state *cli1, *cli2;
2091 5 : const char *fname = "\\lockt4.lck";
2092 0 : uint16_t fnum1, fnum2, f;
2093 0 : bool ret;
2094 0 : char buf[1000];
2095 5 : bool correct = True;
2096 0 : NTSTATUS status;
2097 :
2098 5 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2099 0 : return False;
2100 : }
2101 :
2102 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2103 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
2104 :
2105 5 : printf("starting locktest4\n");
2106 :
2107 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2108 :
2109 5 : cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2110 5 : cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2111 :
2112 5 : memset(buf, 0, sizeof(buf));
2113 :
2114 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2115 : NULL);
2116 5 : if (!NT_STATUS_IS_OK(status)) {
2117 0 : printf("Failed to create file: %s\n", nt_errstr(status));
2118 0 : correct = False;
2119 0 : goto fail;
2120 : }
2121 :
2122 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2123 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
2124 5 : EXPECTED(ret, False);
2125 5 : printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2126 :
2127 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2128 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2129 5 : EXPECTED(ret, True);
2130 5 : printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2131 :
2132 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2133 5 : NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2134 5 : EXPECTED(ret, False);
2135 5 : printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2136 :
2137 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2138 5 : NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2139 5 : EXPECTED(ret, True);
2140 5 : printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2141 :
2142 5 : ret = (cli_setpid(cli1, 1),
2143 10 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2144 5 : (cli_setpid(cli1, 2),
2145 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2146 5 : EXPECTED(ret, False);
2147 5 : printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2148 :
2149 5 : ret = (cli_setpid(cli1, 1),
2150 10 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2151 5 : (cli_setpid(cli1, 2),
2152 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2153 5 : EXPECTED(ret, True);
2154 5 : printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2155 :
2156 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2157 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2158 5 : EXPECTED(ret, True);
2159 5 : printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2160 :
2161 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2162 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2163 5 : EXPECTED(ret, False);
2164 5 : printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2165 :
2166 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2167 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2168 5 : EXPECTED(ret, False);
2169 5 : printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2170 :
2171 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2172 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2173 5 : EXPECTED(ret, True);
2174 5 : printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2175 :
2176 5 : ret = (cli_setpid(cli1, 1),
2177 10 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2178 5 : (cli_setpid(cli1, 2),
2179 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2180 5 : EXPECTED(ret, False);
2181 5 : printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2182 :
2183 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2184 10 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2185 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2186 5 : EXPECTED(ret, False);
2187 5 : printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2188 :
2189 :
2190 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2191 5 : test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2192 5 : EXPECTED(ret, False);
2193 5 : printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2194 :
2195 5 : status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2196 5 : ret = NT_STATUS_IS_OK(status);
2197 5 : if (ret) {
2198 5 : status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2199 : NULL);
2200 5 : ret = NT_STATUS_IS_OK(status);
2201 : }
2202 5 : EXPECTED(ret, False);
2203 5 : printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2204 :
2205 :
2206 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2207 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2208 15 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2209 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2210 5 : EXPECTED(ret, True);
2211 5 : printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2212 :
2213 :
2214 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2215 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2216 10 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2217 5 : test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2218 5 : !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2219 10 : 150, 4, NULL))) &&
2220 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2221 5 : EXPECTED(ret, True);
2222 5 : printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2223 :
2224 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2225 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2226 5 : NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2227 10 : 160, 4, NULL)) &&
2228 5 : test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2229 5 : EXPECTED(ret, True);
2230 5 : printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2231 :
2232 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2233 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2234 5 : NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2235 10 : 170, 4, NULL)) &&
2236 5 : test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2237 5 : EXPECTED(ret, True);
2238 5 : printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2239 :
2240 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2241 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2242 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2243 5 : !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2244 10 : 190, 4, NULL)) &&
2245 5 : test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2246 5 : EXPECTED(ret, True);
2247 5 : printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2248 :
2249 5 : cli_close(cli1, fnum1);
2250 5 : cli_close(cli2, fnum2);
2251 5 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2252 5 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2253 5 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2254 5 : NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2255 5 : NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2256 15 : NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2257 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2258 5 : cli_close(cli1, f);
2259 5 : cli_close(cli1, fnum1);
2260 5 : EXPECTED(ret, True);
2261 5 : printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2262 :
2263 5 : fail:
2264 5 : cli_close(cli1, fnum1);
2265 5 : cli_close(cli2, fnum2);
2266 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2267 5 : torture_close_connection(cli1);
2268 5 : torture_close_connection(cli2);
2269 :
2270 5 : printf("finished locktest4\n");
2271 5 : return correct;
2272 : }
2273 :
2274 : /*
2275 : looks at lock upgrade/downgrade.
2276 : */
2277 5 : static bool run_locktest5(int dummy)
2278 : {
2279 0 : static struct cli_state *cli1, *cli2;
2280 5 : const char *fname = "\\lockt5.lck";
2281 0 : uint16_t fnum1, fnum2, fnum3;
2282 0 : bool ret;
2283 0 : char buf[1000];
2284 5 : bool correct = True;
2285 0 : NTSTATUS status;
2286 :
2287 5 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2288 0 : return False;
2289 : }
2290 :
2291 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2292 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
2293 :
2294 5 : printf("starting locktest5\n");
2295 :
2296 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2297 :
2298 5 : cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2299 5 : cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2300 5 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2301 :
2302 5 : memset(buf, 0, sizeof(buf));
2303 :
2304 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2305 : NULL);
2306 5 : if (!NT_STATUS_IS_OK(status)) {
2307 0 : printf("Failed to create file: %s\n", nt_errstr(status));
2308 0 : correct = False;
2309 0 : goto fail;
2310 : }
2311 :
2312 : /* Check for NT bug... */
2313 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2314 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2315 5 : cli_close(cli1, fnum1);
2316 5 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2317 5 : status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2318 5 : ret = NT_STATUS_IS_OK(status);
2319 5 : EXPECTED(ret, True);
2320 5 : printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2321 5 : cli_close(cli1, fnum1);
2322 5 : cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2323 5 : cli_unlock(cli1, fnum3, 0, 1);
2324 :
2325 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2326 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2327 5 : EXPECTED(ret, True);
2328 5 : printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2329 :
2330 5 : status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2331 5 : ret = NT_STATUS_IS_OK(status);
2332 5 : EXPECTED(ret, False);
2333 :
2334 5 : printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2335 :
2336 : /* Unlock the process 2 lock. */
2337 5 : cli_unlock(cli2, fnum2, 0, 4);
2338 :
2339 5 : status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2340 5 : ret = NT_STATUS_IS_OK(status);
2341 5 : EXPECTED(ret, False);
2342 :
2343 5 : printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2344 :
2345 : /* Unlock the process 1 fnum3 lock. */
2346 5 : cli_unlock(cli1, fnum3, 0, 4);
2347 :
2348 : /* Stack 2 more locks here. */
2349 10 : ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2350 5 : NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2351 :
2352 5 : EXPECTED(ret, True);
2353 5 : printf("the same process %s stack read locks\n", ret?"can":"cannot");
2354 :
2355 : /* Unlock the first process lock, then check this was the WRITE lock that was
2356 : removed. */
2357 :
2358 10 : ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2359 5 : NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2360 :
2361 5 : EXPECTED(ret, True);
2362 5 : printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2363 :
2364 : /* Unlock the process 2 lock. */
2365 5 : cli_unlock(cli2, fnum2, 0, 4);
2366 :
2367 : /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2368 :
2369 5 : ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2370 10 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2371 5 : NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2372 :
2373 5 : EXPECTED(ret, True);
2374 5 : printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2375 :
2376 : /* Ensure the next unlock fails. */
2377 5 : ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2378 5 : EXPECTED(ret, False);
2379 5 : printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2380 :
2381 : /* Ensure connection 2 can get a write lock. */
2382 5 : status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2383 5 : ret = NT_STATUS_IS_OK(status);
2384 5 : EXPECTED(ret, True);
2385 :
2386 5 : printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2387 :
2388 :
2389 5 : fail:
2390 5 : cli_close(cli1, fnum1);
2391 5 : cli_close(cli2, fnum2);
2392 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2393 5 : if (!torture_close_connection(cli1)) {
2394 0 : correct = False;
2395 : }
2396 5 : if (!torture_close_connection(cli2)) {
2397 0 : correct = False;
2398 : }
2399 :
2400 5 : printf("finished locktest5\n");
2401 :
2402 5 : return correct;
2403 : }
2404 :
2405 : /*
2406 : tries the unusual lockingX locktype bits
2407 : */
2408 5 : static bool run_locktest6(int dummy)
2409 : {
2410 0 : static struct cli_state *cli;
2411 5 : const char *fname[1] = { "\\lock6.txt" };
2412 0 : int i;
2413 0 : uint16_t fnum;
2414 0 : NTSTATUS status;
2415 :
2416 5 : if (!torture_open_connection(&cli, 0)) {
2417 0 : return False;
2418 : }
2419 :
2420 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
2421 :
2422 5 : printf("starting locktest6\n");
2423 :
2424 10 : for (i=0;i<1;i++) {
2425 5 : printf("Testing %s\n", fname[i]);
2426 :
2427 5 : cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2428 :
2429 5 : cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2430 5 : status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2431 5 : cli_close(cli, fnum);
2432 5 : printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2433 :
2434 5 : cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2435 5 : status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2436 5 : cli_close(cli, fnum);
2437 5 : printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2438 :
2439 5 : cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2440 : }
2441 :
2442 5 : torture_close_connection(cli);
2443 :
2444 5 : printf("finished locktest6\n");
2445 5 : return True;
2446 : }
2447 :
2448 5 : static bool run_locktest7(int dummy)
2449 : {
2450 0 : struct cli_state *cli1;
2451 5 : const char *fname = "\\lockt7.lck";
2452 0 : uint16_t fnum1;
2453 0 : char buf[200];
2454 5 : bool correct = False;
2455 0 : size_t nread;
2456 0 : NTSTATUS status;
2457 :
2458 5 : if (!torture_open_connection(&cli1, 0)) {
2459 0 : return False;
2460 : }
2461 :
2462 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2463 :
2464 5 : printf("starting locktest7\n");
2465 :
2466 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2467 :
2468 5 : cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2469 :
2470 5 : memset(buf, 0, sizeof(buf));
2471 :
2472 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2473 : NULL);
2474 5 : if (!NT_STATUS_IS_OK(status)) {
2475 0 : printf("Failed to create file: %s\n", nt_errstr(status));
2476 0 : goto fail;
2477 : }
2478 :
2479 5 : cli_setpid(cli1, 1);
2480 :
2481 5 : status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2482 5 : if (!NT_STATUS_IS_OK(status)) {
2483 0 : printf("Unable to apply read lock on range 130:4, "
2484 : "error was %s\n", nt_errstr(status));
2485 0 : goto fail;
2486 : } else {
2487 5 : printf("pid1 successfully locked range 130:4 for READ\n");
2488 : }
2489 :
2490 5 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2491 5 : if (!NT_STATUS_IS_OK(status)) {
2492 0 : printf("pid1 unable to read the range 130:4, error was %s\n",
2493 : nt_errstr(status));
2494 0 : goto fail;
2495 5 : } else if (nread != 4) {
2496 0 : printf("pid1 unable to read the range 130:4, "
2497 : "recv %ld req %d\n", (unsigned long)nread, 4);
2498 0 : goto fail;
2499 : } else {
2500 5 : printf("pid1 successfully read the range 130:4\n");
2501 : }
2502 :
2503 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2504 5 : if (!NT_STATUS_IS_OK(status)) {
2505 5 : printf("pid1 unable to write to the range 130:4, error was "
2506 : "%s\n", nt_errstr(status));
2507 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2508 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2509 0 : goto fail;
2510 : }
2511 : } else {
2512 0 : printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2513 0 : goto fail;
2514 : }
2515 :
2516 5 : cli_setpid(cli1, 2);
2517 :
2518 5 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2519 5 : if (!NT_STATUS_IS_OK(status)) {
2520 0 : printf("pid2 unable to read the range 130:4, error was %s\n",
2521 : nt_errstr(status));
2522 0 : goto fail;
2523 5 : } else if (nread != 4) {
2524 0 : printf("pid2 unable to read the range 130:4, "
2525 : "recv %ld req %d\n", (unsigned long)nread, 4);
2526 0 : goto fail;
2527 : } else {
2528 5 : printf("pid2 successfully read the range 130:4\n");
2529 : }
2530 :
2531 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2532 5 : if (!NT_STATUS_IS_OK(status)) {
2533 5 : printf("pid2 unable to write to the range 130:4, error was "
2534 : "%s\n", nt_errstr(status));
2535 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2536 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2537 0 : goto fail;
2538 : }
2539 : } else {
2540 0 : printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2541 0 : goto fail;
2542 : }
2543 :
2544 5 : cli_setpid(cli1, 1);
2545 5 : cli_unlock(cli1, fnum1, 130, 4);
2546 :
2547 5 : status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2548 5 : if (!NT_STATUS_IS_OK(status)) {
2549 0 : printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2550 0 : goto fail;
2551 : } else {
2552 5 : printf("pid1 successfully locked range 130:4 for WRITE\n");
2553 : }
2554 :
2555 5 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2556 5 : if (!NT_STATUS_IS_OK(status)) {
2557 0 : printf("pid1 unable to read the range 130:4, error was %s\n",
2558 : nt_errstr(status));
2559 0 : goto fail;
2560 5 : } else if (nread != 4) {
2561 0 : printf("pid1 unable to read the range 130:4, "
2562 : "recv %ld req %d\n", (unsigned long)nread, 4);
2563 0 : goto fail;
2564 : } else {
2565 5 : printf("pid1 successfully read the range 130:4\n");
2566 : }
2567 :
2568 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2569 5 : if (!NT_STATUS_IS_OK(status)) {
2570 0 : printf("pid1 unable to write to the range 130:4, error was "
2571 : "%s\n", nt_errstr(status));
2572 0 : goto fail;
2573 : } else {
2574 5 : printf("pid1 successfully wrote to the range 130:4\n");
2575 : }
2576 :
2577 5 : cli_setpid(cli1, 2);
2578 :
2579 5 : status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2580 5 : if (!NT_STATUS_IS_OK(status)) {
2581 5 : printf("pid2 unable to read the range 130:4, error was "
2582 : "%s\n", nt_errstr(status));
2583 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2584 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2585 0 : goto fail;
2586 : }
2587 : } else {
2588 0 : printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2589 : (unsigned long)nread);
2590 0 : goto fail;
2591 : }
2592 :
2593 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2594 5 : if (!NT_STATUS_IS_OK(status)) {
2595 5 : printf("pid2 unable to write to the range 130:4, error was "
2596 : "%s\n", nt_errstr(status));
2597 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2598 0 : printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2599 0 : goto fail;
2600 : }
2601 : } else {
2602 0 : printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2603 0 : goto fail;
2604 : }
2605 :
2606 5 : cli_unlock(cli1, fnum1, 130, 0);
2607 5 : correct = True;
2608 :
2609 5 : fail:
2610 5 : cli_close(cli1, fnum1);
2611 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2612 5 : torture_close_connection(cli1);
2613 :
2614 5 : printf("finished locktest7\n");
2615 5 : return correct;
2616 : }
2617 :
2618 : /*
2619 : * This demonstrates a problem with our use of GPFS share modes: A file
2620 : * descriptor sitting in the pending close queue holding a GPFS share mode
2621 : * blocks opening a file another time. Happens with Word 2007 temp files.
2622 : * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2623 : * open is denied with NT_STATUS_SHARING_VIOLATION.
2624 : */
2625 :
2626 0 : static bool run_locktest8(int dummy)
2627 : {
2628 0 : struct cli_state *cli1;
2629 0 : const char *fname = "\\lockt8.lck";
2630 0 : uint16_t fnum1, fnum2;
2631 0 : char buf[200];
2632 0 : bool correct = False;
2633 0 : NTSTATUS status;
2634 :
2635 0 : if (!torture_open_connection(&cli1, 0)) {
2636 0 : return False;
2637 : }
2638 :
2639 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2640 :
2641 0 : printf("starting locktest8\n");
2642 :
2643 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2644 :
2645 0 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2646 : &fnum1);
2647 0 : if (!NT_STATUS_IS_OK(status)) {
2648 0 : d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2649 0 : return false;
2650 : }
2651 :
2652 0 : memset(buf, 0, sizeof(buf));
2653 :
2654 0 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2655 0 : if (!NT_STATUS_IS_OK(status)) {
2656 0 : d_fprintf(stderr, "cli_openx second time returned %s\n",
2657 : nt_errstr(status));
2658 0 : goto fail;
2659 : }
2660 :
2661 0 : status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2662 0 : if (!NT_STATUS_IS_OK(status)) {
2663 0 : printf("Unable to apply read lock on range 1:1, error was "
2664 : "%s\n", nt_errstr(status));
2665 0 : goto fail;
2666 : }
2667 :
2668 0 : status = cli_close(cli1, fnum1);
2669 0 : if (!NT_STATUS_IS_OK(status)) {
2670 0 : d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2671 0 : goto fail;
2672 : }
2673 :
2674 0 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2675 0 : if (!NT_STATUS_IS_OK(status)) {
2676 0 : d_fprintf(stderr, "cli_openx third time returned %s\n",
2677 : nt_errstr(status));
2678 0 : goto fail;
2679 : }
2680 :
2681 0 : correct = true;
2682 :
2683 0 : fail:
2684 0 : cli_close(cli1, fnum1);
2685 0 : cli_close(cli1, fnum2);
2686 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2687 0 : torture_close_connection(cli1);
2688 :
2689 0 : printf("finished locktest8\n");
2690 0 : return correct;
2691 : }
2692 :
2693 : /*
2694 : * This test is designed to be run in conjunction with
2695 : * external NFS or POSIX locks taken in the filesystem.
2696 : * It checks that the smbd server will block until the
2697 : * lock is released and then acquire it. JRA.
2698 : */
2699 :
2700 : static bool got_alarm;
2701 : static struct cli_state *alarm_cli;
2702 :
2703 0 : static void alarm_handler(int dummy)
2704 : {
2705 0 : got_alarm = True;
2706 0 : }
2707 :
2708 0 : static void alarm_handler_parent(int dummy)
2709 : {
2710 0 : smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2711 0 : }
2712 :
2713 8 : static void do_local_lock(const char *fname, int read_fd, int write_fd)
2714 : {
2715 0 : int fd;
2716 8 : char c = '\0';
2717 0 : struct flock lock;
2718 8 : const char *local_pathname = NULL;
2719 0 : int ret;
2720 :
2721 8 : local_pathname = talloc_asprintf(talloc_tos(),
2722 : "%s/%s", local_path, fname);
2723 8 : if (!local_pathname) {
2724 0 : printf("child: alloc fail\n");
2725 0 : exit(1);
2726 : }
2727 :
2728 8 : unlink(local_pathname);
2729 8 : fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2730 8 : if (fd == -1) {
2731 0 : printf("child: open of %s failed %s.\n",
2732 0 : local_pathname, strerror(errno));
2733 0 : exit(1);
2734 : }
2735 :
2736 : /* Now take a fcntl lock. */
2737 8 : lock.l_type = F_WRLCK;
2738 8 : lock.l_whence = SEEK_SET;
2739 8 : lock.l_start = 0;
2740 8 : lock.l_len = 4;
2741 8 : lock.l_pid = getpid();
2742 :
2743 8 : ret = fcntl(fd,F_SETLK,&lock);
2744 8 : if (ret == -1) {
2745 0 : printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2746 0 : local_pathname, strerror(errno));
2747 0 : exit(1);
2748 : } else {
2749 8 : printf("child: got lock 0:4 on file %s.\n",
2750 : local_pathname );
2751 8 : fflush(stdout);
2752 : }
2753 :
2754 8 : CatchSignal(SIGALRM, alarm_handler);
2755 8 : alarm(5);
2756 : /* Signal the parent. */
2757 8 : if (write(write_fd, &c, 1) != 1) {
2758 0 : printf("child: start signal fail %s.\n",
2759 0 : strerror(errno));
2760 0 : exit(1);
2761 : }
2762 8 : alarm(0);
2763 :
2764 8 : alarm(10);
2765 : /* Wait for the parent to be ready. */
2766 8 : if (read(read_fd, &c, 1) != 1) {
2767 0 : printf("child: reply signal fail %s.\n",
2768 0 : strerror(errno));
2769 0 : exit(1);
2770 : }
2771 8 : alarm(0);
2772 :
2773 8 : sleep(5);
2774 8 : close(fd);
2775 8 : printf("child: released lock 0:4 on file %s.\n",
2776 : local_pathname );
2777 8 : fflush(stdout);
2778 8 : exit(0);
2779 : }
2780 :
2781 8 : static bool _run_locktest9X(const char *fname, int timeout)
2782 : {
2783 0 : struct cli_state *cli1;
2784 8 : char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2785 0 : uint16_t fnum;
2786 8 : bool correct = False;
2787 0 : int pipe_in[2], pipe_out[2];
2788 0 : pid_t child_pid;
2789 8 : char c = '\0';
2790 0 : int ret;
2791 0 : struct timeval start;
2792 0 : double seconds;
2793 0 : NTSTATUS status;
2794 :
2795 8 : printf("starting locktest9X: %s\n", fname);
2796 :
2797 8 : if (local_path == NULL) {
2798 0 : d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2799 0 : return false;
2800 : }
2801 :
2802 8 : if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2803 0 : return false;
2804 : }
2805 :
2806 8 : child_pid = fork();
2807 16 : if (child_pid == -1) {
2808 0 : return false;
2809 : }
2810 :
2811 16 : if (child_pid == 0) {
2812 : /* Child. */
2813 8 : do_local_lock(fname, pipe_out[0], pipe_in[1]);
2814 0 : exit(0);
2815 : }
2816 :
2817 8 : close(pipe_out[0]);
2818 8 : close(pipe_in[1]);
2819 8 : pipe_out[0] = -1;
2820 8 : pipe_in[1] = -1;
2821 :
2822 : /* Parent. */
2823 8 : ret = read(pipe_in[0], &c, 1);
2824 8 : if (ret != 1) {
2825 0 : d_fprintf(stderr, "failed to read start signal from child. %s\n",
2826 0 : strerror(errno));
2827 0 : return false;
2828 : }
2829 :
2830 8 : if (!torture_open_connection(&cli1, 0)) {
2831 0 : return false;
2832 : }
2833 :
2834 8 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2835 :
2836 8 : status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2837 : &fnum);
2838 8 : if (!NT_STATUS_IS_OK(status)) {
2839 0 : d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2840 0 : return false;
2841 : }
2842 :
2843 : /* Ensure the child has the lock. */
2844 8 : status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2845 8 : if (NT_STATUS_IS_OK(status)) {
2846 0 : d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2847 0 : goto fail;
2848 : } else {
2849 8 : d_printf("Child has the lock.\n");
2850 : }
2851 :
2852 : /* Tell the child to wait 5 seconds then exit. */
2853 8 : ret = write(pipe_out[1], &c, 1);
2854 8 : if (ret != 1) {
2855 0 : d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2856 0 : strerror(errno));
2857 0 : goto fail;
2858 : }
2859 :
2860 : /* Wait 20 seconds for the lock. */
2861 8 : alarm_cli = cli1;
2862 8 : CatchSignal(SIGALRM, alarm_handler_parent);
2863 8 : alarm(20);
2864 :
2865 8 : start = timeval_current();
2866 :
2867 8 : status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2868 8 : if (!NT_STATUS_IS_OK(status)) {
2869 0 : d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2870 : "%s\n", nt_errstr(status));
2871 0 : goto fail_nofd;
2872 : }
2873 8 : alarm(0);
2874 :
2875 8 : seconds = timeval_elapsed(&start);
2876 :
2877 8 : printf("Parent got the lock after %.2f seconds.\n",
2878 : seconds);
2879 :
2880 8 : status = cli_close(cli1, fnum);
2881 8 : if (!NT_STATUS_IS_OK(status)) {
2882 0 : d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2883 0 : goto fail;
2884 : }
2885 :
2886 8 : correct = true;
2887 :
2888 8 : fail:
2889 8 : cli_close(cli1, fnum);
2890 8 : torture_close_connection(cli1);
2891 :
2892 8 : fail_nofd:
2893 :
2894 8 : printf("finished locktest9X: %s\n", fname);
2895 8 : return correct;
2896 : }
2897 :
2898 4 : static bool run_locktest9a(int dummy)
2899 : {
2900 4 : return _run_locktest9X("lock9a.dat", -1);
2901 : }
2902 :
2903 4 : static bool run_locktest9b(int dummy)
2904 : {
2905 4 : return _run_locktest9X("lock9b.dat", 10000);
2906 : }
2907 :
2908 : struct locktest10_state {
2909 : bool ok;
2910 : bool done;
2911 : };
2912 :
2913 : static void locktest10_lockingx_done(struct tevent_req *subreq);
2914 : static void locktest10_read_andx_done(struct tevent_req *subreq);
2915 :
2916 5 : static bool run_locktest10(int dummy)
2917 : {
2918 5 : struct tevent_context *ev = NULL;
2919 5 : struct cli_state *cli1 = NULL;
2920 5 : struct cli_state *cli2 = NULL;
2921 5 : struct smb1_lock_element lck = { 0 };
2922 5 : struct tevent_req *reqs[2] = { NULL };
2923 5 : struct tevent_req *smbreqs[2] = { NULL };
2924 5 : const char fname[] = "\\lockt10.lck";
2925 0 : uint16_t fnum1, fnum2;
2926 5 : bool ret = false;
2927 0 : bool ok;
2928 5 : uint8_t data = 1;
2929 5 : struct locktest10_state state = { .ok = true };
2930 0 : NTSTATUS status;
2931 :
2932 5 : printf("starting locktest10\n");
2933 :
2934 5 : ev = samba_tevent_context_init(NULL);
2935 5 : if (ev == NULL) {
2936 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
2937 0 : goto done;
2938 : }
2939 :
2940 5 : ok = torture_open_connection(&cli1, 0);
2941 5 : if (!ok) {
2942 0 : goto done;
2943 : }
2944 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
2945 :
2946 5 : ok = torture_open_connection(&cli2, 1);
2947 5 : if (!ok) {
2948 0 : goto done;
2949 : }
2950 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
2951 :
2952 5 : status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2953 5 : if (!NT_STATUS_IS_OK(status)) {
2954 0 : d_fprintf(stderr,
2955 : "cli_openx failed: %s\n",
2956 : nt_errstr(status));
2957 0 : goto done;
2958 : }
2959 :
2960 5 : status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2961 5 : if (!NT_STATUS_IS_OK(status)) {
2962 0 : d_fprintf(stderr,
2963 : "cli_writeall failed: %s\n",
2964 : nt_errstr(status));
2965 0 : goto done;
2966 : }
2967 :
2968 5 : status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2969 5 : if (!NT_STATUS_IS_OK(status)) {
2970 0 : d_fprintf(stderr,
2971 : "cli_openx failed: %s\n",
2972 : nt_errstr(status));
2973 0 : goto done;
2974 : }
2975 :
2976 5 : status = cli_locktype(
2977 : cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2978 5 : if (!NT_STATUS_IS_OK(status)) {
2979 0 : d_fprintf(stderr,
2980 : "cli_locktype failed: %s\n",
2981 : nt_errstr(status));
2982 0 : goto done;
2983 : }
2984 :
2985 5 : lck = (struct smb1_lock_element) {
2986 5 : .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2987 : };
2988 :
2989 5 : reqs[0] = cli_lockingx_create(
2990 : ev, /* mem_ctx */
2991 : ev, /* tevent_context */
2992 : cli1, /* cli */
2993 : fnum1, /* fnum */
2994 : LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
2995 : 0, /* newoplocklevel */
2996 : 1, /* timeout */
2997 : 0, /* num_unlocks */
2998 : NULL, /* unlocks */
2999 : 1, /* num_locks */
3000 : &lck, /* locks */
3001 : &smbreqs[0]); /* psmbreq */
3002 5 : if (reqs[0] == NULL) {
3003 0 : d_fprintf(stderr, "cli_lockingx_create failed\n");
3004 0 : goto done;
3005 : }
3006 5 : tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
3007 :
3008 5 : reqs[1] = cli_read_andx_create(
3009 : ev, /* mem_ctx */
3010 : ev, /* ev */
3011 : cli1, /* cli */
3012 : fnum1, /* fnum */
3013 : 0, /* offset */
3014 : 1, /* size */
3015 : &smbreqs[1]); /* psmbreq */
3016 5 : if (reqs[1] == NULL) {
3017 0 : d_fprintf(stderr, "cli_read_andx_create failed\n");
3018 0 : goto done;
3019 : }
3020 5 : tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
3021 :
3022 5 : status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
3023 5 : if (!NT_STATUS_IS_OK(status)) {
3024 0 : d_fprintf(stderr,
3025 : "smb1cli_req_chain_submit failed: %s\n",
3026 : nt_errstr(status));
3027 0 : goto done;
3028 : }
3029 :
3030 30 : while (!state.done) {
3031 25 : tevent_loop_once(ev);
3032 : }
3033 :
3034 5 : torture_close_connection(cli1);
3035 :
3036 5 : if (state.ok) {
3037 5 : ret = true;
3038 : }
3039 0 : done:
3040 5 : return ret;
3041 : }
3042 :
3043 5 : static void locktest10_lockingx_done(struct tevent_req *subreq)
3044 : {
3045 5 : struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3046 0 : NTSTATUS status;
3047 :
3048 5 : status = cli_lockingx_recv(subreq);
3049 5 : TALLOC_FREE(subreq);
3050 :
3051 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3052 0 : d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3053 0 : state->ok = false;
3054 : }
3055 5 : }
3056 :
3057 5 : static void locktest10_read_andx_done(struct tevent_req *subreq)
3058 : {
3059 5 : struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3060 5 : ssize_t received = -1;
3061 5 : uint8_t *rcvbuf = NULL;
3062 0 : NTSTATUS status;
3063 :
3064 5 : status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3065 :
3066 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
3067 0 : d_printf("cli_read_andx returned %s\n", nt_errstr(status));
3068 0 : state->ok = false;
3069 : }
3070 :
3071 5 : state->done = true;
3072 5 : TALLOC_FREE(subreq);
3073 5 : }
3074 :
3075 5 : static bool run_locktest11(int dummy)
3076 : {
3077 0 : struct cli_state *cli1;
3078 5 : const char *fname = "\\lockt11.lck";
3079 0 : NTSTATUS status;
3080 0 : uint16_t fnum;
3081 5 : bool ret = false;
3082 :
3083 5 : if (!torture_open_connection(&cli1, 0)) {
3084 0 : return false;
3085 : }
3086 :
3087 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
3088 :
3089 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3090 :
3091 5 : status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
3092 5 : if (!NT_STATUS_IS_OK(status)) {
3093 0 : d_fprintf(stderr,
3094 : "cli_openx returned %s\n",
3095 : nt_errstr(status));
3096 0 : return false;
3097 : }
3098 :
3099 : /*
3100 : * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3101 : * returns NT_STATUS_OK
3102 : */
3103 :
3104 5 : status = cli_lockingx(
3105 : cli1, /* cli */
3106 : fnum, /* fnum */
3107 : LOCKING_ANDX_CANCEL_LOCK, /* typeoflock */
3108 : 0, /* newoplocklevel */
3109 : 0, /* timeout */
3110 : 0, /* num_unlocks */
3111 : NULL, /* unlocks */
3112 : 0, /* num_locks */
3113 : NULL); /* locks */
3114 :
3115 5 : if (!NT_STATUS_IS_OK(status)) {
3116 1 : d_printf("cli_lockingX returned %s\n", nt_errstr(status));
3117 1 : goto fail;
3118 : }
3119 :
3120 4 : ret = true;
3121 5 : fail:
3122 5 : cli_close(cli1, fnum);
3123 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3124 :
3125 5 : return ret;
3126 : }
3127 :
3128 : struct deferred_close_state {
3129 : struct tevent_context *ev;
3130 : struct cli_state *cli;
3131 : uint16_t fnum;
3132 : };
3133 :
3134 : static void deferred_close_waited(struct tevent_req *subreq);
3135 : static void deferred_close_done(struct tevent_req *subreq);
3136 :
3137 5 : static struct tevent_req *deferred_close_send(
3138 : TALLOC_CTX *mem_ctx,
3139 : struct tevent_context *ev,
3140 : int wait_secs,
3141 : struct cli_state *cli,
3142 : uint16_t fnum)
3143 : {
3144 5 : struct tevent_req *req = NULL, *subreq = NULL;
3145 5 : struct deferred_close_state *state = NULL;
3146 5 : struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
3147 :
3148 5 : req = tevent_req_create(
3149 : mem_ctx, &state, struct deferred_close_state);
3150 5 : if (req == NULL) {
3151 0 : return NULL;
3152 : }
3153 5 : state->ev = ev;
3154 5 : state->cli = cli;
3155 5 : state->fnum = fnum;
3156 :
3157 5 : subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
3158 5 : if (tevent_req_nomem(subreq, req)) {
3159 0 : return tevent_req_post(req, ev);
3160 : }
3161 5 : tevent_req_set_callback(subreq, deferred_close_waited, req);
3162 5 : return req;
3163 : }
3164 :
3165 5 : static void deferred_close_waited(struct tevent_req *subreq)
3166 : {
3167 5 : struct tevent_req *req = tevent_req_callback_data(
3168 : subreq, struct tevent_req);
3169 5 : struct deferred_close_state *state = tevent_req_data(
3170 : req, struct deferred_close_state);
3171 0 : bool ok;
3172 :
3173 5 : ok = tevent_wakeup_recv(subreq);
3174 5 : TALLOC_FREE(subreq);
3175 5 : if (!ok) {
3176 0 : tevent_req_oom(req);
3177 0 : return;
3178 : }
3179 :
3180 5 : subreq = cli_close_send(state, state->ev, state->cli, state->fnum, 0);
3181 5 : if (tevent_req_nomem(subreq, req)) {
3182 0 : return;
3183 : }
3184 5 : tevent_req_set_callback(subreq, deferred_close_done, req);
3185 : }
3186 :
3187 5 : static void deferred_close_done(struct tevent_req *subreq)
3188 : {
3189 5 : NTSTATUS status = cli_close_recv(subreq);
3190 5 : tevent_req_simple_finish_ntstatus(subreq, status);
3191 5 : }
3192 :
3193 5 : static NTSTATUS deferred_close_recv(struct tevent_req *req)
3194 : {
3195 5 : return tevent_req_simple_recv_ntstatus(req);
3196 : }
3197 :
3198 : struct lockread_state {
3199 : struct smb1_lock_element lck;
3200 : struct tevent_req *reqs[2];
3201 : struct tevent_req *smbreqs[2];
3202 : NTSTATUS lock_status;
3203 : NTSTATUS read_status;
3204 : uint8_t *readbuf;
3205 : };
3206 :
3207 : static void lockread_lockingx_done(struct tevent_req *subreq);
3208 : static void lockread_read_andx_done(struct tevent_req *subreq);
3209 :
3210 5 : static struct tevent_req *lockread_send(
3211 : TALLOC_CTX *mem_ctx,
3212 : struct tevent_context *ev,
3213 : struct cli_state *cli,
3214 : uint16_t fnum)
3215 : {
3216 5 : struct tevent_req *req = NULL;
3217 5 : struct lockread_state *state = NULL;
3218 0 : NTSTATUS status;
3219 :
3220 5 : req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3221 5 : if (req == NULL) {
3222 0 : return NULL;
3223 : }
3224 :
3225 10 : state->lck = (struct smb1_lock_element) {
3226 5 : .pid = cli_getpid(cli), .offset = 0, .length = 1,
3227 : };
3228 :
3229 10 : state->reqs[0] = cli_lockingx_create(
3230 : ev, /* mem_ctx */
3231 : ev, /* tevent_context */
3232 : cli, /* cli */
3233 : fnum, /* fnum */
3234 : LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3235 : 0, /* newoplocklevel */
3236 : 10000, /* timeout */
3237 : 0, /* num_unlocks */
3238 : NULL, /* unlocks */
3239 : 1, /* num_locks */
3240 5 : &state->lck, /* locks */
3241 5 : &state->smbreqs[0]); /* psmbreq */
3242 5 : if (tevent_req_nomem(state->reqs[0], req)) {
3243 0 : return tevent_req_post(req, ev);
3244 : }
3245 5 : tevent_req_set_callback(
3246 : state->reqs[0], lockread_lockingx_done, req);
3247 :
3248 10 : state->reqs[1] = cli_read_andx_create(
3249 : ev, /* mem_ctx */
3250 : ev, /* ev */
3251 : cli, /* cli */
3252 : fnum, /* fnum */
3253 : 0, /* offset */
3254 : 1, /* size */
3255 5 : &state->smbreqs[1]); /* psmbreq */
3256 5 : if (tevent_req_nomem(state->reqs[1], req)) {
3257 0 : return tevent_req_post(req, ev);
3258 : }
3259 5 : tevent_req_set_callback(
3260 : state->reqs[1], lockread_read_andx_done, req);
3261 :
3262 5 : status = smb1cli_req_chain_submit(state->smbreqs, 2);
3263 5 : if (tevent_req_nterror(req, status)) {
3264 0 : return tevent_req_post(req, ev);
3265 : }
3266 5 : return req;
3267 : }
3268 :
3269 5 : static void lockread_lockingx_done(struct tevent_req *subreq)
3270 : {
3271 5 : struct tevent_req *req = tevent_req_callback_data(
3272 : subreq, struct tevent_req);
3273 5 : struct lockread_state *state = tevent_req_data(
3274 : req, struct lockread_state);
3275 5 : state->lock_status = cli_lockingx_recv(subreq);
3276 5 : TALLOC_FREE(subreq);
3277 5 : d_fprintf(stderr,
3278 : "lockingx returned %s\n",
3279 : nt_errstr(state->lock_status));
3280 5 : }
3281 :
3282 5 : static void lockread_read_andx_done(struct tevent_req *subreq)
3283 : {
3284 5 : struct tevent_req *req = tevent_req_callback_data(
3285 : subreq, struct tevent_req);
3286 5 : struct lockread_state *state = tevent_req_data(
3287 : req, struct lockread_state);
3288 5 : ssize_t received = -1;
3289 5 : uint8_t *rcvbuf = NULL;
3290 :
3291 5 : state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3292 :
3293 5 : d_fprintf(stderr,
3294 : "read returned %s\n",
3295 : nt_errstr(state->read_status));
3296 :
3297 5 : if (!NT_STATUS_IS_OK(state->read_status)) {
3298 4 : TALLOC_FREE(subreq);
3299 4 : tevent_req_done(req);
3300 4 : return;
3301 : }
3302 :
3303 1 : if (received > 0) {
3304 1 : state->readbuf = talloc_memdup(state, rcvbuf, received);
3305 1 : TALLOC_FREE(subreq);
3306 1 : if (tevent_req_nomem(state->readbuf, req)) {
3307 0 : return;
3308 : }
3309 : }
3310 1 : TALLOC_FREE(subreq);
3311 1 : tevent_req_done(req);
3312 : }
3313 :
3314 5 : static NTSTATUS lockread_recv(
3315 : struct tevent_req *req,
3316 : NTSTATUS *lock_status,
3317 : NTSTATUS *read_status,
3318 : TALLOC_CTX *mem_ctx,
3319 : uint8_t **read_buf)
3320 : {
3321 5 : struct lockread_state *state = tevent_req_data(
3322 : req, struct lockread_state);
3323 0 : NTSTATUS status;
3324 :
3325 5 : if (tevent_req_is_nterror(req, &status)) {
3326 0 : return status;
3327 : }
3328 :
3329 5 : *lock_status = state->lock_status;
3330 5 : *read_status = state->read_status;
3331 5 : if (state->readbuf != NULL) {
3332 1 : *read_buf = talloc_move(mem_ctx, &state->readbuf);
3333 : } else {
3334 4 : *read_buf = NULL;
3335 : }
3336 :
3337 5 : return NT_STATUS_OK;
3338 : }
3339 :
3340 : struct lock12_state {
3341 : uint8_t dummy;
3342 : };
3343 :
3344 : static void lock12_closed(struct tevent_req *subreq);
3345 : static void lock12_read(struct tevent_req *subreq);
3346 :
3347 5 : static struct tevent_req *lock12_send(
3348 : TALLOC_CTX *mem_ctx,
3349 : struct tevent_context *ev,
3350 : struct cli_state *cli,
3351 : uint16_t fnum1,
3352 : uint16_t fnum2)
3353 : {
3354 5 : struct tevent_req *req = NULL, *subreq = NULL;
3355 5 : struct lock12_state *state = NULL;
3356 :
3357 5 : req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3358 5 : if (req == NULL) {
3359 0 : return NULL;
3360 : }
3361 :
3362 5 : subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3363 5 : if (tevent_req_nomem(subreq, req)) {
3364 0 : return tevent_req_post(req, ev);
3365 : }
3366 5 : tevent_req_set_callback(subreq, lock12_closed, req);
3367 :
3368 5 : subreq = lockread_send(state, ev, cli, fnum2);
3369 5 : if (tevent_req_nomem(subreq, req)) {
3370 0 : return tevent_req_post(req, ev);
3371 : }
3372 5 : tevent_req_set_callback(subreq, lock12_read, req);
3373 :
3374 5 : return req;
3375 : }
3376 :
3377 5 : static void lock12_closed(struct tevent_req *subreq)
3378 : {
3379 5 : struct tevent_req *req = tevent_req_callback_data(
3380 : subreq, struct tevent_req);
3381 0 : NTSTATUS status;
3382 :
3383 5 : status = deferred_close_recv(subreq);
3384 5 : TALLOC_FREE(subreq);
3385 5 : DBG_DEBUG("close returned %s\n", nt_errstr(status));
3386 5 : if (tevent_req_nterror(req, status)) {
3387 0 : return;
3388 : }
3389 : }
3390 :
3391 5 : static void lock12_read(struct tevent_req *subreq)
3392 : {
3393 5 : struct tevent_req *req = tevent_req_callback_data(
3394 : subreq, struct tevent_req);
3395 5 : struct lock12_state *state = tevent_req_data(
3396 : req, struct lock12_state);
3397 0 : NTSTATUS status, lock_status, read_status;
3398 5 : uint8_t *buf = NULL;
3399 :
3400 5 : status = lockread_recv(
3401 : subreq, &lock_status, &read_status, state, &buf);
3402 5 : TALLOC_FREE(subreq);
3403 10 : if (tevent_req_nterror(req, status) ||
3404 10 : tevent_req_nterror(req, lock_status) ||
3405 5 : tevent_req_nterror(req, read_status)) {
3406 4 : return;
3407 : }
3408 1 : tevent_req_done(req);
3409 : }
3410 :
3411 5 : static NTSTATUS lock12_recv(struct tevent_req *req)
3412 :
3413 : {
3414 0 : NTSTATUS status;
3415 :
3416 5 : if (tevent_req_is_nterror(req, &status)) {
3417 4 : return status;
3418 : }
3419 1 : return NT_STATUS_OK;
3420 : }
3421 :
3422 5 : static bool run_locktest12(int dummy)
3423 : {
3424 5 : struct tevent_context *ev = NULL;
3425 5 : struct tevent_req *req = NULL;
3426 5 : struct cli_state *cli = NULL;
3427 5 : const char fname[] = "\\lockt12.lck";
3428 0 : uint16_t fnum1, fnum2;
3429 5 : bool ret = false;
3430 0 : bool ok;
3431 5 : uint8_t data = 1;
3432 0 : NTSTATUS status;
3433 :
3434 5 : printf("starting locktest12\n");
3435 :
3436 5 : ev = samba_tevent_context_init(NULL);
3437 5 : if (ev == NULL) {
3438 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
3439 0 : goto done;
3440 : }
3441 :
3442 5 : ok = torture_open_connection(&cli, 0);
3443 5 : if (!ok) {
3444 0 : goto done;
3445 : }
3446 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3447 :
3448 5 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3449 5 : if (!NT_STATUS_IS_OK(status)) {
3450 0 : d_fprintf(stderr,
3451 : "cli_openx failed: %s\n",
3452 : nt_errstr(status));
3453 0 : goto done;
3454 : }
3455 :
3456 5 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3457 5 : if (!NT_STATUS_IS_OK(status)) {
3458 0 : d_fprintf(stderr,
3459 : "cli_openx failed: %s\n",
3460 : nt_errstr(status));
3461 0 : goto done;
3462 : }
3463 :
3464 5 : status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3465 5 : if (!NT_STATUS_IS_OK(status)) {
3466 0 : d_fprintf(stderr,
3467 : "cli_writeall failed: %s\n",
3468 : nt_errstr(status));
3469 0 : goto done;
3470 : }
3471 :
3472 5 : status = cli_locktype(
3473 : cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3474 5 : if (!NT_STATUS_IS_OK(status)) {
3475 0 : d_fprintf(stderr,
3476 : "cli_locktype failed: %s\n",
3477 : nt_errstr(status));
3478 0 : goto done;
3479 : }
3480 :
3481 5 : req = lock12_send(ev, ev, cli, fnum1, fnum2);
3482 5 : if (req == NULL) {
3483 0 : d_fprintf(stderr, "lock12_send failed\n");
3484 0 : goto done;
3485 : }
3486 :
3487 5 : ok = tevent_req_poll_ntstatus(req, ev, &status);
3488 5 : if (!ok) {
3489 0 : d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3490 0 : goto done;
3491 : }
3492 :
3493 5 : if (!NT_STATUS_IS_OK(status)) {
3494 0 : d_fprintf(stderr,
3495 : "tevent_req_poll_ntstatus returned %s\n",
3496 : nt_errstr(status));
3497 0 : goto done;
3498 : }
3499 :
3500 5 : status = lock12_recv(req);
3501 5 : if (!NT_STATUS_IS_OK(status)) {
3502 4 : d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3503 4 : goto done;
3504 : }
3505 :
3506 1 : ret = true;
3507 5 : done:
3508 5 : if (cli != NULL) {
3509 5 : torture_close_connection(cli);
3510 : }
3511 5 : return ret;
3512 : }
3513 :
3514 : struct lock_ntcancel_state {
3515 : struct timeval start;
3516 : struct smb1_lock_element lck;
3517 : struct tevent_req *subreq;
3518 : };
3519 :
3520 : static void lock_ntcancel_waited(struct tevent_req *subreq);
3521 : static void lock_ntcancel_done(struct tevent_req *subreq);
3522 :
3523 5 : static struct tevent_req *lock_ntcancel_send(
3524 : TALLOC_CTX *mem_ctx,
3525 : struct tevent_context *ev,
3526 : struct cli_state *cli,
3527 : uint16_t fnum)
3528 : {
3529 5 : struct tevent_req *req = NULL, *subreq = NULL;
3530 5 : struct lock_ntcancel_state *state = NULL;
3531 :
3532 5 : req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3533 5 : if (req == NULL) {
3534 0 : return NULL;
3535 : }
3536 10 : state->lck = (struct smb1_lock_element) {
3537 5 : .pid = cli_getpid(cli), .offset = 0, .length = 1,
3538 : };
3539 5 : state->start = timeval_current();
3540 :
3541 10 : state->subreq = cli_lockingx_send(
3542 : state, /* mem_ctx */
3543 : ev, /* tevent_context */
3544 : cli, /* cli */
3545 : fnum, /* fnum */
3546 : LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3547 : 0, /* newoplocklevel */
3548 : 10000, /* timeout */
3549 : 0, /* num_unlocks */
3550 : NULL, /* unlocks */
3551 : 1, /* num_locks */
3552 5 : &state->lck); /* locks */
3553 5 : if (tevent_req_nomem(state->subreq, req)) {
3554 0 : return tevent_req_post(req, ev);
3555 : }
3556 5 : tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3557 :
3558 5 : subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3559 5 : if (tevent_req_nomem(subreq, req)) {
3560 0 : return tevent_req_post(req, ev);
3561 : }
3562 5 : tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3563 5 : return req;
3564 : }
3565 :
3566 5 : static void lock_ntcancel_waited(struct tevent_req *subreq)
3567 : {
3568 5 : struct tevent_req *req = tevent_req_callback_data(
3569 : subreq, struct tevent_req);
3570 5 : struct lock_ntcancel_state *state = tevent_req_data(
3571 : req, struct lock_ntcancel_state);
3572 0 : bool ok;
3573 :
3574 5 : ok = tevent_wakeup_recv(subreq);
3575 5 : TALLOC_FREE(subreq);
3576 5 : if (!ok) {
3577 0 : tevent_req_oom(req);
3578 0 : return;
3579 : }
3580 :
3581 5 : ok = tevent_req_cancel(state->subreq);
3582 5 : if (!ok) {
3583 0 : d_fprintf(stderr, "Could not cancel subreq\n");
3584 0 : tevent_req_oom(req);
3585 0 : return;
3586 : }
3587 : }
3588 :
3589 5 : static void lock_ntcancel_done(struct tevent_req *subreq)
3590 : {
3591 5 : struct tevent_req *req = tevent_req_callback_data(
3592 : subreq, struct tevent_req);
3593 5 : struct lock_ntcancel_state *state = tevent_req_data(
3594 : req, struct lock_ntcancel_state);
3595 0 : NTSTATUS status;
3596 0 : double elapsed;
3597 :
3598 5 : status = cli_lockingx_recv(subreq);
3599 5 : TALLOC_FREE(subreq);
3600 :
3601 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3602 0 : d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3603 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3604 0 : return;
3605 : }
3606 :
3607 5 : elapsed = timeval_elapsed(&state->start);
3608 :
3609 5 : if (elapsed > 3) {
3610 0 : d_printf("cli_lockingx was too slow, cancel did not work\n");
3611 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3612 0 : return;
3613 : }
3614 :
3615 5 : tevent_req_done(req);
3616 : }
3617 :
3618 5 : static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3619 : {
3620 5 : return tevent_req_simple_recv_ntstatus(req);
3621 : }
3622 :
3623 5 : static bool run_locktest13(int dummy)
3624 : {
3625 5 : struct tevent_context *ev = NULL;
3626 5 : struct tevent_req *req = NULL;
3627 5 : struct cli_state *cli = NULL;
3628 5 : const char fname[] = "\\lockt13.lck";
3629 0 : uint16_t fnum1, fnum2;
3630 5 : bool ret = false;
3631 0 : bool ok;
3632 5 : uint8_t data = 1;
3633 0 : NTSTATUS status;
3634 :
3635 5 : printf("starting locktest13\n");
3636 :
3637 5 : ev = samba_tevent_context_init(NULL);
3638 5 : if (ev == NULL) {
3639 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
3640 0 : goto done;
3641 : }
3642 :
3643 5 : ok = torture_open_connection(&cli, 0);
3644 5 : if (!ok) {
3645 0 : goto done;
3646 : }
3647 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3648 :
3649 5 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3650 5 : if (!NT_STATUS_IS_OK(status)) {
3651 0 : d_fprintf(stderr,
3652 : "cli_openx failed: %s\n",
3653 : nt_errstr(status));
3654 0 : goto done;
3655 : }
3656 :
3657 5 : status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3658 5 : if (!NT_STATUS_IS_OK(status)) {
3659 0 : d_fprintf(stderr,
3660 : "cli_openx failed: %s\n",
3661 : nt_errstr(status));
3662 0 : goto done;
3663 : }
3664 :
3665 5 : status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3666 5 : if (!NT_STATUS_IS_OK(status)) {
3667 0 : d_fprintf(stderr,
3668 : "cli_writeall failed: %s\n",
3669 : nt_errstr(status));
3670 0 : goto done;
3671 : }
3672 :
3673 5 : status = cli_locktype(
3674 : cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3675 5 : if (!NT_STATUS_IS_OK(status)) {
3676 0 : d_fprintf(stderr,
3677 : "cli_locktype failed: %s\n",
3678 : nt_errstr(status));
3679 0 : goto done;
3680 : }
3681 :
3682 5 : req = lock_ntcancel_send(ev, ev, cli, fnum2);
3683 5 : if (req == NULL) {
3684 0 : d_fprintf(stderr, "lock_ntcancel_send failed\n");
3685 0 : goto done;
3686 : }
3687 :
3688 5 : ok = tevent_req_poll_ntstatus(req, ev, &status);
3689 5 : if (!ok) {
3690 0 : d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3691 0 : goto done;
3692 : }
3693 :
3694 5 : if (!NT_STATUS_IS_OK(status)) {
3695 0 : d_fprintf(stderr,
3696 : "tevent_req_poll_ntstatus returned %s\n",
3697 : nt_errstr(status));
3698 0 : goto done;
3699 : }
3700 :
3701 5 : status = lock_ntcancel_recv(req);
3702 5 : if (!NT_STATUS_IS_OK(status)) {
3703 0 : d_fprintf(stderr,
3704 : "lock_ntcancel returned %s\n",
3705 : nt_errstr(status));
3706 0 : goto done;
3707 : }
3708 :
3709 5 : ret = true;
3710 5 : done:
3711 5 : if (cli != NULL) {
3712 5 : torture_close_connection(cli);
3713 : }
3714 5 : return ret;
3715 : }
3716 :
3717 : /*
3718 : test whether fnums and tids open on one VC are available on another (a major
3719 : security hole)
3720 : */
3721 5 : static bool run_fdpasstest(int dummy)
3722 : {
3723 0 : struct cli_state *cli1, *cli2;
3724 5 : const char *fname = "\\fdpass.tst";
3725 0 : uint16_t fnum1;
3726 0 : char buf[1024];
3727 0 : NTSTATUS status;
3728 :
3729 5 : if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3730 0 : return False;
3731 : }
3732 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
3733 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
3734 :
3735 5 : printf("starting fdpasstest\n");
3736 :
3737 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3738 :
3739 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3740 : &fnum1);
3741 5 : if (!NT_STATUS_IS_OK(status)) {
3742 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3743 0 : return False;
3744 : }
3745 :
3746 5 : status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3747 : 13, NULL);
3748 5 : if (!NT_STATUS_IS_OK(status)) {
3749 0 : printf("write failed (%s)\n", nt_errstr(status));
3750 0 : return False;
3751 : }
3752 :
3753 5 : cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3754 5 : cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3755 5 : cli_setpid(cli2, cli_getpid(cli1));
3756 :
3757 5 : if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3758 0 : printf("read succeeded! nasty security hole [%s]\n", buf);
3759 0 : return false;
3760 : }
3761 :
3762 5 : cli_close(cli1, fnum1);
3763 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3764 :
3765 5 : torture_close_connection(cli1);
3766 5 : torture_close_connection(cli2);
3767 :
3768 5 : printf("finished fdpasstest\n");
3769 5 : return True;
3770 : }
3771 :
3772 5 : static bool run_fdsesstest(int dummy)
3773 : {
3774 0 : struct cli_state *cli;
3775 0 : uint16_t new_vuid;
3776 0 : uint16_t saved_vuid;
3777 0 : uint32_t new_cnum;
3778 0 : uint32_t saved_cnum;
3779 5 : const char *fname = "\\fdsess.tst";
3780 5 : const char *fname1 = "\\fdsess1.tst";
3781 0 : uint16_t fnum1;
3782 0 : uint16_t fnum2;
3783 0 : char buf[1024];
3784 5 : bool ret = True;
3785 0 : NTSTATUS status;
3786 :
3787 5 : if (!torture_open_connection(&cli, 0))
3788 0 : return False;
3789 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3790 :
3791 5 : if (!torture_cli_session_setup2(cli, &new_vuid))
3792 0 : return False;
3793 :
3794 5 : saved_cnum = cli_state_get_tid(cli);
3795 5 : if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3796 0 : return False;
3797 5 : new_cnum = cli_state_get_tid(cli);
3798 5 : cli_state_set_tid(cli, saved_cnum);
3799 :
3800 5 : printf("starting fdsesstest\n");
3801 :
3802 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3803 5 : cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3804 :
3805 5 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3806 5 : if (!NT_STATUS_IS_OK(status)) {
3807 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3808 0 : return False;
3809 : }
3810 :
3811 5 : status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3812 : NULL);
3813 5 : if (!NT_STATUS_IS_OK(status)) {
3814 0 : printf("write failed (%s)\n", nt_errstr(status));
3815 0 : return False;
3816 : }
3817 :
3818 5 : saved_vuid = cli_state_get_uid(cli);
3819 5 : cli_state_set_uid(cli, new_vuid);
3820 :
3821 5 : if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3822 0 : printf("read succeeded with different vuid! "
3823 : "nasty security hole [%s]\n", buf);
3824 0 : ret = false;
3825 : }
3826 : /* Try to open a file with different vuid, samba cnum. */
3827 5 : if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3828 5 : printf("create with different vuid, same cnum succeeded.\n");
3829 5 : cli_close(cli, fnum2);
3830 5 : cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3831 : } else {
3832 0 : printf("create with different vuid, same cnum failed.\n");
3833 0 : printf("This will cause problems with service clients.\n");
3834 0 : ret = False;
3835 : }
3836 :
3837 5 : cli_state_set_uid(cli, saved_vuid);
3838 :
3839 : /* Try with same vuid, different cnum. */
3840 5 : cli_state_set_tid(cli, new_cnum);
3841 :
3842 5 : if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3843 0 : printf("read succeeded with different cnum![%s]\n", buf);
3844 0 : ret = false;
3845 : }
3846 :
3847 5 : cli_state_set_tid(cli, saved_cnum);
3848 5 : cli_close(cli, fnum1);
3849 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3850 :
3851 5 : torture_close_connection(cli);
3852 :
3853 5 : printf("finished fdsesstest\n");
3854 5 : return ret;
3855 : }
3856 :
3857 : /*
3858 : This test checks that
3859 :
3860 : 1) the server does not allow an unlink on a file that is open
3861 : */
3862 5 : static bool run_unlinktest(int dummy)
3863 : {
3864 0 : struct cli_state *cli;
3865 5 : const char *fname = "\\unlink.tst";
3866 0 : uint16_t fnum;
3867 5 : bool correct = True;
3868 0 : NTSTATUS status;
3869 :
3870 5 : if (!torture_open_connection(&cli, 0)) {
3871 0 : return False;
3872 : }
3873 :
3874 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3875 :
3876 5 : printf("starting unlink test\n");
3877 :
3878 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3879 :
3880 5 : cli_setpid(cli, 1);
3881 :
3882 5 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3883 5 : if (!NT_STATUS_IS_OK(status)) {
3884 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3885 0 : return False;
3886 : }
3887 :
3888 5 : status = cli_unlink(cli, fname,
3889 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3890 5 : if (NT_STATUS_IS_OK(status)) {
3891 0 : printf("error: server allowed unlink on an open file\n");
3892 0 : correct = False;
3893 : } else {
3894 5 : correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3895 5 : NT_STATUS_SHARING_VIOLATION);
3896 : }
3897 :
3898 5 : cli_close(cli, fnum);
3899 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3900 :
3901 5 : if (!torture_close_connection(cli)) {
3902 0 : correct = False;
3903 : }
3904 :
3905 5 : printf("unlink test finished\n");
3906 :
3907 5 : return correct;
3908 : }
3909 :
3910 :
3911 : /*
3912 : test how many open files this server supports on the one socket
3913 : */
3914 0 : static bool run_maxfidtest(int dummy)
3915 : {
3916 0 : struct cli_state *cli;
3917 0 : fstring fname;
3918 0 : uint16_t fnums[0x11000];
3919 0 : int i;
3920 0 : int retries=4;
3921 0 : bool correct = True;
3922 0 : NTSTATUS status;
3923 :
3924 0 : cli = current_cli;
3925 :
3926 0 : if (retries <= 0) {
3927 0 : printf("failed to connect\n");
3928 0 : return False;
3929 : }
3930 :
3931 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
3932 :
3933 0 : for (i=0; i<0x11000; i++) {
3934 0 : slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3935 0 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3936 : &fnums[i]);
3937 0 : if (!NT_STATUS_IS_OK(status)) {
3938 0 : printf("open of %s failed (%s)\n",
3939 : fname, nt_errstr(status));
3940 0 : printf("maximum fnum is %d\n", i);
3941 0 : break;
3942 : }
3943 0 : printf("%6d\r", i);
3944 : }
3945 0 : printf("%6d\n", i);
3946 0 : i--;
3947 :
3948 0 : printf("cleaning up\n");
3949 0 : for (;i>=0;i--) {
3950 0 : slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3951 0 : cli_close(cli, fnums[i]);
3952 :
3953 0 : status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3954 0 : if (!NT_STATUS_IS_OK(status)) {
3955 0 : printf("unlink of %s failed (%s)\n",
3956 : fname, nt_errstr(status));
3957 0 : correct = False;
3958 : }
3959 0 : printf("%6d\r", i);
3960 : }
3961 0 : printf("%6d\n", 0);
3962 :
3963 0 : printf("maxfid test finished\n");
3964 0 : if (!torture_close_connection(cli)) {
3965 0 : correct = False;
3966 : }
3967 0 : return correct;
3968 : }
3969 :
3970 : /* generate a random buffer */
3971 0 : static void rand_buf(char *buf, int len)
3972 : {
3973 0 : while (len--) {
3974 0 : *buf = (char)sys_random();
3975 0 : buf++;
3976 : }
3977 0 : }
3978 :
3979 : /* send smb negprot commands, not reading the response */
3980 0 : static bool run_negprot_nowait(int dummy)
3981 : {
3982 0 : struct tevent_context *ev;
3983 0 : int i;
3984 0 : struct cli_state *cli;
3985 0 : bool correct = True;
3986 :
3987 0 : printf("starting negprot nowait test\n");
3988 :
3989 0 : ev = samba_tevent_context_init(talloc_tos());
3990 0 : if (ev == NULL) {
3991 0 : return false;
3992 : }
3993 :
3994 0 : if (!(cli = open_nbt_connection())) {
3995 0 : TALLOC_FREE(ev);
3996 0 : return False;
3997 : }
3998 :
3999 0 : for (i=0;i<50000;i++) {
4000 0 : struct tevent_req *req;
4001 :
4002 0 : req = smbXcli_negprot_send(
4003 : ev,
4004 : ev,
4005 : cli->conn,
4006 0 : cli->timeout,
4007 : PROTOCOL_CORE,
4008 : PROTOCOL_NT1,
4009 : 0,
4010 : NULL);
4011 0 : if (req == NULL) {
4012 0 : TALLOC_FREE(ev);
4013 0 : return false;
4014 : }
4015 0 : if (!tevent_req_poll(req, ev)) {
4016 0 : d_fprintf(stderr, "tevent_req_poll failed: %s\n",
4017 0 : strerror(errno));
4018 0 : TALLOC_FREE(ev);
4019 0 : return false;
4020 : }
4021 0 : TALLOC_FREE(req);
4022 : }
4023 :
4024 0 : if (torture_close_connection(cli)) {
4025 0 : correct = False;
4026 : }
4027 :
4028 0 : printf("finished negprot nowait test\n");
4029 :
4030 0 : return correct;
4031 : }
4032 :
4033 : /* send smb negprot commands, not reading the response */
4034 4 : static bool run_bad_nbt_session(int dummy)
4035 : {
4036 0 : struct nmb_name called, calling;
4037 0 : struct sockaddr_storage ss;
4038 0 : NTSTATUS status;
4039 0 : int fd;
4040 0 : bool ret;
4041 :
4042 4 : printf("starting bad nbt session test\n");
4043 :
4044 4 : make_nmb_name(&calling, myname, 0x0);
4045 4 : make_nmb_name(&called , host, 0x20);
4046 :
4047 4 : if (!resolve_name(host, &ss, 0x20, true)) {
4048 0 : d_fprintf(stderr, "Could not resolve name %s\n", host);
4049 0 : return false;
4050 : }
4051 :
4052 4 : status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4053 4 : if (!NT_STATUS_IS_OK(status)) {
4054 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
4055 : nt_errstr(status));
4056 0 : return false;
4057 : }
4058 :
4059 4 : ret = cli_bad_session_request(fd, &calling, &called);
4060 4 : close(fd);
4061 4 : if (!ret) {
4062 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
4063 : nt_errstr(status));
4064 0 : return false;
4065 : }
4066 :
4067 4 : printf("finished bad nbt session test\n");
4068 4 : return true;
4069 : }
4070 :
4071 : /* send random IPC commands */
4072 0 : static bool run_randomipc(int dummy)
4073 : {
4074 0 : char *rparam = NULL;
4075 0 : char *rdata = NULL;
4076 0 : unsigned int rdrcnt,rprcnt;
4077 0 : char param[1024];
4078 0 : int api, param_len, i;
4079 0 : struct cli_state *cli;
4080 0 : bool correct = True;
4081 0 : int count = 50000;
4082 :
4083 0 : printf("starting random ipc test\n");
4084 :
4085 0 : if (!torture_open_connection(&cli, 0)) {
4086 0 : return False;
4087 : }
4088 :
4089 0 : for (i=0;i<count;i++) {
4090 0 : api = sys_random() % 500;
4091 0 : param_len = (sys_random() % 64);
4092 :
4093 0 : rand_buf(param, param_len);
4094 :
4095 0 : SSVAL(param,0,api);
4096 :
4097 0 : cli_api(cli,
4098 : param, param_len, 8,
4099 : NULL, 0, CLI_BUFFER_SIZE,
4100 : &rparam, &rprcnt,
4101 : &rdata, &rdrcnt);
4102 0 : if (i % 100 == 0) {
4103 0 : printf("%d/%d\r", i,count);
4104 : }
4105 : }
4106 0 : printf("%d/%d\n", i, count);
4107 :
4108 0 : if (!torture_close_connection(cli)) {
4109 0 : correct = False;
4110 : }
4111 :
4112 0 : SAFE_FREE(rparam);
4113 0 : SAFE_FREE(rdata);
4114 :
4115 0 : printf("finished random ipc test\n");
4116 :
4117 0 : return correct;
4118 : }
4119 :
4120 :
4121 :
4122 8 : static void browse_callback(const char *sname, uint32_t stype,
4123 : const char *comment, void *state)
4124 : {
4125 8 : printf("\t%20.20s %08x %s\n", sname, stype, comment);
4126 8 : }
4127 :
4128 :
4129 :
4130 : /*
4131 : This test checks the browse list code
4132 :
4133 : */
4134 5 : static bool run_browsetest(int dummy)
4135 : {
4136 0 : static struct cli_state *cli;
4137 5 : bool correct = True;
4138 :
4139 5 : printf("starting browse test\n");
4140 :
4141 5 : if (!torture_open_connection(&cli, 0)) {
4142 0 : return False;
4143 : }
4144 :
4145 5 : printf("domain list:\n");
4146 5 : cli_NetServerEnum(cli, cli->server_domain,
4147 : SV_TYPE_DOMAIN_ENUM,
4148 : browse_callback, NULL);
4149 :
4150 5 : printf("machine list:\n");
4151 5 : cli_NetServerEnum(cli, cli->server_domain,
4152 : SV_TYPE_ALL,
4153 : browse_callback, NULL);
4154 :
4155 5 : if (!torture_close_connection(cli)) {
4156 0 : correct = False;
4157 : }
4158 :
4159 5 : printf("browse test finished\n");
4160 :
4161 5 : return correct;
4162 :
4163 : }
4164 :
4165 20 : static bool check_attributes(struct cli_state *cli,
4166 : const char *fname,
4167 : uint32_t expected_attrs)
4168 : {
4169 20 : uint32_t attrs = 0;
4170 20 : NTSTATUS status = cli_getatr(cli,
4171 : fname,
4172 : &attrs,
4173 : NULL,
4174 : NULL);
4175 20 : if (!NT_STATUS_IS_OK(status)) {
4176 0 : printf("cli_getatr failed with %s\n",
4177 : nt_errstr(status));
4178 0 : return false;
4179 : }
4180 20 : if (attrs != expected_attrs) {
4181 0 : printf("Attributes incorrect 0x%x, should be 0x%x\n",
4182 : (unsigned int)attrs,
4183 : (unsigned int)expected_attrs);
4184 0 : return false;
4185 : }
4186 20 : return true;
4187 : }
4188 :
4189 : /*
4190 : This checks how the getatr calls works
4191 : */
4192 5 : static bool run_attrtest(int dummy)
4193 : {
4194 0 : struct cli_state *cli;
4195 0 : uint16_t fnum;
4196 0 : time_t t, t2;
4197 5 : const char *fname = "\\attrib123456789.tst";
4198 5 : bool correct = True;
4199 0 : NTSTATUS status;
4200 :
4201 5 : printf("starting attrib test\n");
4202 :
4203 5 : if (!torture_open_connection(&cli, 0)) {
4204 0 : return False;
4205 : }
4206 :
4207 : /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4208 5 : status = cli_unlink(cli, fname, 0x20000);
4209 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4210 0 : correct = false;
4211 0 : goto out;
4212 : }
4213 :
4214 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4215 5 : cli_openx(cli, fname,
4216 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4217 5 : cli_close(cli, fnum);
4218 :
4219 5 : status = cli_getatr(cli, fname, NULL, NULL, &t);
4220 5 : if (!NT_STATUS_IS_OK(status)) {
4221 0 : printf("getatr failed (%s)\n", nt_errstr(status));
4222 0 : correct = False;
4223 : }
4224 :
4225 5 : if (labs(t - time(NULL)) > 60*60*24*10) {
4226 0 : printf("ERROR: SMBgetatr bug. time is %s",
4227 : ctime(&t));
4228 0 : t = time(NULL);
4229 0 : correct = True;
4230 : }
4231 :
4232 5 : t2 = t-60*60*24; /* 1 day ago */
4233 :
4234 : /* Ensure we can't set with out-of-range (unknown) attribute. */
4235 5 : status = cli_setatr(cli, fname, 0x20000, t2);
4236 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4237 0 : correct = false;
4238 0 : goto out;
4239 : }
4240 :
4241 5 : status = cli_setatr(cli, fname, 0, t2);
4242 5 : if (!NT_STATUS_IS_OK(status)) {
4243 0 : printf("setatr failed (%s)\n", nt_errstr(status));
4244 0 : correct = True;
4245 : }
4246 :
4247 5 : status = cli_getatr(cli, fname, NULL, NULL, &t);
4248 5 : if (!NT_STATUS_IS_OK(status)) {
4249 0 : printf("getatr failed (%s)\n", nt_errstr(status));
4250 0 : correct = True;
4251 : }
4252 :
4253 5 : if (t != t2) {
4254 0 : printf("ERROR: getatr/setatr bug. times are\n%s",
4255 : ctime(&t));
4256 0 : printf("%s", ctime(&t2));
4257 0 : correct = True;
4258 : }
4259 :
4260 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4261 :
4262 : /* Check cli_setpathinfo_ext() */
4263 : /* Re-create the file. */
4264 5 : status = cli_openx(cli, fname,
4265 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4266 5 : if (!NT_STATUS_IS_OK(status)) {
4267 0 : printf("Failed to recreate %s (%s)\n",
4268 : fname, nt_errstr(status));
4269 0 : correct = false;
4270 : }
4271 5 : cli_close(cli, fnum);
4272 :
4273 5 : status = cli_setpathinfo_ext(
4274 : cli,
4275 : fname,
4276 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4277 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4278 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4279 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4280 : FILE_ATTRIBUTE_SYSTEM |
4281 : FILE_ATTRIBUTE_HIDDEN |
4282 : FILE_ATTRIBUTE_READONLY);
4283 5 : if (!NT_STATUS_IS_OK(status)) {
4284 0 : printf("cli_setpathinfo_ext failed with %s\n",
4285 : nt_errstr(status));
4286 0 : correct = false;
4287 : }
4288 :
4289 : /* Check attributes are correct. */
4290 5 : correct = check_attributes(cli,
4291 : fname,
4292 : FILE_ATTRIBUTE_SYSTEM |
4293 : FILE_ATTRIBUTE_HIDDEN |
4294 : FILE_ATTRIBUTE_READONLY);
4295 5 : if (correct == false) {
4296 0 : goto out;
4297 : }
4298 :
4299 : /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4300 5 : status = cli_setpathinfo_ext(
4301 : cli,
4302 : fname,
4303 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4304 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4305 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4306 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4307 : FILE_ATTRIBUTE_NORMAL);
4308 5 : if (!NT_STATUS_IS_OK(status)) {
4309 0 : printf("cli_setpathinfo_ext failed with %s\n",
4310 : nt_errstr(status));
4311 0 : correct = false;
4312 : }
4313 :
4314 : /* Check attributes are correct. */
4315 5 : correct = check_attributes(cli,
4316 : fname,
4317 : FILE_ATTRIBUTE_SYSTEM |
4318 : FILE_ATTRIBUTE_HIDDEN |
4319 : FILE_ATTRIBUTE_READONLY);
4320 5 : if (correct == false) {
4321 0 : goto out;
4322 : }
4323 :
4324 : /* Setting to (uint16_t)-1 should also be ignored. */
4325 5 : status = cli_setpathinfo_ext(
4326 : cli,
4327 : fname,
4328 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4329 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4330 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4331 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4332 : (uint32_t)-1);
4333 5 : if (!NT_STATUS_IS_OK(status)) {
4334 0 : printf("cli_setpathinfo_ext failed with %s\n",
4335 : nt_errstr(status));
4336 0 : correct = false;
4337 : }
4338 :
4339 : /* Check attributes are correct. */
4340 5 : correct = check_attributes(cli,
4341 : fname,
4342 : FILE_ATTRIBUTE_SYSTEM |
4343 : FILE_ATTRIBUTE_HIDDEN |
4344 : FILE_ATTRIBUTE_READONLY);
4345 5 : if (correct == false) {
4346 0 : goto out;
4347 : }
4348 :
4349 : /* Setting to 0 should clear them all. */
4350 5 : status = cli_setpathinfo_ext(
4351 : cli,
4352 : fname,
4353 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4354 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4355 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4356 5 : (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4357 : 0);
4358 5 : if (!NT_STATUS_IS_OK(status)) {
4359 0 : printf("cli_setpathinfo_ext failed with %s\n",
4360 : nt_errstr(status));
4361 0 : correct = false;
4362 : }
4363 :
4364 : /* Check attributes are correct. */
4365 5 : correct = check_attributes(cli,
4366 : fname,
4367 : FILE_ATTRIBUTE_NORMAL);
4368 5 : if (correct == false) {
4369 0 : goto out;
4370 : }
4371 :
4372 5 : out:
4373 :
4374 5 : cli_unlink(cli,
4375 : fname,
4376 : FILE_ATTRIBUTE_SYSTEM |
4377 : FILE_ATTRIBUTE_HIDDEN|
4378 : FILE_ATTRIBUTE_READONLY);
4379 :
4380 5 : if (!torture_close_connection(cli)) {
4381 0 : correct = False;
4382 : }
4383 :
4384 5 : printf("attrib test finished\n");
4385 :
4386 5 : return correct;
4387 : }
4388 :
4389 5 : static NTSTATUS cli_qfilename(
4390 : struct cli_state *cli,
4391 : uint16_t fnum,
4392 : TALLOC_CTX *mem_ctx,
4393 : char **_name)
4394 : {
4395 0 : uint16_t recv_flags2;
4396 0 : uint8_t *rdata;
4397 0 : uint32_t num_rdata;
4398 0 : NTSTATUS status;
4399 5 : char *name = NULL;
4400 0 : uint32_t namelen;
4401 :
4402 5 : status = cli_qfileinfo(talloc_tos(), cli, fnum,
4403 : SMB_QUERY_FILE_NAME_INFO,
4404 : 4, CLI_BUFFER_SIZE, &recv_flags2,
4405 : &rdata, &num_rdata);
4406 5 : if (!NT_STATUS_IS_OK(status)) {
4407 0 : return status;
4408 : }
4409 :
4410 5 : namelen = IVAL(rdata, 0);
4411 5 : if (namelen > (num_rdata - 4)) {
4412 0 : TALLOC_FREE(rdata);
4413 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
4414 : }
4415 :
4416 5 : pull_string_talloc(mem_ctx,
4417 : (const char *)rdata,
4418 : recv_flags2,
4419 : &name,
4420 5 : rdata + 4,
4421 : namelen,
4422 : STR_UNICODE);
4423 5 : if (name == NULL) {
4424 0 : status = map_nt_error_from_unix(errno);
4425 0 : TALLOC_FREE(rdata);
4426 0 : return status;
4427 : }
4428 :
4429 5 : *_name = name;
4430 5 : TALLOC_FREE(rdata);
4431 5 : return NT_STATUS_OK;
4432 : }
4433 :
4434 : /*
4435 : This checks a couple of trans2 calls
4436 : */
4437 5 : static bool run_trans2test(int dummy)
4438 : {
4439 0 : struct cli_state *cli;
4440 0 : uint16_t fnum;
4441 0 : off_t size;
4442 0 : time_t c_time, a_time, m_time;
4443 0 : struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4444 5 : const char *fname = "\\trans2.tst";
4445 5 : const char *dname = "\\trans2";
4446 5 : const char *fname2 = "\\trans2\\trans2.tst";
4447 5 : char *pname = NULL;
4448 5 : bool correct = True;
4449 0 : NTSTATUS status;
4450 0 : uint32_t fs_attr;
4451 0 : uint64_t ino;
4452 :
4453 5 : printf("starting trans2 test\n");
4454 :
4455 5 : if (!torture_open_connection(&cli, 0)) {
4456 0 : return False;
4457 : }
4458 :
4459 5 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4460 : /* Ensure ino is zero, SMB2 gets a real one. */
4461 0 : ino = 0;
4462 : } else {
4463 : /* Ensure ino is -1, SMB1 never gets a real one. */
4464 5 : ino = (uint64_t)-1;
4465 : }
4466 :
4467 5 : status = cli_get_fs_attr_info(cli, &fs_attr);
4468 5 : if (!NT_STATUS_IS_OK(status)) {
4469 0 : printf("ERROR: cli_get_fs_attr_info returned %s\n",
4470 : nt_errstr(status));
4471 0 : correct = false;
4472 : }
4473 :
4474 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4475 5 : cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4476 5 : status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4477 : &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4478 5 : if (!NT_STATUS_IS_OK(status)) {
4479 0 : printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4480 0 : correct = False;
4481 : }
4482 :
4483 5 : status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4484 5 : if (!NT_STATUS_IS_OK(status)) {
4485 0 : printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4486 0 : correct = False;
4487 : }
4488 5 : else if (strcmp(pname, fname)) {
4489 0 : printf("qfilename gave different name? [%s] [%s]\n",
4490 : fname, pname);
4491 0 : correct = False;
4492 : }
4493 :
4494 5 : cli_close(cli, fnum);
4495 :
4496 5 : sleep(2);
4497 :
4498 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4499 5 : status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4500 : &fnum);
4501 5 : if (!NT_STATUS_IS_OK(status)) {
4502 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4503 0 : return False;
4504 : }
4505 5 : cli_close(cli, fnum);
4506 :
4507 5 : status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4508 : NULL);
4509 5 : if (!NT_STATUS_IS_OK(status)) {
4510 0 : printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4511 0 : correct = False;
4512 : } else {
4513 5 : time_t t = time(NULL);
4514 :
4515 5 : if (c_time != m_time) {
4516 0 : printf("create time=%s", ctime(&c_time));
4517 0 : printf("modify time=%s", ctime(&m_time));
4518 0 : printf("This system appears to have sticky create times\n");
4519 : }
4520 5 : if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4521 0 : printf("access time=%s", ctime(&a_time));
4522 0 : printf("This system appears to set a midnight access time\n");
4523 0 : correct = False;
4524 : }
4525 :
4526 5 : if (labs(m_time - t) > 60*60*24*7) {
4527 0 : printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4528 0 : correct = False;
4529 : }
4530 : }
4531 :
4532 :
4533 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4534 5 : cli_openx(cli, fname,
4535 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4536 5 : cli_close(cli, fnum);
4537 5 : status = cli_qpathinfo2(cli,
4538 : fname,
4539 : &c_time_ts,
4540 : &a_time_ts,
4541 : &w_time_ts,
4542 : &m_time_ts,
4543 : &size,
4544 : NULL,
4545 : &ino,
4546 : NULL);
4547 5 : if (!NT_STATUS_IS_OK(status)) {
4548 0 : printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4549 0 : correct = False;
4550 : } else {
4551 5 : if (w_time_ts.tv_sec < 60*60*24*2) {
4552 0 : printf("write time=%s", ctime(&w_time_ts.tv_sec));
4553 0 : printf("This system appears to set a initial 0 write time\n");
4554 0 : correct = False;
4555 : }
4556 5 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4557 : /* SMB2 should always return an inode. */
4558 0 : if (ino == 0) {
4559 0 : printf("SMB2 bad inode (0)\n");
4560 0 : correct = false;
4561 : }
4562 : } else {
4563 : /* SMB1 must always return zero here. */
4564 5 : if (ino != 0) {
4565 0 : printf("SMB1 bad inode (!0)\n");
4566 0 : correct = false;
4567 : }
4568 : }
4569 : }
4570 :
4571 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4572 :
4573 :
4574 : /* check if the server updates the directory modification time
4575 : when creating a new file */
4576 5 : status = cli_mkdir(cli, dname);
4577 5 : if (!NT_STATUS_IS_OK(status)) {
4578 0 : printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4579 0 : correct = False;
4580 : }
4581 5 : sleep(3);
4582 5 : status = cli_qpathinfo2(cli,
4583 : "\\trans2\\",
4584 : &c_time_ts,
4585 : &a_time_ts,
4586 : &w_time_ts,
4587 : &m_time_ts,
4588 : &size,
4589 : NULL,
4590 : NULL,
4591 : NULL);
4592 5 : if (!NT_STATUS_IS_OK(status)) {
4593 0 : printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4594 0 : correct = False;
4595 : }
4596 :
4597 5 : cli_openx(cli, fname2,
4598 : O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4599 5 : cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4600 5 : cli_close(cli, fnum);
4601 5 : status = cli_qpathinfo2(cli,
4602 : "\\trans2\\",
4603 : &c_time_ts,
4604 : &a_time_ts,
4605 : &w_time_ts,
4606 : &m_time2_ts,
4607 : &size,
4608 : NULL,
4609 : NULL,
4610 : NULL);
4611 5 : if (!NT_STATUS_IS_OK(status)) {
4612 0 : printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4613 0 : correct = False;
4614 : } else {
4615 5 : if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4616 : == 0) {
4617 0 : printf("This system does not update directory modification times\n");
4618 0 : correct = False;
4619 : }
4620 : }
4621 5 : cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4622 5 : cli_rmdir(cli, dname);
4623 :
4624 5 : if (!torture_close_connection(cli)) {
4625 0 : correct = False;
4626 : }
4627 :
4628 5 : printf("trans2 test finished\n");
4629 :
4630 5 : return correct;
4631 : }
4632 :
4633 : /*
4634 : This checks new W2K calls.
4635 : */
4636 :
4637 180 : static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4638 : {
4639 180 : uint8_t *buf = NULL;
4640 0 : uint32_t len;
4641 0 : NTSTATUS status;
4642 :
4643 180 : status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4644 : CLI_BUFFER_SIZE, NULL, &buf, &len);
4645 180 : if (!NT_STATUS_IS_OK(status)) {
4646 180 : printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4647 : nt_errstr(status));
4648 : } else {
4649 0 : printf("qfileinfo: level %d, len = %u\n", level, len);
4650 0 : dump_data(0, (uint8_t *)buf, len);
4651 0 : printf("\n");
4652 : }
4653 180 : TALLOC_FREE(buf);
4654 180 : return status;
4655 : }
4656 :
4657 5 : static bool run_w2ktest(int dummy)
4658 : {
4659 0 : struct cli_state *cli;
4660 0 : uint16_t fnum;
4661 5 : const char *fname = "\\w2ktest\\w2k.tst";
4662 0 : int level;
4663 5 : bool correct = True;
4664 :
4665 5 : printf("starting w2k test\n");
4666 :
4667 5 : if (!torture_open_connection(&cli, 0)) {
4668 0 : return False;
4669 : }
4670 :
4671 5 : cli_openx(cli, fname,
4672 : O_RDWR | O_CREAT , DENY_NONE, &fnum);
4673 :
4674 185 : for (level = 1004; level < 1040; level++) {
4675 180 : new_trans(cli, fnum, level);
4676 : }
4677 :
4678 5 : cli_close(cli, fnum);
4679 :
4680 5 : if (!torture_close_connection(cli)) {
4681 0 : correct = False;
4682 : }
4683 :
4684 5 : printf("w2k test finished\n");
4685 :
4686 5 : return correct;
4687 : }
4688 :
4689 :
4690 : /*
4691 : this is a harness for some oplock tests
4692 : */
4693 5 : static bool run_oplock1(int dummy)
4694 : {
4695 0 : struct cli_state *cli1;
4696 5 : const char *fname = "\\lockt1.lck";
4697 0 : uint16_t fnum1;
4698 5 : bool correct = True;
4699 0 : NTSTATUS status;
4700 :
4701 5 : printf("starting oplock test 1\n");
4702 :
4703 5 : if (!torture_open_connection(&cli1, 0)) {
4704 0 : return False;
4705 : }
4706 :
4707 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4708 :
4709 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
4710 :
4711 5 : cli1->use_oplocks = True;
4712 :
4713 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4714 : &fnum1);
4715 5 : if (!NT_STATUS_IS_OK(status)) {
4716 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4717 0 : return False;
4718 : }
4719 :
4720 5 : cli1->use_oplocks = False;
4721 :
4722 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4723 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4724 :
4725 5 : status = cli_close(cli1, fnum1);
4726 5 : if (!NT_STATUS_IS_OK(status)) {
4727 0 : printf("close2 failed (%s)\n", nt_errstr(status));
4728 0 : return False;
4729 : }
4730 :
4731 5 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4732 5 : if (!NT_STATUS_IS_OK(status)) {
4733 0 : printf("unlink failed (%s)\n", nt_errstr(status));
4734 0 : return False;
4735 : }
4736 :
4737 5 : if (!torture_close_connection(cli1)) {
4738 0 : correct = False;
4739 : }
4740 :
4741 5 : printf("finished oplock test 1\n");
4742 :
4743 5 : return correct;
4744 : }
4745 :
4746 4 : static bool run_oplock2(int dummy)
4747 : {
4748 0 : struct cli_state *cli1, *cli2;
4749 4 : const char *fname = "\\lockt2.lck";
4750 0 : uint16_t fnum1, fnum2;
4751 4 : int saved_use_oplocks = use_oplocks;
4752 0 : char buf[4];
4753 4 : bool correct = True;
4754 0 : volatile bool *shared_correct;
4755 0 : size_t nread;
4756 0 : NTSTATUS status;
4757 :
4758 4 : shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4759 4 : *shared_correct = True;
4760 :
4761 4 : use_level_II_oplocks = True;
4762 4 : use_oplocks = True;
4763 :
4764 4 : printf("starting oplock test 2\n");
4765 :
4766 4 : if (!torture_open_connection(&cli1, 0)) {
4767 0 : use_level_II_oplocks = False;
4768 0 : use_oplocks = saved_use_oplocks;
4769 0 : return False;
4770 : }
4771 :
4772 4 : if (!torture_open_connection(&cli2, 1)) {
4773 0 : use_level_II_oplocks = False;
4774 0 : use_oplocks = saved_use_oplocks;
4775 0 : return False;
4776 : }
4777 :
4778 4 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4779 :
4780 4 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
4781 4 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
4782 :
4783 4 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4784 : &fnum1);
4785 4 : if (!NT_STATUS_IS_OK(status)) {
4786 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4787 0 : return False;
4788 : }
4789 :
4790 : /* Don't need the globals any more. */
4791 4 : use_level_II_oplocks = False;
4792 4 : use_oplocks = saved_use_oplocks;
4793 :
4794 4 : if (fork() == 0) {
4795 : /* Child code */
4796 4 : status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4797 4 : if (!NT_STATUS_IS_OK(status)) {
4798 0 : printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4799 0 : *shared_correct = False;
4800 0 : exit(0);
4801 : }
4802 :
4803 4 : sleep(2);
4804 :
4805 4 : status = cli_close(cli2, fnum2);
4806 4 : if (!NT_STATUS_IS_OK(status)) {
4807 0 : printf("close2 failed (%s)\n", nt_errstr(status));
4808 0 : *shared_correct = False;
4809 : }
4810 :
4811 4 : exit(0);
4812 : }
4813 :
4814 4 : sleep(2);
4815 :
4816 : /* Ensure cli1 processes the break. Empty file should always return 0
4817 : * bytes. */
4818 4 : status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4819 4 : if (!NT_STATUS_IS_OK(status)) {
4820 0 : printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4821 0 : correct = false;
4822 4 : } else if (nread != 0) {
4823 0 : printf("read on empty fnum1 failed. recv %ld expected %d\n",
4824 : (unsigned long)nread, 0);
4825 0 : correct = false;
4826 : }
4827 :
4828 : /* Should now be at level II. */
4829 : /* Test if sending a write locks causes a break to none. */
4830 4 : status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4831 4 : if (!NT_STATUS_IS_OK(status)) {
4832 0 : printf("lock failed (%s)\n", nt_errstr(status));
4833 0 : correct = False;
4834 : }
4835 :
4836 4 : cli_unlock(cli1, fnum1, 0, 4);
4837 :
4838 4 : sleep(2);
4839 :
4840 4 : status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4841 4 : if (!NT_STATUS_IS_OK(status)) {
4842 0 : printf("lock failed (%s)\n", nt_errstr(status));
4843 0 : correct = False;
4844 : }
4845 :
4846 4 : cli_unlock(cli1, fnum1, 0, 4);
4847 :
4848 4 : sleep(2);
4849 :
4850 4 : cli_read(cli1, fnum1, buf, 0, 4, NULL);
4851 :
4852 4 : status = cli_close(cli1, fnum1);
4853 4 : if (!NT_STATUS_IS_OK(status)) {
4854 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4855 0 : correct = False;
4856 : }
4857 :
4858 4 : sleep(4);
4859 :
4860 4 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4861 4 : if (!NT_STATUS_IS_OK(status)) {
4862 0 : printf("unlink failed (%s)\n", nt_errstr(status));
4863 0 : correct = False;
4864 : }
4865 :
4866 4 : if (!torture_close_connection(cli1)) {
4867 0 : correct = False;
4868 : }
4869 :
4870 4 : if (!*shared_correct) {
4871 0 : correct = False;
4872 : }
4873 :
4874 4 : printf("finished oplock test 2\n");
4875 :
4876 4 : return correct;
4877 : }
4878 :
4879 : struct oplock4_state {
4880 : struct tevent_context *ev;
4881 : struct cli_state *cli;
4882 : bool *got_break;
4883 : uint16_t *fnum2;
4884 : };
4885 :
4886 : static void oplock4_got_break(struct tevent_req *req);
4887 : static void oplock4_got_open(struct tevent_req *req);
4888 :
4889 5 : static bool run_oplock4(int dummy)
4890 : {
4891 0 : struct tevent_context *ev;
4892 0 : struct cli_state *cli1, *cli2;
4893 0 : struct tevent_req *oplock_req, *open_req;
4894 5 : const char *fname = "\\lockt4.lck";
4895 5 : const char *fname_ln = "\\lockt4_ln.lck";
4896 0 : uint16_t fnum1, fnum2;
4897 5 : int saved_use_oplocks = use_oplocks;
4898 0 : NTSTATUS status;
4899 5 : bool correct = true;
4900 :
4901 0 : bool got_break;
4902 :
4903 0 : struct oplock4_state *state;
4904 :
4905 5 : printf("starting oplock test 4\n");
4906 :
4907 5 : if (!torture_open_connection(&cli1, 0)) {
4908 0 : use_level_II_oplocks = false;
4909 0 : use_oplocks = saved_use_oplocks;
4910 0 : return false;
4911 : }
4912 :
4913 5 : if (!torture_open_connection(&cli2, 1)) {
4914 0 : use_level_II_oplocks = false;
4915 0 : use_oplocks = saved_use_oplocks;
4916 0 : return false;
4917 : }
4918 :
4919 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4920 5 : cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4921 :
4922 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
4923 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
4924 :
4925 : /* Create the file. */
4926 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4927 : &fnum1);
4928 5 : if (!NT_STATUS_IS_OK(status)) {
4929 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4930 0 : return false;
4931 : }
4932 :
4933 5 : status = cli_close(cli1, fnum1);
4934 5 : if (!NT_STATUS_IS_OK(status)) {
4935 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4936 0 : return false;
4937 : }
4938 :
4939 : /* Now create a hardlink. */
4940 5 : status = cli_hardlink(cli1, fname, fname_ln);
4941 5 : if (!NT_STATUS_IS_OK(status)) {
4942 0 : printf("nt hardlink failed (%s)\n", nt_errstr(status));
4943 0 : return false;
4944 : }
4945 :
4946 : /* Prove that opening hardlinks cause deny modes to conflict. */
4947 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4948 5 : if (!NT_STATUS_IS_OK(status)) {
4949 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4950 0 : return false;
4951 : }
4952 :
4953 5 : status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4954 5 : if (NT_STATUS_IS_OK(status)) {
4955 0 : printf("open of %s succeeded - should fail with sharing violation.\n",
4956 : fname_ln);
4957 0 : return false;
4958 : }
4959 :
4960 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4961 0 : printf("open of %s should fail with sharing violation. Got %s\n",
4962 : fname_ln, nt_errstr(status));
4963 0 : return false;
4964 : }
4965 :
4966 5 : status = cli_close(cli1, fnum1);
4967 5 : if (!NT_STATUS_IS_OK(status)) {
4968 0 : printf("close1 failed (%s)\n", nt_errstr(status));
4969 0 : return false;
4970 : }
4971 :
4972 5 : cli1->use_oplocks = true;
4973 5 : cli2->use_oplocks = true;
4974 :
4975 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4976 5 : if (!NT_STATUS_IS_OK(status)) {
4977 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4978 0 : return false;
4979 : }
4980 :
4981 5 : ev = samba_tevent_context_init(talloc_tos());
4982 5 : if (ev == NULL) {
4983 0 : printf("tevent_context_init failed\n");
4984 0 : return false;
4985 : }
4986 :
4987 5 : state = talloc(ev, struct oplock4_state);
4988 5 : if (state == NULL) {
4989 0 : printf("talloc failed\n");
4990 0 : return false;
4991 : }
4992 5 : state->ev = ev;
4993 5 : state->cli = cli1;
4994 5 : state->got_break = &got_break;
4995 5 : state->fnum2 = &fnum2;
4996 :
4997 5 : oplock_req = cli_smb_oplock_break_waiter_send(
4998 : talloc_tos(), ev, cli1);
4999 5 : if (oplock_req == NULL) {
5000 0 : printf("cli_smb_oplock_break_waiter_send failed\n");
5001 0 : return false;
5002 : }
5003 5 : tevent_req_set_callback(oplock_req, oplock4_got_break, state);
5004 :
5005 5 : open_req = cli_openx_send(
5006 : talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
5007 5 : if (open_req == NULL) {
5008 0 : printf("cli_openx_send failed\n");
5009 0 : return false;
5010 : }
5011 5 : tevent_req_set_callback(open_req, oplock4_got_open, state);
5012 :
5013 5 : got_break = false;
5014 5 : fnum2 = 0xffff;
5015 :
5016 40 : while (!got_break || fnum2 == 0xffff) {
5017 0 : int ret;
5018 35 : ret = tevent_loop_once(ev);
5019 35 : if (ret == -1) {
5020 0 : printf("tevent_loop_once failed: %s\n",
5021 0 : strerror(errno));
5022 0 : return false;
5023 : }
5024 : }
5025 :
5026 5 : status = cli_close(cli2, fnum2);
5027 5 : if (!NT_STATUS_IS_OK(status)) {
5028 0 : printf("close2 failed (%s)\n", nt_errstr(status));
5029 0 : correct = false;
5030 : }
5031 :
5032 5 : status = cli_close(cli1, fnum1);
5033 5 : if (!NT_STATUS_IS_OK(status)) {
5034 0 : printf("close1 failed (%s)\n", nt_errstr(status));
5035 0 : correct = false;
5036 : }
5037 :
5038 5 : status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5039 5 : if (!NT_STATUS_IS_OK(status)) {
5040 0 : printf("unlink failed (%s)\n", nt_errstr(status));
5041 0 : correct = false;
5042 : }
5043 :
5044 5 : status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5045 5 : if (!NT_STATUS_IS_OK(status)) {
5046 0 : printf("unlink failed (%s)\n", nt_errstr(status));
5047 0 : correct = false;
5048 : }
5049 :
5050 5 : if (!torture_close_connection(cli1)) {
5051 0 : correct = false;
5052 : }
5053 :
5054 5 : if (!got_break) {
5055 0 : correct = false;
5056 : }
5057 :
5058 5 : printf("finished oplock test 4\n");
5059 :
5060 5 : return correct;
5061 : }
5062 :
5063 5 : static void oplock4_got_break(struct tevent_req *req)
5064 : {
5065 5 : struct oplock4_state *state = tevent_req_callback_data(
5066 : req, struct oplock4_state);
5067 0 : uint16_t fnum;
5068 0 : uint8_t level;
5069 0 : NTSTATUS status;
5070 :
5071 5 : status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
5072 5 : TALLOC_FREE(req);
5073 5 : if (!NT_STATUS_IS_OK(status)) {
5074 0 : printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5075 : nt_errstr(status));
5076 0 : return;
5077 : }
5078 5 : *state->got_break = true;
5079 :
5080 5 : req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5081 : NO_OPLOCK);
5082 5 : if (req == NULL) {
5083 0 : printf("cli_oplock_ack_send failed\n");
5084 0 : return;
5085 : }
5086 : }
5087 :
5088 5 : static void oplock4_got_open(struct tevent_req *req)
5089 : {
5090 5 : struct oplock4_state *state = tevent_req_callback_data(
5091 : req, struct oplock4_state);
5092 0 : NTSTATUS status;
5093 :
5094 5 : status = cli_openx_recv(req, state->fnum2);
5095 5 : if (!NT_STATUS_IS_OK(status)) {
5096 0 : printf("cli_openx_recv returned %s\n", nt_errstr(status));
5097 0 : *state->fnum2 = 0xffff;
5098 : }
5099 5 : }
5100 :
5101 : #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5102 :
5103 : struct oplock5_state {
5104 : int pipe_down_fd;
5105 : };
5106 :
5107 : /*
5108 : * Async open the file that has a kernel oplock, do an echo to get
5109 : * that 100% across, close the file to signal to the child fd that the
5110 : * oplock can be dropped, wait for the open reply.
5111 : */
5112 :
5113 : static void oplock5_opened(struct tevent_req *subreq);
5114 : static void oplock5_pong(struct tevent_req *subreq);
5115 : static void oplock5_timedout(struct tevent_req *subreq);
5116 :
5117 1 : static struct tevent_req *oplock5_send(
5118 : TALLOC_CTX *mem_ctx,
5119 : struct tevent_context *ev,
5120 : struct cli_state *cli,
5121 : const char *fname,
5122 : int pipe_down_fd)
5123 : {
5124 1 : struct tevent_req *req = NULL, *subreq = NULL;
5125 1 : struct oplock5_state *state = NULL;
5126 0 : static uint8_t data = 0;
5127 :
5128 1 : req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5129 1 : if (req == NULL) {
5130 0 : return NULL;
5131 : }
5132 1 : state->pipe_down_fd = pipe_down_fd;
5133 :
5134 1 : subreq = cli_ntcreate_send(
5135 : state,
5136 : ev,
5137 : cli,
5138 : fname,
5139 : 0, /* CreatFlags */
5140 : SEC_FILE_READ_DATA, /* DesiredAccess */
5141 : FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
5142 : FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5143 : FILE_OPEN, /* CreateDisposition */
5144 : FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5145 : 0, /* Impersonation */
5146 : 0); /* SecurityFlags */
5147 1 : if (tevent_req_nomem(subreq, req)) {
5148 0 : return tevent_req_post(req, ev);
5149 : }
5150 1 : tevent_req_set_callback(subreq, oplock5_opened, req);
5151 :
5152 1 : subreq = cli_echo_send(
5153 : state,
5154 : ev,
5155 : cli,
5156 : 1,
5157 1 : (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5158 1 : if (tevent_req_nomem(subreq, req)) {
5159 0 : return tevent_req_post(req, ev);
5160 : }
5161 1 : tevent_req_set_callback(subreq, oplock5_pong, req);
5162 :
5163 1 : subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5164 1 : if (tevent_req_nomem(subreq, req)) {
5165 0 : return tevent_req_post(req, ev);
5166 : }
5167 1 : tevent_req_set_callback(subreq, oplock5_timedout, req);
5168 :
5169 1 : return req;
5170 : }
5171 :
5172 1 : static void oplock5_opened(struct tevent_req *subreq)
5173 : {
5174 1 : struct tevent_req *req = tevent_req_callback_data(
5175 : subreq, struct tevent_req);
5176 0 : NTSTATUS status;
5177 0 : uint16_t fnum;
5178 :
5179 1 : status = cli_ntcreate_recv(subreq, &fnum, NULL);
5180 1 : TALLOC_FREE(subreq);
5181 1 : if (tevent_req_nterror(req, status)) {
5182 0 : return;
5183 : }
5184 1 : tevent_req_done(req);
5185 : }
5186 :
5187 1 : static void oplock5_pong(struct tevent_req *subreq)
5188 : {
5189 1 : struct tevent_req *req = tevent_req_callback_data(
5190 : subreq, struct tevent_req);
5191 1 : struct oplock5_state *state = tevent_req_data(
5192 : req, struct oplock5_state);
5193 0 : NTSTATUS status;
5194 :
5195 1 : status = cli_echo_recv(subreq);
5196 1 : TALLOC_FREE(subreq);
5197 1 : if (tevent_req_nterror(req, status)) {
5198 0 : return;
5199 : }
5200 :
5201 1 : close(state->pipe_down_fd);
5202 : }
5203 :
5204 0 : static void oplock5_timedout(struct tevent_req *subreq)
5205 : {
5206 0 : struct tevent_req *req = tevent_req_callback_data(
5207 : subreq, struct tevent_req);
5208 0 : bool ok;
5209 :
5210 0 : ok = tevent_wakeup_recv(subreq);
5211 0 : TALLOC_FREE(subreq);
5212 0 : if (!ok) {
5213 0 : tevent_req_oom(req);
5214 0 : return;
5215 : }
5216 0 : tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5217 : }
5218 :
5219 1 : static NTSTATUS oplock5_recv(struct tevent_req *req)
5220 : {
5221 1 : return tevent_req_simple_recv_ntstatus(req);
5222 : }
5223 :
5224 1 : static bool run_oplock5(int dummy)
5225 : {
5226 1 : struct tevent_context *ev = NULL;
5227 1 : struct tevent_req *req = NULL;
5228 1 : struct cli_state *cli = NULL;
5229 1 : const char *fname = "oplock5.txt";
5230 0 : int pipe_down[2], pipe_up[2];
5231 0 : pid_t child_pid;
5232 1 : uint8_t c = '\0';
5233 0 : NTSTATUS status;
5234 0 : int ret;
5235 0 : bool ok;
5236 :
5237 1 : printf("starting oplock5\n");
5238 :
5239 1 : if (local_path == NULL) {
5240 0 : d_fprintf(stderr, "oplock5 must be given a local path via "
5241 : "-l <localpath>\n");
5242 0 : return false;
5243 : }
5244 :
5245 1 : ret = pipe(pipe_down);
5246 1 : if (ret == -1) {
5247 0 : d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5248 0 : return false;
5249 : }
5250 1 : ret = pipe(pipe_up);
5251 1 : if (ret == -1) {
5252 0 : d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5253 0 : return false;
5254 : }
5255 :
5256 1 : child_pid = fork();
5257 2 : if (child_pid == -1) {
5258 0 : d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5259 0 : return false;
5260 : }
5261 :
5262 2 : if (child_pid == 0) {
5263 1 : char *local_file = NULL;
5264 0 : int fd;
5265 :
5266 1 : close(pipe_down[1]);
5267 1 : close(pipe_up[0]);
5268 :
5269 1 : local_file = talloc_asprintf(
5270 1 : talloc_tos(), "%s/%s", local_path, fname);
5271 1 : if (local_file == 0) {
5272 0 : c = 1;
5273 0 : goto do_write;
5274 : }
5275 1 : fd = open(local_file, O_RDWR|O_CREAT, 0644);
5276 1 : if (fd == -1) {
5277 0 : d_fprintf(stderr,
5278 : "open(%s) in child failed: %s\n",
5279 : local_file,
5280 0 : strerror(errno));
5281 0 : c = 2;
5282 0 : goto do_write;
5283 : }
5284 :
5285 1 : signal(SIGIO, SIG_IGN);
5286 :
5287 1 : ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5288 1 : if (ret == -1) {
5289 0 : d_fprintf(stderr,
5290 : "SETLEASE in child failed: %s\n",
5291 0 : strerror(errno));
5292 0 : c = 3;
5293 0 : goto do_write;
5294 : }
5295 :
5296 1 : do_write:
5297 1 : ret = sys_write(pipe_up[1], &c, sizeof(c));
5298 1 : if (ret == -1) {
5299 0 : d_fprintf(stderr,
5300 : "sys_write failed: %s\n",
5301 0 : strerror(errno));
5302 0 : exit(4);
5303 : }
5304 1 : ret = sys_read(pipe_down[0], &c, sizeof(c));
5305 1 : if (ret == -1) {
5306 0 : d_fprintf(stderr,
5307 : "sys_read failed: %s\n",
5308 0 : strerror(errno));
5309 0 : exit(5);
5310 : }
5311 1 : exit(0);
5312 : }
5313 :
5314 1 : close(pipe_up[1]);
5315 1 : close(pipe_down[0]);
5316 :
5317 1 : ret = sys_read(pipe_up[0], &c, sizeof(c));
5318 1 : if (ret != 1) {
5319 0 : d_fprintf(stderr,
5320 : "sys_read failed: %s\n",
5321 0 : strerror(errno));
5322 0 : return false;
5323 : }
5324 1 : if (c != 0) {
5325 0 : d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5326 0 : return false;
5327 : }
5328 :
5329 1 : ok = torture_open_connection(&cli, 0);
5330 1 : if (!ok) {
5331 0 : d_fprintf(stderr, "torture_open_connection failed\n");
5332 0 : return false;
5333 : }
5334 :
5335 1 : ev = samba_tevent_context_init(talloc_tos());
5336 1 : if (ev == NULL) {
5337 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
5338 0 : return false;
5339 : }
5340 :
5341 1 : req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5342 1 : if (req == NULL) {
5343 0 : d_fprintf(stderr, "oplock5_send failed\n");
5344 0 : return false;
5345 : }
5346 :
5347 1 : ok = tevent_req_poll_ntstatus(req, ev, &status);
5348 1 : if (!ok) {
5349 0 : d_fprintf(stderr,
5350 : "tevent_req_poll_ntstatus failed: %s\n",
5351 : nt_errstr(status));
5352 0 : return false;
5353 : }
5354 :
5355 1 : status = oplock5_recv(req);
5356 1 : TALLOC_FREE(req);
5357 1 : if (!NT_STATUS_IS_OK(status)) {
5358 0 : d_fprintf(stderr,
5359 : "oplock5 failed: %s\n",
5360 : nt_errstr(status));
5361 0 : return false;
5362 : }
5363 :
5364 1 : return true;
5365 : }
5366 :
5367 : #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5368 :
5369 : /*
5370 : Test delete on close semantics.
5371 : */
5372 5 : static bool run_deletetest(int dummy)
5373 : {
5374 5 : struct cli_state *cli1 = NULL;
5375 5 : struct cli_state *cli2 = NULL;
5376 5 : const char *fname = "\\delete.file";
5377 5 : uint16_t fnum1 = (uint16_t)-1;
5378 5 : uint16_t fnum2 = (uint16_t)-1;
5379 5 : bool correct = false;
5380 0 : NTSTATUS status;
5381 :
5382 5 : printf("starting delete test\n");
5383 :
5384 5 : if (!torture_open_connection(&cli1, 0)) {
5385 0 : return False;
5386 : }
5387 :
5388 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
5389 :
5390 : /* Test 1 - this should delete the file on close. */
5391 :
5392 5 : cli_setatr(cli1, fname, 0, 0);
5393 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5394 :
5395 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5396 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5397 : FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5398 5 : if (!NT_STATUS_IS_OK(status)) {
5399 0 : printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5400 0 : goto fail;
5401 : }
5402 :
5403 5 : status = cli_close(cli1, fnum1);
5404 5 : if (!NT_STATUS_IS_OK(status)) {
5405 0 : printf("[1] close failed (%s)\n", nt_errstr(status));
5406 0 : goto fail;
5407 : }
5408 :
5409 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5410 5 : if (NT_STATUS_IS_OK(status)) {
5411 0 : printf("[1] open of %s succeeded (should fail)\n", fname);
5412 0 : goto fail;
5413 : }
5414 :
5415 5 : printf("first delete on close test succeeded.\n");
5416 :
5417 : /* Test 2 - this should delete the file on close. */
5418 :
5419 5 : cli_setatr(cli1, fname, 0, 0);
5420 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5421 :
5422 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5423 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5424 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5425 5 : if (!NT_STATUS_IS_OK(status)) {
5426 0 : printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5427 0 : goto fail;
5428 : }
5429 :
5430 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5431 5 : if (!NT_STATUS_IS_OK(status)) {
5432 0 : printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5433 0 : goto fail;
5434 : }
5435 :
5436 5 : status = cli_close(cli1, fnum1);
5437 5 : if (!NT_STATUS_IS_OK(status)) {
5438 0 : printf("[2] close failed (%s)\n", nt_errstr(status));
5439 0 : goto fail;
5440 : }
5441 :
5442 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5443 5 : if (NT_STATUS_IS_OK(status)) {
5444 0 : printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5445 0 : status = cli_close(cli1, fnum1);
5446 0 : if (!NT_STATUS_IS_OK(status)) {
5447 0 : printf("[2] close failed (%s)\n", nt_errstr(status));
5448 : }
5449 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5450 0 : goto fail;
5451 : }
5452 :
5453 5 : printf("second delete on close test succeeded.\n");
5454 :
5455 : /* Test 3 - ... */
5456 5 : cli_setatr(cli1, fname, 0, 0);
5457 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5458 :
5459 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5460 : FILE_ATTRIBUTE_NORMAL,
5461 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5462 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5463 5 : if (!NT_STATUS_IS_OK(status)) {
5464 0 : printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5465 0 : goto fail;
5466 : }
5467 :
5468 : /* This should fail with a sharing violation - open for delete is only compatible
5469 : with SHARE_DELETE. */
5470 :
5471 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5472 : FILE_ATTRIBUTE_NORMAL,
5473 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5474 : FILE_OPEN, 0, 0, &fnum2, NULL);
5475 5 : if (NT_STATUS_IS_OK(status)) {
5476 0 : printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
5477 0 : goto fail;
5478 : }
5479 :
5480 : /* This should succeed. */
5481 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5482 : FILE_ATTRIBUTE_NORMAL,
5483 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5484 : FILE_OPEN, 0, 0, &fnum2, NULL);
5485 5 : if (!NT_STATUS_IS_OK(status)) {
5486 0 : printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5487 0 : goto fail;
5488 : }
5489 :
5490 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5491 5 : if (!NT_STATUS_IS_OK(status)) {
5492 0 : printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5493 0 : goto fail;
5494 : }
5495 :
5496 5 : status = cli_close(cli1, fnum1);
5497 5 : if (!NT_STATUS_IS_OK(status)) {
5498 0 : printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5499 0 : goto fail;
5500 : }
5501 :
5502 5 : status = cli_close(cli1, fnum2);
5503 5 : if (!NT_STATUS_IS_OK(status)) {
5504 0 : printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5505 0 : goto fail;
5506 : }
5507 :
5508 : /* This should fail - file should no longer be there. */
5509 :
5510 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5511 5 : if (NT_STATUS_IS_OK(status)) {
5512 0 : printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5513 0 : status = cli_close(cli1, fnum1);
5514 0 : if (!NT_STATUS_IS_OK(status)) {
5515 0 : printf("[3] close failed (%s)\n", nt_errstr(status));
5516 : }
5517 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5518 0 : goto fail;
5519 : }
5520 :
5521 5 : printf("third delete on close test succeeded.\n");
5522 :
5523 : /* Test 4 ... */
5524 5 : cli_setatr(cli1, fname, 0, 0);
5525 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5526 :
5527 5 : status = cli_ntcreate(cli1, fname, 0,
5528 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5529 : FILE_ATTRIBUTE_NORMAL,
5530 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5531 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5532 5 : if (!NT_STATUS_IS_OK(status)) {
5533 0 : printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5534 0 : goto fail;
5535 : }
5536 :
5537 : /* This should succeed. */
5538 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5539 : FILE_ATTRIBUTE_NORMAL,
5540 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5541 : FILE_OPEN, 0, 0, &fnum2, NULL);
5542 5 : if (!NT_STATUS_IS_OK(status)) {
5543 0 : printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5544 0 : goto fail;
5545 : }
5546 :
5547 5 : status = cli_close(cli1, fnum2);
5548 5 : if (!NT_STATUS_IS_OK(status)) {
5549 0 : printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5550 0 : goto fail;
5551 : }
5552 :
5553 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5554 5 : if (!NT_STATUS_IS_OK(status)) {
5555 0 : printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5556 0 : goto fail;
5557 : }
5558 :
5559 : /* This should fail - no more opens once delete on close set. */
5560 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5561 : FILE_ATTRIBUTE_NORMAL,
5562 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5563 : FILE_OPEN, 0, 0, &fnum2, NULL);
5564 5 : if (NT_STATUS_IS_OK(status)) {
5565 0 : printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
5566 0 : goto fail;
5567 : }
5568 :
5569 5 : status = cli_close(cli1, fnum1);
5570 5 : if (!NT_STATUS_IS_OK(status)) {
5571 0 : printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5572 0 : goto fail;
5573 : }
5574 :
5575 5 : printf("fourth delete on close test succeeded.\n");
5576 :
5577 : /* Test 5 ... */
5578 5 : cli_setatr(cli1, fname, 0, 0);
5579 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5580 :
5581 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5582 5 : if (!NT_STATUS_IS_OK(status)) {
5583 0 : printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5584 0 : goto fail;
5585 : }
5586 :
5587 : /* This should fail - only allowed on NT opens with DELETE access. */
5588 :
5589 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5590 5 : if (NT_STATUS_IS_OK(status)) {
5591 0 : printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5592 0 : goto fail;
5593 : }
5594 :
5595 5 : status = cli_close(cli1, fnum1);
5596 5 : if (!NT_STATUS_IS_OK(status)) {
5597 0 : printf("[5] close failed (%s)\n", nt_errstr(status));
5598 0 : goto fail;
5599 : }
5600 :
5601 5 : printf("fifth delete on close test succeeded.\n");
5602 :
5603 : /* Test 6 ... */
5604 5 : cli_setatr(cli1, fname, 0, 0);
5605 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5606 :
5607 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5608 : FILE_ATTRIBUTE_NORMAL,
5609 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5610 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5611 5 : if (!NT_STATUS_IS_OK(status)) {
5612 0 : printf("[6] open of %s failed (%s)\n", fname,
5613 : nt_errstr(status));
5614 0 : goto fail;
5615 : }
5616 :
5617 : /* This should fail - only allowed on NT opens with DELETE access. */
5618 :
5619 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5620 5 : if (NT_STATUS_IS_OK(status)) {
5621 0 : printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5622 0 : goto fail;
5623 : }
5624 :
5625 5 : status = cli_close(cli1, fnum1);
5626 5 : if (!NT_STATUS_IS_OK(status)) {
5627 0 : printf("[6] close failed (%s)\n", nt_errstr(status));
5628 0 : goto fail;
5629 : }
5630 :
5631 5 : printf("sixth delete on close test succeeded.\n");
5632 :
5633 : /* Test 7 ... */
5634 5 : cli_setatr(cli1, fname, 0, 0);
5635 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5636 :
5637 5 : status = cli_ntcreate(cli1, fname, 0,
5638 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5639 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5640 : 0, 0, &fnum1, NULL);
5641 5 : if (!NT_STATUS_IS_OK(status)) {
5642 0 : printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5643 0 : goto fail;
5644 : }
5645 :
5646 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5647 5 : if (!NT_STATUS_IS_OK(status)) {
5648 0 : printf("[7] setting delete_on_close on file failed !\n");
5649 0 : goto fail;
5650 : }
5651 :
5652 5 : status = cli_nt_delete_on_close(cli1, fnum1, false);
5653 5 : if (!NT_STATUS_IS_OK(status)) {
5654 0 : printf("[7] unsetting delete_on_close on file failed !\n");
5655 0 : goto fail;
5656 : }
5657 :
5658 5 : status = cli_close(cli1, fnum1);
5659 5 : if (!NT_STATUS_IS_OK(status)) {
5660 0 : printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5661 0 : goto fail;
5662 : }
5663 :
5664 : /* This next open should succeed - we reset the flag. */
5665 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5666 5 : if (!NT_STATUS_IS_OK(status)) {
5667 0 : printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5668 0 : goto fail;
5669 : }
5670 :
5671 5 : status = cli_close(cli1, fnum1);
5672 5 : if (!NT_STATUS_IS_OK(status)) {
5673 0 : printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5674 0 : goto fail;
5675 : }
5676 :
5677 5 : printf("seventh delete on close test succeeded.\n");
5678 :
5679 : /* Test 8 ... */
5680 5 : cli_setatr(cli1, fname, 0, 0);
5681 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5682 :
5683 5 : if (!torture_open_connection(&cli2, 1)) {
5684 0 : printf("[8] failed to open second connection.\n");
5685 0 : goto fail;
5686 : }
5687 :
5688 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
5689 :
5690 5 : status = cli_ntcreate(cli1, fname, 0,
5691 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5692 : FILE_ATTRIBUTE_NORMAL,
5693 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5694 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5695 5 : if (!NT_STATUS_IS_OK(status)) {
5696 0 : printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5697 0 : goto fail;
5698 : }
5699 :
5700 5 : status = cli_ntcreate(cli2, fname, 0,
5701 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5702 : FILE_ATTRIBUTE_NORMAL,
5703 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5704 : FILE_OPEN, 0, 0, &fnum2, NULL);
5705 5 : if (!NT_STATUS_IS_OK(status)) {
5706 0 : printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5707 0 : goto fail;
5708 : }
5709 :
5710 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5711 5 : if (!NT_STATUS_IS_OK(status)) {
5712 0 : printf("[8] setting delete_on_close on file failed !\n");
5713 0 : goto fail;
5714 : }
5715 :
5716 5 : status = cli_close(cli1, fnum1);
5717 5 : if (!NT_STATUS_IS_OK(status)) {
5718 0 : printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5719 0 : goto fail;
5720 : }
5721 :
5722 5 : status = cli_close(cli2, fnum2);
5723 5 : if (!NT_STATUS_IS_OK(status)) {
5724 0 : printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5725 0 : goto fail;
5726 : }
5727 :
5728 : /* This should fail.. */
5729 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5730 5 : if (NT_STATUS_IS_OK(status)) {
5731 0 : printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5732 0 : goto fail;
5733 : }
5734 :
5735 5 : printf("eighth delete on close test succeeded.\n");
5736 :
5737 : /* Test 9 ... */
5738 :
5739 : /* This should fail - we need to set DELETE_ACCESS. */
5740 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5741 : FILE_ATTRIBUTE_NORMAL,
5742 : FILE_SHARE_NONE,
5743 : FILE_OVERWRITE_IF,
5744 : FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5745 5 : if (NT_STATUS_IS_OK(status)) {
5746 0 : printf("[9] open of %s succeeded should have failed!\n", fname);
5747 0 : goto fail;
5748 : }
5749 :
5750 5 : printf("ninth delete on close test succeeded.\n");
5751 :
5752 : /* Test 10 ... */
5753 :
5754 5 : status = cli_ntcreate(cli1, fname, 0,
5755 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5756 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5757 : FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5758 : 0, &fnum1, NULL);
5759 5 : if (!NT_STATUS_IS_OK(status)) {
5760 0 : printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5761 0 : goto fail;
5762 : }
5763 :
5764 : /* This should delete the file. */
5765 5 : status = cli_close(cli1, fnum1);
5766 5 : if (!NT_STATUS_IS_OK(status)) {
5767 0 : printf("[10] close failed (%s)\n", nt_errstr(status));
5768 0 : goto fail;
5769 : }
5770 :
5771 : /* This should fail.. */
5772 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5773 5 : if (NT_STATUS_IS_OK(status)) {
5774 0 : printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5775 0 : goto fail;
5776 : }
5777 :
5778 5 : printf("tenth delete on close test succeeded.\n");
5779 :
5780 : /* Test 11 ... */
5781 :
5782 5 : cli_setatr(cli1, fname, 0, 0);
5783 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5784 :
5785 : /* Can we open a read-only file with delete access? */
5786 :
5787 : /* Create a readonly file. */
5788 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5789 : FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5790 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5791 5 : if (!NT_STATUS_IS_OK(status)) {
5792 0 : printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5793 0 : goto fail;
5794 : }
5795 :
5796 5 : status = cli_close(cli1, fnum1);
5797 5 : if (!NT_STATUS_IS_OK(status)) {
5798 0 : printf("[11] close failed (%s)\n", nt_errstr(status));
5799 0 : goto fail;
5800 : }
5801 :
5802 : /* Now try open for delete access. */
5803 5 : status = cli_ntcreate(cli1, fname, 0,
5804 : FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5805 : 0,
5806 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5807 : FILE_OPEN, 0, 0, &fnum1, NULL);
5808 5 : if (!NT_STATUS_IS_OK(status)) {
5809 0 : printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5810 0 : goto fail;
5811 : }
5812 :
5813 5 : cli_close(cli1, fnum1);
5814 :
5815 5 : printf("eleventh delete on close test succeeded.\n");
5816 :
5817 : /*
5818 : * Test 12
5819 : * like test 4 but with initial delete on close
5820 : */
5821 :
5822 5 : cli_setatr(cli1, fname, 0, 0);
5823 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5824 :
5825 5 : status = cli_ntcreate(cli1, fname, 0,
5826 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5827 : FILE_ATTRIBUTE_NORMAL,
5828 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5829 : FILE_OVERWRITE_IF,
5830 : FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5831 5 : if (!NT_STATUS_IS_OK(status)) {
5832 0 : printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5833 0 : goto fail;
5834 : }
5835 :
5836 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5837 : FILE_ATTRIBUTE_NORMAL,
5838 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5839 : FILE_OPEN, 0, 0, &fnum2, NULL);
5840 5 : if (!NT_STATUS_IS_OK(status)) {
5841 0 : printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5842 0 : goto fail;
5843 : }
5844 :
5845 5 : status = cli_close(cli1, fnum2);
5846 5 : if (!NT_STATUS_IS_OK(status)) {
5847 0 : printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5848 0 : goto fail;
5849 : }
5850 :
5851 5 : status = cli_nt_delete_on_close(cli1, fnum1, true);
5852 5 : if (!NT_STATUS_IS_OK(status)) {
5853 0 : printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5854 0 : goto fail;
5855 : }
5856 :
5857 : /* This should fail - no more opens once delete on close set. */
5858 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5859 : FILE_ATTRIBUTE_NORMAL,
5860 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5861 : FILE_OPEN, 0, 0, &fnum2, NULL);
5862 5 : if (NT_STATUS_IS_OK(status)) {
5863 0 : printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5864 0 : goto fail;
5865 : }
5866 :
5867 5 : status = cli_nt_delete_on_close(cli1, fnum1, false);
5868 5 : if (!NT_STATUS_IS_OK(status)) {
5869 0 : printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5870 0 : goto fail;
5871 : }
5872 :
5873 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5874 : FILE_ATTRIBUTE_NORMAL,
5875 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5876 : FILE_OPEN, 0, 0, &fnum2, NULL);
5877 5 : if (!NT_STATUS_IS_OK(status)) {
5878 0 : printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5879 0 : goto fail;
5880 : }
5881 :
5882 5 : status = cli_close(cli1, fnum2);
5883 5 : if (!NT_STATUS_IS_OK(status)) {
5884 0 : printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5885 0 : goto fail;
5886 : }
5887 :
5888 5 : status = cli_close(cli1, fnum1);
5889 5 : if (!NT_STATUS_IS_OK(status)) {
5890 0 : printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5891 0 : goto fail;
5892 : }
5893 :
5894 : /*
5895 : * setting delete on close on the handle does
5896 : * not unset the initial delete on close...
5897 : */
5898 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5899 : FILE_ATTRIBUTE_NORMAL,
5900 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5901 : FILE_OPEN, 0, 0, &fnum2, NULL);
5902 5 : if (NT_STATUS_IS_OK(status)) {
5903 0 : printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5904 0 : goto fail;
5905 5 : } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5906 0 : printf("ntcreate returned %s, expected "
5907 : "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5908 : nt_errstr(status));
5909 0 : goto fail;
5910 : }
5911 :
5912 5 : printf("twelfth delete on close test succeeded.\n");
5913 :
5914 :
5915 5 : printf("finished delete test\n");
5916 :
5917 5 : correct = true;
5918 :
5919 5 : fail:
5920 : /* FIXME: This will crash if we aborted before cli2 got
5921 : * initialized, because these functions don't handle
5922 : * uninitialized connections. */
5923 :
5924 5 : if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5925 5 : if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5926 5 : cli_setatr(cli1, fname, 0, 0);
5927 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5928 :
5929 5 : if (cli1 && !torture_close_connection(cli1)) {
5930 0 : correct = False;
5931 : }
5932 5 : if (cli2 && !torture_close_connection(cli2)) {
5933 0 : correct = False;
5934 : }
5935 5 : return correct;
5936 : }
5937 :
5938 : struct delete_stream_state {
5939 : bool closed;
5940 : };
5941 :
5942 : static void delete_stream_unlinked(struct tevent_req *subreq);
5943 : static void delete_stream_closed(struct tevent_req *subreq);
5944 :
5945 5 : static struct tevent_req *delete_stream_send(
5946 : TALLOC_CTX *mem_ctx,
5947 : struct tevent_context *ev,
5948 : struct cli_state *cli,
5949 : const char *base_fname,
5950 : uint16_t stream_fnum)
5951 : {
5952 5 : struct tevent_req *req = NULL, *subreq = NULL;
5953 5 : struct delete_stream_state *state = NULL;
5954 :
5955 5 : req = tevent_req_create(
5956 : mem_ctx, &state, struct delete_stream_state);
5957 5 : if (req == NULL) {
5958 0 : return NULL;
5959 : }
5960 :
5961 5 : subreq = cli_unlink_send(
5962 : state,
5963 : ev,
5964 : cli,
5965 : base_fname,
5966 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5967 5 : if (tevent_req_nomem(subreq, req)) {
5968 0 : return tevent_req_post(req, ev);
5969 : }
5970 5 : tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5971 :
5972 5 : subreq = cli_close_send(state, ev, cli, stream_fnum, 0);
5973 5 : if (tevent_req_nomem(subreq, req)) {
5974 0 : return tevent_req_post(req, ev);
5975 : }
5976 5 : tevent_req_set_callback(subreq, delete_stream_closed, req);
5977 :
5978 5 : return req;
5979 : }
5980 :
5981 5 : static void delete_stream_unlinked(struct tevent_req *subreq)
5982 : {
5983 5 : struct tevent_req *req = tevent_req_callback_data(
5984 : subreq, struct tevent_req);
5985 5 : struct delete_stream_state *state = tevent_req_data(
5986 : req, struct delete_stream_state);
5987 0 : NTSTATUS status;
5988 :
5989 5 : status = cli_unlink_recv(subreq);
5990 5 : TALLOC_FREE(subreq);
5991 5 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5992 0 : printf("cli_unlink returned %s\n",
5993 : nt_errstr(status));
5994 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5995 0 : return;
5996 : }
5997 5 : if (!state->closed) {
5998 : /* close reply should have come in first */
5999 0 : printf("Not closed\n");
6000 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6001 0 : return;
6002 : }
6003 5 : tevent_req_done(req);
6004 : }
6005 :
6006 5 : static void delete_stream_closed(struct tevent_req *subreq)
6007 : {
6008 5 : struct tevent_req *req = tevent_req_callback_data(
6009 : subreq, struct tevent_req);
6010 5 : struct delete_stream_state *state = tevent_req_data(
6011 : req, struct delete_stream_state);
6012 0 : NTSTATUS status;
6013 :
6014 5 : status = cli_close_recv(subreq);
6015 5 : TALLOC_FREE(subreq);
6016 5 : if (tevent_req_nterror(req, status)) {
6017 0 : return;
6018 : }
6019 : /* also waiting for the unlink to come back */
6020 5 : state->closed = true;
6021 : }
6022 :
6023 5 : static NTSTATUS delete_stream_recv(struct tevent_req *req)
6024 : {
6025 5 : return tevent_req_simple_recv_ntstatus(req);
6026 : }
6027 :
6028 5 : static bool run_delete_stream(int dummy)
6029 : {
6030 5 : struct tevent_context *ev = NULL;
6031 5 : struct tevent_req *req = NULL;
6032 5 : struct cli_state *cli = NULL;
6033 5 : const char fname[] = "delete_stream";
6034 5 : const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
6035 0 : uint16_t fnum1, fnum2;
6036 0 : NTSTATUS status;
6037 0 : bool ok;
6038 :
6039 5 : printf("Starting stream delete test\n");
6040 :
6041 5 : ok = torture_open_connection(&cli, 0);
6042 5 : if (!ok) {
6043 0 : return false;
6044 : }
6045 :
6046 5 : cli_setatr(cli, fname, 0, 0);
6047 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6048 :
6049 : /* Create the file. */
6050 5 : status = cli_ntcreate(
6051 : cli,
6052 : fname,
6053 : 0,
6054 : READ_CONTROL_ACCESS,
6055 : 0,
6056 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6057 : FILE_CREATE,
6058 : 0x0,
6059 : 0x0,
6060 : &fnum1,
6061 : NULL);
6062 5 : if (!NT_STATUS_IS_OK(status)) {
6063 0 : d_fprintf(stderr,
6064 : "cli_ntcreate of %s failed (%s)\n",
6065 : fname,
6066 : nt_errstr(status));
6067 0 : return false;
6068 : }
6069 5 : status = cli_close(cli, fnum1);
6070 5 : if (!NT_STATUS_IS_OK(status)) {
6071 0 : d_fprintf(stderr,
6072 : "cli_close of %s failed (%s)\n",
6073 : fname,
6074 : nt_errstr(status));
6075 0 : return false;
6076 : }
6077 :
6078 : /* Now create the stream. */
6079 5 : status = cli_ntcreate(
6080 : cli,
6081 : fname_stream,
6082 : 0,
6083 : FILE_WRITE_DATA,
6084 : 0,
6085 : FILE_SHARE_READ|FILE_SHARE_WRITE,
6086 : FILE_CREATE,
6087 : 0x0,
6088 : 0x0,
6089 : &fnum1,
6090 : NULL);
6091 :
6092 5 : if (!NT_STATUS_IS_OK(status)) {
6093 0 : d_fprintf(stderr,
6094 : "cli_ntcreate of %s failed (%s)\n",
6095 : fname_stream,
6096 : nt_errstr(status));
6097 0 : return false;
6098 : }
6099 :
6100 : /* open it a second time */
6101 :
6102 5 : status = cli_ntcreate(
6103 : cli,
6104 : fname_stream,
6105 : 0,
6106 : FILE_WRITE_DATA,
6107 : 0,
6108 : FILE_SHARE_READ|FILE_SHARE_WRITE,
6109 : FILE_OPEN,
6110 : 0x0,
6111 : 0x0,
6112 : &fnum2,
6113 : NULL);
6114 :
6115 5 : if (!NT_STATUS_IS_OK(status)) {
6116 0 : d_fprintf(stderr,
6117 : "2nd cli_ntcreate of %s failed (%s)\n",
6118 : fname_stream,
6119 : nt_errstr(status));
6120 0 : return false;
6121 : }
6122 :
6123 5 : ev = samba_tevent_context_init(talloc_tos());
6124 5 : if (ev == NULL) {
6125 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
6126 0 : return false;
6127 : }
6128 :
6129 5 : req = delete_stream_send(ev, ev, cli, fname, fnum1);
6130 5 : if (req == NULL) {
6131 0 : d_fprintf(stderr, "delete_stream_send failed\n");
6132 0 : return false;
6133 : }
6134 :
6135 5 : ok = tevent_req_poll_ntstatus(req, ev, &status);
6136 5 : if (!ok) {
6137 0 : d_fprintf(stderr,
6138 : "tevent_req_poll_ntstatus failed: %s\n",
6139 : nt_errstr(status));
6140 0 : return false;
6141 : }
6142 :
6143 5 : status = delete_stream_recv(req);
6144 5 : TALLOC_FREE(req);
6145 5 : if (!NT_STATUS_IS_OK(status)) {
6146 0 : d_fprintf(stderr,
6147 : "delete_stream failed: %s\n",
6148 : nt_errstr(status));
6149 0 : return false;
6150 : }
6151 :
6152 5 : status = cli_close(cli, fnum2);
6153 5 : if (!NT_STATUS_IS_OK(status)) {
6154 0 : d_fprintf(stderr,
6155 : "close failed: %s\n",
6156 : nt_errstr(status));
6157 0 : return false;
6158 : }
6159 :
6160 5 : status = cli_unlink(
6161 : cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6162 5 : if (!NT_STATUS_IS_OK(status)) {
6163 0 : d_fprintf(stderr,
6164 : "unlink failed: %s\n",
6165 : nt_errstr(status));
6166 0 : return false;
6167 : }
6168 :
6169 5 : return true;
6170 : }
6171 :
6172 : /*
6173 : Exercise delete on close semantics - use on the PRINT1 share in torture
6174 : testing.
6175 : */
6176 2 : static bool run_delete_print_test(int dummy)
6177 : {
6178 2 : struct cli_state *cli1 = NULL;
6179 2 : const char *fname = "print_delete.file";
6180 2 : uint16_t fnum1 = (uint16_t)-1;
6181 2 : bool correct = false;
6182 2 : const char *buf = "print file data\n";
6183 0 : NTSTATUS status;
6184 :
6185 2 : printf("starting print delete test\n");
6186 :
6187 2 : if (!torture_open_connection(&cli1, 0)) {
6188 0 : return false;
6189 : }
6190 :
6191 2 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
6192 :
6193 2 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6194 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6195 : 0, 0, &fnum1, NULL);
6196 2 : if (!NT_STATUS_IS_OK(status)) {
6197 0 : printf("open of %s failed (%s)\n",
6198 : fname,
6199 : nt_errstr(status));
6200 0 : goto fail;
6201 : }
6202 :
6203 2 : status = cli_writeall(cli1,
6204 : fnum1,
6205 : 0,
6206 : (const uint8_t *)buf,
6207 : 0, /* offset */
6208 : strlen(buf), /* size */
6209 : NULL);
6210 2 : if (!NT_STATUS_IS_OK(status)) {
6211 0 : printf("writing print file data failed (%s)\n",
6212 : nt_errstr(status));
6213 0 : goto fail;
6214 : }
6215 :
6216 2 : status = cli_nt_delete_on_close(cli1, fnum1, true);
6217 2 : if (!NT_STATUS_IS_OK(status)) {
6218 0 : printf("setting delete_on_close failed (%s)\n",
6219 : nt_errstr(status));
6220 0 : goto fail;
6221 : }
6222 :
6223 2 : status = cli_close(cli1, fnum1);
6224 2 : if (!NT_STATUS_IS_OK(status)) {
6225 0 : printf("close failed (%s)\n", nt_errstr(status));
6226 0 : goto fail;
6227 : }
6228 :
6229 2 : printf("finished print delete test\n");
6230 :
6231 2 : correct = true;
6232 :
6233 2 : fail:
6234 :
6235 2 : if (fnum1 != (uint16_t)-1) {
6236 2 : cli_close(cli1, fnum1);
6237 : }
6238 :
6239 2 : if (cli1 && !torture_close_connection(cli1)) {
6240 0 : correct = false;
6241 : }
6242 2 : return correct;
6243 : }
6244 :
6245 4 : static bool run_deletetest_ln(int dummy)
6246 : {
6247 0 : struct cli_state *cli;
6248 4 : const char *fname = "\\delete1";
6249 4 : const char *fname_ln = "\\delete1_ln";
6250 0 : uint16_t fnum;
6251 0 : uint16_t fnum1;
6252 0 : NTSTATUS status;
6253 4 : bool correct = true;
6254 0 : time_t t;
6255 :
6256 4 : printf("starting deletetest-ln\n");
6257 :
6258 4 : if (!torture_open_connection(&cli, 0)) {
6259 0 : return false;
6260 : }
6261 :
6262 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6263 4 : cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6264 :
6265 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6266 :
6267 : /* Create the file. */
6268 4 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6269 4 : if (!NT_STATUS_IS_OK(status)) {
6270 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6271 0 : return false;
6272 : }
6273 :
6274 4 : status = cli_close(cli, fnum);
6275 4 : if (!NT_STATUS_IS_OK(status)) {
6276 0 : printf("close1 failed (%s)\n", nt_errstr(status));
6277 0 : return false;
6278 : }
6279 :
6280 : /* Now create a hardlink. */
6281 4 : status = cli_hardlink(cli, fname, fname_ln);
6282 4 : if (!NT_STATUS_IS_OK(status)) {
6283 0 : printf("nt hardlink failed (%s)\n", nt_errstr(status));
6284 0 : return false;
6285 : }
6286 :
6287 : /* Open the original file. */
6288 4 : status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6289 : FILE_ATTRIBUTE_NORMAL,
6290 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6291 : FILE_OPEN_IF, 0, 0, &fnum, NULL);
6292 4 : if (!NT_STATUS_IS_OK(status)) {
6293 0 : printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6294 0 : return false;
6295 : }
6296 :
6297 : /* Unlink the hard link path. */
6298 4 : status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6299 : FILE_ATTRIBUTE_NORMAL,
6300 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6301 : FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6302 4 : if (!NT_STATUS_IS_OK(status)) {
6303 0 : printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6304 0 : return false;
6305 : }
6306 4 : status = cli_nt_delete_on_close(cli, fnum1, true);
6307 4 : if (!NT_STATUS_IS_OK(status)) {
6308 0 : d_printf("(%s) failed to set delete_on_close %s: %s\n",
6309 : __location__, fname_ln, nt_errstr(status));
6310 0 : return false;
6311 : }
6312 :
6313 4 : status = cli_close(cli, fnum1);
6314 4 : if (!NT_STATUS_IS_OK(status)) {
6315 0 : printf("close %s failed (%s)\n",
6316 : fname_ln, nt_errstr(status));
6317 0 : return false;
6318 : }
6319 :
6320 4 : status = cli_close(cli, fnum);
6321 4 : if (!NT_STATUS_IS_OK(status)) {
6322 0 : printf("close %s failed (%s)\n",
6323 : fname, nt_errstr(status));
6324 0 : return false;
6325 : }
6326 :
6327 : /* Ensure the original file is still there. */
6328 4 : status = cli_getatr(cli, fname, NULL, NULL, &t);
6329 4 : if (!NT_STATUS_IS_OK(status)) {
6330 0 : printf("%s getatr on file %s failed (%s)\n",
6331 : __location__,
6332 : fname,
6333 : nt_errstr(status));
6334 0 : correct = False;
6335 : }
6336 :
6337 : /* Ensure the link path is gone. */
6338 4 : status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6339 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6340 0 : printf("%s, getatr for file %s returned wrong error code %s "
6341 : "- should have been deleted\n",
6342 : __location__,
6343 : fname_ln, nt_errstr(status));
6344 0 : correct = False;
6345 : }
6346 :
6347 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6348 4 : cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6349 :
6350 4 : if (!torture_close_connection(cli)) {
6351 0 : correct = false;
6352 : }
6353 :
6354 4 : printf("finished deletetest-ln\n");
6355 :
6356 4 : return correct;
6357 : }
6358 :
6359 : /*
6360 : print out server properties
6361 : */
6362 5 : static bool run_properties(int dummy)
6363 : {
6364 0 : struct cli_state *cli;
6365 5 : bool correct = True;
6366 :
6367 5 : printf("starting properties test\n");
6368 :
6369 5 : ZERO_STRUCT(cli);
6370 :
6371 5 : if (!torture_open_connection(&cli, 0)) {
6372 0 : return False;
6373 : }
6374 :
6375 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6376 :
6377 5 : d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6378 :
6379 5 : if (!torture_close_connection(cli)) {
6380 0 : correct = False;
6381 : }
6382 :
6383 5 : return correct;
6384 : }
6385 :
6386 :
6387 :
6388 : /* FIRST_DESIRED_ACCESS 0xf019f */
6389 : #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6390 : FILE_READ_EA| /* 0xf */ \
6391 : FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
6392 : FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
6393 : DELETE_ACCESS|READ_CONTROL_ACCESS|\
6394 : WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
6395 : /* SECOND_DESIRED_ACCESS 0xe0080 */
6396 : #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6397 : READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6398 : WRITE_OWNER_ACCESS /* 0xe0000 */
6399 :
6400 : #if 0
6401 : #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6402 : READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6403 : FILE_READ_DATA|\
6404 : WRITE_OWNER_ACCESS /* */
6405 : #endif
6406 :
6407 : /*
6408 : Test ntcreate calls made by xcopy
6409 : */
6410 5 : static bool run_xcopy(int dummy)
6411 : {
6412 0 : static struct cli_state *cli1;
6413 5 : const char *fname = "\\test.txt";
6414 5 : bool correct = True;
6415 0 : uint16_t fnum1, fnum2;
6416 0 : NTSTATUS status;
6417 :
6418 5 : printf("starting xcopy test\n");
6419 :
6420 5 : if (!torture_open_connection(&cli1, 0)) {
6421 0 : return False;
6422 : }
6423 :
6424 5 : status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6425 : FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6426 : FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6427 5 : if (!NT_STATUS_IS_OK(status)) {
6428 0 : printf("First open failed - %s\n", nt_errstr(status));
6429 0 : return False;
6430 : }
6431 :
6432 5 : status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6433 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6434 : FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6435 5 : if (!NT_STATUS_IS_OK(status)) {
6436 0 : printf("second open failed - %s\n", nt_errstr(status));
6437 0 : return False;
6438 : }
6439 :
6440 5 : if (!torture_close_connection(cli1)) {
6441 0 : correct = False;
6442 : }
6443 :
6444 5 : return correct;
6445 : }
6446 :
6447 : /*
6448 : Test rename on files open with share delete and no share delete.
6449 : */
6450 5 : static bool run_rename(int dummy)
6451 : {
6452 0 : static struct cli_state *cli1;
6453 5 : const char *fname = "\\test.txt";
6454 5 : const char *fname1 = "\\test1.txt";
6455 5 : bool correct = True;
6456 0 : uint16_t fnum1;
6457 0 : uint32_t attr;
6458 0 : NTSTATUS status;
6459 :
6460 5 : printf("starting rename test\n");
6461 :
6462 5 : if (!torture_open_connection(&cli1, 0)) {
6463 0 : return False;
6464 : }
6465 :
6466 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6467 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6468 :
6469 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6470 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6471 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6472 5 : if (!NT_STATUS_IS_OK(status)) {
6473 0 : printf("First open failed - %s\n", nt_errstr(status));
6474 0 : return False;
6475 : }
6476 :
6477 5 : status = cli_rename(cli1, fname, fname1, false);
6478 5 : if (!NT_STATUS_IS_OK(status)) {
6479 5 : printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6480 : } else {
6481 0 : printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6482 0 : correct = False;
6483 : }
6484 :
6485 5 : status = cli_close(cli1, fnum1);
6486 5 : if (!NT_STATUS_IS_OK(status)) {
6487 0 : printf("close - 1 failed (%s)\n", nt_errstr(status));
6488 0 : return False;
6489 : }
6490 :
6491 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6492 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6493 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6494 : #if 0
6495 : FILE_SHARE_DELETE|FILE_SHARE_NONE,
6496 : #else
6497 : FILE_SHARE_DELETE|FILE_SHARE_READ,
6498 : #endif
6499 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6500 5 : if (!NT_STATUS_IS_OK(status)) {
6501 0 : printf("Second open failed - %s\n", nt_errstr(status));
6502 0 : return False;
6503 : }
6504 :
6505 5 : status = cli_rename(cli1, fname, fname1, false);
6506 5 : if (!NT_STATUS_IS_OK(status)) {
6507 0 : printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6508 0 : correct = False;
6509 : } else {
6510 5 : printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6511 : }
6512 :
6513 5 : status = cli_close(cli1, fnum1);
6514 5 : if (!NT_STATUS_IS_OK(status)) {
6515 0 : printf("close - 2 failed (%s)\n", nt_errstr(status));
6516 0 : return False;
6517 : }
6518 :
6519 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6520 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6521 :
6522 5 : status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6523 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6524 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6525 5 : if (!NT_STATUS_IS_OK(status)) {
6526 0 : printf("Third open failed - %s\n", nt_errstr(status));
6527 0 : return False;
6528 : }
6529 :
6530 :
6531 5 : status = cli_rename(cli1, fname, fname1, false);
6532 5 : if (!NT_STATUS_IS_OK(status)) {
6533 0 : printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6534 0 : correct = False;
6535 : } else {
6536 5 : printf("Third rename succeeded (SHARE_NONE)\n");
6537 : }
6538 :
6539 5 : status = cli_close(cli1, fnum1);
6540 5 : if (!NT_STATUS_IS_OK(status)) {
6541 0 : printf("close - 3 failed (%s)\n", nt_errstr(status));
6542 0 : return False;
6543 : }
6544 :
6545 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6546 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6547 :
6548 : /*----*/
6549 :
6550 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6551 : FILE_ATTRIBUTE_NORMAL,
6552 : FILE_SHARE_READ | FILE_SHARE_WRITE,
6553 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6554 5 : if (!NT_STATUS_IS_OK(status)) {
6555 0 : printf("Fourth open failed - %s\n", nt_errstr(status));
6556 0 : return False;
6557 : }
6558 :
6559 5 : status = cli_rename(cli1, fname, fname1, false);
6560 5 : if (!NT_STATUS_IS_OK(status)) {
6561 5 : printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6562 : } else {
6563 0 : printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6564 0 : correct = False;
6565 : }
6566 :
6567 5 : status = cli_close(cli1, fnum1);
6568 5 : if (!NT_STATUS_IS_OK(status)) {
6569 0 : printf("close - 4 failed (%s)\n", nt_errstr(status));
6570 0 : return False;
6571 : }
6572 :
6573 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6574 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6575 :
6576 : /*--*/
6577 :
6578 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6579 : FILE_ATTRIBUTE_NORMAL,
6580 : FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6581 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6582 5 : if (!NT_STATUS_IS_OK(status)) {
6583 0 : printf("Fifth open failed - %s\n", nt_errstr(status));
6584 0 : return False;
6585 : }
6586 :
6587 5 : status = cli_rename(cli1, fname, fname1, false);
6588 5 : if (!NT_STATUS_IS_OK(status)) {
6589 0 : printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6590 0 : correct = False;
6591 : } else {
6592 5 : printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6593 : }
6594 :
6595 : /*--*/
6596 5 : status = cli_close(cli1, fnum1);
6597 5 : if (!NT_STATUS_IS_OK(status)) {
6598 0 : printf("close - 5 failed (%s)\n", nt_errstr(status));
6599 0 : return False;
6600 : }
6601 :
6602 : /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6603 5 : status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6604 5 : if (!NT_STATUS_IS_OK(status)) {
6605 0 : printf("getatr on file %s failed - %s ! \n",
6606 : fname1, nt_errstr(status));
6607 0 : correct = False;
6608 : } else {
6609 5 : if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6610 0 : printf("Renamed file %s has wrong attr 0x%x "
6611 : "(should be 0x%x)\n",
6612 : fname1,
6613 : attr,
6614 : (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6615 0 : correct = False;
6616 : } else {
6617 5 : printf("Renamed file %s has archive bit set\n", fname1);
6618 : }
6619 : }
6620 :
6621 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6622 5 : cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6623 :
6624 5 : if (!torture_close_connection(cli1)) {
6625 0 : correct = False;
6626 : }
6627 :
6628 5 : return correct;
6629 : }
6630 :
6631 : /*
6632 : Test rename into a directory with an ACL denying it.
6633 : */
6634 4 : static bool run_rename_access(int dummy)
6635 : {
6636 0 : static struct cli_state *cli = NULL;
6637 0 : static struct cli_state *posix_cli = NULL;
6638 4 : const char *src = "test.txt";
6639 4 : const char *dname = "dir";
6640 4 : const char *dst = "dir\\test.txt";
6641 4 : const char *dsrc = "test.dir";
6642 4 : const char *ddst = "dir\\test.dir";
6643 4 : uint16_t fnum = (uint16_t)-1;
6644 4 : struct security_descriptor *sd = NULL;
6645 4 : struct security_descriptor *newsd = NULL;
6646 0 : NTSTATUS status;
6647 4 : TALLOC_CTX *frame = NULL;
6648 :
6649 4 : frame = talloc_stackframe();
6650 4 : printf("starting rename access test\n");
6651 :
6652 : /* Windows connection. */
6653 4 : if (!torture_open_connection(&cli, 0)) {
6654 0 : goto fail;
6655 : }
6656 :
6657 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6658 :
6659 : /* Posix connection. */
6660 4 : if (!torture_open_connection(&posix_cli, 0)) {
6661 0 : goto fail;
6662 : }
6663 :
6664 4 : smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6665 :
6666 4 : status = torture_setup_unix_extensions(posix_cli);
6667 4 : if (!NT_STATUS_IS_OK(status)) {
6668 0 : goto fail;
6669 : }
6670 :
6671 : /* Start with a clean slate. */
6672 4 : cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6673 4 : cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6674 4 : cli_rmdir(cli, dsrc);
6675 4 : cli_rmdir(cli, ddst);
6676 4 : cli_rmdir(cli, dname);
6677 :
6678 : /*
6679 : * Setup the destination directory with a DENY ACE to
6680 : * prevent new files within it.
6681 : */
6682 4 : status = cli_ntcreate(cli,
6683 : dname,
6684 : 0,
6685 : FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6686 : WRITE_DAC_ACCESS|FILE_READ_DATA|
6687 : WRITE_OWNER_ACCESS,
6688 : FILE_ATTRIBUTE_DIRECTORY,
6689 : FILE_SHARE_READ|FILE_SHARE_WRITE,
6690 : FILE_CREATE,
6691 : FILE_DIRECTORY_FILE,
6692 : 0,
6693 : &fnum,
6694 : NULL);
6695 4 : if (!NT_STATUS_IS_OK(status)) {
6696 0 : printf("Create of %s - %s\n", dname, nt_errstr(status));
6697 0 : goto fail;
6698 : }
6699 :
6700 4 : status = cli_query_secdesc(cli,
6701 : fnum,
6702 : frame,
6703 : &sd);
6704 4 : if (!NT_STATUS_IS_OK(status)) {
6705 0 : printf("cli_query_secdesc failed for %s (%s)\n",
6706 : dname, nt_errstr(status));
6707 0 : goto fail;
6708 : }
6709 :
6710 4 : newsd = security_descriptor_dacl_create(frame,
6711 : 0,
6712 : NULL,
6713 : NULL,
6714 : SID_WORLD,
6715 : SEC_ACE_TYPE_ACCESS_DENIED,
6716 : SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6717 : 0,
6718 : NULL);
6719 4 : if (newsd == NULL) {
6720 0 : goto fail;
6721 : }
6722 8 : sd->dacl = security_acl_concatenate(frame,
6723 4 : newsd->dacl,
6724 4 : sd->dacl);
6725 4 : if (sd->dacl == NULL) {
6726 0 : goto fail;
6727 : }
6728 4 : status = cli_set_secdesc(cli, fnum, sd);
6729 4 : if (!NT_STATUS_IS_OK(status)) {
6730 0 : printf("cli_set_secdesc failed for %s (%s)\n",
6731 : dname, nt_errstr(status));
6732 0 : goto fail;
6733 : }
6734 4 : status = cli_close(cli, fnum);
6735 4 : if (!NT_STATUS_IS_OK(status)) {
6736 0 : printf("close failed for %s (%s)\n",
6737 : dname, nt_errstr(status));
6738 0 : goto fail;
6739 : }
6740 : /* Now go around the back and chmod to 777 via POSIX. */
6741 4 : status = cli_posix_chmod(posix_cli, dname, 0777);
6742 4 : if (!NT_STATUS_IS_OK(status)) {
6743 0 : printf("cli_posix_chmod failed for %s (%s)\n",
6744 : dname, nt_errstr(status));
6745 0 : goto fail;
6746 : }
6747 :
6748 : /* Check we can't create a file within dname via Windows. */
6749 4 : status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6750 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6751 0 : cli_close(posix_cli, fnum);
6752 0 : printf("Create of %s should be ACCESS denied, was %s\n",
6753 : dst, nt_errstr(status));
6754 0 : goto fail;
6755 : }
6756 :
6757 : /* Make the sample file/directory. */
6758 4 : status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6759 4 : if (!NT_STATUS_IS_OK(status)) {
6760 0 : printf("open of %s failed (%s)\n", src, nt_errstr(status));
6761 0 : goto fail;
6762 : }
6763 4 : status = cli_close(cli, fnum);
6764 4 : if (!NT_STATUS_IS_OK(status)) {
6765 0 : printf("cli_close failed (%s)\n", nt_errstr(status));
6766 0 : goto fail;
6767 : }
6768 :
6769 4 : status = cli_mkdir(cli, dsrc);
6770 4 : if (!NT_STATUS_IS_OK(status)) {
6771 0 : printf("cli_mkdir of %s failed (%s)\n",
6772 : dsrc, nt_errstr(status));
6773 0 : goto fail;
6774 : }
6775 :
6776 : /*
6777 : * OK - renames of the new file and directory into the
6778 : * dst directory should fail.
6779 : */
6780 :
6781 4 : status = cli_rename(cli, src, dst, false);
6782 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6783 0 : printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6784 : src, dst, nt_errstr(status));
6785 0 : goto fail;
6786 : }
6787 4 : status = cli_rename(cli, dsrc, ddst, false);
6788 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6789 0 : printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6790 : src, dst, nt_errstr(status));
6791 0 : goto fail;
6792 : }
6793 :
6794 4 : TALLOC_FREE(frame);
6795 4 : return true;
6796 :
6797 0 : fail:
6798 :
6799 0 : if (posix_cli) {
6800 0 : torture_close_connection(posix_cli);
6801 : }
6802 :
6803 0 : if (cli) {
6804 0 : if (fnum != (uint16_t)-1) {
6805 0 : cli_close(cli, fnum);
6806 : }
6807 0 : cli_unlink(cli, src,
6808 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6809 0 : cli_unlink(cli, dst,
6810 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6811 0 : cli_rmdir(cli, dsrc);
6812 0 : cli_rmdir(cli, ddst);
6813 0 : cli_rmdir(cli, dname);
6814 :
6815 0 : torture_close_connection(cli);
6816 : }
6817 :
6818 0 : TALLOC_FREE(frame);
6819 0 : return false;
6820 : }
6821 :
6822 : /*
6823 : Test owner rights ACE.
6824 : */
6825 4 : static bool run_owner_rights(int dummy)
6826 : {
6827 0 : static struct cli_state *cli = NULL;
6828 4 : const char *fname = "owner_rights.txt";
6829 4 : uint16_t fnum = (uint16_t)-1;
6830 4 : struct security_descriptor *sd = NULL;
6831 4 : struct security_descriptor *newsd = NULL;
6832 0 : NTSTATUS status;
6833 4 : TALLOC_CTX *frame = NULL;
6834 :
6835 4 : frame = talloc_stackframe();
6836 4 : printf("starting owner rights test\n");
6837 :
6838 : /* Windows connection. */
6839 4 : if (!torture_open_connection(&cli, 0)) {
6840 0 : goto fail;
6841 : }
6842 :
6843 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
6844 :
6845 : /* Start with a clean slate. */
6846 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6847 :
6848 : /* Create the test file. */
6849 : /* Now try and open for read and write-dac. */
6850 4 : status = cli_ntcreate(cli,
6851 : fname,
6852 : 0,
6853 : GENERIC_ALL_ACCESS,
6854 : FILE_ATTRIBUTE_NORMAL,
6855 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6856 : FILE_SHARE_DELETE,
6857 : FILE_CREATE,
6858 : 0,
6859 : 0,
6860 : &fnum,
6861 : NULL);
6862 4 : if (!NT_STATUS_IS_OK(status)) {
6863 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
6864 0 : goto fail;
6865 : }
6866 :
6867 : /* Get the original SD. */
6868 4 : status = cli_query_secdesc(cli,
6869 : fnum,
6870 : frame,
6871 : &sd);
6872 4 : if (!NT_STATUS_IS_OK(status)) {
6873 0 : printf("cli_query_secdesc failed for %s (%s)\n",
6874 : fname, nt_errstr(status));
6875 0 : goto fail;
6876 : }
6877 :
6878 : /*
6879 : * Add an "owner-rights" ACE denying WRITE_DATA,
6880 : * and an "owner-rights" ACE allowing READ_DATA.
6881 : */
6882 :
6883 4 : newsd = security_descriptor_dacl_create(frame,
6884 : 0,
6885 : NULL,
6886 : NULL,
6887 : SID_OWNER_RIGHTS,
6888 : SEC_ACE_TYPE_ACCESS_DENIED,
6889 : FILE_WRITE_DATA,
6890 : 0,
6891 : SID_OWNER_RIGHTS,
6892 : SEC_ACE_TYPE_ACCESS_ALLOWED,
6893 : FILE_READ_DATA,
6894 : 0,
6895 : NULL);
6896 4 : if (newsd == NULL) {
6897 0 : goto fail;
6898 : }
6899 8 : sd->dacl = security_acl_concatenate(frame,
6900 4 : newsd->dacl,
6901 4 : sd->dacl);
6902 4 : if (sd->dacl == NULL) {
6903 0 : goto fail;
6904 : }
6905 4 : status = cli_set_secdesc(cli, fnum, sd);
6906 4 : if (!NT_STATUS_IS_OK(status)) {
6907 0 : printf("cli_set_secdesc failed for %s (%s)\n",
6908 : fname, nt_errstr(status));
6909 0 : goto fail;
6910 : }
6911 4 : status = cli_close(cli, fnum);
6912 4 : if (!NT_STATUS_IS_OK(status)) {
6913 0 : printf("close failed for %s (%s)\n",
6914 : fname, nt_errstr(status));
6915 0 : goto fail;
6916 : }
6917 4 : fnum = (uint16_t)-1;
6918 :
6919 : /* Try and open for FILE_WRITE_DATA */
6920 4 : status = cli_ntcreate(cli,
6921 : fname,
6922 : 0,
6923 : FILE_WRITE_DATA,
6924 : FILE_ATTRIBUTE_NORMAL,
6925 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6926 : FILE_SHARE_DELETE,
6927 : FILE_OPEN,
6928 : 0,
6929 : 0,
6930 : &fnum,
6931 : NULL);
6932 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6933 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
6934 0 : goto fail;
6935 : }
6936 :
6937 : /* Now try and open for FILE_READ_DATA */
6938 4 : status = cli_ntcreate(cli,
6939 : fname,
6940 : 0,
6941 : FILE_READ_DATA,
6942 : FILE_ATTRIBUTE_NORMAL,
6943 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6944 : FILE_SHARE_DELETE,
6945 : FILE_OPEN,
6946 : 0,
6947 : 0,
6948 : &fnum,
6949 : NULL);
6950 4 : if (!NT_STATUS_IS_OK(status)) {
6951 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
6952 0 : goto fail;
6953 : }
6954 :
6955 4 : status = cli_close(cli, fnum);
6956 4 : if (!NT_STATUS_IS_OK(status)) {
6957 0 : printf("close failed for %s (%s)\n",
6958 : fname, nt_errstr(status));
6959 0 : goto fail;
6960 : }
6961 :
6962 : /* Restore clean slate. */
6963 4 : TALLOC_FREE(sd);
6964 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6965 :
6966 : /* Create the test file. */
6967 4 : status = cli_ntcreate(cli,
6968 : fname,
6969 : 0,
6970 : GENERIC_ALL_ACCESS,
6971 : FILE_ATTRIBUTE_NORMAL,
6972 : FILE_SHARE_READ|FILE_SHARE_WRITE|
6973 : FILE_SHARE_DELETE,
6974 : FILE_CREATE,
6975 : 0,
6976 : 0,
6977 : &fnum,
6978 : NULL);
6979 4 : if (!NT_STATUS_IS_OK(status)) {
6980 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
6981 0 : goto fail;
6982 : }
6983 :
6984 : /* Get the original SD. */
6985 4 : status = cli_query_secdesc(cli,
6986 : fnum,
6987 : frame,
6988 : &sd);
6989 4 : if (!NT_STATUS_IS_OK(status)) {
6990 0 : printf("cli_query_secdesc failed for %s (%s)\n",
6991 : fname, nt_errstr(status));
6992 0 : goto fail;
6993 : }
6994 :
6995 : /*
6996 : * Add an "owner-rights ACE denying WRITE_DATA,
6997 : * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6998 : */
6999 :
7000 4 : newsd = security_descriptor_dacl_create(frame,
7001 : 0,
7002 : NULL,
7003 : NULL,
7004 : SID_OWNER_RIGHTS,
7005 : SEC_ACE_TYPE_ACCESS_DENIED,
7006 : FILE_WRITE_DATA,
7007 : 0,
7008 : SID_OWNER_RIGHTS,
7009 : SEC_ACE_TYPE_ACCESS_ALLOWED,
7010 : FILE_READ_DATA|FILE_WRITE_DATA,
7011 : 0,
7012 : NULL);
7013 4 : if (newsd == NULL) {
7014 0 : goto fail;
7015 : }
7016 8 : sd->dacl = security_acl_concatenate(frame,
7017 4 : newsd->dacl,
7018 4 : sd->dacl);
7019 4 : if (sd->dacl == NULL) {
7020 0 : goto fail;
7021 : }
7022 4 : status = cli_set_secdesc(cli, fnum, sd);
7023 4 : if (!NT_STATUS_IS_OK(status)) {
7024 0 : printf("cli_set_secdesc failed for %s (%s)\n",
7025 : fname, nt_errstr(status));
7026 0 : goto fail;
7027 : }
7028 4 : status = cli_close(cli, fnum);
7029 4 : if (!NT_STATUS_IS_OK(status)) {
7030 0 : printf("close failed for %s (%s)\n",
7031 : fname, nt_errstr(status));
7032 0 : goto fail;
7033 : }
7034 4 : fnum = (uint16_t)-1;
7035 :
7036 : /* Try and open for FILE_WRITE_DATA */
7037 4 : status = cli_ntcreate(cli,
7038 : fname,
7039 : 0,
7040 : FILE_WRITE_DATA,
7041 : FILE_ATTRIBUTE_NORMAL,
7042 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7043 : FILE_SHARE_DELETE,
7044 : FILE_OPEN,
7045 : 0,
7046 : 0,
7047 : &fnum,
7048 : NULL);
7049 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7050 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
7051 0 : goto fail;
7052 : }
7053 :
7054 : /* Now try and open for FILE_READ_DATA */
7055 4 : status = cli_ntcreate(cli,
7056 : fname,
7057 : 0,
7058 : FILE_READ_DATA,
7059 : FILE_ATTRIBUTE_NORMAL,
7060 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7061 : FILE_SHARE_DELETE,
7062 : FILE_OPEN,
7063 : 0,
7064 : 0,
7065 : &fnum,
7066 : NULL);
7067 4 : if (!NT_STATUS_IS_OK(status)) {
7068 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
7069 0 : goto fail;
7070 : }
7071 :
7072 4 : status = cli_close(cli, fnum);
7073 4 : if (!NT_STATUS_IS_OK(status)) {
7074 0 : printf("close failed for %s (%s)\n",
7075 : fname, nt_errstr(status));
7076 0 : goto fail;
7077 : }
7078 :
7079 : /* Restore clean slate. */
7080 4 : TALLOC_FREE(sd);
7081 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7082 :
7083 :
7084 : /* Create the test file. */
7085 4 : status = cli_ntcreate(cli,
7086 : fname,
7087 : 0,
7088 : GENERIC_ALL_ACCESS,
7089 : FILE_ATTRIBUTE_NORMAL,
7090 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7091 : FILE_SHARE_DELETE,
7092 : FILE_CREATE,
7093 : 0,
7094 : 0,
7095 : &fnum,
7096 : NULL);
7097 4 : if (!NT_STATUS_IS_OK(status)) {
7098 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
7099 0 : goto fail;
7100 : }
7101 :
7102 : /* Get the original SD. */
7103 4 : status = cli_query_secdesc(cli,
7104 : fnum,
7105 : frame,
7106 : &sd);
7107 4 : if (!NT_STATUS_IS_OK(status)) {
7108 0 : printf("cli_query_secdesc failed for %s (%s)\n",
7109 : fname, nt_errstr(status));
7110 0 : goto fail;
7111 : }
7112 :
7113 : /*
7114 : * Add an "authenticated users" ACE allowing READ_DATA,
7115 : * add an "owner-rights" denying READ_DATA,
7116 : * and an "authenticated users" ACE allowing WRITE_DATA.
7117 : */
7118 :
7119 4 : newsd = security_descriptor_dacl_create(frame,
7120 : 0,
7121 : NULL,
7122 : NULL,
7123 : SID_NT_AUTHENTICATED_USERS,
7124 : SEC_ACE_TYPE_ACCESS_ALLOWED,
7125 : FILE_READ_DATA,
7126 : 0,
7127 : SID_OWNER_RIGHTS,
7128 : SEC_ACE_TYPE_ACCESS_DENIED,
7129 : FILE_READ_DATA,
7130 : 0,
7131 : SID_NT_AUTHENTICATED_USERS,
7132 : SEC_ACE_TYPE_ACCESS_ALLOWED,
7133 : FILE_WRITE_DATA,
7134 : 0,
7135 : NULL);
7136 4 : if (newsd == NULL) {
7137 0 : printf("newsd == NULL\n");
7138 0 : goto fail;
7139 : }
7140 8 : sd->dacl = security_acl_concatenate(frame,
7141 4 : newsd->dacl,
7142 4 : sd->dacl);
7143 4 : if (sd->dacl == NULL) {
7144 0 : printf("sd->dacl == NULL\n");
7145 0 : goto fail;
7146 : }
7147 4 : status = cli_set_secdesc(cli, fnum, sd);
7148 4 : if (!NT_STATUS_IS_OK(status)) {
7149 0 : printf("cli_set_secdesc failed for %s (%s)\n",
7150 : fname, nt_errstr(status));
7151 0 : goto fail;
7152 : }
7153 4 : status = cli_close(cli, fnum);
7154 4 : if (!NT_STATUS_IS_OK(status)) {
7155 0 : printf("close failed for %s (%s)\n",
7156 : fname, nt_errstr(status));
7157 0 : goto fail;
7158 : }
7159 4 : fnum = (uint16_t)-1;
7160 :
7161 : /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7162 4 : status = cli_ntcreate(cli,
7163 : fname,
7164 : 0,
7165 : FILE_READ_DATA|FILE_WRITE_DATA,
7166 : FILE_ATTRIBUTE_NORMAL,
7167 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7168 : FILE_SHARE_DELETE,
7169 : FILE_OPEN,
7170 : 0,
7171 : 0,
7172 : &fnum,
7173 : NULL);
7174 4 : if (!NT_STATUS_IS_OK(status)) {
7175 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
7176 0 : goto fail;
7177 : }
7178 :
7179 4 : status = cli_close(cli, fnum);
7180 4 : if (!NT_STATUS_IS_OK(status)) {
7181 0 : printf("close failed for %s (%s)\n",
7182 : fname, nt_errstr(status));
7183 0 : goto fail;
7184 : }
7185 :
7186 4 : cli_unlink(cli, fname,
7187 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7188 :
7189 4 : TALLOC_FREE(frame);
7190 4 : return true;
7191 :
7192 0 : fail:
7193 :
7194 0 : if (cli) {
7195 0 : if (fnum != (uint16_t)-1) {
7196 0 : cli_close(cli, fnum);
7197 : }
7198 0 : cli_unlink(cli, fname,
7199 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7200 0 : torture_close_connection(cli);
7201 : }
7202 :
7203 0 : TALLOC_FREE(frame);
7204 0 : return false;
7205 : }
7206 :
7207 : /*
7208 : * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7209 : * Note this test only works with a user with SeSecurityPrivilege set.
7210 : *
7211 : * NB. This is also tested in samba3.base.createx_access
7212 : * but this makes it very explicit what we're looking for.
7213 : */
7214 2 : static bool run_smb1_system_security(int dummy)
7215 : {
7216 0 : static struct cli_state *cli = NULL;
7217 2 : const char *fname = "system_security.txt";
7218 2 : uint16_t fnum = (uint16_t)-1;
7219 0 : NTSTATUS status;
7220 2 : TALLOC_CTX *frame = NULL;
7221 :
7222 2 : frame = talloc_stackframe();
7223 2 : printf("starting smb1 system security test\n");
7224 :
7225 : /* SMB1 connection - torture_open_connection() forces this. */
7226 2 : if (!torture_open_connection(&cli, 0)) {
7227 0 : goto fail;
7228 : }
7229 :
7230 2 : smbXcli_conn_set_sockopt(cli->conn, sockops);
7231 :
7232 : /* Start with a clean slate. */
7233 2 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7234 :
7235 : /* Create the test file. */
7236 2 : status = cli_ntcreate(cli,
7237 : fname,
7238 : 0,
7239 : GENERIC_ALL_ACCESS,
7240 : FILE_ATTRIBUTE_NORMAL,
7241 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7242 : FILE_SHARE_DELETE,
7243 : FILE_CREATE,
7244 : 0,
7245 : 0,
7246 : &fnum,
7247 : NULL);
7248 2 : if (!NT_STATUS_IS_OK(status)) {
7249 0 : printf("Create of %s - %s\n", fname, nt_errstr(status));
7250 0 : goto fail;
7251 : }
7252 :
7253 2 : status = cli_close(cli, fnum);
7254 :
7255 : /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7256 : /*
7257 : * On SMB1 this succeeds - SMB2 it fails,
7258 : * see the SMB2-SACL test.
7259 : */
7260 2 : status = cli_ntcreate(cli,
7261 : fname,
7262 : 0,
7263 : SEC_FLAG_SYSTEM_SECURITY,
7264 : FILE_ATTRIBUTE_NORMAL,
7265 : FILE_SHARE_READ|FILE_SHARE_WRITE|
7266 : FILE_SHARE_DELETE,
7267 : FILE_OPEN,
7268 : 0,
7269 : 0,
7270 : &fnum,
7271 : NULL);
7272 2 : if (!NT_STATUS_IS_OK(status)) {
7273 0 : printf("Open of %s - %s\n", fname, nt_errstr(status));
7274 0 : goto fail;
7275 : }
7276 :
7277 2 : status = cli_close(cli, fnum);
7278 :
7279 2 : cli_unlink(cli, fname,
7280 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7281 :
7282 2 : torture_close_connection(cli);
7283 2 : TALLOC_FREE(frame);
7284 2 : return true;
7285 :
7286 0 : fail:
7287 :
7288 0 : if (cli) {
7289 0 : if (fnum != (uint16_t)-1) {
7290 0 : cli_close(cli, fnum);
7291 : }
7292 0 : cli_unlink(cli, fname,
7293 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7294 0 : torture_close_connection(cli);
7295 : }
7296 :
7297 0 : TALLOC_FREE(frame);
7298 0 : return false;
7299 : }
7300 :
7301 0 : static bool run_pipe_number(int dummy)
7302 : {
7303 0 : struct cli_state *cli1;
7304 0 : const char *pipe_name = "\\SPOOLSS";
7305 0 : uint16_t fnum;
7306 0 : int num_pipes = 0;
7307 0 : NTSTATUS status;
7308 :
7309 0 : printf("starting pipenumber test\n");
7310 0 : if (!torture_open_connection(&cli1, 0)) {
7311 0 : return False;
7312 : }
7313 :
7314 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
7315 0 : while(1) {
7316 0 : status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7317 : FILE_ATTRIBUTE_NORMAL,
7318 : FILE_SHARE_READ|FILE_SHARE_WRITE,
7319 : FILE_OPEN_IF, 0, 0, &fnum, NULL);
7320 0 : if (!NT_STATUS_IS_OK(status)) {
7321 0 : printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7322 0 : break;
7323 : }
7324 0 : num_pipes++;
7325 0 : printf("\r%6d", num_pipes);
7326 : }
7327 :
7328 0 : printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7329 0 : torture_close_connection(cli1);
7330 0 : return True;
7331 : }
7332 :
7333 : /*
7334 : Test open mode returns on read-only files.
7335 : */
7336 5 : static bool run_opentest(int dummy)
7337 : {
7338 0 : static struct cli_state *cli1;
7339 0 : static struct cli_state *cli2;
7340 5 : const char *fname = "\\readonly.file";
7341 0 : uint16_t fnum1, fnum2;
7342 0 : char buf[20];
7343 0 : off_t fsize;
7344 5 : bool correct = True;
7345 0 : char *tmp_path;
7346 0 : NTSTATUS status;
7347 :
7348 5 : printf("starting open test\n");
7349 :
7350 5 : if (!torture_open_connection(&cli1, 0)) {
7351 0 : return False;
7352 : }
7353 :
7354 5 : cli_setatr(cli1, fname, 0, 0);
7355 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7356 :
7357 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
7358 :
7359 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7360 5 : if (!NT_STATUS_IS_OK(status)) {
7361 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7362 0 : return False;
7363 : }
7364 :
7365 5 : status = cli_close(cli1, fnum1);
7366 5 : if (!NT_STATUS_IS_OK(status)) {
7367 0 : printf("close2 failed (%s)\n", nt_errstr(status));
7368 0 : return False;
7369 : }
7370 :
7371 5 : status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7372 5 : if (!NT_STATUS_IS_OK(status)) {
7373 0 : printf("cli_setatr failed (%s)\n", nt_errstr(status));
7374 0 : return False;
7375 : }
7376 :
7377 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7378 5 : if (!NT_STATUS_IS_OK(status)) {
7379 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7380 0 : return False;
7381 : }
7382 :
7383 : /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7384 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7385 :
7386 5 : if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7387 5 : NT_STATUS_ACCESS_DENIED)) {
7388 4 : printf("correct error code ERRDOS/ERRnoaccess returned\n");
7389 : }
7390 :
7391 5 : printf("finished open test 1\n");
7392 :
7393 5 : cli_close(cli1, fnum1);
7394 :
7395 : /* Now try not readonly and ensure ERRbadshare is returned. */
7396 :
7397 5 : cli_setatr(cli1, fname, 0, 0);
7398 :
7399 5 : status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7400 5 : if (!NT_STATUS_IS_OK(status)) {
7401 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7402 0 : return False;
7403 : }
7404 :
7405 : /* This will fail - but the error should be ERRshare. */
7406 5 : status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7407 :
7408 5 : if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7409 5 : NT_STATUS_SHARING_VIOLATION)) {
7410 5 : printf("correct error code ERRDOS/ERRbadshare returned\n");
7411 : }
7412 :
7413 5 : status = cli_close(cli1, fnum1);
7414 5 : if (!NT_STATUS_IS_OK(status)) {
7415 0 : printf("close2 failed (%s)\n", nt_errstr(status));
7416 0 : return False;
7417 : }
7418 :
7419 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7420 :
7421 5 : printf("finished open test 2\n");
7422 :
7423 : /* Test truncate open disposition on file opened for read. */
7424 5 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7425 5 : if (!NT_STATUS_IS_OK(status)) {
7426 0 : printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7427 0 : return False;
7428 : }
7429 :
7430 : /* write 20 bytes. */
7431 :
7432 5 : memset(buf, '\0', 20);
7433 :
7434 5 : status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7435 5 : if (!NT_STATUS_IS_OK(status)) {
7436 0 : printf("write failed (%s)\n", nt_errstr(status));
7437 0 : correct = False;
7438 : }
7439 :
7440 5 : status = cli_close(cli1, fnum1);
7441 5 : if (!NT_STATUS_IS_OK(status)) {
7442 0 : printf("(3) close1 failed (%s)\n", nt_errstr(status));
7443 0 : return False;
7444 : }
7445 :
7446 : /* Ensure size == 20. */
7447 5 : status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7448 5 : if (!NT_STATUS_IS_OK(status)) {
7449 0 : printf("(3) getatr failed (%s)\n", nt_errstr(status));
7450 0 : return False;
7451 : }
7452 :
7453 5 : if (fsize != 20) {
7454 0 : printf("(3) file size != 20\n");
7455 0 : return False;
7456 : }
7457 :
7458 : /* Now test if we can truncate a file opened for readonly. */
7459 5 : status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7460 5 : if (!NT_STATUS_IS_OK(status)) {
7461 0 : printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7462 0 : return False;
7463 : }
7464 :
7465 5 : status = cli_close(cli1, fnum1);
7466 5 : if (!NT_STATUS_IS_OK(status)) {
7467 0 : printf("close2 failed (%s)\n", nt_errstr(status));
7468 0 : return False;
7469 : }
7470 :
7471 : /* Ensure size == 0. */
7472 5 : status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7473 5 : if (!NT_STATUS_IS_OK(status)) {
7474 0 : printf("(3) getatr failed (%s)\n", nt_errstr(status));
7475 0 : return False;
7476 : }
7477 :
7478 5 : if (fsize != 0) {
7479 0 : printf("(3) file size != 0\n");
7480 0 : return False;
7481 : }
7482 5 : printf("finished open test 3\n");
7483 :
7484 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7485 :
7486 5 : printf("Do ctemp tests\n");
7487 5 : status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7488 5 : if (!NT_STATUS_IS_OK(status)) {
7489 0 : printf("ctemp failed (%s)\n", nt_errstr(status));
7490 0 : return False;
7491 : }
7492 :
7493 5 : printf("ctemp gave path %s\n", tmp_path);
7494 5 : status = cli_close(cli1, fnum1);
7495 5 : if (!NT_STATUS_IS_OK(status)) {
7496 0 : printf("close of temp failed (%s)\n", nt_errstr(status));
7497 : }
7498 :
7499 5 : status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7500 5 : if (!NT_STATUS_IS_OK(status)) {
7501 0 : printf("unlink of temp failed (%s)\n", nt_errstr(status));
7502 : }
7503 :
7504 : /* Test the non-io opens... */
7505 :
7506 5 : if (!torture_open_connection(&cli2, 1)) {
7507 0 : return False;
7508 : }
7509 :
7510 5 : cli_setatr(cli2, fname, 0, 0);
7511 5 : cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7512 :
7513 5 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
7514 :
7515 5 : printf("TEST #1 testing 2 non-io opens (no delete)\n");
7516 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7517 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7518 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7519 5 : if (!NT_STATUS_IS_OK(status)) {
7520 0 : printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7521 0 : return False;
7522 : }
7523 :
7524 5 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7525 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7526 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7527 5 : if (!NT_STATUS_IS_OK(status)) {
7528 0 : printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7529 0 : return False;
7530 : }
7531 :
7532 5 : status = cli_close(cli1, fnum1);
7533 5 : if (!NT_STATUS_IS_OK(status)) {
7534 0 : printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7535 0 : return False;
7536 : }
7537 :
7538 5 : status = cli_close(cli2, fnum2);
7539 5 : if (!NT_STATUS_IS_OK(status)) {
7540 0 : printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7541 0 : return False;
7542 : }
7543 :
7544 5 : printf("non-io open test #1 passed.\n");
7545 :
7546 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7547 :
7548 5 : printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7549 :
7550 5 : status = cli_ntcreate(cli1, fname, 0,
7551 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7552 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7553 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7554 5 : if (!NT_STATUS_IS_OK(status)) {
7555 0 : printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7556 0 : return False;
7557 : }
7558 :
7559 5 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7560 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7561 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7562 5 : if (!NT_STATUS_IS_OK(status)) {
7563 0 : printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7564 0 : return False;
7565 : }
7566 :
7567 5 : status = cli_close(cli1, fnum1);
7568 5 : if (!NT_STATUS_IS_OK(status)) {
7569 0 : printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7570 0 : return False;
7571 : }
7572 :
7573 5 : status = cli_close(cli2, fnum2);
7574 5 : if (!NT_STATUS_IS_OK(status)) {
7575 0 : printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7576 0 : return False;
7577 : }
7578 :
7579 5 : printf("non-io open test #2 passed.\n");
7580 :
7581 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7582 :
7583 5 : printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7584 :
7585 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7586 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7587 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7588 5 : if (!NT_STATUS_IS_OK(status)) {
7589 0 : printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7590 0 : return False;
7591 : }
7592 :
7593 5 : status = cli_ntcreate(cli2, fname, 0,
7594 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7595 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7596 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7597 5 : if (!NT_STATUS_IS_OK(status)) {
7598 0 : printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7599 0 : return False;
7600 : }
7601 :
7602 5 : status = cli_close(cli1, fnum1);
7603 5 : if (!NT_STATUS_IS_OK(status)) {
7604 0 : printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7605 0 : return False;
7606 : }
7607 :
7608 5 : status = cli_close(cli2, fnum2);
7609 5 : if (!NT_STATUS_IS_OK(status)) {
7610 0 : printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7611 0 : return False;
7612 : }
7613 :
7614 5 : printf("non-io open test #3 passed.\n");
7615 :
7616 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7617 :
7618 5 : printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7619 :
7620 5 : status = cli_ntcreate(cli1, fname, 0,
7621 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7622 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7623 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7624 5 : if (!NT_STATUS_IS_OK(status)) {
7625 0 : printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7626 0 : return False;
7627 : }
7628 :
7629 5 : status = cli_ntcreate(cli2, fname, 0,
7630 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7631 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7632 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7633 5 : if (NT_STATUS_IS_OK(status)) {
7634 0 : printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7635 0 : return False;
7636 : }
7637 :
7638 5 : printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7639 :
7640 5 : status = cli_close(cli1, fnum1);
7641 5 : if (!NT_STATUS_IS_OK(status)) {
7642 0 : printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7643 0 : return False;
7644 : }
7645 :
7646 5 : printf("non-io open test #4 passed.\n");
7647 :
7648 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7649 :
7650 5 : printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7651 :
7652 5 : status = cli_ntcreate(cli1, fname, 0,
7653 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7654 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7655 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7656 5 : if (!NT_STATUS_IS_OK(status)) {
7657 0 : printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7658 0 : return False;
7659 : }
7660 :
7661 5 : status = cli_ntcreate(cli2, fname, 0,
7662 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7663 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7664 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7665 5 : if (!NT_STATUS_IS_OK(status)) {
7666 0 : printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7667 0 : return False;
7668 : }
7669 :
7670 5 : status = cli_close(cli1, fnum1);
7671 5 : if (!NT_STATUS_IS_OK(status)) {
7672 0 : printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7673 0 : return False;
7674 : }
7675 :
7676 5 : status = cli_close(cli2, fnum2);
7677 5 : if (!NT_STATUS_IS_OK(status)) {
7678 0 : printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7679 0 : return False;
7680 : }
7681 :
7682 5 : printf("non-io open test #5 passed.\n");
7683 :
7684 5 : printf("TEST #6 testing 1 non-io open, one io open\n");
7685 :
7686 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7687 :
7688 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7689 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7690 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7691 5 : if (!NT_STATUS_IS_OK(status)) {
7692 0 : printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7693 0 : return False;
7694 : }
7695 :
7696 5 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7697 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7698 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7699 5 : if (!NT_STATUS_IS_OK(status)) {
7700 0 : printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7701 0 : return False;
7702 : }
7703 :
7704 5 : status = cli_close(cli1, fnum1);
7705 5 : if (!NT_STATUS_IS_OK(status)) {
7706 0 : printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7707 0 : return False;
7708 : }
7709 :
7710 5 : status = cli_close(cli2, fnum2);
7711 5 : if (!NT_STATUS_IS_OK(status)) {
7712 0 : printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7713 0 : return False;
7714 : }
7715 :
7716 5 : printf("non-io open test #6 passed.\n");
7717 :
7718 5 : printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7719 :
7720 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7721 :
7722 5 : status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7723 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7724 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7725 5 : if (!NT_STATUS_IS_OK(status)) {
7726 0 : printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7727 0 : return False;
7728 : }
7729 :
7730 5 : status = cli_ntcreate(cli2, fname, 0,
7731 : DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7732 : FILE_ATTRIBUTE_NORMAL,
7733 : FILE_SHARE_READ|FILE_SHARE_DELETE,
7734 : FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7735 5 : if (NT_STATUS_IS_OK(status)) {
7736 0 : printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7737 0 : return False;
7738 : }
7739 :
7740 5 : printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7741 :
7742 5 : status = cli_close(cli1, fnum1);
7743 5 : if (!NT_STATUS_IS_OK(status)) {
7744 0 : printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7745 0 : return False;
7746 : }
7747 :
7748 5 : printf("non-io open test #7 passed.\n");
7749 :
7750 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7751 :
7752 5 : printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7753 5 : status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7754 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7755 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7756 5 : if (!NT_STATUS_IS_OK(status)) {
7757 0 : printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7758 0 : correct = false;
7759 0 : goto out;
7760 : }
7761 :
7762 : /* Write to ensure we have to update the file time. */
7763 5 : status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7764 : NULL);
7765 5 : if (!NT_STATUS_IS_OK(status)) {
7766 0 : printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7767 0 : correct = false;
7768 0 : goto out;
7769 : }
7770 :
7771 5 : status = cli_close(cli1, fnum1);
7772 5 : if (!NT_STATUS_IS_OK(status)) {
7773 0 : printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7774 0 : correct = false;
7775 : }
7776 :
7777 5 : out:
7778 :
7779 5 : if (!torture_close_connection(cli1)) {
7780 0 : correct = False;
7781 : }
7782 5 : if (!torture_close_connection(cli2)) {
7783 0 : correct = False;
7784 : }
7785 :
7786 5 : return correct;
7787 : }
7788 :
7789 102 : NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7790 : {
7791 0 : uint16_t major, minor;
7792 0 : uint32_t caplow, caphigh;
7793 0 : NTSTATUS status;
7794 :
7795 102 : if (!SERVER_HAS_UNIX_CIFS(cli)) {
7796 0 : printf("Server doesn't support UNIX CIFS extensions.\n");
7797 0 : return NT_STATUS_NOT_SUPPORTED;
7798 : }
7799 :
7800 102 : status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7801 : &caphigh);
7802 102 : if (!NT_STATUS_IS_OK(status)) {
7803 0 : printf("Server didn't return UNIX CIFS extensions: %s\n",
7804 : nt_errstr(status));
7805 0 : return status;
7806 : }
7807 :
7808 102 : status = cli_set_unix_extensions_capabilities(cli, major, minor,
7809 : caplow, caphigh);
7810 102 : if (!NT_STATUS_IS_OK(status)) {
7811 0 : printf("Server doesn't support setting UNIX CIFS extensions: "
7812 : "%s.\n", nt_errstr(status));
7813 0 : return status;
7814 : }
7815 :
7816 102 : return NT_STATUS_OK;
7817 : }
7818 :
7819 : /*
7820 : Test POSIX open /mkdir calls.
7821 : */
7822 4 : static bool run_simple_posix_open_test(int dummy)
7823 : {
7824 0 : static struct cli_state *cli1;
7825 4 : const char *fname = "posix:file";
7826 4 : const char *hname = "posix:hlink";
7827 4 : const char *sname = "posix:symlink";
7828 4 : const char *dname = "posix:dir";
7829 0 : char buf[10];
7830 4 : char *target = NULL;
7831 4 : uint16_t fnum1 = (uint16_t)-1;
7832 0 : SMB_STRUCT_STAT sbuf;
7833 4 : bool correct = false;
7834 0 : NTSTATUS status;
7835 0 : size_t nread;
7836 4 : const char *fname_windows = "windows_file";
7837 4 : uint16_t fnum2 = (uint16_t)-1;
7838 0 : bool ok;
7839 :
7840 4 : printf("Starting simple POSIX open test\n");
7841 :
7842 4 : if (!torture_open_connection(&cli1, 0)) {
7843 0 : return false;
7844 : }
7845 :
7846 4 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
7847 :
7848 4 : status = torture_setup_unix_extensions(cli1);
7849 4 : if (!NT_STATUS_IS_OK(status)) {
7850 0 : return false;
7851 : }
7852 :
7853 4 : cli_setatr(cli1, fname, 0, 0);
7854 4 : cli_posix_unlink(cli1, fname);
7855 4 : cli_setatr(cli1, dname, 0, 0);
7856 4 : cli_posix_rmdir(cli1, dname);
7857 4 : cli_setatr(cli1, hname, 0, 0);
7858 4 : cli_posix_unlink(cli1, hname);
7859 4 : cli_setatr(cli1, sname, 0, 0);
7860 4 : cli_posix_unlink(cli1, sname);
7861 4 : cli_setatr(cli1, fname_windows, 0, 0);
7862 4 : cli_posix_unlink(cli1, fname_windows);
7863 :
7864 : /* Create a directory. */
7865 4 : status = cli_posix_mkdir(cli1, dname, 0777);
7866 4 : if (!NT_STATUS_IS_OK(status)) {
7867 0 : printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7868 0 : goto out;
7869 : }
7870 :
7871 4 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7872 : 0600, &fnum1);
7873 4 : if (!NT_STATUS_IS_OK(status)) {
7874 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7875 0 : goto out;
7876 : }
7877 :
7878 : /* Test ftruncate - set file size. */
7879 4 : status = cli_ftruncate(cli1, fnum1, 1000);
7880 4 : if (!NT_STATUS_IS_OK(status)) {
7881 0 : printf("ftruncate failed (%s)\n", nt_errstr(status));
7882 0 : goto out;
7883 : }
7884 :
7885 : /* Ensure st_size == 1000 */
7886 4 : status = cli_posix_stat(cli1, fname, &sbuf);
7887 4 : if (!NT_STATUS_IS_OK(status)) {
7888 0 : printf("stat failed (%s)\n", nt_errstr(status));
7889 0 : goto out;
7890 : }
7891 :
7892 4 : if (sbuf.st_ex_size != 1000) {
7893 0 : printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7894 0 : goto out;
7895 : }
7896 :
7897 : /* Ensure st_mode == 0600 */
7898 4 : if ((sbuf.st_ex_mode & 07777) != 0600) {
7899 0 : printf("posix_open - bad permissions 0%o != 0600\n",
7900 0 : (unsigned int)(sbuf.st_ex_mode & 07777));
7901 0 : goto out;
7902 : }
7903 :
7904 : /* Test ftruncate - set file size back to zero. */
7905 4 : status = cli_ftruncate(cli1, fnum1, 0);
7906 4 : if (!NT_STATUS_IS_OK(status)) {
7907 0 : printf("ftruncate failed (%s)\n", nt_errstr(status));
7908 0 : goto out;
7909 : }
7910 :
7911 4 : status = cli_close(cli1, fnum1);
7912 4 : if (!NT_STATUS_IS_OK(status)) {
7913 0 : printf("close failed (%s)\n", nt_errstr(status));
7914 0 : goto out;
7915 : }
7916 :
7917 : /* Now open the file again for read only. */
7918 4 : status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7919 4 : if (!NT_STATUS_IS_OK(status)) {
7920 0 : printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7921 0 : goto out;
7922 : }
7923 :
7924 : /* Now unlink while open. */
7925 4 : status = cli_posix_unlink(cli1, fname);
7926 4 : if (!NT_STATUS_IS_OK(status)) {
7927 0 : printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7928 0 : goto out;
7929 : }
7930 :
7931 4 : status = cli_close(cli1, fnum1);
7932 4 : if (!NT_STATUS_IS_OK(status)) {
7933 0 : printf("close(2) failed (%s)\n", nt_errstr(status));
7934 0 : goto out;
7935 : }
7936 :
7937 : /* Ensure the file has gone. */
7938 4 : status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7939 4 : if (NT_STATUS_IS_OK(status)) {
7940 0 : printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7941 0 : goto out;
7942 : }
7943 :
7944 : /* Create again to test open with O_TRUNC. */
7945 4 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7946 4 : if (!NT_STATUS_IS_OK(status)) {
7947 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7948 0 : goto out;
7949 : }
7950 :
7951 : /* Test ftruncate - set file size. */
7952 4 : status = cli_ftruncate(cli1, fnum1, 1000);
7953 4 : if (!NT_STATUS_IS_OK(status)) {
7954 0 : printf("ftruncate failed (%s)\n", nt_errstr(status));
7955 0 : goto out;
7956 : }
7957 :
7958 : /* Ensure st_size == 1000 */
7959 4 : status = cli_posix_stat(cli1, fname, &sbuf);
7960 4 : if (!NT_STATUS_IS_OK(status)) {
7961 0 : printf("stat failed (%s)\n", nt_errstr(status));
7962 0 : goto out;
7963 : }
7964 :
7965 4 : if (sbuf.st_ex_size != 1000) {
7966 0 : printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7967 0 : goto out;
7968 : }
7969 :
7970 4 : status = cli_close(cli1, fnum1);
7971 4 : if (!NT_STATUS_IS_OK(status)) {
7972 0 : printf("close(2) failed (%s)\n", nt_errstr(status));
7973 0 : goto out;
7974 : }
7975 :
7976 : /* Re-open with O_TRUNC. */
7977 4 : status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7978 4 : if (!NT_STATUS_IS_OK(status)) {
7979 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7980 0 : goto out;
7981 : }
7982 :
7983 : /* Ensure st_size == 0 */
7984 4 : status = cli_posix_stat(cli1, fname, &sbuf);
7985 4 : if (!NT_STATUS_IS_OK(status)) {
7986 0 : printf("stat failed (%s)\n", nt_errstr(status));
7987 0 : goto out;
7988 : }
7989 :
7990 4 : if (sbuf.st_ex_size != 0) {
7991 0 : printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7992 0 : goto out;
7993 : }
7994 :
7995 4 : status = cli_close(cli1, fnum1);
7996 4 : if (!NT_STATUS_IS_OK(status)) {
7997 0 : printf("close failed (%s)\n", nt_errstr(status));
7998 0 : goto out;
7999 : }
8000 :
8001 4 : status = cli_posix_unlink(cli1, fname);
8002 4 : if (!NT_STATUS_IS_OK(status)) {
8003 0 : printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
8004 0 : goto out;
8005 : }
8006 :
8007 4 : status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
8008 4 : if (!NT_STATUS_IS_OK(status)) {
8009 0 : printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
8010 : dname, nt_errstr(status));
8011 0 : goto out;
8012 : }
8013 :
8014 4 : cli_close(cli1, fnum1);
8015 :
8016 : /* What happens when we try and POSIX open a directory for write ? */
8017 4 : status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
8018 4 : if (NT_STATUS_IS_OK(status)) {
8019 0 : printf("POSIX open of directory %s succeeded, "
8020 : "should have failed.\n",
8021 : dname);
8022 0 : goto out;
8023 : } else {
8024 4 : if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
8025 4 : NT_STATUS_FILE_IS_A_DIRECTORY)) {
8026 0 : goto out;
8027 : }
8028 : }
8029 :
8030 : /* Create the file. */
8031 4 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8032 : 0600, &fnum1);
8033 4 : if (!NT_STATUS_IS_OK(status)) {
8034 0 : printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
8035 0 : goto out;
8036 : }
8037 :
8038 : /* Write some data into it. */
8039 4 : status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
8040 : NULL);
8041 4 : if (!NT_STATUS_IS_OK(status)) {
8042 0 : printf("cli_write failed: %s\n", nt_errstr(status));
8043 0 : goto out;
8044 : }
8045 :
8046 4 : cli_close(cli1, fnum1);
8047 :
8048 : /* Now create a hardlink. */
8049 4 : status = cli_posix_hardlink(cli1, fname, hname);
8050 4 : if (!NT_STATUS_IS_OK(status)) {
8051 0 : printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
8052 0 : goto out;
8053 : }
8054 :
8055 : /* Now create a symlink. */
8056 4 : status = cli_posix_symlink(cli1, fname, sname);
8057 4 : if (!NT_STATUS_IS_OK(status)) {
8058 0 : printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
8059 0 : goto out;
8060 : }
8061 :
8062 : /* Open the hardlink for read. */
8063 4 : status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
8064 4 : if (!NT_STATUS_IS_OK(status)) {
8065 0 : printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
8066 0 : goto out;
8067 : }
8068 :
8069 4 : status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
8070 4 : if (!NT_STATUS_IS_OK(status)) {
8071 0 : printf("POSIX read of %s failed (%s)\n", hname,
8072 : nt_errstr(status));
8073 0 : goto out;
8074 4 : } else if (nread != 10) {
8075 0 : printf("POSIX read of %s failed. Received %ld, expected %d\n",
8076 : hname, (unsigned long)nread, 10);
8077 0 : goto out;
8078 : }
8079 :
8080 4 : if (memcmp(buf, "TEST DATA\n", 10)) {
8081 0 : printf("invalid data read from hardlink\n");
8082 0 : goto out;
8083 : }
8084 :
8085 : /* Do a POSIX lock/unlock. */
8086 4 : status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8087 4 : if (!NT_STATUS_IS_OK(status)) {
8088 0 : printf("POSIX lock failed %s\n", nt_errstr(status));
8089 0 : goto out;
8090 : }
8091 :
8092 : /* Punch a hole in the locked area. */
8093 4 : status = cli_posix_unlock(cli1, fnum1, 10, 80);
8094 4 : if (!NT_STATUS_IS_OK(status)) {
8095 0 : printf("POSIX unlock failed %s\n", nt_errstr(status));
8096 0 : goto out;
8097 : }
8098 :
8099 4 : cli_close(cli1, fnum1);
8100 :
8101 : /* Open the symlink for read - this should fail. A POSIX
8102 : client should not be doing opens on a symlink. */
8103 4 : status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8104 4 : if (NT_STATUS_IS_OK(status)) {
8105 0 : printf("POSIX open of %s succeeded (should have failed)\n", sname);
8106 0 : goto out;
8107 : }
8108 4 : ok = check_both_error(
8109 : __LINE__, status, ERRDOS, ERRbadpath,
8110 4 : NT_STATUS_OBJECT_NAME_NOT_FOUND);
8111 4 : if (!ok) {
8112 0 : printf("POSIX open of %s should have failed "
8113 : "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8114 : "failed with %s instead.\n",
8115 : sname, nt_errstr(status));
8116 0 : goto out;
8117 : }
8118 :
8119 4 : status = cli_readlink(cli1, sname, talloc_tos(), &target, NULL, NULL);
8120 4 : if (!NT_STATUS_IS_OK(status)) {
8121 0 : printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8122 0 : goto out;
8123 : }
8124 :
8125 4 : if (strcmp(target, fname) != 0) {
8126 0 : printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8127 : sname, fname, target);
8128 0 : goto out;
8129 : }
8130 :
8131 4 : status = cli_posix_rmdir(cli1, dname);
8132 4 : if (!NT_STATUS_IS_OK(status)) {
8133 0 : printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8134 0 : goto out;
8135 : }
8136 :
8137 : /* Check directory opens with a specific permission. */
8138 4 : status = cli_posix_mkdir(cli1, dname, 0700);
8139 4 : if (!NT_STATUS_IS_OK(status)) {
8140 0 : printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8141 0 : goto out;
8142 : }
8143 :
8144 : /* Ensure st_mode == 0700 */
8145 4 : status = cli_posix_stat(cli1, dname, &sbuf);
8146 4 : if (!NT_STATUS_IS_OK(status)) {
8147 0 : printf("stat failed (%s)\n", nt_errstr(status));
8148 0 : goto out;
8149 : }
8150 :
8151 4 : if ((sbuf.st_ex_mode & 07777) != 0700) {
8152 0 : printf("posix_mkdir - bad permissions 0%o != 0700\n",
8153 0 : (unsigned int)(sbuf.st_ex_mode & 07777));
8154 0 : goto out;
8155 : }
8156 :
8157 : /*
8158 : * Now create a Windows file, and attempt a POSIX unlink.
8159 : * This should fail with a sharing violation but due to:
8160 : *
8161 : * [Bug 9571] Unlink after open causes smbd to panic
8162 : *
8163 : * ensure we've fixed the lock ordering violation.
8164 : */
8165 :
8166 4 : status = cli_ntcreate(cli1, fname_windows, 0,
8167 : FILE_READ_DATA|FILE_WRITE_DATA, 0,
8168 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8169 : FILE_CREATE,
8170 : 0x0, 0x0, &fnum2, NULL);
8171 4 : if (!NT_STATUS_IS_OK(status)) {
8172 0 : printf("Windows create of %s failed (%s)\n", fname_windows,
8173 : nt_errstr(status));
8174 0 : goto out;
8175 : }
8176 :
8177 : /* Now try posix_unlink. */
8178 4 : status = cli_posix_unlink(cli1, fname_windows);
8179 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8180 0 : printf("POSIX unlink of %s should fail "
8181 : "with NT_STATUS_SHARING_VIOLATION "
8182 : "got %s instead !\n",
8183 : fname_windows,
8184 : nt_errstr(status));
8185 0 : goto out;
8186 : }
8187 :
8188 4 : cli_close(cli1, fnum2);
8189 :
8190 4 : printf("Simple POSIX open test passed\n");
8191 4 : correct = true;
8192 :
8193 4 : out:
8194 :
8195 4 : if (fnum1 != (uint16_t)-1) {
8196 4 : cli_close(cli1, fnum1);
8197 4 : fnum1 = (uint16_t)-1;
8198 : }
8199 :
8200 4 : if (fnum2 != (uint16_t)-1) {
8201 4 : cli_close(cli1, fnum2);
8202 4 : fnum2 = (uint16_t)-1;
8203 : }
8204 :
8205 4 : cli_setatr(cli1, sname, 0, 0);
8206 4 : cli_posix_unlink(cli1, sname);
8207 4 : cli_setatr(cli1, hname, 0, 0);
8208 4 : cli_posix_unlink(cli1, hname);
8209 4 : cli_setatr(cli1, fname, 0, 0);
8210 4 : cli_posix_unlink(cli1, fname);
8211 4 : cli_setatr(cli1, dname, 0, 0);
8212 4 : cli_posix_rmdir(cli1, dname);
8213 4 : cli_setatr(cli1, fname_windows, 0, 0);
8214 4 : cli_posix_unlink(cli1, fname_windows);
8215 :
8216 4 : if (!torture_close_connection(cli1)) {
8217 0 : correct = false;
8218 : }
8219 :
8220 4 : return correct;
8221 : }
8222 :
8223 : /*
8224 : Test POSIX and Windows ACLs are rejected on symlinks.
8225 : */
8226 4 : static bool run_acl_symlink_test(int dummy)
8227 : {
8228 0 : static struct cli_state *cli;
8229 4 : const char *fname = "posix_file";
8230 4 : const char *sname = "posix_symlink";
8231 4 : uint16_t fnum = (uint16_t)-1;
8232 4 : bool correct = false;
8233 0 : NTSTATUS status;
8234 4 : char *posix_acl = NULL;
8235 4 : size_t posix_acl_len = 0;
8236 4 : char *posix_acl_sym = NULL;
8237 4 : size_t posix_acl_len_sym = 0;
8238 4 : struct security_descriptor *sd = NULL;
8239 4 : TALLOC_CTX *frame = NULL;
8240 :
8241 4 : frame = talloc_stackframe();
8242 :
8243 4 : printf("Starting acl symlink test\n");
8244 :
8245 4 : if (!torture_open_connection(&cli, 0)) {
8246 0 : TALLOC_FREE(frame);
8247 0 : return false;
8248 : }
8249 :
8250 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
8251 :
8252 4 : status = torture_setup_unix_extensions(cli);
8253 4 : if (!NT_STATUS_IS_OK(status)) {
8254 0 : TALLOC_FREE(frame);
8255 0 : return false;
8256 : }
8257 :
8258 4 : cli_setatr(cli, fname, 0, 0);
8259 4 : cli_posix_unlink(cli, fname);
8260 4 : cli_setatr(cli, sname, 0, 0);
8261 4 : cli_posix_unlink(cli, sname);
8262 :
8263 4 : status = cli_ntcreate(cli,
8264 : fname,
8265 : 0,
8266 : READ_CONTROL_ACCESS,
8267 : 0,
8268 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8269 : FILE_CREATE,
8270 : 0x0,
8271 : 0x0,
8272 : &fnum,
8273 : NULL);
8274 :
8275 4 : if (!NT_STATUS_IS_OK(status)) {
8276 0 : printf("cli_ntcreate of %s failed (%s)\n",
8277 : fname,
8278 : nt_errstr(status));
8279 0 : goto out;
8280 : }
8281 :
8282 : /* Get the Windows ACL on the file. */
8283 4 : status = cli_query_secdesc(cli,
8284 : fnum,
8285 : frame,
8286 : &sd);
8287 4 : if (!NT_STATUS_IS_OK(status)) {
8288 0 : printf("cli_query_secdesc failed (%s)\n",
8289 : nt_errstr(status));
8290 0 : goto out;
8291 : }
8292 :
8293 : /* Get the POSIX ACL on the file. */
8294 4 : status = cli_posix_getacl(cli,
8295 : fname,
8296 : frame,
8297 : &posix_acl_len,
8298 : &posix_acl);
8299 :
8300 4 : if (!NT_STATUS_IS_OK(status)) {
8301 0 : printf("cli_posix_getacl failed (%s)\n",
8302 : nt_errstr(status));
8303 0 : goto out;
8304 : }
8305 :
8306 4 : status = cli_close(cli, fnum);
8307 4 : if (!NT_STATUS_IS_OK(status)) {
8308 0 : printf("close failed (%s)\n", nt_errstr(status));
8309 0 : goto out;
8310 : }
8311 4 : fnum = (uint16_t)-1;
8312 :
8313 : /* Now create a symlink. */
8314 4 : status = cli_posix_symlink(cli, fname, sname);
8315 4 : if (!NT_STATUS_IS_OK(status)) {
8316 0 : printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8317 : sname,
8318 : fname,
8319 : nt_errstr(status));
8320 0 : goto out;
8321 : }
8322 :
8323 : /* Open a handle on the symlink for SD set/get should fail. */
8324 4 : status = cli_ntcreate(cli,
8325 : sname,
8326 : 0,
8327 : READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8328 : 0,
8329 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8330 : FILE_OPEN,
8331 : 0x0,
8332 : 0x0,
8333 : &fnum,
8334 : NULL);
8335 :
8336 4 : if (NT_STATUS_IS_OK(status)) {
8337 0 : printf("Symlink open for getsd/setsd of %s "
8338 : "succeeded (should fail)\n",
8339 : sname);
8340 0 : goto out;
8341 : }
8342 :
8343 : /* Try a stat-open on the symlink, should also fail. */
8344 4 : status = cli_ntcreate(cli,
8345 : sname,
8346 : 0,
8347 : FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8348 : 0,
8349 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8350 : FILE_OPEN,
8351 : 0x0,
8352 : 0x0,
8353 : &fnum,
8354 : NULL);
8355 :
8356 4 : if (NT_STATUS_IS_OK(status)) {
8357 0 : printf("Stat-open of symlink succeeded (should fail)\n");
8358 0 : goto out;
8359 : }
8360 :
8361 : /* Get the POSIX ACL on the symlink pathname. Should fail. */
8362 4 : status = cli_posix_getacl(cli,
8363 : sname,
8364 : frame,
8365 : &posix_acl_len_sym,
8366 : &posix_acl_sym);
8367 :
8368 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8369 0 : printf("cli_posix_getacl on a symlink gave %s. "
8370 : "Should be NT_STATUS_ACCESS_DENIED.\n",
8371 : nt_errstr(status));
8372 0 : goto out;
8373 : }
8374 :
8375 : /* Set the POSIX ACL on the symlink pathname. Should fail. */
8376 4 : status = cli_posix_setacl(cli,
8377 : sname,
8378 : posix_acl,
8379 : posix_acl_len);
8380 :
8381 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8382 0 : printf("cli_posix_setacl on a symlink gave %s. "
8383 : "Should be NT_STATUS_ACCESS_DENIED.\n",
8384 : nt_errstr(status));
8385 0 : goto out;
8386 : }
8387 :
8388 4 : printf("ACL symlink test passed\n");
8389 4 : correct = true;
8390 :
8391 4 : out:
8392 :
8393 4 : if (fnum != (uint16_t)-1) {
8394 0 : cli_close(cli, fnum);
8395 0 : fnum = (uint16_t)-1;
8396 : }
8397 :
8398 4 : cli_setatr(cli, sname, 0, 0);
8399 4 : cli_posix_unlink(cli, sname);
8400 4 : cli_setatr(cli, fname, 0, 0);
8401 4 : cli_posix_unlink(cli, fname);
8402 :
8403 4 : if (!torture_close_connection(cli)) {
8404 0 : correct = false;
8405 : }
8406 :
8407 4 : TALLOC_FREE(frame);
8408 4 : return correct;
8409 : }
8410 :
8411 : /*
8412 : Test POSIX can delete a file containing streams.
8413 : */
8414 4 : static bool run_posix_stream_delete(int dummy)
8415 : {
8416 4 : struct cli_state *cli1 = NULL;
8417 4 : struct cli_state *cli2 = NULL;
8418 4 : const char *fname = "streamfile";
8419 4 : const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8420 4 : uint16_t fnum1 = (uint16_t)-1;
8421 4 : bool correct = false;
8422 0 : NTSTATUS status;
8423 4 : TALLOC_CTX *frame = NULL;
8424 :
8425 4 : frame = talloc_stackframe();
8426 :
8427 4 : printf("Starting POSIX stream delete test\n");
8428 :
8429 4 : if (!torture_open_connection(&cli1, 0) ||
8430 4 : !torture_open_connection(&cli2, 1)) {
8431 0 : TALLOC_FREE(frame);
8432 0 : return false;
8433 : }
8434 :
8435 4 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
8436 4 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
8437 :
8438 4 : status = torture_setup_unix_extensions(cli2);
8439 4 : if (!NT_STATUS_IS_OK(status)) {
8440 0 : goto out;
8441 : }
8442 :
8443 4 : cli_setatr(cli1, fname, 0, 0);
8444 4 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8445 :
8446 : /* Create the file. */
8447 4 : status = cli_ntcreate(cli1,
8448 : fname,
8449 : 0,
8450 : READ_CONTROL_ACCESS,
8451 : 0,
8452 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8453 : FILE_CREATE,
8454 : 0x0,
8455 : 0x0,
8456 : &fnum1,
8457 : NULL);
8458 :
8459 4 : if (!NT_STATUS_IS_OK(status)) {
8460 0 : printf("cli_ntcreate of %s failed (%s)\n",
8461 : fname,
8462 : nt_errstr(status));
8463 0 : goto out;
8464 : }
8465 :
8466 4 : status = cli_close(cli1, fnum1);
8467 4 : if (!NT_STATUS_IS_OK(status)) {
8468 0 : printf("cli_close of %s failed (%s)\n",
8469 : fname,
8470 : nt_errstr(status));
8471 0 : goto out;
8472 : }
8473 4 : fnum1 = (uint16_t)-1;
8474 :
8475 : /* Now create the stream. */
8476 4 : status = cli_ntcreate(cli1,
8477 : stream_fname,
8478 : 0,
8479 : FILE_WRITE_DATA,
8480 : 0,
8481 : FILE_SHARE_READ|FILE_SHARE_WRITE,
8482 : FILE_CREATE,
8483 : 0x0,
8484 : 0x0,
8485 : &fnum1,
8486 : NULL);
8487 :
8488 4 : if (!NT_STATUS_IS_OK(status)) {
8489 0 : printf("cli_ntcreate of %s failed (%s)\n",
8490 : stream_fname,
8491 : nt_errstr(status));
8492 0 : goto out;
8493 : }
8494 :
8495 : /* Leave the stream handle open... */
8496 :
8497 : /* POSIX unlink should fail. */
8498 4 : status = cli_posix_unlink(cli2, fname);
8499 4 : if (NT_STATUS_IS_OK(status)) {
8500 0 : printf("cli_posix_unlink of %s succeeded, should have failed\n",
8501 : fname);
8502 0 : goto out;
8503 : }
8504 :
8505 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8506 0 : printf("cli_posix_unlink of %s failed with (%s) "
8507 : "should have been NT_STATUS_SHARING_VIOLATION\n",
8508 : fname,
8509 : nt_errstr(status));
8510 0 : goto out;
8511 : }
8512 :
8513 : /* Close the stream handle. */
8514 4 : status = cli_close(cli1, fnum1);
8515 4 : if (!NT_STATUS_IS_OK(status)) {
8516 0 : printf("cli_close of %s failed (%s)\n",
8517 : stream_fname,
8518 : nt_errstr(status));
8519 0 : goto out;
8520 : }
8521 4 : fnum1 = (uint16_t)-1;
8522 :
8523 : /* POSIX unlink after stream handle closed should succeed. */
8524 4 : status = cli_posix_unlink(cli2, fname);
8525 4 : if (!NT_STATUS_IS_OK(status)) {
8526 0 : printf("cli_posix_unlink of %s failed (%s)\n",
8527 : fname,
8528 : nt_errstr(status));
8529 0 : goto out;
8530 : }
8531 :
8532 4 : printf("POSIX stream delete test passed\n");
8533 4 : correct = true;
8534 :
8535 4 : out:
8536 :
8537 4 : if (fnum1 != (uint16_t)-1) {
8538 0 : cli_close(cli1, fnum1);
8539 0 : fnum1 = (uint16_t)-1;
8540 : }
8541 :
8542 4 : cli_setatr(cli1, fname, 0, 0);
8543 4 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8544 :
8545 4 : if (!torture_close_connection(cli1)) {
8546 0 : correct = false;
8547 : }
8548 4 : if (!torture_close_connection(cli2)) {
8549 0 : correct = false;
8550 : }
8551 :
8552 4 : TALLOC_FREE(frame);
8553 4 : return correct;
8554 : }
8555 :
8556 : /*
8557 : Test setting EA's are rejected on symlinks.
8558 : */
8559 4 : static bool run_ea_symlink_test(int dummy)
8560 : {
8561 0 : static struct cli_state *cli;
8562 4 : const char *fname = "posix_file_ea";
8563 4 : const char *sname = "posix_symlink_ea";
8564 4 : const char *ea_name = "testea_name";
8565 4 : const char *ea_value = "testea_value";
8566 4 : uint16_t fnum = (uint16_t)-1;
8567 4 : bool correct = false;
8568 0 : NTSTATUS status;
8569 0 : size_t i, num_eas;
8570 4 : struct ea_struct *eas = NULL;
8571 4 : TALLOC_CTX *frame = NULL;
8572 :
8573 4 : frame = talloc_stackframe();
8574 :
8575 4 : printf("Starting EA symlink test\n");
8576 :
8577 4 : if (!torture_open_connection(&cli, 0)) {
8578 0 : TALLOC_FREE(frame);
8579 0 : return false;
8580 : }
8581 :
8582 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
8583 :
8584 4 : status = torture_setup_unix_extensions(cli);
8585 4 : if (!NT_STATUS_IS_OK(status)) {
8586 0 : TALLOC_FREE(frame);
8587 0 : return false;
8588 : }
8589 :
8590 4 : cli_setatr(cli, fname, 0, 0);
8591 4 : cli_posix_unlink(cli, fname);
8592 4 : cli_setatr(cli, sname, 0, 0);
8593 4 : cli_posix_unlink(cli, sname);
8594 :
8595 4 : status = cli_ntcreate(cli,
8596 : fname,
8597 : 0,
8598 : READ_CONTROL_ACCESS,
8599 : 0,
8600 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8601 : FILE_CREATE,
8602 : 0x0,
8603 : 0x0,
8604 : &fnum,
8605 : NULL);
8606 :
8607 4 : if (!NT_STATUS_IS_OK(status)) {
8608 0 : printf("cli_ntcreate of %s failed (%s)\n",
8609 : fname,
8610 : nt_errstr(status));
8611 0 : goto out;
8612 : }
8613 :
8614 4 : status = cli_close(cli, fnum);
8615 4 : if (!NT_STATUS_IS_OK(status)) {
8616 0 : printf("close failed (%s)\n",
8617 : nt_errstr(status));
8618 0 : goto out;
8619 : }
8620 4 : fnum = (uint16_t)-1;
8621 :
8622 : /* Set an EA on the path. */
8623 4 : status = cli_set_ea_path(cli,
8624 : fname,
8625 : ea_name,
8626 : ea_value,
8627 4 : strlen(ea_value)+1);
8628 :
8629 4 : if (!NT_STATUS_IS_OK(status)) {
8630 0 : printf("cli_set_ea_path failed (%s)\n",
8631 : nt_errstr(status));
8632 0 : goto out;
8633 : }
8634 :
8635 : /* Now create a symlink. */
8636 4 : status = cli_posix_symlink(cli, fname, sname);
8637 4 : if (!NT_STATUS_IS_OK(status)) {
8638 0 : printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8639 : sname,
8640 : fname,
8641 : nt_errstr(status));
8642 0 : goto out;
8643 : }
8644 :
8645 : /* Get the EA list on the path. Should return value set. */
8646 4 : status = cli_get_ea_list_path(cli,
8647 : fname,
8648 : frame,
8649 : &num_eas,
8650 : &eas);
8651 :
8652 4 : if (!NT_STATUS_IS_OK(status)) {
8653 0 : printf("cli_get_ea_list_path failed (%s)\n",
8654 : nt_errstr(status));
8655 0 : goto out;
8656 : }
8657 :
8658 : /* Ensure the EA we set is there. */
8659 4 : for (i=0; i<num_eas; i++) {
8660 4 : if (strcmp(eas[i].name, ea_name) == 0 &&
8661 4 : eas[i].value.length == strlen(ea_value)+1 &&
8662 4 : memcmp(eas[i].value.data,
8663 : ea_value,
8664 4 : eas[i].value.length) == 0) {
8665 4 : break;
8666 : }
8667 : }
8668 :
8669 4 : if (i == num_eas) {
8670 0 : printf("Didn't find EA on pathname %s\n",
8671 : fname);
8672 0 : goto out;
8673 : }
8674 :
8675 4 : num_eas = 0;
8676 4 : TALLOC_FREE(eas);
8677 :
8678 : /* Get the EA list on the symlink. Should return empty list. */
8679 4 : status = cli_get_ea_list_path(cli,
8680 : sname,
8681 : frame,
8682 : &num_eas,
8683 : &eas);
8684 :
8685 4 : if (!NT_STATUS_IS_OK(status)) {
8686 0 : printf("cli_get_ea_list_path failed (%s)\n",
8687 : nt_errstr(status));
8688 0 : goto out;
8689 : }
8690 :
8691 4 : if (num_eas != 0) {
8692 0 : printf("cli_get_ea_list_path failed (%s)\n",
8693 : nt_errstr(status));
8694 0 : goto out;
8695 : }
8696 :
8697 : /* Set an EA on the symlink. Should fail. */
8698 4 : status = cli_set_ea_path(cli,
8699 : sname,
8700 : ea_name,
8701 : ea_value,
8702 4 : strlen(ea_value)+1);
8703 :
8704 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8705 0 : printf("cli_set_ea_path on a symlink gave %s. "
8706 : "Should be NT_STATUS_ACCESS_DENIED.\n",
8707 : nt_errstr(status));
8708 0 : goto out;
8709 : }
8710 :
8711 4 : printf("EA symlink test passed\n");
8712 4 : correct = true;
8713 :
8714 4 : out:
8715 :
8716 4 : if (fnum != (uint16_t)-1) {
8717 0 : cli_close(cli, fnum);
8718 0 : fnum = (uint16_t)-1;
8719 : }
8720 :
8721 4 : cli_setatr(cli, sname, 0, 0);
8722 4 : cli_posix_unlink(cli, sname);
8723 4 : cli_setatr(cli, fname, 0, 0);
8724 4 : cli_posix_unlink(cli, fname);
8725 :
8726 4 : if (!torture_close_connection(cli)) {
8727 0 : correct = false;
8728 : }
8729 :
8730 4 : TALLOC_FREE(frame);
8731 4 : return correct;
8732 : }
8733 :
8734 : /*
8735 : Test POSIX locks are OFD-locks.
8736 : */
8737 4 : static bool run_posix_ofd_lock_test(int dummy)
8738 : {
8739 0 : static struct cli_state *cli;
8740 4 : const char *fname = "posix_file";
8741 4 : uint16_t fnum1 = (uint16_t)-1;
8742 4 : uint16_t fnum2 = (uint16_t)-1;
8743 4 : bool correct = false;
8744 0 : NTSTATUS status;
8745 4 : TALLOC_CTX *frame = NULL;
8746 :
8747 4 : frame = talloc_stackframe();
8748 :
8749 4 : printf("Starting POSIX ofd-lock test\n");
8750 :
8751 4 : if (!torture_open_connection(&cli, 0)) {
8752 0 : TALLOC_FREE(frame);
8753 0 : return false;
8754 : }
8755 :
8756 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
8757 :
8758 4 : status = torture_setup_unix_extensions(cli);
8759 4 : if (!NT_STATUS_IS_OK(status)) {
8760 0 : TALLOC_FREE(frame);
8761 0 : return false;
8762 : }
8763 :
8764 4 : cli_setatr(cli, fname, 0, 0);
8765 4 : cli_posix_unlink(cli, fname);
8766 :
8767 : /* Open the file twice. */
8768 4 : status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8769 : 0600, &fnum1);
8770 4 : if (!NT_STATUS_IS_OK(status)) {
8771 0 : printf("First POSIX open of %s failed\n", fname);
8772 0 : goto out;
8773 : }
8774 :
8775 4 : status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8776 4 : if (!NT_STATUS_IS_OK(status)) {
8777 0 : printf("First POSIX open of %s failed\n", fname);
8778 0 : goto out;
8779 : }
8780 :
8781 : /* Set a 0-50 lock on fnum1. */
8782 4 : status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8783 4 : if (!NT_STATUS_IS_OK(status)) {
8784 0 : printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8785 0 : goto out;
8786 : }
8787 :
8788 : /* Set a 60-100 lock on fnum2. */
8789 4 : status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8790 4 : if (!NT_STATUS_IS_OK(status)) {
8791 0 : printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8792 0 : goto out;
8793 : }
8794 :
8795 : /* close fnum1 - 0-50 lock should go away. */
8796 4 : status = cli_close(cli, fnum1);
8797 4 : if (!NT_STATUS_IS_OK(status)) {
8798 0 : printf("close failed (%s)\n",
8799 : nt_errstr(status));
8800 0 : goto out;
8801 : }
8802 4 : fnum1 = (uint16_t)-1;
8803 :
8804 : /* Change the lock context. */
8805 4 : cli_setpid(cli, cli_getpid(cli) + 1);
8806 :
8807 : /* Re-open fnum1. */
8808 4 : status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8809 4 : if (!NT_STATUS_IS_OK(status)) {
8810 0 : printf("Third POSIX open of %s failed\n", fname);
8811 0 : goto out;
8812 : }
8813 :
8814 : /* 60-100 lock should still be there. */
8815 4 : status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8816 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8817 0 : printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8818 0 : goto out;
8819 : }
8820 :
8821 : /* 0-50 lock should be gone. */
8822 4 : status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8823 4 : if (!NT_STATUS_IS_OK(status)) {
8824 0 : printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8825 0 : goto out;
8826 : }
8827 :
8828 4 : printf("POSIX OFD lock test passed\n");
8829 4 : correct = true;
8830 :
8831 4 : out:
8832 :
8833 4 : if (fnum1 != (uint16_t)-1) {
8834 4 : cli_close(cli, fnum1);
8835 4 : fnum1 = (uint16_t)-1;
8836 : }
8837 4 : if (fnum2 != (uint16_t)-1) {
8838 4 : cli_close(cli, fnum2);
8839 4 : fnum2 = (uint16_t)-1;
8840 : }
8841 :
8842 4 : cli_setatr(cli, fname, 0, 0);
8843 4 : cli_posix_unlink(cli, fname);
8844 :
8845 4 : if (!torture_close_connection(cli)) {
8846 0 : correct = false;
8847 : }
8848 :
8849 4 : TALLOC_FREE(frame);
8850 4 : return correct;
8851 : }
8852 :
8853 : struct posix_blocking_state {
8854 : struct tevent_context *ev;
8855 : struct cli_state *cli1;
8856 : uint16_t fnum1;
8857 : struct cli_state *cli2;
8858 : uint16_t fnum2;
8859 : bool gotblocked;
8860 : bool gotecho;
8861 : };
8862 :
8863 : static void posix_blocking_locked(struct tevent_req *subreq);
8864 : static void posix_blocking_gotblocked(struct tevent_req *subreq);
8865 : static void posix_blocking_gotecho(struct tevent_req *subreq);
8866 : static void posix_blocking_unlocked(struct tevent_req *subreq);
8867 :
8868 4 : static struct tevent_req *posix_blocking_send(
8869 : TALLOC_CTX *mem_ctx,
8870 : struct tevent_context *ev,
8871 : struct cli_state *cli1,
8872 : uint16_t fnum1,
8873 : struct cli_state *cli2,
8874 : uint16_t fnum2)
8875 : {
8876 4 : struct tevent_req *req = NULL, *subreq = NULL;
8877 4 : struct posix_blocking_state *state = NULL;
8878 :
8879 4 : req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8880 4 : if (req == NULL) {
8881 0 : return NULL;
8882 : }
8883 4 : state->ev = ev;
8884 4 : state->cli1 = cli1;
8885 4 : state->fnum1 = fnum1;
8886 4 : state->cli2 = cli2;
8887 4 : state->fnum2 = fnum2;
8888 :
8889 4 : subreq = cli_posix_lock_send(
8890 : state,
8891 4 : state->ev,
8892 4 : state->cli1,
8893 4 : state->fnum1,
8894 : 0,
8895 : 1,
8896 : false,
8897 : WRITE_LOCK);
8898 4 : if (tevent_req_nomem(subreq, req)) {
8899 0 : return tevent_req_post(req, ev);
8900 : }
8901 4 : tevent_req_set_callback(subreq, posix_blocking_locked, req);
8902 4 : return req;
8903 : }
8904 :
8905 4 : static void posix_blocking_locked(struct tevent_req *subreq)
8906 : {
8907 4 : struct tevent_req *req = tevent_req_callback_data(
8908 : subreq, struct tevent_req);
8909 4 : struct posix_blocking_state *state = tevent_req_data(
8910 : req, struct posix_blocking_state);
8911 0 : NTSTATUS status;
8912 :
8913 4 : status = cli_posix_lock_recv(subreq);
8914 4 : TALLOC_FREE(subreq);
8915 4 : if (tevent_req_nterror(req, status)) {
8916 0 : return;
8917 : }
8918 :
8919 4 : subreq = cli_posix_lock_send(
8920 : state,
8921 : state->ev,
8922 : state->cli2,
8923 4 : state->fnum2,
8924 : 0,
8925 : 1,
8926 : true,
8927 : WRITE_LOCK);
8928 4 : if (tevent_req_nomem(subreq, req)) {
8929 0 : return;
8930 : }
8931 4 : tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8932 :
8933 : /* Make sure the blocking request is delivered */
8934 4 : subreq = cli_echo_send(
8935 : state,
8936 : state->ev,
8937 : state->cli2,
8938 : 1,
8939 4 : (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8940 4 : if (tevent_req_nomem(subreq, req)) {
8941 0 : return;
8942 : }
8943 4 : tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8944 : }
8945 :
8946 4 : static void posix_blocking_gotblocked(struct tevent_req *subreq)
8947 : {
8948 4 : struct tevent_req *req = tevent_req_callback_data(
8949 : subreq, struct tevent_req);
8950 4 : struct posix_blocking_state *state = tevent_req_data(
8951 : req, struct posix_blocking_state);
8952 0 : NTSTATUS status;
8953 :
8954 4 : status = cli_posix_lock_recv(subreq);
8955 4 : TALLOC_FREE(subreq);
8956 4 : if (tevent_req_nterror(req, status)) {
8957 0 : return;
8958 : }
8959 4 : if (!state->gotecho) {
8960 0 : printf("blocked req got through before echo\n");
8961 0 : tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8962 0 : return;
8963 : }
8964 4 : tevent_req_done(req);
8965 : }
8966 :
8967 4 : static void posix_blocking_gotecho(struct tevent_req *subreq)
8968 : {
8969 4 : struct tevent_req *req = tevent_req_callback_data(
8970 : subreq, struct tevent_req);
8971 4 : struct posix_blocking_state *state = tevent_req_data(
8972 : req, struct posix_blocking_state);
8973 0 : NTSTATUS status;
8974 :
8975 4 : status = cli_echo_recv(subreq);
8976 4 : TALLOC_FREE(subreq);
8977 4 : if (tevent_req_nterror(req, status)) {
8978 0 : return;
8979 : }
8980 4 : if (state->gotblocked) {
8981 0 : printf("blocked req got through before echo\n");
8982 0 : tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8983 0 : return;
8984 : }
8985 4 : state->gotecho = true;
8986 :
8987 4 : subreq = cli_posix_lock_send(
8988 : state,
8989 : state->ev,
8990 : state->cli1,
8991 4 : state->fnum1,
8992 : 0,
8993 : 1,
8994 : false,
8995 : UNLOCK_LOCK);
8996 4 : if (tevent_req_nomem(subreq, req)) {
8997 0 : return;
8998 : }
8999 4 : tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
9000 : }
9001 :
9002 4 : static void posix_blocking_unlocked(struct tevent_req *subreq)
9003 : {
9004 4 : struct tevent_req *req = tevent_req_callback_data(
9005 : subreq, struct tevent_req);
9006 0 : NTSTATUS status;
9007 :
9008 4 : status = cli_posix_lock_recv(subreq);
9009 4 : TALLOC_FREE(subreq);
9010 4 : if (tevent_req_nterror(req, status)) {
9011 0 : return;
9012 : }
9013 : /* tevent_req_done in posix_blocking_gotlocked */
9014 : }
9015 :
9016 4 : static NTSTATUS posix_blocking_recv(struct tevent_req *req)
9017 : {
9018 4 : return tevent_req_simple_recv_ntstatus(req);
9019 : }
9020 :
9021 4 : static bool run_posix_blocking_lock(int dummy)
9022 : {
9023 4 : struct tevent_context *ev = NULL;
9024 4 : struct cli_state *cli1 = NULL, *cli2 = NULL;
9025 4 : const char *fname = "posix_blocking";
9026 4 : uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
9027 4 : struct tevent_req *req = NULL;
9028 0 : NTSTATUS status;
9029 4 : bool ret = false;
9030 0 : bool ok;
9031 :
9032 4 : printf("Starting posix blocking lock test\n");
9033 :
9034 4 : ev = samba_tevent_context_init(NULL);
9035 4 : if (ev == NULL) {
9036 0 : return false;
9037 : }
9038 :
9039 4 : ok = torture_open_connection(&cli1, 0);
9040 4 : if (!ok) {
9041 0 : goto fail;
9042 : }
9043 4 : ok = torture_open_connection(&cli2, 0);
9044 4 : if (!ok) {
9045 0 : goto fail;
9046 : }
9047 :
9048 4 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
9049 :
9050 4 : status = torture_setup_unix_extensions(cli1);
9051 4 : if (!NT_STATUS_IS_OK(status)) {
9052 0 : return false;
9053 : }
9054 :
9055 4 : status = torture_setup_unix_extensions(cli2);
9056 4 : if (!NT_STATUS_IS_OK(status)) {
9057 0 : return false;
9058 : }
9059 :
9060 4 : cli_setatr(cli1, fname, 0, 0);
9061 4 : cli_posix_unlink(cli1, fname);
9062 :
9063 4 : status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
9064 : 0600, &fnum1);
9065 4 : if (!NT_STATUS_IS_OK(status)) {
9066 0 : printf("First POSIX open of %s failed: %s\n",
9067 : fname,
9068 : nt_errstr(status));
9069 0 : goto fail;
9070 : }
9071 :
9072 4 : status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
9073 4 : if (!NT_STATUS_IS_OK(status)) {
9074 0 : printf("Second POSIX open of %s failed: %s\n",
9075 : fname,
9076 : nt_errstr(status));
9077 0 : goto fail;
9078 : }
9079 :
9080 4 : req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9081 4 : if (req == NULL) {
9082 0 : printf("cli_posix_blocking failed\n");
9083 0 : goto fail;
9084 : }
9085 :
9086 4 : ok = tevent_req_poll_ntstatus(req, ev, &status);
9087 4 : if (!ok) {
9088 0 : printf("tevent_req_poll_ntstatus failed: %s\n",
9089 : nt_errstr(status));
9090 0 : goto fail;
9091 : }
9092 4 : status = posix_blocking_recv(req);
9093 4 : TALLOC_FREE(req);
9094 4 : if (!NT_STATUS_IS_OK(status)) {
9095 0 : printf("posix_blocking_recv returned %s\n",
9096 : nt_errstr(status));
9097 0 : goto fail;
9098 : }
9099 :
9100 4 : ret = true;
9101 4 : fail:
9102 :
9103 4 : if (fnum1 != UINT16_MAX) {
9104 4 : cli_close(cli1, fnum1);
9105 4 : fnum1 = UINT16_MAX;
9106 : }
9107 4 : if (fnum2 != UINT16_MAX) {
9108 4 : cli_close(cli2, fnum2);
9109 4 : fnum2 = UINT16_MAX;
9110 : }
9111 :
9112 4 : if (cli1 != NULL) {
9113 4 : cli_setatr(cli1, fname, 0, 0);
9114 4 : cli_posix_unlink(cli1, fname);
9115 : }
9116 :
9117 4 : ok = true;
9118 :
9119 4 : if (cli1 != NULL) {
9120 4 : ok &= torture_close_connection(cli1);
9121 4 : cli1 = NULL;
9122 : }
9123 4 : if (cli2 != NULL) {
9124 4 : ok &= torture_close_connection(cli2);
9125 4 : cli2 = NULL;
9126 : }
9127 :
9128 4 : if (!ok) {
9129 0 : ret = false;
9130 : }
9131 4 : TALLOC_FREE(ev);
9132 4 : return ret;
9133 : }
9134 :
9135 : /*
9136 : Test POSIX mkdir is case-sensitive.
9137 : */
9138 4 : static bool run_posix_mkdir_test(int dummy)
9139 : {
9140 0 : static struct cli_state *cli;
9141 4 : const char *fname_foo = "POSIX_foo";
9142 4 : const char *fname_foo_Foo = "POSIX_foo/Foo";
9143 4 : const char *fname_foo_foo = "POSIX_foo/foo";
9144 4 : const char *fname_Foo = "POSIX_Foo";
9145 4 : const char *fname_Foo_Foo = "POSIX_Foo/Foo";
9146 4 : const char *fname_Foo_foo = "POSIX_Foo/foo";
9147 4 : bool correct = false;
9148 0 : NTSTATUS status;
9149 4 : TALLOC_CTX *frame = NULL;
9150 4 : uint16_t fnum = (uint16_t)-1;
9151 :
9152 4 : frame = talloc_stackframe();
9153 :
9154 4 : printf("Starting POSIX mkdir test\n");
9155 :
9156 4 : if (!torture_open_connection(&cli, 0)) {
9157 0 : TALLOC_FREE(frame);
9158 0 : return false;
9159 : }
9160 :
9161 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
9162 :
9163 4 : status = torture_setup_unix_extensions(cli);
9164 4 : if (!NT_STATUS_IS_OK(status)) {
9165 0 : TALLOC_FREE(frame);
9166 0 : return false;
9167 : }
9168 :
9169 4 : cli_posix_rmdir(cli, fname_foo_foo);
9170 4 : cli_posix_rmdir(cli, fname_foo_Foo);
9171 4 : cli_posix_rmdir(cli, fname_foo);
9172 :
9173 4 : cli_posix_rmdir(cli, fname_Foo_foo);
9174 4 : cli_posix_rmdir(cli, fname_Foo_Foo);
9175 4 : cli_posix_rmdir(cli, fname_Foo);
9176 :
9177 : /*
9178 : * Create a file POSIX_foo then try
9179 : * and use it in a directory path by
9180 : * doing mkdir POSIX_foo/bar.
9181 : * The mkdir should fail with
9182 : * NT_STATUS_OBJECT_PATH_NOT_FOUND
9183 : */
9184 :
9185 4 : status = cli_posix_open(cli,
9186 : fname_foo,
9187 : O_RDWR|O_CREAT,
9188 : 0666,
9189 : &fnum);
9190 4 : if (!NT_STATUS_IS_OK(status)) {
9191 0 : printf("cli_posix_open of %s failed error %s\n",
9192 : fname_foo,
9193 : nt_errstr(status));
9194 0 : goto out;
9195 : }
9196 :
9197 4 : status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9198 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9199 0 : printf("cli_posix_mkdir of %s should fail with "
9200 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9201 : "%s instead\n",
9202 : fname_foo_foo,
9203 : nt_errstr(status));
9204 0 : goto out;
9205 : }
9206 :
9207 4 : status = cli_close(cli, fnum);
9208 4 : if (!NT_STATUS_IS_OK(status)) {
9209 0 : printf("cli_close failed %s\n", nt_errstr(status));
9210 0 : goto out;
9211 : }
9212 4 : fnum = (uint16_t)-1;
9213 :
9214 4 : status = cli_posix_unlink(cli, fname_foo);
9215 4 : if (!NT_STATUS_IS_OK(status)) {
9216 0 : printf("cli_posix_unlink of %s failed error %s\n",
9217 : fname_foo,
9218 : nt_errstr(status));
9219 0 : goto out;
9220 : }
9221 :
9222 : /*
9223 : * Now we've deleted everything, posix_mkdir, posix_rmdir,
9224 : * posix_open, posix_unlink, on
9225 : * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9226 : * not silently create POSIX_foo/foo.
9227 : */
9228 :
9229 4 : status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9230 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9231 0 : printf("cli_posix_mkdir of %s should fail with "
9232 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9233 : "%s instead\n",
9234 : fname_foo_foo,
9235 : nt_errstr(status));
9236 0 : goto out;
9237 : }
9238 :
9239 4 : status = cli_posix_rmdir(cli, fname_foo_foo);
9240 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9241 0 : printf("cli_posix_rmdir of %s should fail with "
9242 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9243 : "%s instead\n",
9244 : fname_foo_foo,
9245 : nt_errstr(status));
9246 0 : goto out;
9247 : }
9248 :
9249 4 : status = cli_posix_open(cli,
9250 : fname_foo_foo,
9251 : O_RDWR|O_CREAT,
9252 : 0666,
9253 : &fnum);
9254 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9255 0 : printf("cli_posix_open of %s should fail with "
9256 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9257 : "%s instead\n",
9258 : fname_foo_foo,
9259 : nt_errstr(status));
9260 0 : goto out;
9261 : }
9262 :
9263 4 : status = cli_posix_unlink(cli, fname_foo_foo);
9264 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9265 0 : printf("cli_posix_unlink of %s should fail with "
9266 : "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9267 : "%s instead\n",
9268 : fname_foo_foo,
9269 : nt_errstr(status));
9270 0 : goto out;
9271 : }
9272 :
9273 4 : status = cli_posix_mkdir(cli, fname_foo, 0777);
9274 4 : if (!NT_STATUS_IS_OK(status)) {
9275 0 : printf("cli_posix_mkdir of %s failed\n", fname_foo);
9276 0 : goto out;
9277 : }
9278 :
9279 4 : status = cli_posix_mkdir(cli, fname_Foo, 0777);
9280 4 : if (!NT_STATUS_IS_OK(status)) {
9281 0 : printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9282 0 : goto out;
9283 : }
9284 :
9285 4 : status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9286 4 : if (!NT_STATUS_IS_OK(status)) {
9287 0 : printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9288 0 : goto out;
9289 : }
9290 :
9291 4 : status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9292 4 : if (!NT_STATUS_IS_OK(status)) {
9293 0 : printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9294 0 : goto out;
9295 : }
9296 :
9297 4 : status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9298 4 : if (!NT_STATUS_IS_OK(status)) {
9299 0 : printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9300 0 : goto out;
9301 : }
9302 :
9303 4 : status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9304 4 : if (!NT_STATUS_IS_OK(status)) {
9305 0 : printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9306 0 : goto out;
9307 : }
9308 :
9309 4 : printf("POSIX mkdir test passed\n");
9310 4 : correct = true;
9311 :
9312 4 : out:
9313 :
9314 4 : if (fnum != (uint16_t)-1) {
9315 0 : cli_close(cli, fnum);
9316 0 : fnum = (uint16_t)-1;
9317 : }
9318 :
9319 4 : cli_posix_rmdir(cli, fname_foo_foo);
9320 4 : cli_posix_rmdir(cli, fname_foo_Foo);
9321 4 : cli_posix_rmdir(cli, fname_foo);
9322 :
9323 4 : cli_posix_rmdir(cli, fname_Foo_foo);
9324 4 : cli_posix_rmdir(cli, fname_Foo_Foo);
9325 4 : cli_posix_rmdir(cli, fname_Foo);
9326 :
9327 4 : if (!torture_close_connection(cli)) {
9328 0 : correct = false;
9329 : }
9330 :
9331 4 : TALLOC_FREE(frame);
9332 4 : return correct;
9333 : }
9334 :
9335 : struct posix_acl_oplock_state {
9336 : struct tevent_context *ev;
9337 : struct cli_state *cli;
9338 : bool *got_break;
9339 : bool *acl_ret;
9340 : NTSTATUS status;
9341 : };
9342 :
9343 4 : static void posix_acl_oplock_got_break(struct tevent_req *req)
9344 : {
9345 4 : struct posix_acl_oplock_state *state = tevent_req_callback_data(
9346 : req, struct posix_acl_oplock_state);
9347 0 : uint16_t fnum;
9348 0 : uint8_t level;
9349 0 : NTSTATUS status;
9350 :
9351 4 : status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9352 4 : TALLOC_FREE(req);
9353 4 : if (!NT_STATUS_IS_OK(status)) {
9354 0 : printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9355 : nt_errstr(status));
9356 0 : return;
9357 : }
9358 4 : *state->got_break = true;
9359 :
9360 4 : req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9361 : NO_OPLOCK);
9362 4 : if (req == NULL) {
9363 0 : printf("cli_oplock_ack_send failed\n");
9364 0 : return;
9365 : }
9366 : }
9367 :
9368 4 : static void posix_acl_oplock_got_acl(struct tevent_req *req)
9369 : {
9370 4 : struct posix_acl_oplock_state *state = tevent_req_callback_data(
9371 : req, struct posix_acl_oplock_state);
9372 4 : size_t ret_size = 0;
9373 4 : char *ret_data = NULL;
9374 :
9375 4 : state->status = cli_posix_getacl_recv(req,
9376 : state,
9377 : &ret_size,
9378 : &ret_data);
9379 :
9380 4 : if (!NT_STATUS_IS_OK(state->status)) {
9381 0 : printf("cli_posix_getacl_recv returned %s\n",
9382 : nt_errstr(state->status));
9383 : }
9384 4 : *state->acl_ret = true;
9385 4 : }
9386 :
9387 4 : static bool run_posix_acl_oplock_test(int dummy)
9388 : {
9389 0 : struct tevent_context *ev;
9390 0 : struct cli_state *cli1, *cli2;
9391 0 : struct tevent_req *oplock_req, *getacl_req;
9392 4 : const char *fname = "posix_acl_oplock";
9393 0 : uint16_t fnum;
9394 4 : int saved_use_oplocks = use_oplocks;
9395 0 : NTSTATUS status;
9396 4 : bool correct = true;
9397 4 : bool got_break = false;
9398 4 : bool acl_ret = false;
9399 :
9400 0 : struct posix_acl_oplock_state *state;
9401 :
9402 4 : printf("starting posix_acl_oplock test\n");
9403 :
9404 4 : if (!torture_open_connection(&cli1, 0)) {
9405 0 : use_level_II_oplocks = false;
9406 0 : use_oplocks = saved_use_oplocks;
9407 0 : return false;
9408 : }
9409 :
9410 4 : if (!torture_open_connection(&cli2, 1)) {
9411 0 : use_level_II_oplocks = false;
9412 0 : use_oplocks = saved_use_oplocks;
9413 0 : return false;
9414 : }
9415 :
9416 : /* Setup posix on cli2 only. */
9417 4 : status = torture_setup_unix_extensions(cli2);
9418 4 : if (!NT_STATUS_IS_OK(status)) {
9419 0 : return false;
9420 : }
9421 :
9422 4 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
9423 4 : smbXcli_conn_set_sockopt(cli2->conn, sockops);
9424 :
9425 4 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9426 :
9427 : /* Create the file on the Windows connection. */
9428 4 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9429 : &fnum);
9430 4 : if (!NT_STATUS_IS_OK(status)) {
9431 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9432 0 : return false;
9433 : }
9434 :
9435 4 : status = cli_close(cli1, fnum);
9436 4 : if (!NT_STATUS_IS_OK(status)) {
9437 0 : printf("close1 failed (%s)\n", nt_errstr(status));
9438 0 : return false;
9439 : }
9440 :
9441 4 : cli1->use_oplocks = true;
9442 :
9443 : /* Open with oplock. */
9444 4 : status = cli_ntcreate(cli1,
9445 : fname,
9446 : 0,
9447 : FILE_READ_DATA,
9448 : FILE_ATTRIBUTE_NORMAL,
9449 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9450 : FILE_OPEN,
9451 : 0,
9452 : 0,
9453 : &fnum,
9454 : NULL);
9455 :
9456 4 : if (!NT_STATUS_IS_OK(status)) {
9457 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9458 0 : return false;
9459 : }
9460 :
9461 4 : ev = samba_tevent_context_init(talloc_tos());
9462 4 : if (ev == NULL) {
9463 0 : printf("tevent_context_init failed\n");
9464 0 : return false;
9465 : }
9466 :
9467 4 : state = talloc_zero(ev, struct posix_acl_oplock_state);
9468 4 : if (state == NULL) {
9469 0 : printf("talloc failed\n");
9470 0 : return false;
9471 : }
9472 4 : state->ev = ev;
9473 4 : state->cli = cli1;
9474 4 : state->got_break = &got_break;
9475 4 : state->acl_ret = &acl_ret;
9476 :
9477 4 : oplock_req = cli_smb_oplock_break_waiter_send(
9478 : talloc_tos(), ev, cli1);
9479 4 : if (oplock_req == NULL) {
9480 0 : printf("cli_smb_oplock_break_waiter_send failed\n");
9481 0 : return false;
9482 : }
9483 4 : tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9484 :
9485 : /* Get ACL on POSIX connection - should break oplock. */
9486 4 : getacl_req = cli_posix_getacl_send(talloc_tos(),
9487 : ev,
9488 : cli2,
9489 : fname);
9490 4 : if (getacl_req == NULL) {
9491 0 : printf("cli_posix_getacl_send failed\n");
9492 0 : return false;
9493 : }
9494 4 : tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9495 :
9496 36 : while (!got_break || !acl_ret) {
9497 0 : int ret;
9498 32 : ret = tevent_loop_once(ev);
9499 32 : if (ret == -1) {
9500 0 : printf("tevent_loop_once failed: %s\n",
9501 0 : strerror(errno));
9502 0 : return false;
9503 : }
9504 : }
9505 :
9506 4 : if (!NT_STATUS_IS_OK(state->status)) {
9507 0 : printf("getacl failed (%s)\n", nt_errstr(state->status));
9508 0 : correct = false;
9509 : }
9510 :
9511 4 : status = cli_close(cli1, fnum);
9512 4 : if (!NT_STATUS_IS_OK(status)) {
9513 0 : printf("close2 failed (%s)\n", nt_errstr(status));
9514 0 : correct = false;
9515 : }
9516 :
9517 4 : status = cli_unlink(cli1,
9518 : fname,
9519 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9520 4 : if (!NT_STATUS_IS_OK(status)) {
9521 0 : printf("unlink failed (%s)\n", nt_errstr(status));
9522 0 : correct = false;
9523 : }
9524 :
9525 4 : if (!torture_close_connection(cli1)) {
9526 0 : correct = false;
9527 : }
9528 4 : if (!torture_close_connection(cli2)) {
9529 0 : correct = false;
9530 : }
9531 :
9532 4 : if (!got_break) {
9533 0 : correct = false;
9534 : }
9535 :
9536 4 : printf("finished posix acl oplock test\n");
9537 :
9538 4 : return correct;
9539 : }
9540 :
9541 4 : static bool run_posix_acl_shareroot_test(int dummy)
9542 : {
9543 0 : struct cli_state *cli;
9544 0 : NTSTATUS status;
9545 4 : bool correct = false;
9546 4 : char *posix_acl = NULL;
9547 4 : size_t posix_acl_len = 0;
9548 4 : uint16_t num_file_acls = 0;
9549 4 : uint16_t num_dir_acls = 0;
9550 0 : uint16_t i;
9551 4 : uint32_t expected_size = 0;
9552 4 : bool got_user = false;
9553 4 : bool got_group = false;
9554 4 : bool got_other = false;
9555 4 : TALLOC_CTX *frame = NULL;
9556 :
9557 4 : frame = talloc_stackframe();
9558 :
9559 4 : printf("starting posix_acl_shareroot test\n");
9560 :
9561 4 : if (!torture_open_connection(&cli, 0)) {
9562 0 : TALLOC_FREE(frame);
9563 0 : return false;
9564 : }
9565 :
9566 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
9567 :
9568 4 : status = torture_setup_unix_extensions(cli);
9569 4 : if (!NT_STATUS_IS_OK(status)) {
9570 0 : printf("Failed to setup unix extensions\n");
9571 0 : goto out;
9572 : }
9573 :
9574 : /* Get the POSIX ACL on the root of the share. */
9575 4 : status = cli_posix_getacl(cli,
9576 : ".",
9577 : frame,
9578 : &posix_acl_len,
9579 : &posix_acl);
9580 :
9581 4 : if (!NT_STATUS_IS_OK(status)) {
9582 0 : printf("cli_posix_getacl of '.' failed (%s)\n",
9583 : nt_errstr(status));
9584 0 : goto out;
9585 : }
9586 :
9587 4 : if (posix_acl_len < 6 ||
9588 4 : SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9589 0 : printf("getfacl ., unknown POSIX acl version %u.\n",
9590 0 : (unsigned int)CVAL(posix_acl,0) );
9591 0 : goto out;
9592 : }
9593 :
9594 4 : num_file_acls = SVAL(posix_acl,2);
9595 4 : num_dir_acls = SVAL(posix_acl,4);
9596 4 : expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9597 4 : SMB_POSIX_ACL_ENTRY_SIZE*
9598 4 : (num_file_acls+num_dir_acls);
9599 :
9600 4 : if (posix_acl_len != expected_size) {
9601 0 : printf("incorrect POSIX acl buffer size "
9602 : "(should be %u, was %u).\n",
9603 : (unsigned int)expected_size,
9604 : (unsigned int)posix_acl_len);
9605 0 : goto out;
9606 : }
9607 :
9608 : /*
9609 : * We don't need to know what the ACL's are
9610 : * we just need to know we have at least 3
9611 : * file entries (u,g,o).
9612 : */
9613 :
9614 16 : for (i = 0; i < num_file_acls; i++) {
9615 12 : unsigned char tagtype =
9616 12 : CVAL(posix_acl,
9617 : SMB_POSIX_ACL_HEADER_SIZE+
9618 : (i*SMB_POSIX_ACL_ENTRY_SIZE));
9619 :
9620 12 : switch(tagtype) {
9621 4 : case SMB_POSIX_ACL_USER_OBJ:
9622 4 : got_user = true;
9623 4 : break;
9624 4 : case SMB_POSIX_ACL_GROUP_OBJ:
9625 4 : got_group = true;
9626 4 : break;
9627 4 : case SMB_POSIX_ACL_OTHER:
9628 4 : got_other = true;
9629 4 : break;
9630 0 : default:
9631 0 : break;
9632 : }
9633 : }
9634 :
9635 4 : if (!got_user) {
9636 0 : printf("Missing user entry\n");
9637 0 : goto out;
9638 : }
9639 :
9640 4 : if (!got_group) {
9641 0 : printf("Missing group entry\n");
9642 0 : goto out;
9643 : }
9644 :
9645 4 : if (!got_other) {
9646 0 : printf("Missing other entry\n");
9647 0 : goto out;
9648 : }
9649 :
9650 4 : correct = true;
9651 :
9652 4 : out:
9653 :
9654 4 : if (!torture_close_connection(cli)) {
9655 0 : correct = false;
9656 : }
9657 :
9658 4 : printf("finished posix acl shareroot test\n");
9659 4 : TALLOC_FREE(frame);
9660 :
9661 4 : return correct;
9662 : }
9663 :
9664 : static uint32_t open_attrs_table[] = {
9665 : FILE_ATTRIBUTE_NORMAL,
9666 : FILE_ATTRIBUTE_ARCHIVE,
9667 : FILE_ATTRIBUTE_READONLY,
9668 : FILE_ATTRIBUTE_HIDDEN,
9669 : FILE_ATTRIBUTE_SYSTEM,
9670 :
9671 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9672 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9673 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9674 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9675 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9676 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9677 :
9678 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9679 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9680 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9681 : FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9682 : };
9683 :
9684 : struct trunc_open_results {
9685 : unsigned int num;
9686 : uint32_t init_attr;
9687 : uint32_t trunc_attr;
9688 : uint32_t result_attr;
9689 : };
9690 :
9691 : static struct trunc_open_results attr_results[] = {
9692 : { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9693 : { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9694 : { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9695 : { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9696 : { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9697 : { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9698 : { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9699 : { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9700 : { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9701 : { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9702 : { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9703 : { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9704 : { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9705 : { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9706 : { 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 },
9707 : { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9708 : { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9709 : { 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 },
9710 : { 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 },
9711 : { 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 },
9712 : { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9713 : { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9714 : { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9715 : { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9716 : { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9717 : { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9718 : };
9719 :
9720 0 : static bool run_openattrtest(int dummy)
9721 : {
9722 0 : static struct cli_state *cli1;
9723 0 : const char *fname = "\\openattr.file";
9724 0 : uint16_t fnum1;
9725 0 : bool correct = True;
9726 0 : uint32_t attr;
9727 0 : unsigned int i, j, k, l;
9728 0 : NTSTATUS status;
9729 :
9730 0 : printf("starting open attr test\n");
9731 :
9732 0 : if (!torture_open_connection(&cli1, 0)) {
9733 0 : return False;
9734 : }
9735 :
9736 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
9737 :
9738 0 : for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9739 0 : cli_setatr(cli1, fname, 0, 0);
9740 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9741 :
9742 0 : status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9743 : open_attrs_table[i], FILE_SHARE_NONE,
9744 : FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9745 0 : if (!NT_STATUS_IS_OK(status)) {
9746 0 : printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9747 0 : return False;
9748 : }
9749 :
9750 0 : status = cli_close(cli1, fnum1);
9751 0 : if (!NT_STATUS_IS_OK(status)) {
9752 0 : printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9753 0 : return False;
9754 : }
9755 :
9756 0 : for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9757 0 : status = cli_ntcreate(cli1, fname, 0,
9758 : FILE_READ_DATA|FILE_WRITE_DATA,
9759 : open_attrs_table[j],
9760 : FILE_SHARE_NONE, FILE_OVERWRITE,
9761 : 0, 0, &fnum1, NULL);
9762 0 : if (!NT_STATUS_IS_OK(status)) {
9763 0 : for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9764 0 : if (attr_results[l].num == k) {
9765 0 : printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9766 : k, open_attrs_table[i],
9767 : open_attrs_table[j],
9768 : fname, NT_STATUS_V(status), nt_errstr(status));
9769 0 : correct = False;
9770 : }
9771 : }
9772 :
9773 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9774 0 : printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9775 : k, open_attrs_table[i], open_attrs_table[j],
9776 : nt_errstr(status));
9777 0 : correct = False;
9778 : }
9779 : #if 0
9780 : printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9781 : #endif
9782 0 : k++;
9783 0 : continue;
9784 : }
9785 :
9786 0 : status = cli_close(cli1, fnum1);
9787 0 : if (!NT_STATUS_IS_OK(status)) {
9788 0 : printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9789 0 : return False;
9790 : }
9791 :
9792 0 : status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9793 0 : if (!NT_STATUS_IS_OK(status)) {
9794 0 : printf("getatr(2) failed (%s)\n", nt_errstr(status));
9795 0 : return False;
9796 : }
9797 :
9798 : #if 0
9799 : printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9800 : k, open_attrs_table[i], open_attrs_table[j], attr );
9801 : #endif
9802 :
9803 0 : for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9804 0 : if (attr_results[l].num == k) {
9805 0 : if (attr != attr_results[l].result_attr ||
9806 0 : open_attrs_table[i] != attr_results[l].init_attr ||
9807 0 : open_attrs_table[j] != attr_results[l].trunc_attr) {
9808 0 : printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9809 : open_attrs_table[i],
9810 : open_attrs_table[j],
9811 : (unsigned int)attr,
9812 : attr_results[l].result_attr);
9813 0 : correct = False;
9814 : }
9815 0 : break;
9816 : }
9817 : }
9818 0 : k++;
9819 : }
9820 : }
9821 :
9822 0 : cli_setatr(cli1, fname, 0, 0);
9823 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9824 :
9825 0 : printf("open attr test %s.\n", correct ? "passed" : "failed");
9826 :
9827 0 : if (!torture_close_connection(cli1)) {
9828 0 : correct = False;
9829 : }
9830 0 : return correct;
9831 : }
9832 :
9833 0 : static NTSTATUS list_fn(struct file_info *finfo,
9834 : const char *name, void *state)
9835 : {
9836 0 : int *matched = (int *)state;
9837 0 : if (matched != NULL) {
9838 0 : *matched += 1;
9839 : }
9840 0 : return NT_STATUS_OK;
9841 : }
9842 :
9843 : /*
9844 : test directory listing speed
9845 : */
9846 5 : static bool run_dirtest(int dummy)
9847 : {
9848 0 : int i;
9849 0 : static struct cli_state *cli;
9850 0 : uint16_t fnum;
9851 0 : struct timeval core_start;
9852 5 : bool correct = True;
9853 0 : int matched;
9854 :
9855 5 : printf("starting directory test\n");
9856 :
9857 5 : if (!torture_open_connection(&cli, 0)) {
9858 0 : return False;
9859 : }
9860 :
9861 5 : smbXcli_conn_set_sockopt(cli->conn, sockops);
9862 :
9863 5 : srandom(0);
9864 505 : for (i=0;i<torture_numops;i++) {
9865 0 : fstring fname;
9866 500 : slprintf(fname, sizeof(fname), "\\%x", (int)random());
9867 500 : if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9868 0 : fprintf(stderr,"Failed to open %s\n", fname);
9869 0 : return False;
9870 : }
9871 500 : cli_close(cli, fnum);
9872 : }
9873 :
9874 5 : core_start = timeval_current();
9875 :
9876 5 : matched = 0;
9877 5 : cli_list(cli, "a*.*", 0, list_fn, &matched);
9878 5 : printf("Matched %d\n", matched);
9879 :
9880 5 : matched = 0;
9881 5 : cli_list(cli, "b*.*", 0, list_fn, &matched);
9882 5 : printf("Matched %d\n", matched);
9883 :
9884 5 : matched = 0;
9885 5 : cli_list(cli, "xyzabc", 0, list_fn, &matched);
9886 5 : printf("Matched %d\n", matched);
9887 :
9888 5 : printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9889 :
9890 5 : srandom(0);
9891 505 : for (i=0;i<torture_numops;i++) {
9892 0 : fstring fname;
9893 500 : slprintf(fname, sizeof(fname), "\\%x", (int)random());
9894 500 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9895 : }
9896 :
9897 5 : if (!torture_close_connection(cli)) {
9898 0 : correct = False;
9899 : }
9900 :
9901 5 : printf("finished dirtest\n");
9902 :
9903 5 : return correct;
9904 : }
9905 :
9906 0 : static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9907 : void *state)
9908 : {
9909 0 : struct cli_state *pcli = (struct cli_state *)state;
9910 0 : fstring fname;
9911 0 : slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9912 :
9913 0 : if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9914 0 : return NT_STATUS_OK;
9915 :
9916 0 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9917 0 : if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9918 0 : printf("del_fn: failed to rmdir %s\n,", fname );
9919 : } else {
9920 0 : if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9921 0 : printf("del_fn: failed to unlink %s\n,", fname );
9922 : }
9923 0 : return NT_STATUS_OK;
9924 : }
9925 :
9926 :
9927 : /*
9928 : send a raw ioctl - used by the torture code
9929 : */
9930 327690 : static NTSTATUS cli_raw_ioctl(struct cli_state *cli,
9931 : uint16_t fnum,
9932 : uint32_t code,
9933 : DATA_BLOB *blob)
9934 : {
9935 0 : uint16_t vwv[3];
9936 0 : NTSTATUS status;
9937 :
9938 327690 : PUSH_LE_U16(vwv + 0, 0, fnum);
9939 327690 : PUSH_LE_U16(vwv + 1, 0, code >> 16);
9940 327690 : PUSH_LE_U16(vwv + 2, 0, (code & 0xFFFF));
9941 :
9942 327690 : status = cli_smb(talloc_tos(),
9943 : cli,
9944 : SMBioctl,
9945 : 0,
9946 : 3,
9947 : vwv,
9948 : 0,
9949 : NULL,
9950 : NULL,
9951 : 0,
9952 : NULL,
9953 : NULL,
9954 : NULL,
9955 : NULL);
9956 327690 : if (!NT_STATUS_IS_OK(status)) {
9957 327682 : return status;
9958 : }
9959 8 : *blob = data_blob_null;
9960 8 : return NT_STATUS_OK;
9961 : }
9962 :
9963 : /*
9964 : sees what IOCTLs are supported
9965 : */
9966 5 : bool torture_ioctl_test(int dummy)
9967 : {
9968 0 : static struct cli_state *cli;
9969 0 : uint16_t device, function;
9970 0 : uint16_t fnum;
9971 5 : const char *fname = "\\ioctl.dat";
9972 0 : DATA_BLOB blob;
9973 0 : NTSTATUS status;
9974 :
9975 5 : if (!torture_open_connection(&cli, 0)) {
9976 0 : return False;
9977 : }
9978 :
9979 5 : printf("starting ioctl test\n");
9980 :
9981 5 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9982 :
9983 5 : status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9984 5 : if (!NT_STATUS_IS_OK(status)) {
9985 0 : printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9986 0 : return False;
9987 : }
9988 :
9989 5 : status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9990 5 : printf("ioctl device info: %s\n", nt_errstr(status));
9991 :
9992 5 : status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9993 5 : printf("ioctl job info: %s\n", nt_errstr(status));
9994 :
9995 1285 : for (device=0;device<0x100;device++) {
9996 1280 : printf("ioctl test with device = 0x%x\n", device);
9997 328960 : for (function=0;function<0x100;function++) {
9998 327680 : uint32_t code = (device<<16) | function;
9999 :
10000 327680 : status = cli_raw_ioctl(cli, fnum, code, &blob);
10001 :
10002 327680 : if (NT_STATUS_IS_OK(status)) {
10003 4 : printf("ioctl 0x%x OK : %d bytes\n", (int)code,
10004 4 : (int)blob.length);
10005 4 : data_blob_free(&blob);
10006 : }
10007 : }
10008 : }
10009 :
10010 5 : if (!torture_close_connection(cli)) {
10011 0 : return False;
10012 : }
10013 :
10014 5 : return True;
10015 : }
10016 :
10017 :
10018 : /*
10019 : tries variants of chkpath
10020 : */
10021 5 : bool torture_chkpath_test(int dummy)
10022 : {
10023 0 : static struct cli_state *cli;
10024 0 : uint16_t fnum;
10025 0 : bool ret;
10026 0 : NTSTATUS status;
10027 :
10028 5 : if (!torture_open_connection(&cli, 0)) {
10029 0 : return False;
10030 : }
10031 :
10032 5 : printf("starting chkpath test\n");
10033 :
10034 : /* cleanup from an old run */
10035 5 : torture_deltree(cli, "\\chkpath.dir");
10036 :
10037 5 : status = cli_mkdir(cli, "\\chkpath.dir");
10038 5 : if (!NT_STATUS_IS_OK(status)) {
10039 0 : printf("mkdir1 failed : %s\n", nt_errstr(status));
10040 0 : return False;
10041 : }
10042 :
10043 5 : status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
10044 5 : if (!NT_STATUS_IS_OK(status)) {
10045 0 : printf("mkdir2 failed : %s\n", nt_errstr(status));
10046 0 : return False;
10047 : }
10048 :
10049 5 : status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
10050 : DENY_NONE, &fnum);
10051 5 : if (!NT_STATUS_IS_OK(status)) {
10052 0 : printf("open1 failed (%s)\n", nt_errstr(status));
10053 0 : return False;
10054 : }
10055 5 : cli_close(cli, fnum);
10056 :
10057 5 : status = cli_chkpath(cli, "\\chkpath.dir");
10058 5 : if (!NT_STATUS_IS_OK(status)) {
10059 0 : printf("chkpath1 failed: %s\n", nt_errstr(status));
10060 0 : ret = False;
10061 : }
10062 :
10063 5 : status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
10064 5 : if (!NT_STATUS_IS_OK(status)) {
10065 0 : printf("chkpath2 failed: %s\n", nt_errstr(status));
10066 0 : ret = False;
10067 : }
10068 :
10069 5 : status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
10070 5 : if (!NT_STATUS_IS_OK(status)) {
10071 5 : ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10072 5 : NT_STATUS_NOT_A_DIRECTORY);
10073 : } else {
10074 0 : printf("* chkpath on a file should fail\n");
10075 0 : ret = False;
10076 : }
10077 :
10078 5 : status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
10079 5 : if (!NT_STATUS_IS_OK(status)) {
10080 5 : ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
10081 5 : NT_STATUS_OBJECT_NAME_NOT_FOUND);
10082 : } else {
10083 0 : printf("* chkpath on a non existent file should fail\n");
10084 0 : ret = False;
10085 : }
10086 :
10087 5 : status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
10088 5 : if (!NT_STATUS_IS_OK(status)) {
10089 5 : ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10090 5 : NT_STATUS_OBJECT_PATH_NOT_FOUND);
10091 : } else {
10092 0 : printf("* chkpath on a non existent component should fail\n");
10093 0 : ret = False;
10094 : }
10095 :
10096 5 : torture_deltree(cli, "\\chkpath.dir");
10097 :
10098 5 : if (!torture_close_connection(cli)) {
10099 0 : return False;
10100 : }
10101 :
10102 5 : return ret;
10103 : }
10104 :
10105 0 : static bool run_eatest(int dummy)
10106 : {
10107 0 : static struct cli_state *cli;
10108 0 : const char *fname = "\\eatest.txt";
10109 0 : bool correct = True;
10110 0 : uint16_t fnum;
10111 0 : size_t i, num_eas;
10112 0 : struct ea_struct *ea_list = NULL;
10113 0 : TALLOC_CTX *mem_ctx = talloc_init("eatest");
10114 0 : NTSTATUS status;
10115 :
10116 0 : printf("starting eatest\n");
10117 :
10118 0 : if (!torture_open_connection(&cli, 0)) {
10119 0 : talloc_destroy(mem_ctx);
10120 0 : return False;
10121 : }
10122 :
10123 0 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10124 :
10125 0 : status = cli_ntcreate(cli, fname, 0,
10126 : FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10127 : FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10128 : 0x4044, 0, &fnum, NULL);
10129 0 : if (!NT_STATUS_IS_OK(status)) {
10130 0 : printf("open failed - %s\n", nt_errstr(status));
10131 0 : talloc_destroy(mem_ctx);
10132 0 : return False;
10133 : }
10134 :
10135 0 : for (i = 0; i < 10; i++) {
10136 0 : fstring ea_name, ea_val;
10137 :
10138 0 : slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10139 0 : memset(ea_val, (char)i+1, i+1);
10140 0 : status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10141 0 : if (!NT_STATUS_IS_OK(status)) {
10142 0 : printf("ea_set of name %s failed - %s\n", ea_name,
10143 : nt_errstr(status));
10144 0 : talloc_destroy(mem_ctx);
10145 0 : return False;
10146 : }
10147 : }
10148 :
10149 0 : cli_close(cli, fnum);
10150 0 : for (i = 0; i < 10; i++) {
10151 0 : fstring ea_name, ea_val;
10152 :
10153 0 : slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10154 0 : memset(ea_val, (char)i+1, i+1);
10155 0 : status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10156 0 : if (!NT_STATUS_IS_OK(status)) {
10157 0 : printf("ea_set of name %s failed - %s\n", ea_name,
10158 : nt_errstr(status));
10159 0 : talloc_destroy(mem_ctx);
10160 0 : return False;
10161 : }
10162 : }
10163 :
10164 0 : status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10165 0 : if (!NT_STATUS_IS_OK(status)) {
10166 0 : printf("ea_get list failed - %s\n", nt_errstr(status));
10167 0 : correct = False;
10168 : }
10169 :
10170 0 : printf("num_eas = %d\n", (int)num_eas);
10171 :
10172 0 : if (num_eas != 20) {
10173 0 : printf("Should be 20 EA's stored... failing.\n");
10174 0 : correct = False;
10175 : }
10176 :
10177 0 : for (i = 0; i < num_eas; i++) {
10178 0 : printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10179 0 : dump_data(0, ea_list[i].value.data,
10180 0 : ea_list[i].value.length);
10181 : }
10182 :
10183 : /* Setting EA's to zero length deletes them. Test this */
10184 0 : printf("Now deleting all EA's - case independent....\n");
10185 :
10186 : #if 1
10187 0 : cli_set_ea_path(cli, fname, "", "", 0);
10188 : #else
10189 : for (i = 0; i < 20; i++) {
10190 : fstring ea_name;
10191 : slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10192 : status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10193 : if (!NT_STATUS_IS_OK(status)) {
10194 : printf("ea_set of name %s failed - %s\n", ea_name,
10195 : nt_errstr(status));
10196 : talloc_destroy(mem_ctx);
10197 : return False;
10198 : }
10199 : }
10200 : #endif
10201 :
10202 0 : status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10203 0 : if (!NT_STATUS_IS_OK(status)) {
10204 0 : printf("ea_get list failed - %s\n", nt_errstr(status));
10205 0 : correct = False;
10206 : }
10207 :
10208 0 : printf("num_eas = %d\n", (int)num_eas);
10209 0 : for (i = 0; i < num_eas; i++) {
10210 0 : printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10211 0 : dump_data(0, ea_list[i].value.data,
10212 0 : ea_list[i].value.length);
10213 : }
10214 :
10215 0 : if (num_eas != 0) {
10216 0 : printf("deleting EA's failed.\n");
10217 0 : correct = False;
10218 : }
10219 :
10220 : /* Try and delete a non existent EA. */
10221 0 : status = cli_set_ea_path(cli, fname, "foo", "", 0);
10222 0 : if (!NT_STATUS_IS_OK(status)) {
10223 0 : printf("deleting non-existent EA 'foo' should succeed. %s\n",
10224 : nt_errstr(status));
10225 0 : correct = False;
10226 : }
10227 :
10228 0 : talloc_destroy(mem_ctx);
10229 0 : if (!torture_close_connection(cli)) {
10230 0 : correct = False;
10231 : }
10232 :
10233 0 : return correct;
10234 : }
10235 :
10236 0 : static bool run_dirtest1(int dummy)
10237 : {
10238 0 : int i;
10239 0 : static struct cli_state *cli;
10240 0 : uint16_t fnum;
10241 0 : int num_seen;
10242 0 : bool correct = True;
10243 :
10244 0 : printf("starting directory test\n");
10245 :
10246 0 : if (!torture_open_connection(&cli, 0)) {
10247 0 : return False;
10248 : }
10249 :
10250 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
10251 :
10252 0 : cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10253 0 : cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10254 0 : cli_rmdir(cli, "\\LISTDIR");
10255 0 : cli_mkdir(cli, "\\LISTDIR");
10256 :
10257 : /* Create 1000 files and 1000 directories. */
10258 0 : for (i=0;i<1000;i++) {
10259 0 : fstring fname;
10260 0 : slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10261 0 : if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10262 : FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10263 : 0, 0, &fnum, NULL))) {
10264 0 : fprintf(stderr,"Failed to open %s\n", fname);
10265 0 : return False;
10266 : }
10267 0 : cli_close(cli, fnum);
10268 : }
10269 0 : for (i=0;i<1000;i++) {
10270 0 : fstring fname;
10271 0 : slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10272 0 : if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10273 0 : fprintf(stderr,"Failed to open %s\n", fname);
10274 0 : return False;
10275 : }
10276 : }
10277 :
10278 : /* Now ensure that doing an old list sees both files and directories. */
10279 0 : num_seen = 0;
10280 0 : cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10281 0 : printf("num_seen = %d\n", num_seen );
10282 : /* We should see 100 files + 1000 directories + . and .. */
10283 0 : if (num_seen != 2002)
10284 0 : correct = False;
10285 :
10286 : /* Ensure if we have the "must have" bits we only see the
10287 : * relevant entries.
10288 : */
10289 0 : num_seen = 0;
10290 0 : cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10291 0 : printf("num_seen = %d\n", num_seen );
10292 0 : if (num_seen != 1002)
10293 0 : correct = False;
10294 :
10295 0 : num_seen = 0;
10296 0 : cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10297 0 : printf("num_seen = %d\n", num_seen );
10298 0 : if (num_seen != 1000)
10299 0 : correct = False;
10300 :
10301 : /* Delete everything. */
10302 0 : cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10303 0 : cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10304 0 : cli_rmdir(cli, "\\LISTDIR");
10305 :
10306 : #if 0
10307 : printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10308 : printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10309 : printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10310 : #endif
10311 :
10312 0 : if (!torture_close_connection(cli)) {
10313 0 : correct = False;
10314 : }
10315 :
10316 0 : printf("finished dirtest1\n");
10317 :
10318 0 : return correct;
10319 : }
10320 :
10321 0 : static bool run_error_map_extract(int dummy) {
10322 :
10323 0 : static struct cli_state *c_dos;
10324 0 : static struct cli_state *c_nt;
10325 0 : NTSTATUS status;
10326 :
10327 0 : uint32_t error;
10328 :
10329 0 : uint32_t errnum;
10330 0 : uint8_t errclass;
10331 :
10332 0 : NTSTATUS nt_status;
10333 :
10334 0 : fstring user;
10335 :
10336 : /* NT-Error connection */
10337 :
10338 0 : disable_spnego = true;
10339 0 : if (!(c_nt = open_nbt_connection())) {
10340 0 : disable_spnego = false;
10341 0 : return False;
10342 : }
10343 0 : disable_spnego = false;
10344 :
10345 0 : status = smbXcli_negprot(c_nt->conn,
10346 0 : c_nt->timeout,
10347 : PROTOCOL_CORE,
10348 : PROTOCOL_NT1,
10349 : NULL,
10350 : NULL,
10351 : NULL);
10352 :
10353 0 : if (!NT_STATUS_IS_OK(status)) {
10354 0 : printf("%s rejected the NT-error negprot (%s)\n", host,
10355 : nt_errstr(status));
10356 0 : cli_shutdown(c_nt);
10357 0 : return False;
10358 : }
10359 :
10360 0 : status = cli_session_setup_anon(c_nt);
10361 0 : if (!NT_STATUS_IS_OK(status)) {
10362 0 : printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10363 0 : return False;
10364 : }
10365 :
10366 : /* DOS-Error connection */
10367 :
10368 0 : disable_spnego = true;
10369 0 : force_dos_errors = true;
10370 0 : if (!(c_dos = open_nbt_connection())) {
10371 0 : disable_spnego = false;
10372 0 : force_dos_errors = false;
10373 0 : return False;
10374 : }
10375 0 : disable_spnego = false;
10376 0 : force_dos_errors = false;
10377 :
10378 0 : status = smbXcli_negprot(c_dos->conn,
10379 0 : c_dos->timeout,
10380 : PROTOCOL_CORE,
10381 : PROTOCOL_NT1,
10382 : NULL,
10383 : NULL,
10384 : NULL);
10385 0 : if (!NT_STATUS_IS_OK(status)) {
10386 0 : printf("%s rejected the DOS-error negprot (%s)\n", host,
10387 : nt_errstr(status));
10388 0 : cli_shutdown(c_dos);
10389 0 : return False;
10390 : }
10391 :
10392 0 : status = cli_session_setup_anon(c_dos);
10393 0 : if (!NT_STATUS_IS_OK(status)) {
10394 0 : printf("%s rejected the DOS-error initial session setup (%s)\n",
10395 : host, nt_errstr(status));
10396 0 : return False;
10397 : }
10398 :
10399 0 : c_nt->map_dos_errors = false;
10400 0 : c_dos->map_dos_errors = false;
10401 :
10402 0 : for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10403 0 : struct cli_credentials *user_creds = NULL;
10404 :
10405 0 : fstr_sprintf(user, "%X", error);
10406 :
10407 0 : user_creds = cli_session_creds_init(talloc_tos(),
10408 : user,
10409 : workgroup,
10410 : NULL, /* realm */
10411 : password,
10412 : false, /* use_kerberos */
10413 : false, /* fallback_after_kerberos */
10414 : false, /* use_ccache */
10415 : false); /* password_is_nt_hash */
10416 0 : if (user_creds == NULL) {
10417 0 : printf("cli_session_creds_init(%s) failed\n", user);
10418 0 : return false;
10419 : }
10420 :
10421 0 : status = cli_session_setup_creds(c_nt, user_creds);
10422 0 : if (NT_STATUS_IS_OK(status)) {
10423 0 : printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10424 : }
10425 :
10426 : /* Case #1: 32-bit NT errors */
10427 0 : if (!NT_STATUS_IS_DOS(status)) {
10428 0 : nt_status = status;
10429 : } else {
10430 0 : printf("/** Dos error on NT connection! (%s) */\n",
10431 : nt_errstr(status));
10432 0 : nt_status = NT_STATUS(0xc0000000);
10433 : }
10434 :
10435 0 : status = cli_session_setup_creds(c_dos, user_creds);
10436 0 : if (NT_STATUS_IS_OK(status)) {
10437 0 : printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10438 : }
10439 :
10440 : /* Case #1: 32-bit NT errors */
10441 0 : if (NT_STATUS_IS_DOS(status)) {
10442 0 : printf("/** NT error on DOS connection! (%s) */\n",
10443 : nt_errstr(status));
10444 0 : errnum = errclass = 0;
10445 : } else {
10446 0 : errclass = NT_STATUS_DOS_CLASS(status);
10447 0 : errnum = NT_STATUS_DOS_CODE(status);
10448 : }
10449 :
10450 0 : if (NT_STATUS_V(nt_status) != error) {
10451 0 : printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10452 0 : get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
10453 0 : get_nt_error_c_code(talloc_tos(), nt_status));
10454 : }
10455 :
10456 0 : printf("\t{%s,\t%s,\t%s},\n",
10457 : smb_dos_err_class(errclass),
10458 : smb_dos_err_name(errclass, errnum),
10459 0 : get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10460 :
10461 0 : TALLOC_FREE(user_creds);
10462 : }
10463 0 : return True;
10464 : }
10465 :
10466 0 : static bool run_sesssetup_bench(int dummy)
10467 : {
10468 0 : static struct cli_state *c;
10469 0 : const char *fname = "\\file.dat";
10470 0 : uint16_t fnum;
10471 0 : NTSTATUS status;
10472 0 : int i;
10473 :
10474 0 : if (!torture_open_connection(&c, 0)) {
10475 0 : return false;
10476 : }
10477 :
10478 0 : status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10479 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10480 : FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10481 0 : if (!NT_STATUS_IS_OK(status)) {
10482 0 : d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10483 0 : return false;
10484 : }
10485 :
10486 0 : for (i=0; i<torture_numops; i++) {
10487 0 : status = cli_session_setup_creds(c, torture_creds);
10488 0 : if (!NT_STATUS_IS_OK(status)) {
10489 0 : d_printf("(%s) cli_session_setup_creds failed: %s\n",
10490 : __location__, nt_errstr(status));
10491 0 : return false;
10492 : }
10493 :
10494 0 : d_printf("\r%d ", (int)cli_state_get_uid(c));
10495 :
10496 0 : status = cli_ulogoff(c);
10497 0 : if (!NT_STATUS_IS_OK(status)) {
10498 0 : d_printf("(%s) cli_ulogoff failed: %s\n",
10499 : __location__, nt_errstr(status));
10500 0 : return false;
10501 : }
10502 : }
10503 :
10504 0 : return true;
10505 : }
10506 :
10507 9 : static bool subst_test(const char *str, const char *user, const char *domain,
10508 : uid_t uid, gid_t gid, const char *expected)
10509 : {
10510 9 : char *subst;
10511 9 : bool result = true;
10512 :
10513 9 : subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10514 :
10515 9 : if (strcmp(subst, expected) != 0) {
10516 0 : printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10517 : "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10518 : expected);
10519 0 : result = false;
10520 : }
10521 :
10522 9 : TALLOC_FREE(subst);
10523 9 : return result;
10524 : }
10525 :
10526 5 : static void chain1_open_completion(struct tevent_req *req)
10527 : {
10528 0 : uint16_t fnum;
10529 0 : NTSTATUS status;
10530 5 : status = cli_openx_recv(req, &fnum);
10531 5 : TALLOC_FREE(req);
10532 :
10533 5 : d_printf("cli_openx_recv returned %s: %d\n",
10534 : nt_errstr(status),
10535 5 : NT_STATUS_IS_OK(status) ? fnum : -1);
10536 5 : }
10537 :
10538 5 : static void chain1_write_completion(struct tevent_req *req)
10539 : {
10540 0 : size_t written;
10541 0 : NTSTATUS status;
10542 5 : status = cli_write_andx_recv(req, &written);
10543 5 : TALLOC_FREE(req);
10544 :
10545 5 : d_printf("cli_write_andx_recv returned %s: %d\n",
10546 : nt_errstr(status),
10547 5 : NT_STATUS_IS_OK(status) ? (int)written : -1);
10548 5 : }
10549 :
10550 5 : static void chain1_close_completion(struct tevent_req *req)
10551 : {
10552 0 : NTSTATUS status;
10553 5 : bool *done = (bool *)tevent_req_callback_data_void(req);
10554 :
10555 5 : status = cli_close_recv(req);
10556 5 : *done = true;
10557 :
10558 5 : TALLOC_FREE(req);
10559 :
10560 5 : d_printf("cli_close returned %s\n", nt_errstr(status));
10561 5 : }
10562 :
10563 5 : static bool run_chain1(int dummy)
10564 : {
10565 0 : struct cli_state *cli1;
10566 5 : struct tevent_context *evt = samba_tevent_context_init(NULL);
10567 0 : struct tevent_req *reqs[3], *smbreqs[3];
10568 5 : bool done = false;
10569 5 : const char *str = "foobar";
10570 5 : const char *fname = "\\test_chain";
10571 0 : NTSTATUS status;
10572 :
10573 5 : printf("starting chain1 test\n");
10574 5 : if (!torture_open_connection(&cli1, 0)) {
10575 0 : return False;
10576 : }
10577 :
10578 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
10579 :
10580 5 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10581 :
10582 5 : reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10583 : O_CREAT|O_RDWR, 0, &smbreqs[0]);
10584 5 : if (reqs[0] == NULL) return false;
10585 5 : tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10586 :
10587 :
10588 5 : reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10589 5 : (const uint8_t *)str, 0, strlen(str)+1,
10590 : smbreqs, 1, &smbreqs[1]);
10591 5 : if (reqs[1] == NULL) return false;
10592 5 : tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10593 :
10594 5 : reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10595 5 : if (reqs[2] == NULL) return false;
10596 5 : tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10597 :
10598 5 : status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10599 5 : if (!NT_STATUS_IS_OK(status)) {
10600 0 : return false;
10601 : }
10602 :
10603 35 : while (!done) {
10604 30 : tevent_loop_once(evt);
10605 : }
10606 :
10607 5 : torture_close_connection(cli1);
10608 5 : return True;
10609 : }
10610 :
10611 5 : static void chain2_sesssetup_completion(struct tevent_req *req)
10612 : {
10613 0 : NTSTATUS status;
10614 5 : status = cli_session_setup_guest_recv(req);
10615 5 : d_printf("sesssetup returned %s\n", nt_errstr(status));
10616 5 : }
10617 :
10618 5 : static void chain2_tcon_completion(struct tevent_req *req)
10619 : {
10620 5 : bool *done = (bool *)tevent_req_callback_data_void(req);
10621 0 : NTSTATUS status;
10622 5 : status = cli_tcon_andx_recv(req);
10623 5 : d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10624 5 : *done = true;
10625 5 : }
10626 :
10627 5 : static bool run_chain2(int dummy)
10628 : {
10629 0 : struct cli_state *cli1;
10630 5 : struct tevent_context *evt = samba_tevent_context_init(NULL);
10631 0 : struct tevent_req *reqs[2], *smbreqs[2];
10632 5 : bool done = false;
10633 0 : NTSTATUS status;
10634 5 : int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10635 :
10636 5 : printf("starting chain2 test\n");
10637 5 : status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10638 : port_to_use, SMB_SIGNING_DEFAULT, flags);
10639 5 : if (!NT_STATUS_IS_OK(status)) {
10640 0 : return False;
10641 : }
10642 :
10643 5 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
10644 :
10645 5 : reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10646 : &smbreqs[0]);
10647 5 : if (reqs[0] == NULL) return false;
10648 5 : tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10649 :
10650 5 : reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10651 : "?????", NULL, 0, &smbreqs[1]);
10652 5 : if (reqs[1] == NULL) return false;
10653 5 : tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10654 :
10655 5 : status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10656 5 : if (!NT_STATUS_IS_OK(status)) {
10657 0 : return false;
10658 : }
10659 :
10660 30 : while (!done) {
10661 25 : tevent_loop_once(evt);
10662 : }
10663 :
10664 5 : torture_close_connection(cli1);
10665 5 : return True;
10666 : }
10667 :
10668 :
10669 : struct torture_createdel_state {
10670 : struct tevent_context *ev;
10671 : struct cli_state *cli;
10672 : };
10673 :
10674 : static void torture_createdel_created(struct tevent_req *subreq);
10675 : static void torture_createdel_closed(struct tevent_req *subreq);
10676 :
10677 0 : static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10678 : struct tevent_context *ev,
10679 : struct cli_state *cli,
10680 : const char *name)
10681 : {
10682 0 : struct tevent_req *req, *subreq;
10683 0 : struct torture_createdel_state *state;
10684 :
10685 0 : req = tevent_req_create(mem_ctx, &state,
10686 : struct torture_createdel_state);
10687 0 : if (req == NULL) {
10688 0 : return NULL;
10689 : }
10690 0 : state->ev = ev;
10691 0 : state->cli = cli;
10692 :
10693 0 : subreq = cli_ntcreate_send(
10694 : state, ev, cli, name, 0,
10695 : FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10696 : FILE_ATTRIBUTE_NORMAL,
10697 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10698 : FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10699 : SMB2_IMPERSONATION_IMPERSONATION, 0);
10700 :
10701 0 : if (tevent_req_nomem(subreq, req)) {
10702 0 : return tevent_req_post(req, ev);
10703 : }
10704 0 : tevent_req_set_callback(subreq, torture_createdel_created, req);
10705 0 : return req;
10706 : }
10707 :
10708 0 : static void torture_createdel_created(struct tevent_req *subreq)
10709 : {
10710 0 : struct tevent_req *req = tevent_req_callback_data(
10711 : subreq, struct tevent_req);
10712 0 : struct torture_createdel_state *state = tevent_req_data(
10713 : req, struct torture_createdel_state);
10714 0 : NTSTATUS status;
10715 0 : uint16_t fnum;
10716 :
10717 0 : status = cli_ntcreate_recv(subreq, &fnum, NULL);
10718 0 : TALLOC_FREE(subreq);
10719 0 : if (tevent_req_nterror(req, status)) {
10720 0 : DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10721 : nt_errstr(status)));
10722 0 : return;
10723 : }
10724 :
10725 0 : subreq = cli_close_send(state, state->ev, state->cli, fnum, 0);
10726 0 : if (tevent_req_nomem(subreq, req)) {
10727 0 : return;
10728 : }
10729 0 : tevent_req_set_callback(subreq, torture_createdel_closed, req);
10730 : }
10731 :
10732 0 : static void torture_createdel_closed(struct tevent_req *subreq)
10733 : {
10734 0 : struct tevent_req *req = tevent_req_callback_data(
10735 : subreq, struct tevent_req);
10736 0 : NTSTATUS status;
10737 :
10738 0 : status = cli_close_recv(subreq);
10739 0 : if (tevent_req_nterror(req, status)) {
10740 0 : DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10741 0 : return;
10742 : }
10743 0 : tevent_req_done(req);
10744 : }
10745 :
10746 0 : static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10747 : {
10748 0 : return tevent_req_simple_recv_ntstatus(req);
10749 : }
10750 :
10751 : struct torture_createdels_state {
10752 : struct tevent_context *ev;
10753 : struct cli_state *cli;
10754 : const char *base_name;
10755 : int sent;
10756 : int received;
10757 : int num_files;
10758 : struct tevent_req **reqs;
10759 : };
10760 :
10761 : static void torture_createdels_done(struct tevent_req *subreq);
10762 :
10763 0 : static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10764 : struct tevent_context *ev,
10765 : struct cli_state *cli,
10766 : const char *base_name,
10767 : int num_parallel,
10768 : int num_files)
10769 : {
10770 0 : struct tevent_req *req;
10771 0 : struct torture_createdels_state *state;
10772 0 : int i;
10773 :
10774 0 : req = tevent_req_create(mem_ctx, &state,
10775 : struct torture_createdels_state);
10776 0 : if (req == NULL) {
10777 0 : return NULL;
10778 : }
10779 0 : state->ev = ev;
10780 0 : state->cli = cli;
10781 0 : state->base_name = talloc_strdup(state, base_name);
10782 0 : if (tevent_req_nomem(state->base_name, req)) {
10783 0 : return tevent_req_post(req, ev);
10784 : }
10785 0 : state->num_files = MAX(num_parallel, num_files);
10786 0 : state->sent = 0;
10787 0 : state->received = 0;
10788 :
10789 0 : state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10790 0 : if (tevent_req_nomem(state->reqs, req)) {
10791 0 : return tevent_req_post(req, ev);
10792 : }
10793 :
10794 0 : for (i=0; i<num_parallel; i++) {
10795 0 : char *name;
10796 :
10797 0 : name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10798 0 : state->sent);
10799 0 : if (tevent_req_nomem(name, req)) {
10800 0 : return tevent_req_post(req, ev);
10801 : }
10802 0 : state->reqs[i] = torture_createdel_send(
10803 0 : state->reqs, state->ev, state->cli, name);
10804 0 : if (tevent_req_nomem(state->reqs[i], req)) {
10805 0 : return tevent_req_post(req, ev);
10806 : }
10807 0 : name = talloc_move(state->reqs[i], &name);
10808 0 : tevent_req_set_callback(state->reqs[i],
10809 : torture_createdels_done, req);
10810 0 : state->sent += 1;
10811 : }
10812 0 : return req;
10813 : }
10814 :
10815 0 : static void torture_createdels_done(struct tevent_req *subreq)
10816 : {
10817 0 : struct tevent_req *req = tevent_req_callback_data(
10818 : subreq, struct tevent_req);
10819 0 : struct torture_createdels_state *state = tevent_req_data(
10820 : req, struct torture_createdels_state);
10821 0 : size_t i, num_parallel = talloc_array_length(state->reqs);
10822 0 : NTSTATUS status;
10823 0 : char *name;
10824 :
10825 0 : status = torture_createdel_recv(subreq);
10826 0 : if (!NT_STATUS_IS_OK(status)){
10827 0 : DEBUG(10, ("torture_createdel_recv returned %s\n",
10828 : nt_errstr(status)));
10829 0 : TALLOC_FREE(subreq);
10830 0 : tevent_req_nterror(req, status);
10831 0 : return;
10832 : }
10833 :
10834 0 : for (i=0; i<num_parallel; i++) {
10835 0 : if (subreq == state->reqs[i]) {
10836 0 : break;
10837 : }
10838 : }
10839 0 : if (i == num_parallel) {
10840 0 : DEBUG(10, ("received something we did not send\n"));
10841 0 : tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10842 0 : return;
10843 : }
10844 0 : TALLOC_FREE(state->reqs[i]);
10845 :
10846 0 : if (state->sent >= state->num_files) {
10847 0 : tevent_req_done(req);
10848 0 : return;
10849 : }
10850 :
10851 0 : name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10852 : state->sent);
10853 0 : if (tevent_req_nomem(name, req)) {
10854 0 : return;
10855 : }
10856 0 : state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10857 : state->cli, name);
10858 0 : if (tevent_req_nomem(state->reqs[i], req)) {
10859 0 : return;
10860 : }
10861 0 : name = talloc_move(state->reqs[i], &name);
10862 0 : tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10863 0 : state->sent += 1;
10864 : }
10865 :
10866 0 : static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10867 : {
10868 0 : return tevent_req_simple_recv_ntstatus(req);
10869 : }
10870 :
10871 : struct swallow_notify_state {
10872 : struct tevent_context *ev;
10873 : struct cli_state *cli;
10874 : uint16_t fnum;
10875 : uint32_t completion_filter;
10876 : bool recursive;
10877 : bool (*fn)(uint32_t action, const char *name, void *priv);
10878 : void *priv;
10879 : };
10880 :
10881 : static void swallow_notify_done(struct tevent_req *subreq);
10882 :
10883 0 : static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10884 : struct tevent_context *ev,
10885 : struct cli_state *cli,
10886 : uint16_t fnum,
10887 : uint32_t completion_filter,
10888 : bool recursive,
10889 : bool (*fn)(uint32_t action,
10890 : const char *name,
10891 : void *priv),
10892 : void *priv)
10893 : {
10894 0 : struct tevent_req *req, *subreq;
10895 0 : struct swallow_notify_state *state;
10896 :
10897 0 : req = tevent_req_create(mem_ctx, &state,
10898 : struct swallow_notify_state);
10899 0 : if (req == NULL) {
10900 0 : return NULL;
10901 : }
10902 0 : state->ev = ev;
10903 0 : state->cli = cli;
10904 0 : state->fnum = fnum;
10905 0 : state->completion_filter = completion_filter;
10906 0 : state->recursive = recursive;
10907 0 : state->fn = fn;
10908 0 : state->priv = priv;
10909 :
10910 0 : subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10911 0 : 0xffff, state->completion_filter,
10912 0 : state->recursive);
10913 0 : if (tevent_req_nomem(subreq, req)) {
10914 0 : return tevent_req_post(req, ev);
10915 : }
10916 0 : tevent_req_set_callback(subreq, swallow_notify_done, req);
10917 0 : return req;
10918 : }
10919 :
10920 0 : static void swallow_notify_done(struct tevent_req *subreq)
10921 : {
10922 0 : struct tevent_req *req = tevent_req_callback_data(
10923 : subreq, struct tevent_req);
10924 0 : struct swallow_notify_state *state = tevent_req_data(
10925 : req, struct swallow_notify_state);
10926 0 : NTSTATUS status;
10927 0 : uint32_t i, num_changes;
10928 0 : struct notify_change *changes;
10929 :
10930 0 : status = cli_notify_recv(subreq, state, &num_changes, &changes);
10931 0 : TALLOC_FREE(subreq);
10932 0 : if (!NT_STATUS_IS_OK(status)) {
10933 0 : DEBUG(10, ("cli_notify_recv returned %s\n",
10934 : nt_errstr(status)));
10935 0 : tevent_req_nterror(req, status);
10936 0 : return;
10937 : }
10938 :
10939 0 : for (i=0; i<num_changes; i++) {
10940 0 : state->fn(changes[i].action, changes[i].name, state->priv);
10941 : }
10942 0 : TALLOC_FREE(changes);
10943 :
10944 0 : subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10945 : 0xffff, state->completion_filter,
10946 0 : state->recursive);
10947 0 : if (tevent_req_nomem(subreq, req)) {
10948 0 : return;
10949 : }
10950 0 : tevent_req_set_callback(subreq, swallow_notify_done, req);
10951 : }
10952 :
10953 0 : static bool print_notifies(uint32_t action, const char *name, void *priv)
10954 : {
10955 0 : if (DEBUGLEVEL > 5) {
10956 0 : d_printf("%d %s\n", (int)action, name);
10957 : }
10958 0 : return true;
10959 : }
10960 :
10961 0 : static void notify_bench_done(struct tevent_req *req)
10962 : {
10963 0 : int *num_finished = (int *)tevent_req_callback_data_void(req);
10964 0 : *num_finished += 1;
10965 0 : }
10966 :
10967 0 : static bool run_notify_bench(int dummy)
10968 : {
10969 0 : const char *dname = "\\notify-bench";
10970 0 : struct tevent_context *ev;
10971 0 : NTSTATUS status;
10972 0 : uint16_t dnum;
10973 0 : struct tevent_req *req1;
10974 0 : struct tevent_req *req2 = NULL;
10975 0 : int i, num_unc_names;
10976 0 : int num_finished = 0;
10977 :
10978 0 : printf("starting notify-bench test\n");
10979 :
10980 0 : if (use_multishare_conn) {
10981 0 : char **unc_list;
10982 0 : unc_list = file_lines_load(multishare_conn_fname,
10983 : &num_unc_names, 0, NULL);
10984 0 : if (!unc_list || num_unc_names <= 0) {
10985 0 : d_printf("Failed to load unc names list from '%s'\n",
10986 : multishare_conn_fname);
10987 0 : return false;
10988 : }
10989 0 : TALLOC_FREE(unc_list);
10990 : } else {
10991 0 : num_unc_names = 1;
10992 : }
10993 :
10994 0 : ev = samba_tevent_context_init(talloc_tos());
10995 0 : if (ev == NULL) {
10996 0 : d_printf("tevent_context_init failed\n");
10997 0 : return false;
10998 : }
10999 :
11000 0 : for (i=0; i<num_unc_names; i++) {
11001 0 : struct cli_state *cli;
11002 0 : char *base_fname;
11003 :
11004 0 : base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
11005 : dname, i);
11006 0 : if (base_fname == NULL) {
11007 0 : return false;
11008 : }
11009 :
11010 0 : if (!torture_open_connection(&cli, i)) {
11011 0 : return false;
11012 : }
11013 :
11014 0 : status = cli_ntcreate(cli, dname, 0,
11015 : MAXIMUM_ALLOWED_ACCESS,
11016 : 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
11017 : FILE_SHARE_DELETE,
11018 : FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
11019 : &dnum, NULL);
11020 :
11021 0 : if (!NT_STATUS_IS_OK(status)) {
11022 0 : d_printf("Could not create %s: %s\n", dname,
11023 : nt_errstr(status));
11024 0 : return false;
11025 : }
11026 :
11027 0 : req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
11028 : FILE_NOTIFY_CHANGE_FILE_NAME |
11029 : FILE_NOTIFY_CHANGE_DIR_NAME |
11030 : FILE_NOTIFY_CHANGE_ATTRIBUTES |
11031 : FILE_NOTIFY_CHANGE_LAST_WRITE,
11032 : false, print_notifies, NULL);
11033 0 : if (req1 == NULL) {
11034 0 : d_printf("Could not create notify request\n");
11035 0 : return false;
11036 : }
11037 :
11038 0 : req2 = torture_createdels_send(talloc_tos(), ev, cli,
11039 : base_fname, 10, torture_numops);
11040 0 : if (req2 == NULL) {
11041 0 : d_printf("Could not create createdels request\n");
11042 0 : return false;
11043 : }
11044 0 : TALLOC_FREE(base_fname);
11045 :
11046 0 : tevent_req_set_callback(req2, notify_bench_done,
11047 : &num_finished);
11048 : }
11049 :
11050 0 : while (num_finished < num_unc_names) {
11051 0 : int ret;
11052 0 : ret = tevent_loop_once(ev);
11053 0 : if (ret != 0) {
11054 0 : d_printf("tevent_loop_once failed\n");
11055 0 : return false;
11056 : }
11057 : }
11058 :
11059 0 : if (!tevent_req_poll(req2, ev)) {
11060 0 : d_printf("tevent_req_poll failed\n");
11061 : }
11062 :
11063 0 : status = torture_createdels_recv(req2);
11064 0 : d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
11065 :
11066 0 : return true;
11067 : }
11068 :
11069 0 : static bool run_mangle1(int dummy)
11070 : {
11071 0 : struct cli_state *cli;
11072 0 : const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
11073 0 : uint16_t fnum;
11074 0 : fstring alt_name;
11075 0 : NTSTATUS status;
11076 :
11077 0 : printf("starting mangle1 test\n");
11078 0 : if (!torture_open_connection(&cli, 0)) {
11079 0 : return False;
11080 : }
11081 :
11082 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11083 :
11084 0 : status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11085 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11086 : 0, 0, &fnum, NULL);
11087 0 : if (!NT_STATUS_IS_OK(status)) {
11088 0 : d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11089 0 : return false;
11090 : }
11091 0 : cli_close(cli, fnum);
11092 :
11093 0 : status = cli_qpathinfo_alt_name(cli, fname, alt_name);
11094 0 : if (!NT_STATUS_IS_OK(status)) {
11095 0 : d_printf("cli_qpathinfo_alt_name failed: %s\n",
11096 : nt_errstr(status));
11097 0 : return false;
11098 : }
11099 0 : d_printf("alt_name: %s\n", alt_name);
11100 :
11101 0 : status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
11102 0 : if (!NT_STATUS_IS_OK(status)) {
11103 0 : d_printf("cli_openx(%s) failed: %s\n", alt_name,
11104 : nt_errstr(status));
11105 0 : return false;
11106 : }
11107 0 : cli_close(cli, fnum);
11108 :
11109 0 : status = cli_qpathinfo1(cli, alt_name, NULL, NULL, NULL, NULL, NULL);
11110 0 : if (!NT_STATUS_IS_OK(status)) {
11111 0 : d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
11112 : nt_errstr(status));
11113 0 : return false;
11114 : }
11115 :
11116 0 : return true;
11117 : }
11118 :
11119 2 : static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
11120 : const char *mask,
11121 : void *state)
11122 : {
11123 2 : if (f->short_name == NULL) {
11124 2 : return NT_STATUS_OK;
11125 : }
11126 :
11127 0 : if (strlen(f->short_name) == 0) {
11128 0 : return NT_STATUS_OK;
11129 : }
11130 :
11131 0 : printf("unexpected shortname: %s\n", f->short_name);
11132 :
11133 0 : return NT_STATUS_OBJECT_NAME_INVALID;
11134 : }
11135 :
11136 2 : static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11137 : const char *mask,
11138 : void *state)
11139 : {
11140 2 : char *name = state;
11141 :
11142 2 : printf("name: %s\n", f->name);
11143 2 : fstrcpy(name, f->name);
11144 2 : return NT_STATUS_OK;
11145 : }
11146 :
11147 2 : static bool run_mangle_illegal(int dummy)
11148 : {
11149 2 : struct cli_state *cli = NULL;
11150 2 : struct cli_state *cli_posix = NULL;
11151 2 : const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11152 2 : const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11153 2 : char *mangled_path = NULL;
11154 0 : uint16_t fnum;
11155 0 : fstring name;
11156 0 : fstring alt_name;
11157 0 : NTSTATUS status;
11158 :
11159 2 : printf("starting mangle-illegal test\n");
11160 :
11161 2 : if (!torture_open_connection(&cli, 0)) {
11162 0 : return False;
11163 : }
11164 :
11165 2 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11166 :
11167 2 : if (!torture_open_connection(&cli_posix, 0)) {
11168 0 : return false;
11169 : }
11170 :
11171 2 : smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11172 :
11173 2 : status = torture_setup_unix_extensions(cli_posix);
11174 2 : if (!NT_STATUS_IS_OK(status)) {
11175 0 : return false;
11176 : }
11177 :
11178 2 : cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11179 2 : status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11180 2 : if (!NT_STATUS_IS_OK(status)) {
11181 0 : printf("mkdir1 failed : %s\n", nt_errstr(status));
11182 0 : return False;
11183 : }
11184 :
11185 : /*
11186 : * Create a file with illegal NTFS characters and test that we
11187 : * get a usable mangled name
11188 : */
11189 :
11190 2 : cli_setatr(cli_posix, illegal_fname, 0, 0);
11191 2 : cli_posix_unlink(cli_posix, illegal_fname);
11192 :
11193 2 : status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11194 : 0600, &fnum);
11195 2 : if (!NT_STATUS_IS_OK(status)) {
11196 0 : printf("POSIX create of %s failed (%s)\n",
11197 : illegal_fname, nt_errstr(status));
11198 0 : return false;
11199 : }
11200 :
11201 2 : status = cli_close(cli_posix, fnum);
11202 2 : if (!NT_STATUS_IS_OK(status)) {
11203 0 : printf("close failed (%s)\n", nt_errstr(status));
11204 0 : return false;
11205 : }
11206 :
11207 2 : status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11208 2 : if (!NT_STATUS_IS_OK(status)) {
11209 0 : d_printf("cli_list failed: %s\n", nt_errstr(status));
11210 0 : return false;
11211 : }
11212 :
11213 2 : mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11214 2 : if (mangled_path == NULL) {
11215 0 : return false;
11216 : }
11217 :
11218 2 : status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11219 2 : if (!NT_STATUS_IS_OK(status)) {
11220 0 : d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11221 0 : TALLOC_FREE(mangled_path);
11222 0 : return false;
11223 : }
11224 2 : TALLOC_FREE(mangled_path);
11225 2 : cli_close(cli, fnum);
11226 :
11227 2 : cli_setatr(cli_posix, illegal_fname, 0, 0);
11228 2 : cli_posix_unlink(cli_posix, illegal_fname);
11229 :
11230 : /*
11231 : * Create a file with a long name and check that we got *no* short name.
11232 : */
11233 :
11234 2 : status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11235 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11236 : 0, 0, &fnum, NULL);
11237 2 : if (!NT_STATUS_IS_OK(status)) {
11238 0 : d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11239 0 : return false;
11240 : }
11241 2 : cli_close(cli, fnum);
11242 :
11243 2 : status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11244 2 : if (!NT_STATUS_IS_OK(status)) {
11245 0 : d_printf("cli_list failed\n");
11246 0 : return false;
11247 : }
11248 :
11249 2 : cli_unlink(cli, fname, 0);
11250 2 : cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11251 :
11252 2 : if (!torture_close_connection(cli_posix)) {
11253 0 : return false;
11254 : }
11255 :
11256 2 : if (!torture_close_connection(cli)) {
11257 0 : return false;
11258 : }
11259 :
11260 2 : return true;
11261 : }
11262 :
11263 0 : static size_t null_source(uint8_t *buf, size_t n, void *priv)
11264 : {
11265 0 : size_t *to_pull = (size_t *)priv;
11266 0 : size_t thistime = *to_pull;
11267 :
11268 0 : thistime = MIN(thistime, n);
11269 0 : if (thistime == 0) {
11270 0 : return 0;
11271 : }
11272 :
11273 0 : memset(buf, 0, thistime);
11274 0 : *to_pull -= thistime;
11275 0 : return thistime;
11276 : }
11277 :
11278 0 : static bool run_windows_write(int dummy)
11279 : {
11280 0 : struct cli_state *cli1;
11281 0 : uint16_t fnum;
11282 0 : int i;
11283 0 : bool ret = false;
11284 0 : const char *fname = "\\writetest.txt";
11285 0 : struct timeval start_time;
11286 0 : double seconds;
11287 0 : double kbytes;
11288 0 : NTSTATUS status;
11289 :
11290 0 : printf("starting windows_write test\n");
11291 0 : if (!torture_open_connection(&cli1, 0)) {
11292 0 : return False;
11293 : }
11294 :
11295 0 : status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11296 0 : if (!NT_STATUS_IS_OK(status)) {
11297 0 : printf("open failed (%s)\n", nt_errstr(status));
11298 0 : return False;
11299 : }
11300 :
11301 0 : smbXcli_conn_set_sockopt(cli1->conn, sockops);
11302 :
11303 0 : start_time = timeval_current();
11304 :
11305 0 : for (i=0; i<torture_numops; i++) {
11306 0 : uint8_t c = 0;
11307 0 : off_t start = i * torture_blocksize;
11308 0 : size_t to_pull = torture_blocksize - 1;
11309 :
11310 0 : status = cli_writeall(cli1, fnum, 0, &c,
11311 0 : start + torture_blocksize - 1, 1, NULL);
11312 0 : if (!NT_STATUS_IS_OK(status)) {
11313 0 : printf("cli_write failed: %s\n", nt_errstr(status));
11314 0 : goto fail;
11315 : }
11316 :
11317 0 : status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11318 : null_source, &to_pull);
11319 0 : if (!NT_STATUS_IS_OK(status)) {
11320 0 : printf("cli_push returned: %s\n", nt_errstr(status));
11321 0 : goto fail;
11322 : }
11323 : }
11324 :
11325 0 : seconds = timeval_elapsed(&start_time);
11326 0 : kbytes = (double)torture_blocksize * torture_numops;
11327 0 : kbytes /= 1024;
11328 :
11329 0 : printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11330 0 : (double)seconds, (int)(kbytes/seconds));
11331 :
11332 0 : ret = true;
11333 0 : fail:
11334 0 : cli_close(cli1, fnum);
11335 0 : cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11336 0 : torture_close_connection(cli1);
11337 0 : return ret;
11338 : }
11339 :
11340 64 : static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11341 : {
11342 64 : size_t max_pdu = 0x1FFFF;
11343 :
11344 64 : if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11345 32 : max_pdu = 0xFFFFFF;
11346 : }
11347 :
11348 64 : if (smb1cli_conn_signing_is_active(cli->conn)) {
11349 32 : max_pdu = 0x1FFFF;
11350 : }
11351 :
11352 64 : if (smb1cli_conn_encryption_on(cli->conn)) {
11353 16 : max_pdu = CLI_BUFFER_SIZE;
11354 : }
11355 :
11356 64 : if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11357 8 : len_requested &= 0xFFFF;
11358 : }
11359 :
11360 64 : return MIN(len_requested,
11361 : max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11362 : }
11363 :
11364 64 : static bool check_read_call(struct cli_state *cli,
11365 : uint16_t fnum,
11366 : uint8_t *buf,
11367 : size_t len_requested)
11368 : {
11369 0 : NTSTATUS status;
11370 64 : struct tevent_req *subreq = NULL;
11371 64 : ssize_t len_read = 0;
11372 64 : size_t len_expected = 0;
11373 64 : struct tevent_context *ev = NULL;
11374 :
11375 64 : ev = samba_tevent_context_init(talloc_tos());
11376 64 : if (ev == NULL) {
11377 0 : return false;
11378 : }
11379 :
11380 64 : subreq = cli_read_andx_send(talloc_tos(),
11381 : ev,
11382 : cli,
11383 : fnum,
11384 : 0,
11385 : len_requested);
11386 :
11387 64 : if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11388 0 : return false;
11389 : }
11390 :
11391 64 : status = cli_read_andx_recv(subreq, &len_read, &buf);
11392 64 : if (!NT_STATUS_IS_OK(status)) {
11393 0 : d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11394 0 : return false;
11395 : }
11396 :
11397 64 : TALLOC_FREE(subreq);
11398 64 : TALLOC_FREE(ev);
11399 :
11400 64 : len_expected = calc_expected_return(cli, len_requested);
11401 :
11402 64 : if (len_expected > 0x10000 && len_read == 0x10000) {
11403 : /* Windows servers only return a max of 0x10000,
11404 : doesn't matter if you set CAP_LARGE_READX in
11405 : the client sessionsetupX call or not. */
11406 12 : d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11407 : (unsigned int)len_requested);
11408 52 : } else if (len_read != len_expected) {
11409 0 : d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11410 : (unsigned int)len_requested,
11411 : (unsigned int)len_read,
11412 : (unsigned int)len_expected);
11413 0 : return false;
11414 : } else {
11415 52 : d_printf("Correct read reply.\n");
11416 : }
11417 :
11418 64 : return true;
11419 : }
11420 :
11421 : /* Test large readX variants. */
11422 8 : static bool large_readx_tests(struct cli_state *cli,
11423 : uint16_t fnum,
11424 : uint8_t *buf)
11425 : {
11426 : /* A read of 0xFFFF0001 should *always* return 1 byte. */
11427 8 : if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11428 0 : return false;
11429 : }
11430 : /* A read of 0x10000 should return 0x10000 bytes. */
11431 8 : if (check_read_call(cli, fnum, buf, 0x10000) == false) {
11432 0 : return false;
11433 : }
11434 : /* A read of 0x10000 should return 0x10001 bytes. */
11435 8 : if (check_read_call(cli, fnum, buf, 0x10001) == false) {
11436 0 : return false;
11437 : }
11438 : /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11439 : the requested number of bytes. */
11440 8 : if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11441 0 : return false;
11442 : }
11443 : /* A read of 1MB should return 1MB bytes (on Samba). */
11444 8 : if (check_read_call(cli, fnum, buf, 0x100000) == false) {
11445 0 : return false;
11446 : }
11447 :
11448 8 : if (check_read_call(cli, fnum, buf, 0x20001) == false) {
11449 0 : return false;
11450 : }
11451 8 : if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11452 0 : return false;
11453 : }
11454 8 : if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11455 0 : return false;
11456 : }
11457 8 : return true;
11458 : }
11459 :
11460 5 : static bool run_large_readx(int dummy)
11461 : {
11462 5 : uint8_t *buf = NULL;
11463 5 : struct cli_state *cli1 = NULL;
11464 5 : struct cli_state *cli2 = NULL;
11465 5 : bool correct = false;
11466 5 : const char *fname = "\\large_readx.dat";
11467 0 : NTSTATUS status;
11468 5 : uint16_t fnum1 = UINT16_MAX;
11469 5 : uint32_t normal_caps = 0;
11470 5 : size_t file_size = 20*1024*1024;
11471 5 : TALLOC_CTX *frame = talloc_stackframe();
11472 0 : size_t i;
11473 0 : struct {
11474 : const char *name;
11475 : enum smb_signing_setting signing_setting;
11476 : enum protocol_types protocol;
11477 5 : } runs[] = {
11478 : {
11479 : .name = "NT1",
11480 : .signing_setting = SMB_SIGNING_IF_REQUIRED,
11481 : .protocol = PROTOCOL_NT1,
11482 : },{
11483 : .name = "NT1 - SIGNING_REQUIRED",
11484 : .signing_setting = SMB_SIGNING_REQUIRED,
11485 : .protocol = PROTOCOL_NT1,
11486 : },
11487 : };
11488 :
11489 5 : printf("starting large_readx test\n");
11490 :
11491 5 : if (!torture_open_connection(&cli1, 0)) {
11492 0 : goto out;
11493 : }
11494 :
11495 5 : normal_caps = smb1cli_conn_capabilities(cli1->conn);
11496 :
11497 5 : if (!(normal_caps & CAP_LARGE_READX)) {
11498 0 : d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11499 : (unsigned int)normal_caps);
11500 0 : goto out;
11501 : }
11502 :
11503 : /* Create a file of size 4MB. */
11504 5 : status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11505 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11506 : 0, 0, &fnum1, NULL);
11507 :
11508 5 : if (!NT_STATUS_IS_OK(status)) {
11509 0 : d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11510 0 : goto out;
11511 : }
11512 :
11513 : /* Write file_size bytes. */
11514 5 : buf = talloc_zero_array(frame, uint8_t, file_size);
11515 5 : if (buf == NULL) {
11516 0 : goto out;
11517 : }
11518 :
11519 5 : status = cli_writeall(cli1,
11520 : fnum1,
11521 : 0,
11522 : buf,
11523 : 0,
11524 : file_size,
11525 : NULL);
11526 5 : if (!NT_STATUS_IS_OK(status)) {
11527 0 : d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11528 0 : goto out;
11529 : }
11530 :
11531 5 : status = cli_close(cli1, fnum1);
11532 5 : if (!NT_STATUS_IS_OK(status)) {
11533 0 : d_printf("cli_close failed: %s\n", nt_errstr(status));
11534 0 : goto out;
11535 : }
11536 :
11537 5 : fnum1 = UINT16_MAX;
11538 :
11539 15 : for (i=0; i < ARRAY_SIZE(runs); i++) {
11540 10 : enum smb_signing_setting saved_signing_setting = signing_state;
11541 10 : uint16_t fnum2 = -1;
11542 :
11543 10 : if (do_encrypt &&
11544 4 : (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11545 : {
11546 2 : d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11547 2 : continue;
11548 : }
11549 :
11550 8 : d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11551 :
11552 8 : signing_state = runs[i].signing_setting;
11553 8 : cli2 = open_nbt_connection();
11554 8 : signing_state = saved_signing_setting;
11555 8 : if (cli2 == NULL) {
11556 0 : goto out;
11557 : }
11558 :
11559 8 : status = smbXcli_negprot(cli2->conn,
11560 8 : cli2->timeout,
11561 : runs[i].protocol,
11562 : runs[i].protocol,
11563 : NULL,
11564 : NULL,
11565 : NULL);
11566 8 : if (!NT_STATUS_IS_OK(status)) {
11567 0 : goto out;
11568 : }
11569 :
11570 8 : status = cli_session_setup_creds(cli2, torture_creds);
11571 8 : if (!NT_STATUS_IS_OK(status)) {
11572 0 : goto out;
11573 : }
11574 :
11575 8 : status = cli_tree_connect(cli2,
11576 : share,
11577 : "?????",
11578 : password);
11579 8 : if (!NT_STATUS_IS_OK(status)) {
11580 0 : goto out;
11581 : }
11582 :
11583 8 : cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11584 :
11585 8 : normal_caps = smb1cli_conn_capabilities(cli2->conn);
11586 :
11587 8 : if (!(normal_caps & CAP_LARGE_READX)) {
11588 0 : d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11589 : (unsigned int)normal_caps);
11590 0 : goto out;
11591 : }
11592 :
11593 8 : if (do_encrypt) {
11594 2 : if (force_cli_encryption(cli2, share) == false) {
11595 0 : goto out;
11596 : }
11597 6 : } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11598 0 : uint16_t major, minor;
11599 0 : uint32_t caplow, caphigh;
11600 :
11601 4 : status = cli_unix_extensions_version(cli2,
11602 : &major, &minor,
11603 : &caplow, &caphigh);
11604 4 : if (!NT_STATUS_IS_OK(status)) {
11605 0 : goto out;
11606 : }
11607 : }
11608 :
11609 8 : status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11610 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11611 : 0, 0, &fnum2, NULL);
11612 8 : if (!NT_STATUS_IS_OK(status)) {
11613 0 : d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11614 0 : goto out;
11615 : }
11616 :
11617 : /* All reads must return less than file_size bytes. */
11618 8 : if (!large_readx_tests(cli2, fnum2, buf)) {
11619 0 : goto out;
11620 : }
11621 :
11622 8 : status = cli_close(cli2, fnum2);
11623 8 : if (!NT_STATUS_IS_OK(status)) {
11624 0 : d_printf("cli_close failed: %s\n", nt_errstr(status));
11625 0 : goto out;
11626 : }
11627 8 : fnum2 = -1;
11628 :
11629 8 : if (!torture_close_connection(cli2)) {
11630 0 : goto out;
11631 : }
11632 8 : cli2 = NULL;
11633 : }
11634 :
11635 5 : correct = true;
11636 5 : printf("Success on large_readx test\n");
11637 :
11638 5 : out:
11639 :
11640 5 : if (cli2) {
11641 0 : if (!torture_close_connection(cli2)) {
11642 0 : correct = false;
11643 : }
11644 : }
11645 :
11646 5 : if (cli1) {
11647 5 : if (fnum1 != UINT16_MAX) {
11648 0 : status = cli_close(cli1, fnum1);
11649 0 : if (!NT_STATUS_IS_OK(status)) {
11650 0 : d_printf("cli_close failed: %s\n", nt_errstr(status));
11651 : }
11652 0 : fnum1 = UINT16_MAX;
11653 : }
11654 :
11655 5 : status = cli_unlink(cli1, fname,
11656 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11657 5 : if (!NT_STATUS_IS_OK(status)) {
11658 0 : printf("unlink failed (%s)\n", nt_errstr(status));
11659 : }
11660 :
11661 5 : if (!torture_close_connection(cli1)) {
11662 0 : correct = false;
11663 : }
11664 : }
11665 :
11666 5 : TALLOC_FREE(frame);
11667 :
11668 5 : printf("finished large_readx test\n");
11669 5 : return correct;
11670 : }
11671 :
11672 24 : static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11673 : const char *mask,
11674 : void *private_data)
11675 : {
11676 24 : uint32_t *p_attr = (uint32_t *)private_data;
11677 :
11678 24 : if (strequal(finfo->name, test_filename)) {
11679 4 : *p_attr = finfo->attr;
11680 : }
11681 :
11682 24 : return NT_STATUS_OK;
11683 : }
11684 :
11685 4 : static bool run_msdfs_attribute(int dummy)
11686 : {
11687 0 : static struct cli_state *cli;
11688 4 : bool correct = false;
11689 4 : uint32_t attr = 0;
11690 0 : NTSTATUS status;
11691 :
11692 4 : printf("Starting MSDFS-ATTRIBUTE test\n");
11693 :
11694 4 : if (test_filename == NULL || test_filename[0] == '\0') {
11695 0 : printf("MSDFS-ATTRIBUTE test "
11696 : "needs -f filename-of-msdfs-link\n");
11697 0 : return false;
11698 : }
11699 :
11700 : /*
11701 : * NB. We use torture_open_connection_flags() not
11702 : * torture_open_connection() as the latter forces
11703 : * SMB1.
11704 : */
11705 4 : if (!torture_open_connection_flags(&cli, 0, 0)) {
11706 0 : return false;
11707 : }
11708 :
11709 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11710 :
11711 4 : status = cli_list(cli,
11712 : "*",
11713 : FILE_ATTRIBUTE_DIRECTORY,
11714 : msdfs_attribute_list_fn,
11715 : &attr);
11716 :
11717 4 : if (!NT_STATUS_IS_OK(status)) {
11718 0 : printf("cli_list failed with %s\n",
11719 : nt_errstr(status));
11720 0 : goto out;
11721 : }
11722 4 : if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11723 0 : printf("file %s should have "
11724 : "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11725 : test_filename,
11726 : (unsigned int)attr);
11727 0 : goto out;
11728 : }
11729 :
11730 4 : if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11731 0 : printf("file %s should have "
11732 : "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11733 : test_filename,
11734 : (unsigned int)attr);
11735 0 : goto out;
11736 : }
11737 :
11738 4 : correct = true;
11739 :
11740 4 : out:
11741 :
11742 4 : torture_close_connection(cli);
11743 4 : return correct;
11744 : }
11745 :
11746 0 : static bool run_cli_echo(int dummy)
11747 : {
11748 0 : struct cli_state *cli;
11749 0 : NTSTATUS status;
11750 :
11751 0 : printf("starting cli_echo test\n");
11752 0 : if (!torture_open_connection(&cli, 0)) {
11753 0 : return false;
11754 : }
11755 0 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11756 :
11757 0 : status = cli_echo(cli, 5, data_blob_const("hello", 5));
11758 :
11759 0 : d_printf("cli_echo returned %s\n", nt_errstr(status));
11760 :
11761 0 : torture_close_connection(cli);
11762 0 : return NT_STATUS_IS_OK(status);
11763 : }
11764 :
11765 14 : static int splice_status(off_t written, void *priv)
11766 : {
11767 14 : return true;
11768 : }
11769 :
11770 7 : static bool run_cli_splice(int dummy)
11771 : {
11772 7 : uint8_t *buf = NULL;
11773 7 : struct cli_state *cli1 = NULL;
11774 7 : bool correct = false;
11775 7 : const char *fname_src = "\\splice_src.dat";
11776 7 : const char *fname_dst = "\\splice_dst.dat";
11777 0 : NTSTATUS status;
11778 7 : uint16_t fnum1 = UINT16_MAX;
11779 7 : uint16_t fnum2 = UINT16_MAX;
11780 7 : size_t file_size = 2*1024*1024;
11781 7 : size_t splice_size = 1*1024*1024 + 713;
11782 0 : uint8_t digest1[16], digest2[16];
11783 7 : off_t written = 0;
11784 7 : size_t nread = 0;
11785 7 : TALLOC_CTX *frame = talloc_stackframe();
11786 :
11787 7 : printf("starting cli_splice test\n");
11788 :
11789 7 : if (!torture_open_connection(&cli1, 0)) {
11790 0 : goto out;
11791 : }
11792 :
11793 7 : cli_unlink(cli1, fname_src,
11794 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11795 7 : cli_unlink(cli1, fname_dst,
11796 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11797 :
11798 : /* Create a file */
11799 7 : status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11800 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11801 : 0, 0, &fnum1, NULL);
11802 :
11803 7 : if (!NT_STATUS_IS_OK(status)) {
11804 0 : d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11805 0 : goto out;
11806 : }
11807 :
11808 : /* Write file_size bytes - must be bigger than splice_size. */
11809 7 : buf = talloc_zero_array(frame, uint8_t, file_size);
11810 7 : if (buf == NULL) {
11811 0 : d_printf("talloc_fail\n");
11812 0 : goto out;
11813 : }
11814 :
11815 : /* Fill it with random numbers. */
11816 7 : generate_random_buffer(buf, file_size);
11817 :
11818 : /* MD5 the first 1MB + 713 bytes. */
11819 7 : gnutls_hash_fast(GNUTLS_DIG_MD5,
11820 : buf,
11821 : splice_size,
11822 : digest1);
11823 :
11824 7 : status = cli_writeall(cli1,
11825 : fnum1,
11826 : 0,
11827 : buf,
11828 : 0,
11829 : file_size,
11830 : NULL);
11831 7 : if (!NT_STATUS_IS_OK(status)) {
11832 0 : d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11833 0 : goto out;
11834 : }
11835 :
11836 7 : status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11837 : FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11838 : 0, 0, &fnum2, NULL);
11839 :
11840 7 : if (!NT_STATUS_IS_OK(status)) {
11841 0 : d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11842 0 : goto out;
11843 : }
11844 :
11845 : /* Now splice 1MB + 713 bytes. */
11846 7 : status = cli_splice(cli1,
11847 : cli1,
11848 : fnum1,
11849 : fnum2,
11850 : splice_size,
11851 : 0,
11852 : 0,
11853 : &written,
11854 : splice_status,
11855 : NULL);
11856 :
11857 7 : if (!NT_STATUS_IS_OK(status)) {
11858 0 : d_printf("cli_splice failed: %s\n", nt_errstr(status));
11859 0 : goto out;
11860 : }
11861 :
11862 : /* Clear the old buffer. */
11863 7 : memset(buf, '\0', file_size);
11864 :
11865 : /* Read the new file. */
11866 7 : status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11867 7 : if (!NT_STATUS_IS_OK(status)) {
11868 0 : d_printf("cli_read failed: %s\n", nt_errstr(status));
11869 0 : goto out;
11870 : }
11871 7 : if (nread != splice_size) {
11872 0 : d_printf("bad read of 0x%x, should be 0x%x\n",
11873 : (unsigned int)nread,
11874 : (unsigned int)splice_size);
11875 0 : goto out;
11876 : }
11877 :
11878 : /* MD5 the first 1MB + 713 bytes. */
11879 7 : gnutls_hash_fast(GNUTLS_DIG_MD5,
11880 : buf,
11881 : splice_size,
11882 : digest2);
11883 :
11884 : /* Must be the same. */
11885 7 : if (memcmp(digest1, digest2, 16) != 0) {
11886 0 : d_printf("bad MD5 compare\n");
11887 0 : goto out;
11888 : }
11889 :
11890 7 : correct = true;
11891 7 : printf("Success on cli_splice test\n");
11892 :
11893 7 : out:
11894 :
11895 7 : if (cli1) {
11896 7 : if (fnum1 != UINT16_MAX) {
11897 7 : cli_close(cli1, fnum1);
11898 : }
11899 7 : if (fnum2 != UINT16_MAX) {
11900 7 : cli_close(cli1, fnum2);
11901 : }
11902 :
11903 7 : cli_unlink(cli1, fname_src,
11904 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11905 7 : cli_unlink(cli1, fname_dst,
11906 : FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11907 :
11908 7 : if (!torture_close_connection(cli1)) {
11909 0 : correct = false;
11910 : }
11911 : }
11912 :
11913 7 : TALLOC_FREE(frame);
11914 7 : return correct;
11915 : }
11916 :
11917 4 : static bool run_uid_regression_test(int dummy)
11918 : {
11919 0 : static struct cli_state *cli;
11920 0 : int16_t old_vuid;
11921 0 : int32_t old_cnum;
11922 4 : bool correct = True;
11923 4 : struct smbXcli_tcon *tcon_copy = NULL;
11924 0 : NTSTATUS status;
11925 :
11926 4 : printf("starting uid regression test\n");
11927 :
11928 4 : if (!torture_open_connection(&cli, 0)) {
11929 0 : return False;
11930 : }
11931 :
11932 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
11933 :
11934 : /* Ok - now save then logoff our current user. */
11935 4 : old_vuid = cli_state_get_uid(cli);
11936 :
11937 4 : status = cli_ulogoff(cli);
11938 4 : if (!NT_STATUS_IS_OK(status)) {
11939 0 : d_printf("(%s) cli_ulogoff failed: %s\n",
11940 : __location__, nt_errstr(status));
11941 0 : correct = false;
11942 0 : goto out;
11943 : }
11944 :
11945 4 : cli_state_set_uid(cli, old_vuid);
11946 :
11947 : /* Try an operation. */
11948 4 : status = cli_mkdir(cli, "\\uid_reg_test");
11949 4 : if (NT_STATUS_IS_OK(status)) {
11950 0 : d_printf("(%s) cli_mkdir succeeded\n",
11951 : __location__);
11952 0 : correct = false;
11953 0 : goto out;
11954 : } else {
11955 : /* Should be bad uid. */
11956 4 : if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11957 4 : NT_STATUS_USER_SESSION_DELETED)) {
11958 0 : correct = false;
11959 0 : goto out;
11960 : }
11961 : }
11962 :
11963 4 : old_cnum = cli_state_get_tid(cli);
11964 : /*
11965 : * This is an SMB1-only test.
11966 : * Copy the tcon, not "save/restore".
11967 : *
11968 : * In SMB1 the cli_tdis() below frees
11969 : * cli->smb1.tcon so we need a copy
11970 : * of the struct to put back for the
11971 : * second tdis call with invalid vuid.
11972 : *
11973 : * This is a test-only hack. Real client code
11974 : * uses cli_state_save_tcon_share()/cli_state_restore_tcon_share().
11975 : */
11976 4 : tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
11977 4 : if (tcon_copy == NULL) {
11978 0 : correct = false;
11979 0 : goto out;
11980 : }
11981 :
11982 : /* Now try a SMBtdis with the invalid vuid set to zero. */
11983 4 : cli_state_set_uid(cli, 0);
11984 :
11985 : /* This should succeed. */
11986 4 : status = cli_tdis(cli);
11987 :
11988 4 : if (NT_STATUS_IS_OK(status)) {
11989 4 : d_printf("First tdis with invalid vuid should succeed.\n");
11990 : } else {
11991 0 : d_printf("First tdis failed (%s)\n", nt_errstr(status));
11992 0 : correct = false;
11993 0 : cli->smb1.tcon = tcon_copy;
11994 0 : goto out;
11995 : }
11996 :
11997 4 : cli->smb1.tcon = tcon_copy;
11998 4 : cli_state_set_uid(cli, old_vuid);
11999 4 : cli_state_set_tid(cli, old_cnum);
12000 :
12001 : /* This should fail. */
12002 4 : status = cli_tdis(cli);
12003 4 : if (NT_STATUS_IS_OK(status)) {
12004 0 : d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
12005 0 : correct = false;
12006 0 : goto out;
12007 : } else {
12008 : /* Should be bad tid. */
12009 4 : if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
12010 4 : NT_STATUS_NETWORK_NAME_DELETED)) {
12011 0 : correct = false;
12012 0 : goto out;
12013 : }
12014 : }
12015 :
12016 4 : cli_rmdir(cli, "\\uid_reg_test");
12017 :
12018 4 : out:
12019 :
12020 4 : cli_shutdown(cli);
12021 4 : return correct;
12022 : }
12023 :
12024 :
12025 : static const char *illegal_chars = "*\\/?<>|\":";
12026 : static char force_shortname_chars[] = " +,.[];=\177";
12027 :
12028 8 : static NTSTATUS shortname_del_fn(struct file_info *finfo,
12029 : const char *mask, void *state)
12030 : {
12031 8 : struct cli_state *pcli = (struct cli_state *)state;
12032 0 : fstring fname;
12033 8 : NTSTATUS status = NT_STATUS_OK;
12034 :
12035 8 : slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
12036 :
12037 8 : if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
12038 8 : return NT_STATUS_OK;
12039 :
12040 0 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
12041 0 : status = cli_rmdir(pcli, fname);
12042 0 : if (!NT_STATUS_IS_OK(status)) {
12043 0 : printf("del_fn: failed to rmdir %s\n,", fname );
12044 : }
12045 : } else {
12046 0 : status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12047 0 : if (!NT_STATUS_IS_OK(status)) {
12048 0 : printf("del_fn: failed to unlink %s\n,", fname );
12049 : }
12050 : }
12051 0 : return status;
12052 : }
12053 :
12054 : struct sn_state {
12055 : int matched;
12056 : int i;
12057 : bool val;
12058 : };
12059 :
12060 348 : static NTSTATUS shortname_list_fn(struct file_info *finfo,
12061 : const char *name, void *state)
12062 : {
12063 348 : struct sn_state *s = (struct sn_state *)state;
12064 348 : int i = s->i;
12065 :
12066 : #if 0
12067 : printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
12068 : i, finfo->name, finfo->short_name);
12069 : #endif
12070 :
12071 348 : if (strchr(force_shortname_chars, i)) {
12072 36 : if (!finfo->short_name) {
12073 : /* Shortname not created when it should be. */
12074 0 : d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
12075 : __location__, finfo->name, i);
12076 0 : s->val = true;
12077 : }
12078 312 : } else if (finfo->short_name){
12079 : /* Shortname created when it should not be. */
12080 0 : d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
12081 : __location__, finfo->short_name, finfo->name);
12082 0 : s->val = true;
12083 : }
12084 348 : s->matched += 1;
12085 348 : return NT_STATUS_OK;
12086 : }
12087 :
12088 4 : static bool run_shortname_test(int dummy)
12089 : {
12090 0 : static struct cli_state *cli;
12091 4 : bool correct = True;
12092 0 : int i;
12093 0 : struct sn_state s;
12094 0 : char fname[40];
12095 0 : NTSTATUS status;
12096 :
12097 4 : printf("starting shortname test\n");
12098 :
12099 4 : if (!torture_open_connection(&cli, 0)) {
12100 0 : return False;
12101 : }
12102 :
12103 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
12104 :
12105 4 : cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12106 4 : cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12107 4 : cli_rmdir(cli, "\\shortname");
12108 :
12109 4 : status = cli_mkdir(cli, "\\shortname");
12110 4 : if (!NT_STATUS_IS_OK(status)) {
12111 0 : d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
12112 : __location__, nt_errstr(status));
12113 0 : correct = false;
12114 0 : goto out;
12115 : }
12116 :
12117 4 : if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
12118 0 : correct = false;
12119 0 : goto out;
12120 : }
12121 4 : if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
12122 0 : correct = false;
12123 0 : goto out;
12124 : }
12125 :
12126 4 : s.val = false;
12127 :
12128 388 : for (i = 32; i < 128; i++) {
12129 384 : uint16_t fnum = (uint16_t)-1;
12130 :
12131 384 : s.i = i;
12132 :
12133 384 : if (strchr(illegal_chars, i)) {
12134 36 : continue;
12135 : }
12136 348 : fname[15] = i;
12137 :
12138 348 : status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12139 : FILE_SHARE_READ|FILE_SHARE_WRITE,
12140 : FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12141 348 : if (!NT_STATUS_IS_OK(status)) {
12142 0 : d_printf("(%s) cli_nt_create of %s failed: %s\n",
12143 : __location__, fname, nt_errstr(status));
12144 0 : correct = false;
12145 0 : goto out;
12146 : }
12147 348 : cli_close(cli, fnum);
12148 :
12149 348 : s.matched = 0;
12150 348 : status = cli_list(cli, "\\shortname\\test*.*", 0,
12151 : shortname_list_fn, &s);
12152 348 : if (s.matched != 1) {
12153 0 : d_printf("(%s) failed to list %s: %s\n",
12154 : __location__, fname, nt_errstr(status));
12155 0 : correct = false;
12156 0 : goto out;
12157 : }
12158 :
12159 348 : status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12160 348 : if (!NT_STATUS_IS_OK(status)) {
12161 0 : d_printf("(%s) failed to delete %s: %s\n",
12162 : __location__, fname, nt_errstr(status));
12163 0 : correct = false;
12164 0 : goto out;
12165 : }
12166 :
12167 348 : if (s.val) {
12168 0 : correct = false;
12169 0 : goto out;
12170 : }
12171 : }
12172 :
12173 4 : out:
12174 :
12175 4 : cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12176 4 : cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12177 4 : cli_rmdir(cli, "\\shortname");
12178 4 : torture_close_connection(cli);
12179 4 : return correct;
12180 : }
12181 :
12182 : TLDAPRC callback_code;
12183 :
12184 478 : static void pagedsearch_cb(struct tevent_req *req)
12185 : {
12186 0 : TLDAPRC rc;
12187 0 : struct tldap_message *msg;
12188 0 : char *dn;
12189 :
12190 478 : rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12191 478 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12192 0 : d_printf("tldap_search_paged_recv failed: %s\n",
12193 : tldap_rc2string(rc));
12194 0 : callback_code = rc;
12195 0 : return;
12196 : }
12197 478 : if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12198 8 : TALLOC_FREE(msg);
12199 8 : return;
12200 : }
12201 470 : if (!tldap_entry_dn(msg, &dn)) {
12202 0 : d_printf("tldap_entry_dn failed\n");
12203 0 : return;
12204 : }
12205 470 : d_printf("%s\n", dn);
12206 470 : TALLOC_FREE(msg);
12207 : }
12208 :
12209 : enum tldap_extended_val {
12210 : EXTENDED_ZERO = 0,
12211 : EXTENDED_ONE = 1,
12212 : EXTENDED_NONE = 2,
12213 : };
12214 :
12215 : /*
12216 : * Construct an extended dn control with either no value, 0 or 1
12217 : *
12218 : * No value and 0 are equivalent (non-hyphenated GUID)
12219 : * 1 has the hyphenated GUID
12220 : */
12221 : static struct tldap_control *
12222 6 : tldap_build_extended_control(enum tldap_extended_val val)
12223 : {
12224 0 : struct tldap_control empty_control;
12225 0 : struct asn1_data *data;
12226 :
12227 6 : ZERO_STRUCT(empty_control);
12228 :
12229 6 : if (val != EXTENDED_NONE) {
12230 4 : data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12231 :
12232 4 : if (!data) {
12233 0 : return NULL;
12234 : }
12235 :
12236 4 : if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12237 0 : return NULL;
12238 : }
12239 :
12240 4 : if (!asn1_write_Integer(data, (int)val)) {
12241 0 : return NULL;
12242 : }
12243 :
12244 4 : if (!asn1_pop_tag(data)) {
12245 0 : return NULL;
12246 : }
12247 :
12248 4 : if (!asn1_blob(data, &empty_control.value)) {
12249 0 : return NULL;
12250 : }
12251 : }
12252 :
12253 6 : empty_control.oid = "1.2.840.113556.1.4.529";
12254 6 : empty_control.critical = true;
12255 :
12256 6 : return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12257 :
12258 : }
12259 :
12260 6 : static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12261 : enum tldap_extended_val control_val)
12262 : {
12263 6 : struct tldap_control *control = tldap_build_extended_control(control_val);
12264 6 : char *dn = NULL;
12265 0 : struct tldap_message **msg;
12266 0 : TLDAPRC rc;
12267 :
12268 6 : rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12269 : "(objectClass=*)", NULL, 0, 0,
12270 : control, 1, NULL,
12271 : 0, 0, 0, 0, talloc_tos(), &msg);
12272 6 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12273 0 : d_printf("tldap_search for domain DN failed: %s\n",
12274 : tldap_errstr(talloc_tos(), ld, rc));
12275 0 : return false;
12276 : }
12277 :
12278 6 : if (!tldap_entry_dn(msg[0], &dn)) {
12279 0 : d_printf("tldap_search domain DN fetch failed: %s\n",
12280 : tldap_errstr(talloc_tos(), ld, rc));
12281 0 : return false;
12282 : }
12283 :
12284 6 : d_printf("%s\n", dn);
12285 : {
12286 0 : uint32_t time_low;
12287 0 : uint32_t time_mid, time_hi_and_version;
12288 0 : uint32_t clock_seq[2];
12289 0 : uint32_t node[6];
12290 0 : char next;
12291 :
12292 6 : switch (control_val) {
12293 4 : case EXTENDED_NONE:
12294 : case EXTENDED_ZERO:
12295 : /*
12296 : * When reading GUIDs with hyphens, scanf will treat
12297 : * hyphen as a hex character (and counts as part of the
12298 : * width). This creates leftover GUID string which we
12299 : * check will for with 'next' and closing '>'.
12300 : */
12301 4 : if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12302 : &time_low, &time_mid,
12303 : &time_hi_and_version, &clock_seq[0],
12304 : &clock_seq[1], &node[0], &node[1],
12305 : &node[2], &node[3], &node[4],
12306 : &node[5], &next)) {
12307 : /* This GUID is good */
12308 : } else {
12309 0 : d_printf("GUID format in control (no hyphens) doesn't match output\n");
12310 0 : return false;
12311 : }
12312 :
12313 4 : break;
12314 2 : case EXTENDED_ONE:
12315 2 : if (12 == sscanf(dn,
12316 : "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12317 : &time_low, &time_mid,
12318 : &time_hi_and_version, &clock_seq[0],
12319 : &clock_seq[1], &node[0], &node[1],
12320 : &node[2], &node[3], &node[4],
12321 : &node[5], &next)) {
12322 : /* This GUID is good */
12323 : } else {
12324 0 : d_printf("GUID format in control (with hyphens) doesn't match output\n");
12325 0 : return false;
12326 : }
12327 :
12328 2 : break;
12329 0 : default:
12330 0 : return false;
12331 : }
12332 : }
12333 :
12334 6 : return true;
12335 : }
12336 :
12337 2 : static bool run_tldap(int dummy)
12338 : {
12339 0 : struct tldap_context *ld;
12340 0 : int fd;
12341 0 : TLDAPRC rc;
12342 0 : NTSTATUS status;
12343 0 : struct sockaddr_storage addr;
12344 0 : struct tevent_context *ev;
12345 0 : struct tevent_req *req;
12346 0 : char *basedn;
12347 0 : const char *filter;
12348 :
12349 2 : if (!resolve_name(host, &addr, 0, false)) {
12350 0 : d_printf("could not find host %s\n", host);
12351 0 : return false;
12352 : }
12353 2 : status = open_socket_out(&addr, 389, 9999, &fd);
12354 2 : if (!NT_STATUS_IS_OK(status)) {
12355 0 : d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12356 0 : return false;
12357 : }
12358 :
12359 2 : ld = tldap_context_create(talloc_tos(), fd);
12360 2 : if (ld == NULL) {
12361 0 : close(fd);
12362 0 : d_printf("tldap_context_create failed\n");
12363 0 : return false;
12364 : }
12365 :
12366 2 : rc = tldap_fetch_rootdse(ld);
12367 2 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12368 0 : d_printf("tldap_fetch_rootdse failed: %s\n",
12369 : tldap_errstr(talloc_tos(), ld, rc));
12370 0 : return false;
12371 : }
12372 :
12373 2 : basedn = tldap_talloc_single_attribute(
12374 : tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12375 2 : if (basedn == NULL) {
12376 0 : d_printf("no defaultNamingContext\n");
12377 0 : return false;
12378 : }
12379 2 : d_printf("defaultNamingContext: %s\n", basedn);
12380 :
12381 2 : ev = samba_tevent_context_init(talloc_tos());
12382 2 : if (ev == NULL) {
12383 0 : d_printf("tevent_context_init failed\n");
12384 0 : return false;
12385 : }
12386 :
12387 2 : rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12388 : loadparm_init_s3(talloc_tos(),
12389 : loadparm_s3_helpers()),
12390 : GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12391 :
12392 2 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12393 0 : d_printf("tldap_gensec_bind failed\n");
12394 0 : return false;
12395 : }
12396 :
12397 2 : callback_code = TLDAP_SUCCESS;
12398 :
12399 2 : req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12400 : TLDAP_SCOPE_SUB, "(objectclass=*)",
12401 : NULL, 0, 0,
12402 : NULL, 0, NULL, 0, 0, 0, 0, 5);
12403 2 : if (req == NULL) {
12404 0 : d_printf("tldap_search_paged_send failed\n");
12405 0 : return false;
12406 : }
12407 2 : tevent_req_set_callback(req, pagedsearch_cb, NULL);
12408 :
12409 2 : tevent_req_poll(req, ev);
12410 :
12411 2 : TALLOC_FREE(req);
12412 :
12413 2 : rc = callback_code;
12414 :
12415 2 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12416 0 : d_printf("tldap_search with paging failed: %s\n",
12417 : tldap_errstr(talloc_tos(), ld, rc));
12418 0 : return false;
12419 : }
12420 :
12421 : /* test search filters against rootDSE */
12422 2 : filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12423 : "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12424 :
12425 2 : rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12426 : NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12427 : talloc_tos(), NULL);
12428 2 : if (!TLDAP_RC_IS_SUCCESS(rc)) {
12429 0 : d_printf("tldap_search with complex filter failed: %s\n",
12430 : tldap_errstr(talloc_tos(), ld, rc));
12431 0 : return false;
12432 : }
12433 :
12434 : /*
12435 : * Tests to check for regression of:
12436 : *
12437 : * https://bugzilla.samba.org/show_bug.cgi?id=14029
12438 : *
12439 : * TLDAP used here to pick apart the original string DN (with GUID)
12440 : */
12441 2 : if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12442 0 : d_printf("tldap_search with extended dn (no val) failed: %s\n",
12443 : tldap_errstr(talloc_tos(), ld, rc));
12444 0 : return false;
12445 : }
12446 2 : if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12447 0 : d_printf("tldap_search with extended dn (0) failed: %s\n",
12448 : tldap_errstr(talloc_tos(), ld, rc));
12449 0 : return false;
12450 : }
12451 2 : if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12452 0 : d_printf("tldap_search with extended dn (1) failed: %s\n",
12453 : tldap_errstr(talloc_tos(), ld, rc));
12454 0 : return false;
12455 : }
12456 :
12457 2 : TALLOC_FREE(ld);
12458 2 : return true;
12459 : }
12460 :
12461 : /* Torture test to ensure no regression of :
12462 : https://bugzilla.samba.org/show_bug.cgi?id=7084
12463 : */
12464 :
12465 4 : static bool run_dir_createtime(int dummy)
12466 : {
12467 0 : struct cli_state *cli;
12468 4 : const char *dname = "\\testdir_createtime";
12469 4 : const char *fname = "\\testdir_createtime\\testfile";
12470 0 : NTSTATUS status;
12471 0 : struct timespec create_time;
12472 0 : struct timespec create_time1;
12473 0 : uint16_t fnum;
12474 4 : bool ret = false;
12475 0 : uint64_t ino;
12476 :
12477 4 : if (!torture_open_connection(&cli, 0)) {
12478 0 : return false;
12479 : }
12480 :
12481 4 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12482 : /* Ensure ino is zero, SMB2 gets a real one. */
12483 0 : ino = 0;
12484 : } else {
12485 : /* Ensure ino is -1, SMB1 never gets a real one. */
12486 4 : ino = (uint64_t)-1;
12487 : }
12488 :
12489 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12490 4 : cli_rmdir(cli, dname);
12491 :
12492 4 : status = cli_mkdir(cli, dname);
12493 4 : if (!NT_STATUS_IS_OK(status)) {
12494 0 : printf("mkdir failed: %s\n", nt_errstr(status));
12495 0 : goto out;
12496 : }
12497 :
12498 4 : status = cli_qpathinfo2(cli,
12499 : dname,
12500 : &create_time,
12501 : NULL,
12502 : NULL,
12503 : NULL,
12504 : NULL,
12505 : NULL,
12506 : &ino,
12507 : NULL);
12508 4 : if (!NT_STATUS_IS_OK(status)) {
12509 0 : printf("cli_qpathinfo2 returned %s\n",
12510 : nt_errstr(status));
12511 0 : goto out;
12512 : }
12513 :
12514 4 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12515 : /* SMB2 should always return an inode. */
12516 0 : if (ino == 0) {
12517 0 : printf("SMB2 bad inode (0)\n");
12518 0 : goto out;
12519 : }
12520 : } else {
12521 : /* SMB1 must always return zero here. */
12522 4 : if (ino != 0) {
12523 0 : printf("SMB1 bad inode (!0)\n");
12524 0 : goto out;
12525 : }
12526 : }
12527 :
12528 : /* Sleep 3 seconds, then create a file. */
12529 4 : sleep(3);
12530 :
12531 4 : status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12532 : DENY_NONE, &fnum);
12533 4 : if (!NT_STATUS_IS_OK(status)) {
12534 0 : printf("cli_openx failed: %s\n", nt_errstr(status));
12535 0 : goto out;
12536 : }
12537 :
12538 4 : status = cli_qpathinfo2(cli,
12539 : dname,
12540 : &create_time1,
12541 : NULL,
12542 : NULL,
12543 : NULL,
12544 : NULL,
12545 : NULL,
12546 : NULL,
12547 : NULL);
12548 4 : if (!NT_STATUS_IS_OK(status)) {
12549 0 : printf("cli_qpathinfo2 (2) returned %s\n",
12550 : nt_errstr(status));
12551 0 : goto out;
12552 : }
12553 :
12554 4 : if (timespec_compare(&create_time1, &create_time)) {
12555 0 : printf("run_dir_createtime: create time was updated (error)\n");
12556 : } else {
12557 4 : printf("run_dir_createtime: create time was not updated (correct)\n");
12558 4 : ret = true;
12559 : }
12560 :
12561 4 : out:
12562 :
12563 4 : cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12564 4 : cli_rmdir(cli, dname);
12565 4 : if (!torture_close_connection(cli)) {
12566 0 : ret = false;
12567 : }
12568 4 : return ret;
12569 : }
12570 :
12571 :
12572 4 : static bool run_streamerror(int dummy)
12573 : {
12574 0 : struct cli_state *cli;
12575 4 : const char *dname = "\\testdir_streamerror";
12576 4 : const char *streamname =
12577 : "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12578 0 : NTSTATUS status;
12579 0 : time_t change_time, access_time, write_time;
12580 0 : off_t size;
12581 0 : uint16_t fnum;
12582 0 : uint32_t attr;
12583 4 : bool ret = true;
12584 :
12585 4 : if (!torture_open_connection(&cli, 0)) {
12586 0 : return false;
12587 : }
12588 :
12589 4 : torture_deltree(cli, dname);
12590 :
12591 4 : status = cli_mkdir(cli, dname);
12592 4 : if (!NT_STATUS_IS_OK(status)) {
12593 0 : printf("mkdir failed: %s\n", nt_errstr(status));
12594 0 : return false;
12595 : }
12596 :
12597 4 : status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12598 : &write_time, &size, &attr);
12599 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12600 0 : printf("pathinfo returned %s, expected "
12601 : "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12602 : nt_errstr(status));
12603 0 : ret = false;
12604 : }
12605 :
12606 4 : status = cli_ntcreate(cli, streamname, 0x16,
12607 : FILE_READ_DATA|FILE_READ_EA|
12608 : FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12609 : FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12610 : FILE_OPEN, 0, 0, &fnum, NULL);
12611 :
12612 4 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12613 0 : printf("ntcreate returned %s, expected "
12614 : "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12615 : nt_errstr(status));
12616 0 : ret = false;
12617 : }
12618 :
12619 :
12620 4 : cli_rmdir(cli, dname);
12621 4 : return ret;
12622 : }
12623 :
12624 : struct pidtest_state {
12625 : bool success;
12626 : uint16_t vwv[1];
12627 : DATA_BLOB data;
12628 : };
12629 :
12630 : static void pid_echo_done(struct tevent_req *subreq);
12631 :
12632 4 : static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12633 : struct tevent_context *ev,
12634 : struct cli_state *cli)
12635 : {
12636 0 : struct tevent_req *req, *subreq;
12637 0 : struct pidtest_state *state;
12638 :
12639 4 : req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12640 4 : if (req == NULL) {
12641 0 : return NULL;
12642 : }
12643 :
12644 4 : SSVAL(state->vwv, 0, 1);
12645 4 : state->data = data_blob_const("hello", 5);
12646 :
12647 4 : subreq = smb1cli_req_send(state,
12648 : ev,
12649 : cli->conn,
12650 : SMBecho,
12651 : 0, 0, /* *_flags */
12652 : 0, 0, /* *_flags2 */
12653 4 : cli->timeout,
12654 : 0xDEADBEEF, /* pid */
12655 : NULL, /* tcon */
12656 : NULL, /* session */
12657 4 : ARRAY_SIZE(state->vwv), state->vwv,
12658 4 : state->data.length, state->data.data);
12659 :
12660 4 : if (tevent_req_nomem(subreq, req)) {
12661 0 : return tevent_req_post(req, ev);
12662 : }
12663 4 : tevent_req_set_callback(subreq, pid_echo_done, req);
12664 4 : return req;
12665 : }
12666 :
12667 4 : static void pid_echo_done(struct tevent_req *subreq)
12668 : {
12669 4 : struct tevent_req *req = tevent_req_callback_data(
12670 : subreq, struct tevent_req);
12671 4 : struct pidtest_state *state = tevent_req_data(
12672 : req, struct pidtest_state);
12673 0 : NTSTATUS status;
12674 0 : uint32_t num_bytes;
12675 4 : uint8_t *bytes = NULL;
12676 4 : struct iovec *recv_iov = NULL;
12677 4 : uint8_t *phdr = NULL;
12678 4 : uint16_t pidlow = 0;
12679 4 : uint16_t pidhigh = 0;
12680 4 : struct smb1cli_req_expected_response expected[] = {
12681 : {
12682 : .status = NT_STATUS_OK,
12683 : .wct = 1,
12684 : },
12685 : };
12686 :
12687 4 : status = smb1cli_req_recv(subreq, state,
12688 : &recv_iov,
12689 : &phdr,
12690 : NULL, /* pwct */
12691 : NULL, /* pvwv */
12692 : NULL, /* pvwv_offset */
12693 : &num_bytes,
12694 : &bytes,
12695 : NULL, /* pbytes_offset */
12696 : NULL, /* pinbuf */
12697 : expected, ARRAY_SIZE(expected));
12698 :
12699 4 : TALLOC_FREE(subreq);
12700 :
12701 4 : if (!NT_STATUS_IS_OK(status)) {
12702 0 : tevent_req_nterror(req, status);
12703 0 : return;
12704 : }
12705 :
12706 4 : if (num_bytes != state->data.length) {
12707 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12708 0 : return;
12709 : }
12710 :
12711 4 : if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12712 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12713 0 : return;
12714 : }
12715 :
12716 : /* Check pid low/high == DEADBEEF */
12717 4 : pidlow = SVAL(phdr, HDR_PID);
12718 4 : if (pidlow != 0xBEEF){
12719 0 : printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12720 : (unsigned int)pidlow);
12721 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12722 0 : return;
12723 : }
12724 4 : pidhigh = SVAL(phdr, HDR_PIDHIGH);
12725 4 : if (pidhigh != 0xDEAD){
12726 0 : printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12727 : (unsigned int)pidhigh);
12728 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12729 0 : return;
12730 : }
12731 :
12732 4 : tevent_req_done(req);
12733 : }
12734 :
12735 4 : static NTSTATUS pid_echo_recv(struct tevent_req *req)
12736 : {
12737 4 : return tevent_req_simple_recv_ntstatus(req);
12738 : }
12739 :
12740 4 : static bool run_pidhigh(int dummy)
12741 : {
12742 4 : bool success = false;
12743 4 : struct cli_state *cli = NULL;
12744 0 : NTSTATUS status;
12745 4 : struct tevent_context *ev = NULL;
12746 4 : struct tevent_req *req = NULL;
12747 4 : TALLOC_CTX *frame = talloc_stackframe();
12748 :
12749 4 : printf("starting pid high test\n");
12750 4 : if (!torture_open_connection(&cli, 0)) {
12751 0 : return false;
12752 : }
12753 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
12754 :
12755 4 : ev = samba_tevent_context_init(frame);
12756 4 : if (ev == NULL) {
12757 0 : goto fail;
12758 : }
12759 :
12760 4 : req = pid_echo_send(frame, ev, cli);
12761 4 : if (req == NULL) {
12762 0 : goto fail;
12763 : }
12764 :
12765 4 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12766 0 : goto fail;
12767 : }
12768 :
12769 4 : status = pid_echo_recv(req);
12770 4 : if (NT_STATUS_IS_OK(status)) {
12771 4 : printf("pid high test ok\n");
12772 4 : success = true;
12773 : }
12774 :
12775 0 : fail:
12776 :
12777 4 : TALLOC_FREE(frame);
12778 4 : torture_close_connection(cli);
12779 4 : return success;
12780 : }
12781 :
12782 : /*
12783 : Test Windows open on a bad POSIX symlink.
12784 : */
12785 4 : static bool run_symlink_open_test(int dummy)
12786 : {
12787 0 : static struct cli_state *cli;
12788 4 : const char *fname = "non_existant_file";
12789 4 : const char *sname = "dangling_symlink";
12790 4 : uint16_t fnum = (uint16_t)-1;
12791 4 : bool correct = false;
12792 0 : NTSTATUS status;
12793 4 : TALLOC_CTX *frame = NULL;
12794 :
12795 4 : frame = talloc_stackframe();
12796 :
12797 4 : printf("Starting Windows bad symlink open test\n");
12798 :
12799 4 : if (!torture_open_connection(&cli, 0)) {
12800 0 : TALLOC_FREE(frame);
12801 0 : return false;
12802 : }
12803 :
12804 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
12805 :
12806 4 : status = torture_setup_unix_extensions(cli);
12807 4 : if (!NT_STATUS_IS_OK(status)) {
12808 0 : TALLOC_FREE(frame);
12809 0 : return false;
12810 : }
12811 :
12812 : /* Ensure nothing exists. */
12813 4 : cli_setatr(cli, fname, 0, 0);
12814 4 : cli_posix_unlink(cli, fname);
12815 4 : cli_setatr(cli, sname, 0, 0);
12816 4 : cli_posix_unlink(cli, sname);
12817 :
12818 : /* Create a symlink pointing nowhere. */
12819 4 : status = cli_posix_symlink(cli, fname, sname);
12820 4 : if (!NT_STATUS_IS_OK(status)) {
12821 0 : printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12822 : sname,
12823 : fname,
12824 : nt_errstr(status));
12825 0 : goto out;
12826 : }
12827 :
12828 : /* Now ensure that a Windows open doesn't hang. */
12829 4 : status = cli_ntcreate(cli,
12830 : sname,
12831 : 0,
12832 : FILE_READ_DATA|FILE_WRITE_DATA,
12833 : 0,
12834 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12835 : FILE_OPEN_IF,
12836 : 0x0,
12837 : 0x0,
12838 : &fnum,
12839 : NULL);
12840 :
12841 : /*
12842 : * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12843 : * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12844 : * we use O_NOFOLLOW on the server or not.
12845 : */
12846 4 : if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12847 0 : NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12848 : {
12849 4 : correct = true;
12850 : } else {
12851 0 : printf("cli_ntcreate of %s returned %s - should return"
12852 : " either (%s) or (%s)\n",
12853 : sname,
12854 : nt_errstr(status),
12855 0 : nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12856 0 : nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12857 0 : goto out;
12858 : }
12859 :
12860 4 : correct = true;
12861 :
12862 4 : out:
12863 :
12864 4 : if (fnum != (uint16_t)-1) {
12865 0 : cli_close(cli, fnum);
12866 0 : fnum = (uint16_t)-1;
12867 : }
12868 :
12869 4 : cli_setatr(cli, sname, 0, 0);
12870 4 : cli_posix_unlink(cli, sname);
12871 4 : cli_setatr(cli, fname, 0, 0);
12872 4 : cli_posix_unlink(cli, fname);
12873 :
12874 4 : if (!torture_close_connection(cli)) {
12875 0 : correct = false;
12876 : }
12877 :
12878 4 : TALLOC_FREE(frame);
12879 4 : return correct;
12880 : }
12881 :
12882 16 : static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12883 : const char *name,
12884 : void *state)
12885 : {
12886 16 : char **mangled_name_return = (char **)state;
12887 16 : bool is_mangled = strchr(finfo->name, '~');
12888 :
12889 16 : if (is_mangled) {
12890 8 : *mangled_name_return = talloc_strdup(NULL, finfo->name);
12891 8 : if (*mangled_name_return == NULL) {
12892 0 : return NT_STATUS_NO_MEMORY;
12893 : }
12894 : }
12895 16 : return NT_STATUS_OK;
12896 : }
12897 :
12898 4 : static bool run_smb1_wild_mangle_unlink_test(int dummy)
12899 : {
12900 0 : static struct cli_state *cli_posix = NULL;
12901 0 : static struct cli_state *cli = NULL;
12902 4 : uint16_t fnum = (uint16_t)-1;
12903 4 : bool correct = false;
12904 4 : const char *dname = "smb1_wild_mangle_unlink";
12905 4 : const char *aname = "smb1_wild_mangle_unlink/a";
12906 4 : const char *star_name = "smb1_wild_mangle_unlink/*";
12907 4 : char *windows_unlink_name = NULL;
12908 4 : char *mangled_name = NULL;
12909 0 : NTSTATUS status;
12910 :
12911 4 : printf("Starting SMB1 wild mangle unlink test\n");
12912 :
12913 : /* Open a Windows connection. */
12914 4 : if (!torture_open_connection(&cli, 0)) {
12915 0 : return false;
12916 : }
12917 :
12918 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
12919 :
12920 : /* Open a POSIX connection. */
12921 4 : if (!torture_open_connection(&cli_posix, 0)) {
12922 0 : goto out;
12923 : }
12924 :
12925 4 : smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12926 :
12927 4 : status = torture_setup_unix_extensions(cli_posix);
12928 4 : if (!NT_STATUS_IS_OK(status)) {
12929 0 : printf("server doesn't support POSIX\n");
12930 0 : goto out;
12931 : }
12932 :
12933 : /* Start fresh. */
12934 4 : torture_deltree(cli, dname);
12935 :
12936 : /*
12937 : * Create two files - 'a' and '*'.
12938 : * We need POSIX extensions for this as '*'
12939 : * is not a valid Windows name.
12940 : */
12941 :
12942 4 : status = cli_mkdir(cli, dname);
12943 4 : if (!NT_STATUS_IS_OK(status)) {
12944 0 : printf("cli_mkdir of %s returned %s\n",
12945 : dname,
12946 : nt_errstr(status));
12947 0 : goto out;
12948 : }
12949 :
12950 4 : status = cli_posix_open(cli_posix,
12951 : aname,
12952 : O_RDWR|O_CREAT|O_EXCL,
12953 : 0660,
12954 : &fnum);
12955 4 : if (!NT_STATUS_IS_OK(status)) {
12956 0 : printf("cli_posix_open (create) of %s returned %s\n",
12957 : aname,
12958 : nt_errstr(status));
12959 0 : goto out;
12960 : }
12961 4 : status = cli_close(cli_posix, fnum);
12962 4 : if (!NT_STATUS_IS_OK(status)) {
12963 0 : goto out;
12964 : }
12965 4 : status = cli_posix_open(cli_posix,
12966 : star_name,
12967 : O_RDWR|O_CREAT|O_EXCL,
12968 : 0660,
12969 : &fnum);
12970 4 : if (!NT_STATUS_IS_OK(status)) {
12971 0 : printf("cli_posix_open (create) of %s returned %s\n",
12972 : star_name,
12973 : nt_errstr(status));
12974 0 : goto out;
12975 : }
12976 4 : status = cli_close(cli_posix, fnum);
12977 4 : if (!NT_STATUS_IS_OK(status)) {
12978 0 : goto out;
12979 : }
12980 :
12981 4 : status = cli_list(cli,
12982 : star_name,
12983 : 0,
12984 : smb1_wild_mangle_list_fn,
12985 : &mangled_name);
12986 4 : if (!NT_STATUS_IS_OK(status)) {
12987 0 : printf("cli_list of %s returned %s\n",
12988 : star_name,
12989 : nt_errstr(status));
12990 0 : goto out;
12991 : }
12992 :
12993 4 : if (mangled_name == NULL) {
12994 0 : goto out;
12995 : }
12996 :
12997 4 : printf("mangled_name = %s\n",
12998 : mangled_name);
12999 :
13000 : /*
13001 : * Try a Windows unlink with the mangled name.
13002 : * This should *NOT* unlink the 'a' name.
13003 : */
13004 :
13005 4 : windows_unlink_name = talloc_asprintf(cli_posix,
13006 : "%s\\%s",
13007 : dname,
13008 : mangled_name);
13009 :
13010 4 : status = cli_unlink(cli, windows_unlink_name, 0);
13011 4 : if (!NT_STATUS_IS_OK(status)) {
13012 0 : printf("cli_unlink of %s returned %s\n",
13013 : windows_unlink_name,
13014 : nt_errstr(status));
13015 0 : goto out;
13016 : }
13017 :
13018 : /* Does 'a' still exist ? */
13019 4 : status = cli_posix_open(cli_posix,
13020 : aname,
13021 : O_RDONLY,
13022 : 0,
13023 : &fnum);
13024 4 : if (!NT_STATUS_IS_OK(status)) {
13025 0 : printf("cli_posix_open O_RNONLY of %s returned %s\n",
13026 : aname,
13027 : nt_errstr(status));
13028 0 : goto out;
13029 : }
13030 :
13031 4 : status = cli_close(cli_posix, fnum);
13032 4 : if (!NT_STATUS_IS_OK(status)) {
13033 0 : goto out;
13034 : }
13035 :
13036 4 : correct = true;
13037 :
13038 4 : out:
13039 :
13040 4 : TALLOC_FREE(windows_unlink_name);
13041 4 : TALLOC_FREE(mangled_name);
13042 :
13043 4 : if (cli != NULL) {
13044 4 : torture_deltree(cli, dname);
13045 4 : torture_close_connection(cli);
13046 : }
13047 :
13048 4 : if (cli_posix != NULL) {
13049 4 : torture_close_connection(cli_posix);
13050 : }
13051 :
13052 4 : return correct;
13053 : }
13054 :
13055 4 : static bool run_smb1_wild_mangle_rename_test(int dummy)
13056 : {
13057 0 : static struct cli_state *cli_posix = NULL;
13058 0 : static struct cli_state *cli = NULL;
13059 4 : uint16_t fnum = (uint16_t)-1;
13060 4 : bool correct = false;
13061 4 : const char *dname = "smb1_wild_mangle_rename";
13062 4 : const char *fooname = "smb1_wild_mangle_rename/foo";
13063 4 : const char *foostar_name = "smb1_wild_mangle_rename/fo*";
13064 4 : const char *wild_name = "smb1_wild_mangle_rename/*";
13065 4 : char *windows_rename_src = NULL;
13066 4 : const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
13067 4 : char *mangled_name = NULL;
13068 0 : NTSTATUS status;
13069 :
13070 4 : printf("Starting SMB1 wild mangle rename test\n");
13071 :
13072 4 : if (!torture_open_connection(&cli_posix, 0)) {
13073 0 : return false;
13074 : }
13075 :
13076 4 : smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
13077 :
13078 4 : status = torture_setup_unix_extensions(cli_posix);
13079 4 : if (!NT_STATUS_IS_OK(status)) {
13080 0 : printf("server doesn't support POSIX\n");
13081 0 : return false;
13082 : }
13083 :
13084 : /* Open a Windows connection. */
13085 4 : if (!torture_open_connection(&cli, 0)) {
13086 0 : goto out;
13087 : }
13088 :
13089 4 : smbXcli_conn_set_sockopt(cli->conn, sockops);
13090 :
13091 : /* Ensure we start from fresh. */
13092 4 : torture_deltree(cli, dname);
13093 :
13094 : /*
13095 : * Create two files - 'foo' and 'fo*'.
13096 : * We need POSIX extensions for this as 'fo*'
13097 : * is not a valid Windows name.
13098 : */
13099 :
13100 4 : status = cli_posix_mkdir(cli_posix, dname, 0770);
13101 4 : if (!NT_STATUS_IS_OK(status)) {
13102 0 : printf("cli_posix_mkdir of %s returned %s\n",
13103 : dname,
13104 : nt_errstr(status));
13105 0 : goto out;
13106 : }
13107 :
13108 4 : status = cli_posix_open(cli_posix,
13109 : fooname,
13110 : O_RDWR|O_CREAT|O_EXCL,
13111 : 0660,
13112 : &fnum);
13113 4 : if (!NT_STATUS_IS_OK(status)) {
13114 0 : printf("cli_posix_open (create) of %s returned %s\n",
13115 : fooname,
13116 : nt_errstr(status));
13117 0 : goto out;
13118 : }
13119 4 : status = cli_close(cli_posix, fnum);
13120 4 : if (!NT_STATUS_IS_OK(status)) {
13121 0 : goto out;
13122 : }
13123 4 : status = cli_posix_open(cli_posix,
13124 : foostar_name,
13125 : O_RDWR|O_CREAT|O_EXCL,
13126 : 0660,
13127 : &fnum);
13128 4 : if (!NT_STATUS_IS_OK(status)) {
13129 0 : printf("cli_posix_open (create) of %s returned %s\n",
13130 : foostar_name,
13131 : nt_errstr(status));
13132 0 : goto out;
13133 : }
13134 4 : status = cli_close(cli_posix, fnum);
13135 4 : if (!NT_STATUS_IS_OK(status)) {
13136 0 : goto out;
13137 : }
13138 :
13139 : /*
13140 : * Get the mangled name. We can re-use the
13141 : * previous smb1_wild_mangle_list_fn for this.
13142 : */
13143 :
13144 4 : status = cli_list(cli,
13145 : wild_name,
13146 : 0,
13147 : smb1_wild_mangle_list_fn,
13148 : &mangled_name);
13149 4 : if (!NT_STATUS_IS_OK(status)) {
13150 0 : printf("cli_list of %s returned %s\n",
13151 : wild_name,
13152 : nt_errstr(status));
13153 0 : goto out;
13154 : }
13155 :
13156 4 : if (mangled_name == NULL) {
13157 0 : goto out;
13158 : }
13159 :
13160 4 : printf("mangled_name = %s\n",
13161 : mangled_name);
13162 :
13163 : /*
13164 : * Try a Windows rename with the mangled name.
13165 : * This should *NOT* rename the 'foo' name.
13166 : */
13167 :
13168 4 : windows_rename_src = talloc_asprintf(cli_posix,
13169 : "%s\\%s",
13170 : dname,
13171 : mangled_name);
13172 :
13173 4 : status = cli_rename(cli,
13174 : windows_rename_src,
13175 : windows_rename_dst,
13176 : false);
13177 4 : if (!NT_STATUS_IS_OK(status)) {
13178 0 : printf("cli_rename of %s -> %s returned %s\n",
13179 : windows_rename_src,
13180 : windows_rename_dst,
13181 : nt_errstr(status));
13182 0 : goto out;
13183 : }
13184 :
13185 : /* Does 'foo' still exist ? */
13186 4 : status = cli_posix_open(cli_posix,
13187 : fooname,
13188 : O_RDONLY,
13189 : 0,
13190 : &fnum);
13191 4 : if (!NT_STATUS_IS_OK(status)) {
13192 0 : printf("cli_posix_open O_RNONLY of %s returned %s\n",
13193 : fooname,
13194 : nt_errstr(status));
13195 0 : goto out;
13196 : }
13197 :
13198 4 : status = cli_close(cli_posix, fnum);
13199 4 : if (!NT_STATUS_IS_OK(status)) {
13200 0 : goto out;
13201 : }
13202 :
13203 4 : correct = true;
13204 :
13205 4 : out:
13206 :
13207 4 : TALLOC_FREE(mangled_name);
13208 4 : TALLOC_FREE(windows_rename_src);
13209 :
13210 4 : if (cli != NULL) {
13211 4 : torture_deltree(cli, dname);
13212 4 : torture_close_connection(cli);
13213 : }
13214 :
13215 4 : torture_close_connection(cli_posix);
13216 :
13217 4 : return correct;
13218 : }
13219 :
13220 : /*
13221 : * Only testing minimal time strings, as the others
13222 : * need (locale-dependent) guessing at what strftime does and
13223 : * even may differ in builds.
13224 : */
13225 1 : static bool timesubst_test(void)
13226 : {
13227 1 : TALLOC_CTX *ctx = NULL;
13228 : /* Sa 23. Dez 04:33:20 CET 2017 */
13229 1 : const struct timeval tv = { 1514000000, 123 };
13230 1 : const char* expect_minimal = "20171223_033320";
13231 1 : const char* expect_minus = "20171223_033320_000123";
13232 1 : char *s;
13233 1 : char *env_tz, *orig_tz = NULL;
13234 1 : bool result = true;
13235 :
13236 1 : ctx = talloc_new(NULL);
13237 :
13238 1 : env_tz = getenv("TZ");
13239 1 : if(env_tz) {
13240 1 : orig_tz = talloc_strdup(ctx, env_tz);
13241 : }
13242 1 : setenv("TZ", "UTC", 1);
13243 :
13244 1 : s = minimal_timeval_string(ctx, &tv, false);
13245 :
13246 1 : if(!s || strcmp(s, expect_minimal)) {
13247 0 : printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13248 : "[%s]\n", s ? s : "<nil>", expect_minimal);
13249 0 : result = false;
13250 : }
13251 1 : TALLOC_FREE(s);
13252 1 : s = minimal_timeval_string(ctx, &tv, true);
13253 1 : if(!s || strcmp(s, expect_minus)) {
13254 0 : printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13255 : "[%s]\n", s ? s : "<nil>", expect_minus);
13256 0 : result = false;
13257 : }
13258 1 : TALLOC_FREE(s);
13259 :
13260 1 : if(orig_tz) {
13261 1 : setenv("TZ", orig_tz, 1);
13262 : }
13263 :
13264 1 : TALLOC_FREE(ctx);
13265 1 : return result;
13266 : }
13267 :
13268 1 : static bool run_local_substitute(int dummy)
13269 : {
13270 1 : bool ok = true;
13271 :
13272 1 : ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13273 1 : ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13274 1 : ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13275 1 : ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13276 1 : ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13277 1 : ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13278 1 : ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13279 1 : ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13280 1 : ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13281 : /* Substitution depends on current time, so better test the underlying
13282 : formatting function. At least covers %t. */
13283 1 : ok &= timesubst_test();
13284 :
13285 : /* Different captialization rules in sub_basic... */
13286 :
13287 1 : ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13288 1 : "blaDOM") == 0);
13289 :
13290 1 : return ok;
13291 : }
13292 :
13293 1 : static bool run_local_base64(int dummy)
13294 : {
13295 1 : int i;
13296 1 : bool ret = true;
13297 :
13298 2000 : for (i=1; i<2000; i++) {
13299 1999 : DATA_BLOB blob1, blob2;
13300 1999 : char *b64;
13301 :
13302 1999 : blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13303 1999 : blob1.length = i;
13304 1999 : generate_random_buffer(blob1.data, blob1.length);
13305 :
13306 1999 : b64 = base64_encode_data_blob(talloc_tos(), blob1);
13307 1999 : if (b64 == NULL) {
13308 0 : d_fprintf(stderr, "base64_encode_data_blob failed "
13309 : "for %d bytes\n", i);
13310 0 : ret = false;
13311 : }
13312 1999 : blob2 = base64_decode_data_blob(b64);
13313 1999 : TALLOC_FREE(b64);
13314 :
13315 1999 : if (data_blob_cmp(&blob1, &blob2)) {
13316 0 : d_fprintf(stderr, "data_blob_cmp failed for %d "
13317 : "bytes\n", i);
13318 0 : ret = false;
13319 : }
13320 1999 : TALLOC_FREE(blob1.data);
13321 1999 : data_blob_free(&blob2);
13322 : }
13323 1 : return ret;
13324 : }
13325 :
13326 1000000 : static void parse_fn(const struct gencache_timeout *t,
13327 : DATA_BLOB blob,
13328 : void *private_data)
13329 : {
13330 1000000 : return;
13331 : }
13332 :
13333 1 : static bool run_local_gencache(int dummy)
13334 : {
13335 1 : char *val;
13336 1 : time_t tm;
13337 1 : DATA_BLOB blob;
13338 1 : char v;
13339 1 : struct memcache *mem;
13340 1 : int i;
13341 :
13342 1 : mem = memcache_init(NULL, 0);
13343 1 : if (mem == NULL) {
13344 0 : d_printf("%s: memcache_init failed\n", __location__);
13345 0 : return false;
13346 : }
13347 1 : memcache_set_global(mem);
13348 :
13349 1 : if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13350 0 : d_printf("%s: gencache_set() failed\n", __location__);
13351 0 : return False;
13352 : }
13353 :
13354 1 : if (!gencache_get("foo", NULL, NULL, NULL)) {
13355 0 : d_printf("%s: gencache_get() failed\n", __location__);
13356 0 : return False;
13357 : }
13358 :
13359 1000001 : for (i=0; i<1000000; i++) {
13360 1000000 : gencache_parse("foo", parse_fn, NULL);
13361 : }
13362 :
13363 1 : if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13364 0 : d_printf("%s: gencache_get() failed\n", __location__);
13365 0 : return False;
13366 : }
13367 1 : TALLOC_FREE(val);
13368 :
13369 1 : if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13370 0 : d_printf("%s: gencache_get() failed\n", __location__);
13371 0 : return False;
13372 : }
13373 :
13374 1 : if (strcmp(val, "bar") != 0) {
13375 0 : d_printf("%s: gencache_get() returned %s, expected %s\n",
13376 : __location__, val, "bar");
13377 0 : TALLOC_FREE(val);
13378 0 : return False;
13379 : }
13380 :
13381 1 : TALLOC_FREE(val);
13382 :
13383 1 : if (!gencache_del("foo")) {
13384 0 : d_printf("%s: gencache_del() failed\n", __location__);
13385 0 : return False;
13386 : }
13387 1 : if (gencache_del("foo")) {
13388 0 : d_printf("%s: second gencache_del() succeeded\n",
13389 : __location__);
13390 0 : return False;
13391 : }
13392 :
13393 1 : if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13394 0 : d_printf("%s: gencache_get() on deleted entry "
13395 : "succeeded\n", __location__);
13396 0 : return False;
13397 : }
13398 :
13399 1 : blob = data_blob_string_const_null("bar");
13400 1 : tm = time(NULL) + 60;
13401 :
13402 1 : if (!gencache_set_data_blob("foo", blob, tm)) {
13403 0 : d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13404 0 : return False;
13405 : }
13406 :
13407 1 : if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13408 0 : d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13409 0 : return False;
13410 : }
13411 :
13412 1 : if (strcmp((const char *)blob.data, "bar") != 0) {
13413 0 : d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13414 0 : __location__, (const char *)blob.data, "bar");
13415 0 : data_blob_free(&blob);
13416 0 : return False;
13417 : }
13418 :
13419 1 : data_blob_free(&blob);
13420 :
13421 1 : if (!gencache_del("foo")) {
13422 0 : d_printf("%s: gencache_del() failed\n", __location__);
13423 0 : return False;
13424 : }
13425 1 : if (gencache_del("foo")) {
13426 0 : d_printf("%s: second gencache_del() succeeded\n",
13427 : __location__);
13428 0 : return False;
13429 : }
13430 :
13431 1 : if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13432 0 : d_printf("%s: gencache_get_data_blob() on deleted entry "
13433 : "succeeded\n", __location__);
13434 0 : return False;
13435 : }
13436 :
13437 1 : v = 1;
13438 1 : blob.data = (uint8_t *)&v;
13439 1 : blob.length = sizeof(v);
13440 :
13441 1 : if (!gencache_set_data_blob("blob", blob, tm)) {
13442 0 : d_printf("%s: gencache_set_data_blob() failed\n",
13443 : __location__);
13444 0 : return false;
13445 : }
13446 1 : if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13447 0 : d_printf("%s: gencache_get succeeded\n", __location__);
13448 0 : return false;
13449 : }
13450 :
13451 0 : return True;
13452 : }
13453 :
13454 1 : static bool rbt_testflags(struct db_context *db, const char *key,
13455 : const char *value)
13456 : {
13457 1 : bool ret = false;
13458 1 : NTSTATUS status;
13459 1 : struct db_record *rec;
13460 :
13461 1 : rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13462 1 : if (rec == NULL) {
13463 0 : d_fprintf(stderr, "fetch_locked failed\n");
13464 0 : goto done;
13465 : }
13466 :
13467 1 : status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13468 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13469 0 : d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13470 : nt_errstr(status));
13471 0 : goto done;
13472 : }
13473 :
13474 1 : status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13475 : TDB_INSERT);
13476 1 : if (!NT_STATUS_IS_OK(status)) {
13477 0 : d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13478 : nt_errstr(status));
13479 0 : goto done;
13480 : }
13481 :
13482 1 : status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13483 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13484 0 : d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13485 : nt_errstr(status));
13486 0 : goto done;
13487 : }
13488 :
13489 1 : status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13490 1 : if (!NT_STATUS_IS_OK(status)) {
13491 0 : d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13492 : nt_errstr(status));
13493 0 : goto done;
13494 : }
13495 :
13496 0 : ret = true;
13497 1 : done:
13498 1 : TALLOC_FREE(rec);
13499 1 : return ret;
13500 : }
13501 :
13502 1998 : static bool rbt_testval(struct db_context *db, const char *key,
13503 : const char *value)
13504 : {
13505 1998 : struct db_record *rec;
13506 1998 : TDB_DATA data = string_tdb_data(value);
13507 1998 : bool ret = false;
13508 1998 : NTSTATUS status;
13509 1998 : TDB_DATA dbvalue;
13510 :
13511 1998 : rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13512 1998 : if (rec == NULL) {
13513 0 : d_fprintf(stderr, "fetch_locked failed\n");
13514 0 : goto done;
13515 : }
13516 1998 : status = dbwrap_record_store(rec, data, 0);
13517 1998 : if (!NT_STATUS_IS_OK(status)) {
13518 0 : d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13519 0 : goto done;
13520 : }
13521 1998 : TALLOC_FREE(rec);
13522 :
13523 1998 : rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13524 1998 : if (rec == NULL) {
13525 0 : d_fprintf(stderr, "second fetch_locked failed\n");
13526 0 : goto done;
13527 : }
13528 :
13529 1998 : dbvalue = dbwrap_record_get_value(rec);
13530 1998 : if ((dbvalue.dsize != data.dsize)
13531 1998 : || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13532 0 : d_fprintf(stderr, "Got wrong data back\n");
13533 0 : goto done;
13534 : }
13535 :
13536 0 : ret = true;
13537 1998 : done:
13538 1998 : TALLOC_FREE(rec);
13539 1998 : return ret;
13540 : }
13541 :
13542 1000 : static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13543 : {
13544 1000 : int *count2 = (int *)private_data;
13545 1000 : (*count2)++;
13546 1000 : return 0;
13547 : }
13548 :
13549 1000 : static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13550 : {
13551 1000 : int *count2 = (int *)private_data;
13552 1000 : (*count2)++;
13553 1000 : dbwrap_record_delete(rec);
13554 1000 : return 0;
13555 : }
13556 :
13557 1 : static bool run_local_rbtree(int dummy)
13558 : {
13559 1 : struct db_context *db;
13560 1 : bool ret = false;
13561 1 : int i;
13562 1 : NTSTATUS status;
13563 1 : int count = 0;
13564 1 : int count2 = 0;
13565 :
13566 1 : db = db_open_rbt(NULL);
13567 :
13568 1 : if (db == NULL) {
13569 0 : d_fprintf(stderr, "db_open_rbt failed\n");
13570 0 : return false;
13571 : }
13572 :
13573 1 : if (!rbt_testflags(db, "firstkey", "firstval")) {
13574 0 : goto done;
13575 : }
13576 :
13577 1000 : for (i = 0; i < 999; i++) {
13578 999 : char key[sizeof("key-9223372036854775807")];
13579 999 : char value[sizeof("value-9223372036854775807")];
13580 :
13581 999 : snprintf(key, sizeof(key), "key%ld", random());
13582 999 : snprintf(value, sizeof(value) ,"value%ld", random());
13583 :
13584 999 : if (!rbt_testval(db, key, value)) {
13585 0 : goto done;
13586 : }
13587 :
13588 999 : snprintf(value, sizeof(value) ,"value%ld", random());
13589 :
13590 999 : if (!rbt_testval(db, key, value)) {
13591 0 : goto done;
13592 : }
13593 : }
13594 :
13595 1 : ret = true;
13596 1 : count = 0; count2 = 0;
13597 1 : status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13598 : &count2, &count);
13599 1 : printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13600 1 : if ((count != count2) || (count != 1000)) {
13601 0 : ret = false;
13602 : }
13603 1 : count = 0; count2 = 0;
13604 1 : status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13605 : &count2, &count);
13606 1 : printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13607 1 : if ((count != count2) || (count != 1000)) {
13608 0 : ret = false;
13609 : }
13610 1 : count = 0; count2 = 0;
13611 1 : status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13612 : &count2, &count);
13613 1 : printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13614 1 : if ((count != count2) || (count != 0)) {
13615 0 : ret = false;
13616 : }
13617 :
13618 1 : done:
13619 1 : TALLOC_FREE(db);
13620 1 : return ret;
13621 : }
13622 :
13623 :
13624 : /*
13625 : local test for character set functions
13626 :
13627 : This is a very simple test for the functionality in convert_string_error()
13628 : */
13629 1 : static bool run_local_convert_string(int dummy)
13630 : {
13631 1 : TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13632 1 : const char *test_strings[2] = { "March", "M\303\244rz" };
13633 1 : char dst[7];
13634 1 : int i;
13635 :
13636 3 : for (i=0; i<2; i++) {
13637 2 : const char *str = test_strings[i];
13638 2 : int len = strlen(str);
13639 2 : size_t converted_size;
13640 2 : bool ret;
13641 :
13642 2 : memset(dst, 'X', sizeof(dst));
13643 :
13644 : /* first try with real source length */
13645 2 : ret = convert_string_error(CH_UNIX, CH_UTF8,
13646 : str, len,
13647 : dst, sizeof(dst),
13648 : &converted_size);
13649 2 : if (ret != true) {
13650 0 : d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13651 0 : goto failed;
13652 : }
13653 :
13654 2 : if (converted_size != len) {
13655 0 : d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13656 : str, len, (int)converted_size);
13657 0 : goto failed;
13658 : }
13659 :
13660 2 : if (strncmp(str, dst, converted_size) != 0) {
13661 0 : d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13662 0 : goto failed;
13663 : }
13664 :
13665 2 : if (strlen(str) != converted_size) {
13666 0 : d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13667 0 : (int)strlen(str), (int)converted_size);
13668 0 : goto failed;
13669 : }
13670 :
13671 2 : if (dst[converted_size] != 'X') {
13672 0 : d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13673 0 : goto failed;
13674 : }
13675 :
13676 : /* now with srclen==-1, this causes the nul to be
13677 : * converted too */
13678 2 : ret = convert_string_error(CH_UNIX, CH_UTF8,
13679 : str, -1,
13680 : dst, sizeof(dst),
13681 : &converted_size);
13682 2 : if (ret != true) {
13683 0 : d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13684 0 : goto failed;
13685 : }
13686 :
13687 2 : if (converted_size != len+1) {
13688 0 : d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13689 : str, len, (int)converted_size);
13690 0 : goto failed;
13691 : }
13692 :
13693 2 : if (strncmp(str, dst, converted_size) != 0) {
13694 0 : d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13695 0 : goto failed;
13696 : }
13697 :
13698 2 : if (len+1 != converted_size) {
13699 0 : d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13700 : len+1, (int)converted_size);
13701 0 : goto failed;
13702 : }
13703 :
13704 2 : if (dst[converted_size] != 'X') {
13705 0 : d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13706 0 : goto failed;
13707 : }
13708 :
13709 : }
13710 :
13711 :
13712 1 : TALLOC_FREE(tmp_ctx);
13713 0 : return true;
13714 0 : failed:
13715 0 : TALLOC_FREE(tmp_ctx);
13716 0 : return false;
13717 : }
13718 :
13719 1 : static bool run_local_string_to_sid(int dummy) {
13720 1 : struct dom_sid sid;
13721 :
13722 1 : if (string_to_sid(&sid, "S--1-5-32-545")) {
13723 0 : printf("allowing S--1-5-32-545\n");
13724 0 : return false;
13725 : }
13726 1 : if (string_to_sid(&sid, "S-1-5-32-+545")) {
13727 0 : printf("allowing S-1-5-32-+545\n");
13728 0 : return false;
13729 : }
13730 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")) {
13731 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");
13732 0 : return false;
13733 : }
13734 1 : if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13735 0 : printf("allowing S-1-5-32-545-abc\n");
13736 0 : return false;
13737 : }
13738 1 : if (string_to_sid(&sid, "S-300-5-32-545")) {
13739 0 : printf("allowing S-300-5-32-545\n");
13740 0 : return false;
13741 : }
13742 1 : if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13743 0 : printf("allowing S-1-0xfffffffffffffe-32-545\n");
13744 0 : return false;
13745 : }
13746 1 : if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13747 0 : printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13748 0 : return false;
13749 : }
13750 1 : if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13751 0 : printf("could not parse S-1-0xfffffffffffe-32-545\n");
13752 0 : return false;
13753 : }
13754 1 : if (!string_to_sid(&sid, "S-1-5-32-545")) {
13755 0 : printf("could not parse S-1-5-32-545\n");
13756 0 : return false;
13757 : }
13758 1 : if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13759 0 : struct dom_sid_buf buf;
13760 0 : printf("mis-parsed S-1-5-32-545 as %s\n",
13761 : dom_sid_str_buf(&sid, &buf));
13762 0 : return false;
13763 : }
13764 0 : return true;
13765 : }
13766 :
13767 3 : static bool sid_to_string_test(const char *expected) {
13768 3 : char *str;
13769 3 : bool res = true;
13770 3 : struct dom_sid sid;
13771 :
13772 3 : if (!string_to_sid(&sid, expected)) {
13773 0 : printf("could not parse %s\n", expected);
13774 0 : return false;
13775 : }
13776 :
13777 3 : str = dom_sid_string(NULL, &sid);
13778 3 : if (strcmp(str, expected)) {
13779 0 : printf("Comparison failed (%s != %s)\n", str, expected);
13780 0 : res = false;
13781 : }
13782 3 : TALLOC_FREE(str);
13783 3 : return res;
13784 : }
13785 :
13786 1 : static bool run_local_sid_to_string(int dummy) {
13787 1 : if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13788 0 : return false;
13789 1 : if (!sid_to_string_test("S-1-545"))
13790 0 : return false;
13791 1 : if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13792 0 : return false;
13793 0 : return true;
13794 : }
13795 :
13796 1 : static bool run_local_binary_to_sid(int dummy) {
13797 1 : ssize_t ret;
13798 1 : struct dom_sid *sid = talloc(NULL, struct dom_sid);
13799 1 : static const uint8_t good_binary_sid[] = {
13800 : 0x1, /* revision number */
13801 : 15, /* num auths */
13802 : 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13803 : 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13804 : 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13805 : 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13806 : 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13807 : 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13808 : 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13809 : 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13810 : 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13811 : 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13812 : 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13813 : 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13814 : 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13815 : 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13816 : 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13817 : 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13818 : };
13819 :
13820 1 : static const uint8_t long_binary_sid[] = {
13821 : 0x1, /* revision number */
13822 : 15, /* num auths */
13823 : 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13824 : 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13825 : 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13826 : 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13827 : 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13828 : 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13829 : 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13830 : 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13831 : 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13832 : 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13833 : 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13834 : 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13835 : 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13836 : 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13837 : 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13838 : 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13839 : 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13840 : 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13841 : 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13842 : };
13843 :
13844 1 : static const uint8_t long_binary_sid2[] = {
13845 : 0x1, /* revision number */
13846 : 32, /* num auths */
13847 : 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13848 : 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13849 : 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13850 : 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13851 : 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13852 : 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13853 : 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13854 : 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13855 : 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13856 : 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13857 : 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13858 : 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13859 : 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13860 : 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13861 : 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13862 : 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13863 : 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13864 : 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13865 : 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13866 : 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13867 : 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13868 : 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13869 : 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13870 : 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13871 : 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13872 : 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13873 : 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13874 : 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13875 : 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13876 : 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13877 : 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13878 : 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13879 : 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13880 : };
13881 :
13882 1 : ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13883 1 : if (ret == -1) {
13884 0 : return false;
13885 : }
13886 1 : ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13887 1 : if (ret != -1) {
13888 0 : return false;
13889 : }
13890 1 : ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13891 1 : if (ret != -1) {
13892 0 : return false;
13893 : }
13894 0 : return true;
13895 : }
13896 :
13897 : /* Split a path name into filename and stream name components. Canonicalise
13898 : * such that an implicit $DATA token is always explicit.
13899 : *
13900 : * The "specification" of this function can be found in the
13901 : * run_local_stream_name() function in torture.c, I've tried those
13902 : * combinations against a W2k3 server.
13903 : */
13904 :
13905 8 : static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13906 : char **pbase, char **pstream)
13907 : {
13908 8 : char *base = NULL;
13909 8 : char *stream = NULL;
13910 8 : char *sname; /* stream name */
13911 8 : const char *stype; /* stream type */
13912 :
13913 8 : DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13914 :
13915 8 : sname = strchr_m(fname, ':');
13916 :
13917 8 : if (sname == NULL) {
13918 1 : if (pbase != NULL) {
13919 1 : base = talloc_strdup(mem_ctx, fname);
13920 1 : NT_STATUS_HAVE_NO_MEMORY(base);
13921 : }
13922 1 : goto done;
13923 : }
13924 :
13925 7 : if (pbase != NULL) {
13926 7 : base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13927 7 : NT_STATUS_HAVE_NO_MEMORY(base);
13928 : }
13929 :
13930 7 : sname += 1;
13931 :
13932 7 : stype = strchr_m(sname, ':');
13933 :
13934 7 : if (stype == NULL) {
13935 2 : sname = talloc_strdup(mem_ctx, sname);
13936 2 : stype = "$DATA";
13937 : }
13938 : else {
13939 5 : if (strcasecmp_m(stype, ":$DATA") != 0) {
13940 : /*
13941 : * If there is an explicit stream type, so far we only
13942 : * allow $DATA. Is there anything else allowed? -- vl
13943 : */
13944 3 : DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13945 3 : TALLOC_FREE(base);
13946 3 : return NT_STATUS_OBJECT_NAME_INVALID;
13947 : }
13948 2 : sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13949 2 : stype += 1;
13950 : }
13951 :
13952 4 : if (sname == NULL) {
13953 0 : TALLOC_FREE(base);
13954 0 : return NT_STATUS_NO_MEMORY;
13955 : }
13956 :
13957 4 : if (sname[0] == '\0') {
13958 : /*
13959 : * no stream name, so no stream
13960 : */
13961 1 : goto done;
13962 : }
13963 :
13964 3 : if (pstream != NULL) {
13965 3 : stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13966 3 : if (stream == NULL) {
13967 0 : TALLOC_FREE(sname);
13968 0 : TALLOC_FREE(base);
13969 0 : return NT_STATUS_NO_MEMORY;
13970 : }
13971 : /*
13972 : * upper-case the type field
13973 : */
13974 3 : (void)strupper_m(strchr_m(stream, ':')+1);
13975 : }
13976 :
13977 0 : done:
13978 5 : if (pbase != NULL) {
13979 5 : *pbase = base;
13980 : }
13981 5 : if (pstream != NULL) {
13982 5 : *pstream = stream;
13983 : }
13984 5 : return NT_STATUS_OK;
13985 : }
13986 :
13987 8 : static bool test_stream_name(const char *fname, const char *expected_base,
13988 : const char *expected_stream,
13989 : NTSTATUS expected_status)
13990 : {
13991 8 : NTSTATUS status;
13992 8 : char *base = NULL;
13993 8 : char *stream = NULL;
13994 :
13995 8 : status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13996 8 : if (!NT_STATUS_EQUAL(status, expected_status)) {
13997 0 : goto error;
13998 : }
13999 :
14000 8 : if (!NT_STATUS_IS_OK(status)) {
14001 0 : return true;
14002 : }
14003 :
14004 5 : if (base == NULL) goto error;
14005 :
14006 5 : if (strcmp(expected_base, base) != 0) goto error;
14007 :
14008 5 : if ((expected_stream != NULL) && (stream == NULL)) goto error;
14009 5 : if ((expected_stream == NULL) && (stream != NULL)) goto error;
14010 :
14011 5 : if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
14012 0 : goto error;
14013 :
14014 5 : TALLOC_FREE(base);
14015 5 : TALLOC_FREE(stream);
14016 0 : return true;
14017 :
14018 0 : error:
14019 0 : d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
14020 : fname, expected_base ? expected_base : "<NULL>",
14021 : expected_stream ? expected_stream : "<NULL>",
14022 : nt_errstr(expected_status));
14023 0 : d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
14024 0 : base ? base : "<NULL>", stream ? stream : "<NULL>",
14025 : nt_errstr(status));
14026 0 : TALLOC_FREE(base);
14027 0 : TALLOC_FREE(stream);
14028 0 : return false;
14029 : }
14030 :
14031 1 : static bool run_local_stream_name(int dummy)
14032 : {
14033 1 : bool ret = true;
14034 :
14035 2 : ret &= test_stream_name(
14036 1 : "bla", "bla", NULL, NT_STATUS_OK);
14037 2 : ret &= test_stream_name(
14038 1 : "bla::$DATA", "bla", NULL, NT_STATUS_OK);
14039 2 : ret &= test_stream_name(
14040 1 : "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14041 2 : ret &= test_stream_name(
14042 1 : "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
14043 2 : ret &= test_stream_name(
14044 1 : "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14045 2 : ret &= test_stream_name(
14046 1 : "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
14047 2 : ret &= test_stream_name(
14048 1 : "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
14049 2 : ret &= test_stream_name(
14050 1 : "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
14051 :
14052 1 : return ret;
14053 : }
14054 :
14055 2 : static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
14056 : {
14057 2 : if (a.length != b.length) {
14058 0 : printf("a.length=%d != b.length=%d\n",
14059 0 : (int)a.length, (int)b.length);
14060 0 : return false;
14061 : }
14062 2 : if (memcmp(a.data, b.data, a.length) != 0) {
14063 0 : printf("a.data and b.data differ\n");
14064 0 : return false;
14065 : }
14066 0 : return true;
14067 : }
14068 :
14069 1 : static bool run_local_memcache(int dummy)
14070 : {
14071 1 : struct memcache *cache;
14072 1 : DATA_BLOB k1, k2, k3, k4, k5;
14073 1 : DATA_BLOB d1, d3;
14074 1 : DATA_BLOB v1, v3;
14075 :
14076 1 : TALLOC_CTX *mem_ctx;
14077 1 : char *ptr1 = NULL;
14078 1 : char *ptr2 = NULL;
14079 1 : char *ptr3 = NULL;
14080 :
14081 1 : char *str1, *str2;
14082 1 : size_t size1, size2;
14083 1 : bool ret = false;
14084 :
14085 1 : mem_ctx = talloc_init("foo");
14086 1 : if (mem_ctx == NULL) {
14087 0 : return false;
14088 : }
14089 :
14090 : /* STAT_CACHE TESTS */
14091 :
14092 1 : cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14093 :
14094 1 : if (cache == NULL) {
14095 0 : printf("memcache_init failed\n");
14096 0 : return false;
14097 : }
14098 :
14099 1 : d1 = data_blob_const("d1", 2);
14100 1 : d3 = data_blob_const("d3", 2);
14101 :
14102 1 : k1 = data_blob_const("d1", 2);
14103 1 : k2 = data_blob_const("d2", 2);
14104 1 : k3 = data_blob_const("d3", 2);
14105 1 : k4 = data_blob_const("d4", 2);
14106 1 : k5 = data_blob_const("d5", 2);
14107 :
14108 1 : memcache_add(cache, STAT_CACHE, k1, d1);
14109 :
14110 1 : if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
14111 0 : printf("could not find k1\n");
14112 0 : return false;
14113 : }
14114 1 : if (!data_blob_equal(d1, v1)) {
14115 0 : return false;
14116 : }
14117 :
14118 1 : memcache_add(cache, STAT_CACHE, k1, d3);
14119 :
14120 1 : if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
14121 0 : printf("could not find replaced k1\n");
14122 0 : return false;
14123 : }
14124 1 : if (!data_blob_equal(d3, v3)) {
14125 0 : return false;
14126 : }
14127 :
14128 1 : TALLOC_FREE(cache);
14129 :
14130 : /* GETWD_CACHE TESTS */
14131 1 : str1 = talloc_strdup(mem_ctx, "string1");
14132 1 : if (str1 == NULL) {
14133 0 : return false;
14134 : }
14135 1 : ptr2 = str1; /* Keep an alias for comparison. */
14136 :
14137 1 : str2 = talloc_strdup(mem_ctx, "string2");
14138 1 : if (str2 == NULL) {
14139 0 : return false;
14140 : }
14141 :
14142 1 : cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14143 1 : if (cache == NULL) {
14144 0 : printf("memcache_init failed\n");
14145 0 : return false;
14146 : }
14147 :
14148 1 : memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14149 : /* str1 == NULL now. */
14150 1 : ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14151 1 : if (ptr1 == NULL) {
14152 0 : printf("could not find k2\n");
14153 0 : return false;
14154 : }
14155 1 : if (ptr1 != ptr2) {
14156 0 : printf("fetch of k2 got wrong string\n");
14157 0 : return false;
14158 : }
14159 :
14160 : /* Add a blob to ensure k2 gets purged. */
14161 1 : d3 = data_blob_talloc_zero(mem_ctx, 180);
14162 1 : memcache_add(cache, STAT_CACHE, k3, d3);
14163 :
14164 1 : ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14165 1 : if (ptr2 != NULL) {
14166 0 : printf("Did find k2, should have been purged\n");
14167 0 : return false;
14168 : }
14169 :
14170 : /*
14171 : * Test that talloc size also is accounted in memcache and
14172 : * causes purge of other object.
14173 : */
14174 :
14175 1 : str1 = talloc_zero_size(mem_ctx, 100);
14176 1 : str2 = talloc_zero_size(mem_ctx, 100);
14177 :
14178 1 : memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14179 1 : memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14180 :
14181 1 : ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14182 1 : if (ptr3 != NULL) {
14183 0 : printf("Did find k4, should have been purged\n");
14184 0 : return false;
14185 : }
14186 :
14187 : /*
14188 : * Test that adding a duplicate non-talloced
14189 : * key/value on top of a talloced key/value takes account
14190 : * of the talloc_freed value size.
14191 : */
14192 1 : TALLOC_FREE(cache);
14193 1 : TALLOC_FREE(mem_ctx);
14194 :
14195 1 : mem_ctx = talloc_init("key_replace");
14196 1 : if (mem_ctx == NULL) {
14197 0 : return false;
14198 : }
14199 :
14200 1 : cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14201 1 : if (cache == NULL) {
14202 0 : return false;
14203 : }
14204 :
14205 : /*
14206 : * Add a 100 byte talloced string. This will
14207 : * store a (4 or 8 byte) pointer and record the
14208 : * total talloced size.
14209 : */
14210 1 : str1 = talloc_zero_size(mem_ctx, 100);
14211 1 : memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14212 : /*
14213 : * Now overwrite with a small talloced
14214 : * value. This should fit in the existing size
14215 : * and the total talloced size should be removed
14216 : * from the cache size.
14217 : */
14218 1 : str1 = talloc_zero_size(mem_ctx, 2);
14219 1 : memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14220 : /*
14221 : * Now store a 20 byte string. If the
14222 : * total talloced size wasn't accounted for
14223 : * and removed in the overwrite, then this
14224 : * will evict k4.
14225 : */
14226 1 : str2 = talloc_zero_size(mem_ctx, 20);
14227 1 : memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14228 :
14229 1 : ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14230 1 : if (ptr3 == NULL) {
14231 0 : printf("Did not find k4, should not have been purged\n");
14232 0 : return false;
14233 : }
14234 :
14235 1 : TALLOC_FREE(cache);
14236 1 : TALLOC_FREE(mem_ctx);
14237 :
14238 1 : mem_ctx = talloc_init("foo");
14239 1 : if (mem_ctx == NULL) {
14240 0 : return false;
14241 : }
14242 :
14243 1 : cache = memcache_init(NULL, 0);
14244 1 : if (cache == NULL) {
14245 0 : return false;
14246 : }
14247 :
14248 1 : str1 = talloc_strdup(mem_ctx, "string1");
14249 1 : if (str1 == NULL) {
14250 0 : return false;
14251 : }
14252 1 : str2 = talloc_strdup(mem_ctx, "string2");
14253 1 : if (str2 == NULL) {
14254 0 : return false;
14255 : }
14256 1 : memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14257 : data_blob_string_const("torture"), &str1);
14258 1 : size1 = talloc_total_size(cache);
14259 :
14260 1 : memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14261 : data_blob_string_const("torture"), &str2);
14262 1 : size2 = talloc_total_size(cache);
14263 :
14264 1 : printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14265 :
14266 1 : if (size2 > size1) {
14267 0 : printf("memcache leaks memory!\n");
14268 0 : goto fail;
14269 : }
14270 :
14271 0 : ret = true;
14272 1 : fail:
14273 1 : TALLOC_FREE(cache);
14274 1 : return ret;
14275 : }
14276 :
14277 200 : static void wbclient_done(struct tevent_req *req)
14278 : {
14279 0 : wbcErr wbc_err;
14280 0 : struct winbindd_response *wb_resp;
14281 200 : int *i = (int *)tevent_req_callback_data_void(req);
14282 :
14283 200 : wbc_err = wb_trans_recv(req, req, &wb_resp);
14284 200 : TALLOC_FREE(req);
14285 200 : *i += 1;
14286 200 : d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14287 200 : }
14288 :
14289 2 : static bool run_wbclient_multi_ping(int dummy)
14290 : {
14291 0 : struct tevent_context *ev;
14292 0 : struct wb_context **wb_ctx;
14293 0 : struct winbindd_request wb_req;
14294 2 : bool result = false;
14295 0 : int i, j;
14296 :
14297 2 : BlockSignals(True, SIGPIPE);
14298 :
14299 2 : ev = tevent_context_init(talloc_tos());
14300 2 : if (ev == NULL) {
14301 0 : goto fail;
14302 : }
14303 :
14304 2 : wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14305 2 : if (wb_ctx == NULL) {
14306 0 : goto fail;
14307 : }
14308 :
14309 2 : ZERO_STRUCT(wb_req);
14310 2 : wb_req.cmd = WINBINDD_PING;
14311 :
14312 2 : d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14313 :
14314 4 : for (i=0; i<torture_nprocs; i++) {
14315 2 : wb_ctx[i] = wb_context_init(ev, NULL);
14316 2 : if (wb_ctx[i] == NULL) {
14317 0 : goto fail;
14318 : }
14319 202 : for (j=0; j<torture_numops; j++) {
14320 0 : struct tevent_req *req;
14321 200 : req = wb_trans_send(ev, ev, wb_ctx[i],
14322 200 : (j % 2) == 0, &wb_req);
14323 200 : if (req == NULL) {
14324 0 : goto fail;
14325 : }
14326 200 : tevent_req_set_callback(req, wbclient_done, &i);
14327 : }
14328 : }
14329 :
14330 2 : i = 0;
14331 :
14332 818 : while (i < torture_nprocs * torture_numops) {
14333 816 : tevent_loop_once(ev);
14334 : }
14335 :
14336 2 : result = true;
14337 2 : fail:
14338 2 : TALLOC_FREE(ev);
14339 2 : return result;
14340 : }
14341 :
14342 0 : static bool dbtrans_inc(struct db_context *db)
14343 : {
14344 0 : struct db_record *rec;
14345 0 : uint32_t val;
14346 0 : bool ret = false;
14347 0 : NTSTATUS status;
14348 0 : TDB_DATA value;
14349 :
14350 0 : rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14351 0 : if (rec == NULL) {
14352 0 : printf(__location__ "fetch_lock failed\n");
14353 0 : return false;
14354 : }
14355 :
14356 0 : value = dbwrap_record_get_value(rec);
14357 :
14358 0 : if (value.dsize != sizeof(uint32_t)) {
14359 0 : printf(__location__ "value.dsize = %d\n",
14360 0 : (int)value.dsize);
14361 0 : goto fail;
14362 : }
14363 :
14364 0 : memcpy(&val, value.dptr, sizeof(val));
14365 0 : val += 1;
14366 :
14367 0 : status = dbwrap_record_store(
14368 : rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14369 0 : if (!NT_STATUS_IS_OK(status)) {
14370 0 : printf(__location__ "store failed: %s\n",
14371 : nt_errstr(status));
14372 0 : goto fail;
14373 : }
14374 :
14375 0 : ret = true;
14376 0 : fail:
14377 0 : TALLOC_FREE(rec);
14378 0 : return ret;
14379 : }
14380 :
14381 0 : static bool run_local_dbtrans(int dummy)
14382 : {
14383 0 : struct db_context *db;
14384 0 : struct db_record *rec;
14385 0 : NTSTATUS status;
14386 0 : uint32_t initial;
14387 0 : int res;
14388 0 : TDB_DATA value;
14389 :
14390 0 : db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14391 : O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14392 : DBWRAP_FLAG_NONE);
14393 0 : if (db == NULL) {
14394 0 : printf("Could not open transtest.db\n");
14395 0 : return false;
14396 : }
14397 :
14398 0 : res = dbwrap_transaction_start(db);
14399 0 : if (res != 0) {
14400 0 : printf(__location__ "transaction_start failed\n");
14401 0 : return false;
14402 : }
14403 :
14404 0 : rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14405 0 : if (rec == NULL) {
14406 0 : printf(__location__ "fetch_lock failed\n");
14407 0 : return false;
14408 : }
14409 :
14410 0 : value = dbwrap_record_get_value(rec);
14411 :
14412 0 : if (value.dptr == NULL) {
14413 0 : initial = 0;
14414 0 : status = dbwrap_record_store(
14415 : rec, make_tdb_data((uint8_t *)&initial,
14416 : sizeof(initial)),
14417 : 0);
14418 0 : if (!NT_STATUS_IS_OK(status)) {
14419 0 : printf(__location__ "store returned %s\n",
14420 : nt_errstr(status));
14421 0 : return false;
14422 : }
14423 : }
14424 :
14425 0 : TALLOC_FREE(rec);
14426 :
14427 0 : res = dbwrap_transaction_commit(db);
14428 0 : if (res != 0) {
14429 0 : printf(__location__ "transaction_commit failed\n");
14430 0 : return false;
14431 : }
14432 :
14433 0 : while (true) {
14434 0 : uint32_t val, val2;
14435 0 : int i;
14436 :
14437 0 : res = dbwrap_transaction_start(db);
14438 0 : if (res != 0) {
14439 0 : printf(__location__ "transaction_start failed\n");
14440 0 : break;
14441 : }
14442 :
14443 0 : status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14444 0 : if (!NT_STATUS_IS_OK(status)) {
14445 0 : printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14446 : nt_errstr(status));
14447 0 : break;
14448 : }
14449 :
14450 0 : for (i=0; i<10; i++) {
14451 0 : if (!dbtrans_inc(db)) {
14452 0 : return false;
14453 : }
14454 : }
14455 :
14456 0 : status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14457 0 : if (!NT_STATUS_IS_OK(status)) {
14458 0 : printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14459 : nt_errstr(status));
14460 0 : break;
14461 : }
14462 :
14463 0 : if (val2 != val + 10) {
14464 0 : printf(__location__ "val=%d, val2=%d\n",
14465 : (int)val, (int)val2);
14466 0 : break;
14467 : }
14468 :
14469 0 : printf("val2=%d\r", val2);
14470 :
14471 0 : res = dbwrap_transaction_commit(db);
14472 0 : if (res != 0) {
14473 0 : printf(__location__ "transaction_commit failed\n");
14474 0 : break;
14475 : }
14476 : }
14477 :
14478 0 : TALLOC_FREE(db);
14479 0 : return true;
14480 : }
14481 :
14482 : /*
14483 : * Just a dummy test to be run under a debugger. There's no real way
14484 : * to inspect the tevent_poll specific function from outside of
14485 : * tevent_poll.c.
14486 : */
14487 :
14488 1 : static bool run_local_tevent_poll(int dummy)
14489 : {
14490 1 : struct tevent_context *ev;
14491 1 : struct tevent_fd *fd1, *fd2;
14492 1 : bool result = false;
14493 :
14494 1 : ev = tevent_context_init_byname(NULL, "poll");
14495 1 : if (ev == NULL) {
14496 0 : d_fprintf(stderr, "tevent_context_init_byname failed\n");
14497 0 : goto fail;
14498 : }
14499 :
14500 1 : fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14501 1 : if (fd1 == NULL) {
14502 0 : d_fprintf(stderr, "tevent_add_fd failed\n");
14503 0 : goto fail;
14504 : }
14505 1 : fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14506 1 : if (fd2 == NULL) {
14507 0 : d_fprintf(stderr, "tevent_add_fd failed\n");
14508 0 : goto fail;
14509 : }
14510 1 : TALLOC_FREE(fd2);
14511 :
14512 1 : fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14513 1 : if (fd2 == NULL) {
14514 0 : d_fprintf(stderr, "tevent_add_fd failed\n");
14515 0 : goto fail;
14516 : }
14517 :
14518 0 : result = true;
14519 1 : fail:
14520 1 : TALLOC_FREE(ev);
14521 1 : return result;
14522 : }
14523 :
14524 1 : static bool run_local_hex_encode_buf(int dummy)
14525 : {
14526 1 : char buf[17];
14527 1 : uint8_t src[8];
14528 1 : size_t i;
14529 :
14530 9 : for (i=0; i<sizeof(src); i++) {
14531 8 : src[i] = i;
14532 : }
14533 1 : hex_encode_buf(buf, src, sizeof(src));
14534 1 : if (strcmp(buf, "0001020304050607") != 0) {
14535 0 : return false;
14536 : }
14537 1 : hex_encode_buf(buf, NULL, 0);
14538 1 : if (buf[0] != '\0') {
14539 0 : return false;
14540 : }
14541 0 : return true;
14542 : }
14543 :
14544 : static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14545 : "0.0.0.0",
14546 : "::0",
14547 : "1.2.3.1",
14548 : "0.0.0.0",
14549 : "0.0.0.0",
14550 : "1.2.3.2",
14551 : "1.2.3.3",
14552 : "1.2.3.4",
14553 : "1.2.3.5",
14554 : "::0",
14555 : "1.2.3.6",
14556 : "1.2.3.7",
14557 : "::0",
14558 : "::0",
14559 : "::0",
14560 : "1.2.3.8",
14561 : "1.2.3.9",
14562 : "1.2.3.10",
14563 : "1.2.3.11",
14564 : "1.2.3.12",
14565 : "1.2.3.13",
14566 : "1001:1111:1111:1000:0:1111:1111:1111",
14567 : "1.2.3.1",
14568 : "1.2.3.2",
14569 : "1.2.3.3",
14570 : "1.2.3.12",
14571 : "::0",
14572 : "::0"
14573 : };
14574 :
14575 : static const char *remove_duplicate_addrs2_test_strings_result[] = {
14576 : "1.2.3.1",
14577 : "1.2.3.2",
14578 : "1.2.3.3",
14579 : "1.2.3.4",
14580 : "1.2.3.5",
14581 : "1.2.3.6",
14582 : "1.2.3.7",
14583 : "1.2.3.8",
14584 : "1.2.3.9",
14585 : "1.2.3.10",
14586 : "1.2.3.11",
14587 : "1.2.3.12",
14588 : "1.2.3.13",
14589 : "1001:1111:1111:1000:0:1111:1111:1111"
14590 : };
14591 :
14592 1 : static bool run_local_remove_duplicate_addrs2(int dummy)
14593 : {
14594 1 : struct samba_sockaddr test_vector[28];
14595 1 : size_t count, i;
14596 :
14597 : /* Construct the sockaddr_storage test vector. */
14598 29 : for (i = 0; i < 28; i++) {
14599 28 : struct addrinfo hints;
14600 28 : struct addrinfo *res = NULL;
14601 28 : int ret;
14602 :
14603 28 : memset(&hints, '\0', sizeof(hints));
14604 28 : hints.ai_flags = AI_NUMERICHOST;
14605 28 : ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14606 : NULL,
14607 : &hints,
14608 : &res);
14609 28 : if (ret) {
14610 0 : fprintf(stderr, "getaddrinfo failed on [%s]\n",
14611 : remove_duplicate_addrs2_test_strings_vector[i]);
14612 0 : return false;
14613 : }
14614 28 : memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14615 28 : memcpy(&test_vector[i].u.ss,
14616 28 : res->ai_addr,
14617 28 : res->ai_addrlen);
14618 28 : freeaddrinfo(res);
14619 : }
14620 :
14621 1 : count = remove_duplicate_addrs2(test_vector, i);
14622 :
14623 1 : if (count != 14) {
14624 0 : fprintf(stderr, "count wrong (%zu) should be 14\n",
14625 : count);
14626 0 : return false;
14627 : }
14628 :
14629 15 : for (i = 0; i < count; i++) {
14630 14 : char addr[INET6_ADDRSTRLEN];
14631 :
14632 14 : print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14633 :
14634 14 : if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14635 0 : fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14636 : i,
14637 : addr,
14638 : remove_duplicate_addrs2_test_strings_result[i]);
14639 0 : return false;
14640 : }
14641 : }
14642 :
14643 1 : printf("run_local_remove_duplicate_addrs2: success\n");
14644 1 : return true;
14645 : }
14646 :
14647 0 : static bool run_local_tdb_opener(int dummy)
14648 : {
14649 0 : TDB_CONTEXT *t;
14650 0 : unsigned v = 0;
14651 :
14652 0 : while (1) {
14653 0 : t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14654 : O_RDWR|O_CREAT, 0755);
14655 0 : if (t == NULL) {
14656 0 : perror("tdb_open failed");
14657 0 : return false;
14658 : }
14659 0 : tdb_close(t);
14660 :
14661 0 : v += 1;
14662 0 : printf("\r%u", v);
14663 : }
14664 : return true;
14665 : }
14666 :
14667 0 : static bool run_local_tdb_writer(int dummy)
14668 : {
14669 0 : TDB_CONTEXT *t;
14670 0 : unsigned v = 0;
14671 0 : TDB_DATA val;
14672 :
14673 0 : t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14674 0 : if (t == 0) {
14675 0 : perror("tdb_open failed");
14676 0 : return 1;
14677 : }
14678 :
14679 0 : val.dptr = (uint8_t *)&v;
14680 0 : val.dsize = sizeof(v);
14681 :
14682 0 : while (1) {
14683 0 : TDB_DATA data;
14684 0 : int ret;
14685 :
14686 0 : ret = tdb_store(t, val, val, 0);
14687 0 : if (ret != 0) {
14688 0 : printf("%s\n", tdb_errorstr(t));
14689 : }
14690 0 : v += 1;
14691 0 : printf("\r%u", v);
14692 :
14693 0 : data = tdb_fetch(t, val);
14694 0 : if (data.dptr != NULL) {
14695 0 : SAFE_FREE(data.dptr);
14696 : }
14697 : }
14698 : return true;
14699 : }
14700 :
14701 1 : static bool run_local_canonicalize_path(int dummy)
14702 : {
14703 1 : const char *src[] = {
14704 : "/foo/..",
14705 : "/..",
14706 : "/foo/bar/../baz",
14707 : "/foo/././",
14708 : "/../foo",
14709 : ".././././",
14710 : ".././././../../../boo",
14711 : "./..",
14712 : "/",
14713 : "/../../",
14714 : "/foo/../",
14715 : "/./././",
14716 : "/./././.",
14717 : "/.../././.",
14718 : "/./././.foo",
14719 : "/./././.foo.",
14720 : "/./././foo.",
14721 : "/foo/bar/..",
14722 : "/foo/bar/../baz/",
14723 : "////////////////",
14724 : "/////////./././././.",
14725 : "/./.././../.boo/../baz",
14726 : "/a/component/path",
14727 : "/a/component/path/",
14728 : "/a/component/path/..",
14729 : "/a/component/../path/",
14730 : "///a/./././///component/../////path/",
14731 : NULL
14732 : };
14733 1 : const char *dst[] = {
14734 : "/",
14735 : "/",
14736 : "/foo/baz",
14737 : "/foo",
14738 : "/foo",
14739 : "/",
14740 : "/boo",
14741 : "/",
14742 : "/",
14743 : "/",
14744 : "/",
14745 : "/",
14746 : "/",
14747 : "/...",
14748 : "/.foo",
14749 : "/.foo.",
14750 : "/foo.",
14751 : "/foo",
14752 : "/foo/baz",
14753 : "/",
14754 : "/",
14755 : "/baz",
14756 : "/a/component/path",
14757 : "/a/component/path",
14758 : "/a/component",
14759 : "/a/path",
14760 : "/a/path",
14761 : NULL
14762 : };
14763 1 : unsigned int i;
14764 :
14765 28 : for (i = 0; src[i] != NULL; i++) {
14766 27 : char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14767 27 : if (d == NULL) {
14768 0 : perror("talloc fail\n");
14769 0 : return false;
14770 : }
14771 27 : if (strcmp(d, dst[i]) != 0) {
14772 0 : d_fprintf(stderr,
14773 : "canonicalize mismatch %s -> %s != %s",
14774 : src[i], d, dst[i]);
14775 0 : return false;
14776 : }
14777 27 : talloc_free(d);
14778 : }
14779 0 : return true;
14780 : }
14781 : struct session_setup_nt1_truncated_state {
14782 : uint16_t vwv[13];
14783 : uint8_t bytes[20];
14784 : };
14785 :
14786 : static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq);
14787 :
14788 2 : static struct tevent_req *smb1_session_setup_nt1_truncated_send(
14789 : TALLOC_CTX *mem_ctx,
14790 : struct tevent_context *ev,
14791 : struct smbXcli_conn *conn)
14792 : {
14793 2 : uint16_t *vwv = NULL;
14794 2 : uint8_t *bytes = NULL;
14795 2 : const char *pass = "12345678";
14796 2 : const char *uname = "z";
14797 2 : struct session_setup_nt1_truncated_state *state = NULL;
14798 2 : struct tevent_req *req = NULL;
14799 2 : struct tevent_req *subreq = NULL;
14800 :
14801 2 : req = tevent_req_create(mem_ctx,
14802 : &state,
14803 : struct session_setup_nt1_truncated_state);
14804 2 : if (req == NULL) {
14805 0 : return NULL;
14806 : }
14807 2 : vwv = &state->vwv[0];
14808 2 : bytes = &state->bytes[0];
14809 :
14810 2 : SCVAL(vwv+0, 0, 0xff);
14811 2 : SCVAL(vwv+0, 1, 0);
14812 2 : SSVAL(vwv+1, 0, 0);
14813 2 : SSVAL(vwv+2, 0, 8192);
14814 2 : SSVAL(vwv+3, 0, 2);
14815 2 : SSVAL(vwv+4, 0, 1);
14816 2 : SIVAL(vwv+5, 0, 0);
14817 2 : SSVAL(vwv+7, 0, strlen(pass)); /* OEMPasswordLen */
14818 2 : SSVAL(vwv+8, 0, 0); /* UnicodePasswordLen */
14819 2 : SSVAL(vwv+9, 0, 0); /* reserved */
14820 2 : SSVAL(vwv+10, 0, 0); /* reserved */
14821 2 : SIVAL(vwv+11, 0, CAP_STATUS32);
14822 :
14823 2 : memcpy(bytes, pass, strlen(pass));
14824 2 : bytes += strlen(pass);
14825 2 : memcpy(bytes, uname, strlen(uname)+1);
14826 :
14827 2 : subreq = smb1cli_req_send(state, ev, conn,
14828 : SMBsesssetupX,
14829 : 0, /* additional_flags */
14830 : 0, /* clear_flags */
14831 : 0, /* additional_flags2 */
14832 : 0, /* clear_flags2 */
14833 : 10000, /* timeout_msec */
14834 2 : getpid(),
14835 : NULL, /* tcon */
14836 : NULL, /* session */
14837 : 13, /* wct */
14838 2 : state->vwv,
14839 2 : strlen(pass), /* Truncate length at password. */
14840 2 : state->bytes);
14841 2 : if (tevent_req_nomem(subreq, req)) {
14842 0 : return tevent_req_post(req, ev);
14843 : }
14844 2 : tevent_req_set_callback(subreq,
14845 : smb1_session_setup_nt1_truncated_done,
14846 : req);
14847 2 : return req;
14848 : }
14849 :
14850 2 : static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq)
14851 : {
14852 0 : struct tevent_req *req =
14853 2 : tevent_req_callback_data(subreq,
14854 : struct tevent_req);
14855 0 : struct session_setup_nt1_truncated_state *state =
14856 2 : tevent_req_data(req,
14857 : struct session_setup_nt1_truncated_state);
14858 0 : NTSTATUS status;
14859 2 : struct smb1cli_req_expected_response expected[] = {
14860 : {
14861 : .status = NT_STATUS_OK,
14862 : .wct = 3,
14863 : },
14864 : };
14865 :
14866 2 : status = smb1cli_req_recv(subreq, state,
14867 : NULL,
14868 : NULL,
14869 : NULL,
14870 : NULL,
14871 : NULL, /* pvwv_offset */
14872 : NULL,
14873 : NULL,
14874 : NULL, /* pbytes_offset */
14875 : NULL,
14876 : expected, ARRAY_SIZE(expected));
14877 2 : TALLOC_FREE(subreq);
14878 2 : if (tevent_req_nterror(req, status)) {
14879 0 : return;
14880 : }
14881 2 : tevent_req_done(req);
14882 : }
14883 :
14884 2 : static NTSTATUS smb1_session_setup_nt1_truncated_recv(struct tevent_req *req)
14885 : {
14886 2 : return tevent_req_simple_recv_ntstatus(req);
14887 : }
14888 :
14889 2 : static bool run_smb1_truncated_sesssetup(int dummy)
14890 : {
14891 0 : struct tevent_context *ev;
14892 0 : struct tevent_req *req;
14893 0 : struct smbXcli_conn *conn;
14894 0 : struct sockaddr_storage ss;
14895 0 : NTSTATUS status;
14896 0 : int fd;
14897 0 : bool ok;
14898 :
14899 2 : printf("Starting send truncated SMB1 sesssetup.\n");
14900 :
14901 2 : ok = resolve_name(host, &ss, 0x20, true);
14902 2 : if (!ok) {
14903 0 : d_fprintf(stderr, "Could not resolve name %s\n", host);
14904 0 : return false;
14905 : }
14906 :
14907 2 : status = open_socket_out(&ss, 445, 10000, &fd);
14908 2 : if (!NT_STATUS_IS_OK(status)) {
14909 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
14910 : nt_errstr(status));
14911 0 : return false;
14912 : }
14913 :
14914 2 : conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14915 : NULL, 0, NULL);
14916 2 : if (conn == NULL) {
14917 0 : d_fprintf(stderr, "smbXcli_conn_create failed\n");
14918 0 : return false;
14919 : }
14920 :
14921 2 : status = smbXcli_negprot(conn,
14922 : 0,
14923 : PROTOCOL_NT1,
14924 : PROTOCOL_NT1,
14925 : NULL,
14926 : NULL,
14927 : NULL);
14928 2 : if (!NT_STATUS_IS_OK(status)) {
14929 0 : d_fprintf(stderr, "smbXcli_negprot failed!\n");
14930 0 : return false;
14931 : }
14932 :
14933 2 : ev = samba_tevent_context_init(talloc_tos());
14934 2 : if (ev == NULL) {
14935 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
14936 0 : return false;
14937 : }
14938 :
14939 2 : req = smb1_session_setup_nt1_truncated_send(ev, ev, conn);
14940 2 : if (req == NULL) {
14941 0 : d_fprintf(stderr, "smb1_session_setup_nt1_truncated_send failed\n");
14942 0 : return false;
14943 : }
14944 :
14945 2 : ok = tevent_req_poll_ntstatus(req, ev, &status);
14946 2 : if (!ok) {
14947 0 : d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
14948 : nt_errstr(status));
14949 0 : return false;
14950 : }
14951 :
14952 2 : status = smb1_session_setup_nt1_truncated_recv(req);
14953 2 : if (!NT_STATUS_IS_OK(status)) {
14954 0 : d_fprintf(stderr, "smb1_session_setup_nt1_truncated_recv returned "
14955 : "%s, expected NT_STATUS_OK\n",
14956 : nt_errstr(status));
14957 0 : return false;
14958 : }
14959 :
14960 2 : TALLOC_FREE(conn);
14961 2 : return true;
14962 : }
14963 :
14964 : struct smb1_negotiate_exit_state {
14965 : int dummy;
14966 : };
14967 :
14968 : static void smb1_negotiate_exit_done(struct tevent_req *subreq);
14969 :
14970 4 : static struct tevent_req *smb1_negotiate_exit_send(
14971 : TALLOC_CTX *mem_ctx,
14972 : struct tevent_context *ev,
14973 : struct smbXcli_conn *conn)
14974 : {
14975 4 : struct smb1_negotiate_exit_state *state = NULL;
14976 4 : struct tevent_req *req = NULL;
14977 4 : struct tevent_req *subreq = NULL;
14978 :
14979 4 : req = tevent_req_create(mem_ctx,
14980 : &state,
14981 : struct smb1_negotiate_exit_state);
14982 4 : if (req == NULL) {
14983 0 : return NULL;
14984 : }
14985 4 : subreq = smb1cli_req_send(state, ev, conn,
14986 : SMBexit,
14987 : 0, /* additional_flags */
14988 : 0, /* clear_flags */
14989 : 0, /* additional_flags2 */
14990 : 0, /* clear_flags2 */
14991 : 10000, /* timeout_msec */
14992 4 : getpid(),
14993 : NULL, /* tcon */
14994 : NULL, /* session */
14995 : 0, /* wct */
14996 : NULL,
14997 : 0,
14998 : NULL);
14999 4 : if (tevent_req_nomem(subreq, req)) {
15000 0 : return tevent_req_post(req, ev);
15001 : }
15002 4 : tevent_req_set_callback(subreq,
15003 : smb1_negotiate_exit_done,
15004 : req);
15005 4 : return req;
15006 : }
15007 :
15008 4 : static void smb1_negotiate_exit_done(struct tevent_req *subreq)
15009 : {
15010 0 : struct tevent_req *req =
15011 4 : tevent_req_callback_data(subreq,
15012 : struct tevent_req);
15013 0 : struct smb1_negotiate_exit_state *state =
15014 4 : tevent_req_data(req,
15015 : struct smb1_negotiate_exit_state);
15016 0 : NTSTATUS status;
15017 4 : struct smb1cli_req_expected_response expected[] = {
15018 : {
15019 : .status = NT_STATUS_OK,
15020 : .wct = 0,
15021 : },
15022 : };
15023 :
15024 4 : status = smb1cli_req_recv(subreq, state,
15025 : NULL,
15026 : NULL,
15027 : NULL,
15028 : NULL,
15029 : NULL, /* pvwv_offset */
15030 : NULL,
15031 : NULL,
15032 : NULL, /* pbytes_offset */
15033 : NULL,
15034 : expected, ARRAY_SIZE(expected));
15035 4 : TALLOC_FREE(subreq);
15036 4 : if (tevent_req_nterror(req, status)) {
15037 4 : return;
15038 : }
15039 0 : tevent_req_done(req);
15040 : }
15041 :
15042 4 : static NTSTATUS smb1_negotiate_exit_recv(struct tevent_req *req)
15043 : {
15044 4 : return tevent_req_simple_recv_ntstatus(req);
15045 : }
15046 :
15047 4 : static bool do_smb1_exit(TALLOC_CTX *mem_ctx,
15048 : struct tevent_context *ev,
15049 : struct smbXcli_conn *conn)
15050 : {
15051 0 : struct tevent_req *req;
15052 0 : bool ok;
15053 0 : NTSTATUS status;
15054 4 : NTSTATUS expected_status = NT_STATUS_DOS(ERRSRV, ERRinvnid);;
15055 :
15056 4 : req = smb1_negotiate_exit_send(ev, ev, conn);
15057 4 : if (req == NULL) {
15058 0 : d_fprintf(stderr, "smb1_negotiate_exit_send failed\n");
15059 0 : return false;
15060 : }
15061 :
15062 4 : ok = tevent_req_poll_ntstatus(req, ev, &status);
15063 4 : if (!ok) {
15064 0 : d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
15065 : nt_errstr(status));
15066 0 : return false;
15067 : }
15068 :
15069 4 : status = smb1_negotiate_exit_recv(req);
15070 4 : if (!NT_STATUS_EQUAL(status, expected_status)) {
15071 0 : d_fprintf(stderr, "smb1_negotiate_exit_recv returned "
15072 : "%s, expected ERRSRV, ERRinvnid\n",
15073 : nt_errstr(status));
15074 0 : return false;
15075 : }
15076 4 : return true;
15077 : }
15078 :
15079 2 : static bool run_smb1_negotiate_exit(int dummy)
15080 : {
15081 0 : struct tevent_context *ev;
15082 0 : struct smbXcli_conn *conn;
15083 0 : struct sockaddr_storage ss;
15084 0 : NTSTATUS status;
15085 0 : int fd;
15086 0 : bool ok;
15087 :
15088 2 : printf("Starting send SMB1 negotiate+exit.\n");
15089 :
15090 2 : ok = resolve_name(host, &ss, 0x20, true);
15091 2 : if (!ok) {
15092 0 : d_fprintf(stderr, "Could not resolve name %s\n", host);
15093 0 : return false;
15094 : }
15095 :
15096 2 : status = open_socket_out(&ss, 445, 10000, &fd);
15097 2 : if (!NT_STATUS_IS_OK(status)) {
15098 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
15099 : nt_errstr(status));
15100 0 : return false;
15101 : }
15102 :
15103 2 : conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15104 : NULL, 0, NULL);
15105 2 : if (conn == NULL) {
15106 0 : d_fprintf(stderr, "smbXcli_conn_create failed\n");
15107 0 : return false;
15108 : }
15109 :
15110 2 : status = smbXcli_negprot(conn,
15111 : 0,
15112 : PROTOCOL_NT1,
15113 : PROTOCOL_NT1,
15114 : NULL,
15115 : NULL,
15116 : NULL);
15117 2 : if (!NT_STATUS_IS_OK(status)) {
15118 0 : d_fprintf(stderr, "smbXcli_negprot failed!\n");
15119 0 : return false;
15120 : }
15121 :
15122 2 : ev = samba_tevent_context_init(talloc_tos());
15123 2 : if (ev == NULL) {
15124 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
15125 0 : return false;
15126 : }
15127 :
15128 : /*
15129 : * Call do_smb1_exit twice to catch a server crash, the
15130 : * server sends the first return code then crashes.
15131 : */
15132 2 : ok = do_smb1_exit(ev, ev, conn);
15133 2 : if (!ok) {
15134 0 : d_fprintf(stderr, "do_smb1_exit (1) failed\n");
15135 0 : return false;
15136 : }
15137 2 : ok = do_smb1_exit(ev, ev, conn);
15138 2 : if (!ok) {
15139 0 : d_fprintf(stderr, "do_smb1_exit (2) failed\n");
15140 0 : return false;
15141 : }
15142 :
15143 2 : TALLOC_FREE(conn);
15144 2 : return true;
15145 : }
15146 :
15147 2 : static bool run_smb1_negotiate_tcon(int dummy)
15148 : {
15149 2 : struct cli_state *cli = NULL;
15150 2 : uint16_t cnum = 0;
15151 2 : uint16_t max_xmit = 0;
15152 0 : NTSTATUS status;
15153 :
15154 2 : printf("Starting send SMB1 negotiate+tcon.\n");
15155 2 : cli = open_nbt_connection();
15156 2 : if (cli == NULL) {
15157 0 : d_fprintf(stderr, "open_nbt_connection failed!\n");
15158 0 : return false;
15159 : }
15160 2 : smbXcli_conn_set_sockopt(cli->conn, sockops);
15161 :
15162 2 : status = smbXcli_negprot(cli->conn,
15163 : 0,
15164 : PROTOCOL_NT1,
15165 : PROTOCOL_NT1,
15166 : NULL,
15167 : NULL,
15168 : NULL);
15169 2 : if (!NT_STATUS_IS_OK(status)) {
15170 0 : d_fprintf(stderr, "smbXcli_negprot failed %s!\n",
15171 : nt_errstr(status));
15172 0 : return false;
15173 : }
15174 2 : status = cli_raw_tcon(cli,
15175 : share,
15176 : "",
15177 : "?????",
15178 : &max_xmit,
15179 : &cnum);
15180 2 : if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
15181 0 : d_fprintf(stderr, "cli_raw_tcon failed - got %s "
15182 : "(should get NT_STATUS_ACCESS_DENIED)!\n",
15183 : nt_errstr(status));
15184 0 : return false;
15185 : }
15186 2 : return true;
15187 : }
15188 :
15189 0 : static bool run_ign_bad_negprot(int dummy)
15190 : {
15191 0 : struct tevent_context *ev;
15192 0 : struct tevent_req *req;
15193 0 : struct smbXcli_conn *conn;
15194 0 : struct sockaddr_storage ss;
15195 0 : NTSTATUS status;
15196 0 : int fd;
15197 0 : bool ok;
15198 :
15199 0 : printf("starting ignore bad negprot\n");
15200 :
15201 0 : ok = resolve_name(host, &ss, 0x20, true);
15202 0 : if (!ok) {
15203 0 : d_fprintf(stderr, "Could not resolve name %s\n", host);
15204 0 : return false;
15205 : }
15206 :
15207 0 : status = open_socket_out(&ss, 445, 10000, &fd);
15208 0 : if (!NT_STATUS_IS_OK(status)) {
15209 0 : d_fprintf(stderr, "open_socket_out failed: %s\n",
15210 : nt_errstr(status));
15211 0 : return false;
15212 : }
15213 :
15214 0 : conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15215 : NULL, 0, NULL);
15216 0 : if (conn == NULL) {
15217 0 : d_fprintf(stderr, "smbXcli_conn_create failed\n");
15218 0 : return false;
15219 : }
15220 :
15221 0 : status = smbXcli_negprot(conn,
15222 : 0,
15223 : PROTOCOL_CORE,
15224 : PROTOCOL_CORE,
15225 : NULL,
15226 : NULL,
15227 : NULL);
15228 0 : if (NT_STATUS_IS_OK(status)) {
15229 0 : d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
15230 0 : return false;
15231 : }
15232 :
15233 0 : ev = samba_tevent_context_init(talloc_tos());
15234 0 : if (ev == NULL) {
15235 0 : d_fprintf(stderr, "samba_tevent_context_init failed\n");
15236 0 : return false;
15237 : }
15238 :
15239 0 : req = smb1cli_session_setup_nt1_send(
15240 0 : ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
15241 : data_blob_null, data_blob_null, 0x40,
15242 : "Windows 2000 2195", "Windows 2000 5.0");
15243 0 : if (req == NULL) {
15244 0 : d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
15245 0 : return false;
15246 : }
15247 :
15248 0 : ok = tevent_req_poll_ntstatus(req, ev, &status);
15249 0 : if (!ok) {
15250 0 : d_fprintf(stderr, "tevent_req_poll failed\n");
15251 0 : return false;
15252 : }
15253 :
15254 0 : status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
15255 : NULL, NULL);
15256 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
15257 0 : d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
15258 : "%s, expected NT_STATUS_CONNECTION_RESET\n",
15259 : nt_errstr(status));
15260 0 : return false;
15261 : }
15262 :
15263 0 : TALLOC_FREE(conn);
15264 :
15265 0 : printf("starting ignore bad negprot\n");
15266 :
15267 0 : return true;
15268 : }
15269 :
15270 :
15271 16 : static double create_procs(bool (*fn)(int), bool *result)
15272 : {
15273 0 : int i, status;
15274 0 : volatile pid_t *child_status;
15275 0 : volatile bool *child_status_out;
15276 0 : int synccount;
15277 16 : int tries = 8;
15278 0 : struct timeval start;
15279 :
15280 16 : synccount = 0;
15281 :
15282 16 : child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
15283 16 : if (!child_status) {
15284 0 : printf("Failed to setup shared memory\n");
15285 0 : return -1;
15286 : }
15287 :
15288 16 : child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
15289 16 : if (!child_status_out) {
15290 0 : printf("Failed to setup result status shared memory\n");
15291 0 : return -1;
15292 : }
15293 :
15294 32 : for (i = 0; i < torture_nprocs; i++) {
15295 16 : child_status[i] = 0;
15296 16 : child_status_out[i] = True;
15297 : }
15298 :
15299 16 : start = timeval_current();
15300 :
15301 32 : for (i=0;i<torture_nprocs;i++) {
15302 16 : procnum = i;
15303 16 : if (fork() == 0) {
15304 0 : pid_t mypid = getpid();
15305 0 : sys_srandom(((int)mypid) ^ ((int)time(NULL)));
15306 :
15307 0 : slprintf(myname,sizeof(myname),"CLIENT%d", i);
15308 :
15309 0 : while (1) {
15310 0 : if (torture_open_connection(¤t_cli, i)) break;
15311 0 : if (tries-- == 0) {
15312 0 : printf("pid %d failed to start\n", (int)getpid());
15313 0 : _exit(1);
15314 : }
15315 0 : smb_msleep(10);
15316 : }
15317 :
15318 0 : child_status[i] = getpid();
15319 :
15320 0 : while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
15321 :
15322 0 : child_status_out[i] = fn(i);
15323 0 : _exit(0);
15324 : }
15325 : }
15326 :
15327 0 : do {
15328 74 : synccount = 0;
15329 148 : for (i=0;i<torture_nprocs;i++) {
15330 74 : if (child_status[i]) synccount++;
15331 : }
15332 74 : if (synccount == torture_nprocs) break;
15333 58 : smb_msleep(10);
15334 58 : } while (timeval_elapsed(&start) < 30);
15335 :
15336 16 : if (synccount != torture_nprocs) {
15337 0 : printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
15338 0 : *result = False;
15339 0 : return timeval_elapsed(&start);
15340 : }
15341 :
15342 : /* start the client load */
15343 16 : start = timeval_current();
15344 :
15345 32 : for (i=0;i<torture_nprocs;i++) {
15346 16 : child_status[i] = 0;
15347 : }
15348 :
15349 16 : printf("%d clients started\n", torture_nprocs);
15350 :
15351 32 : for (i=0;i<torture_nprocs;i++) {
15352 16 : while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
15353 : }
15354 :
15355 16 : printf("\n");
15356 :
15357 32 : for (i=0;i<torture_nprocs;i++) {
15358 16 : if (!child_status_out[i]) {
15359 2 : *result = False;
15360 : }
15361 : }
15362 16 : return timeval_elapsed(&start);
15363 : }
15364 :
15365 : #define FLAG_MULTIPROC 1
15366 :
15367 : static struct {
15368 : const char *name;
15369 : bool (*fn)(int);
15370 : unsigned flags;
15371 : } torture_ops[] = {
15372 : {
15373 : .name = "FDPASS",
15374 : .fn = run_fdpasstest,
15375 : },
15376 : {
15377 : .name = "LOCK1",
15378 : .fn = run_locktest1,
15379 : },
15380 : {
15381 : .name = "LOCK2",
15382 : .fn = run_locktest2,
15383 : },
15384 : {
15385 : .name = "LOCK3",
15386 : .fn = run_locktest3,
15387 : },
15388 : {
15389 : .name = "LOCK4",
15390 : .fn = run_locktest4,
15391 : },
15392 : {
15393 : .name = "LOCK5",
15394 : .fn = run_locktest5,
15395 : },
15396 : {
15397 : .name = "LOCK6",
15398 : .fn = run_locktest6,
15399 : },
15400 : {
15401 : .name = "LOCK7",
15402 : .fn = run_locktest7,
15403 : },
15404 : {
15405 : .name = "LOCK8",
15406 : .fn = run_locktest8,
15407 : },
15408 : {
15409 : .name = "LOCK9A",
15410 : .fn = run_locktest9a,
15411 : },
15412 : {
15413 : .name = "LOCK9B",
15414 : .fn = run_locktest9b,
15415 : },
15416 : {
15417 : .name = "LOCK10",
15418 : .fn = run_locktest10,
15419 : },
15420 : {
15421 : .name = "LOCK11",
15422 : .fn = run_locktest11,
15423 : },
15424 : {
15425 : .name = "LOCK12",
15426 : .fn = run_locktest12,
15427 : },
15428 : {
15429 : .name = "LOCK13",
15430 : .fn = run_locktest13,
15431 : },
15432 : {
15433 : .name = "UNLINK",
15434 : .fn = run_unlinktest,
15435 : },
15436 : {
15437 : .name = "BROWSE",
15438 : .fn = run_browsetest,
15439 : },
15440 : {
15441 : .name = "ATTR",
15442 : .fn = run_attrtest,
15443 : },
15444 : {
15445 : .name = "TRANS2",
15446 : .fn = run_trans2test,
15447 : },
15448 : {
15449 : .name = "MAXFID",
15450 : .fn = run_maxfidtest,
15451 : .flags = FLAG_MULTIPROC,
15452 : },
15453 : {
15454 : .name = "TORTURE",
15455 : .fn = run_torture,
15456 : .flags = FLAG_MULTIPROC,
15457 : },
15458 : {
15459 : .name = "RANDOMIPC",
15460 : .fn = run_randomipc,
15461 : },
15462 : {
15463 : .name = "NEGNOWAIT",
15464 : .fn = run_negprot_nowait,
15465 : },
15466 : {
15467 : .name = "NBENCH",
15468 : .fn = run_nbench,
15469 : },
15470 : {
15471 : .name = "NBENCH2",
15472 : .fn = run_nbench2,
15473 : },
15474 : {
15475 : .name = "OPLOCK1",
15476 : .fn = run_oplock1,
15477 : },
15478 : {
15479 : .name = "OPLOCK2",
15480 : .fn = run_oplock2,
15481 : },
15482 : {
15483 : .name = "OPLOCK4",
15484 : .fn = run_oplock4,
15485 : },
15486 : #ifdef HAVE_KERNEL_OPLOCKS_LINUX
15487 : {
15488 : .name = "OPLOCK5",
15489 : .fn = run_oplock5,
15490 : },
15491 : #endif
15492 : {
15493 : .name = "DIR",
15494 : .fn = run_dirtest,
15495 : },
15496 : {
15497 : .name = "DIR1",
15498 : .fn = run_dirtest1,
15499 : },
15500 : {
15501 : .name = "DIR-CREATETIME",
15502 : .fn = run_dir_createtime,
15503 : },
15504 : {
15505 : .name = "DENY1",
15506 : .fn = torture_denytest1,
15507 : },
15508 : {
15509 : .name = "DENY2",
15510 : .fn = torture_denytest2,
15511 : },
15512 : {
15513 : .name = "TCON",
15514 : .fn = run_tcon_test,
15515 : },
15516 : {
15517 : .name = "TCONDEV",
15518 : .fn = run_tcon_devtype_test,
15519 : },
15520 : {
15521 : .name = "RW1",
15522 : .fn = run_readwritetest,
15523 : },
15524 : {
15525 : .name = "RW2",
15526 : .fn = run_readwritemulti,
15527 : .flags = FLAG_MULTIPROC
15528 : },
15529 : {
15530 : .name = "RW3",
15531 : .fn = run_readwritelarge,
15532 : },
15533 : {
15534 : .name = "RW-SIGNING",
15535 : .fn = run_readwritelarge_signtest,
15536 : },
15537 : {
15538 : .name = "OPEN",
15539 : .fn = run_opentest,
15540 : },
15541 : {
15542 : .name = "POSIX",
15543 : .fn = run_simple_posix_open_test,
15544 : },
15545 : {
15546 : .name = "POSIX-APPEND",
15547 : .fn = run_posix_append,
15548 : },
15549 : {
15550 : .name = "POSIX-SYMLINK-ACL",
15551 : .fn = run_acl_symlink_test,
15552 : },
15553 : {
15554 : .name = "POSIX-SYMLINK-EA",
15555 : .fn = run_ea_symlink_test,
15556 : },
15557 : {
15558 : .name = "POSIX-STREAM-DELETE",
15559 : .fn = run_posix_stream_delete,
15560 : },
15561 : {
15562 : .name = "POSIX-OFD-LOCK",
15563 : .fn = run_posix_ofd_lock_test,
15564 : },
15565 : {
15566 : .name = "POSIX-BLOCKING-LOCK",
15567 : .fn = run_posix_blocking_lock,
15568 : },
15569 : {
15570 : .name = "POSIX-MKDIR",
15571 : .fn = run_posix_mkdir_test,
15572 : },
15573 : {
15574 : .name = "POSIX-ACL-OPLOCK",
15575 : .fn = run_posix_acl_oplock_test,
15576 : },
15577 : {
15578 : .name = "POSIX-ACL-SHAREROOT",
15579 : .fn = run_posix_acl_shareroot_test,
15580 : },
15581 : {
15582 : .name = "POSIX-LS-WILDCARD",
15583 : .fn = run_posix_ls_wildcard_test,
15584 : },
15585 : {
15586 : .name = "POSIX-LS-SINGLE",
15587 : .fn = run_posix_ls_single_test,
15588 : },
15589 : {
15590 : .name = "POSIX-READLINK",
15591 : .fn = run_posix_readlink_test,
15592 : },
15593 : {
15594 : .name = "POSIX-STAT",
15595 : .fn = run_posix_stat_test,
15596 : },
15597 : {
15598 : .name = "POSIX-SYMLINK-PARENT",
15599 : .fn = run_posix_symlink_parent_test,
15600 : },
15601 : {
15602 : .name = "POSIX-SYMLINK-CHMOD",
15603 : .fn = run_posix_symlink_chmod_test,
15604 : },
15605 : {
15606 : .name = "POSIX-SYMLINK-RENAME",
15607 : .fn = run_posix_symlink_rename_test,
15608 : },
15609 : {
15610 : .name = "POSIX-DIR-DEFAULT-ACL",
15611 : .fn = run_posix_dir_default_acl_test,
15612 : },
15613 : {
15614 : .name = "POSIX-SYMLINK-GETPATHINFO",
15615 : .fn = run_posix_symlink_getpathinfo_test,
15616 : },
15617 : {
15618 : .name = "POSIX-SYMLINK-SETPATHINFO",
15619 : .fn = run_posix_symlink_setpathinfo_test,
15620 : },
15621 : {
15622 : .name = "WINDOWS-BAD-SYMLINK",
15623 : .fn = run_symlink_open_test,
15624 : },
15625 : {
15626 : .name = "SMB1-WILD-MANGLE-UNLINK",
15627 : .fn = run_smb1_wild_mangle_unlink_test,
15628 : },
15629 : {
15630 : .name = "SMB1-WILD-MANGLE-RENAME",
15631 : .fn = run_smb1_wild_mangle_rename_test,
15632 : },
15633 : {
15634 : .name = "CASE-INSENSITIVE-CREATE",
15635 : .fn = run_case_insensitive_create,
15636 : },
15637 : {
15638 : .name = "ASYNC-ECHO",
15639 : .fn = run_async_echo,
15640 : },
15641 : {
15642 : .name = "UID-REGRESSION-TEST",
15643 : .fn = run_uid_regression_test,
15644 : },
15645 : {
15646 : .name = "SHORTNAME-TEST",
15647 : .fn = run_shortname_test,
15648 : },
15649 : {
15650 : .name = "ADDRCHANGE",
15651 : .fn = run_addrchange,
15652 : },
15653 : #if 1
15654 : {
15655 : .name = "OPENATTR",
15656 : .fn = run_openattrtest,
15657 : },
15658 : #endif
15659 : {
15660 : .name = "XCOPY",
15661 : .fn = run_xcopy,
15662 : },
15663 : {
15664 : .name = "RENAME",
15665 : .fn = run_rename,
15666 : },
15667 : {
15668 : .name = "RENAME-ACCESS",
15669 : .fn = run_rename_access,
15670 : },
15671 : {
15672 : .name = "OWNER-RIGHTS",
15673 : .fn = run_owner_rights,
15674 : },
15675 : {
15676 : .name = "DELETE",
15677 : .fn = run_deletetest,
15678 : },
15679 : {
15680 : .name = "DELETE-STREAM",
15681 : .fn = run_delete_stream,
15682 : },
15683 : {
15684 : .name = "DELETE-PRINT",
15685 : .fn = run_delete_print_test,
15686 : },
15687 : {
15688 : .name = "DELETE-LN",
15689 : .fn = run_deletetest_ln,
15690 : },
15691 : {
15692 : .name = "PROPERTIES",
15693 : .fn = run_properties,
15694 : },
15695 : {
15696 : .name = "MANGLE",
15697 : .fn = torture_mangle,
15698 : },
15699 : {
15700 : .name = "MANGLE1",
15701 : .fn = run_mangle1,
15702 : },
15703 : {
15704 : .name = "MANGLE-ILLEGAL",
15705 : .fn = run_mangle_illegal,
15706 : },
15707 : {
15708 : .name = "W2K",
15709 : .fn = run_w2ktest,
15710 : },
15711 : {
15712 : .name = "TRANS2SCAN",
15713 : .fn = torture_trans2_scan,
15714 : },
15715 : {
15716 : .name = "NTTRANSSCAN",
15717 : .fn = torture_nttrans_scan,
15718 : },
15719 : {
15720 : .name = "UTABLE",
15721 : .fn = torture_utable,
15722 : },
15723 : {
15724 : .name = "CASETABLE",
15725 : .fn = torture_casetable,
15726 : },
15727 : {
15728 : .name = "ERRMAPEXTRACT",
15729 : .fn = run_error_map_extract,
15730 : },
15731 : {
15732 : .name = "PIPE_NUMBER",
15733 : .fn = run_pipe_number,
15734 : },
15735 : {
15736 : .name = "TCON2",
15737 : .fn = run_tcon2_test,
15738 : },
15739 : {
15740 : .name = "IOCTL",
15741 : .fn = torture_ioctl_test,
15742 : },
15743 : {
15744 : .name = "CHKPATH",
15745 : .fn = torture_chkpath_test,
15746 : },
15747 : {
15748 : .name = "FDSESS",
15749 : .fn = run_fdsesstest,
15750 : },
15751 : {
15752 : .name = "EATEST",
15753 : .fn = run_eatest,
15754 : },
15755 : {
15756 : .name = "SESSSETUP_BENCH",
15757 : .fn = run_sesssetup_bench,
15758 : },
15759 : {
15760 : .name = "CHAIN1",
15761 : .fn = run_chain1,
15762 : },
15763 : {
15764 : .name = "CHAIN2",
15765 : .fn = run_chain2,
15766 : },
15767 : {
15768 : .name = "CHAIN3",
15769 : .fn = run_chain3,
15770 : },
15771 : {
15772 : .name = "WINDOWS-WRITE",
15773 : .fn = run_windows_write,
15774 : },
15775 : {
15776 : .name = "LARGE_READX",
15777 : .fn = run_large_readx,
15778 : },
15779 : {
15780 : .name = "MSDFS-ATTRIBUTE",
15781 : .fn = run_msdfs_attribute,
15782 : },
15783 : {
15784 : .name = "NTTRANS-CREATE",
15785 : .fn = run_nttrans_create,
15786 : },
15787 : {
15788 : .name = "NTTRANS-FSCTL",
15789 : .fn = run_nttrans_fsctl,
15790 : },
15791 : {
15792 : .name = "CLI_ECHO",
15793 : .fn = run_cli_echo,
15794 : },
15795 : {
15796 : .name = "CLI_SPLICE",
15797 : .fn = run_cli_splice,
15798 : },
15799 : {
15800 : .name = "TLDAP",
15801 : .fn = run_tldap,
15802 : },
15803 : {
15804 : .name = "STREAMERROR",
15805 : .fn = run_streamerror,
15806 : },
15807 : {
15808 : .name = "NOTIFY-BENCH",
15809 : .fn = run_notify_bench,
15810 : },
15811 : {
15812 : .name = "NOTIFY-BENCH2",
15813 : .fn = run_notify_bench2,
15814 : },
15815 : {
15816 : .name = "NOTIFY-BENCH3",
15817 : .fn = run_notify_bench3,
15818 : },
15819 : {
15820 : .name = "BAD-NBT-SESSION",
15821 : .fn = run_bad_nbt_session,
15822 : },
15823 : {
15824 : .name = "IGN-BAD-NEGPROT",
15825 : .fn = run_ign_bad_negprot,
15826 : },
15827 : {
15828 : .name = "SMB-ANY-CONNECT",
15829 : .fn = run_smb_any_connect,
15830 : },
15831 : {
15832 : .name = "NOTIFY-ONLINE",
15833 : .fn = run_notify_online,
15834 : },
15835 : {
15836 : .name = "SMB2-BASIC",
15837 : .fn = run_smb2_basic,
15838 : },
15839 : {
15840 : .name = "SMB2-NEGPROT",
15841 : .fn = run_smb2_negprot,
15842 : },
15843 : {
15844 : .name = "SMB2-ANONYMOUS",
15845 : .fn = run_smb2_anonymous,
15846 : },
15847 : {
15848 : .name = "SMB2-SESSION-RECONNECT",
15849 : .fn = run_smb2_session_reconnect,
15850 : },
15851 : {
15852 : .name = "SMB2-TCON-DEPENDENCE",
15853 : .fn = run_smb2_tcon_dependence,
15854 : },
15855 : {
15856 : .name = "SMB2-MULTI-CHANNEL",
15857 : .fn = run_smb2_multi_channel,
15858 : },
15859 : {
15860 : .name = "SMB2-SESSION-REAUTH",
15861 : .fn = run_smb2_session_reauth,
15862 : },
15863 : {
15864 : .name = "SMB2-FTRUNCATE",
15865 : .fn = run_smb2_ftruncate,
15866 : },
15867 : {
15868 : .name = "SMB2-DIR-FSYNC",
15869 : .fn = run_smb2_dir_fsync,
15870 : },
15871 : {
15872 : .name = "SMB2-PATH-SLASH",
15873 : .fn = run_smb2_path_slash,
15874 : },
15875 : {
15876 : .name = "SMB1-SYSTEM-SECURITY",
15877 : .fn = run_smb1_system_security,
15878 : },
15879 : {
15880 : .name = "SMB2-SACL",
15881 : .fn = run_smb2_sacl,
15882 : },
15883 : {
15884 : .name = "SMB2-QUOTA1",
15885 : .fn = run_smb2_quota1,
15886 : },
15887 : {
15888 : .name = "SMB2-INVALID-PIPENAME",
15889 : .fn = run_smb2_invalid_pipename,
15890 : },
15891 : {
15892 : .name = "SMB2-STREAM-ACL",
15893 : .fn = run_smb2_stream_acl,
15894 : },
15895 : {
15896 : .name = "SMB2-LIST-DIR-ASYNC",
15897 : .fn = run_list_dir_async_test,
15898 : },
15899 : {
15900 : .name = "SMB2-DEL-ON-CLOSE-NONEMPTY",
15901 : .fn = run_delete_on_close_non_empty,
15902 : },
15903 : {
15904 : .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15905 : .fn = run_delete_on_close_nonwrite_delete_yes_test,
15906 : },
15907 : {
15908 : .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15909 : .fn = run_delete_on_close_nonwrite_delete_no_test,
15910 : },
15911 : {
15912 : .name = "SMB2-DFS-PATHS",
15913 : .fn = run_smb2_dfs_paths,
15914 : },
15915 : {
15916 : .name = "SMB2-NON-DFS-SHARE",
15917 : .fn = run_smb2_non_dfs_share,
15918 : },
15919 : {
15920 : .name = "SMB2-DFS-SHARE-NON-DFS-PATH",
15921 : .fn = run_smb2_dfs_share_non_dfs_path,
15922 : },
15923 : {
15924 : .name = "SMB2-DFS-FILENAME-LEADING-BACKSLASH",
15925 : .fn = run_smb2_dfs_filename_leading_backslash,
15926 : },
15927 : {
15928 : .name = "SMB2-PIPE-READ-ASYNC-DISCONNECT",
15929 : .fn = run_smb2_pipe_read_async_disconnect,
15930 : },
15931 : {
15932 : .name = "SMB1-TRUNCATED-SESSSETUP",
15933 : .fn = run_smb1_truncated_sesssetup,
15934 : },
15935 : {
15936 : .name = "SMB1-NEGOTIATE-EXIT",
15937 : .fn = run_smb1_negotiate_exit,
15938 : },
15939 : {
15940 : .name = "SMB1-NEGOTIATE-TCON",
15941 : .fn = run_smb1_negotiate_tcon,
15942 : },
15943 : {
15944 : .name = "SMB1-DFS-PATHS",
15945 : .fn = run_smb1_dfs_paths,
15946 : },
15947 : {
15948 : .name = "SMB1-DFS-SEARCH-PATHS",
15949 : .fn = run_smb1_dfs_search_paths,
15950 : },
15951 : {
15952 : .name = "SMB1-DFS-OPERATIONS",
15953 : .fn = run_smb1_dfs_operations,
15954 : },
15955 : {
15956 : .name = "SMB1-DFS-BADPATH",
15957 : .fn = run_smb1_dfs_check_badpath,
15958 : },
15959 : {
15960 : .name = "CLEANUP1",
15961 : .fn = run_cleanup1,
15962 : },
15963 : {
15964 : .name = "CLEANUP2",
15965 : .fn = run_cleanup2,
15966 : },
15967 : {
15968 : .name = "CLEANUP4",
15969 : .fn = run_cleanup4,
15970 : },
15971 : {
15972 : .name = "OPLOCK-CANCEL",
15973 : .fn = run_oplock_cancel,
15974 : },
15975 : {
15976 : .name = "PIDHIGH",
15977 : .fn = run_pidhigh,
15978 : },
15979 : {
15980 : .name = "LOCAL-SUBSTITUTE",
15981 : .fn = run_local_substitute,
15982 : },
15983 : {
15984 : .name = "LOCAL-GENCACHE",
15985 : .fn = run_local_gencache,
15986 : },
15987 : {
15988 : .name = "LOCAL-DBWRAP-WATCH1",
15989 : .fn = run_dbwrap_watch1,
15990 : },
15991 : {
15992 : .name = "LOCAL-DBWRAP-WATCH2",
15993 : .fn = run_dbwrap_watch2,
15994 : },
15995 : {
15996 : .name = "LOCAL-DBWRAP-WATCH3",
15997 : .fn = run_dbwrap_watch3,
15998 : },
15999 : {
16000 : .name = "LOCAL-DBWRAP-WATCH4",
16001 : .fn = run_dbwrap_watch4,
16002 : },
16003 : {
16004 : .name = "LOCAL-DBWRAP-DO-LOCKED1",
16005 : .fn = run_dbwrap_do_locked1,
16006 : },
16007 : {
16008 : .name = "LOCAL-MESSAGING-READ1",
16009 : .fn = run_messaging_read1,
16010 : },
16011 : {
16012 : .name = "LOCAL-MESSAGING-READ2",
16013 : .fn = run_messaging_read2,
16014 : },
16015 : {
16016 : .name = "LOCAL-MESSAGING-READ3",
16017 : .fn = run_messaging_read3,
16018 : },
16019 : {
16020 : .name = "LOCAL-MESSAGING-READ4",
16021 : .fn = run_messaging_read4,
16022 : },
16023 : {
16024 : .name = "LOCAL-MESSAGING-FDPASS1",
16025 : .fn = run_messaging_fdpass1,
16026 : },
16027 : {
16028 : .name = "LOCAL-MESSAGING-FDPASS2",
16029 : .fn = run_messaging_fdpass2,
16030 : },
16031 : {
16032 : .name = "LOCAL-MESSAGING-FDPASS2a",
16033 : .fn = run_messaging_fdpass2a,
16034 : },
16035 : {
16036 : .name = "LOCAL-MESSAGING-FDPASS2b",
16037 : .fn = run_messaging_fdpass2b,
16038 : },
16039 : {
16040 : .name = "LOCAL-MESSAGING-SEND-ALL",
16041 : .fn = run_messaging_send_all,
16042 : },
16043 : {
16044 : .name = "LOCAL-BASE64",
16045 : .fn = run_local_base64,
16046 : },
16047 : {
16048 : .name = "LOCAL-RBTREE",
16049 : .fn = run_local_rbtree,
16050 : },
16051 : {
16052 : .name = "LOCAL-MEMCACHE",
16053 : .fn = run_local_memcache,
16054 : },
16055 : {
16056 : .name = "LOCAL-STREAM-NAME",
16057 : .fn = run_local_stream_name,
16058 : },
16059 : {
16060 : .name = "LOCAL-STR-MATCH-MSWILD",
16061 : .fn = run_str_match_mswild,
16062 : },
16063 : {
16064 : .name = "LOCAL-STR-MATCH-REGEX-SUB1",
16065 : .fn = run_str_match_regex_sub1,
16066 : },
16067 : {
16068 : .name = "WBCLIENT-MULTI-PING",
16069 : .fn = run_wbclient_multi_ping,
16070 : },
16071 : {
16072 : .name = "LOCAL-string_to_sid",
16073 : .fn = run_local_string_to_sid,
16074 : },
16075 : {
16076 : .name = "LOCAL-sid_to_string",
16077 : .fn = run_local_sid_to_string,
16078 : },
16079 : {
16080 : .name = "LOCAL-binary_to_sid",
16081 : .fn = run_local_binary_to_sid,
16082 : },
16083 : {
16084 : .name = "LOCAL-DBTRANS",
16085 : .fn = run_local_dbtrans,
16086 : },
16087 : {
16088 : .name = "LOCAL-TEVENT-POLL",
16089 : .fn = run_local_tevent_poll,
16090 : },
16091 : {
16092 : .name = "LOCAL-CONVERT-STRING",
16093 : .fn = run_local_convert_string,
16094 : },
16095 : {
16096 : .name = "LOCAL-CONV-AUTH-INFO",
16097 : .fn = run_local_conv_auth_info,
16098 : },
16099 : {
16100 : .name = "LOCAL-hex_encode_buf",
16101 : .fn = run_local_hex_encode_buf,
16102 : },
16103 : {
16104 : .name = "LOCAL-IDMAP-TDB-COMMON",
16105 : .fn = run_idmap_tdb_common_test,
16106 : },
16107 : {
16108 : .name = "LOCAL-remove_duplicate_addrs2",
16109 : .fn = run_local_remove_duplicate_addrs2,
16110 : },
16111 : {
16112 : .name = "local-tdb-opener",
16113 : .fn = run_local_tdb_opener,
16114 : },
16115 : {
16116 : .name = "local-tdb-writer",
16117 : .fn = run_local_tdb_writer,
16118 : },
16119 : {
16120 : .name = "LOCAL-DBWRAP-CTDB1",
16121 : .fn = run_local_dbwrap_ctdb1,
16122 : },
16123 : {
16124 : .name = "LOCAL-BENCH-PTHREADPOOL",
16125 : .fn = run_bench_pthreadpool,
16126 : },
16127 : {
16128 : .name = "LOCAL-PTHREADPOOL-TEVENT",
16129 : .fn = run_pthreadpool_tevent,
16130 : },
16131 : {
16132 : .name = "LOCAL-G-LOCK1",
16133 : .fn = run_g_lock1,
16134 : },
16135 : {
16136 : .name = "LOCAL-G-LOCK2",
16137 : .fn = run_g_lock2,
16138 : },
16139 : {
16140 : .name = "LOCAL-G-LOCK3",
16141 : .fn = run_g_lock3,
16142 : },
16143 : {
16144 : .name = "LOCAL-G-LOCK4",
16145 : .fn = run_g_lock4,
16146 : },
16147 : {
16148 : .name = "LOCAL-G-LOCK4A",
16149 : .fn = run_g_lock4a,
16150 : },
16151 : {
16152 : .name = "LOCAL-G-LOCK5",
16153 : .fn = run_g_lock5,
16154 : },
16155 : {
16156 : .name = "LOCAL-G-LOCK6",
16157 : .fn = run_g_lock6,
16158 : },
16159 : {
16160 : .name = "LOCAL-G-LOCK7",
16161 : .fn = run_g_lock7,
16162 : },
16163 : {
16164 : .name = "LOCAL-G-LOCK8",
16165 : .fn = run_g_lock8,
16166 : },
16167 : {
16168 : .name = "LOCAL-G-LOCK-PING-PONG",
16169 : .fn = run_g_lock_ping_pong,
16170 : },
16171 : {
16172 : .name = "LOCAL-CANONICALIZE-PATH",
16173 : .fn = run_local_canonicalize_path,
16174 : },
16175 : {
16176 : .name = "LOCAL-NAMEMAP-CACHE1",
16177 : .fn = run_local_namemap_cache1,
16178 : },
16179 : {
16180 : .name = "LOCAL-IDMAP-CACHE1",
16181 : .fn = run_local_idmap_cache1,
16182 : },
16183 : {
16184 : .name = "qpathinfo-bufsize",
16185 : .fn = run_qpathinfo_bufsize,
16186 : },
16187 : {
16188 : .name = "hide-new-files-timeout",
16189 : .fn = run_hidenewfiles,
16190 : },
16191 : {
16192 : .name = "hide-new-files-timeout-showdirs",
16193 : .fn = run_hidenewfiles_showdirs,
16194 : },
16195 : #ifdef CLUSTER_SUPPORT
16196 : {
16197 : .name = "ctdbd-conn1",
16198 : .fn = run_ctdbd_conn1,
16199 : },
16200 : #endif
16201 : {
16202 : .name = "readdir-timestamp",
16203 : .fn = run_readdir_timestamp,
16204 : },
16205 : {
16206 : .name = "rpc-scale",
16207 : .fn = run_rpc_scale,
16208 : },
16209 : {
16210 : .name = "LOCAL-TDB-VALIDATE",
16211 : .fn = run_tdb_validate,
16212 : },
16213 : {
16214 : .name = NULL,
16215 : },
16216 : };
16217 :
16218 : /****************************************************************************
16219 : run a specified test or "ALL"
16220 : ****************************************************************************/
16221 546 : static bool run_test(const char *name)
16222 : {
16223 546 : bool ret = True;
16224 546 : bool result = True;
16225 546 : bool found = False;
16226 45 : int i;
16227 45 : double t;
16228 546 : if (strequal(name,"ALL")) {
16229 0 : for (i=0;torture_ops[i].name;i++) {
16230 0 : run_test(torture_ops[i].name);
16231 : }
16232 0 : found = True;
16233 : }
16234 :
16235 113747 : for (i=0;torture_ops[i].name;i++) {
16236 113197 : fstr_sprintf(randomfname, "\\XX%x",
16237 113197 : (unsigned)random());
16238 :
16239 113197 : if (strequal(name, torture_ops[i].name)) {
16240 546 : found = True;
16241 546 : printf("Running %s\n", name);
16242 546 : if (torture_ops[i].flags & FLAG_MULTIPROC) {
16243 16 : t = create_procs(torture_ops[i].fn, &result);
16244 16 : if (!result) {
16245 2 : ret = False;
16246 2 : printf("TEST %s FAILED!\n", name);
16247 : }
16248 : } else {
16249 45 : struct timeval start;
16250 530 : start = timeval_current();
16251 530 : if (!torture_ops[i].fn(0)) {
16252 14 : ret = False;
16253 14 : printf("TEST %s FAILED!\n", name);
16254 : }
16255 534 : t = timeval_elapsed(&start);
16256 : }
16257 9995 : printf("%s took %g secs\n\n", name, t);
16258 : }
16259 : }
16260 :
16261 550 : if (!found) {
16262 0 : printf("Did not find a test named %s\n", name);
16263 0 : ret = False;
16264 : }
16265 :
16266 550 : return ret;
16267 : }
16268 :
16269 :
16270 0 : static void usage(void)
16271 : {
16272 0 : int i;
16273 :
16274 0 : printf("WARNING samba4 test suite is much more complete nowadays.\n");
16275 0 : printf("Please use samba4 torture.\n\n");
16276 :
16277 0 : printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
16278 :
16279 0 : printf("\t-d debuglevel\n");
16280 0 : printf("\t-U user%%pass\n");
16281 0 : printf("\t-k use kerberos\n");
16282 0 : printf("\t-N numprocs\n");
16283 0 : printf("\t-n my_netbios_name\n");
16284 0 : printf("\t-W workgroup\n");
16285 0 : printf("\t-o num_operations\n");
16286 0 : printf("\t-O socket_options\n");
16287 0 : printf("\t-m maximum protocol\n");
16288 0 : printf("\t-L use oplocks\n");
16289 0 : printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
16290 0 : printf("\t-A showall\n");
16291 0 : printf("\t-p port\n");
16292 0 : printf("\t-s seed\n");
16293 0 : printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
16294 0 : printf("\t-f filename filename to test\n");
16295 0 : printf("\t-e encrypt\n");
16296 0 : printf("\n\n");
16297 :
16298 0 : printf("tests are:");
16299 0 : for (i=0;torture_ops[i].name;i++) {
16300 0 : printf(" %s", torture_ops[i].name);
16301 : }
16302 0 : printf("\n");
16303 :
16304 0 : printf("default test is ALL\n");
16305 :
16306 0 : exit(1);
16307 : }
16308 :
16309 : /****************************************************************************
16310 : main program
16311 : ****************************************************************************/
16312 546 : int main(int argc,char *argv[])
16313 : {
16314 45 : int opt, i;
16315 45 : char *p;
16316 546 : int gotuser = 0;
16317 546 : int gotpass = 0;
16318 546 : bool correct = True;
16319 546 : TALLOC_CTX *frame = talloc_stackframe();
16320 546 : int seed = time(NULL);
16321 546 : struct loadparm_context *lp_ctx = NULL;
16322 :
16323 : #ifdef HAVE_SETBUFFER
16324 546 : setbuffer(stdout, NULL, 0);
16325 : #endif
16326 :
16327 546 : setup_logging("smbtorture", DEBUG_STDOUT);
16328 :
16329 546 : smb_init_locale();
16330 546 : fault_setup();
16331 :
16332 546 : lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
16333 546 : if (lp_ctx == NULL) {
16334 0 : fprintf(stderr,
16335 : "Failed to initialise the global parameter structure.\n");
16336 0 : return 1;
16337 : }
16338 :
16339 546 : if (is_default_dyn_CONFIGFILE()) {
16340 546 : if(getenv("SMB_CONF_PATH")) {
16341 546 : set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
16342 : }
16343 : }
16344 546 : lp_load_global(get_dyn_CONFIGFILE());
16345 546 : load_interfaces();
16346 :
16347 546 : if (argc < 2) {
16348 0 : usage();
16349 : }
16350 :
16351 11065 : for(p = argv[1]; *p; p++)
16352 10519 : if(*p == '\\')
16353 0 : *p = '/';
16354 :
16355 546 : if (strncmp(argv[1], "//", 2)) {
16356 0 : usage();
16357 : }
16358 :
16359 546 : fstrcpy(host, &argv[1][2]);
16360 546 : p = strchr_m(&host[2],'/');
16361 546 : if (!p) {
16362 0 : usage();
16363 : }
16364 546 : *p = 0;
16365 546 : fstrcpy(share, p+1);
16366 :
16367 546 : fstrcpy(myname, get_myname(talloc_tos()));
16368 546 : if (!*myname) {
16369 0 : fprintf(stderr, "Failed to get my hostname.\n");
16370 0 : return 1;
16371 : }
16372 :
16373 546 : if (*username == 0 && getenv("LOGNAME")) {
16374 0 : fstrcpy(username,getenv("LOGNAME"));
16375 : }
16376 :
16377 546 : argc--;
16378 546 : argv++;
16379 :
16380 546 : fstrcpy(workgroup, lp_workgroup());
16381 :
16382 1729 : while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
16383 1774 : != EOF) {
16384 1228 : switch (opt) {
16385 0 : case 'p':
16386 0 : port_to_use = atoi(optarg);
16387 0 : break;
16388 0 : case 's':
16389 0 : seed = atoi(optarg);
16390 0 : break;
16391 0 : case 'W':
16392 0 : fstrcpy(workgroup,optarg);
16393 0 : break;
16394 33 : case 'm':
16395 33 : lpcfg_set_cmdline(lp_ctx, "client max protocol", optarg);
16396 33 : break;
16397 0 : case 'N':
16398 0 : torture_nprocs = atoi(optarg);
16399 0 : break;
16400 0 : case 'o':
16401 0 : torture_numops = atoi(optarg);
16402 0 : break;
16403 0 : case 'd':
16404 0 : lpcfg_set_cmdline(lp_ctx, "log level", optarg);
16405 0 : break;
16406 0 : case 'O':
16407 0 : sockops = optarg;
16408 0 : break;
16409 0 : case 'L':
16410 0 : use_oplocks = True;
16411 0 : break;
16412 463 : case 'l':
16413 463 : local_path = optarg;
16414 463 : break;
16415 0 : case 'A':
16416 0 : torture_showall = True;
16417 0 : break;
16418 0 : case 'n':
16419 0 : fstrcpy(myname, optarg);
16420 0 : break;
16421 0 : case 'c':
16422 0 : client_txt = optarg;
16423 0 : break;
16424 182 : case 'e':
16425 182 : do_encrypt = true;
16426 182 : break;
16427 0 : case 'k':
16428 : #ifdef HAVE_KRB5
16429 0 : use_kerberos = True;
16430 : #else
16431 : d_printf("No kerberos support compiled in\n");
16432 : exit(1);
16433 : #endif
16434 0 : break;
16435 546 : case 'U':
16436 546 : gotuser = 1;
16437 546 : fstrcpy(username,optarg);
16438 546 : p = strchr_m(username,'%');
16439 546 : if (p) {
16440 546 : *p = 0;
16441 546 : fstrcpy(password, p+1);
16442 546 : gotpass = 1;
16443 : }
16444 501 : break;
16445 0 : case 'b':
16446 0 : fstrcpy(multishare_conn_fname, optarg);
16447 0 : use_multishare_conn = True;
16448 0 : break;
16449 0 : case 'B':
16450 0 : torture_blocksize = atoi(optarg);
16451 0 : break;
16452 4 : case 'f':
16453 4 : test_filename = SMB_STRDUP(optarg);
16454 4 : break;
16455 0 : default:
16456 0 : printf("Unknown option %c (%d)\n", (char)opt, opt);
16457 0 : usage();
16458 : }
16459 : }
16460 :
16461 546 : d_printf("using seed %d\n", seed);
16462 :
16463 546 : srandom(seed);
16464 :
16465 546 : if(use_kerberos && !gotuser) gotpass = True;
16466 :
16467 546 : while (!gotpass) {
16468 0 : char pwd[256] = {0};
16469 0 : int rc;
16470 :
16471 0 : rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
16472 0 : if (rc == 0) {
16473 0 : fstrcpy(password, pwd);
16474 0 : gotpass = 1;
16475 : }
16476 : }
16477 :
16478 546 : printf("host=%s share=%s user=%s myname=%s\n",
16479 : host, share, username, myname);
16480 :
16481 546 : torture_creds = cli_session_creds_init(frame,
16482 : username,
16483 : workgroup,
16484 : NULL, /* realm */
16485 : password,
16486 : use_kerberos,
16487 : false, /* fallback_after_kerberos */
16488 : false, /* use_ccache */
16489 : false); /* password_is_nt_hash */
16490 546 : if (torture_creds == NULL) {
16491 0 : d_printf("cli_session_creds_init() failed.\n");
16492 0 : exit(1);
16493 : }
16494 :
16495 546 : if (argc == optind) {
16496 0 : correct = run_test("ALL");
16497 : } else {
16498 1096 : for (i=optind;i<argc;i++) {
16499 546 : if (!run_test(argv[i])) {
16500 16 : correct = False;
16501 : }
16502 : }
16503 : }
16504 :
16505 550 : TALLOC_FREE(frame);
16506 :
16507 550 : if (correct) {
16508 485 : return(0);
16509 : } else {
16510 16 : return(1);
16511 : }
16512 : }
|